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:
commit
c7d437c6d2
@ -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}
|
||||
|
@ -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))
|
||||
|
35
README.md
35
README.md
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 ;;
|
||||
|
@ -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 ;;
|
||||
|
@ -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 ;;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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)))
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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|| ] }
|
||||
|
@ -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 ;
|
||||
|
||||
|
@ -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* [
|
||||
|
@ -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* [
|
||||
|
@ -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* [
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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" }:
|
||||
|
@ -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" }:
|
||||
|
@ -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" }:
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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))
|
||||
|
@ -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))
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user