Skip to content

Instantly share code, notes, and snippets.

@tyru
Last active June 6, 2017 16:40
Show Gist options
  • Save tyru/76a9fdebd29e280d18836f07218a3da5 to your computer and use it in GitHub Desktop.
Save tyru/76a9fdebd29e280d18836f07218a3da5 to your computer and use it in GitHub Desktop.
Uglifier of Vim script
" test1
function s:foo(a, b, ...)
append
foo
bar
.
echo 'foo'
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
fu s:foo(a,b,...)
a
foo
bar
.
ec'foo'
retu 0
endf
if 1
ec"if 1"
elsei 2
ec"elseif 2"
el
ec"else"
en
wh 1
con
brea
endw
for[a,b;c]in d
ec a b c
endfo
delf s:foo
cal 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]
unl a b c
lockv a b c
lockv 1 a b c
unlo a b c
unlo 1 a b c
try
th"err"
cat/err/
ec"catch /err/"
cat
ec"catch"
fina
ec"finally"
endt
echoh Error
echon"echon"
echom"echomsg"
echoe"echoerr"
exe"normal ihello"
ec[] [1,2,3] [1,2,3]
ec{} {"x":"y"} {"x":"y","z":"w"}
ec x[0] x[y]
ec x[1:2] x[1:] x[:2] x[:]
ec x.y x.y.z
let s:vimlparser=vimlparser#import()
let s:T_STRING=type("")
let s:T_DICT=type({})
let s:T_LIST=type([])
fu!s:run() abort
let src=readfile('uglifier.vim')
let r=s:vimlparser.StringReader.new(src)
let neovim=0
let parser=s:vimlparser.VimLParser.new(neovim)
let uglifier=s:Uglifier.new()
ec uglifier.uglify(parser.parse(r))
endf
let s:UglifyNode={}
fu!s:UglifyNode.new(node) abort
retu extend(deepcopy(s:UglifyNode),{'node':a:node,'children':[]})
endf
fu!s:UglifyNode.add(child) abort
let self.children+=[a:child]
retu self
endf
fu!s:UglifyNode.add_fmt(...) abort
retu self.add(call('printf',a:000))
endf
fu!s:UglifyNode.concat(children) abort
let self.children+=a:children
retu self
endf
let s:Uglifier={}
fu!s:Uglifier.new() abort
retu deepcopy(self)
endf
fu!s:Uglifier.uglify(node) abort
let unode=self.uglify_node(a:node)
retu self.compile(unode)
endf
fu!s:Uglifier.uglify_node(node) abort dict
retu call(s:UGLIFY_FUNC[a:node.type],[a:node],self)
endf
fu!s:Uglifier.uglify_nodes(body) abort
retu map(copy(a:body),'self.uglify_node(v:val)')
endf
fu!s:Uglifier.compile(tree) abort
let parts=s:Uglifier.flatten_nodes(a:tree)
retu self.do_compile(parts)
endf
fu!s:Uglifier.flatten_nodes(tree) abort
if s:is_terminal_node(a:tree)
retu a:tree==#''?[]:[a:tree]
elsei s:is_conditional_node(a:tree)
retu[a:tree]
en
let nodes=a:tree.children
let parts=[]
for i in range(len(nodes))
if s:is_terminal_node(nodes[i])
let parts+=nodes[i]==#''?[]:[nodes[i]]
elsei s:is_conditional_node(nodes[i])
let parts+=[nodes[i]]
el
let parts+=s:Uglifier.flatten_nodes(nodes[i])
en
endfo
retu parts
endf
fu!s:Uglifier.do_compile(parts) abort
let source=[]
for i in range(len(a:parts))
if s:is_terminal_node(a:parts[i])
let source+=[a:parts[i]]
el
let prev_part=i>0?a:parts[i-1]:s:vimlparser.NIL
let next_part=i+1<len(a:parts)?a:parts[i+1]:s:vimlparser.NIL
let ctx={'prev_part':prev_part,'next_part':next_part}
let source+=[a:parts[i].get(ctx)]
en
endfo
retu join(source,'')
endf
fu!s:is_terminal_node(node) abort
retu type(a:node)is s:T_STRING
endf
fu!s:is_conditional_node(node) abort
retu type(a:node)is s:T_DICT&&has_key(a:node,'get')
endf
fu!s:place_between(list,sep) abort
if empty(a:list)
retu[]
en
let result=[a:list[0]]
for value in a:list[1:]
let result+=[a:sep,value]
endfo
retu result
endf
fu!s:word_boundary_space(ctx) abort
if s:is_terminal_node(a:ctx.prev_part)&&s:is_terminal_node(a:ctx.next_part)&&a:ctx.prev_part[len(a:ctx.prev_part)-1]!~#'\w'||a:ctx.next_part[0]!~#'\w'
retu''
en
retu' '
endf
let s:WORD_BOUNDARY_SPACE={'get':function('s:word_boundary_space')}
fu!s:ex_begin_newline(ctx) abort
if a:ctx.prev_part is s:vimlparser.NIL
retu''
el
retu"\n"
en
endf
let s:EX_BEGIN_NEWLINE={'get':function('s:ex_begin_newline')}
fu!s:ex_arg_space(ctx) abort
if s:is_terminal_node(a:ctx.next_part)&&a:ctx.next_part[0]!=#'!'&&a:ctx.next_part[0]!~#'\w'
retu''
el
retu' '
en
endf
let s:EX_ARG_SPACE={'get':function('s:ex_arg_space')}
let s:UGLIFY_FUNC={}
fu!s:uglify_toplevel(node) abort dict
retu s:UglifyNode.new(a:node).concat(self.uglify_nodes(a:node.body))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_TOPLEVEL]=function('s:uglify_toplevel')
fu!s:uglify_comment(node) abort dict
retu s:UglifyNode.new(a:node)
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_COMMENT]=function('s:uglify_comment')
fu!s:uglify_excmd(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).add(s:lookup_min_cmd(a:node.str))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_EXCMD]=function('s:uglify_excmd')
fu!s:lookup_min_cmd(cmd) abort
for cmd in s:vimlparser.VimLParser.builtin_commands
if cmd.name[cmd.minlen:]==#''
let re='^'.cmd.name
el
let re='^'.cmd.name[:cmd.minlen-1].'\%['.cmd.name[cmd.minlen:].']'
en
if a:cmd=~#re
retu substitute(a:cmd,re,cmd.name[:cmd.minlen-1],'')
en
endfo
retu a:cmd
endf
fu!s:uglify_function(node) abort dict
let unode=s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE)
let unode=unode.add(a:node.ea.forceit?'fu!':'fu ')
let unode=unode.add(self.uglify_node(a:node.left))
let unode=unode.add('(')
let unode=unode.concat(s:place_between(self.uglify_nodes(a:node.rlist),','))
let unode=unode.add(')')
let attrs=map(['range','abort','dict','closure'],'a:node.attr[v:val] ? " " . v:val : ""')
let unode=unode.concat(attrs)
let unode=unode.concat(self.uglify_nodes(a:node.body))
let unode=unode.add("\nendf")
retu unode
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_FUNCTION]=function('s:uglify_function')
fu!s:uglify_delfunction(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).add('delf').add(s:EX_ARG_SPACE).add(self.uglify_node(a:node.left))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_DELFUNCTION]=function('s:uglify_delfunction')
fu!s:uglify_return(node) abort dict
let unode=s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE)
if a:node.left is s:vimlparser.NIL
retu unode.add('retu')
el
retu unode.add('retu').add(s:EX_ARG_SPACE).add(self.uglify_node(a:node.left))
en
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_RETURN]=function('s:uglify_return')
fu!s:uglify_excall(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).add('cal').add(s:EX_ARG_SPACE).add(self.uglify_node(a:node.left))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_EXCALL]=function('s:uglify_excall')
fu!s:uglify_let(node) abort dict
let unode=s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE)
if a:node.left isnot s:vimlparser.NIL
let unode=unode.add('let')
let unode=unode.add(s:EX_ARG_SPACE)
let unode=unode.add(self.uglify_node(a:node.left))
el
let unode=unode.add('let[')
let unode=unode.concat(s:place_between(self.uglify_nodes(a:node.list),','))
if a:node.rest isnot s:vimlparser.NIL
let unode=unode.concat([';',self.uglify_node(a:node.rest)])
en
let unode=unode.add(']')
en
let unode=unode.concat([a:node.op,self.uglify_node(a:node.right)])
retu unode
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_LET]=function('s:uglify_let')
fu!s:uglify_unlet(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).concat(a:node.ea.forceit?['unl!']:['unl',s:EX_ARG_SPACE]).concat(s:place_between(self.uglify_nodes(a:node.list),' '))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_UNLET]=function('s:uglify_unlet')
fu!s:uglify_lockvar(node) abort dict
let unode=s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE)
if a:node.depth is s:vimlparser.NIL
let unode=unode.concat(a:node.ea.forceit?['lockv!']:['lockv',s:EX_ARG_SPACE])
el
let unode=unode.add_fmt('lockv%s %s ',a:node.ea.forceit?'!':'',a:node.depth)
en
let unode=unode.concat(s:place_between(self.uglify_nodes(a:node.list),' '))
retu unode
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_LOCKVAR]=function('s:uglify_lockvar')
fu!s:uglify_unlockvar(node) abort dict
let unode=s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE)
if a:node.depth is s:vimlparser.NIL
let unode=unode.concat(a:node.ea.forceit?['unlo!']:['unlo',s:EX_ARG_SPACE])
el
let unode=unode.add_fmt('unlo%s %s ',a:node.ea.forceit?'!':'',a:node.depth)
en
let unode=unode.concat(s:place_between(self.uglify_nodes(a:node.list),' '))
retu unode
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_UNLOCKVAR]=function('s:uglify_unlockvar')
fu!s:uglify_if(node) abort dict
let unode=s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE)
let unode=unode.concat(['if',s:EX_ARG_SPACE,self.uglify_node(a:node.cond)]+self.uglify_nodes(a:node.body))
for enode in a:node.elseif
let unode=unode.concat(["\nelsei",s:EX_ARG_SPACE,self.uglify_node(enode.cond)]+self.uglify_nodes(enode.body))
endfo
if a:node.else isnot s:vimlparser.NIL
let unode=unode.concat(["\nel"]+self.uglify_nodes(a:node.else.body))
en
let unode=unode.add("\nen")
retu unode
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_IF]=function('s:uglify_if')
fu!s:uglify_while(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).concat(['wh',s:EX_ARG_SPACE,self.uglify_node(a:node.cond)]+self.uglify_nodes(a:node.body)+["\nendw"])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_WHILE]=function('s:uglify_while')
fu!s:uglify_for(node) abort dict
let unode=s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE)
if a:node.left isnot s:vimlparser.NIL
let unode=unode.add('for ')
let unode=unode.add(self.uglify_node(a:node.left))
let unode=unode.concat([' in',s:EX_ARG_SPACE])
el
let unode=unode.add('for[')
let unode=unode.concat(s:place_between(self.uglify_nodes(a:node.list),','))
if a:node.rest isnot s:vimlparser.NIL
let unode=unode.concat([';',self.uglify_node(a:node.rest)])
en
let unode=unode.concat([']in',s:EX_ARG_SPACE])
en
let unode=unode.concat([self.uglify_node(a:node.right)]+self.uglify_nodes(a:node.body)+["\nendfo"])
retu unode
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_FOR]=function('s:uglify_for')
fu!s:uglify_continue(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).add('con')
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_CONTINUE]=function('s:uglify_continue')
fu!s:uglify_break(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).add('brea')
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_BREAK]=function('s:uglify_break')
fu!s:uglify_try(node) abort dict
let unode=s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE)
let unode=unode.concat(["try"]+self.uglify_nodes(a:node.body))
for cnode in a:node.catch
if cnode.pattern isnot s:vimlparser.NIL
let unode=unode.add_fmt("\ncat/%s/",cnode.pattern)
let unode=unode.concat(self.uglify_nodes(cnode.body))
el
let unode=unode.add("\ncat")
let unode=unode.concat(self.uglify_nodes(cnode.body))
en
endfo
if a:node.finally isnot s:vimlparser.NIL
let unode=unode.add("\nfina")
let unode=unode.concat(self.uglify_nodes(a:node.finally.body))
en
let unode=unode.add("\nendt")
retu unode
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_TRY]=function('s:uglify_try')
fu!s:uglify_throw(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).concat(['th',s:EX_ARG_SPACE,self.uglify_node(a:node.left)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_THROW]=function('s:uglify_throw')
fu!s:uglify_echo(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).concat(['ec',s:EX_ARG_SPACE]+s:place_between(self.uglify_nodes(a:node.list),' '))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHO]=function('s:uglify_echo')
fu!s:uglify_echon(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).concat(['echon',s:EX_ARG_SPACE]+s:place_between(self.uglify_nodes(a:node.list),' '))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHON]=function('s:uglify_echon')
fu!s:uglify_echohl(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).concat(['echoh',s:EX_ARG_SPACE,a:node.str])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHOHL]=function('s:uglify_echohl')
fu!s:uglify_echomsg(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).concat(['echom',s:EX_ARG_SPACE]+s:place_between(self.uglify_nodes(a:node.list),' '))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHOMSG]=function('s:uglify_echomsg')
fu!s:uglify_echoerr(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).concat(['echoe',s:EX_ARG_SPACE]+s:place_between(self.uglify_nodes(a:node.list),' '))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHOERR]=function('s:uglify_echoerr')
fu!s:uglify_execute(node) abort dict
retu s:UglifyNode.new(a:node).add(s:EX_BEGIN_NEWLINE).concat(['exe',s:EX_ARG_SPACE]+s:place_between(self.uglify_nodes(a:node.list),' '))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_EXECUTE]=function('s:uglify_execute')
fu!s:uglify_ternary(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.cond),'?',self.uglify_node(a:node.left),':',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_TERNARY]=function('s:uglify_ternary')
fu!s:uglify_or(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'||',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_OR]=function('s:uglify_or')
fu!s:uglify_and(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'&&',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_AND]=function('s:uglify_and')
fu!s:uglify_equal(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'==',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_EQUAL]=function('s:uglify_equal')
fu!s:uglify_equalci(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'==?',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_EQUALCI]=function('s:uglify_equalci')
fu!s:uglify_equalcs(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'==#',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_EQUALCS]=function('s:uglify_equalcs')
fu!s:uglify_nequal(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'!=',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_NEQUAL]=function('s:uglify_nequal')
fu!s:uglify_nequalci(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'!=?',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_NEQUALCI]=function('s:uglify_nequalci')
fu!s:uglify_nequalcs(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'!=#',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_NEQUALCS]=function('s:uglify_nequalcs')
fu!s:uglify_greater(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'>',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_GREATER]=function('s:uglify_greater')
fu!s:uglify_greaterci(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'>?',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_GREATERCI]=function('s:uglify_greaterci')
fu!s:uglify_greatercs(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'>#',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_GREATERCS]=function('s:uglify_greatercs')
fu!s:uglify_gequal(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'>=',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_GEQUAL]=function('s:uglify_gequal')
fu!s:uglify_gequalci(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'>=?',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_GEQUALCI]=function('s:uglify_gequalci')
fu!s:uglify_gequalcs(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'>=#',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_GEQUALCS]=function('s:uglify_gequalcs')
fu!s:uglify_smaller(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'<',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_SMALLER]=function('s:uglify_smaller')
fu!s:uglify_smallerci(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'<?',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_SMALLERCI]=function('s:uglify_smallerci')
fu!s:uglify_smallercs(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'<#',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_SMALLERCS]=function('s:uglify_smallercs')
fu!s:uglify_sequal(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'<=',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_SEQUAL]=function('s:uglify_sequal')
fu!s:uglify_sequalci(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'<=?',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_SEQUALCI]=function('s:uglify_sequalci')
fu!s:uglify_sequalcs(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'<=#',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_SEQUALCS]=function('s:uglify_sequalcs')
fu!s:uglify_match(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'=~',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_MATCH]=function('s:uglify_match')
fu!s:uglify_matchci(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'=~?',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_MATCHCI]=function('s:uglify_matchci')
fu!s:uglify_matchcs(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'=~#',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_MATCHCS]=function('s:uglify_matchcs')
fu!s:uglify_nomatch(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'!~',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_NOMATCH]=function('s:uglify_nomatch')
fu!s:uglify_nomatchci(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'!~?',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_NOMATCHCI]=function('s:uglify_nomatchci')
fu!s:uglify_nomatchcs(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'!~#',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_NOMATCHCS]=function('s:uglify_nomatchcs')
fu!s:uglify_is(node) abort dict
retu s:UglifyNode.new(a:node).add(self.uglify_node(a:node.left)).add(s:WORD_BOUNDARY_SPACE).add('is').add(s:WORD_BOUNDARY_SPACE).add(self.uglify_node(a:node.right))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_IS]=function('s:uglify_is')
fu!s:uglify_isci(node) abort dict
retu s:UglifyNode.new(a:node).add(self.uglify_node(a:node.left)).add(s:WORD_BOUNDARY_SPACE).add('is?').add(self.uglify_node(a:node.right))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISCI]=function('s:uglify_isci')
fu!s:uglify_iscs(node) abort dict
retu s:UglifyNode.new(a:node).add(self.uglify_node(a:node.left)).add(s:WORD_BOUNDARY_SPACE).add('is#').add(self.uglify_node(a:node.right))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISCS]=function('s:uglify_iscs')
fu!s:uglify_isnot(node) abort dict
retu s:UglifyNode.new(a:node).add(self.uglify_node(a:node.left)).add(s:WORD_BOUNDARY_SPACE).add('isnot').add(s:WORD_BOUNDARY_SPACE).add(self.uglify_node(a:node.right))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISNOT]=function('s:uglify_isnot')
fu!s:uglify_isnotci(node) abort dict
retu s:UglifyNode.new(a:node).add(self.uglify_node(a:node.left)).add(s:WORD_BOUNDARY_SPACE).add('isnot?').add(self.uglify_node(a:node.right))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISNOTCI]=function('s:uglify_isnotci')
fu!s:uglify_isnotcs(node) abort dict
retu s:UglifyNode.new(a:node).add(self.uglify_node(a:node.left)).add(s:WORD_BOUNDARY_SPACE).add('isnot#').add(self.uglify_node(a:node.right))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISNOTCS]=function('s:uglify_isnotcs')
fu!s:uglify_add(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'+',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ADD]=function('s:uglify_add')
fu!s:uglify_subtract(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'-',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_SUBTRACT]=function('s:uglify_subtract')
fu!s:uglify_concat(node) abort dict
retu call('s:uglify_dot',[a:node],self)
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_CONCAT]=function('s:uglify_concat')
fu!s:uglify_multiply(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'*',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_MULTIPLY]=function('s:uglify_multiply')
fu!s:uglify_divide(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'/',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_DIVIDE]=function('s:uglify_divide')
fu!s:uglify_remainder(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'%',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_REMAINDER]=function('s:uglify_remainder')
fu!s:uglify_not(node) abort dict
retu s:UglifyNode.new(a:node).concat(['!',self.uglify_node(a:node.left)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_NOT]=function('s:uglify_not')
fu!s:uglify_minus(node) abort dict
retu s:UglifyNode.new(a:node).concat(['-',self.uglify_node(a:node.left)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_MINUS]=function('s:uglify_minus')
fu!s:uglify_plus(node) abort dict
retu s:UglifyNode.new(a:node).concat(['+',self.uglify_node(a:node.left)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_PLUS]=function('s:uglify_plus')
fu!s:uglify_subscript(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'[',self.uglify_node(a:node.right),']'])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_SUBSCRIPT]=function('s:uglify_subscript')
fu!s:uglify_slice(node) abort dict
let unode=s:UglifyNode.new(a:node)
let unode=unode.add(self.uglify_node(a:node.left))
let unode=unode.add('[')
if a:node.rlist[0]isnot s:vimlparser.NIL
let unode=unode.add(self.uglify_node(a:node.rlist[0]))
en
let unode=unode.add(':')
if a:node.rlist[1]isnot s:vimlparser.NIL
let unode=unode.add(self.uglify_node(a:node.rlist[1]))
en
let unode=unode.add(']')
retu unode
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_SLICE]=function('s:uglify_slice')
fu!s:uglify_call(node) abort dict
retu s:UglifyNode.new(a:node).add(self.uglify_node(a:node.left)).add('(').concat(s:place_between(self.uglify_nodes(a:node.rlist),',')).add(')')
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_CALL]=function('s:uglify_call')
fu!s:uglify_dot(node) abort dict
retu s:UglifyNode.new(a:node).concat([self.uglify_node(a:node.left),'.',self.uglify_node(a:node.right)])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_DOT]=function('s:uglify_dot')
fu!s:uglify_number(node) abort dict
retu s:UglifyNode.new(a:node).add(a:node.value)
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_NUMBER]=function('s:uglify_number')
fu!s:uglify_string(node) abort dict
retu s:UglifyNode.new(a:node).add(a:node.value)
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_STRING]=function('s:uglify_string')
fu!s:uglify_list(node) abort dict
retu s:UglifyNode.new(a:node).add('[').concat(s:place_between(self.uglify_nodes(a:node.value),',')).add(']')
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_LIST]=function('s:uglify_list')
fu!s:uglify_dict(node) abort dict
let unode=s:UglifyNode.new(a:node).add('{')
let i=0
for entry in map(copy(a:node.value),'[self.uglify_node(v:val[0]), ":", self.uglify_node(v:val[1])]')
let unode=unode.concat(i>0?[',']:[]+entry)
let i+=1
endfo
let unode=unode.add('}')
retu unode
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_DICT]=function('s:uglify_dict')
fu!s:uglify_option(node) abort dict
retu s:UglifyNode.new(a:node).add(a:node.value)
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_OPTION]=function('s:uglify_option')
fu!s:uglify_identifier(node) abort dict
retu s:UglifyNode.new(a:node).add(a:node.value)
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_IDENTIFIER]=function('s:uglify_identifier')
fu!s:uglify_curlyname(node) abort dict
retu s:UglifyNode.new(a:node).concat(self.uglify_nodes(a:node.value))
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_CURLYNAME]=function('s:uglify_curlyname')
fu!s:uglify_env(node) abort dict
retu s:UglifyNode.new(a:node).add(a:node.value)
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_ENV]=function('s:uglify_env')
fu!s:uglify_reg(node) abort dict
retu s:UglifyNode.new(a:node).add(a:node.value)
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_REG]=function('s:uglify_reg')
fu!s:uglify_curlynamepart(node) abort dict
retu s:UglifyNode.new(a:node).add(a:node.value)
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_CURLYNAMEPART]=function('s:uglify_curlynamepart')
fu!s:uglify_curlynameexpr(node) abort dict
retu s:UglifyNode.new(a:node).concat(['{',self.uglify_node(a:node.value),'}'])
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_CURLYNAMEEXPR]=function('s:uglify_curlynameexpr')
fu!s:uglify_lambda(node) abort dict
retu s:UglifyNode.new(a:node).add('{').concat(s:place_between(self.uglify_nodes(a:node.rlist),',')).add('->').add(self.uglify_node(a:node.left)).add('}')
endf
let s:UGLIFY_FUNC[s:vimlparser.NODE_LAMBDA]=function('s:uglify_lambda')
cal s:run()
" REQUIREMENT:
" Add vim-vimlparser to 'runtimepath'
"
" RUN:
" 1. Open this script file (:e uglifier.vim)
" 2. so %
" 3. Uglified version of uglifier.vim (uglified-uglifier.vim) is echoed
"
" TODO:
" * Rename local / argument variables to 1-character variable if curly brace /
" eval() / execute are not used
" * Parse :execute arguments
" * Binary search builtin_commands
let s:vimlparser = vimlparser#import()
let s:T_STRING = type("")
let s:T_DICT = type({})
let s:T_LIST = type([])
function! s:run() abort
" let src = readfile('test-script.vim')
let src = readfile('uglifier.vim')
let r = s:vimlparser.StringReader.new(src)
let neovim = 0
let parser = s:vimlparser.VimLParser.new(neovim)
let uglifier = s:Uglifier.new()
echo uglifier.uglify(parser.parse(r))
endfunction
let s:UglifyNode = {}
" @param node Node
" @return UglifyNode
" node: Node
" children: List[String | UglifyNode | ConditionalNode]
function! s:UglifyNode.new(node) abort
return extend(deepcopy(s:UglifyNode),
\ {'node': a:node, 'children': []})
endfunction
" @param child String | UglifyNode | ConditionalNode
" @return UglifyNode
function! s:UglifyNode.add(child) abort
let self.children += [a:child]
return self
endfunction
function! s:UglifyNode.add_fmt(...) abort
return self.add(call('printf', a:000))
endfunction
" @param unode List[String | UglifyNode | ConditionalNode]
" @return UglifyNode
function! s:UglifyNode.concat(children) abort
let self.children += a:children
return self
endfunction
let s:Uglifier = {}
" TODO: Option (target Vim version, and so on)
function! s:Uglifier.new() abort
return deepcopy(self)
endfunction
" @param node Node
" @return String
function! s:Uglifier.uglify(node) abort
let unode = self.uglify_node(a:node)
return self.compile(unode)
endfunction
" @param node Node
" @return UglifyNode
function! s:Uglifier.uglify_node(node) abort dict
return call(s:UGLIFY_FUNC[a:node.type], [a:node], self)
endfunction
" @param body List[Node]
" @return List[UglifyNode]
function! s:Uglifier.uglify_nodes(body) abort
return map(copy(a:body), 'self.uglify_node(v:val)')
endfunction
" @param tree String | UglifyNode | ConditionalNode
" @return String
" NOTE: Using newline instead of '|' because command-bar affects the expression
function! s:Uglifier.compile(tree) abort
let parts = s:Uglifier.flatten_nodes(a:tree)
return self.do_compile(parts)
endfunction
" @param tree String | UglifyNode | ConditionalNode
" @return List[String | ConditionalNode]
function! s:Uglifier.flatten_nodes(tree) abort
if s:is_terminal_node(a:tree)
return a:tree ==# '' ? [] : [a:tree]
elseif s:is_conditional_node(a:tree)
return [a:tree]
endif
let nodes = a:tree.children
let parts = []
for i in range(len(nodes))
if s:is_terminal_node(nodes[i])
let parts += nodes[i] ==# '' ? [] : [nodes[i]]
elseif s:is_conditional_node(nodes[i])
let parts += [nodes[i]]
else
let parts += s:Uglifier.flatten_nodes(nodes[i])
endif
endfor
return parts
endfunction
" @param parts List[String | ConditionalNode]
" @return String
function! s:Uglifier.do_compile(parts) abort
let source = []
for i in range(len(a:parts))
if s:is_terminal_node(a:parts[i])
let source += [a:parts[i]]
else
let prev_part = i > 0 ? a:parts[i - 1] : s:vimlparser.NIL
let next_part = i + 1 < len(a:parts) ? a:parts[i + 1] : s:vimlparser.NIL
let ctx = {
\ 'prev_part': prev_part,
\ 'next_part': next_part
\}
let source += [a:parts[i].get(ctx)]
endif
endfor
return join(source, '')
endfunction
function! s:is_terminal_node(node) abort
return type(a:node) is s:T_STRING
endfunction
function! s:is_conditional_node(node) abort
return type(a:node) is s:T_DICT &&
\ has_key(a:node, 'get')
endfunction
function! s:place_between(list, sep) abort
if empty(a:list)
return []
endif
let result = [a:list[0]]
for value in a:list[1:]
let result += [a:sep, value]
endfor
return result
endfunction
function! s:word_boundary_space(ctx) abort
if s:is_terminal_node(a:ctx.prev_part) &&
\ s:is_terminal_node(a:ctx.next_part) &&
\ (a:ctx.prev_part[len(a:ctx.prev_part) - 1] !~# '\w' ||
\ a:ctx.next_part[0] !~# '\w')
return ''
endif
return ' '
endfunction
let s:WORD_BOUNDARY_SPACE = {'get': function('s:word_boundary_space')}
function! s:ex_begin_newline(ctx) abort
if a:ctx.prev_part is s:vimlparser.NIL
return ''
else
return "\n"
endif
endfunction
let s:EX_BEGIN_NEWLINE = {'get': function('s:ex_begin_newline')}
function! s:ex_arg_space(ctx) abort
if s:is_terminal_node(a:ctx.next_part) &&
\ a:ctx.next_part[0] !=# '!' &&
\ a:ctx.next_part[0] !~# '\w'
return ''
else
return ' '
endif
endfunction
let s:EX_ARG_SPACE = {'get': function('s:ex_arg_space')}
let s:UGLIFY_FUNC = {}
function! s:uglify_toplevel(node) abort dict
return s:UglifyNode.new(a:node)
\.concat(self.uglify_nodes(a:node.body))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_TOPLEVEL] = function('s:uglify_toplevel')
function! s:uglify_comment(node) abort dict
return s:UglifyNode.new(a:node)
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_COMMENT] = function('s:uglify_comment')
function! s:uglify_excmd(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.add(s:lookup_min_cmd(a:node.str))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_EXCMD] = function('s:uglify_excmd')
function! s:lookup_min_cmd(cmd) abort
for cmd in s:vimlparser.VimLParser.builtin_commands
if cmd.name[cmd.minlen :] ==# ''
let re = '^' . cmd.name
else
let re = '^' . cmd.name[: cmd.minlen - 1] . '\%[' . cmd.name[cmd.minlen :] . ']'
endif
if a:cmd =~# re
return substitute(a:cmd, re, cmd.name[: cmd.minlen - 1], '')
endif
endfor
return a:cmd
endfunction
" :function[!] {name}([arguments]) [range] [abort] [dict] [closure]
function! s:uglify_function(node) abort dict
let unode = s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
" :function
let unode = unode.add(a:node.ea.forceit ? 'fu!' : 'fu ')
" {name}
let unode = unode.add(self.uglify_node(a:node.left))
let unode = unode.add('(')
" arguments
let unode = unode.concat(
\ s:place_between(self.uglify_nodes(a:node.rlist), ','))
let unode = unode.add(')')
" attributes
let attrs = map(['range', 'abort', 'dict', 'closure'],
\ 'a:node.attr[v:val] ? " " . v:val : ""')
let unode = unode.concat(attrs)
" body
let unode = unode.concat(self.uglify_nodes(a:node.body))
let unode = unode.add("\nendf")
return unode
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_FUNCTION] = function('s:uglify_function')
function! s:uglify_delfunction(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.add('delf')
\.add(s:EX_ARG_SPACE)
\.add(self.uglify_node(a:node.left))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_DELFUNCTION] = function('s:uglify_delfunction')
function! s:uglify_return(node) abort dict
let unode = s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
if a:node.left is s:vimlparser.NIL
return unode.add('retu')
else
return unode.add('retu')
\.add(s:EX_ARG_SPACE)
\.add(self.uglify_node(a:node.left))
endif
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_RETURN] = function('s:uglify_return')
function! s:uglify_excall(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.add('cal')
\.add(s:EX_ARG_SPACE)
\.add(self.uglify_node(a:node.left))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_EXCALL] = function('s:uglify_excall')
function! s:uglify_let(node) abort dict
let unode = s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
if a:node.left isnot s:vimlparser.NIL
let unode = unode.add('let')
let unode = unode.add(s:EX_ARG_SPACE)
let unode = unode.add(self.uglify_node(a:node.left))
else
let unode = unode.add('let[')
let unode = unode.concat(s:place_between(self.uglify_nodes(a:node.list), ','))
if a:node.rest isnot s:vimlparser.NIL
let unode = unode.concat([';', self.uglify_node(a:node.rest)])
endif
let unode = unode.add(']')
endif
let unode = unode.concat([a:node.op, self.uglify_node(a:node.right)])
return unode
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_LET] = function('s:uglify_let')
function! s:uglify_unlet(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.concat(a:node.ea.forceit ? ['unl!'] : ['unl', s:EX_ARG_SPACE])
\.concat(
\ s:place_between(self.uglify_nodes(a:node.list), ' '))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_UNLET] = function('s:uglify_unlet')
function! s:uglify_lockvar(node) abort dict
let unode = s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
if a:node.depth is s:vimlparser.NIL
let unode = unode.concat(a:node.ea.forceit ? ['lockv!'] : ['lockv', s:EX_ARG_SPACE])
else
" NOTE: bang and depth cannot be used together (e.g. 'lockvar! 1').
" But output as-is.
let unode = unode.add_fmt('lockv%s %s ',
\ (a:node.ea.forceit ? '!' : ''), a:node.depth)
endif
let unode = unode.concat(
\ s:place_between(self.uglify_nodes(a:node.list), ' '))
return unode
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_LOCKVAR] = function('s:uglify_lockvar')
function! s:uglify_unlockvar(node) abort dict
let unode = s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
if a:node.depth is s:vimlparser.NIL
let unode = unode.concat(a:node.ea.forceit ? ['unlo!'] : ['unlo', s:EX_ARG_SPACE])
else
" NOTE: bang and depth cannot be used together (e.g. 'lockvar! 1').
" But output as-is.
let unode = unode.add_fmt('unlo%s %s ',
\ (a:node.ea.forceit ? '!' : ''), a:node.depth)
endif
let unode = unode.concat(
\ s:place_between(self.uglify_nodes(a:node.list), ' '))
return unode
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_UNLOCKVAR] = function('s:uglify_unlockvar')
function! s:uglify_if(node) abort dict
let unode = s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
let unode = unode.concat(['if', s:EX_ARG_SPACE, self.uglify_node(a:node.cond)] +
\ self.uglify_nodes(a:node.body))
for enode in a:node.elseif
let unode = unode.concat(["\nelsei", s:EX_ARG_SPACE, self.uglify_node(enode.cond)] +
\ self.uglify_nodes(enode.body))
endfor
if a:node.else isnot s:vimlparser.NIL
let unode = unode.concat(["\nel"] +
\ self.uglify_nodes(a:node.else.body))
endif
let unode = unode.add("\nen")
return unode
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_IF] = function('s:uglify_if')
function! s:uglify_while(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.concat(['wh', s:EX_ARG_SPACE, self.uglify_node(a:node.cond)] +
\ self.uglify_nodes(a:node.body) + ["\nendw"])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_WHILE] = function('s:uglify_while')
function! s:uglify_for(node) abort dict
let unode = s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
if a:node.left isnot s:vimlparser.NIL
let unode = unode.add('for ')
let unode = unode.add(self.uglify_node(a:node.left))
let unode = unode.concat([' in', s:EX_ARG_SPACE])
else
let unode = unode.add('for[')
let unode = unode.concat(s:place_between(self.uglify_nodes(a:node.list), ','))
if a:node.rest isnot s:vimlparser.NIL
let unode = unode.concat([';', self.uglify_node(a:node.rest)])
endif
let unode = unode.concat([']in', s:EX_ARG_SPACE])
endif
let unode = unode.concat([self.uglify_node(a:node.right)] +
\ self.uglify_nodes(a:node.body) + ["\nendfo"])
return unode
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_FOR] = function('s:uglify_for')
function! s:uglify_continue(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.add('con')
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_CONTINUE] = function('s:uglify_continue')
function! s:uglify_break(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.add('brea')
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_BREAK] = function('s:uglify_break')
function! s:uglify_try(node) abort dict
let unode = s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
let unode = unode.concat(["try"] + self.uglify_nodes(a:node.body))
for cnode in a:node.catch
if cnode.pattern isnot s:vimlparser.NIL
let unode = unode.add_fmt("\ncat/%s/", cnode.pattern)
let unode = unode.concat(self.uglify_nodes(cnode.body))
else
let unode = unode.add("\ncat")
let unode = unode.concat(self.uglify_nodes(cnode.body))
endif
endfor
if a:node.finally isnot s:vimlparser.NIL
let unode = unode.add("\nfina")
let unode = unode.concat(self.uglify_nodes(a:node.finally.body))
endif
let unode = unode.add("\nendt")
return unode
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_TRY] = function('s:uglify_try')
function! s:uglify_throw(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.concat(['th', s:EX_ARG_SPACE, self.uglify_node(a:node.left)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_THROW] = function('s:uglify_throw')
function! s:uglify_echo(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.concat(['ec', s:EX_ARG_SPACE] +
\ s:place_between(self.uglify_nodes(a:node.list), ' '))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHO] = function('s:uglify_echo')
function! s:uglify_echon(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.concat(['echon', s:EX_ARG_SPACE] +
\ s:place_between(self.uglify_nodes(a:node.list), ' '))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHON] = function('s:uglify_echon')
function! s:uglify_echohl(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.concat(['echoh', s:EX_ARG_SPACE, a:node.str])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHOHL] = function('s:uglify_echohl')
function! s:uglify_echomsg(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.concat(['echom', s:EX_ARG_SPACE] +
\ s:place_between(self.uglify_nodes(a:node.list), ' '))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHOMSG] = function('s:uglify_echomsg')
function! s:uglify_echoerr(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.concat(['echoe', s:EX_ARG_SPACE] +
\ s:place_between(self.uglify_nodes(a:node.list), ' '))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ECHOERR] = function('s:uglify_echoerr')
function! s:uglify_execute(node) abort dict
return s:UglifyNode.new(a:node)
\.add(s:EX_BEGIN_NEWLINE)
\.concat(['exe', s:EX_ARG_SPACE] +
\ s:place_between(self.uglify_nodes(a:node.list), ' '))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_EXECUTE] = function('s:uglify_execute')
function! s:uglify_ternary(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.cond),
\ '?',
\ self.uglify_node(a:node.left),
\ ':',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_TERNARY] = function('s:uglify_ternary')
function! s:uglify_or(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '||',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_OR] = function('s:uglify_or')
function! s:uglify_and(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '&&',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_AND] = function('s:uglify_and')
function! s:uglify_equal(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '==',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_EQUAL] = function('s:uglify_equal')
function! s:uglify_equalci(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '==?',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_EQUALCI] = function('s:uglify_equalci')
function! s:uglify_equalcs(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '==#',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_EQUALCS] = function('s:uglify_equalcs')
function! s:uglify_nequal(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '!=',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_NEQUAL] = function('s:uglify_nequal')
function! s:uglify_nequalci(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '!=?',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_NEQUALCI] = function('s:uglify_nequalci')
function! s:uglify_nequalcs(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '!=#',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_NEQUALCS] = function('s:uglify_nequalcs')
function! s:uglify_greater(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '>',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_GREATER] = function('s:uglify_greater')
function! s:uglify_greaterci(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '>?',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_GREATERCI] = function('s:uglify_greaterci')
function! s:uglify_greatercs(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '>#',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_GREATERCS] = function('s:uglify_greatercs')
function! s:uglify_gequal(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '>=',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_GEQUAL] = function('s:uglify_gequal')
function! s:uglify_gequalci(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '>=?',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_GEQUALCI] = function('s:uglify_gequalci')
function! s:uglify_gequalcs(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '>=#',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_GEQUALCS] = function('s:uglify_gequalcs')
function! s:uglify_smaller(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '<',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_SMALLER] = function('s:uglify_smaller')
function! s:uglify_smallerci(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '<?',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_SMALLERCI] = function('s:uglify_smallerci')
function! s:uglify_smallercs(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '<#',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_SMALLERCS] = function('s:uglify_smallercs')
function! s:uglify_sequal(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '<=',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_SEQUAL] = function('s:uglify_sequal')
function! s:uglify_sequalci(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '<=?',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_SEQUALCI] = function('s:uglify_sequalci')
function! s:uglify_sequalcs(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '<=#',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_SEQUALCS] = function('s:uglify_sequalcs')
function! s:uglify_match(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '=~',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_MATCH] = function('s:uglify_match')
function! s:uglify_matchci(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '=~?',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_MATCHCI] = function('s:uglify_matchci')
function! s:uglify_matchcs(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '=~#',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_MATCHCS] = function('s:uglify_matchcs')
function! s:uglify_nomatch(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '!~',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_NOMATCH] = function('s:uglify_nomatch')
function! s:uglify_nomatchci(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '!~?',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_NOMATCHCI] = function('s:uglify_nomatchci')
function! s:uglify_nomatchcs(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '!~#',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_NOMATCHCS] = function('s:uglify_nomatchcs')
function! s:uglify_is(node) abort dict
return s:UglifyNode.new(a:node)
\.add(self.uglify_node(a:node.left))
\.add(s:WORD_BOUNDARY_SPACE)
\.add('is')
\.add(s:WORD_BOUNDARY_SPACE)
\.add(self.uglify_node(a:node.right))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_IS] = function('s:uglify_is')
function! s:uglify_isci(node) abort dict
return s:UglifyNode.new(a:node)
\.add(self.uglify_node(a:node.left))
\.add(s:WORD_BOUNDARY_SPACE)
\.add('is?')
\.add(self.uglify_node(a:node.right))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISCI] = function('s:uglify_isci')
function! s:uglify_iscs(node) abort dict
return s:UglifyNode.new(a:node)
\.add(self.uglify_node(a:node.left))
\.add(s:WORD_BOUNDARY_SPACE)
\.add('is#')
\.add(self.uglify_node(a:node.right))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISCS] = function('s:uglify_iscs')
function! s:uglify_isnot(node) abort dict
return s:UglifyNode.new(a:node)
\.add(self.uglify_node(a:node.left))
\.add(s:WORD_BOUNDARY_SPACE)
\.add('isnot')
\.add(s:WORD_BOUNDARY_SPACE)
\.add(self.uglify_node(a:node.right))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISNOT] = function('s:uglify_isnot')
function! s:uglify_isnotci(node) abort dict
return s:UglifyNode.new(a:node)
\.add(self.uglify_node(a:node.left))
\.add(s:WORD_BOUNDARY_SPACE)
\.add('isnot?')
\.add(self.uglify_node(a:node.right))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISNOTCI] = function('s:uglify_isnotci')
function! s:uglify_isnotcs(node) abort dict
return s:UglifyNode.new(a:node)
\.add(self.uglify_node(a:node.left))
\.add(s:WORD_BOUNDARY_SPACE)
\.add('isnot#')
\.add(self.uglify_node(a:node.right))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ISNOTCS] = function('s:uglify_isnotcs')
function! s:uglify_add(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '+',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ADD] = function('s:uglify_add')
function! s:uglify_subtract(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '-',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_SUBTRACT] = function('s:uglify_subtract')
" XXX: NODE_DOT(property access or string concatenation) and
" NODE_CONCAT(string concatenation) are different. is it safe to mix?
function! s:uglify_concat(node) abort dict
return call('s:uglify_dot', [a:node], self)
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_CONCAT] = function('s:uglify_concat')
function! s:uglify_multiply(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '*',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_MULTIPLY] = function('s:uglify_multiply')
function! s:uglify_divide(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '/',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_DIVIDE] = function('s:uglify_divide')
function! s:uglify_remainder(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '%',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_REMAINDER] = function('s:uglify_remainder')
function! s:uglify_not(node) abort dict
return s:UglifyNode.new(a:node)
\.concat(['!', self.uglify_node(a:node.left)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_NOT] = function('s:uglify_not')
function! s:uglify_minus(node) abort dict
return s:UglifyNode.new(a:node)
\.concat(['-', self.uglify_node(a:node.left)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_MINUS] = function('s:uglify_minus')
function! s:uglify_plus(node) abort dict
return s:UglifyNode.new(a:node)
\.concat(['+', self.uglify_node(a:node.left)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_PLUS] = function('s:uglify_plus')
function! s:uglify_subscript(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '[',
\ self.uglify_node(a:node.right),
\ ']'])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_SUBSCRIPT] = function('s:uglify_subscript')
function! s:uglify_slice(node) abort dict
let unode = s:UglifyNode.new(a:node)
let unode = unode.add(self.uglify_node(a:node.left))
let unode = unode.add('[')
if a:node.rlist[0] isnot s:vimlparser.NIL
let unode = unode.add(self.uglify_node(a:node.rlist[0]))
endif
let unode = unode.add(':')
if a:node.rlist[1] isnot s:vimlparser.NIL
let unode = unode.add(self.uglify_node(a:node.rlist[1]))
endif
let unode = unode.add(']')
return unode
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_SLICE] = function('s:uglify_slice')
function! s:uglify_call(node) abort dict
return s:UglifyNode.new(a:node)
\.add(self.uglify_node(a:node.left))
\.add('(')
\.concat(
\ s:place_between(self.uglify_nodes(a:node.rlist), ','))
\.add(')')
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_CALL] = function('s:uglify_call')
function! s:uglify_dot(node) abort dict
return s:UglifyNode.new(a:node)
\.concat([self.uglify_node(a:node.left),
\ '.',
\ self.uglify_node(a:node.right)])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_DOT] = function('s:uglify_dot')
function! s:uglify_number(node) abort dict
return s:UglifyNode.new(a:node).add(a:node.value)
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_NUMBER] = function('s:uglify_number')
function! s:uglify_string(node) abort dict
return s:UglifyNode.new(a:node).add(a:node.value)
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_STRING] = function('s:uglify_string')
function! s:uglify_list(node) abort dict
return s:UglifyNode.new(a:node)
\.add('[')
\.concat(s:place_between(self.uglify_nodes(a:node.value), ','))
\.add(']')
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_LIST] = function('s:uglify_list')
function! s:uglify_dict(node) abort dict
let unode = s:UglifyNode.new(a:node)
\.add('{')
let i = 0
for entry in map(copy(a:node.value),
\ '[self.uglify_node(v:val[0]), ":", self.uglify_node(v:val[1])]')
let unode = unode.concat((i > 0 ? [','] : []) + entry)
let i += 1
endfor
let unode = unode.add('}')
return unode
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_DICT] = function('s:uglify_dict')
function! s:uglify_option(node) abort dict
return s:UglifyNode.new(a:node).add(a:node.value)
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_OPTION] = function('s:uglify_option')
function! s:uglify_identifier(node) abort dict
return s:UglifyNode.new(a:node).add(a:node.value)
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_IDENTIFIER] = function('s:uglify_identifier')
function! s:uglify_curlyname(node) abort dict
return s:UglifyNode.new(a:node).concat(self.uglify_nodes(a:node.value))
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_CURLYNAME] = function('s:uglify_curlyname')
function! s:uglify_env(node) abort dict
return s:UglifyNode.new(a:node).add(a:node.value)
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_ENV] = function('s:uglify_env')
function! s:uglify_reg(node) abort dict
return s:UglifyNode.new(a:node).add(a:node.value)
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_REG] = function('s:uglify_reg')
function! s:uglify_curlynamepart(node) abort dict
return s:UglifyNode.new(a:node).add(a:node.value)
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_CURLYNAMEPART] = function('s:uglify_curlynamepart')
function! s:uglify_curlynameexpr(node) abort dict
return s:UglifyNode.new(a:node)
\.concat(['{', self.uglify_node(a:node.value), '}'])
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_CURLYNAMEEXPR] = function('s:uglify_curlynameexpr')
function! s:uglify_lambda(node) abort dict
return s:UglifyNode.new(a:node)
\.add('{')
\.concat(s:place_between(self.uglify_nodes(a:node.rlist), ','))
\.add('->')
\.add(self.uglify_node(a:node.left))
\.add('}')
endfunction
let s:UGLIFY_FUNC[s:vimlparser.NODE_LAMBDA] = function('s:uglify_lambda')
call s:run()
@tyru
Copy link
Author

tyru commented Jun 6, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment