aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2015-03-04 08:48:52 -0600
committerJoel Martin <github@martintribe.org>2015-03-04 08:48:52 -0600
commitc67c27e6c295200accf3c95c33e9ca5821268e74 (patch)
tree8d8659bb36e672e37c0cf84832d895c37380fc06
parent2c47ac541ec6f2c959a0f0ff4f0f654400efd2fd (diff)
parent2800f318812a1598fcbc918a361ce1f6f24be9f0 (diff)
downloadmal-c67c27e6c295200accf3c95c33e9ca5821268e74.tar.gz
mal-c67c27e6c295200accf3c95c33e9ca5821268e74.zip
Merge pull request #21 from def-/master
Fix and clean up Nim implementation
-rw-r--r--nim/Makefile2
-rw-r--r--nim/core.nim31
-rw-r--r--nim/nim.cfg2
-rw-r--r--nim/printer.nim2
-rw-r--r--nim/reader.nim2
-rw-r--r--nim/step5_tco.nim12
-rw-r--r--nim/step6_file.nim12
-rw-r--r--nim/step7_quote.nim12
-rw-r--r--nim/step8_macros.nim14
-rw-r--r--nim/step9_try.nim2
-rw-r--r--nim/stepA_mal.nim3
-rw-r--r--nim/types.nim34
12 files changed, 66 insertions, 62 deletions
diff --git a/nim/Makefile b/nim/Makefile
index 4b8707d..e8c450e 100644
--- a/nim/Makefile
+++ b/nim/Makefile
@@ -18,7 +18,7 @@ all: $(BINS) mal
mal: $(word $(words $(BINS)),$(BINS))
cp $< $@
-$(BINS):
+$(BINS): %: %.nim
nim -d:release c $@
clean:
diff --git a/nim/core.nim b/nim/core.nim
index 5fc9e63..e5ca517 100644
--- a/nim/core.nim
+++ b/nim/core.nim
@@ -57,21 +57,22 @@ proc throw(xs: varargs[MalType]): MalType =
proc assoc(xs: varargs[MalType]): MalType =
result = hash_map()
- result.hash_map[] = xs[0].hash_map[]
+ result.hash_map = xs[0].hash_map
for i in countup(1, xs.high, 2):
result.hash_map[xs[i].str] = xs[i+1]
proc dissoc(xs: varargs[MalType]): MalType =
result = hash_map()
- result.hash_map[] = xs[0].hash_map[]
+ result.hash_map = xs[0].hash_map
for i in 1 .. xs.high:
if result.hash_map.hasKey(xs[i].str): result.hash_map.del(xs[i].str)
proc get(xs: varargs[MalType]): MalType =
if xs[0].kind == HashMap:
- xs[0].hash_map[xs[1].str]
- else:
- nilObj
+ result = xs[0].hash_map[xs[1].str]
+ if not result.isNil: return
+
+ result = nilObj
proc contains_q(xs: varargs[MalType]): MalType =
boolObj xs[0].hash_map.hasKey(xs[1].str)
@@ -113,27 +114,27 @@ proc map(xs: varargs[MalType]): MalType =
result.list.add xs[0].getFun()(xs[1].list[i])
proc with_meta(xs: varargs[MalType]): MalType =
- result = xs[0]
- new result.meta
- result.meta[] = xs[1]
+ new result
+ result[] = xs[0][]
+ result.meta = xs[1]
proc meta(xs: varargs[MalType]): MalType =
- if xs[0].meta != nil: xs[0].meta[]
+ if not xs[0].meta.isNil: xs[0].meta
else: nilObj
proc deref(xs: varargs[MalType]): MalType =
- xs[0].val[]
+ xs[0].val
proc reset_bang(xs: varargs[MalType]): MalType =
- xs[0].val[] = xs[1]
- result = xs[0].val[]
+ xs[0].val = xs[1]
+ result = xs[0].val
proc swap_bang(xs: varargs[MalType]): MalType =
- var args = @[xs[0].val[]]
+ var args = @[xs[0].val]
for i in 2 .. xs.high:
args.add xs[i]
- xs[0].val[] = xs[1].getFun()(args)
- result = xs[0].val[]
+ xs[0].val = xs[1].getFun()(args)
+ result = xs[0].val
proc time_ms(xs: varargs[MalType]): MalType =
number int(epochTime() * 1000)
diff --git a/nim/nim.cfg b/nim/nim.cfg
index 55df3f9..dbf197a 100644
--- a/nim/nim.cfg
+++ b/nim/nim.cfg
@@ -1,2 +1,2 @@
-d: pcreDynlib
deadCodeElim: off
+gc: markandsweep
diff --git a/nim/printer.nim b/nim/printer.nim
index 95eb840..912b8a9 100644
--- a/nim/printer.nim
+++ b/nim/printer.nim
@@ -13,7 +13,7 @@ proc pr_str*(m: MalType, pr = true): string =
of False: result = "false"
of Fun: result = "#<function>"
of MalFun: result = "#<malfun>"
- of Atom: result = "(atom " & m.val[].pr_str & ")"
+ of Atom: result = "(atom " & m.val.pr_str & ")"
of Symbol: result = m.str
of String: result = m.str.str_handle(pr)
of Number: result = $m.number
diff --git a/nim/reader.nim b/nim/reader.nim
index 856a6a6..10fce10 100644
--- a/nim/reader.nim
+++ b/nim/reader.nim
@@ -1,6 +1,6 @@
import nre, optional_t, strutils, types
-var
+let
tokenRE = re"""[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)"""
intRE = re"-?[0-9]+$"
diff --git a/nim/step5_tco.nim b/nim/step5_tco.nim
index a03dbd1..bbbb160 100644
--- a/nim/step5_tco.nim
+++ b/nim/step5_tco.nim
@@ -20,20 +20,20 @@ proc eval_ast(ast: MalType, env: var Env): MalType =
result = ast
proc eval(ast: MalType, env: var Env): MalType =
+ var ast = ast
+
template defaultApply =
let el = ast.eval_ast(env)
let f = el.list[0]
case f.kind
of MalFun:
ast = f.malfun.ast
- env = initEnv(env, f.malfun.params, list(el.list[1 .. -1]))
+ env = initEnv(f.malfun.env, f.malfun.params, list(el.list[1 .. -1]))
else:
return f.fun(el.list[1 .. -1])
- var ast = ast
while true:
- if ast.kind != List:
- return ast.eval_ast(env)
+ if ast.kind != List: return ast.eval_ast(env)
let a0 = ast.list[0]
case a0.kind
@@ -62,7 +62,7 @@ proc eval(ast: MalType, env: var Env): MalType =
of "do":
let last = ast.list.high
let el = (list ast.list[1 .. <last]).eval_ast(env)
- ast = ast.list[last].eval(env)
+ ast = ast.list[last]
# Continue loop (TCO)
of "if":
@@ -84,7 +84,7 @@ proc eval(ast: MalType, env: var Env): MalType =
let fn = proc(a: varargs[MalType]): MalType =
var newEnv = initEnv(env2, a1, list(a))
a2.eval(newEnv)
- return malfun(fn, a2, a1, env2)
+ return malfun(fn, a2, a1, env)
else:
defaultApply()
diff --git a/nim/step6_file.nim b/nim/step6_file.nim
index 6f0e02a..a0a569e 100644
--- a/nim/step6_file.nim
+++ b/nim/step6_file.nim
@@ -20,20 +20,20 @@ proc eval_ast(ast: MalType, env: var Env): MalType =
result = ast
proc eval(ast: MalType, env: var Env): MalType =
+ var ast = ast
+
template defaultApply =
let el = ast.eval_ast(env)
let f = el.list[0]
case f.kind
of MalFun:
ast = f.malfun.ast
- env = initEnv(env, f.malfun.params, list(el.list[1 .. -1]))
+ env = initEnv(f.malfun.env, f.malfun.params, list(el.list[1 .. -1]))
else:
return f.fun(el.list[1 .. -1])
- var ast = ast
while true:
- if ast.kind != List:
- return ast.eval_ast(env)
+ if ast.kind != List: return ast.eval_ast(env)
let a0 = ast.list[0]
case a0.kind
@@ -62,7 +62,7 @@ proc eval(ast: MalType, env: var Env): MalType =
of "do":
let last = ast.list.high
let el = (list ast.list[1 .. <last]).eval_ast(env)
- ast = ast.list[last].eval(env)
+ ast = ast.list[last]
# Continue loop (TCO)
of "if":
@@ -84,7 +84,7 @@ proc eval(ast: MalType, env: var Env): MalType =
let fn = proc(a: varargs[MalType]): MalType =
var newEnv = initEnv(env2, a1, list(a))
a2.eval(newEnv)
- return malfun(fn, a2, a1, env2)
+ return malfun(fn, a2, a1, env)
else:
defaultApply()
diff --git a/nim/step7_quote.nim b/nim/step7_quote.nim
index 58fc3b6..848913d 100644
--- a/nim/step7_quote.nim
+++ b/nim/step7_quote.nim
@@ -34,20 +34,20 @@ proc eval_ast(ast: MalType, env: var Env): MalType =
result = ast
proc eval(ast: MalType, env: var Env): MalType =
+ var ast = ast
+
template defaultApply =
let el = ast.eval_ast(env)
let f = el.list[0]
case f.kind
of MalFun:
ast = f.malfun.ast
- env = initEnv(env, f.malfun.params, list(el.list[1 .. -1]))
+ env = initEnv(f.malfun.env, f.malfun.params, list(el.list[1 .. -1]))
else:
return f.fun(el.list[1 .. -1])
- var ast = ast
while true:
- if ast.kind != List:
- return ast.eval_ast(env)
+ if ast.kind != List: return ast.eval_ast(env)
let a0 = ast.list[0]
case a0.kind
@@ -83,7 +83,7 @@ proc eval(ast: MalType, env: var Env): MalType =
of "do":
let last = ast.list.high
let el = (list ast.list[1 .. <last]).eval_ast(env)
- ast = ast.list[last].eval(env)
+ ast = ast.list[last]
# Continue loop (TCO)
of "if":
@@ -105,7 +105,7 @@ proc eval(ast: MalType, env: var Env): MalType =
let fn = proc(a: varargs[MalType]): MalType =
var newEnv = initEnv(env2, a1, list(a))
a2.eval(newEnv)
- return malfun(fn, a2, a1, env2)
+ return malfun(fn, a2, a1, env)
else:
defaultApply()
diff --git a/nim/step8_macros.nim b/nim/step8_macros.nim
index 43c1cb4..96981a7 100644
--- a/nim/step8_macros.nim
+++ b/nim/step8_macros.nim
@@ -26,7 +26,7 @@ proc macroexpand(ast: MalType, env: Env): MalType =
let mac = env.get(result.list[0].str)
result = mac.malfun.fn(result.list[1 .. -1]).macroexpand(env)
-proc eval(ast: MalType, env: var Env): MalType
+proc eval(ast: MalType, env: Env): MalType
proc eval_ast(ast: MalType, env: var Env): MalType =
case ast.kind
@@ -43,18 +43,20 @@ proc eval_ast(ast: MalType, env: var Env): MalType =
else:
result = ast
-proc eval(ast: MalType, env: var Env): MalType =
+proc eval(ast: MalType, env: Env): MalType =
+ var ast = ast
+ var env = env
+
template defaultApply =
let el = ast.eval_ast(env)
let f = el.list[0]
case f.kind
of MalFun:
ast = f.malfun.ast
- env = initEnv(env, f.malfun.params, list(el.list[1 .. -1]))
+ env = initEnv(f.malfun.env, f.malfun.params, list(el.list[1 .. -1]))
else:
return f.fun(el.list[1 .. -1])
- var ast = ast
while true:
if ast.kind != List: return ast.eval_ast(env)
@@ -104,7 +106,7 @@ proc eval(ast: MalType, env: var Env): MalType =
of "do":
let last = ast.list.high
let el = (list ast.list[1 .. <last]).eval_ast(env)
- ast = ast.list[last].eval(env)
+ ast = ast.list[last]
# Continue loop (TCO)
of "if":
@@ -126,7 +128,7 @@ proc eval(ast: MalType, env: var Env): MalType =
let fn = proc(a: varargs[MalType]): MalType =
var newEnv = initEnv(env2, a1, list(a))
a2.eval(newEnv)
- return malfun(fn, a2, a1, env2)
+ return malfun(fn, a2, a1, env)
else:
defaultApply()
diff --git a/nim/step9_try.nim b/nim/step9_try.nim
index 688817d..6d77ac7 100644
--- a/nim/step9_try.nim
+++ b/nim/step9_try.nim
@@ -125,7 +125,7 @@ proc eval(ast: MalType, env: Env): MalType =
of "do":
let last = ast.list.high
let el = (list ast.list[1 .. <last]).eval_ast(env)
- ast = ast.list[last].eval(env)
+ ast = ast.list[last]
# Continue loop (TCO)
of "if":
diff --git a/nim/stepA_mal.nim b/nim/stepA_mal.nim
index 48dd9dd..b138bd9 100644
--- a/nim/stepA_mal.nim
+++ b/nim/stepA_mal.nim
@@ -175,11 +175,12 @@ rep "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (
rep "(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))"
rep "(def! *host-language* \"nim\")"
-rep "(println (str \"Mal [\" *host-language* \"]\"))"
if paramCount() >= 1:
rep "(load-file \"" & paramStr(1) & "\")"
quit()
+rep "(println (str \"Mal [\" *host-language* \"]\"))"
+
while true:
try:
let line = readLineFromStdin("user> ")
diff --git a/nim/types.nim b/nim/types.nim
index b5e1bec..56983ff 100644
--- a/nim/types.nim
+++ b/nim/types.nim
@@ -13,28 +13,28 @@ type
env*: Env
is_macro*: bool
- MalType* = object
+ MalType* = ref object
case kind*: MalTypeKind
of Nil, True, False: nil
of Number: number*: int
of String, Symbol: str*: string
of List, Vector: list*: seq[MalType]
- of HashMap: hash_map*: TableRef[string, MalType]
+ of HashMap: hash_map*: Table[string, MalType]
of Fun:
fun*: FunType
is_macro*: bool
of MalFun: malfun*: MalFunType
- of Atom: val*: ref MalType
+ of Atom: val*: MalType
- meta*: ref MalType
+ meta*: MalType
Env* = ref object
data*: Table[string, MalType]
outer*: Env
-const nilObj* = MalType(kind: Nil)
-const trueObj* = MalType(kind: True)
-const falseObj* = MalType(kind: False)
+let nilObj* = MalType(kind: Nil)
+let trueObj* = MalType(kind: True)
+let falseObj* = MalType(kind: False)
proc number*(x: int): MalType = MalType(kind: Number, number: x)
@@ -46,19 +46,18 @@ proc keyword*(x: string): MalType = MalType(kind: String, str: "\xff" & x)
proc atom*(x: MalType): MalType =
result = MalType(kind: Atom)
- new result.val
- result.val[] = x
+ result.val = x
proc list*(xs: varargs[MalType]): MalType {.procvar.} =
- result = MalType(kind: List, list: @[])
- for x in xs: result.list.add x
+ result = MalType(kind: List, list: newSeq[MalType](xs.len))
+ for i, x in xs: result.list[i] = x
proc vector*(xs: varargs[MalType]): MalType {.procvar.} =
- result = MalType(kind: Vector, list: @[])
- for x in xs: result.list.add x
+ result = MalType(kind: Vector, list: newSeq[MalType](xs.len))
+ for i, x in xs: result.list[i] = x
proc hash_map*(xs: varargs[MalType]): MalType {.procvar.} =
- result = MalType(kind: HashMap, hash_map: newTable[string, MalType]())
+ result = MalType(kind: HashMap, hash_map: initTable[string, MalType]())
for i in countup(0, xs.high, 2):
let s = case xs[i].kind
of String: xs[i].str
@@ -66,13 +65,14 @@ proc hash_map*(xs: varargs[MalType]): MalType {.procvar.} =
result.hash_map[s] = xs[i+1]
proc macro_q*(x: MalType): bool =
- if x.kind == Fun: x.is_macro
- else: x.malfun.is_macro
+ if x.kind == Fun: result = x.is_macro
+ elif x.kind == MalFun: result = x.malfun.is_macro
+ else: raise newException(ValueError, "no function")
proc getFun*(x: MalType): FunType =
if x.kind == Fun: result = x.fun
elif x.kind == MalFun: result = x.malfun.fn
- else: echo x.kind
+ else: raise newException(ValueError, "no function")
proc fun*(x: proc(xs: varargs[MalType]): MalType, is_macro = false): MalType =
MalType(kind: Fun, fun: x, is_macro: is_macro)