diff --git a/.gitignore b/.gitignore index f47cb204..cae0dfe2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.out +*.vimout diff --git a/autoload/vimlparser.vim b/autoload/vimlparser.vim index 2c0c4c56..351ad85c 100644 --- a/autoload/vimlparser.vim +++ b/autoload/vimlparser.vim @@ -204,6 +204,63 @@ let s:TOKEN_DOTDOTDOT = 63 let s:TOKEN_SHARP = 64 let s:TOKEN_ARROW = 65 +let s:opprec = {} +let s:opprec[s:NODE_TERNARY] = 1 +let s:opprec[s:NODE_OR] = 2 +let s:opprec[s:NODE_AND] = 3 +let s:opprec[s:NODE_EQUAL] = 4 +let s:opprec[s:NODE_EQUALCI] = 4 +let s:opprec[s:NODE_EQUALCS] = 4 +let s:opprec[s:NODE_NEQUAL] = 4 +let s:opprec[s:NODE_NEQUALCI] = 4 +let s:opprec[s:NODE_NEQUALCS] = 4 +let s:opprec[s:NODE_GREATER] = 4 +let s:opprec[s:NODE_GREATERCI] = 4 +let s:opprec[s:NODE_GREATERCS] = 4 +let s:opprec[s:NODE_GEQUAL] = 4 +let s:opprec[s:NODE_GEQUALCI] = 4 +let s:opprec[s:NODE_GEQUALCS] = 4 +let s:opprec[s:NODE_SMALLER] = 4 +let s:opprec[s:NODE_SMALLERCI] = 4 +let s:opprec[s:NODE_SMALLERCS] = 4 +let s:opprec[s:NODE_SEQUAL] = 4 +let s:opprec[s:NODE_SEQUALCI] = 4 +let s:opprec[s:NODE_SEQUALCS] = 4 +let s:opprec[s:NODE_MATCH] = 4 +let s:opprec[s:NODE_MATCHCI] = 4 +let s:opprec[s:NODE_MATCHCS] = 4 +let s:opprec[s:NODE_NOMATCH] = 4 +let s:opprec[s:NODE_NOMATCHCI] = 4 +let s:opprec[s:NODE_NOMATCHCS] = 4 +let s:opprec[s:NODE_IS] = 4 +let s:opprec[s:NODE_ISCI] = 4 +let s:opprec[s:NODE_ISCS] = 4 +let s:opprec[s:NODE_ISNOT] = 4 +let s:opprec[s:NODE_ISNOTCI] = 4 +let s:opprec[s:NODE_ISNOTCS] = 4 +let s:opprec[s:NODE_ADD] = 5 +let s:opprec[s:NODE_SUBTRACT] = 5 +let s:opprec[s:NODE_CONCAT] = 5 +let s:opprec[s:NODE_MULTIPLY] = 6 +let s:opprec[s:NODE_DIVIDE] = 6 +let s:opprec[s:NODE_REMAINDER] = 6 +let s:opprec[s:NODE_NOT] = 7 +let s:opprec[s:NODE_MINUS] = 7 +let s:opprec[s:NODE_PLUS] = 7 +let s:opprec[s:NODE_SUBSCRIPT] = 8 +let s:opprec[s:NODE_SLICE] = 8 +let s:opprec[s:NODE_CALL] = 8 +let s:opprec[s:NODE_DOT] = 8 +let s:opprec[s:NODE_NUMBER] = 9 +let s:opprec[s:NODE_STRING] = 9 +let s:opprec[s:NODE_LIST] = 9 +let s:opprec[s:NODE_DICT] = 9 +let s:opprec[s:NODE_OPTION] = 9 +let s:opprec[s:NODE_IDENTIFIER] = 9 +let s:opprec[s:NODE_CURLYNAME] = 9 +let s:opprec[s:NODE_ENV] = 9 +let s:opprec[s:NODE_REG] = 9 + let s:MAX_FUNC_ARGS = 20 function! s:isalpha(c) @@ -4685,6 +4742,750 @@ function! s:Compiler.compile_lambda(node) return printf('(lambda (%s) %s)', join(rlist, ' '), self.compile(a:node.left)) endfunction +let s:Printer = {} + +function! s:Printer.new(...) + let obj = copy(self) + call call(obj.__init__, a:000, obj) + return obj +endfunction + +function! s:Printer.__init__(...) + let opts = a:0 > 0 && type(a:1) == 4 ? a:1 : {} + let self.indent_sp = type(get(opts, 'indent_sp', 0)) == 1 ? opts.indent_sp : ' ' + let self.indent = [''] + let self.lines = [] +endfunction + +function! s:Printer.out(...) + if len(a:000) == 1 + if a:000[0][0] ==# ')' + let self.lines[-1] .= a:000[0] + else + call add(self.lines, self.indent[0] . a:000[0]) + endif + else + call add(self.lines, self.indent[0] . call('printf', a:000)) + endif +endfunction + +function! s:Printer.incindent() + call insert(self.indent, self.indent[0] . self.indent_sp) +endfunction + +function! s:Printer.decindent() + call remove(self.indent, 0) +endfunction + +function! s:Printer.print(node) + if has_key(a:node, 'ea') && has_key(a:node.ea, 'modifiers') && + \ !empty(a:node.ea.modifiers) + call self.print_modifiers(a:node) + endif + if a:node.type == s:NODE_TOPLEVEL + return self.print_toplevel(a:node) + elseif a:node.type == s:NODE_COMMENT + call self.print_comment(a:node) + return s:NIL + elseif a:node.type == s:NODE_EXCMD + call self.print_excmd(a:node) + return s:NIL + elseif a:node.type == s:NODE_FUNCTION + call self.print_function(a:node) + return s:NIL + elseif a:node.type == s:NODE_DELFUNCTION + call self.print_delfunction(a:node) + return s:NIL + elseif a:node.type == s:NODE_RETURN + call self.print_return(a:node) + return s:NIL + elseif a:node.type == s:NODE_EXCALL + call self.print_excall(a:node) + return s:NIL + elseif a:node.type == s:NODE_LET + call self.print_let(a:node) + return s:NIL + elseif a:node.type == s:NODE_UNLET + call self.print_unlet(a:node) + return s:NIL + elseif a:node.type == s:NODE_LOCKVAR + call self.print_lockvar(a:node) + return s:NIL + elseif a:node.type == s:NODE_UNLOCKVAR + call self.print_unlockvar(a:node) + return s:NIL + elseif a:node.type == s:NODE_IF + call self.print_if(a:node) + return s:NIL + elseif a:node.type == s:NODE_WHILE + call self.print_while(a:node) + return s:NIL + elseif a:node.type == s:NODE_FOR + call self.print_for(a:node) + return s:NIL + elseif a:node.type == s:NODE_CONTINUE + call self.print_continue(a:node) + return s:NIL + elseif a:node.type == s:NODE_BREAK + call self.print_break(a:node) + return s:NIL + elseif a:node.type == s:NODE_TRY + call self.print_try(a:node) + return s:NIL + elseif a:node.type == s:NODE_THROW + call self.print_throw(a:node) + return s:NIL + elseif a:node.type == s:NODE_ECHO + call self.print_echo(a:node) + return s:NIL + elseif a:node.type == s:NODE_ECHON + call self.print_echon(a:node) + return s:NIL + elseif a:node.type == s:NODE_ECHOHL + call self.print_echohl(a:node) + return s:NIL + elseif a:node.type == s:NODE_ECHOMSG + call self.print_echomsg(a:node) + return s:NIL + elseif a:node.type == s:NODE_ECHOERR + call self.print_echoerr(a:node) + return s:NIL + elseif a:node.type == s:NODE_EXECUTE + call self.print_execute(a:node) + return s:NIL + elseif a:node.type == s:NODE_TERNARY + return self.print_ternary(a:node) + elseif a:node.type == s:NODE_OR + return self.print_or(a:node) + elseif a:node.type == s:NODE_AND + return self.print_and(a:node) + elseif a:node.type == s:NODE_EQUAL + return self.print_equal(a:node) + elseif a:node.type == s:NODE_EQUALCI + return self.print_equalci(a:node) + elseif a:node.type == s:NODE_EQUALCS + return self.print_equalcs(a:node) + elseif a:node.type == s:NODE_NEQUAL + return self.print_nequal(a:node) + elseif a:node.type == s:NODE_NEQUALCI + return self.print_nequalci(a:node) + elseif a:node.type == s:NODE_NEQUALCS + return self.print_nequalcs(a:node) + elseif a:node.type == s:NODE_GREATER + return self.print_greater(a:node) + elseif a:node.type == s:NODE_GREATERCI + return self.print_greaterci(a:node) + elseif a:node.type == s:NODE_GREATERCS + return self.print_greatercs(a:node) + elseif a:node.type == s:NODE_GEQUAL + return self.print_gequal(a:node) + elseif a:node.type == s:NODE_GEQUALCI + return self.print_gequalci(a:node) + elseif a:node.type == s:NODE_GEQUALCS + return self.print_gequalcs(a:node) + elseif a:node.type == s:NODE_SMALLER + return self.print_smaller(a:node) + elseif a:node.type == s:NODE_SMALLERCI + return self.print_smallerci(a:node) + elseif a:node.type == s:NODE_SMALLERCS + return self.print_smallercs(a:node) + elseif a:node.type == s:NODE_SEQUAL + return self.print_sequal(a:node) + elseif a:node.type == s:NODE_SEQUALCI + return self.print_sequalci(a:node) + elseif a:node.type == s:NODE_SEQUALCS + return self.print_sequalcs(a:node) + elseif a:node.type == s:NODE_MATCH + return self.print_match(a:node) + elseif a:node.type == s:NODE_MATCHCI + return self.print_matchci(a:node) + elseif a:node.type == s:NODE_MATCHCS + return self.print_matchcs(a:node) + elseif a:node.type == s:NODE_NOMATCH + return self.print_nomatch(a:node) + elseif a:node.type == s:NODE_NOMATCHCI + return self.print_nomatchci(a:node) + elseif a:node.type == s:NODE_NOMATCHCS + return self.print_nomatchcs(a:node) + elseif a:node.type == s:NODE_IS + return self.print_is(a:node) + elseif a:node.type == s:NODE_ISCI + return self.print_isci(a:node) + elseif a:node.type == s:NODE_ISCS + return self.print_iscs(a:node) + elseif a:node.type == s:NODE_ISNOT + return self.print_isnot(a:node) + elseif a:node.type == s:NODE_ISNOTCI + return self.print_isnotci(a:node) + elseif a:node.type == s:NODE_ISNOTCS + return self.print_isnotcs(a:node) + elseif a:node.type == s:NODE_ADD + return self.print_add(a:node) + elseif a:node.type == s:NODE_SUBTRACT + return self.print_subtract(a:node) + elseif a:node.type == s:NODE_CONCAT + return self.print_concat(a:node) + elseif a:node.type == s:NODE_MULTIPLY + return self.print_multiply(a:node) + elseif a:node.type == s:NODE_DIVIDE + return self.print_divide(a:node) + elseif a:node.type == s:NODE_REMAINDER + return self.print_remainder(a:node) + elseif a:node.type == s:NODE_NOT + return self.print_not(a:node) + elseif a:node.type == s:NODE_PLUS + return self.print_plus(a:node) + elseif a:node.type == s:NODE_MINUS + return self.print_minus(a:node) + elseif a:node.type == s:NODE_SUBSCRIPT + return self.print_subscript(a:node) + elseif a:node.type == s:NODE_SLICE + return self.print_slice(a:node) + elseif a:node.type == s:NODE_DOT + return self.print_dot(a:node) + elseif a:node.type == s:NODE_CALL + return self.print_call(a:node) + elseif a:node.type == s:NODE_NUMBER + return self.print_number(a:node) + elseif a:node.type == s:NODE_STRING + return self.print_string(a:node) + elseif a:node.type == s:NODE_LIST + return self.print_list(a:node) + elseif a:node.type == s:NODE_DICT + return self.print_dict(a:node) + elseif a:node.type == s:NODE_OPTION + return self.print_option(a:node) + elseif a:node.type == s:NODE_IDENTIFIER + return self.print_identifier(a:node) + elseif a:node.type == s:NODE_CURLYNAME + return self.print_curlyname(a:node) + elseif a:node.type == s:NODE_ENV + return self.print_env(a:node) + elseif a:node.type == s:NODE_REG + return self.print_reg(a:node) + elseif a:node.type == s:NODE_CURLYNAMEPART + return self.print_curlynamepart(a:node) + elseif a:node.type == s:NODE_CURLYNAMEEXPR + return self.print_curlynameexpr(a:node) + elseif a:node.type == s:NODE_LAMBDA + return self.print_lambda(a:node) + else + throw printf('Printer: unknown node: %s', string(a:node)) + endif + return s:NIL +endfunction + +function! s:Printer.print_body(body) + for node in a:body + call self.print(node) + endfor +endfunction + +function! s:Printer.print_toplevel(node) + call self.print_body(a:node.body) + return self.lines +endfunction + +function! s:Printer.print_comment(node) + call self.out('"%s', a:node.str) +endfunction + +function! s:Printer.print_excmd(node) + call self.out('%s', a:node.str) +endfunction + +function! s:Printer.print_function(node) + let left = self.print(a:node.left) + let rlist = map(a:node.rlist, 'self.print(v:val)') + let attrs = filter(sort(keys(a:node.attr)), 'a:node.attr[v:val]') + let attr = empty(attrs) ? '' : ' ' . join(attrs, ' ') + let bang = a:node.ea.forceit ? '!' : '' + call self.out('function%s %s(%s)%s', bang, left, join(rlist, ', '), attr) + call self.incindent() + call self.print_body(a:node.body) + call self.decindent() + call self.out('endfunction') +endfunction + +function! s:Printer.print_delfunction(node) + call self.out('delfunction %s', self.print(a:node.left)) +endfunction + +function! s:Printer.print_return(node) + if a:node.left is s:NIL + call self.out('return') + else + call self.out('return %s', self.print(a:node.left)) + endif +endfunction + +function! s:Printer.print_excall(node) + call self.out('call %s', self.print(a:node.left)) +endfunction + +function! s:Printer.print_let(node) + let left = '' + if a:node.left isnot s:NIL + let left = self.print(a:node.left) + else + let left = '[' + let left .= join(map(a:node.list, 'self.print(v:val)'), ', ') + if a:node.rest isnot s:NIL + let left .= '; ' . self.print(a:node.rest) + endif + let left .= ']' + endif + let right = self.print(a:node.right) + call self.out('let %s %s %s', left, a:node.op, right) +endfunction + +function! s:Printer.print_unlet(node) + let list = map(a:node.list, 'self.print(v:val)') + let bang = a:node.ea.forceit ? '!' : '' + call self.out('unlet%s %s', bang, join(list, ' ')) +endfunction + +function! s:Printer.print_lockvar(node) + let list = map(a:node.list, 'self.print(v:val)') + let bang = a:node.ea.forceit ? '!' : '' + if a:node.depth is s:NIL + call self.out('lockvar%s %s', bang, join(list, ' ')) + else + call self.out('lockvar%s %s %s', bang, a:node.depth, join(list, ' ')) + endif +endfunction + +function! s:Printer.print_unlockvar(node) + let list = map(a:node.list, 'self.print(v:val)') + let bang = a:node.ea.forceit ? '!' : '' + if a:node.depth is s:NIL + call self.out('unlockvar%s %s', bang, join(list, ' ')) + else + call self.out('unlockvar%s %s %s', bang, a:node.depth, join(list, ' ')) + endif +endfunction + +function! s:Printer.print_if(node) + call self.out('if %s', self.print(a:node.cond)) + call self.incindent() + call self.print_body(a:node.body) + call self.decindent() + for enode in a:node.elseif + call self.out('elseif %s', self.print(enode.cond)) + call self.incindent() + call self.print_body(enode.body) + call self.decindent() + endfor + if a:node.else isnot s:NIL + call self.out('else') + call self.incindent() + call self.print_body(a:node.else.body) + call self.decindent() + endif + call self.out('endif') +endfunction + +function! s:Printer.print_while(node) + call self.out('while %s', self.print(a:node.cond)) + call self.incindent() + call self.print_body(a:node.body) + call self.decindent() + call self.out('endwhile') +endfunction + +function! s:Printer.print_for(node) + let left = '' + if a:node.left isnot s:NIL + let left = self.print(a:node.left) + else + let left = '[' + let left .= join(map(a:node.list, 'self.print(v:val)'), ', ') + if a:node.rest isnot s:NIL + let left .= '; ' . self.print(a:node.rest) + endif + let left .= ']' + endif + let right = self.print(a:node.right) + call self.out('for %s in %s', left, right) + call self.incindent() + call self.print_body(a:node.body) + call self.decindent() + call self.out('endfor') +endfunction + +function! s:Printer.print_continue(node) + call self.out('continue') +endfunction + +function! s:Printer.print_break(node) + call self.out('break') +endfunction + +function! s:Printer.print_try(node) + call self.out('try') + call self.incindent() + call self.print_body(a:node.body) + for cnode in a:node.catch + if cnode.pattern isnot s:NIL + call self.decindent() + call self.out('catch /%s/', cnode.pattern) + call self.incindent() + call self.print_body(cnode.body) + else + call self.decindent() + call self.out('catch') + call self.incindent() + call self.print_body(cnode.body) + endif + endfor + if a:node.finally isnot s:NIL + call self.decindent() + call self.out('finally') + call self.incindent() + call self.print_body(a:node.finally.body) + endif + call self.decindent() + call self.out('endtry') +endfunction + +function! s:Printer.print_throw(node) + call self.out('throw %s', self.print(a:node.left)) +endfunction + +function! s:Printer.print_echo(node) + let list = map(a:node.list, 'self.print(v:val)') + call self.out('echo %s', join(list, ' ')) +endfunction + +function! s:Printer.print_echon(node) + let list = map(a:node.list, 'self.print(v:val)') + call self.out('echon %s', join(list, ' ')) +endfunction + +function! s:Printer.print_echohl(node) + call self.out('echohl %s', a:node.str) +endfunction + +function! s:Printer.print_echomsg(node) + let list = map(a:node.list, 'self.print(v:val)') + call self.out('echomsg %s', join(list, ' ')) +endfunction + +function! s:Printer.print_echoerr(node) + let list = map(a:node.list, 'self.print(v:val)') + call self.out('echoerr %s', join(list, ' ')) +endfunction + +function! s:Printer.print_execute(node) + let list = map(a:node.list, 'self.print(v:val)') + call self.out('execute %s', join(list, ' ')) +endfunction + +function! s:Printer.print_ternary(node) + let cond = self.print(a:node.cond) + if s:opprec[a:node.type] >= s:opprec[a:node.cond.type] + let cond = '(' . cond . ')' + endif + let left = self.print(a:node.left) + let right = self.print(a:node.right) + return printf('%s ? %s : %s', cond, left, right) +endfunction + +function! s:Printer.print_or(node) + return self.print_op2(a:node, '||') +endfunction + +function! s:Printer.print_and(node) + return self.print_op2(a:node, '&&') +endfunction + +function! s:Printer.print_equal(node) + return self.print_op2(a:node, '==') +endfunction + +function! s:Printer.print_equalci(node) + return self.print_op2(a:node, '==?') +endfunction + +function! s:Printer.print_equalcs(node) + return self.print_op2(a:node, '==#') +endfunction + +function! s:Printer.print_nequal(node) + return self.print_op2(a:node, '!=') +endfunction + +function! s:Printer.print_nequalci(node) + return self.print_op2(a:node, '!=?') +endfunction + +function! s:Printer.print_nequalcs(node) + return self.print_op2(a:node, '!=#') +endfunction + +function! s:Printer.print_greater(node) + return self.print_op2(a:node, '>') +endfunction + +function! s:Printer.print_greaterci(node) + return self.print_op2(a:node, '>?') +endfunction + +function! s:Printer.print_greatercs(node) + return self.print_op2(a:node, '>#') +endfunction + +function! s:Printer.print_gequal(node) + return self.print_op2(a:node, '>=') +endfunction + +function! s:Printer.print_gequalci(node) + return self.print_op2(a:node, '>=?') +endfunction + +function! s:Printer.print_gequalcs(node) + return self.print_op2(a:node, '>=#') +endfunction + +function! s:Printer.print_smaller(node) + return self.print_op2(a:node, '<') +endfunction + +function! s:Printer.print_smallerci(node) + return self.print_op2(a:node, ' %s}', join(rlist, ', '), self.print(a:node.left)) +endfunction + +function! s:Printer.print_modifiers(node) + if empty(a:node.ea.modifiers) + return + endif + let modlist = [] + for mod in a:node.ea.modifiers + if mod.name == 'silent' + call add(modlist, 'silent' . (mod.bang ? '!' : '')) + elseif mod.name == 'tab' + call add(modlist, get(mod, 'count', '') . 'tab') + elseif mod.name == 'verbose' + if get(mod, 'count', '1') != '1' + call add(modlist, mod.count . 'verbose') + else + call add(modlist, 'verbose') + endif + else + call add(modlist, mod.name) + endif + endfor + call self.out('%s ', join(modlist, ' ')) +endfunction + +function s:Printer.print_op1(node, op) + let left = self.print(a:node.left) + if s:opprec[a:node.type] > s:opprec[a:node.left.type] + let left = '(' . left . ')' + endif + return printf('%s%s', a:op, left) +endfunction + +function s:Printer.print_op2(node, op) + let left = self.print(a:node.left) + if s:opprec[a:node.type] > s:opprec[a:node.left.type] + let left = '(' . left . ')' + endif + let right = self.print(a:node.right) + if s:opprec[a:node.type] > s:opprec[a:node.right.type] + let right = '(' . right . ')' + endif + return printf('%s %s %s', left, a:op, right) +endfunction + " TODO: under construction let s:RegexpParser = {} diff --git a/js/jscompiler.vim b/js/jscompiler.vim index da90892b..d25a933b 100644 --- a/js/jscompiler.vim +++ b/js/jscompiler.vim @@ -290,7 +290,7 @@ function s:JavascriptCompiler.compile_function(node) unlet rlist[-1] let va = 1 endif - if left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\)\.' + if left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\|Printer\)\.' let [_0, klass, name; _] = matchlist(left, '^\(.*\)\.\(.*\)$') if name == 'new' return @@ -344,15 +344,15 @@ function s:JavascriptCompiler.compile_let(node) call self.out('function LvalueParser() { ExprParser.apply(this, arguments); this.__init__.apply(this, arguments); }') call self.out('LvalueParser.prototype = Object.create(ExprParser.prototype);') return - elseif left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\)$' + elseif left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\|Printer\)$' call self.out('function %s() { this.__init__.apply(this, arguments); }', left) return - elseif left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\)\.' + elseif left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\|Printer\)\.' let [_0, klass, name; _] = matchlist(left, '^\(.*\)\.\(.*\)$') call self.out('%s.prototype.%s %s %s;', klass, name, op, right) return endif - if left =~ '\.' || op != '=' + if left =~ '\.' || op != '=' || left =~ '^opprec\[\w\+\]$' call self.out('%s %s %s;', left, op, right) else call self.out('var %s %s %s;', left, op, right) @@ -798,6 +798,10 @@ function s:JavascriptCompiler.compile_identifier(node) let name = 'a000' elseif name == 'v:val' let name = 'vval' + elseif name == 'a:0' + let name = 'a000.length' + elseif name =~ '^a:[1-9]$' + let name = 'a000[' . (str2nr(name[2:]) - 1) . ']' elseif name =~ '^[sa]:' let name = name[2:] elseif name == 'self' @@ -859,7 +863,8 @@ function! s:convert(in, out) abort \ ' module.exports = {', \ ' VimLParser: VimLParser,', \ ' StringReader: StringReader,', - \ ' Compiler: Compiler', + \ ' Compiler: Compiler,', + \ ' Printer: Printer', \ ' };', \ '}', \ ] @@ -894,10 +899,10 @@ function! s:parse_args() abort if len(args) != 2 throw 'invalid argument: ' . string(args) endif - let v = args + let v = args endif return v -endfunction: +endfunction function! s:main() abort try diff --git a/js/vimlparser.js b/js/vimlparser.js index 58a4e15e..b0c1a297 100644 --- a/js/vimlparser.js +++ b/js/vimlparser.js @@ -392,6 +392,62 @@ var TOKEN_BACKTICK = 62; var TOKEN_DOTDOTDOT = 63; var TOKEN_SHARP = 64; var TOKEN_ARROW = 65; +var opprec = {}; +opprec[NODE_TERNARY] = 1; +opprec[NODE_OR] = 2; +opprec[NODE_AND] = 3; +opprec[NODE_EQUAL] = 4; +opprec[NODE_EQUALCI] = 4; +opprec[NODE_EQUALCS] = 4; +opprec[NODE_NEQUAL] = 4; +opprec[NODE_NEQUALCI] = 4; +opprec[NODE_NEQUALCS] = 4; +opprec[NODE_GREATER] = 4; +opprec[NODE_GREATERCI] = 4; +opprec[NODE_GREATERCS] = 4; +opprec[NODE_GEQUAL] = 4; +opprec[NODE_GEQUALCI] = 4; +opprec[NODE_GEQUALCS] = 4; +opprec[NODE_SMALLER] = 4; +opprec[NODE_SMALLERCI] = 4; +opprec[NODE_SMALLERCS] = 4; +opprec[NODE_SEQUAL] = 4; +opprec[NODE_SEQUALCI] = 4; +opprec[NODE_SEQUALCS] = 4; +opprec[NODE_MATCH] = 4; +opprec[NODE_MATCHCI] = 4; +opprec[NODE_MATCHCS] = 4; +opprec[NODE_NOMATCH] = 4; +opprec[NODE_NOMATCHCI] = 4; +opprec[NODE_NOMATCHCS] = 4; +opprec[NODE_IS] = 4; +opprec[NODE_ISCI] = 4; +opprec[NODE_ISCS] = 4; +opprec[NODE_ISNOT] = 4; +opprec[NODE_ISNOTCI] = 4; +opprec[NODE_ISNOTCS] = 4; +opprec[NODE_ADD] = 5; +opprec[NODE_SUBTRACT] = 5; +opprec[NODE_CONCAT] = 5; +opprec[NODE_MULTIPLY] = 6; +opprec[NODE_DIVIDE] = 6; +opprec[NODE_REMAINDER] = 6; +opprec[NODE_NOT] = 7; +opprec[NODE_MINUS] = 7; +opprec[NODE_PLUS] = 7; +opprec[NODE_SUBSCRIPT] = 8; +opprec[NODE_SLICE] = 8; +opprec[NODE_CALL] = 8; +opprec[NODE_DOT] = 8; +opprec[NODE_NUMBER] = 9; +opprec[NODE_STRING] = 9; +opprec[NODE_LIST] = 9; +opprec[NODE_DICT] = 9; +opprec[NODE_OPTION] = 9; +opprec[NODE_IDENTIFIER] = 9; +opprec[NODE_CURLYNAME] = 9; +opprec[NODE_ENV] = 9; +opprec[NODE_REG] = 9; var MAX_FUNC_ARGS = 20; function isalpha(c) { return viml_eqregh(c, "^[A-Za-z]$"); @@ -4683,6 +4739,849 @@ Compiler.prototype.compile_lambda = function(node) { return viml_printf("(lambda (%s) %s)", viml_join(rlist, " "), this.compile(node.left)); } +function Printer() { this.__init__.apply(this, arguments); } +Printer.prototype.__init__ = function() { + var a000 = Array.prototype.slice.call(arguments, 0); + var opts = a000.length > 0 && viml_type(a000[0]) == 4 ? a000[0] : {}; + this.indent_sp = viml_type(viml_get(opts, "indent_sp", 0)) == 1 ? opts.indent_sp : " "; + this.indent = [""]; + this.lines = []; +} + +Printer.prototype.out = function() { + var a000 = Array.prototype.slice.call(arguments, 0); + if (viml_len(a000) == 1) { + if (a000[0][0] == ")") { + this.lines[this.lines.length - 1] += a000[0]; + } + else { + viml_add(this.lines, this.indent[0] + a000[0]); + } + } + else { + viml_add(this.lines, this.indent[0] + viml_printf.apply(null, a000)); + } +} + +Printer.prototype.incindent = function() { + viml_insert(this.indent, this.indent[0] + this.indent_sp); +} + +Printer.prototype.decindent = function() { + viml_remove(this.indent, 0); +} + +Printer.prototype.print = function(node) { + if (viml_has_key(node, "ea") && viml_has_key(node.ea, "modifiers") && !viml_empty(node.ea.modifiers)) { + this.print_modifiers(node); + } + if (node.type == NODE_TOPLEVEL) { + return this.print_toplevel(node); + } + else if (node.type == NODE_COMMENT) { + this.print_comment(node); + return NIL; + } + else if (node.type == NODE_EXCMD) { + this.print_excmd(node); + return NIL; + } + else if (node.type == NODE_FUNCTION) { + this.print_function(node); + return NIL; + } + else if (node.type == NODE_DELFUNCTION) { + this.print_delfunction(node); + return NIL; + } + else if (node.type == NODE_RETURN) { + this.print_return(node); + return NIL; + } + else if (node.type == NODE_EXCALL) { + this.print_excall(node); + return NIL; + } + else if (node.type == NODE_LET) { + this.print_let(node); + return NIL; + } + else if (node.type == NODE_UNLET) { + this.print_unlet(node); + return NIL; + } + else if (node.type == NODE_LOCKVAR) { + this.print_lockvar(node); + return NIL; + } + else if (node.type == NODE_UNLOCKVAR) { + this.print_unlockvar(node); + return NIL; + } + else if (node.type == NODE_IF) { + this.print_if(node); + return NIL; + } + else if (node.type == NODE_WHILE) { + this.print_while(node); + return NIL; + } + else if (node.type == NODE_FOR) { + this.print_for(node); + return NIL; + } + else if (node.type == NODE_CONTINUE) { + this.print_continue(node); + return NIL; + } + else if (node.type == NODE_BREAK) { + this.print_break(node); + return NIL; + } + else if (node.type == NODE_TRY) { + this.print_try(node); + return NIL; + } + else if (node.type == NODE_THROW) { + this.print_throw(node); + return NIL; + } + else if (node.type == NODE_ECHO) { + this.print_echo(node); + return NIL; + } + else if (node.type == NODE_ECHON) { + this.print_echon(node); + return NIL; + } + else if (node.type == NODE_ECHOHL) { + this.print_echohl(node); + return NIL; + } + else if (node.type == NODE_ECHOMSG) { + this.print_echomsg(node); + return NIL; + } + else if (node.type == NODE_ECHOERR) { + this.print_echoerr(node); + return NIL; + } + else if (node.type == NODE_EXECUTE) { + this.print_execute(node); + return NIL; + } + else if (node.type == NODE_TERNARY) { + return this.print_ternary(node); + } + else if (node.type == NODE_OR) { + return this.print_or(node); + } + else if (node.type == NODE_AND) { + return this.print_and(node); + } + else if (node.type == NODE_EQUAL) { + return this.print_equal(node); + } + else if (node.type == NODE_EQUALCI) { + return this.print_equalci(node); + } + else if (node.type == NODE_EQUALCS) { + return this.print_equalcs(node); + } + else if (node.type == NODE_NEQUAL) { + return this.print_nequal(node); + } + else if (node.type == NODE_NEQUALCI) { + return this.print_nequalci(node); + } + else if (node.type == NODE_NEQUALCS) { + return this.print_nequalcs(node); + } + else if (node.type == NODE_GREATER) { + return this.print_greater(node); + } + else if (node.type == NODE_GREATERCI) { + return this.print_greaterci(node); + } + else if (node.type == NODE_GREATERCS) { + return this.print_greatercs(node); + } + else if (node.type == NODE_GEQUAL) { + return this.print_gequal(node); + } + else if (node.type == NODE_GEQUALCI) { + return this.print_gequalci(node); + } + else if (node.type == NODE_GEQUALCS) { + return this.print_gequalcs(node); + } + else if (node.type == NODE_SMALLER) { + return this.print_smaller(node); + } + else if (node.type == NODE_SMALLERCI) { + return this.print_smallerci(node); + } + else if (node.type == NODE_SMALLERCS) { + return this.print_smallercs(node); + } + else if (node.type == NODE_SEQUAL) { + return this.print_sequal(node); + } + else if (node.type == NODE_SEQUALCI) { + return this.print_sequalci(node); + } + else if (node.type == NODE_SEQUALCS) { + return this.print_sequalcs(node); + } + else if (node.type == NODE_MATCH) { + return this.print_match(node); + } + else if (node.type == NODE_MATCHCI) { + return this.print_matchci(node); + } + else if (node.type == NODE_MATCHCS) { + return this.print_matchcs(node); + } + else if (node.type == NODE_NOMATCH) { + return this.print_nomatch(node); + } + else if (node.type == NODE_NOMATCHCI) { + return this.print_nomatchci(node); + } + else if (node.type == NODE_NOMATCHCS) { + return this.print_nomatchcs(node); + } + else if (node.type == NODE_IS) { + return this.print_is(node); + } + else if (node.type == NODE_ISCI) { + return this.print_isci(node); + } + else if (node.type == NODE_ISCS) { + return this.print_iscs(node); + } + else if (node.type == NODE_ISNOT) { + return this.print_isnot(node); + } + else if (node.type == NODE_ISNOTCI) { + return this.print_isnotci(node); + } + else if (node.type == NODE_ISNOTCS) { + return this.print_isnotcs(node); + } + else if (node.type == NODE_ADD) { + return this.print_add(node); + } + else if (node.type == NODE_SUBTRACT) { + return this.print_subtract(node); + } + else if (node.type == NODE_CONCAT) { + return this.print_concat(node); + } + else if (node.type == NODE_MULTIPLY) { + return this.print_multiply(node); + } + else if (node.type == NODE_DIVIDE) { + return this.print_divide(node); + } + else if (node.type == NODE_REMAINDER) { + return this.print_remainder(node); + } + else if (node.type == NODE_NOT) { + return this.print_not(node); + } + else if (node.type == NODE_PLUS) { + return this.print_plus(node); + } + else if (node.type == NODE_MINUS) { + return this.print_minus(node); + } + else if (node.type == NODE_SUBSCRIPT) { + return this.print_subscript(node); + } + else if (node.type == NODE_SLICE) { + return this.print_slice(node); + } + else if (node.type == NODE_DOT) { + return this.print_dot(node); + } + else if (node.type == NODE_CALL) { + return this.print_call(node); + } + else if (node.type == NODE_NUMBER) { + return this.print_number(node); + } + else if (node.type == NODE_STRING) { + return this.print_string(node); + } + else if (node.type == NODE_LIST) { + return this.print_list(node); + } + else if (node.type == NODE_DICT) { + return this.print_dict(node); + } + else if (node.type == NODE_OPTION) { + return this.print_option(node); + } + else if (node.type == NODE_IDENTIFIER) { + return this.print_identifier(node); + } + else if (node.type == NODE_CURLYNAME) { + return this.print_curlyname(node); + } + else if (node.type == NODE_ENV) { + return this.print_env(node); + } + else if (node.type == NODE_REG) { + return this.print_reg(node); + } + else if (node.type == NODE_CURLYNAMEPART) { + return this.print_curlynamepart(node); + } + else if (node.type == NODE_CURLYNAMEEXPR) { + return this.print_curlynameexpr(node); + } + else if (node.type == NODE_LAMBDA) { + return this.print_lambda(node); + } + else { + throw viml_printf("Printer: unknown node: %s", viml_string(node)); + } + return NIL; +} + +Printer.prototype.print_body = function(body) { + var __c13 = body; + for (var __i13 = 0; __i13 < __c13.length; ++__i13) { + var node = __c13[__i13]; + this.print(node); + } +} + +Printer.prototype.print_toplevel = function(node) { + this.print_body(node.body); + return this.lines; +} + +Printer.prototype.print_comment = function(node) { + this.out("\"%s", node.str); +} + +Printer.prototype.print_excmd = function(node) { + this.out("%s", node.str); +} + +Printer.prototype.print_function = function(node) { + var left = this.print(node.left); + var rlist = node.rlist.map((function(vval) { return this.print(vval); }).bind(this)); + var attrs = viml_filter(viml_sort(viml_keys(node.attr)), "a:node.attr[v:val]"); + var attr = viml_empty(attrs) ? "" : " " + viml_join(attrs, " "); + var bang = node.ea.forceit ? "!" : ""; + this.out("function%s %s(%s)%s", bang, left, viml_join(rlist, ", "), attr); + this.incindent(); + this.print_body(node.body); + this.decindent(); + this.out("endfunction"); +} + +Printer.prototype.print_delfunction = function(node) { + this.out("delfunction %s", this.print(node.left)); +} + +Printer.prototype.print_return = function(node) { + if (node.left === NIL) { + this.out("return"); + } + else { + this.out("return %s", this.print(node.left)); + } +} + +Printer.prototype.print_excall = function(node) { + this.out("call %s", this.print(node.left)); +} + +Printer.prototype.print_let = function(node) { + var left = ""; + if (node.left !== NIL) { + var left = this.print(node.left); + } + else { + var left = "["; + left += viml_join(node.list.map((function(vval) { return this.print(vval); }).bind(this)), ", "); + if (node.rest !== NIL) { + left += "; " + this.print(node.rest); + } + left += "]"; + } + var right = this.print(node.right); + this.out("let %s %s %s", left, node.op, right); +} + +Printer.prototype.print_unlet = function(node) { + var list = node.list.map((function(vval) { return this.print(vval); }).bind(this)); + var bang = node.ea.forceit ? "!" : ""; + this.out("unlet%s %s", bang, viml_join(list, " ")); +} + +Printer.prototype.print_lockvar = function(node) { + var list = node.list.map((function(vval) { return this.print(vval); }).bind(this)); + var bang = node.ea.forceit ? "!" : ""; + if (node.depth === NIL) { + this.out("lockvar%s %s", bang, viml_join(list, " ")); + } + else { + this.out("lockvar%s %s %s", bang, node.depth, viml_join(list, " ")); + } +} + +Printer.prototype.print_unlockvar = function(node) { + var list = node.list.map((function(vval) { return this.print(vval); }).bind(this)); + var bang = node.ea.forceit ? "!" : ""; + if (node.depth === NIL) { + this.out("unlockvar%s %s", bang, viml_join(list, " ")); + } + else { + this.out("unlockvar%s %s %s", bang, node.depth, viml_join(list, " ")); + } +} + +Printer.prototype.print_if = function(node) { + this.out("if %s", this.print(node.cond)); + this.incindent(); + this.print_body(node.body); + this.decindent(); + var __c14 = node.elseif; + for (var __i14 = 0; __i14 < __c14.length; ++__i14) { + var enode = __c14[__i14]; + this.out("elseif %s", this.print(enode.cond)); + this.incindent(); + this.print_body(enode.body); + this.decindent(); + } + if (node._else !== NIL) { + this.out("else"); + this.incindent(); + this.print_body(node._else.body); + this.decindent(); + } + this.out("endif"); +} + +Printer.prototype.print_while = function(node) { + this.out("while %s", this.print(node.cond)); + this.incindent(); + this.print_body(node.body); + this.decindent(); + this.out("endwhile"); +} + +Printer.prototype.print_for = function(node) { + var left = ""; + if (node.left !== NIL) { + var left = this.print(node.left); + } + else { + var left = "["; + left += viml_join(node.list.map((function(vval) { return this.print(vval); }).bind(this)), ", "); + if (node.rest !== NIL) { + left += "; " + this.print(node.rest); + } + left += "]"; + } + var right = this.print(node.right); + this.out("for %s in %s", left, right); + this.incindent(); + this.print_body(node.body); + this.decindent(); + this.out("endfor"); +} + +Printer.prototype.print_continue = function(node) { + this.out("continue"); +} + +Printer.prototype.print_break = function(node) { + this.out("break"); +} + +Printer.prototype.print_try = function(node) { + this.out("try"); + this.incindent(); + this.print_body(node.body); + var __c15 = node.catch; + for (var __i15 = 0; __i15 < __c15.length; ++__i15) { + var cnode = __c15[__i15]; + if (cnode.pattern !== NIL) { + this.decindent(); + this.out("catch /%s/", cnode.pattern); + this.incindent(); + this.print_body(cnode.body); + } + else { + this.decindent(); + this.out("catch"); + this.incindent(); + this.print_body(cnode.body); + } + } + if (node._finally !== NIL) { + this.decindent(); + this.out("finally"); + this.incindent(); + this.print_body(node._finally.body); + } + this.decindent(); + this.out("endtry"); +} + +Printer.prototype.print_throw = function(node) { + this.out("throw %s", this.print(node.left)); +} + +Printer.prototype.print_echo = function(node) { + var list = node.list.map((function(vval) { return this.print(vval); }).bind(this)); + this.out("echo %s", viml_join(list, " ")); +} + +Printer.prototype.print_echon = function(node) { + var list = node.list.map((function(vval) { return this.print(vval); }).bind(this)); + this.out("echon %s", viml_join(list, " ")); +} + +Printer.prototype.print_echohl = function(node) { + this.out("echohl %s", node.str); +} + +Printer.prototype.print_echomsg = function(node) { + var list = node.list.map((function(vval) { return this.print(vval); }).bind(this)); + this.out("echomsg %s", viml_join(list, " ")); +} + +Printer.prototype.print_echoerr = function(node) { + var list = node.list.map((function(vval) { return this.print(vval); }).bind(this)); + this.out("echoerr %s", viml_join(list, " ")); +} + +Printer.prototype.print_execute = function(node) { + var list = node.list.map((function(vval) { return this.print(vval); }).bind(this)); + this.out("execute %s", viml_join(list, " ")); +} + +Printer.prototype.print_ternary = function(node) { + var cond = this.print(node.cond); + if (opprec[node.type] >= opprec[node.cond.type]) { + var cond = "(" + cond + ")"; + } + var left = this.print(node.left); + var right = this.print(node.right); + return viml_printf("%s ? %s : %s", cond, left, right); +} + +Printer.prototype.print_or = function(node) { + return this.print_op2(node, "||"); +} + +Printer.prototype.print_and = function(node) { + return this.print_op2(node, "&&"); +} + +Printer.prototype.print_equal = function(node) { + return this.print_op2(node, "=="); +} + +Printer.prototype.print_equalci = function(node) { + return this.print_op2(node, "==?"); +} + +Printer.prototype.print_equalcs = function(node) { + return this.print_op2(node, "==#"); +} + +Printer.prototype.print_nequal = function(node) { + return this.print_op2(node, "!="); +} + +Printer.prototype.print_nequalci = function(node) { + return this.print_op2(node, "!=?"); +} + +Printer.prototype.print_nequalcs = function(node) { + return this.print_op2(node, "!=#"); +} + +Printer.prototype.print_greater = function(node) { + return this.print_op2(node, ">"); +} + +Printer.prototype.print_greaterci = function(node) { + return this.print_op2(node, ">?"); +} + +Printer.prototype.print_greatercs = function(node) { + return this.print_op2(node, ">#"); +} + +Printer.prototype.print_gequal = function(node) { + return this.print_op2(node, ">="); +} + +Printer.prototype.print_gequalci = function(node) { + return this.print_op2(node, ">=?"); +} + +Printer.prototype.print_gequalcs = function(node) { + return this.print_op2(node, ">=#"); +} + +Printer.prototype.print_smaller = function(node) { + return this.print_op2(node, "<"); +} + +Printer.prototype.print_smallerci = function(node) { + return this.print_op2(node, " %s}", viml_join(rlist, ", "), this.print(node.left)); +} + +Printer.prototype.print_modifiers = function(node) { + if (viml_empty(node.ea.modifiers)) { + return; + } + var modlist = []; + var __c16 = node.ea.modifiers; + for (var __i16 = 0; __i16 < __c16.length; ++__i16) { + var mod = __c16[__i16]; + if (mod.name == "silent") { + viml_add(modlist, "silent" + (mod.bang ? "!" : "")); + } + else if (mod.name == "tab") { + viml_add(modlist, viml_get(mod, "count", "") + "tab"); + } + else if (mod.name == "verbose") { + if (viml_get(mod, "count", "1") != "1") { + viml_add(modlist, mod.count + "verbose"); + } + else { + viml_add(modlist, "verbose"); + } + } + else { + viml_add(modlist, mod.name); + } + } + this.out("%s ", viml_join(modlist, " ")); +} + +Printer.prototype.print_op1 = function(node, op) { + var left = this.print(node.left); + if (opprec[node.type] > opprec[node.left.type]) { + var left = "(" + left + ")"; + } + return viml_printf("%s%s", op, left); +} + +Printer.prototype.print_op2 = function(node, op) { + var left = this.print(node.left); + if (opprec[node.type] > opprec[node.left.type]) { + var left = "(" + left + ")"; + } + var right = this.print(node.right); + if (opprec[node.type] > opprec[node.right.type]) { + var right = "(" + right + ")"; + } + return viml_printf("%s %s %s", left, op, right); +} + // TODO: under construction function RegexpParser() { this.__init__.apply(this, arguments); } RegexpParser.prototype.RE_VERY_NOMAGIC = 1; @@ -5363,9 +6262,9 @@ RegexpParser.prototype.get_token_sq_char_class = function() { var r = this.reader.read_alpha(); if (this.reader.p(0) == ":" && this.reader.p(1) == "]") { this.reader.seek_cur(2); - var __c13 = class_names; - for (var __i13 = 0; __i13 < __c13.length; ++__i13) { - var name = __c13[__i13]; + var __c17 = class_names; + for (var __i17 = 0; __i17 < __c17.length; ++__i17) { + var name = __c17[__i17]; if (r == name) { return "[:" + name + ":]"; } @@ -5498,9 +6397,9 @@ RegexpParser.prototype.getoctchrs = function() { RegexpParser.prototype.gethexchrs = function(n) { var r = ""; - var __c14 = viml_range(n); - for (var __i14 = 0; __i14 < __c14.length; ++__i14) { - var i = __c14[__i14]; + var __c18 = viml_range(n); + for (var __i18 = 0; __i18 < __c18.length; ++__i18) { + var i = __c18[__i18]; var c = this.reader.peek(); if (!isxdigit(c)) { break; @@ -5517,6 +6416,7 @@ else { module.exports = { VimLParser: VimLParser, StringReader: StringReader, - Compiler: Compiler + Compiler: Compiler, + Printer: Printer }; } diff --git a/py/pycompiler.vim b/py/pycompiler.vim index 8e387d99..9d5f9eda 100644 --- a/py/pycompiler.vim +++ b/py/pycompiler.vim @@ -327,7 +327,7 @@ function s:PythonCompiler.compile_function(node) if !empty(rlist) && rlist[-1] == '...' let rlist[-1] = '*a000' endif - if left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\)\.' + if left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\|Printer\)\.' let left = matchstr(left, '\.\zs.*') if left == 'new' return @@ -375,10 +375,10 @@ function s:PythonCompiler.compile_let(node) if left == 'LvalueParser' call self.out('class LvalueParser(ExprParser):') return - elseif left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\)$' + elseif left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\|Printer\)$' call self.out('class %s:', left) return - elseif left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\)\.' + elseif left =~ '^\(VimLParser\|ExprTokenizer\|ExprParser\|LvalueParser\|StringReader\|Compiler\|RegexpParser\|Printer\)\.' let left = matchstr(left, '\.\zs.*') call self.incindent(' ') call self.out('%s %s %s', left, op, right) @@ -778,6 +778,10 @@ function s:PythonCompiler.compile_identifier(node) let name = 'a000' elseif name == 'v:val' let name = 'vval' + elseif name == 'a:0' + let name = 'len(a000)' + elseif name =~ '^a:[1-9]$' + let name = 'a000[' . (str2nr(name[2:]) - 1) . ']' elseif name =~ '^[sa]:' let name = name[2:] endif diff --git a/py/vimlfunc.py b/py/vimlfunc.py index 8cc75216..6171d801 100644 --- a/py/vimlfunc.py +++ b/py/vimlfunc.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 # usage: python3 vimlparser.py [--neovim] foo.vim +from __future__ import print_function import sys import re import inspect diff --git a/py/vimlparser.py b/py/vimlparser.py index 89c517d1..47f962cb 100644 --- a/py/vimlparser.py +++ b/py/vimlparser.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 # usage: python3 vimlparser.py [--neovim] foo.vim +from __future__ import print_function import sys import re import inspect @@ -346,6 +347,62 @@ def viml_type(obj): TOKEN_DOTDOTDOT = 63 TOKEN_SHARP = 64 TOKEN_ARROW = 65 +opprec = AttributeDict({}) +opprec[NODE_TERNARY] = 1 +opprec[NODE_OR] = 2 +opprec[NODE_AND] = 3 +opprec[NODE_EQUAL] = 4 +opprec[NODE_EQUALCI] = 4 +opprec[NODE_EQUALCS] = 4 +opprec[NODE_NEQUAL] = 4 +opprec[NODE_NEQUALCI] = 4 +opprec[NODE_NEQUALCS] = 4 +opprec[NODE_GREATER] = 4 +opprec[NODE_GREATERCI] = 4 +opprec[NODE_GREATERCS] = 4 +opprec[NODE_GEQUAL] = 4 +opprec[NODE_GEQUALCI] = 4 +opprec[NODE_GEQUALCS] = 4 +opprec[NODE_SMALLER] = 4 +opprec[NODE_SMALLERCI] = 4 +opprec[NODE_SMALLERCS] = 4 +opprec[NODE_SEQUAL] = 4 +opprec[NODE_SEQUALCI] = 4 +opprec[NODE_SEQUALCS] = 4 +opprec[NODE_MATCH] = 4 +opprec[NODE_MATCHCI] = 4 +opprec[NODE_MATCHCS] = 4 +opprec[NODE_NOMATCH] = 4 +opprec[NODE_NOMATCHCI] = 4 +opprec[NODE_NOMATCHCS] = 4 +opprec[NODE_IS] = 4 +opprec[NODE_ISCI] = 4 +opprec[NODE_ISCS] = 4 +opprec[NODE_ISNOT] = 4 +opprec[NODE_ISNOTCI] = 4 +opprec[NODE_ISNOTCS] = 4 +opprec[NODE_ADD] = 5 +opprec[NODE_SUBTRACT] = 5 +opprec[NODE_CONCAT] = 5 +opprec[NODE_MULTIPLY] = 6 +opprec[NODE_DIVIDE] = 6 +opprec[NODE_REMAINDER] = 6 +opprec[NODE_NOT] = 7 +opprec[NODE_MINUS] = 7 +opprec[NODE_PLUS] = 7 +opprec[NODE_SUBSCRIPT] = 8 +opprec[NODE_SLICE] = 8 +opprec[NODE_CALL] = 8 +opprec[NODE_DOT] = 8 +opprec[NODE_NUMBER] = 9 +opprec[NODE_STRING] = 9 +opprec[NODE_LIST] = 9 +opprec[NODE_DICT] = 9 +opprec[NODE_OPTION] = 9 +opprec[NODE_IDENTIFIER] = 9 +opprec[NODE_CURLYNAME] = 9 +opprec[NODE_ENV] = 9 +opprec[NODE_REG] = 9 MAX_FUNC_ARGS = 20 def isalpha(c): return viml_eqregh(c, "^[A-Za-z]$") @@ -3668,6 +3725,621 @@ def compile_lambda(self, node): rlist = [self.compile(vval) for vval in node.rlist] return viml_printf("(lambda (%s) %s)", viml_join(rlist, " "), self.compile(node.left)) +class Printer: + def __init__(self, *a000): + opts = a000[0] if len(a000) > 0 and viml_type(a000[0]) == 4 else AttributeDict({}) + self.indent_sp = opts.indent_sp if viml_type(viml_get(opts, "indent_sp", 0)) == 1 else " " + self.indent = [""] + self.lines = [] + + def out(self, *a000): + if viml_len(a000) == 1: + if a000[0][0] == ")": + self.lines[-1] += a000[0] + else: + viml_add(self.lines, self.indent[0] + a000[0]) + else: + viml_add(self.lines, self.indent[0] + viml_printf(*a000)) + + def incindent(self): + viml_insert(self.indent, self.indent[0] + self.indent_sp) + + def decindent(self): + viml_remove(self.indent, 0) + + def print(self, node): + if viml_has_key(node, "ea") and viml_has_key(node.ea, "modifiers") and not viml_empty(node.ea.modifiers): + self.print_modifiers(node) + if node.type == NODE_TOPLEVEL: + return self.print_toplevel(node) + elif node.type == NODE_COMMENT: + self.print_comment(node) + return NIL + elif node.type == NODE_EXCMD: + self.print_excmd(node) + return NIL + elif node.type == NODE_FUNCTION: + self.print_function(node) + return NIL + elif node.type == NODE_DELFUNCTION: + self.print_delfunction(node) + return NIL + elif node.type == NODE_RETURN: + self.print_return(node) + return NIL + elif node.type == NODE_EXCALL: + self.print_excall(node) + return NIL + elif node.type == NODE_LET: + self.print_let(node) + return NIL + elif node.type == NODE_UNLET: + self.print_unlet(node) + return NIL + elif node.type == NODE_LOCKVAR: + self.print_lockvar(node) + return NIL + elif node.type == NODE_UNLOCKVAR: + self.print_unlockvar(node) + return NIL + elif node.type == NODE_IF: + self.print_if(node) + return NIL + elif node.type == NODE_WHILE: + self.print_while(node) + return NIL + elif node.type == NODE_FOR: + self.print_for(node) + return NIL + elif node.type == NODE_CONTINUE: + self.print_continue(node) + return NIL + elif node.type == NODE_BREAK: + self.print_break(node) + return NIL + elif node.type == NODE_TRY: + self.print_try(node) + return NIL + elif node.type == NODE_THROW: + self.print_throw(node) + return NIL + elif node.type == NODE_ECHO: + self.print_echo(node) + return NIL + elif node.type == NODE_ECHON: + self.print_echon(node) + return NIL + elif node.type == NODE_ECHOHL: + self.print_echohl(node) + return NIL + elif node.type == NODE_ECHOMSG: + self.print_echomsg(node) + return NIL + elif node.type == NODE_ECHOERR: + self.print_echoerr(node) + return NIL + elif node.type == NODE_EXECUTE: + self.print_execute(node) + return NIL + elif node.type == NODE_TERNARY: + return self.print_ternary(node) + elif node.type == NODE_OR: + return self.print_or(node) + elif node.type == NODE_AND: + return self.print_and(node) + elif node.type == NODE_EQUAL: + return self.print_equal(node) + elif node.type == NODE_EQUALCI: + return self.print_equalci(node) + elif node.type == NODE_EQUALCS: + return self.print_equalcs(node) + elif node.type == NODE_NEQUAL: + return self.print_nequal(node) + elif node.type == NODE_NEQUALCI: + return self.print_nequalci(node) + elif node.type == NODE_NEQUALCS: + return self.print_nequalcs(node) + elif node.type == NODE_GREATER: + return self.print_greater(node) + elif node.type == NODE_GREATERCI: + return self.print_greaterci(node) + elif node.type == NODE_GREATERCS: + return self.print_greatercs(node) + elif node.type == NODE_GEQUAL: + return self.print_gequal(node) + elif node.type == NODE_GEQUALCI: + return self.print_gequalci(node) + elif node.type == NODE_GEQUALCS: + return self.print_gequalcs(node) + elif node.type == NODE_SMALLER: + return self.print_smaller(node) + elif node.type == NODE_SMALLERCI: + return self.print_smallerci(node) + elif node.type == NODE_SMALLERCS: + return self.print_smallercs(node) + elif node.type == NODE_SEQUAL: + return self.print_sequal(node) + elif node.type == NODE_SEQUALCI: + return self.print_sequalci(node) + elif node.type == NODE_SEQUALCS: + return self.print_sequalcs(node) + elif node.type == NODE_MATCH: + return self.print_match(node) + elif node.type == NODE_MATCHCI: + return self.print_matchci(node) + elif node.type == NODE_MATCHCS: + return self.print_matchcs(node) + elif node.type == NODE_NOMATCH: + return self.print_nomatch(node) + elif node.type == NODE_NOMATCHCI: + return self.print_nomatchci(node) + elif node.type == NODE_NOMATCHCS: + return self.print_nomatchcs(node) + elif node.type == NODE_IS: + return self.print_is(node) + elif node.type == NODE_ISCI: + return self.print_isci(node) + elif node.type == NODE_ISCS: + return self.print_iscs(node) + elif node.type == NODE_ISNOT: + return self.print_isnot(node) + elif node.type == NODE_ISNOTCI: + return self.print_isnotci(node) + elif node.type == NODE_ISNOTCS: + return self.print_isnotcs(node) + elif node.type == NODE_ADD: + return self.print_add(node) + elif node.type == NODE_SUBTRACT: + return self.print_subtract(node) + elif node.type == NODE_CONCAT: + return self.print_concat(node) + elif node.type == NODE_MULTIPLY: + return self.print_multiply(node) + elif node.type == NODE_DIVIDE: + return self.print_divide(node) + elif node.type == NODE_REMAINDER: + return self.print_remainder(node) + elif node.type == NODE_NOT: + return self.print_not(node) + elif node.type == NODE_PLUS: + return self.print_plus(node) + elif node.type == NODE_MINUS: + return self.print_minus(node) + elif node.type == NODE_SUBSCRIPT: + return self.print_subscript(node) + elif node.type == NODE_SLICE: + return self.print_slice(node) + elif node.type == NODE_DOT: + return self.print_dot(node) + elif node.type == NODE_CALL: + return self.print_call(node) + elif node.type == NODE_NUMBER: + return self.print_number(node) + elif node.type == NODE_STRING: + return self.print_string(node) + elif node.type == NODE_LIST: + return self.print_list(node) + elif node.type == NODE_DICT: + return self.print_dict(node) + elif node.type == NODE_OPTION: + return self.print_option(node) + elif node.type == NODE_IDENTIFIER: + return self.print_identifier(node) + elif node.type == NODE_CURLYNAME: + return self.print_curlyname(node) + elif node.type == NODE_ENV: + return self.print_env(node) + elif node.type == NODE_REG: + return self.print_reg(node) + elif node.type == NODE_CURLYNAMEPART: + return self.print_curlynamepart(node) + elif node.type == NODE_CURLYNAMEEXPR: + return self.print_curlynameexpr(node) + elif node.type == NODE_LAMBDA: + return self.print_lambda(node) + else: + raise VimLParserException(viml_printf("Printer: unknown node: %s", viml_string(node))) + return NIL + + def print_body(self, body): + for node in body: + self.print(node) + + def print_toplevel(self, node): + self.print_body(node.body) + return self.lines + + def print_comment(self, node): + self.out("\"%s", node.str) + + def print_excmd(self, node): + self.out("%s", node.str) + + def print_function(self, node): + left = self.print(node.left) + rlist = [self.print(vval) for vval in node.rlist] + attrs = viml_filter(viml_sort(viml_keys(node.attr)), "a:node.attr[v:val]") + attr = "" if viml_empty(attrs) else " " + viml_join(attrs, " ") + bang = "!" if node.ea.forceit else "" + self.out("function%s %s(%s)%s", bang, left, viml_join(rlist, ", "), attr) + self.incindent() + self.print_body(node.body) + self.decindent() + self.out("endfunction") + + def print_delfunction(self, node): + self.out("delfunction %s", self.print(node.left)) + + def print_return(self, node): + if node.left is NIL: + self.out("return") + else: + self.out("return %s", self.print(node.left)) + + def print_excall(self, node): + self.out("call %s", self.print(node.left)) + + def print_let(self, node): + left = "" + if node.left is not NIL: + left = self.print(node.left) + else: + left = "[" + left += viml_join([self.print(vval) for vval in node.list], ", ") + if node.rest is not NIL: + left += "; " + self.print(node.rest) + left += "]" + right = self.print(node.right) + self.out("let %s %s %s", left, node.op, right) + + def print_unlet(self, node): + list = [self.print(vval) for vval in node.list] + bang = "!" if node.ea.forceit else "" + self.out("unlet%s %s", bang, viml_join(list, " ")) + + def print_lockvar(self, node): + list = [self.print(vval) for vval in node.list] + bang = "!" if node.ea.forceit else "" + if node.depth is NIL: + self.out("lockvar%s %s", bang, viml_join(list, " ")) + else: + self.out("lockvar%s %s %s", bang, node.depth, viml_join(list, " ")) + + def print_unlockvar(self, node): + list = [self.print(vval) for vval in node.list] + bang = "!" if node.ea.forceit else "" + if node.depth is NIL: + self.out("unlockvar%s %s", bang, viml_join(list, " ")) + else: + self.out("unlockvar%s %s %s", bang, node.depth, viml_join(list, " ")) + + def print_if(self, node): + self.out("if %s", self.print(node.cond)) + self.incindent() + self.print_body(node.body) + self.decindent() + for enode in node.elseif: + self.out("elseif %s", self.print(enode.cond)) + self.incindent() + self.print_body(enode.body) + self.decindent() + if node.else_ is not NIL: + self.out("else") + self.incindent() + self.print_body(node.else_.body) + self.decindent() + self.out("endif") + + def print_while(self, node): + self.out("while %s", self.print(node.cond)) + self.incindent() + self.print_body(node.body) + self.decindent() + self.out("endwhile") + + def print_for(self, node): + left = "" + if node.left is not NIL: + left = self.print(node.left) + else: + left = "[" + left += viml_join([self.print(vval) for vval in node.list], ", ") + if node.rest is not NIL: + left += "; " + self.print(node.rest) + left += "]" + right = self.print(node.right) + self.out("for %s in %s", left, right) + self.incindent() + self.print_body(node.body) + self.decindent() + self.out("endfor") + + def print_continue(self, node): + self.out("continue") + + def print_break(self, node): + self.out("break") + + def print_try(self, node): + self.out("try") + self.incindent() + self.print_body(node.body) + for cnode in node.catch: + if cnode.pattern is not NIL: + self.decindent() + self.out("catch /%s/", cnode.pattern) + self.incindent() + self.print_body(cnode.body) + else: + self.decindent() + self.out("catch") + self.incindent() + self.print_body(cnode.body) + if node.finally_ is not NIL: + self.decindent() + self.out("finally") + self.incindent() + self.print_body(node.finally_.body) + self.decindent() + self.out("endtry") + + def print_throw(self, node): + self.out("throw %s", self.print(node.left)) + + def print_echo(self, node): + list = [self.print(vval) for vval in node.list] + self.out("echo %s", viml_join(list, " ")) + + def print_echon(self, node): + list = [self.print(vval) for vval in node.list] + self.out("echon %s", viml_join(list, " ")) + + def print_echohl(self, node): + self.out("echohl %s", node.str) + + def print_echomsg(self, node): + list = [self.print(vval) for vval in node.list] + self.out("echomsg %s", viml_join(list, " ")) + + def print_echoerr(self, node): + list = [self.print(vval) for vval in node.list] + self.out("echoerr %s", viml_join(list, " ")) + + def print_execute(self, node): + list = [self.print(vval) for vval in node.list] + self.out("execute %s", viml_join(list, " ")) + + def print_ternary(self, node): + cond = self.print(node.cond) + if opprec[node.type] >= opprec[node.cond.type]: + cond = "(" + cond + ")" + left = self.print(node.left) + right = self.print(node.right) + return viml_printf("%s ? %s : %s", cond, left, right) + + def print_or(self, node): + return self.print_op2(node, "||") + + def print_and(self, node): + return self.print_op2(node, "&&") + + def print_equal(self, node): + return self.print_op2(node, "==") + + def print_equalci(self, node): + return self.print_op2(node, "==?") + + def print_equalcs(self, node): + return self.print_op2(node, "==#") + + def print_nequal(self, node): + return self.print_op2(node, "!=") + + def print_nequalci(self, node): + return self.print_op2(node, "!=?") + + def print_nequalcs(self, node): + return self.print_op2(node, "!=#") + + def print_greater(self, node): + return self.print_op2(node, ">") + + def print_greaterci(self, node): + return self.print_op2(node, ">?") + + def print_greatercs(self, node): + return self.print_op2(node, ">#") + + def print_gequal(self, node): + return self.print_op2(node, ">=") + + def print_gequalci(self, node): + return self.print_op2(node, ">=?") + + def print_gequalcs(self, node): + return self.print_op2(node, ">=#") + + def print_smaller(self, node): + return self.print_op2(node, "<") + + def print_smallerci(self, node): + return self.print_op2(node, " %s}", viml_join(rlist, ", "), self.print(node.left)) + + def print_modifiers(self, node): + if viml_empty(node.ea.modifiers): + return + modlist = [] + for mod in node.ea.modifiers: + if mod.name == "silent": + viml_add(modlist, "silent" + ("!" if mod.bang else "")) + elif mod.name == "tab": + viml_add(modlist, viml_get(mod, "count", "") + "tab") + elif mod.name == "verbose": + if viml_get(mod, "count", "1") != "1": + viml_add(modlist, mod.count + "verbose") + else: + viml_add(modlist, "verbose") + else: + viml_add(modlist, mod.name) + self.out("%s ", viml_join(modlist, " ")) + + def print_op1(self, node, op): + left = self.print(node.left) + if opprec[node.type] > opprec[node.left.type]: + left = "(" + left + ")" + return viml_printf("%s%s", op, left) + + def print_op2(self, node, op): + left = self.print(node.left) + if opprec[node.type] > opprec[node.left.type]: + left = "(" + left + ")" + right = self.print(node.right) + if opprec[node.type] > opprec[node.right.type]: + right = "(" + right + ")" + return viml_printf("%s %s %s", left, op, right) + # TODO: under construction class RegexpParser: RE_VERY_NOMAGIC = 1 diff --git a/scripts/update_builtin_commands.sh b/scripts/update_builtin_commands.sh index ca3d1d61..dbb8d3b6 100755 --- a/scripts/update_builtin_commands.sh +++ b/scripts/update_builtin_commands.sh @@ -8,6 +8,6 @@ fi vim -u NONE -i NONE -n -N -e -s \ --cmd "let &rtp .= ',' . getcwd()" \ --cmd "source scripts/update_builtin_commands.vim" \ - --cmd "call g:VimLParserNewCmds('$1')" \ + --cmd "call VimLParserNewCmds('$1')" \ --cmd "qall!" echo diff --git a/scripts/update_builtin_commands.vim b/scripts/update_builtin_commands.vim index 213bbc3a..8acc89e3 100644 --- a/scripts/update_builtin_commands.vim +++ b/scripts/update_builtin_commands.vim @@ -80,7 +80,6 @@ function! s:gen(ex_cmds_h) abort let trie = s:Trie.new() - let cumname = '' for [i, line] in map(copy(lines), {i, l -> [i, l]}) if line =~# '^EX(' let name = matchstr(line, '"\zs.*\ze",') @@ -123,7 +122,7 @@ endfunction " -- main " ex_cmds_h: path to vim/src/ex_cmds.h -function! g:VimLParserNewCmds(ex_cmds_h) abort +function! VimLParserNewCmds(ex_cmds_h) abort let vimlparser = vimlparser#import() let latest = s:gen(a:ex_cmds_h) let new_cmds = s:gen_new_builtin(vimlparser#import().VimLParser.builtin_commands, latest) diff --git a/test/run.vim b/test/run.vim index 4c7b323e..7ec13d63 100644 --- a/test/run.vim +++ b/test/run.vim @@ -9,9 +9,10 @@ function! s:run() for vimfile in glob(s:sdir . '/test*.vim', 0, 1) let okfile = fnamemodify(vimfile, ':r') . '.ok' let outfile = fnamemodify(vimfile, ':r') . '.out' + let vimokfile = fnamemodify(vimfile, ':r') . '.vimok' + let vimoutfile = fnamemodify(vimfile, ':r') . '.vimout' let skip = filereadable(fnamemodify(vimfile, ':r') . '.skip') let src = readfile(vimfile) - let r = s:vimlparser.StringReader.new(src) if vimfile =~# 'test_neo' let l:neovim = 1 else @@ -19,25 +20,49 @@ function! s:run() endif let p = s:vimlparser.VimLParser.new(l:neovim) let c = s:vimlparser.Compiler.new() + let pr = s:vimlparser.Printer.new() try + let r = s:vimlparser.StringReader.new(src) let out = c.compile(p.parse(r)) call writefile(out, outfile) catch call writefile([v:exception], outfile) endtry if system(printf('diff %s %s', shellescape(okfile), shellescape(outfile))) == "" - let line = printf('%s => ok', fnamemodify(vimfile, ':.')) + let line = printf('%s(compiler) => ok', fnamemodify(vimfile, ':.')) call append(line('$'), line) else if !skip let ng += 1 endif - let line = printf('%s => ' . (skip ? 'skip' : 'ng'), fnamemodify(vimfile, ':.')) + let line = printf('%s(compiler) => ' . (skip ? 'skip' : 'ng'), fnamemodify(vimfile, ':.')) call append(line('$'), line) for line in readfile(outfile) call append(line('$'), ' ' . line) endfor endif + if vimfile !~# 'err\|neo' + try + let r = s:vimlparser.StringReader.new(src) + let vimout = pr.print(p.parse(r)) + call writefile(vimout, vimoutfile) + catch + call writefile([v:exception], vimoutfile) + endtry + if system(printf('diff %s %s', shellescape(filereadable(vimokfile) ? vimokfile : vimfile), shellescape(vimoutfile))) == "" + let line = printf('%s(printer) => ok', fnamemodify(vimfile, ':.')) + call append(line('$'), line) + else + if !skip + let ng += 1 + endif + let line = printf('%s(printer) => ' . (skip ? 'skip' : 'ng'), fnamemodify(vimfile, ':.')) + call append(line('$'), line) + for line in readfile(vimoutfile) + call append(line('$'), ' ' . line) + endfor + endif + endif endfor if $CI == 'true' call writefile(getline(1, '$'), 'test.log') diff --git a/test/test1.vimok b/test/test1.vimok new file mode 100644 index 00000000..e608306c --- /dev/null +++ b/test/test1.vimok @@ -0,0 +1,53 @@ +" test1 +function s:foo(a, b, ...) + return 0 +endfunction +if 1 + echo "if 1" +elseif 2 + echo "elseif 2" +else + echo "else" +endif +while 1 + continue + break +endwhile +for [a, b; c] in d + echo a b c +endfor +delfunction s:foo +call s:foo(1, 2, 3) +let a = {"x" : "y"} +let [a, b; c] = [1, 2, 3] +let [a, b; c] += [1, 2, 3] +let [a, b; c] -= [1, 2, 3] +let [a, b; c] .= [1, 2, 3] +let foo.bar.baz = 123 +let foo[bar()][baz()] = 456 +let foo[bar()].baz = 789 +let foo[1:2] = [3, 4] +unlet a b c +lockvar a b c +lockvar 1 a b c +unlockvar a b c +unlockvar 1 a b c +try + throw "err" +catch /err/ + echo "catch /err/" +catch + echo "catch" +finally + echo "finally" +endtry +echohl Error +echon "echon" +echomsg "echomsg" +echoerr "echoerr" +execute "normal ihello" +echo [] [1, 2, 3] [1, 2, 3] +echo {} {"x" : "y"} {"x" : "y", "z" : "w"} +echo x[0] x[y] +echo x[1:2] x[1:] x[:2] x[:] +echo x.y x.y.z diff --git a/test/test_bar.vimok b/test/test_bar.vimok new file mode 100644 index 00000000..8cbdb0b2 --- /dev/null +++ b/test/test_bar.vimok @@ -0,0 +1,3 @@ +if 1 + set nocp +endif diff --git a/test/test_dict.vimok b/test/test_dict.vimok new file mode 100644 index 00000000..b378c200 --- /dev/null +++ b/test/test_dict.vimok @@ -0,0 +1,11 @@ +" test_dict +echo {} +echo {'1' : 1} +echo {1 : 1} +echo {x : 1} +echo {"\" : 1} +echo {"vim" : 1} +echo {1 + 1 : 2} +" XXX: echo {x:1} +echo {'x' : {}} +echo [{}] diff --git a/test/test_dot.vimok b/test/test_dot.vimok new file mode 100644 index 00000000..e1f953f3 --- /dev/null +++ b/test/test_dot.vimok @@ -0,0 +1,9 @@ +echo foo.bar +echo foo.bar.baz +echo "foo" . "bar" +echo foo . "bar" +echo "foo" . bar +echo foo.bar() +echo foo . s:bar +echo foo.123 +echo foo.123abc diff --git a/test/test_emptylc.vimok b/test/test_emptylc.vimok new file mode 100644 index 00000000..665284bb --- /dev/null +++ b/test/test_emptylc.vimok @@ -0,0 +1,2 @@ +" test_emptylc +echo 1 diff --git a/test/test_funcattr.vimok b/test/test_funcattr.vimok new file mode 100644 index 00000000..ba4a99df --- /dev/null +++ b/test/test_funcattr.vimok @@ -0,0 +1,4 @@ +function! F() abort +endfunction +function! F() abort closure dict range +endfunction diff --git a/test/test_lambda.vimok b/test/test_lambda.vimok new file mode 100644 index 00000000..5a0dcc7a --- /dev/null +++ b/test/test_lambda.vimok @@ -0,0 +1,5 @@ +" test_lambda +echo { -> 1 + 1} +echo {i, v -> v >= s:x} +echo {... -> a:000} +echo {x -> x * 2}(14) diff --git a/test/test_modifier_commands.vimok b/test/test_modifier_commands.vimok new file mode 100644 index 00000000..865c4340 --- /dev/null +++ b/test/test_modifier_commands.vimok @@ -0,0 +1,4 @@ +aboveleft belowright botright browse confirm hide keepalt keepjumps keepmarks keeppatterns lockmarks noswapfile silent tab topleft verbose vertical +call Func() +aboveleft belowright botright browse confirm hide keepalt keepjumps keepmarks keeppatterns lockmarks noswapfile silent tab topleft verbose vertical +call Func() diff --git a/test/test_syncmd.vimok b/test/test_syncmd.vimok new file mode 100644 index 00000000..32f2a044 --- /dev/null +++ b/test/test_syncmd.vimok @@ -0,0 +1,9 @@ +if 1 + syntax on +endif +syntax +syntax enable +syntax list GroupName +syn match pythonError "[&|]\{2,}" display +syntax match qfFileName /^\zs\S[^|]\+\/\ze[^|\/]\+\/[^|\/]\+|/ conceal cchar=+ +syntax region jsString start=+"+ skip=+\\\("\|$\)+ end=+"\|$+ contains=jsSpecial,@Spell extend diff --git a/test/test_wincmd.vimok b/test/test_wincmd.vimok new file mode 100644 index 00000000..8043d3d6 --- /dev/null +++ b/test/test_wincmd.vimok @@ -0,0 +1,3 @@ +if 1 + wincmd p +endif diff --git a/test/test_xxx_call_last_comma.vimok b/test/test_xxx_call_last_comma.vimok new file mode 100644 index 00000000..bd839f23 --- /dev/null +++ b/test/test_xxx_call_last_comma.vimok @@ -0,0 +1,2 @@ +call foo(a, b) +call bar(c, d) diff --git a/test/test_xxx_funcarg_last_comma.vimok b/test/test_xxx_funcarg_last_comma.vimok new file mode 100644 index 00000000..3d88e4ab --- /dev/null +++ b/test/test_xxx_funcarg_last_comma.vimok @@ -0,0 +1,4 @@ +function F(a) +endfunction +function G(a) +endfunction diff --git a/test/test_xxx_lambdaarg_last_comma.vimok b/test/test_xxx_lambdaarg_last_comma.vimok new file mode 100644 index 00000000..6fcb7a56 --- /dev/null +++ b/test/test_xxx_lambdaarg_last_comma.vimok @@ -0,0 +1,2 @@ +echo {a -> 0} +echo {a -> 0}