Fix unescaping in matlab, miniMAL and rpython.
[jackhill/mal.git] / vimscript / step4_if_fn_do.vim
CommitLineData
50a964ce
DM
1source readline.vim
2source types.vim
3source reader.vim
4source printer.vim
5source env.vim
6source core.vim
7
8function READ(str)
9 return ReadStr(a:str)
10endfunction
11
12function EvalAst(ast, env)
13 if SymbolQ(a:ast)
82641edb 14 let varname = a:ast.val
50a964ce
DM
15 return a:env.get(varname)
16 elseif ListQ(a:ast)
4fbbe571 17 return ListNew(map(copy(a:ast.val), {_, e -> EVAL(e, a:env)}))
50a964ce 18 elseif VectorQ(a:ast)
4fbbe571 19 return VectorNew(map(copy(a:ast.val), {_, e -> EVAL(e, a:env)}))
50a964ce
DM
20 elseif HashQ(a:ast)
21 let ret = {}
82641edb 22 for [k,v] in items(a:ast.val)
50a964ce
DM
23 let keyobj = HashParseKey(k)
24 let newkey = EVAL(keyobj, a:env)
25 let newval = EVAL(v, a:env)
26 let keystring = HashMakeKey(newkey)
27 let ret[keystring] = newval
28 endfor
29 return HashNew(ret)
30 else
31 return a:ast
32 end
33endfunction
34
35function EVAL(ast, env)
36 if !ListQ(a:ast)
37 return EvalAst(a:ast, a:env)
38 end
8f27005f
DM
39 if EmptyQ(a:ast)
40 return a:ast
41 endif
50a964ce
DM
42
43 let first = ListFirst(a:ast)
82641edb 44 let first_symbol = SymbolQ(first) ? first.val : ""
50a964ce 45 if first_symbol == "def!"
82641edb
DM
46 let a1 = a:ast.val[1]
47 let a2 = a:ast.val[2]
48 let ret = a:env.set(a1.val, EVAL(a2, a:env))
50a964ce
DM
49 return ret
50 elseif first_symbol == "let*"
82641edb
DM
51 let a1 = a:ast.val[1]
52 let a2 = a:ast.val[2]
50a964ce 53 let let_env = NewEnv(a:env)
82641edb 54 let let_binds = a1.val
50a964ce
DM
55 let i = 0
56 while i < len(let_binds)
82641edb 57 call let_env.set(let_binds[i].val, EVAL(let_binds[i+1], let_env))
50a964ce
DM
58 let i = i + 2
59 endwhile
60 return EVAL(a2, let_env)
61 elseif first_symbol == "if"
82641edb 62 let condvalue = EVAL(a:ast.val[1], a:env)
50a964ce 63 if FalseQ(condvalue) || NilQ(condvalue)
82641edb 64 if len(a:ast.val) < 4
50a964ce
DM
65 return g:MalNil
66 else
82641edb 67 return EVAL(a:ast.val[3], a:env)
50a964ce
DM
68 endif
69 else
82641edb 70 return EVAL(a:ast.val[2], a:env)
50a964ce
DM
71 endif
72 elseif first_symbol == "do"
73 let el = EvalAst(ListRest(a:ast), a:env)
82641edb 74 return el.val[-1]
50a964ce
DM
75 elseif first_symbol == "fn*"
76 let fn = NewFn(ListNth(a:ast, 2), a:env, ListNth(a:ast, 1))
77 return fn
78 else
79 " apply list
80 let el = EvalAst(a:ast, a:env)
81 let funcobj = ListFirst(el)
82 let args = ListRest(el)
83 if NativeFunctionQ(funcobj)
84 return NativeFuncInvoke(funcobj, args)
85 elseif FunctionQ(funcobj)
86 return FuncInvoke(funcobj, args)
87 else
88 throw "Not a function"
89 endif
90 endif
91endfunction
92
93function PRINT(exp)
94 return PrStr(a:exp, 1)
95endfunction
96
97function REP(str, env)
98 return PRINT(EVAL(READ(a:str), a:env))
99endfunction
100
101let repl_env = NewEnv("")
102
103for [k, Fn] in items(CoreNs)
104 call repl_env.set(k, Fn)
105endfor
106
107call REP("(def! not (fn* (a) (if a false true)))", repl_env)
108
109while 1
110 let [eof, line] = Readline("user> ")
111 if eof
112 break
113 endif
114 if line == ""
115 continue
116 endif
117 try
118 call PrintLn(REP(line, repl_env))
119 catch
120 call PrintLn("Error: " . v:exception)
121 endtry
122endwhile
123qall!