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