diff --git a/impls/ada.2/Dockerfile b/impls/ada.2/Dockerfile index 8b6e8c793a..54cfbefb8a 100644 --- a/impls/ada.2/Dockerfile +++ b/impls/ada.2/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:24.04 MAINTAINER Joel Martin ########################################################## diff --git a/impls/ada.2/envs.ads b/impls/ada.2/envs.ads index e9870e2eb0..aeeaa149eb 100644 --- a/impls/ada.2/envs.ads +++ b/impls/ada.2/envs.ads @@ -14,8 +14,6 @@ package Envs is subtype Ptr is not null Link; function New_Env (Outer : in Link := null) return Ptr with Inline; - -- Set_Binds is provided as distinct subprograms because we some - -- time spare the creation of a subenvironment. procedure Set_Binds (Env : in out Instance; Binds : in Types.T_Array; diff --git a/impls/ada.2/run b/impls/ada.2/run index 8ba68a5484..6efdc3de32 100755 --- a/impls/ada.2/run +++ b/impls/ada.2/run @@ -1,2 +1,2 @@ -#!/bin/bash +#!/bin/sh exec $(dirname $0)/${STEP:-stepA_mal} "${@}" diff --git a/impls/ada.2/step5_tco.adb b/impls/ada.2/step5_tco.adb index 18754079b8..52fc19f679 100644 --- a/impls/ada.2/step5_tco.adb +++ b/impls/ada.2/step5_tco.adb @@ -48,10 +48,6 @@ procedure Step5_Tco is -- optimization goes to <>. Ast : Types.T := Ast0; Env : Envs.Ptr := Env0; - Env_Reusable : Boolean := False; - -- True when the environment has been created in this recursion - -- level, and has not yet been referenced by a closure. If so, - -- we can reuse it instead of creating a subenvironment. First : Types.T; begin <> @@ -106,10 +102,7 @@ procedure Step5_Tco is renames Ast.Sequence.all.Data (2).Sequence.all.Data; begin Err.Check (Bindings'Length mod 2 = 0, "expected even binds"); - if not Env_Reusable then - Env := Envs.New_Env (Outer => Env); - Env_Reusable := True; - end if; + Env := Envs.New_Env (Outer => Env); for I in 0 .. Bindings'Length / 2 - 1 loop Env.all.Set (Bindings (Bindings'First + 2 * I), Eval (Bindings (Bindings'First + 2 * I + 1), Env)); @@ -146,7 +139,6 @@ procedure Step5_Tco is begin Err.Check (Params.Kind in Types.Kind_Sequence, "first argument of fn* must be a sequence"); - Env_Reusable := False; return (Kind_Fn, Types.Fns.New_Function (Params => Params.Sequence, Ast => Ast.Sequence.all.Data (3), @@ -185,7 +177,6 @@ procedure Step5_Tco is end if; -- Like Types.Fns.Apply, except that we use TCO. Env := Envs.New_Env (Outer => First.Fn.all.Env); - Env_Reusable := True; Env.all.Set_Binds (Binds => First.Fn.all.Params.all.Data, Exprs => Args); Ast := First.Fn.all.Ast; diff --git a/impls/ada.2/step6_file.adb b/impls/ada.2/step6_file.adb index 45cce5d679..6fb5ef355e 100644 --- a/impls/ada.2/step6_file.adb +++ b/impls/ada.2/step6_file.adb @@ -52,10 +52,6 @@ procedure Step6_File is -- optimization goes to <>. Ast : Types.T := Ast0; Env : Envs.Ptr := Env0; - Env_Reusable : Boolean := False; - -- True when the environment has been created in this recursion - -- level, and has not yet been referenced by a closure. If so, - -- we can reuse it instead of creating a subenvironment. First : Types.T; begin <> @@ -110,10 +106,7 @@ procedure Step6_File is renames Ast.Sequence.all.Data (2).Sequence.all.Data; begin Err.Check (Bindings'Length mod 2 = 0, "expected even binds"); - if not Env_Reusable then - Env := Envs.New_Env (Outer => Env); - Env_Reusable := True; - end if; + Env := Envs.New_Env (Outer => Env); for I in 0 .. Bindings'Length / 2 - 1 loop Env.all.Set (Bindings (Bindings'First + 2 * I), Eval (Bindings (Bindings'First + 2 * I + 1), Env)); @@ -150,7 +143,6 @@ procedure Step6_File is begin Err.Check (Params.Kind in Types.Kind_Sequence, "first argument of fn* must be a sequence"); - Env_Reusable := False; return (Kind_Fn, Types.Fns.New_Function (Params => Params.Sequence, Ast => Ast.Sequence.all.Data (3), @@ -189,7 +181,6 @@ procedure Step6_File is end if; -- Like Types.Fns.Apply, except that we use TCO. Env := Envs.New_Env (Outer => First.Fn.all.Env); - Env_Reusable := True; Env.all.Set_Binds (Binds => First.Fn.all.Params.all.Data, Exprs => Args); Ast := First.Fn.all.Ast; diff --git a/impls/ada.2/step7_quote.adb b/impls/ada.2/step7_quote.adb index dc134f13fc..10941a059a 100644 --- a/impls/ada.2/step7_quote.adb +++ b/impls/ada.2/step7_quote.adb @@ -54,10 +54,6 @@ procedure Step7_Quote is -- optimization goes to <>. Ast : Types.T := Ast0; Env : Envs.Ptr := Env0; - Env_Reusable : Boolean := False; - -- True when the environment has been created in this recursion - -- level, and has not yet been referenced by a closure. If so, - -- we can reuse it instead of creating a subenvironment. First : Types.T; begin <> @@ -112,10 +108,7 @@ procedure Step7_Quote is renames Ast.Sequence.all.Data (2).Sequence.all.Data; begin Err.Check (Bindings'Length mod 2 = 0, "expected even binds"); - if not Env_Reusable then - Env := Envs.New_Env (Outer => Env); - Env_Reusable := True; - end if; + Env := Envs.New_Env (Outer => Env); for I in 0 .. Bindings'Length / 2 - 1 loop Env.all.Set (Bindings (Bindings'First + 2 * I), Eval (Bindings (Bindings'First + 2 * I + 1), Env)); @@ -155,7 +148,6 @@ procedure Step7_Quote is begin Err.Check (Params.Kind in Types.Kind_Sequence, "first argument of fn* must be a sequence"); - Env_Reusable := False; return (Kind_Fn, Types.Fns.New_Function (Params => Params.Sequence, Ast => Ast.Sequence.all.Data (3), @@ -198,7 +190,6 @@ procedure Step7_Quote is end if; -- Like Types.Fns.Apply, except that we use TCO. Env := Envs.New_Env (Outer => First.Fn.all.Env); - Env_Reusable := True; Env.all.Set_Binds (Binds => First.Fn.all.Params.all.Data, Exprs => Args); Ast := First.Fn.all.Ast; diff --git a/impls/ada.2/step8_macros.adb b/impls/ada.2/step8_macros.adb index 98c7e7022a..4b0633c4bb 100644 --- a/impls/ada.2/step8_macros.adb +++ b/impls/ada.2/step8_macros.adb @@ -54,10 +54,6 @@ procedure Step8_Macros is -- optimization goes to <>. Ast : Types.T := Ast0; Env : Envs.Ptr := Env0; - Env_Reusable : Boolean := False; - -- True when the environment has been created in this recursion - -- level, and has not yet been referenced by a closure. If so, - -- we can reuse it instead of creating a subenvironment. First : Types.T; begin <> @@ -112,10 +108,7 @@ procedure Step8_Macros is renames Ast.Sequence.all.Data (2).Sequence.all.Data; begin Err.Check (Bindings'Length mod 2 = 0, "expected even binds"); - if not Env_Reusable then - Env := Envs.New_Env (Outer => Env); - Env_Reusable := True; - end if; + Env := Envs.New_Env (Outer => Env); for I in 0 .. Bindings'Length / 2 - 1 loop Env.all.Set (Bindings (Bindings'First + 2 * I), Eval (Bindings (Bindings'First + 2 * I + 1), Env)); @@ -170,7 +163,6 @@ procedure Step8_Macros is begin Err.Check (Params.Kind in Types.Kind_Sequence, "first argument of fn* must be a sequence"); - Env_Reusable := False; return (Kind_Fn, Types.Fns.New_Function (Params => Params.Sequence, Ast => Ast.Sequence.all.Data (3), @@ -223,7 +215,6 @@ procedure Step8_Macros is end if; -- Like Types.Fns.Apply, except that we use TCO. Env := Envs.New_Env (Outer => First.Fn.all.Env); - Env_Reusable := True; Env.all.Set_Binds (Binds => First.Fn.all.Params.all.Data, Exprs => Args); Ast := First.Fn.all.Ast; diff --git a/impls/ada.2/step9_try.adb b/impls/ada.2/step9_try.adb index 7ae8b4afcc..b6b2928287 100644 --- a/impls/ada.2/step9_try.adb +++ b/impls/ada.2/step9_try.adb @@ -54,10 +54,6 @@ procedure Step9_Try is -- optimization goes to <>. Ast : Types.T := Ast0; Env : Envs.Ptr := Env0; - Env_Reusable : Boolean := False; - -- True when the environment has been created in this recursion - -- level, and has not yet been referenced by a closure. If so, - -- we can reuse it instead of creating a subenvironment. First : Types.T; begin <> @@ -112,10 +108,7 @@ procedure Step9_Try is renames Ast.Sequence.all.Data (2).Sequence.all.Data; begin Err.Check (Bindings'Length mod 2 = 0, "expected even binds"); - if not Env_Reusable then - Env := Envs.New_Env (Outer => Env); - Env_Reusable := True; - end if; + Env := Envs.New_Env (Outer => Env); for I in 0 .. Bindings'Length / 2 - 1 loop Env.all.Set (Bindings (Bindings'First + 2 * I), Eval (Bindings (Bindings'First + 2 * I + 1), Env)); @@ -170,7 +163,6 @@ procedure Step9_Try is begin Err.Check (Params.Kind in Types.Kind_Sequence, "first argument of fn* must be a sequence"); - Env_Reusable := False; return (Kind_Fn, Types.Fns.New_Function (Params => Params.Sequence, Ast => Ast.Sequence.all.Data (3), @@ -202,10 +194,7 @@ procedure Step9_Try is when Err.Error => null; end; - if not Env_Reusable then - Env := Envs.New_Env (Outer => Env); - Env_Reusable := True; - end if; + Env := Envs.New_Env (Outer => Env); Env.all.Set (A3 (A3'First + 1), Err.Data); -- check key kind Ast := A3 (A3'Last); goto Restart; @@ -253,7 +242,6 @@ procedure Step9_Try is end if; -- Like Types.Fns.Apply, except that we use TCO. Env := Envs.New_Env (Outer => First.Fn.all.Env); - Env_Reusable := True; Env.all.Set_Binds (Binds => First.Fn.all.Params.all.Data, Exprs => Args); Ast := First.Fn.all.Ast; diff --git a/impls/ada.2/stepa_mal.adb b/impls/ada.2/stepa_mal.adb index e790871c0f..620e0fa341 100644 --- a/impls/ada.2/stepa_mal.adb +++ b/impls/ada.2/stepa_mal.adb @@ -55,10 +55,6 @@ procedure StepA_Mal is -- optimization goes to <>. Ast : Types.T := Ast0; Env : Envs.Ptr := Env0; - Env_Reusable : Boolean := False; - -- True when the environment has been created in this recursion - -- level, and has not yet been referenced by a closure. If so, - -- we can reuse it instead of creating a subenvironment. First : Types.T; begin <> @@ -113,10 +109,7 @@ procedure StepA_Mal is renames Ast.Sequence.all.Data (2).Sequence.all.Data; begin Err.Check (Bindings'Length mod 2 = 0, "expected even binds"); - if not Env_Reusable then - Env := Envs.New_Env (Outer => Env); - Env_Reusable := True; - end if; + Env := Envs.New_Env (Outer => Env); for I in 0 .. Bindings'Length / 2 - 1 loop Env.all.Set (Bindings (Bindings'First + 2 * I), Eval (Bindings (Bindings'First + 2 * I + 1), Env)); @@ -171,7 +164,6 @@ procedure StepA_Mal is begin Err.Check (Params.Kind in Types.Kind_Sequence, "first argument of fn* must be a sequence"); - Env_Reusable := False; return (Kind_Fn, Types.Fns.New_Function (Params => Params.Sequence, Ast => Ast.Sequence.all.Data (3), @@ -203,10 +195,7 @@ procedure StepA_Mal is when Err.Error => null; end; - if not Env_Reusable then - Env := Envs.New_Env (Outer => Env); - Env_Reusable := True; - end if; + Env := Envs.New_Env (Outer => Env); Env.all.Set (A3 (A3'First + 1), Err.Data); -- check key kind Ast := A3 (A3'Last); goto Restart; @@ -259,7 +248,6 @@ procedure StepA_Mal is end case; -- Like Types.Fns.Apply, except that we use TCO. Env := Envs.New_Env (Outer => First.Fn.all.Env); - Env_Reusable := True; Env.all.Set_Binds (Binds => First.Fn.all.Params.all.Data, Exprs => Args); Ast := First.Fn.all.Ast; diff --git a/impls/nim/Dockerfile b/impls/nim/Dockerfile index d25f78843e..afa621025a 100644 --- a/impls/nim/Dockerfile +++ b/impls/nim/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:24.04 MAINTAINER Joel Martin ########################################################## @@ -19,7 +19,6 @@ WORKDIR /mal # Specific implementation requirements ########################################################## -# Nim -RUN apt-get -y install gcc libc-dev libreadline-dev nim +RUN apt-get -y install gcc libc-dev nim ENV HOME /mal diff --git a/impls/nim/core.nim b/impls/nim/core.nim index 37f37034de..0393ef6ba6 100644 --- a/impls/nim/core.nim +++ b/impls/nim/core.nim @@ -1,6 +1,6 @@ import strutils, rdstdin, tables, times, sequtils, types, printer, reader -type MalError* = object of Exception +type MalError* = object of CatchableError t*: MalType # String functions diff --git a/impls/nim/env.nim b/impls/nim/env.nim index 75f481c42b..79f210beb6 100644 --- a/impls/nim/env.nim +++ b/impls/nim/env.nim @@ -11,7 +11,7 @@ proc initEnv*(outer: Env = nil, binds, exprs: MalType = nilObj): Env = else: result.data[e.str] = exprs.list[i] -proc set*(e: var Env, key: string, value: MalType): MalType {.discardable.} = +proc set*(e: Env, key: string, value: MalType): MalType {.discardable.} = e.data[key] = value value diff --git a/impls/nim/reader.nim b/impls/nim/reader.nim index 04f4739bf2..7d02a1a7b6 100644 --- a/impls/nim/reader.nim +++ b/impls/nim/reader.nim @@ -6,7 +6,7 @@ let strRE = re"""^"(?:\\.|[^\\"])*"$""" type - Blank* = object of Exception + Blank* = object of CatchableError Reader = object tokens: seq[string] diff --git a/impls/nim/run b/impls/nim/run index 8ba68a5484..6efdc3de32 100755 --- a/impls/nim/run +++ b/impls/nim/run @@ -1,2 +1,2 @@ -#!/bin/bash +#!/bin/sh exec $(dirname $0)/${STEP:-stepA_mal} "${@}" diff --git a/impls/nim/step0_repl.nim b/impls/nim/step0_repl.nim index 6ae7d895a0..45c3127aba 100644 --- a/impls/nim/step0_repl.nim +++ b/impls/nim/step0_repl.nim @@ -7,5 +7,7 @@ proc eval(ast: string): string = ast proc print(exp: string): string = exp while true: + try: let line = readLineFromStdin("user> ") echo line.read.eval.print + except IOError: quit() diff --git a/impls/nim/step3_env.nim b/impls/nim/step3_env.nim index 1554d4d57b..0ada25543f 100644 --- a/impls/nim/step3_env.nim +++ b/impls/nim/step3_env.nim @@ -2,7 +2,7 @@ import rdstdin, tables, sequtils, types, reader, printer, env proc read(str: string): MalType = str.read_str -proc eval(ast: MalType, env: var Env): MalType = +proc eval(ast: MalType, env: Env): MalType = let dbgeval = env.get("DEBUG-EVAL") if not (dbgeval.isNil or dbgeval.kind in {Nil, False}): @@ -30,7 +30,7 @@ proc eval(ast: MalType, env: var Env): MalType = of "def!": result = env.set(a1.str, a2.eval(env)) of "let*": - var let_env = initEnv(env) + let let_env = initEnv(env) case a1.kind of List, Vector: for i in countup(0, a1.list.high, 2): @@ -48,7 +48,7 @@ proc print(exp: MalType): string = exp.pr_str template wrapNumberFun(op): untyped = fun proc(xs: varargs[MalType]): MalType = number op(xs[0].number, xs[1].number) -var repl_env = initEnv() +let repl_env = initEnv() repl_env.set("+", wrapNumberFun(`+`)) repl_env.set("-", wrapNumberFun(`-`)) diff --git a/impls/nim/step4_if_fn_do.nim b/impls/nim/step4_if_fn_do.nim index 9986cbf013..72e7bd42ac 100644 --- a/impls/nim/step4_if_fn_do.nim +++ b/impls/nim/step4_if_fn_do.nim @@ -2,7 +2,7 @@ import rdstdin, tables, sequtils, types, reader, printer, env, core proc read(str: string): MalType = str.read_str -proc eval(ast: MalType, env: var Env): MalType = +proc eval(ast: MalType, env: Env): MalType = let dbgeval = env.get("DEBUG-EVAL") if not (dbgeval.isNil or dbgeval.kind in {Nil, False}): @@ -35,7 +35,7 @@ proc eval(ast: MalType, env: var Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var let_env = initEnv(env) + let let_env = initEnv(env) case a1.kind of List, Vector: for i in countup(0, a1.list.high, 2): @@ -62,10 +62,8 @@ proc eval(ast: MalType, env: var Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var env2 = env return fun(proc(a: varargs[MalType]): MalType = - var newEnv = initEnv(env2, a1, list(a)) - a2.eval(newEnv)) + a2.eval(initEnv(env, a1, list(a)))) let el = ast.list.mapIt(it.eval(env)) result = el[0].fun(el[1 .. ^1]) @@ -75,7 +73,7 @@ proc eval(ast: MalType, env: var Env): MalType = proc print(exp: MalType): string = exp.pr_str -var repl_env = initEnv() +let repl_env = initEnv() for k, v in ns.items: repl_env.set(k, v) diff --git a/impls/nim/step5_tco.nim b/impls/nim/step5_tco.nim index aae61c8d26..00f9bfa38d 100644 --- a/impls/nim/step5_tco.nim +++ b/impls/nim/step5_tco.nim @@ -44,7 +44,7 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var let_env = initEnv(env) + let let_env = initEnv(env) case a1.kind of List, Vector: for i in countup(0, a1.list.high, 2): @@ -80,10 +80,8 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var env2 = env let fn = proc(a: varargs[MalType]): MalType = - var newEnv = initEnv(env2, a1, list(a)) - a2.eval(newEnv) + a2.eval(initEnv(env, a1, list(a))) return malfun(fn, a2, a1, env) let f = eval(a0, env) @@ -97,7 +95,7 @@ proc eval(ast: MalType, env: Env): MalType = proc print(exp: MalType): string = exp.pr_str -var repl_env = initEnv() +let repl_env = initEnv() for k, v in ns.items: repl_env.set(k, v) diff --git a/impls/nim/step6_file.nim b/impls/nim/step6_file.nim index 9f228fc2ae..c54de4dc76 100644 --- a/impls/nim/step6_file.nim +++ b/impls/nim/step6_file.nim @@ -44,7 +44,7 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var let_env = initEnv(env) + let let_env = initEnv(env) case a1.kind of List, Vector: for i in countup(0, a1.list.high, 2): @@ -80,10 +80,8 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var env2 = env let fn = proc(a: varargs[MalType]): MalType = - var newEnv = initEnv(env2, a1, list(a)) - a2.eval(newEnv) + a2.eval(initEnv(env, a1, list(a))) return malfun(fn, a2, a1, env) let f = eval(a0, env) @@ -97,12 +95,12 @@ proc eval(ast: MalType, env: Env): MalType = proc print(exp: MalType): string = exp.pr_str -var repl_env = initEnv() +let repl_env = initEnv() for k, v in ns.items: repl_env.set(k, v) repl_env.set("eval", fun(proc(xs: varargs[MalType]): MalType = eval(xs[0], repl_env))) -var ps = commandLineParams() +let ps = commandLineParams() repl_env.set("*ARGV*", list((if paramCount() > 1: ps[1..ps.high] else: @[]).map(str))) diff --git a/impls/nim/step7_quote.nim b/impls/nim/step7_quote.nim index c09ecfbba1..8ab5418d7f 100644 --- a/impls/nim/step7_quote.nim +++ b/impls/nim/step7_quote.nim @@ -7,7 +7,7 @@ proc quasiquote(ast: MalType): MalType proc quasiquote_loop(xs: seq[MalType]): MalType = result = list() for i in countdown(xs.high, 0): - var elt = xs[i] + let elt = xs[i] if elt.kind == List and 0 < elt.list.len and elt.list[0] == symbol "splice-unquote": result = list(symbol "concat", elt.list[1], result) else: @@ -72,7 +72,7 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var let_env = initEnv(env) + let let_env = initEnv(env) case a1.kind of List, Vector: for i in countup(0, a1.list.high, 2): @@ -115,10 +115,8 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var env2 = env let fn = proc(a: varargs[MalType]): MalType = - var newEnv = initEnv(env2, a1, list(a)) - a2.eval(newEnv) + a2.eval(initEnv(env, a1, list(a))) return malfun(fn, a2, a1, env) let f = eval(a0, env) @@ -132,12 +130,12 @@ proc eval(ast: MalType, env: Env): MalType = proc print(exp: MalType): string = exp.pr_str -var repl_env = initEnv() +let repl_env = initEnv() for k, v in ns.items: repl_env.set(k, v) repl_env.set("eval", fun(proc(xs: varargs[MalType]): MalType = eval(xs[0], repl_env))) -var ps = commandLineParams() +let ps = commandLineParams() repl_env.set("*ARGV*", list((if paramCount() > 1: ps[1..ps.high] else: @[]).map(str))) diff --git a/impls/nim/step8_macros.nim b/impls/nim/step8_macros.nim index e890900a26..e379c2d82d 100644 --- a/impls/nim/step8_macros.nim +++ b/impls/nim/step8_macros.nim @@ -7,7 +7,7 @@ proc quasiquote(ast: MalType): MalType proc quasiquote_loop(xs: seq[MalType]): MalType = result = list() for i in countdown(xs.high, 0): - var elt = xs[i] + let elt = xs[i] if elt.kind == List and 0 < elt.list.len and elt.list[0] == symbol "splice-unquote": result = list(symbol "concat", elt.list[1], result) else: @@ -72,7 +72,7 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var let_env = initEnv(env) + let let_env = initEnv(env) case a1.kind of List, Vector: for i in countup(0, a1.list.high, 2): @@ -90,9 +90,9 @@ proc eval(ast: MalType, env: Env): MalType = continue # TCO of "defmacro!": - var fun = ast.list[2].eval(env) - fun = malfun(fun.malfun.fn, fun.malfun.ast, fun.malfun.params, fun.malfun.env, true) - return env.set(ast.list[1].str, fun) + let fun = ast.list[2].eval(env) + let mac = malfun(fun.malfun.fn, fun.malfun.ast, fun.malfun.params, fun.malfun.env, true) + return env.set(ast.list[1].str, mac) of "do": let last = ast.list.high @@ -120,10 +120,8 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var env2 = env let fn = proc(a: varargs[MalType]): MalType = - var newEnv = initEnv(env2, a1, list(a)) - a2.eval(newEnv) + a2.eval(initEnv(env, a1, list(a))) return malfun(fn, a2, a1, env) let f = eval(a0, env) @@ -140,12 +138,12 @@ proc eval(ast: MalType, env: Env): MalType = proc print(exp: MalType): string = exp.pr_str -var repl_env = initEnv() +let repl_env = initEnv() for k, v in ns.items: repl_env.set(k, v) repl_env.set("eval", fun(proc(xs: varargs[MalType]): MalType = eval(xs[0], repl_env))) -var ps = commandLineParams() +let ps = commandLineParams() repl_env.set("*ARGV*", list((if paramCount() > 1: ps[1..ps.high] else: @[]).map(str))) diff --git a/impls/nim/step9_try.nim b/impls/nim/step9_try.nim index 1b25a11488..ca8effaac8 100644 --- a/impls/nim/step9_try.nim +++ b/impls/nim/step9_try.nim @@ -7,7 +7,7 @@ proc quasiquote(ast: MalType): MalType proc quasiquote_loop(xs: seq[MalType]): MalType = result = list() for i in countdown(xs.high, 0): - var elt = xs[i] + let elt = xs[i] if elt.kind == List and 0 < elt.list.len and elt.list[0] == symbol "splice-unquote": result = list(symbol "concat", elt.list[1], result) else: @@ -73,7 +73,7 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var let_env = initEnv(env) + let let_env = initEnv(env) case a1.kind of List, Vector: for i in countup(0, a1.list.high, 2): @@ -91,9 +91,9 @@ proc eval(ast: MalType, env: Env): MalType = continue # TCO of "defmacro!": - var fun = ast.list[2].eval(env) - fun = malfun(fun.malfun.fn, fun.malfun.ast, fun.malfun.params, fun.malfun.env, true) - return env.set(ast.list[1].str, fun) + let fun = ast.list[2].eval(env) + let mac = malfun(fun.malfun.fn, fun.malfun.ast, fun.malfun.params, fun.malfun.env, true) + return env.set(ast.list[1].str, mac) of "try*": let a1 = ast.list[1] @@ -140,10 +140,8 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var env2 = env let fn = proc(a: varargs[MalType]): MalType = - var newEnv = initEnv(env2, a1, list(a)) - a2.eval(newEnv) + a2.eval(initEnv(env, a1, list(a))) return malfun(fn, a2, a1, env) let f = eval(a0, env) @@ -160,12 +158,12 @@ proc eval(ast: MalType, env: Env): MalType = proc print(exp: MalType): string = exp.pr_str -var repl_env = initEnv() +let repl_env = initEnv() for k, v in ns.items: repl_env.set(k, v) repl_env.set("eval", fun(proc(xs: varargs[MalType]): MalType = eval(xs[0], repl_env))) -var ps = commandLineParams() +let ps = commandLineParams() repl_env.set("*ARGV*", list((if paramCount() > 1: ps[1..ps.high] else: @[]).map(str))) diff --git a/impls/nim/stepA_mal.nim b/impls/nim/stepA_mal.nim index 031d598a49..526e30404b 100644 --- a/impls/nim/stepA_mal.nim +++ b/impls/nim/stepA_mal.nim @@ -7,7 +7,7 @@ proc quasiquote(ast: MalType): MalType proc quasiquote_loop(xs: seq[MalType]): MalType = result = list() for i in countdown(xs.high, 0): - var elt = xs[i] + let elt = xs[i] if elt.kind == List and 0 < elt.list.len and elt.list[0] == symbol "splice-unquote": result = list(symbol "concat", elt.list[1], result) else: @@ -73,7 +73,7 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var let_env = initEnv(env) + let let_env = initEnv(env) case a1.kind of List, Vector: for i in countup(0, a1.list.high, 2): @@ -91,9 +91,9 @@ proc eval(ast: MalType, env: Env): MalType = continue # TCO of "defmacro!": - var fun = ast.list[2].eval(env) - fun = malfun(fun.malfun.fn, fun.malfun.ast, fun.malfun.params, fun.malfun.env, true) - return env.set(ast.list[1].str, fun) + let fun = ast.list[2].eval(env) + let mac = malfun(fun.malfun.fn, fun.malfun.ast, fun.malfun.params, fun.malfun.env, true) + return env.set(ast.list[1].str, mac) of "try*": let a1 = ast.list[1] @@ -140,10 +140,8 @@ proc eval(ast: MalType, env: Env): MalType = let a1 = ast.list[1] a2 = ast.list[2] - var env2 = env let fn = proc(a: varargs[MalType]): MalType = - var newEnv = initEnv(env2, a1, list(a)) - a2.eval(newEnv) + a2.eval(initEnv(env, a1, list(a))) return malfun(fn, a2, a1, env) let f = eval(a0, env) @@ -160,12 +158,12 @@ proc eval(ast: MalType, env: Env): MalType = proc print(exp: MalType): string = exp.pr_str -var repl_env = initEnv() +let repl_env = initEnv() for k, v in ns.items: repl_env.set(k, v) repl_env.set("eval", fun(proc(xs: varargs[MalType]): MalType = eval(xs[0], repl_env))) -var ps = commandLineParams() +let ps = commandLineParams() repl_env.set("*ARGV*", list((if paramCount() > 1: ps[1..ps.high] else: @[]).map(str))) diff --git a/impls/tests/step4_if_fn_do.mal b/impls/tests/step4_if_fn_do.mal index b98f2dae2a..fbecb7d448 100644 --- a/impls/tests/step4_if_fn_do.mal +++ b/impls/tests/step4_if_fn_do.mal @@ -202,6 +202,12 @@ (plus7 8) ;=>15 +(let* [b 0 f (fn* [] b)] (let* [b 1] (f))) +;=>0 + +((let* [b 0] (fn* [] b))) +;=>0 + ;; Testing do form (do (prn 101)) ;/101