DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / vimscript / step6_file.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 let ast = a:ast
37 let env = a:env
38
39 while 1
40 if !ListQ(ast)
41 return EvalAst(ast, env)
42 end
8f27005f
DM
43 if EmptyQ(ast)
44 return ast
45 endif
50a964ce
DM
46
47 let first = ListFirst(ast)
82641edb 48 let first_symbol = SymbolQ(first) ? first.val : ""
50a964ce 49 if first_symbol == "def!"
82641edb
DM
50 let a1 = ast.val[1]
51 let a2 = ast.val[2]
52 let ret = env.set(a1.val, EVAL(a2, env))
50a964ce
DM
53 return ret
54 elseif first_symbol == "let*"
82641edb
DM
55 let a1 = ast.val[1]
56 let a2 = ast.val[2]
50a964ce 57 let env = NewEnv(env)
82641edb 58 let let_binds = a1.val
50a964ce
DM
59 let i = 0
60 while i < len(let_binds)
82641edb 61 call env.set(let_binds[i].val, EVAL(let_binds[i+1], env))
50a964ce
DM
62 let i = i + 2
63 endwhile
64 let ast = a2
65 " TCO
66 elseif first_symbol == "if"
82641edb 67 let condvalue = EVAL(ast.val[1], env)
50a964ce 68 if FalseQ(condvalue) || NilQ(condvalue)
82641edb 69 if len(ast.val) < 4
50a964ce
DM
70 return g:MalNil
71 else
82641edb 72 let ast = ast.val[3]
50a964ce
DM
73 endif
74 else
82641edb 75 let ast = ast.val[2]
50a964ce
DM
76 endif
77 " TCO
78 elseif first_symbol == "do"
82641edb 79 let astlist = ast.val
50a964ce
DM
80 call EvalAst(ListNew(astlist[1:-2]), env)
81 let ast = astlist[-1]
82 " TCO
83 elseif first_symbol == "fn*"
84 let fn = NewFn(ListNth(ast, 2), env, ListNth(ast, 1))
85 return fn
86 elseif first_symbol == "eval"
87 let ast = EVAL(ListNth(ast, 1), env)
88 let env = env.root()
89 " TCO
90 else
91 " apply list
92 let el = EvalAst(ast, env)
93 let funcobj = ListFirst(el)
94 let args = ListRest(el)
95 if NativeFunctionQ(funcobj)
96 return NativeFuncInvoke(funcobj, args)
97 elseif FunctionQ(funcobj)
82641edb 98 let fn = funcobj.val
50a964ce
DM
99 let ast = fn.ast
100 let env = NewEnvWithBinds(fn.env, fn.params, args)
101 " TCO
102 else
103 throw "Not a function"
104 endif
105 endif
106 endwhile
107endfunction
108
109function PRINT(exp)
110 return PrStr(a:exp, 1)
111endfunction
112
113function RE(str, env)
114 return EVAL(READ(a:str), a:env)
115endfunction
116
117function REP(str, env)
118 return PRINT(EVAL(READ(a:str), a:env))
119endfunction
120
121function GetArgvList()
43d17539 122 return ListNew(map(copy(argv()[1:]), {_, arg -> StringNew(arg)}))
50a964ce
DM
123endfunction
124
125set maxfuncdepth=10000
126let repl_env = NewEnv("")
127
128for [k, v] in items(CoreNs)
129 call repl_env.set(k, v)
130endfor
131
132call repl_env.set("*ARGV*", GetArgvList())
133
134call RE("(def! not (fn* (a) (if a false true)))", repl_env)
e6d41de4 135call RE("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))", repl_env)
50a964ce
DM
136
137if !empty(argv())
138 call RE('(load-file "' . argv(0) . '")', repl_env)
139 qall!
140endif
141
142while 1
143 let [eof, line] = Readline("user> ")
144 if eof
145 break
146 endif
147 if line == ""
148 continue
149 endif
150 try
151 call PrintLn(REP(line, repl_env))
152 catch
153 call PrintLn("Error: " . v:exception)
154 endtry
155endwhile
156qall!