Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New test for closures #675

Merged
merged 4 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion impls/ada.2/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ubuntu:20.04
FROM ubuntu:24.04
MAINTAINER Joel Martin <[email protected]>

##########################################################
Expand Down
2 changes: 0 additions & 2 deletions impls/ada.2/envs.ads
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion impls/ada.2/run
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/bin/bash
#!/bin/sh
exec $(dirname $0)/${STEP:-stepA_mal} "${@}"
11 changes: 1 addition & 10 deletions impls/ada.2/step5_tco.adb
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ procedure Step5_Tco is
-- optimization goes to <<Restart>>.
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
<<Restart>>
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 1 addition & 10 deletions impls/ada.2/step6_file.adb
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ procedure Step6_File is
-- optimization goes to <<Restart>>.
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
<<Restart>>
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 1 addition & 10 deletions impls/ada.2/step7_quote.adb
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ procedure Step7_Quote is
-- optimization goes to <<Restart>>.
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
<<Restart>>
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 1 addition & 10 deletions impls/ada.2/step8_macros.adb
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ procedure Step8_Macros is
-- optimization goes to <<Restart>>.
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
<<Restart>>
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 2 additions & 14 deletions impls/ada.2/step9_try.adb
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ procedure Step9_Try is
-- optimization goes to <<Restart>>.
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
<<Restart>>
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 2 additions & 14 deletions impls/ada.2/stepa_mal.adb
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,6 @@ procedure StepA_Mal is
-- optimization goes to <<Restart>>.
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
<<Restart>>
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 2 additions & 3 deletions impls/nim/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ubuntu:20.04
FROM ubuntu:24.04
MAINTAINER Joel Martin <[email protected]>

##########################################################
Expand All @@ -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
2 changes: 1 addition & 1 deletion impls/nim/core.nim
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion impls/nim/env.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion impls/nim/reader.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ let
strRE = re"""^"(?:\\.|[^\\"])*"$"""

type
Blank* = object of Exception
Blank* = object of CatchableError

Reader = object
tokens: seq[string]
Expand Down
2 changes: 1 addition & 1 deletion impls/nim/run
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/bin/bash
#!/bin/sh
exec $(dirname $0)/${STEP:-stepA_mal} "${@}"
2 changes: 2 additions & 0 deletions impls/nim/step0_repl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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()
6 changes: 3 additions & 3 deletions impls/nim/step3_env.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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}):
Expand Down Expand Up @@ -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):
Expand All @@ -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(`-`))
Expand Down
10 changes: 4 additions & 6 deletions impls/nim/step4_if_fn_do.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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}):
Expand Down Expand Up @@ -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):
Expand All @@ -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])
Expand All @@ -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)
Expand Down
Loading
Loading