13 return SequentialQ(a:obj) && !EmptyQ(a:obj)
16 function Quasiquote(ast)
18 return ListNew([SymbolNew("quote"), a:ast])
20 let a0 = ListFirst(a:ast)
21 if SymbolQ(a0) && a0.val == "unquote"
22 return ListNth(a:ast, 1)
23 elseif PairQ(a0) && SymbolQ(ListFirst(a0)) && ListFirst(a0).val == "splice-unquote"
24 return ListNew([SymbolNew("concat"), ListNth(a0, 1), Quasiquote(ListRest(a:ast))])
26 return ListNew([SymbolNew("cons"), Quasiquote(a0), Quasiquote(ListRest(a:ast))])
30 function EvalAst(ast, env)
32 let varname = a:ast.val
33 return a:env.get(varname)
35 return ListNew(map(copy(a:ast.val), {_, e -> EVAL(e, a:env)}))
37 return VectorNew(map(copy(a:ast.val), {_, e -> EVAL(e, a:env)}))
40 for [k,v] in items(a:ast.val)
41 let keyobj = HashParseKey(k)
42 let newkey = EVAL(keyobj, a:env)
43 let newval = EVAL(v, a:env)
44 let keystring = HashMakeKey(newkey)
45 let ret[keystring] = newval
53 function EVAL(ast, env)
59 return EvalAst(ast, env)
65 let first = ListFirst(ast)
66 let first_symbol = SymbolQ(first) ? first.val : ""
67 if first_symbol == "def!"
70 let ret = env.set(a1.val, EVAL(a2, env))
72 elseif first_symbol == "let*"
76 let let_binds = a1.val
78 while i < len(let_binds)
79 call env.set(let_binds[i].val, EVAL(let_binds[i+1], env))
84 elseif first_symbol == "quote"
85 return ListNth(ast, 1)
86 elseif first_symbol == "quasiquote"
87 let ast = Quasiquote(ListNth(ast, 1))
89 elseif first_symbol == "if"
90 let condvalue = EVAL(ast.val[1], env)
91 if FalseQ(condvalue) || NilQ(condvalue)
101 elseif first_symbol == "do"
102 let astlist = ast.val
103 call EvalAst(ListNew(astlist[1:-2]), env)
104 let ast = astlist[-1]
106 elseif first_symbol == "fn*"
107 let fn = NewFn(ListNth(ast, 2), env, ListNth(ast, 1))
109 elseif first_symbol == "eval"
110 let ast = EVAL(ListNth(ast, 1), env)
115 let el = EvalAst(ast, env)
116 let funcobj = ListFirst(el)
117 let args = ListRest(el)
118 if NativeFunctionQ(funcobj)
119 return NativeFuncInvoke(funcobj, args)
120 elseif FunctionQ(funcobj)
123 let env = NewEnvWithBinds(fn.env, fn.params, args)
126 throw "Not a function"
133 return PrStr(a:exp, 1)
136 function RE(str, env)
137 return EVAL(READ(a:str), a:env)
140 function REP(str, env)
141 return PRINT(EVAL(READ(a:str), a:env))
144 function GetArgvList()
145 return ListNew(map(copy(argv()[1:]), {_, arg -> StringNew(arg)}))
148 set maxfuncdepth=10000
149 let repl_env = NewEnv("")
151 for [k, v] in items(CoreNs)
152 call repl_env.set(k, v)
155 call repl_env.set("*ARGV*", GetArgvList())
157 call RE("(def! not (fn* (a) (if a false true)))", repl_env)
158 call RE("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))", repl_env)
161 call RE('(load-file "' . argv(0) . '")', repl_env)
166 let [eof, line] = Readline("user> ")
174 call PrintLn(REP(line, repl_env))
176 call PrintLn("Error: " . v:exception)