Merge pull request #380 from bjh21/bjh21-bbc-basic
[jackhill/mal.git] / io / step3_env.io
1 MalTypes
2 MalReader
3
4 READ := method(str, MalReader read_str(str))
5
6 eval_ast := method(ast, env,
7 (ast type) switch(
8 "MalSymbol", env get(ast),
9 "MalList", MalList with(ast map(a, EVAL(a, env))),
10 "MalVector", MalVector with(ast map(a, EVAL(a, env))),
11 "MalMap",
12 m := MalMap clone
13 ast foreach(k, v,
14 keyObj := MalMap keyToObj(k)
15 m atPut(MalMap objToKey(EVAL(keyObj, env)), EVAL(v, env))
16 )
17 m,
18 ast
19 )
20 )
21
22 EVAL := method(ast, env,
23 if(ast type != "MalList", return(eval_ast(ast, env)))
24 if(ast isEmpty, return ast)
25 if(ast at(0) type == "MalSymbol",
26 ast at(0) val switch(
27 "def!",
28 return(env set(ast at(1), EVAL(ast at(2), env))),
29 "let*",
30 letEnv := Env with(env)
31 varName := nil
32 ast at(1) foreach(i, e,
33 if(i % 2 == 0,
34 varName := e,
35 letEnv set(varName, EVAL(e, letEnv))
36 )
37 )
38 return(EVAL(ast at(2), letEnv))
39 )
40 )
41
42 // Apply
43 el := eval_ast(ast, env)
44 f := el at(0)
45 args := el rest
46 f callWithArgList(args)
47 )
48
49 PRINT := method(exp, exp malPrint(true))
50
51 repl_env := Env with(nil)
52 repl_env set(MalSymbol with("+"), block(a, b, a + b))
53 repl_env set(MalSymbol with("-"), block(a, b, a - b))
54 repl_env set(MalSymbol with("*"), block(a, b, a * b))
55 repl_env set(MalSymbol with("/"), block(a, b, a / b))
56
57 RE := method(str, EVAL(READ(str), repl_env))
58
59 REP := method(str, PRINT(RE(str)))
60
61 loop(
62 line := MalReadline readLine("user> ")
63 if(line isNil, break)
64 if(line isEmpty, continue)
65 e := try(REP(line) println)
66 e catch(Exception,
67 ("Error: " .. (e error)) println
68 )
69 )