1
1
mirror of https://github.com/kanaka/mal.git synced 2024-10-04 01:17:33 +03:00

Merge branch 'kanaka:master' into patch-1

This commit is contained in:
Bezděk Miroslav 2022-03-04 14:33:23 +01:00 committed by GitHub
commit c7d437c6d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
320 changed files with 7408 additions and 618 deletions

View File

@ -73,6 +73,7 @@ IMPL:
- {IMPL: prolog}
- {IMPL: ps}
- {IMPL: powershell, NO_SELF_HOST_PERF: 1}
- {IMPL: purs}
- {IMPL: python, python_MODE: python2}
- {IMPL: python, python_MODE: python3}
- {IMPL: python.2}
@ -81,6 +82,7 @@ IMPL:
- {IMPL: rexx}
- {IMPL: rpython, SLOW: 1}
- {IMPL: ruby}
- {IMPL: ruby.2}
- {IMPL: rust}
- {IMPL: scala}
- {IMPL: scheme, scheme_MODE: chibi}

View File

@ -38,7 +38,7 @@ IMPLS = ada ada.2 awk bash basic bbc-basic c c.2 chuck clojure coffee common-lis
elisp elixir elm erlang es6 factor fantom fennel forth fsharp go groovy gnu-smalltalk \
guile haskell haxe hy io janet java java-truffle js jq julia kotlin livescript logo lua make mal \
matlab miniMAL nasm nim objc objpascal ocaml perl perl6 php picolisp pike plpgsql \
plsql powershell prolog ps python python.2 r racket rexx rpython ruby rust scala scheme skew sml \
plsql powershell prolog ps purs python python.2 r racket rexx rpython ruby ruby.2 rust scala scheme skew sml \
swift swift3 swift4 swift5 tcl ts vala vb vhdl vimscript wasm wren yorick xslt zig
step5_EXCLUDES += bash # never completes at 10,000
@ -168,6 +168,7 @@ plsql_STEP_TO_PROG = impls/plsql/$($(1)).sql
powershell_STEP_TO_PROG = impls/powershell/$($(1)).ps1
prolog_STEP_TO_PROG = impls/prolog/$($(1)).pl
ps_STEP_TO_PROG = impls/ps/$($(1)).ps
purs_STEP_TO_PROG = impls/purs/$($(1)).js
python_STEP_TO_PROG = impls/python/$($(1)).py
python.2_STEP_TO_PROG = impls/python.2/$($(1)).py
r_STEP_TO_PROG = impls/r/$($(1)).r
@ -175,6 +176,7 @@ racket_STEP_TO_PROG = impls/racket/$($(1)).rkt
rexx_STEP_TO_PROG = impls/rexx/$($(1)).rexxpp
rpython_STEP_TO_PROG = impls/rpython/$($(1))
ruby_STEP_TO_PROG = impls/ruby/$($(1)).rb
ruby.2_STEP_TO_PROG = impls/ruby.2/$($(1)).rb
rust_STEP_TO_PROG = impls/rust/$($(1))
scala_STEP_TO_PROG = impls/scala/target/scala-2.11/classes/$($(1)).class
scheme_STEP_TO_PROG = $(scheme_STEP_TO_PROG_$(scheme_MODE))

View File

@ -42,7 +42,7 @@ process guide](process/guide.md) there is also a [mal/make-a-lisp
FAQ](docs/FAQ.md) where I attempt to answer some common questions.
**3. Mal is implemented in 86 languages (91 different implementations and 113 runtime modes)**
**3. Mal is implemented in 87 languages (93 different implementations and 115 runtime modes)**
| Language | Creator |
| -------- | ------- |
@ -83,7 +83,7 @@ FAQ](docs/FAQ.md) where I attempt to answer some common questions.
| [Io](#io) | [Dov Murik](https://github.com/dubek) |
| [Janet](#janet) | [sogaiu](https://github.com/sogaiu) |
| [Java](#java-17) | [Joel Martin](https://github.com/kanaka) |
| [Java](#java-truffle) (Truffle/GraalVM) | [Matt McGill](https://github.com/mmcgill)
| [Java](#java-using-truffle-for-graalvm) (Truffle/GraalVM) | [Matt McGill](https://github.com/mmcgill)
| [JavaScript](#javascriptnode) ([Demo](http://kanaka.github.io/mal)) | [Joel Martin](https://github.com/kanaka) |
| [jq](#jq) | [Ali MohammadPur](https://github.com/alimpfard) |
| [Julia](#julia) | [Joel Martin](https://github.com/kanaka) |
@ -110,6 +110,7 @@ FAQ](docs/FAQ.md) where I attempt to answer some common questions.
| [PostScript](#postscript-level-23) | [Joel Martin](https://github.com/kanaka) |
| [PowerShell](#powershell) | [Joel Martin](https://github.com/kanaka) |
| [Prolog](#prolog-logical-language) | [Nicolas Boulenguez](https://github.com/asarhaddon) |
| [PureScript](#purescript) | [mrsekut](https://github.com/mrsekut) |
| [Python](#python-2x-and-3x) (2.X & 3.X) | [Joel Martin](https://github.com/kanaka) |
| [Python #2](#python2-3x) (3.X) | [Gavin Lewis](https://github.com/epylar) |
| [RPython](#rpython) | [Joel Martin](https://github.com/kanaka) |
@ -117,6 +118,7 @@ FAQ](docs/FAQ.md) where I attempt to answer some common questions.
| [Racket](#racket-53) | [Joel Martin](https://github.com/kanaka) |
| [Rexx](#rexx) | [Dov Murik](https://github.com/dubek) |
| [Ruby](#ruby-19) | [Joel Martin](https://github.com/kanaka) |
| [Ruby #2](#ruby) | [Ryan Cook](https://github.com/cookrn) |
| [Rust](#rust-138) | [Joel Martin](https://github.com/kanaka) |
| [Scala](#scala) | [Joel Martin](https://github.com/kanaka) |
| [Scheme (R7RS)](#scheme-r7rs) | [Vasilij Schneidermann](https://github.com/wasamasa) |
@ -937,6 +939,15 @@ cd impls/prolog
swipl stepX_YYY
```
### PureScript
The PureScript implementation requires the spago compiler version 0.20.2.
```
cd impls/purs
make
node ./stepX_YYY.js
```
### Python (2.X and 3.X)
```
@ -1002,6 +1013,19 @@ cd impls/ruby
ruby stepX_YYY.rb
```
### Ruby #2
A second Ruby implementation with the following goals:
- No global variables
- No modification (monkey-patching) of core Ruby classes
- Modularized into the `Mal` module namespace
```
cd impls/ruby.2
ruby stepX_YYY.rb
```
### Rust (1.38+)
The rust implementation of mal requires the rust compiler and build
@ -1026,16 +1050,15 @@ scala -classpath target/scala*/classes stepX_YYY
### Scheme (R7RS) ###
The Scheme implementation of mal has been tested with Chibi-Scheme
0.7.3, Kawa 2.4, Gauche 0.9.5, CHICKEN 4.11.0, Sagittarius 0.8.3,
Cyclone 0.6.3 (Git version) and Foment 0.4 (Git version). You should
The Scheme implementation of MAL has been tested with Chibi-Scheme
0.10, Kawa 3.1.1, Gauche 0.9.6, CHICKEN 5.1.0, Sagittarius 0.9.7,
Cyclone 0.32.0 (Git version) and Foment 0.4 (Git version). You should
be able to get it running on other conforming R7RS implementations
after figuring out how libraries are loaded and adjusting the
`Makefile` and `run` script accordingly.
```
cd impls/scheme
make symlinks
# chibi
scheme_MODE=chibi ./run
# kawa

View File

@ -179,10 +179,8 @@ package body Core is
return A1.Builtin_With_Meta.all.Meta;
when Kind_Builtin =>
return Types.Nil;
when Kind_Atom =>
return A1.Atom.all.Meta;
when others =>
Err.Raise_With ("expected an atom, function, map or sequence");
Err.Raise_With ("expected a function, map or sequence");
end case;
end;
end Meta;
@ -451,8 +449,6 @@ package body Core is
when Kind_Fn =>
return (Kind_Fn, Types.Fns.New_Function
(A1.Fn.all.Params, A1.Fn.all.Ast, A1.Fn.all.Env, A2));
when Kind_Atom =>
return A1.Atom.all.With_Meta (A2);
when others =>
Err.Raise_With
("parameter 1 must be a function, map or sequence");

View File

@ -29,12 +29,8 @@ package body Types.Atoms is
procedure Keep_References (Object : in out Instance) is
begin
Keep (Object.Data);
Keep (Object.Meta);
end Keep_References;
function Meta (Item : in Instance) return T
is (Item.F_Meta);
function Reset (Args : in T_Array) return T is
begin
Err.Check (Args'Length = 2 and then Args (Args'First).Kind = Kind_Atom,
@ -66,14 +62,4 @@ package body Types.Atoms is
end;
end Swap;
function With_Meta (Item : in Instance;
Metadata : in T) return T is
Ref : constant Atom_Ptr := new Instance;
begin
Garbage_Collected.Register (Garbage_Collected.Pointer (Ref));
Ref.all.Data := Item.Data;
Ref.all.F_Meta := Metadata;
return (Kind_Atom, Ref);
end With_Meta;
end Types.Atoms;

View File

@ -13,15 +13,10 @@ package Types.Atoms is
-- Helper for print.
function Deref (Item : in Instance) return T with Inline;
function With_Meta (Item : in Instance;
Metadata : in T) return T;
function Meta (Item : in Instance) return T;
private
type Instance is new Garbage_Collected.Instance with record
Data : T;
F_Meta : T;
end record;
overriding procedure Keep_References (Object : in out Instance) with Inline;

View File

@ -563,7 +563,18 @@ package body Core is
Sym_Handle := Car (Rest_List);
return New_Symbol_Mal_Type (':' & Deref_String (Sym_Handle).Get_String);
case Deref (Sym_Handle).Sym_Type is
when Str =>
return New_Symbol_Mal_Type (':' & Deref_String (Sym_Handle).Get_String);
when Sym =>
if Deref_Sym (Sym_Handle).Get_Sym (1) = ':' then
return Sym_Handle;
end if;
when others =>
null;
end case;
raise Runtime_Exception with "keyword: expects a keyword or string";
end Keyword;

View File

@ -50,7 +50,10 @@ procedure Step8_Macros is
Fn_Body := Car (Deref_List (Cdr (Args)).all);
Res := Eval (Fn_Body, Env);
Lambda_P := Deref_Lambda (Res);
Lambda_P.Set_Is_Macro (True);
Res := New_Lambda_Mal_Type (Params => Lambda_P.all.Get_Params,
Expr => Lambda_P.all.Get_Expr,
Env => Lambda_P.all.Get_Env);
Deref_Lambda (Res).Set_Is_Macro (True);
Envs.Set (Env, Deref_Sym (Name).Get_Sym, Res);
return Res;
end Def_Macro;
@ -65,7 +68,6 @@ procedure Step8_Macros is
begin
Res := Ast;
E := Env;
loop
@ -77,7 +79,7 @@ procedure Step8_Macros is
-- Get the macro in the list from the env
-- or return null if not applicable.
LP := Get_Macro (Res, E);
LP := Get_Macro (Res, Env);
exit when LP = null or else not LP.Get_Is_Macro;
@ -85,7 +87,7 @@ procedure Step8_Macros is
Fn_List : Mal_Handle := Cdr (LMT);
Params : List_Mal_Type;
begin
E := Envs.New_Env (E);
E := Envs.New_Env (LP.Get_Env);
Params := Deref_List (LP.Get_Params).all;
if Envs.Bind (E, Params, Deref_List (Fn_List).all) then

View File

@ -50,7 +50,10 @@ procedure Step9_Try is
Fn_Body := Car (Deref_List (Cdr (Args)).all);
Res := Eval (Fn_Body, Env);
Lambda_P := Deref_Lambda (Res);
Lambda_P.Set_Is_Macro (True);
Res := New_Lambda_Mal_Type (Params => Lambda_P.all.Get_Params,
Expr => Lambda_P.all.Get_Expr,
Env => Lambda_P.all.Get_Env);
Deref_Lambda (Res).Set_Is_Macro (True);
Envs.Set (Env, Deref_Sym (Name).Get_Sym, Res);
return Res;
end Def_Macro;
@ -65,7 +68,6 @@ procedure Step9_Try is
begin
Res := Ast;
E := Env;
loop
@ -77,7 +79,7 @@ procedure Step9_Try is
-- Get the macro in the list from the env
-- or return null if not applicable.
LP := Get_Macro (Res, E);
LP := Get_Macro (Res, Env);
exit when LP = null or else not LP.Get_Is_Macro;
@ -85,7 +87,7 @@ procedure Step9_Try is
Fn_List : Mal_Handle := Cdr (LMT);
Params : List_Mal_Type;
begin
E := Envs.New_Env (E);
E := Envs.New_Env (LP.Get_Env);
Params := Deref_List (LP.Get_Params).all;
if Envs.Bind (E, Params, Deref_List (Fn_List).all) then

View File

@ -50,7 +50,10 @@ procedure StepA_Mal is
Fn_Body := Car (Deref_List (Cdr (Args)).all);
Res := Eval (Fn_Body, Env);
Lambda_P := Deref_Lambda (Res);
Lambda_P.Set_Is_Macro (True);
Res := New_Lambda_Mal_Type (Params => Lambda_P.all.Get_Params,
Expr => Lambda_P.all.Get_Expr,
Env => Lambda_P.all.Get_Env);
Deref_Lambda (Res).Set_Is_Macro (True);
Envs.Set (Env, Deref_Sym (Name).Get_Sym, Res);
return Res;
end Def_Macro;
@ -65,7 +68,6 @@ procedure StepA_Mal is
begin
Res := Ast;
E := Env;
loop
@ -77,7 +79,7 @@ procedure StepA_Mal is
-- Get the macro in the list from the env
-- or return null if not applicable.
LP := Get_Macro (Res, E);
LP := Get_Macro (Res, Env);
exit when LP = null or else not LP.Get_Is_Macro;
@ -85,9 +87,10 @@ procedure StepA_Mal is
Fn_List : Mal_Handle := Cdr (LMT);
Params : List_Mal_Type;
begin
E := Envs.New_Env (E);
E := Envs.New_Env (LP.Get_Env);
Params := Deref_List (LP.Get_Params).all;
if Envs.Bind (E, Params, Deref_List (Fn_List).all) then
Res := Eval (LP.Get_Expr, E);

View File

@ -233,7 +233,7 @@ function EVAL_let(ast, env, ret_env, idx, params, params_idx, params_len,
return body
}
function EVAL_defmacro(ast, env, idx, sym, ret, len)
function EVAL_defmacro(ast, env, idx, sym, ret, len, fun_idx, mac_idx)
{
idx = substr(ast, 2)
if (types_heap[idx]["len"] != 3) {
@ -259,7 +259,17 @@ function EVAL_defmacro(ast, env, idx, sym, ret, len)
env_release(env)
return "!\"Incompatible type for argument 2 of 'defmacro!'. Expects function, supplied " types_typename(ret) "."
}
types_heap[substr(ret, 2)]["is_macro"] = 1
# Replace `ret` with a clone setting the `is_macro` bit.
fun_idx = substr(ret, 2)
mac_idx = types_allocate()
types_addref(types_heap[mac_idx]["params"] = types_heap[fun_idx]["params"])
types_addref(types_heap[mac_idx]["body"] = types_heap[fun_idx]["body"])
env_addref(types_heap[mac_idx]["env"] = types_heap[fun_idx]["env"])
types_heap[mac_idx]["is_macro"] = 1
types_release(ret)
ret = "$" mac_idx
env_set(env, sym, ret)
types_addref(ret)
env_release(env)

View File

@ -233,7 +233,7 @@ function EVAL_let(ast, env, ret_env, idx, params, params_idx, params_len,
return body
}
function EVAL_defmacro(ast, env, idx, sym, ret, len)
function EVAL_defmacro(ast, env, idx, sym, ret, len, fun_idx, mac_idx)
{
idx = substr(ast, 2)
if (types_heap[idx]["len"] != 3) {
@ -259,7 +259,17 @@ function EVAL_defmacro(ast, env, idx, sym, ret, len)
env_release(env)
return "!\"Incompatible type for argument 2 of 'defmacro!'. Expects function, supplied " types_typename(ret) "."
}
types_heap[substr(ret, 2)]["is_macro"] = 1
# Replace `ret` with a clone setting the `is_macro` bit.
fun_idx = substr(ret, 2)
mac_idx = types_allocate()
types_addref(types_heap[mac_idx]["params"] = types_heap[fun_idx]["params"])
types_addref(types_heap[mac_idx]["body"] = types_heap[fun_idx]["body"])
env_addref(types_heap[mac_idx]["env"] = types_heap[fun_idx]["env"])
types_heap[mac_idx]["is_macro"] = 1
types_release(ret)
ret = "$" mac_idx
env_set(env, sym, ret)
types_addref(ret)
env_release(env)

View File

@ -233,7 +233,7 @@ function EVAL_let(ast, env, ret_env, idx, params, params_idx, params_len,
return body
}
function EVAL_defmacro(ast, env, idx, sym, ret, len)
function EVAL_defmacro(ast, env, idx, sym, ret, len, fun_idx, mac_idx)
{
idx = substr(ast, 2)
if (types_heap[idx]["len"] != 3) {
@ -259,7 +259,17 @@ function EVAL_defmacro(ast, env, idx, sym, ret, len)
env_release(env)
return "!\"Incompatible type for argument 2 of 'defmacro!'. Expects function, supplied " types_typename(ret) "."
}
types_heap[substr(ret, 2)]["is_macro"] = 1
# Replace `ret` with a clone setting the `is_macro` bit.
fun_idx = substr(ret, 2)
mac_idx = types_allocate()
types_addref(types_heap[mac_idx]["params"] = types_heap[fun_idx]["params"])
types_addref(types_heap[mac_idx]["body"] = types_heap[fun_idx]["body"])
env_addref(types_heap[mac_idx]["env"] = types_heap[fun_idx]["env"])
types_heap[mac_idx]["is_macro"] = 1
types_release(ret)
ret = "$" mac_idx
env_set(env, sym, ret)
types_addref(ret)
env_release(env)

View File

@ -164,6 +164,9 @@ EVAL () {
defmacro!)
EVAL "${a2}" "${env}"
[[ "${__ERROR}" ]] && return 1
local func="${r}"
__new_obj_like "${func}"
ANON["${r}"]="${ANON["${func}"]}"
ANON["${r}_ismacro_"]="yes"
ENV_SET "${env}" "${a1}" "${r}"
return ;;

View File

@ -164,6 +164,9 @@ EVAL () {
defmacro!)
EVAL "${a2}" "${env}"
[[ "${__ERROR}" ]] && return 1
local func="${r}"
__new_obj_like "${func}"
ANON["${r}"]="${ANON["${func}"]}"
ANON["${r}_ismacro_"]="yes"
ENV_SET "${env}" "${a1}" "${r}"
return ;;

View File

@ -164,6 +164,9 @@ EVAL () {
defmacro!)
EVAL "${a2}" "${env}"
[[ "${__ERROR}" ]] && return 1
local func="${r}"
__new_obj_like "${func}"
ANON["${r}"]="${ANON["${func}"]}"
ANON["${r}_ismacro_"]="yes"
ENV_SET "${env}" "${a1}" "${r}"
return ;;

View File

@ -14,7 +14,7 @@ eval_ast = (ast, env) ->
types._vector(ast.map((a) -> EVAL(a, env))...)
else if types._hash_map_Q(ast)
new_hm = {}
new_hm[k] = EVAL(ast[k],env) for k,v of ast
new_hm[k] = EVAL(v, env) for k,v of ast
new_hm
else ast

View File

@ -15,7 +15,7 @@ eval_ast = (ast, env) ->
types._vector(ast.map((a) -> EVAL(a, env))...)
else if types._hash_map_Q(ast)
new_hm = {}
new_hm[k] = EVAL(ast[k],env) for k,v of ast
new_hm[k] = EVAL(v, env) for k,v of ast
new_hm
else ast

View File

@ -16,7 +16,7 @@ eval_ast = (ast, env) ->
types._vector(ast.map((a) -> EVAL(a, env))...)
else if types._hash_map_Q(ast)
new_hm = {}
new_hm[k] = EVAL(ast[k],env) for k,v of ast
new_hm[k] = EVAL(v, env) for k,v of ast
new_hm
else ast

View File

@ -16,7 +16,7 @@ eval_ast = (ast, env) ->
types._vector(ast.map((a) -> EVAL(a, env))...)
else if types._hash_map_Q(ast)
new_hm = {}
new_hm[k] = EVAL(ast[k],env) for k,v of ast
new_hm[k] = EVAL(v, env) for k,v of ast
new_hm
else ast

View File

@ -16,7 +16,7 @@ eval_ast = (ast, env) ->
types._vector(ast.map((a) -> EVAL(a, env))...)
else if types._hash_map_Q(ast)
new_hm = {}
new_hm[k] = EVAL(ast[k],env) for k,v of ast
new_hm[k] = EVAL(v, env) for k,v of ast
new_hm
else ast

View File

@ -32,7 +32,7 @@ eval_ast = (ast, env) ->
types._vector(ast.map((a) -> EVAL(a, env))...)
else if types._hash_map_Q(ast)
new_hm = {}
new_hm[k] = EVAL(ast[k],env) for k,v of ast
new_hm[k] = EVAL(v, env) for k,v of ast
new_hm
else ast

View File

@ -41,7 +41,7 @@ eval_ast = (ast, env) ->
types._vector(ast.map((a) -> EVAL(a, env))...)
else if types._hash_map_Q(ast)
new_hm = {}
new_hm[k] = EVAL(ast[k],env) for k,v of ast
new_hm[k] = EVAL(v, env) for k,v of ast
new_hm
else ast
@ -73,6 +73,7 @@ EVAL = (ast, env) ->
ast = quasiquote(a1)
when "defmacro!"
f = EVAL(a2, env)
f = types._clone(f)
f.__ismacro__ = true
return env.set(a1, f)
when "macroexpand"

View File

@ -41,7 +41,7 @@ eval_ast = (ast, env) ->
types._vector(ast.map((a) -> EVAL(a, env))...)
else if types._hash_map_Q(ast)
new_hm = {}
new_hm[k] = EVAL(ast[k],env) for k,v of ast
new_hm[k] = EVAL(v, env) for k,v of ast
new_hm
else ast
@ -73,6 +73,7 @@ EVAL = (ast, env) ->
ast = quasiquote(a1)
when "defmacro!"
f = EVAL(a2, env)
f = types._clone(f)
f.__ismacro__ = true
return env.set(a1, f)
when "macroexpand"

View File

@ -41,7 +41,7 @@ eval_ast = (ast, env) ->
types._vector(ast.map((a) -> EVAL(a, env))...)
else if types._hash_map_Q(ast)
new_hm = {}
new_hm[k] = EVAL(ast[k],env) for k,v of ast
new_hm[k] = EVAL(v, env) for k,v of ast
new_hm
else ast
@ -73,6 +73,7 @@ EVAL = (ast, env) ->
ast = quasiquote(a1)
when "defmacro!"
f = EVAL(a2, env)
f = types._clone(f)
f.__ismacro__ = true
return env.set(a1, f)
when "macroexpand"

View File

@ -55,7 +55,7 @@
(let ((hash-map-value (mal-data-value hash-map))
(new-hash-table (make-mal-value-hash-table)))
(genhash:hashmap (lambda (key value)
(setf (genhash:hashref (mal-eval key env) new-hash-table)
(setf (genhash:hashref key new-hash-table)
(mal-eval value env)))
hash-map-value)
(make-mal-hash-map new-hash-table)))

View File

@ -56,7 +56,7 @@
(let ((hash-map-value (mal-data-value hash-map))
(new-hash-table (make-mal-value-hash-table)))
(genhash:hashmap (lambda (key value)
(setf (genhash:hashref (mal-eval key env) new-hash-table)
(setf (genhash:hashref key new-hash-table)
(mal-eval value env)))
hash-map-value)
(make-mal-hash-map new-hash-table)))

View File

@ -39,7 +39,7 @@
(let ((hash-map-value (mal-data-value hash-map))
(new-hash-table (make-mal-value-hash-table)))
(genhash:hashmap (lambda (key value)
(setf (genhash:hashref (mal-eval key env) new-hash-table)
(setf (genhash:hashref key new-hash-table)
(mal-eval value env)))
hash-map-value)
(make-mal-hash-map new-hash-table)))

View File

@ -39,7 +39,7 @@
(let ((hash-map-value (mal-data-value hash-map))
(new-hash-table (make-mal-value-hash-table)))
(genhash:hashmap (lambda (key value)
(setf (genhash:hashref (mal-eval key env) new-hash-table)
(setf (genhash:hashref key new-hash-table)
(mal-eval value env)))
hash-map-value)
(make-mal-hash-map new-hash-table)))

View File

@ -39,7 +39,7 @@
(let ((hash-map-value (mal-data-value hash-map))
(new-hash-table (make-mal-value-hash-table)))
(genhash:hashmap (lambda (key value)
(setf (genhash:hashref (mal-eval key env) new-hash-table)
(setf (genhash:hashref key new-hash-table)
(mal-eval value env)))
hash-map-value)
(make-mal-hash-map new-hash-table)))

View File

@ -47,7 +47,7 @@
(let ((hash-map-value (mal-data-value hash-map))
(new-hash-table (make-mal-value-hash-table)))
(genhash:hashmap (lambda (key value)
(setf (genhash:hashref (mal-eval key env) new-hash-table)
(setf (genhash:hashref key new-hash-table)
(mal-eval value env)))
hash-map-value)
(make-mal-hash-map new-hash-table)))

View File

@ -61,7 +61,7 @@
(let ((hash-map-value (mal-data-value hash-map))
(new-hash-table (make-mal-value-hash-table)))
(genhash:hashmap (lambda (key value)
(setf (genhash:hashref (mal-eval key env) new-hash-table)
(setf (genhash:hashref key new-hash-table)
(mal-eval value env)))
hash-map-value)
(make-mal-hash-map new-hash-table)))

View File

@ -64,7 +64,7 @@
(let ((hash-map-value (mal-data-value hash-map))
(new-hash-table (make-mal-value-hash-table)))
(genhash:hashmap (lambda (key value)
(setf (genhash:hashref (mal-eval key env) new-hash-table)
(setf (genhash:hashref key new-hash-table)
(mal-eval value env)))
hash-map-value)
(make-mal-hash-map new-hash-table)))

View File

@ -63,7 +63,7 @@
(let ((hash-map-value (mal-data-value hash-map))
(new-hash-table (make-mal-value-hash-table)))
(genhash:hashmap (lambda (key value)
(setf (genhash:hashref (mal-eval key env) new-hash-table)
(setf (genhash:hashref key new-hash-table)
(mal-eval value env)))
hash-map-value)
(make-mal-hash-map new-hash-table)))

View File

@ -307,8 +307,12 @@ BUILTIN("keys")
BUILTIN("keyword")
{
CHECK_ARGS_IS(1);
ARG(malString, token);
return mal::keyword(":" + token->value());
const malValuePtr arg = *argsBegin++;
if (malKeyword* s = DYNAMIC_CAST(malKeyword, arg))
return s;
if (const malString* s = DYNAMIC_CAST(malString, arg))
return mal::keyword(":" + s->value());
MAL_FAIL("keyword expects a keyword or string");
}
BUILTIN("list")

View File

@ -162,6 +162,7 @@ namespace Mal {
a1 = ast[1];
a2 = ast[2];
res = EVAL(a2, env);
res = res.copy();
((MalFunc)res).setMacro();
env.set(((MalSymbol)a1), res);
return res;

View File

@ -162,6 +162,7 @@ namespace Mal {
a1 = ast[1];
a2 = ast[2];
res = EVAL(a2, env);
res = res.copy();
((MalFunc)res).setMacro();
env.set(((MalSymbol)a1), res);
return res;

View File

@ -162,6 +162,7 @@ namespace Mal {
a1 = ast[1];
a2 = ast[2];
res = EVAL(a2, env);
res = res.copy();
((MalFunc)res).setMacro();
env.set(((MalSymbol)a1), res);
return res;

View File

@ -42,6 +42,7 @@ static MalType mal_keyword(MalType[] a ...)
{
verify_args_count(a, 1);
auto s = verify_cast!MalString(a[0]);
if (s.is_keyword()) return s;
return new MalString("\u029e" ~ s.val);
}

View File

@ -165,6 +165,7 @@ MalType EVAL(MalType ast, Env env)
case "defmacro!":
auto a1 = verify_cast!MalSymbol(aste[1]);
auto mac = verify_cast!MalFunc(EVAL(aste[2], env));
mac = new MalFunc(mac.arg_names, mac.func_body, mac.def_env);
mac.is_macro = true;
return env.set(a1, mac);

View File

@ -165,6 +165,7 @@ MalType EVAL(MalType ast, Env env)
case "defmacro!":
auto a1 = verify_cast!MalSymbol(aste[1]);
auto mac = verify_cast!MalFunc(EVAL(aste[2], env));
mac = new MalFunc(mac.arg_names, mac.func_body, mac.def_env);
mac.is_macro = true;
return env.set(a1, mac);

View File

@ -166,6 +166,7 @@ MalType EVAL(MalType ast, Env env)
case "defmacro!":
auto a1 = verify_cast!MalSymbol(aste[1]);
auto mac = verify_cast!MalFunc(EVAL(aste[2], env));
mac = new MalFunc(mac.arg_names, mac.func_body, mac.def_env);
mac.is_macro = true;
return env.set(a1, mac);

View File

@ -1,5 +1,11 @@
(defun mal-func (ast params env fn &optional macrop meta)
(vector 'func (vector ast params env fn macrop) meta))
(defun mal-func (ast params env fn)
(vector 'func (vector ast params env fn nil) nil))
(defun mal-macro (mal-func)
(let ((v (aref mal-func 1)))
(vector 'func
(vector (aref v 0) (aref v 1) (aref v 2) (aref v 3) t)
nil)))
(defun mal-func-ast (mal-func)
(aref (aref mal-func 1) 0))

View File

@ -90,8 +90,7 @@
(setq ast (quasiquote a1))) ; TCO
(defmacro!
(let ((identifier (mal-value a1))
(value (EVAL a2 env)))
(setf (aref (aref value 1) 4) t)
(value (mal-macro (EVAL a2 env))))
(throw 'return (mal-env-set env identifier value))))
(macroexpand
(throw 'return (MACROEXPAND a1 env)))

View File

@ -90,8 +90,7 @@
(setq ast (quasiquote a1))) ; TCO
(defmacro!
(let ((identifier (mal-value a1))
(value (EVAL a2 env)))
(setf (aref (aref value 1) 4) t)
(value (mal-macro (EVAL a2 env))))
(throw 'return (mal-env-set env identifier value))))
(macroexpand
(throw 'return (MACROEXPAND a1 env)))

View File

@ -90,8 +90,7 @@
(setq ast (quasiquote a1))) ; TCO
(defmacro!
(let ((identifier (mal-value a1))
(value (EVAL a2 env)))
(setf (aref (aref value 1) 4) t)
(value (mal-macro (EVAL a2 env))))
(throw 'return (mal-env-set env identifier value))))
(macroexpand
(throw 'return (MACROEXPAND a1 env)))

View File

@ -23,7 +23,7 @@ defmodule Mix.Tasks.Step2Eval do
defp eval_ast({:map, ast, meta}, env) do
map = for {key, value} <- ast, into: %{} do
{eval(key, env), eval(value, env)}
{key, eval(value, env)}
end
{:map, map, meta}

View File

@ -27,7 +27,7 @@ defmodule Mix.Tasks.Step3Env do
defp eval_ast({:map, ast, meta}, env) do
map = for {key, value} <- ast, into: %{} do
{eval(key, env), eval(value, env)}
{key, eval(value, env)}
end
{:map, map, meta}

View File

@ -36,7 +36,7 @@ defmodule Mix.Tasks.Step4IfFnDo do
defp eval_ast({:map, ast, meta}, env) do
map = for {key, value} <- ast, into: %{} do
{eval(key, env), eval(value, env)}
{key, eval(value, env)}
end
{:map, map, meta}

View File

@ -36,7 +36,7 @@ defmodule Mix.Tasks.Step5Tco do
defp eval_ast({:map, ast, meta}, env) do
map = for {key, value} <- ast, into: %{} do
{eval(key, env), eval(value, env)}
{key, eval(value, env)}
end
{:map, map, meta}

View File

@ -59,7 +59,7 @@ defmodule Mix.Tasks.Step6File do
defp eval_ast({:map, ast, meta}, env) do
map = for {key, value} <- ast, into: %{} do
{eval(key, env), eval(value, env)}
{key, eval(value, env)}
end
{:map, map, meta}

View File

@ -59,7 +59,7 @@ defmodule Mix.Tasks.Step7Quote do
defp eval_ast({:map, ast, meta}, env) do
map = for {key, value} <- ast, into: %{} do
{eval(key, env), eval(value, env)}
{key, eval(value, env)}
end
{:map, map, meta}

View File

@ -71,7 +71,7 @@ defmodule Mix.Tasks.Step8Macros do
defp eval_ast({:map, ast, meta}, env) do
map = for {key, value} <- ast, into: %{} do
{eval(key, env), eval(value, env)}
{key, eval(value, env)}
end
{:map, map, meta}

View File

@ -71,7 +71,7 @@ defmodule Mix.Tasks.Step9Try do
defp eval_ast({:map, ast, meta}, env) do
map = for {key, value} <- ast, into: %{} do
{eval(key, env), eval(value, env)}
{key, eval(value, env)}
end
{:map, map, meta}

View File

@ -80,7 +80,7 @@ defmodule Mix.Tasks.StepAMal do
defp eval_ast({:map, ast, meta}, env) do
map = for {key, value} <- ast, into: %{} do
{eval(key, env), eval(value, env)}
{key, eval(value, env)}
end
{:map, map, meta}

View File

@ -19,7 +19,7 @@ const eval_ast = (ast, env) => {
return ast.map(x => EVAL(x, env))
} else if (ast instanceof Map) {
let new_hm = new Map()
ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env)))
ast.forEach((v, k) => new_hm.set(k, EVAL(v, env)))
return new_hm
} else {
return ast

View File

@ -16,7 +16,7 @@ const eval_ast = (ast, env) => {
return ast.map(x => EVAL(x, env))
} else if (ast instanceof Map) {
let new_hm = new Map()
ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env)))
ast.forEach((v, k) => new_hm.set(k, EVAL(v, env)))
return new_hm
} else {
return ast

View File

@ -17,7 +17,7 @@ const eval_ast = (ast, env) => {
return ast.map(x => EVAL(x, env))
} else if (ast instanceof Map) {
let new_hm = new Map()
ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env)))
ast.forEach((v, k) => new_hm.set(k, EVAL(v, env)))
return new_hm
} else {
return ast

View File

@ -17,7 +17,7 @@ const eval_ast = (ast, env) => {
return ast.map(x => EVAL(x, env))
} else if (ast instanceof Map) {
let new_hm = new Map()
ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env)))
ast.forEach((v, k) => new_hm.set(k, EVAL(v, env)))
return new_hm
} else {
return ast

View File

@ -17,7 +17,7 @@ const eval_ast = (ast, env) => {
return ast.map(x => EVAL(x, env))
} else if (ast instanceof Map) {
let new_hm = new Map()
ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env)))
ast.forEach((v, k) => new_hm.set(k, EVAL(v, env)))
return new_hm
} else {
return ast

View File

@ -40,7 +40,7 @@ const eval_ast = (ast, env) => {
return ast.map(x => EVAL(x, env))
} else if (ast instanceof Map) {
let new_hm = new Map()
ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env)))
ast.forEach((v, k) => new_hm.set(k, EVAL(v, env)))
return new_hm
} else {
return ast

View File

@ -51,7 +51,7 @@ const eval_ast = (ast, env) => {
return ast.map(x => EVAL(x, env))
} else if (ast instanceof Map) {
let new_hm = new Map()
ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env)))
ast.forEach((v, k) => new_hm.set(k, EVAL(v, env)))
return new_hm
} else {
return ast

View File

@ -51,7 +51,7 @@ const eval_ast = (ast, env) => {
return ast.map(x => EVAL(x, env))
} else if (ast instanceof Map) {
let new_hm = new Map()
ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env)))
ast.forEach((v, k) => new_hm.set(k, EVAL(v, env)))
return new_hm
} else {
return ast

View File

@ -51,7 +51,7 @@ const eval_ast = (ast, env) => {
return ast.map(x => EVAL(x, env))
} else if (ast instanceof Map) {
let new_hm = new Map()
ast.forEach((v, k) => new_hm.set(EVAL(k, env), EVAL(v, env)))
ast.forEach((v, k) => new_hm.set(k, EVAL(v, env)))
return new_hm
} else {
return ast

View File

@ -49,7 +49,7 @@ CONSTANT: ns H{
{ "symbol" [ first <malsymbol> ] }
{ "symbol?" [ first malsymbol? ] }
{ "string?" [ first string? ] }
{ "keyword" [ first <malkeyword> ] }
{ "keyword" [ first dup string? [ <malkeyword> ] when ] }
{ "keyword?" [ first malkeyword? ] }
{ "number?" [ first number? ] }
{ "fn?" [ first { [ callable? ] [ { [ malfn? ] [ macro?>> not ] } 1&& ] } 1|| ] }

View File

@ -15,9 +15,12 @@ TUPLE: malfn
{ env malenv read-only }
{ binds sequence read-only }
{ exprs read-only }
{ macro? boolean }
{ macro? boolean read-only }
{ meta assoc } ;
: malmacro ( fn -- fn )
[ env>> ] [ binds>> ] [ exprs>> ] tri t f malfn boa ;
: <malfn> ( env binds exprs -- fn )
f f malfn boa ;

View File

@ -21,7 +21,7 @@ M: object eval-ast drop ;
value env EVAL [ key env env-set ] keep ;
:: eval-defmacro! ( key value env -- maltype )
value env EVAL t >>macro? [ key env env-set ] keep ;
value env EVAL malmacro [ key env env-set ] keep ;
: eval-let* ( bindings body env -- maltype env )
[ swap 2 group ] [ new-env ] bi* [

View File

@ -21,7 +21,7 @@ M: object eval-ast drop ;
value env EVAL [ key env env-set ] keep ;
:: eval-defmacro! ( key value env -- maltype )
value env EVAL t >>macro? [ key env env-set ] keep ;
value env EVAL malmacro [ key env env-set ] keep ;
: eval-let* ( bindings body env -- maltype env )
[ swap 2 group ] [ new-env ] bi* [

View File

@ -21,7 +21,7 @@ M: object eval-ast drop ;
value env EVAL [ key env env-set ] keep ;
:: eval-defmacro! ( key value env -- maltype )
value env EVAL t >>macro? [ key env env-set ] keep ;
value env EVAL malmacro [ key env env-set ] keep ;
: eval-let* ( bindings body env -- maltype env )
[ swap 2 group ] [ new-env ] bi* [

View File

@ -157,7 +157,7 @@ Object subclass: MAL [
| result |
a1_ := ast second value.
a2 := ast third.
result := self EVAL: a2 env: env.
result := (self EVAL: a2 env: env) deepCopy.
result isMacro: true.
env set: a1_ value: result.
^result

View File

@ -157,7 +157,7 @@ Object subclass: MAL [
| result |
a1_ := ast second value.
a2 := ast third.
result := self EVAL: a2 env: env.
result := (self EVAL: a2 env: env) deepCopy.
result isMacro: true.
env set: a1_ value: result.
^result

View File

@ -157,7 +157,7 @@ Object subclass: MAL [
| result |
a1_ := ast second value.
a2 := ast third.
result := self EVAL: a2 env: env.
result := (self EVAL: a2 env: env) deepCopy.
result isMacro: true.
env set: a1_ value: result.
^result

View File

@ -52,18 +52,11 @@ func eval_ast(ast MalType, env map[string]MalType) (MalType, error) {
m := ast.(HashMap)
new_hm := HashMap{map[string]MalType{}, nil}
for k, v := range m.Val {
ke, e1 := EVAL(k, env)
if e1 != nil {
return nil, e1
}
if _, ok := ke.(string); !ok {
return nil, errors.New("non string hash-map key")
}
kv, e2 := EVAL(v, env)
if e2 != nil {
return nil, e2
}
new_hm.Val[ke.(string)] = kv
new_hm.Val[k] = kv
}
return new_hm, nil
} else {

View File

@ -48,18 +48,11 @@ func eval_ast(ast MalType, env EnvType) (MalType, error) {
m := ast.(HashMap)
new_hm := HashMap{map[string]MalType{}, nil}
for k, v := range m.Val {
ke, e1 := EVAL(k, env)
if e1 != nil {
return nil, e1
}
if _, ok := ke.(string); !ok {
return nil, errors.New("non string hash-map key")
}
kv, e2 := EVAL(v, env)
if e2 != nil {
return nil, e2
}
new_hm.Val[ke.(string)] = kv
new_hm.Val[k] = kv
}
return new_hm, nil
} else {

View File

@ -49,18 +49,11 @@ func eval_ast(ast MalType, env EnvType) (MalType, error) {
m := ast.(HashMap)
new_hm := HashMap{map[string]MalType{}, nil}
for k, v := range m.Val {
ke, e1 := EVAL(k, env)
if e1 != nil {
return nil, e1
}
if _, ok := ke.(string); !ok {
return nil, errors.New("non string hash-map key")
}
kv, e2 := EVAL(v, env)
if e2 != nil {
return nil, e2
}
new_hm.Val[ke.(string)] = kv
new_hm.Val[k] = kv
}
return new_hm, nil
} else {

View File

@ -49,18 +49,11 @@ func eval_ast(ast MalType, env EnvType) (MalType, error) {
m := ast.(HashMap)
new_hm := HashMap{map[string]MalType{}, nil}
for k, v := range m.Val {
ke, e1 := EVAL(k, env)
if e1 != nil {
return nil, e1
}
if _, ok := ke.(string); !ok {
return nil, errors.New("non string hash-map key")
}
kv, e2 := EVAL(v, env)
if e2 != nil {
return nil, e2
}
new_hm.Val[ke.(string)] = kv
new_hm.Val[k] = kv
}
return new_hm, nil
} else {

View File

@ -50,18 +50,11 @@ func eval_ast(ast MalType, env EnvType) (MalType, error) {
m := ast.(HashMap)
new_hm := HashMap{map[string]MalType{}, nil}
for k, v := range m.Val {
ke, e1 := EVAL(k, env)
if e1 != nil {
return nil, e1
}
if _, ok := ke.(string); !ok {
return nil, errors.New("non string hash-map key")
}
kv, e2 := EVAL(v, env)
if e2 != nil {
return nil, e2
}
new_hm.Val[ke.(string)] = kv
new_hm.Val[k] = kv
}
return new_hm, nil
} else {

View File

@ -95,18 +95,11 @@ func eval_ast(ast MalType, env EnvType) (MalType, error) {
m := ast.(HashMap)
new_hm := HashMap{map[string]MalType{}, nil}
for k, v := range m.Val {
ke, e1 := EVAL(k, env)
if e1 != nil {
return nil, e1
}
if _, ok := ke.(string); !ok {
return nil, errors.New("non string hash-map key")
}
kv, e2 := EVAL(v, env)
if e2 != nil {
return nil, e2
}
new_hm.Val[ke.(string)] = kv
new_hm.Val[k] = kv
}
return new_hm, nil
} else {

View File

@ -134,18 +134,11 @@ func eval_ast(ast MalType, env EnvType) (MalType, error) {
m := ast.(HashMap)
new_hm := HashMap{map[string]MalType{}, nil}
for k, v := range m.Val {
ke, e1 := EVAL(k, env)
if e1 != nil {
return nil, e1
}
if _, ok := ke.(string); !ok {
return nil, errors.New("non string hash-map key")
}
kv, e2 := EVAL(v, env)
if e2 != nil {
return nil, e2
}
new_hm.Val[ke.(string)] = kv
new_hm.Val[k] = kv
}
return new_hm, nil
} else {

View File

@ -134,18 +134,11 @@ func eval_ast(ast MalType, env EnvType) (MalType, error) {
m := ast.(HashMap)
new_hm := HashMap{map[string]MalType{}, nil}
for k, v := range m.Val {
ke, e1 := EVAL(k, env)
if e1 != nil {
return nil, e1
}
if _, ok := ke.(string); !ok {
return nil, errors.New("non string hash-map key")
}
kv, e2 := EVAL(v, env)
if e2 != nil {
return nil, e2
}
new_hm.Val[ke.(string)] = kv
new_hm.Val[k] = kv
}
return new_hm, nil
} else {

View File

@ -134,18 +134,11 @@ func eval_ast(ast MalType, env EnvType) (MalType, error) {
m := ast.(HashMap)
new_hm := HashMap{map[string]MalType{}, nil}
for k, v := range m.Val {
ke, e1 := EVAL(k, env)
if e1 != nil {
return nil, e1
}
if _, ok := ke.(string); !ok {
return nil, errors.New("non string hash-map key")
}
kv, e2 := EVAL(v, env)
if e2 != nil {
return nil, e2
}
new_hm.Val[ke.(string)] = kv
new_hm.Val[k] = kv
}
return new_hm, nil
} else {

View File

@ -22,7 +22,7 @@ eval_ast = { ast, env ->
case Map:
def new_hm = [:]
ast.each { k,v ->
new_hm[EVAL(k, env)] = EVAL(v, env)
new_hm[k] = EVAL(v, env)
}
return new_hm
default:

View File

@ -19,7 +19,7 @@ eval_ast = { ast, env ->
ast.collect { EVAL(it,env) }
case Map: def new_hm = [:]
ast.each { k,v ->
new_hm[EVAL(k, env)] = EVAL(v, env)
new_hm[k] = EVAL(v, env)
}
return new_hm
default: return ast

View File

@ -21,7 +21,7 @@ eval_ast = { ast, env ->
ast.collect { EVAL(it,env) }
case Map: def new_hm = [:]
ast.each { k,v ->
new_hm[EVAL(k, env)] = EVAL(v, env)
new_hm[k] = EVAL(v, env)
}
return new_hm
default: return ast

View File

@ -21,7 +21,7 @@ eval_ast = { ast, env ->
ast.collect { EVAL(it,env) }
case Map: def new_hm = [:]
ast.each { k,v ->
new_hm[EVAL(k, env)] = EVAL(v, env)
new_hm[k] = EVAL(v, env)
}
return new_hm
default: return ast

View File

@ -21,7 +21,7 @@ eval_ast = { ast, env ->
ast.collect { EVAL(it,env) }
case Map: def new_hm = [:]
ast.each { k,v ->
new_hm[EVAL(k, env)] = EVAL(v, env)
new_hm[k] = EVAL(v, env)
}
return new_hm
default: return ast

View File

@ -54,7 +54,7 @@ eval_ast = { ast, env ->
ast.collect { EVAL(it,env) }
case Map: def new_hm = [:]
ast.each { k,v ->
new_hm[EVAL(k, env)] = EVAL(v, env)
new_hm[k] = EVAL(v, env)
}
return new_hm
default: return ast

View File

@ -74,7 +74,7 @@ eval_ast = { ast, env ->
ast.collect { EVAL(it,env) }
case Map: def new_hm = [:]
ast.each { k,v ->
new_hm[EVAL(k, env)] = EVAL(v, env)
new_hm[k] = EVAL(v, env)
}
return new_hm
default: return ast
@ -110,6 +110,7 @@ EVAL = { ast, env ->
break // TCO
case { it instanceof MalSymbol && it.value == "defmacro!" }:
def f = EVAL(ast[2], env)
f = f.clone()
f.ismacro = true
return env.set(ast[1], f)
case { it instanceof MalSymbol && it.value == "macroexpand" }:

View File

@ -74,7 +74,7 @@ eval_ast = { ast, env ->
ast.collect { EVAL(it,env) }
case Map: def new_hm = [:]
ast.each { k,v ->
new_hm[EVAL(k, env)] = EVAL(v, env)
new_hm[k] = EVAL(v, env)
}
return new_hm
default: return ast
@ -110,6 +110,7 @@ EVAL = { ast, env ->
break // TCO
case { it instanceof MalSymbol && it.value == "defmacro!" }:
def f = EVAL(ast[2], env)
f = f.clone()
f.ismacro = true
return env.set(ast[1], f)
case { it instanceof MalSymbol && it.value == "macroexpand" }:

View File

@ -74,7 +74,7 @@ eval_ast = { ast, env ->
ast.collect { EVAL(it,env) }
case Map: def new_hm = [:]
ast.each { k,v ->
new_hm[EVAL(k, env)] = EVAL(v, env)
new_hm[k] = EVAL(v, env)
}
return new_hm
default: return ast
@ -110,6 +110,7 @@ EVAL = { ast, env ->
break // TCO
case { it instanceof MalSymbol && it.value == "defmacro!" }:
def f = EVAL(ast[2], env)
f = f.clone()
f.ismacro = true
return env.set(ast[1], f)
case { it instanceof MalSymbol && it.value == "macroexpand" }:

View File

@ -33,8 +33,9 @@
((? list? lst) (map _eval lst))
((? vector? vec) (vector-map (lambda (i x) (_eval x)) vec))
((? hash-table? ht)
(hash-for-each (lambda (k v) (hash-set! ht k (_eval v))) ht)
ht)
(define new-ht (make-hash-table))
(hash-for-each (lambda (k v) (hash-set! new-ht k (_eval v))) ht)
new-ht)
(else ast)))
(define (EVAL ast env)

View File

@ -36,9 +36,9 @@
((? list? lst) (map _eval lst))
((? vector? vec) (vector-map (lambda (i x) (_eval x)) vec))
((? hash-table? ht)
;; NOTE: we must allocate a new hashmap here to avoid any side-effects, or
;; there'll be strange bugs!!!
(list->hash-map (hash-fold (lambda (k v p) (cons k (cons (_eval v) p))) '() ht)))
(define new-ht (make-hash-table))
(hash-for-each (lambda (k v) (hash-set! new-ht k (_eval v))) ht)
new-ht)
(else ast)))
(define (EVAL ast env)

View File

@ -31,9 +31,9 @@
((? list? lst) (map _eval lst))
((? vector? vec) (vector-map (lambda (i x) (_eval x)) vec))
((? hash-table? ht)
;; NOTE: we must allocate a new hashmap here to avoid any side-effects, or
;; there'll be strange bugs!!!
(list->hash-map (hash-fold (lambda (k v p) (cons k (cons (_eval v) p))) '() ht)))
(define new-ht (make-hash-table))
(hash-for-each (lambda (k v) (hash-set! new-ht k (_eval v))) ht)
new-ht)
(else ast)))
(define (eval_seq ast env)

View File

@ -31,9 +31,9 @@
((? list? lst) (map _eval lst))
((? vector? vec) (vector-map (lambda (i x) (_eval x)) vec))
((? hash-table? ht)
;; NOTE: we must allocate a new hashmap here to avoid any side-effects, or
;; there'll be strange bugs!!!
(list->hash-map (hash-fold (lambda (k v p) (cons k (cons (_eval v) p))) '() ht)))
(define new-ht (make-hash-table))
(hash-for-each (lambda (k v) (hash-set! new-ht k (_eval v))) ht)
new-ht)
(else ast)))
(define (eval_seq ast env)

View File

@ -31,9 +31,9 @@
((? list? lst) (map _eval lst))
((? vector? vec) (vector-map (lambda (i x) (_eval x)) vec))
((? hash-table? ht)
;; NOTE: we must allocate a new hashmap here to avoid any side-effects, or
;; there'll be strange bugs!!!
(list->hash-map (hash-fold (lambda (k v p) (cons k (cons (_eval v) p))) '() ht)))
(define new-ht (make-hash-table))
(hash-for-each (lambda (k v) (hash-set! new-ht k (_eval v))) ht)
new-ht)
(else ast)))
(define (eval_seq ast env)

View File

@ -31,9 +31,9 @@
((? list? lst) (map _eval lst))
((? vector? vec) (vector-map (lambda (i x) (_eval x)) vec))
((? hash-table? ht)
;; NOTE: we must allocate a new hashmap here to avoid any side-effects, or
;; there'll be strange bugs!!!
(list->hash-map (hash-fold (lambda (k v p) (cons k (cons (_eval v) p))) '() ht)))
(define new-ht (make-hash-table))
(hash-for-each (lambda (k v) (hash-set! new-ht k (_eval v))) ht)
new-ht)
(else ast)))
(define (eval_seq ast env)

View File

@ -31,9 +31,9 @@
((? list? lst) (map _eval lst))
((? vector? vec) (vector-map (lambda (i x) (_eval x)) vec))
((? hash-table? ht)
;; NOTE: we must allocate a new hashmap here to avoid any side-effects, or
;; there'll be strange bugs!!!
(list->hash-map (hash-fold (lambda (k v p) (cons k (cons (_eval v) p))) '() ht)))
(define new-ht (make-hash-table))
(hash-for-each (lambda (k v) (hash-set! new-ht k (_eval v))) ht)
new-ht)
(else ast)))
(define (eval_seq ast env)
@ -87,8 +87,7 @@
(() ast)
(('defmacro! k v)
(let ((c (EVAL v env)))
(callable-is_macro-set! c #t)
((env 'set) k c)))
((env 'set) k (callable-as-macro c))))
(('macroexpand obj) (_macroexpand obj env))
(('quote obj) obj)
(('quasiquoteexpand obj) (_quasiquote obj))

View File

@ -40,9 +40,9 @@
((? list? lst) (map _eval lst))
((? vector? vec) (vector-map (lambda (i x) (_eval x)) vec))
((? hash-table? ht)
;; NOTE: we must allocate a new hashmap here to avoid any side-effects, or
;; there'll be strange bugs!!!
(list->hash-map (hash-fold (lambda (k v p) (cons k (cons (_eval v) p))) '() ht)))
(define new-ht (make-hash-table))
(hash-for-each (lambda (k v) (hash-set! new-ht k (_eval v))) ht)
new-ht)
(else ast)))
@ -100,8 +100,7 @@
(() ast)
(('defmacro! k v)
(let ((c (EVAL v env)))
(callable-is_macro-set! c #t)
((env 'set) k c)))
((env 'set) k (callable-as-macro c))))
(('macroexpand obj) (_macroexpand obj env))
(('quote obj) obj)
(('quasiquoteexpand obj) (_quasiquote obj))

View File

@ -40,9 +40,9 @@
((? list? lst) (map _eval lst))
((? vector? vec) (vector-map (lambda (i x) (_eval x)) vec))
((? hash-table? ht)
;; NOTE: we must allocate a new hashmap here to avoid any side-effects, or
;; there'll be strange bugs!!!
(list->hash-map (hash-fold (lambda (k v p) (cons k (cons (_eval v) p))) '() ht)))
(define new-ht (make-hash-table))
(hash-for-each (lambda (k v) (hash-set! new-ht k (_eval v))) ht)
new-ht)
(else ast)))
@ -97,8 +97,7 @@
(() ast)
(('defmacro! k v)
(let ((c (EVAL v env)))
(callable-is_macro-set! c #t)
((env 'set) k c)))
((env 'set) k (callable-as-macro c))))
(('macroexpand obj) (_macroexpand obj env))
(('quote obj) obj)
(('quasiquoteexpand obj) (_quasiquote obj))

View File

@ -20,7 +20,7 @@
cond-true? make-anonymous-func
make-atom atom? atom-val atom-val-set!
make-callable callable? callable-is_macro
callable-is_macro-set! callable-closure
callable-as-macro callable-closure
is-func is-func? is-macro is-macro? make-func callable-apply
callable-unbox-set! callable-unbox
callable-meta-info hash-table-clone
@ -81,6 +81,8 @@
(define (is-func? c) (and (is-func c) #t))
(define (is-macro c) (callable-check c #t))
(define (is-macro? c) (and (is-macro c) #t))
(define (callable-as-macro c)
(make-callable nil (callable-unbox c) #t (callable-closure c)))
(define (hash-table-clone ht)
(list->hash-map (hash-fold (lambda (k v p) (cons k (cons v p))) '() ht)))

Some files were not shown because too many files have changed in this diff Show More