diff options
Diffstat (limited to 'nim/step2_eval.nim')
| -rw-r--r-- | nim/step2_eval.nim | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/nim/step2_eval.nim b/nim/step2_eval.nim new file mode 100644 index 0000000..075b4ac --- /dev/null +++ b/nim/step2_eval.nim @@ -0,0 +1,52 @@ +import rdstdin, tables, sequtils, types, reader, printer + +proc read(str: string): MalType = str.read_str + +proc eval(ast: MalType, env: Table[string, MalType]): MalType + +proc eval_ast(ast: MalType, env: Table[string, MalType]): MalType = + case ast.kind + of Symbol: + if not env.hasKey(ast.str): + raise newException(ValueError, "'" & ast.str & "' not found") + result = env[ast.str] + of List: + result = list ast.list.mapIt(MalType, it.eval(env)) + of Vector: + result = vector ast.list.mapIt(MalType, it.eval(env)) + of HashMap: + result = hash_map() + for k, v in ast.hash_map.pairs: + result.hash_map[k] = v.eval(env) + else: + result = ast + +proc eval(ast: MalType, env: Table[string, MalType]): MalType = + case ast.kind + of List: + let el = ast.eval_ast(env) + el.list[0].fun(el.list[1 .. -1]) + else: + ast.eval_ast(env) + +proc print(exp: MalType): string = exp.pr_str + +template wrapNumberFun(op: expr): expr = + fun proc(xs: varargs[MalType]): MalType = number op(xs[0].number, xs[1].number) + +let repl_env = toTable({ + "+": wrapNumberFun `+`, + "-": wrapNumberFun `-`, + "*": wrapNumberFun `*`, + "/": wrapNumberFun `div`, +}) + +proc rep(str: string): string = + str.read.eval(repl_env).print + +while true: + try: + let line = readLineFromStdin("user> ") + echo line.rep + except: + echo getCurrentExceptionMsg() |
