Add Vim9Script support#205
Conversation
Parse core Vim9Script constructs into proper AST nodes so that downstream tools can analyze Vim9Script code without errors. New node types: NODE_VIM9SCRIPT, NODE_DEF, NODE_ENDDEF, NODE_VAR, NODE_FINAL, NODE_EXPORT, NODE_IMPORT. Parsers for vim9script, def/enddef (with typed parameters, return types, default values, variadics), var/final (with type annotations), export (wrapping inner commands), and import. The # comment syntax is supported when vim9script mode is active. Also fix JS transpiler heuristic for subscript assignments in compile_let to check for [ in addition to . when deciding whether to add var prefix. Fixes vim-jp#194
|
I started on this before seeing #204. The approach in that PR is clearly a much better solution than this. (I hadn’t even known yet about https://github.com/vim-jp/vim-vim9parser.) But I figured I’d go ahead and raise this anyway — in case it happens to be of any interest, or might be a possible interim solution until #204 gets merged. |
From a fork of vimlparser that adds basic support for vim9script See vim-jp/vim-vimlparser#205 And https://github.com/sideshowbarker/vim-vimlparser/tree/vim9script-support While not perfect, this is a great improvement, thanks @sideshowbarker A more comprehensive solution is under development, but not yet ready See vim-jp/vim-vimlparser#204 And https://github.com/vim-jp/vim-vim9parser
From a fork of vimlparser that adds basic support for vim9script See vim-jp/vim-vimlparser#205 And https://github.com/sideshowbarker/vim-vimlparser/tree/vim9script-support While not perfect, this is a great improvement, thanks @sideshowbarker A more comprehensive solution is under development, but not yet ready See vim-jp/vim-vimlparser#204 And https://github.com/vim-jp/vim-vim9parser
| " VAR .ea .op .left .list .rest .right .type | ||
| " FINAL .ea .op .left .list .rest .right .type |
| " HEREDOC .rlist .op .body | ||
| " DEF .ea .body .left .rlist .default_args .attr .enddef | ||
| " ENDDEF .ea | ||
| " VAR .ea .op .left .list .rest .right .type |
| if self.reader.peekn(1) ==# ':' | ||
| call self.reader.getn(1) | ||
| call self.reader.skip_white() | ||
| call self.read_type() |
| if self.reader.peekn(3) ==# '...' | ||
| call self.reader.getn(3) | ||
| call self.reader.skip_white() | ||
| let vname = self.reader.read_alpha() |
There was a problem hiding this comment.
vname should accept number letter or _
| \ || self.reader.getpos() !=# self.ea.argpos) | ||
| \ && (self.ea.cmd.name !=# 'redir' | ||
| \ || self.reader.getpos().i !=# self.ea.argpos.i + 1 || pc !=# '@')) | ||
| \ || (self.vim9script && c ==# '#' && self.ea.cmd.flags !~# '\<NOTRLCOM\>') |
There was a problem hiding this comment.
Vim 9 supports inline suffix comments, but it must place a space immediately before the comment character.
| let node.str = '' | ||
| call self.reader.skip_white() | ||
| " Read the rest of the import line as a string (import autoload 'path' or import 'path' as Name) | ||
| let node.str = self.reader.getn(-1) |
There was a problem hiding this comment.
import './x.vim' as util # comment
comment strings are included.
| let left = '(' . left . ')' | ||
| endif | ||
| let right = self.compile(a:node.right) | ||
| call self.out('(var %s %s %s)', a:node.op, left, right) |
There was a problem hiding this comment.
type name is lost. (type_str should have)
| let left = '(' . left . ')' | ||
| endif | ||
| let right = self.compile(a:node.right) | ||
| call self.out('(final %s %s %s)', a:node.op, left, right) |
There was a problem hiding this comment.
type name is lost. (type_str should have)
Summary
parse_cmd_common, so downstream tools can analyze Vim9Script code without errors#comment support whenvim9scriptmode is activecompile_letheuristic that incorrectly addedvarprefix to subscript assignments likenamed[pname] = 1Motivation
Tools that depend on
vim-vimlparser— such as vint and vim-language-server (which vendors the JS output directly) — report unexpected errors on valid Vim9Script code because the parser doesn't recognize constructs likedef, typed parameters, or#comments. This adds structured parsing for the core Vim9Script syntax so these tools can handle Vim9Script files correctly.Details
New node types:
NODE_VIM9SCRIPT,NODE_DEF,NODE_ENDDEF,NODE_VAR,NODE_FINAL,NODE_EXPORT,NODE_IMPORT.vim9script— sets a mode flag that enables#comments throughout the parser (inparse_one_cmd,parse_command,parse_comment,parse_trail,ends_excmds,separate_nextcmd).def/enddef— parses typed parameters (name: type), default values (name: type = expr), variadic params (...name: type), and return type annotations (: returntype). Reads parameter names directly from the reader rather than usingExprTokenizer, since:is a valid name character in VimL identifiers and would causex:to be tokenized as a single identifier.var/final— parses variable declarations with optional type annotations. Same direct-reader approach to avoid the:tokenization issue.export— wraps the inner command (def, var, etc.) by delegating tofind_command+_parse_command, then moving the resulting nodes into the export node's body.import— captures the import specification as a string.Fixes #194