diff options
| author | def <dennis@felsin9.de> | 2015-02-28 15:20:37 +0100 |
|---|---|---|
| committer | def <dennis@felsin9.de> | 2015-02-28 15:20:37 +0100 |
| commit | c9d2371f7f0a97efe464565fdf8ebc8405eb8780 (patch) | |
| tree | 91144af084a6ac113b1461439de2c9eba07b8938 | |
| parent | b94acce656db4f0b129cd939765c0ca451f6a538 (diff) | |
| download | mal-c9d2371f7f0a97efe464565fdf8ebc8405eb8780.tar.gz mal-c9d2371f7f0a97efe464565fdf8ebc8405eb8780.zip | |
Nim: step2
| -rw-r--r-- | nim/Makefile | 2 | ||||
| -rw-r--r-- | nim/printer.nim | 1 | ||||
| -rw-r--r-- | nim/step2_eval.nim | 52 | ||||
| -rw-r--r-- | nim/types.nim | 5 |
4 files changed, 58 insertions, 2 deletions
diff --git a/nim/Makefile b/nim/Makefile index 5fba42c..8f85496 100644 --- a/nim/Makefile +++ b/nim/Makefile @@ -6,7 +6,7 @@ SOURCES = $(SOURCES_BASE) $(SOURCES_LISP) ##################### -SRCS = step0_repl.nim step1_read_print.nim +SRCS = step0_repl.nim step1_read_print.nim step2_eval.nim BINS = $(SRCS:%.nim=%) ##################### diff --git a/nim/printer.nim b/nim/printer.nim index 45c21f1..e3d3aab 100644 --- a/nim/printer.nim +++ b/nim/printer.nim @@ -3,6 +3,7 @@ import strutils, tables, types proc pr_str*(m: MalType): string = case m.kind of Nil: result = "nil" + of Fun: result = "fun" of Symbol: result = m.symbol of Number: result = $m.number of List: result = "(" & m.list.map(pr_str).join(" ") & ")" diff --git a/nim/step2_eval.nim b/nim/step2_eval.nim new file mode 100644 index 0000000..7418335 --- /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.symbol): + raise newException(ValueError, "'" & ast.symbol & "' not found") + result = env[ast.symbol] + of List: + result = list ast.list.mapIt(MalType, it.eval(env)) + of Vector: + result = vector ast.vector.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() diff --git a/nim/types.nim b/nim/types.nim index 866d6db..dfab369 100644 --- a/nim/types.nim +++ b/nim/types.nim @@ -1,7 +1,7 @@ import tables type - MalTypeKind* = enum Nil, Number, Symbol, List, Vector, HashMap + MalTypeKind* = enum Nil, Number, Symbol, List, Vector, HashMap, Fun MalType* = object case kind*: MalTypeKind @@ -11,6 +11,7 @@ type of List: list*: seq[MalType] of Vector: vector*: seq[MalType] of HashMap: hash_map*: TableRef[string, MalType] + of Fun: fun*: proc(xs: varargs[MalType]): MalType # Convenience procs const nilObj*: MalType = MalType(kind: Nil) @@ -31,3 +32,5 @@ proc hash_map*(xs: varargs[MalType]): MalType = result = MalType(kind: HashMap, hash_map: newTable[string, MalType]()) for i in countup(0, xs.high, 2): result.hash_map[xs[i].symbol] = xs[i+1] + +proc fun*(x: proc(xs: varargs[MalType]): MalType): MalType = MalType(kind: Fun, fun: x) |
