@@ -139,7 +139,8 @@ let s:NODE_CURLYNAMEEXPR = 91
139139let s: NODE_LAMBDA = 92
140140let s: NODE_BLOB = 93
141141let s: NODE_CONST = 94
142- let s: NODE_METHOD = 95
142+ let s: NODE_EVAL = 95
143+ let s: NODE_METHOD = 96
143144
144145let s: TOKEN_EOF = 1
145146let s: TOKEN_EOL = 2
@@ -311,6 +312,7 @@ endfunction
311312" node rest
312313" node[] list
313314" node[] rlist
315+ " node[] default_args
314316" node[] body
315317" string op
316318" string str
@@ -320,7 +322,7 @@ endfunction
320322" TOPLEVEL .body
321323" COMMENT .str
322324" EXCMD .ea .str
323- " FUNCTION .ea .body .left .rlist .attr .endfunction
325+ " FUNCTION .ea .body .left .rlist .default_args . attr .endfunction
324326" ENDFUNCTION .ea
325327" DELFUNCTION .ea .left
326328" RETURN .ea .left
@@ -345,6 +347,7 @@ endfunction
345347" FINALLY .ea .body
346348" ENDTRY .ea
347349" THROW .ea .left
350+ " EVAL .ea .left
348351" ECHO .ea .list
349352" ECHON .ea .list
350353" ECHOHL .ea .str
@@ -890,6 +893,8 @@ function! s:VimLParser._parse_command(parser) abort
890893 call self .parse_cmd_tcl ()
891894 elseif a: parser == # ' parse_cmd_throw'
892895 call self .parse_cmd_throw ()
896+ elseif a: parser == # ' parse_cmd_eval'
897+ call self .parse_cmd_eval ()
893898 elseif a: parser == # ' parse_cmd_try'
894899 call self .parse_cmd_try ()
895900 elseif a: parser == # ' parse_cmd_unlet'
@@ -1360,6 +1365,7 @@ function! s:VimLParser.parse_cmd_function() abort
13601365 let node.ea = self .ea
13611366 let node.left = left
13621367 let node.rlist = []
1368+ let node.default_args = []
13631369 let node.attr = {' range' : 0 , ' abort' : 0 , ' dict' : 0 , ' closure' : 0 }
13641370 let node.endfunction = s: NIL
13651371 call self .reader.getn (1 )
@@ -1381,6 +1387,12 @@ function! s:VimLParser.parse_cmd_function() abort
13811387 let varnode.pos = token.pos
13821388 let varnode.value = token.value
13831389 call add (node.rlist, varnode)
1390+ if tokenizer.peek ().type == # s: TOKEN_EQ
1391+ call tokenizer.get ()
1392+ call add (node.default_args, self .parse_expr ())
1393+ elseif len (node.default_args) > 0
1394+ throw s: Err (' E989: Non-default argument follows default argument' , varnode.pos)
1395+ endif
13841396 " XXX: Vim doesn't skip white space before comma. F(a ,b) => E475
13851397 if s: iswhite (self .reader.p (0 )) && tokenizer.peek ().type == # s: TOKEN_COMMA
13861398 throw s: Err (' E475: Invalid argument: White space is not allowed before comma' , self .reader.getpos ())
@@ -1814,6 +1826,14 @@ function! s:VimLParser.parse_cmd_throw() abort
18141826 call self .add_node (node)
18151827endfunction
18161828
1829+ function ! s: VimLParser .parse_cmd_eval () abort
1830+ let node = s: Node (s: NODE_EVAL )
1831+ let node.pos = self .ea .cmdpos
1832+ let node.ea = self .ea
1833+ let node.left = self .parse_expr ()
1834+ call self .add_node (node)
1835+ endfunction
1836+
18171837function ! s: VimLParser .parse_cmd_echo () abort
18181838 let node = s: Node (s: NODE_ECHO )
18191839 let node.pos = self .ea .cmdpos
@@ -2217,6 +2237,7 @@ let s:VimLParser.builtin_commands = [
22172237 \ {' name' : ' endtry' , ' minlen' : 4 , ' flags' : ' TRLBAR|SBOXOK|CMDWIN' , ' parser' : ' parse_cmd_endtry' },
22182238 \ {' name' : ' endwhile' , ' minlen' : 4 , ' flags' : ' TRLBAR|SBOXOK|CMDWIN' , ' parser' : ' parse_cmd_endwhile' },
22192239 \ {' name' : ' enew' , ' minlen' : 3 , ' flags' : ' BANG|TRLBAR' , ' parser' : ' parse_cmd_common' },
2240+ \ {' name' : ' eval' , ' minlen' : 2 , ' flags' : ' EXTRA|NOTRLCOM|SBOXOK|CMDWIN' , ' parser' : ' parse_cmd_eval' },
22202241 \ {' name' : ' ex' , ' minlen' : 2 , ' flags' : ' BANG|FILE1|EDITCMD|ARGOPT|TRLBAR' , ' parser' : ' parse_cmd_common' },
22212242 \ {' name' : ' execute' , ' minlen' : 3 , ' flags' : ' EXTRA|NOTRLCOM|SBOXOK|CMDWIN' , ' parser' : ' parse_cmd_execute' },
22222243 \ {' name' : ' exit' , ' minlen' : 3 , ' flags' : ' RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR|CMDWIN' , ' parser' : ' parse_cmd_common' },
@@ -4778,6 +4799,9 @@ function! s:Compiler.compile(node) abort
47784799 elseif a: node .type == # s: NODE_EXCALL
47794800 call self .compile_excall (a: node )
47804801 return s: NIL
4802+ elseif a: node .type == # s: NODE_EVAL
4803+ call self .compile_eval (a: node )
4804+ return s: NIL
47814805 elseif a: node .type == # s: NODE_LET
47824806 call self .compile_let (a: node )
47834807 return s: NIL
@@ -4980,14 +5004,25 @@ endfunction
49805004function ! s: Compiler .compile_function (node) abort
49815005 let left = self .compile (a: node .left )
49825006 let rlist = map (a: node .rlist, ' self.compile(v:val)' )
4983- if ! empty (rlist) && rlist[-1 ] == # ' ...'
4984- let rlist[-1 ] = ' . ...'
4985- endif
4986- if empty (rlist)
4987- call self .out (' (function (%s)' , left )
4988- else
4989- call self .out (' (function (%s %s)' , left , join (rlist, ' ' ))
5007+ let default_args = map (a: node .default_args, ' self.compile(v:val)' )
5008+ if ! empty (rlist)
5009+ let remaining = s: FALSE
5010+ if rlist[-1 ] == # ' ...'
5011+ call remove (rlist, -1 )
5012+ let remaining = s: TRUE
5013+ endif
5014+ for i in range (len (rlist))
5015+ if i < len (rlist) - len (default_args)
5016+ let left .= printf (' %s' , rlist[i ])
5017+ else
5018+ let left .= printf (' (%s %s)' , rlist[i ], default_args[i + len (default_args) - len (rlist)])
5019+ endif
5020+ endfor
5021+ if remaining
5022+ let left .= ' . ...'
5023+ endif
49905024 endif
5025+ call self .out (' (function (%s)' , left )
49915026 call self .incindent (' ' )
49925027 call self .compile_body (a: node .body)
49935028 call self .out (' )' )
@@ -5010,6 +5045,10 @@ function! s:Compiler.compile_excall(node) abort
50105045 call self .out (' (call %s)' , self .compile (a: node .left ))
50115046endfunction
50125047
5048+ function ! s: Compiler .compile_eval (node) abort
5049+ call self .out (' (eval %s)' , self .compile (a: node .left ))
5050+ endfunction
5051+
50135052function ! s: Compiler .compile_let (node) abort
50145053 let left = ' '
50155054 if a: node .left isnot # s: NIL
0 commit comments