1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-20 01:57:09 +03:00
mal/vimscript/step2_eval.vim
2015-10-20 15:04:04 -04:00

101 lines
2.0 KiB
VimL

source readline.vim
source types.vim
source reader.vim
source printer.vim
function READ(str)
return ReadStr(a:str)
endfunction
function EvalAst(ast, env)
if SymbolQ(a:ast)
let varname = ObjValue(a:ast)
if !has_key(a:env, varname)
throw "'" . varname . "' not found"
end
return a:env[varname]
elseif ListQ(a:ast)
let ret = []
for e in ObjValue(a:ast)
call add(ret, EVAL(e, a:env))
endfor
return ListNew(ret)
elseif VectorQ(a:ast)
let ret = []
for e in ObjValue(a:ast)
call add(ret, EVAL(e, a:env))
endfor
return VectorNew(ret)
elseif HashQ(a:ast)
let ret = {}
for [k,v] in items(ObjValue(a:ast))
let keyobj = HashParseKey(k)
let newkey = EVAL(keyobj, a:env)
let newval = EVAL(v, a:env)
let keystring = HashMakeKey(newkey)
let ret[keystring] = newval
endfor
return HashNew(ret)
else
return a:ast
end
endfunction
function EVAL(ast, env)
if !ListQ(a:ast)
return EvalAst(a:ast, a:env)
end
" apply list
let el = EvalAst(a:ast, a:env)
let Fn = ObjValue(el)[0]
return Fn(ObjValue(el)[1:-1])
endfunction
function PRINT(exp)
return PrStr(a:exp, 1)
endfunction
function REP(str, env)
return PRINT(EVAL(READ(a:str), a:env))
endfunction
function MalAdd(args)
return IntegerNew(ObjValue(a:args[0]) + ObjValue(a:args[1]))
endfunction
function MalSub(args)
return IntegerNew(ObjValue(a:args[0]) - ObjValue(a:args[1]))
endfunction
function MalMul(args)
return IntegerNew(ObjValue(a:args[0]) * ObjValue(a:args[1]))
endfunction
function MalDiv(args)
return IntegerNew(ObjValue(a:args[0]) / ObjValue(a:args[1]))
endfunction
let repl_env = {}
let repl_env["+"] = function("MalAdd")
let repl_env["-"] = function("MalSub")
let repl_env["*"] = function("MalMul")
let repl_env["/"] = function("MalDiv")
while 1
let [eof, line] = Readline("user> ")
if eof
break
endif
if line == ""
continue
endif
try
call PrintLn(REP(line, repl_env))
catch
call PrintLn("ERROR: " . v:exception)
endtry
endwhile
qall!