function! s:eval(e, v)
if type(a:v) == type([])
return s:doRun(a:e, a:v)
endif
return a:v
endfunction
function! s:doRun(e, v)
let r = 0
let m = a:v[0]
if m == "step"
for vv in a:v[1:]
let r = s:doRun(a:e, vv)
endfor
elseif m == "until"
while !s:eval(a:e, a:v[1])
let r = s:doRun(a:e, a:v[2])
endwhile
elseif m == "while"
while s:eval(a:e, a:v[1])
let r = s:doRun(a:e, a:v[2])
endwhile
elseif m == "set"
let r = s:eval(a:e, a:v[2])
let a:e[s:eval(a:e, a:v[1])] = r
elseif m == "get"
let r = a:e[s:eval(a:e, a:v[1])]
elseif m == "<="
let r = s:eval(a:e, a:v[1]) <= s:eval(a:e, a:v[2])
elseif m == "="
let r = s:eval(a:e, a:v[1]) == s:eval(a:e, a:v[2])
elseif m == "+"
let r = s:eval(a:e, a:v[1]) + s:eval(a:e, a:v[2])
elseif m == "print"
let r = s:eval(a:e, a:v[1])
echo r
else
throw "unknown operator: " + string(a:v)
endif
return r
endfunction
let s:source = '
\["step",
\ ["set", "sum", 0 ],
\ ["set", "i", 1 ],
\ ["while", ["<=", ["get", "i"], 10],
\ ["step",
\ ["set", "sum", ["+", ["get", "sum"], ["get", "i"]]],
\ ["set", "i", ["+", ["get", "i"], 1]]]],
\ ["print", ["get", "sum"]]]
\'
let v = json_decode(s:source)
call s:doRun({}, v)