7af2994e |
1 | import rdstdin, tables, sequtils, types, reader, printer, env |
2 | |
3 | proc read(str: string): MalType = str.read_str |
4 | |
5 | proc eval(ast: MalType, env: var Env): MalType |
6 | |
7 | proc eval_ast(ast: MalType, env: var Env): MalType = |
8 | case ast.kind |
9 | of Symbol: |
10 | result = env.get(ast.symbol) |
11 | of List: |
12 | result = list ast.list.mapIt(MalType, it.eval(env)) |
13 | of Vector: |
819bd786 |
14 | result = vector ast.list.mapIt(MalType, it.eval(env)) |
7af2994e |
15 | of HashMap: |
16 | result = hash_map() |
17 | for k, v in ast.hash_map.pairs: |
18 | result.hash_map[k] = v.eval(env) |
19 | else: |
20 | result = ast |
21 | |
22 | proc eval(ast: MalType, env: var Env): MalType = |
23 | case ast.kind |
24 | of List: |
25 | let |
26 | a0 = ast.list[0] |
27 | a1 = ast.list[1] |
28 | a2 = ast.list[2] |
29 | |
30 | case a0.symbol |
31 | of "def!": |
32 | result = env.set(a1.symbol, a2.eval(env)) |
33 | of "let*": |
34 | var letEnv: Env |
35 | letEnv.deepCopy(env) |
36 | case a1.kind |
819bd786 |
37 | of List, Vector: |
7af2994e |
38 | for i in countup(0, a1.list.high, 2): |
39 | letEnv.set(a1.list[i].symbol, a1.list[i+1].eval(letEnv)) |
7af2994e |
40 | else: discard |
41 | result = a2.eval(letEnv) |
42 | else: |
43 | let el = ast.eval_ast(env) |
44 | result = el.list[0].fun(el.list[1 .. -1]) |
45 | else: |
46 | result = ast.eval_ast(env) |
47 | |
48 | proc print(exp: MalType): string = exp.pr_str |
49 | |
50 | template wrapNumberFun(op: expr): expr = |
51 | fun proc(xs: varargs[MalType]): MalType = number op(xs[0].number, xs[1].number) |
52 | |
53 | var repl_env = initEnv() |
54 | |
55 | repl_env.set("+", wrapNumberFun(`+`)) |
56 | repl_env.set("-", wrapNumberFun(`-`)) |
57 | repl_env.set("*", wrapNumberFun(`*`)) |
58 | repl_env.set("/", wrapNumberFun(`div`)) |
59 | #repl_env.set("/", wrapNumberFun(proc(x,y: int): int = int(x.float / y.float))) |
60 | |
61 | proc rep(str: string): string = |
62 | str.read.eval(repl_env).print |
63 | |
64 | while true: |
65 | try: |
66 | let line = readLineFromStdin("user> ") |
67 | echo line.rep |
68 | except: |
69 | echo getCurrentExceptionMsg() |
70 | echo getCurrentException().getStackTrace() |