DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / vimscript / step2_eval.vim
CommitLineData
50a964ce
DM
1source readline.vim
2source types.vim
3source reader.vim
4source printer.vim
5
6function READ(str)
7 return ReadStr(a:str)
8endfunction
9
10function EvalAst(ast, env)
11 if SymbolQ(a:ast)
82641edb 12 let varname = a:ast.val
50a964ce
DM
13 if !has_key(a:env, varname)
14 throw "'" . varname . "' not found"
15 end
16 return a:env[varname]
17 elseif ListQ(a:ast)
4fbbe571 18 return ListNew(map(copy(a:ast.val), {_, e -> EVAL(e, a:env)}))
50a964ce 19 elseif VectorQ(a:ast)
4fbbe571 20 return VectorNew(map(copy(a:ast.val), {_, e -> EVAL(e, a:env)}))
50a964ce
DM
21 elseif HashQ(a:ast)
22 let ret = {}
82641edb 23 for [k,v] in items(a:ast.val)
50a964ce
DM
24 let keyobj = HashParseKey(k)
25 let newkey = EVAL(keyobj, a:env)
26 let newval = EVAL(v, a:env)
27 let keystring = HashMakeKey(newkey)
28 let ret[keystring] = newval
29 endfor
30 return HashNew(ret)
31 else
32 return a:ast
33 end
34endfunction
35
36function EVAL(ast, env)
37 if !ListQ(a:ast)
38 return EvalAst(a:ast, a:env)
39 end
efa2daef
JM
40 if EmptyQ(a:ast)
41 return a:ast
42 endif
50a964ce
DM
43
44 " apply list
45 let el = EvalAst(a:ast, a:env)
46
82641edb
DM
47 let Fn = el.val[0]
48 return Fn(el.val[1:-1])
50a964ce
DM
49endfunction
50
51function PRINT(exp)
52 return PrStr(a:exp, 1)
53endfunction
54
55function REP(str, env)
56 return PRINT(EVAL(READ(a:str), a:env))
57endfunction
58
50a964ce 59let repl_env = {}
aa62cbda
DM
60let repl_env["+"] = {a -> IntegerNew(a[0].val + a[1].val)}
61let repl_env["-"] = {a -> IntegerNew(a[0].val - a[1].val)}
62let repl_env["*"] = {a -> IntegerNew(a[0].val * a[1].val)}
63let repl_env["/"] = {a -> IntegerNew(a[0].val / a[1].val)}
50a964ce
DM
64
65while 1
66 let [eof, line] = Readline("user> ")
67 if eof
68 break
69 endif
70 if line == ""
71 continue
72 endif
73 try
74 call PrintLn(REP(line, repl_env))
75 catch
76 call PrintLn("ERROR: " . v:exception)
77 endtry
78endwhile
79qall!