Merge pull request #494 from alimpfard/master
[jackhill/mal.git] / skew / step2_eval.sk
CommitLineData
034e82ad
DM
1def READ(str string) MalVal {
2 return read_str(str)
3}
4
5def eval_ast(ast MalVal, env StringMap<MalVal>) MalVal {
6 if ast is MalSymbol {
7 const name = (ast as MalSymbol).val
8 if !(name in env) {
9 throw MalError.new("'" + name + "' not found")
10 }
11 return env[name]
12 } else if ast is MalList {
13 return MalList.new((ast as MalList).val.map<MalVal>(e => EVAL(e, env)))
14 } else if ast is MalVector {
15 return MalVector.new((ast as MalVector).val.map<MalVal>(e => EVAL(e, env)))
16 } else if ast is MalHashMap {
17 var result List<MalVal> = []
18 (ast as MalHashMap).val.each((k string, v MalVal) => {
19 result.append(EVAL(MalVal.fromHashKey(k), env))
20 result.append(EVAL(v, env))
21 })
22 return MalHashMap.fromList(result)
23 } else {
24 return ast
25 }
26}
27
28def EVAL(ast MalVal, env StringMap<MalVal>) MalVal {
29 if !(ast is MalList) { return eval_ast(ast, env) }
30 var astList = ast as MalList
31 if astList.isEmpty { return ast }
32 var evaledList = eval_ast(ast, env) as MalList
33 var fn = evaledList[0] as MalNativeFunc
34 return fn.call(evaledList.val.slice(1))
35}
36
37def PRINT(exp MalVal) string {
38 return exp?.print(true)
39}
40
41var repl_env StringMap<MalVal> = {
42 "+": MalNativeFunc.new((args List<MalVal>) MalVal => MalNumber.new((args[0] as MalNumber).val + (args[1] as MalNumber).val)),
43 "-": MalNativeFunc.new((args List<MalVal>) MalVal => MalNumber.new((args[0] as MalNumber).val - (args[1] as MalNumber).val)),
44 "*": MalNativeFunc.new((args List<MalVal>) MalVal => MalNumber.new((args[0] as MalNumber).val * (args[1] as MalNumber).val)),
45 "/": MalNativeFunc.new((args List<MalVal>) MalVal => MalNumber.new((args[0] as MalNumber).val / (args[1] as MalNumber).val)),
46}
47
48def REP(str string) string {
49 return PRINT(EVAL(READ(str), repl_env))
50}
51
52@entry
53def main {
54 var line string
55 while (line = readLine("user> ")) != null {
56 if line == "" { continue }
57 try {
58 printLn(REP(line))
59 }
60 catch e MalError {
61 printLn("Error: \(e.message)")
62 }
63 }
64}