aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordef <dennis@felsin9.de>2015-02-28 15:20:37 +0100
committerdef <dennis@felsin9.de>2015-02-28 15:20:37 +0100
commitc9d2371f7f0a97efe464565fdf8ebc8405eb8780 (patch)
tree91144af084a6ac113b1461439de2c9eba07b8938
parentb94acce656db4f0b129cd939765c0ca451f6a538 (diff)
downloadmal-c9d2371f7f0a97efe464565fdf8ebc8405eb8780.tar.gz
mal-c9d2371f7f0a97efe464565fdf8ebc8405eb8780.zip
Nim: step2
-rw-r--r--nim/Makefile2
-rw-r--r--nim/printer.nim1
-rw-r--r--nim/step2_eval.nim52
-rw-r--r--nim/types.nim5
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)