diff options
| author | def <dennis@felsin9.de> | 2015-03-04 14:12:19 +0100 |
|---|---|---|
| committer | def <dennis@felsin9.de> | 2015-03-04 15:43:18 +0100 |
| commit | 2800f318812a1598fcbc918a361ce1f6f24be9f0 (patch) | |
| tree | 8d8659bb36e672e37c0cf84832d895c37380fc06 | |
| parent | 2c47ac541ec6f2c959a0f0ff4f0f654400efd2fd (diff) | |
| download | mal-2800f318812a1598fcbc918a361ce1f6f24be9f0.tar.gz mal-2800f318812a1598fcbc918a361ce1f6f24be9f0.zip | |
Fix and clean up Nim implementation
| -rw-r--r-- | nim/Makefile | 2 | ||||
| -rw-r--r-- | nim/core.nim | 31 | ||||
| -rw-r--r-- | nim/nim.cfg | 2 | ||||
| -rw-r--r-- | nim/printer.nim | 2 | ||||
| -rw-r--r-- | nim/reader.nim | 2 | ||||
| -rw-r--r-- | nim/step5_tco.nim | 12 | ||||
| -rw-r--r-- | nim/step6_file.nim | 12 | ||||
| -rw-r--r-- | nim/step7_quote.nim | 12 | ||||
| -rw-r--r-- | nim/step8_macros.nim | 14 | ||||
| -rw-r--r-- | nim/step9_try.nim | 2 | ||||
| -rw-r--r-- | nim/stepA_mal.nim | 3 | ||||
| -rw-r--r-- | nim/types.nim | 34 |
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) |
