mirror of
https://github.com/kanaka/mal.git
synced 2024-09-11 13:55:55 +03:00
Julia: update to verion 0.4. Add time-ms.
This commit is contained in:
parent
eb76b9fbce
commit
8248463181
1
Makefile
1
Makefile
@ -41,7 +41,6 @@ EXCLUDE_TESTS += test^erlang^step5 # erlang is TCO, test passes
|
||||
EXCLUDE_TESTS += test^elixir^step5 # elixir is TCO, test passes
|
||||
EXCLUDE_TESTS += test^fsharp^step5 # completes at 10,000, fatal stack overflow at 100,000
|
||||
EXCLUDE_TESTS += test^haskell^step5 # test completes
|
||||
EXCLUDE_TESTS += test^julia^step5 # hangs test
|
||||
EXCLUDE_TESTS += test^make^step5 # no TCO capability/step
|
||||
EXCLUDE_TESTS += test^mal^step5 # no TCO capability/step
|
||||
EXCLUDE_TESTS += test^miniMAL^step5 # strange error with runtest.py
|
||||
|
@ -190,7 +190,8 @@ iex -S mix stepX_YYY
|
||||
|
||||
*The Erlang implementation was created by [Nathan Fiedler (nlfiedler)](https://github.com/nlfiedler)*
|
||||
|
||||
The Erlang implementation of mal requires [Erlang/OTP R17](http://www.erlang.org/download.html) and [rebar](https://github.com/rebar/rebar) to build.
|
||||
The Erlang implementation of mal requires [Erlang/OTP R17](http://www.erlang.org/download.html)
|
||||
and [rebar](https://github.com/rebar/rebar) to build.
|
||||
|
||||
```
|
||||
cd erlang
|
||||
@ -317,7 +318,7 @@ node stepX_YYY.js
|
||||
|
||||
### Julia
|
||||
|
||||
The Julia implementation of mal has been tested with Julia 0.3.7.
|
||||
The Julia implementation of mal requires Julia 0.4.
|
||||
|
||||
```
|
||||
cd julia
|
||||
|
@ -24,6 +24,6 @@ WORKDIR /mal
|
||||
# Julia
|
||||
RUN apt-get -y install software-properties-common
|
||||
RUN apt-add-repository -y ppa:staticfloat/juliareleases
|
||||
RUN apt-get -y update
|
||||
RUN apt-get update -y
|
||||
RUN apt-get -y install julia
|
||||
|
||||
|
@ -8,9 +8,9 @@ import readline_mod
|
||||
export ns
|
||||
|
||||
function concat(args...)
|
||||
res = {}
|
||||
res = []
|
||||
for a=args
|
||||
res = [res, Any[a...]]
|
||||
res = [res; Any[a...]]
|
||||
end
|
||||
res
|
||||
end
|
||||
@ -27,7 +27,7 @@ function with_meta(obj, meta)
|
||||
new_obj
|
||||
end
|
||||
|
||||
ns = {
|
||||
ns = Dict{Any,Any}(
|
||||
symbol("=") => (a,b) -> types.equal_Q(a, b),
|
||||
:throw => (a) -> throw(types.MalException(a)),
|
||||
|
||||
@ -37,7 +37,7 @@ ns = {
|
||||
symbol("symbol") => (a) -> symbol(a),
|
||||
symbol("symbol?") => (a) -> typeof(a) === Symbol,
|
||||
symbol("keyword") => (a) -> a[1] == '\u029e' ? a : "\u029e$(a)",
|
||||
symbol("keyword?") => (a) -> isa(a,String) && a[1] == '\u029e',
|
||||
symbol("keyword?") => (a) -> isa(a,AbstractString) && a[1] == '\u029e',
|
||||
|
||||
symbol("pr-str") => (a...) -> join(map((e)->pr_str(e, true),a)," "),
|
||||
:str => (a...) -> join(map((e)->pr_str(e, false),a),""),
|
||||
@ -55,6 +55,7 @@ ns = {
|
||||
:- => -,
|
||||
symbol("*") => *,
|
||||
:/ => div,
|
||||
symbol("time-ms") => () -> round(Int, time()*1000),
|
||||
|
||||
:list => (a...) -> Any[a...],
|
||||
symbol("list?") => (a) -> isa(a, Array),
|
||||
@ -66,11 +67,11 @@ ns = {
|
||||
:dissoc => (a, b...) -> foldl((x,y) -> delete!(x,y),copy(a), b),
|
||||
:get => (a,b) -> a === nothing ? nothing : get(a,b,nothing),
|
||||
symbol("contains?") => haskey,
|
||||
:keys => (a) -> {keys(a)...},
|
||||
:vals => (a) -> {values(a)...},
|
||||
:keys => (a) -> [keys(a)...],
|
||||
:vals => (a) -> [values(a)...],
|
||||
|
||||
symbol("sequential?") => types.sequential_Q,
|
||||
:cons => (a,b) -> [Any[a], Any[b...]],
|
||||
:cons => (a,b) -> [Any[a]; Any[b...]],
|
||||
:concat => concat,
|
||||
:nth => (a,b) -> b+1 > length(a) ? error("nth: index out of range") : a[b+1],
|
||||
:first => (a) -> isempty(a) ? nothing : first(a),
|
||||
@ -78,7 +79,7 @@ ns = {
|
||||
symbol("empty?") => isempty,
|
||||
:count => (a) -> a == nothing ? 0 : length(a),
|
||||
:apply => do_apply,
|
||||
:map => (a,b) -> isa(a,types.MalFunc) ? {map(a.fn,b)...} : {map(a,b)...},
|
||||
:map => (a,b) -> isa(a,types.MalFunc) ? [map(a.fn,b)...] : [map(a,b)...],
|
||||
|
||||
:conj => nothing,
|
||||
|
||||
@ -89,6 +90,6 @@ ns = {
|
||||
:deref => (a) -> a.val,
|
||||
:reset! => (a,b) -> a.val = b,
|
||||
:swap! => (a,b,c...) -> a.val = do_apply(b, a.val, c),
|
||||
}
|
||||
)
|
||||
|
||||
end
|
||||
|
12
julia/env.jl
12
julia/env.jl
@ -1,6 +1,6 @@
|
||||
module env
|
||||
|
||||
export Env, set, find, get
|
||||
export Env, env_set, env_find, env_get
|
||||
|
||||
type Env
|
||||
outer::Any
|
||||
@ -29,22 +29,22 @@ function Env(outer, binds, exprs)
|
||||
end
|
||||
|
||||
|
||||
function set(env::Env, k::Symbol, v)
|
||||
function env_set(env::Env, k::Symbol, v)
|
||||
env.data[k] = v
|
||||
end
|
||||
|
||||
function find(env::Env, k::Symbol)
|
||||
function env_find(env::Env, k::Symbol)
|
||||
if haskey(env.data, k)
|
||||
env
|
||||
elseif env.outer != nothing
|
||||
find(env.outer, k)
|
||||
env_find(env.outer, k)
|
||||
else
|
||||
nothing
|
||||
end
|
||||
end
|
||||
|
||||
function get(env::Env, k::Symbol)
|
||||
e = find(env, k)
|
||||
function env_get(env::Env, k::Symbol)
|
||||
e = env_find(env, k)
|
||||
if e != nothing
|
||||
e.data[k]
|
||||
else
|
||||
|
@ -12,9 +12,9 @@ function pr_str(obj, print_readably=true)
|
||||
"[$(join([pr_str(o, _r) for o=obj], " "))]"
|
||||
elseif isa(obj, Dict)
|
||||
"{$(join(["$(pr_str(o[1],_r)) $(pr_str(o[2],_r))" for o=obj], " "))}"
|
||||
elseif isa(obj, String)
|
||||
elseif isa(obj, AbstractString)
|
||||
if length(obj) > 0 && obj[1] == '\u029e'
|
||||
":$(obj[2:end])"
|
||||
":$(obj[3:end])"
|
||||
elseif _r
|
||||
str = replace(replace(replace(obj,
|
||||
"\\", "\\\\"),
|
||||
|
@ -34,7 +34,7 @@ end
|
||||
function read_atom(rdr)
|
||||
token = next(rdr)
|
||||
if ismatch(r"^-?[0-9]+$", token)
|
||||
int(token)
|
||||
parse(Int,token)
|
||||
elseif ismatch(r"^-?[0-9][0-9.]*$", token)
|
||||
float(token)
|
||||
elseif ismatch(r"^\".*\"$", token)
|
||||
@ -85,23 +85,23 @@ function read_form(rdr)
|
||||
token = peek(rdr)
|
||||
if token == "'"
|
||||
next(rdr)
|
||||
[[:quote], Any[read_form(rdr)]]
|
||||
[[:quote]; Any[read_form(rdr)]]
|
||||
elseif token == "`"
|
||||
next(rdr)
|
||||
[[:quasiquote], Any[read_form(rdr)]]
|
||||
[[:quasiquote]; Any[read_form(rdr)]]
|
||||
elseif token == "~"
|
||||
next(rdr)
|
||||
[[:unquote], Any[read_form(rdr)]]
|
||||
[[:unquote]; Any[read_form(rdr)]]
|
||||
elseif token == "~@"
|
||||
next(rdr)
|
||||
[[symbol("splice-unquote")], Any[read_form(rdr)]]
|
||||
[[symbol("splice-unquote")]; Any[read_form(rdr)]]
|
||||
elseif token == "^"
|
||||
next(rdr)
|
||||
meta = read_form(rdr)
|
||||
[[symbol("with-meta")], Any[read_form(rdr)], Any[meta]]
|
||||
[[symbol("with-meta")]; Any[read_form(rdr)]; Any[meta]]
|
||||
elseif token == "@"
|
||||
next(rdr)
|
||||
[[symbol("deref")], Any[read_form(rdr)]]
|
||||
[[symbol("deref")]; Any[read_form(rdr)]]
|
||||
|
||||
elseif token == ")"
|
||||
error("unexpected ')'")
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
|
||||
# READ
|
||||
@ -19,7 +20,7 @@ end
|
||||
|
||||
# REPL
|
||||
function REP(str)
|
||||
return PRINT(EVAL(READ(str), {}))
|
||||
return PRINT(EVAL(READ(str), []))
|
||||
end
|
||||
|
||||
while true
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -21,7 +22,7 @@ end
|
||||
|
||||
# REPL
|
||||
function REP(str)
|
||||
return PRINT(EVAL(READ(str), {}))
|
||||
return PRINT(EVAL(READ(str), []))
|
||||
end
|
||||
|
||||
while true
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -37,10 +38,10 @@ function PRINT(exp)
|
||||
end
|
||||
|
||||
# REPL
|
||||
repl_env = {:+ => +,
|
||||
:- => -,
|
||||
:* => *,
|
||||
:/ => div}
|
||||
repl_env = Dict{Any,Any}(:+ => +,
|
||||
:- => -,
|
||||
:* => *,
|
||||
:/ => div)
|
||||
function REP(str)
|
||||
return PRINT(EVAL(READ(str), repl_env))
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -13,7 +14,7 @@ end
|
||||
# EVAL
|
||||
function eval_ast(ast, env)
|
||||
if typeof(ast) == Symbol
|
||||
get(env,ast)
|
||||
env_get(env,ast)
|
||||
elseif isa(ast, Array) || isa(ast, Tuple)
|
||||
map((x) -> EVAL(x,env), ast)
|
||||
elseif isa(ast, Dict)
|
||||
@ -28,11 +29,11 @@ function EVAL(ast, env)
|
||||
|
||||
# apply
|
||||
if :def! == ast[1]
|
||||
set(env, ast[2], EVAL(ast[3], env))
|
||||
env_set(env, ast[2], EVAL(ast[3], env))
|
||||
elseif symbol("let*") == ast[1]
|
||||
let_env = Env(env)
|
||||
for i = 1:2:length(ast[2])
|
||||
set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
end
|
||||
EVAL(ast[3], let_env)
|
||||
else
|
||||
@ -49,10 +50,10 @@ end
|
||||
|
||||
# REPL
|
||||
repl_env = Env(nothing,
|
||||
{:+ => +,
|
||||
:- => -,
|
||||
:* => *,
|
||||
:/ => div})
|
||||
Dict{Any,Any}(:+ => +,
|
||||
:- => -,
|
||||
:* => *,
|
||||
:/ => div))
|
||||
function REP(str)
|
||||
return PRINT(EVAL(READ(str), repl_env))
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -14,7 +15,7 @@ end
|
||||
# EVAL
|
||||
function eval_ast(ast, env)
|
||||
if typeof(ast) == Symbol
|
||||
get(env,ast)
|
||||
env_get(env,ast)
|
||||
elseif isa(ast, Array) || isa(ast, Tuple)
|
||||
map((x) -> EVAL(x,env), ast)
|
||||
elseif isa(ast, Dict)
|
||||
@ -29,11 +30,11 @@ function EVAL(ast, env)
|
||||
|
||||
# apply
|
||||
if :def! == ast[1]
|
||||
set(env, ast[2], EVAL(ast[3], env))
|
||||
env_set(env, ast[2], EVAL(ast[3], env))
|
||||
elseif symbol("let*") == ast[1]
|
||||
let_env = Env(env)
|
||||
for i = 1:2:length(ast[2])
|
||||
set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
end
|
||||
EVAL(ast[3], let_env)
|
||||
elseif :do == ast[1]
|
||||
@ -86,8 +87,10 @@ while true
|
||||
else
|
||||
println("Error: $(string(e))")
|
||||
end
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
if !isa(e, StackOverflowError)
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
end
|
||||
println()
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -15,7 +16,7 @@ end
|
||||
# EVAL
|
||||
function eval_ast(ast, env)
|
||||
if typeof(ast) == Symbol
|
||||
get(env,ast)
|
||||
env_get(env,ast)
|
||||
elseif isa(ast, Array) || isa(ast, Tuple)
|
||||
map((x) -> EVAL(x,env), ast)
|
||||
elseif isa(ast, Dict)
|
||||
@ -27,15 +28,16 @@ end
|
||||
|
||||
function EVAL(ast, env)
|
||||
while true
|
||||
#println("EVAL: $(printer.pr_str(ast,true))")
|
||||
if !isa(ast, Array) return eval_ast(ast, env) end
|
||||
|
||||
# apply
|
||||
if :def! == ast[1]
|
||||
return set(env, ast[2], EVAL(ast[3], env))
|
||||
return env_set(env, ast[2], EVAL(ast[3], env))
|
||||
elseif symbol("let*") == ast[1]
|
||||
let_env = Env(env)
|
||||
for i = 1:2:length(ast[2])
|
||||
set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
end
|
||||
env = let_env
|
||||
ast = ast[3]
|
||||
@ -103,8 +105,11 @@ while true
|
||||
else
|
||||
println("Error: $(string(e))")
|
||||
end
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
# TODO: show at least part of stack
|
||||
if !isa(e, StackOverflowError)
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
end
|
||||
println()
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -15,7 +16,7 @@ end
|
||||
# EVAL
|
||||
function eval_ast(ast, env)
|
||||
if typeof(ast) == Symbol
|
||||
get(env,ast)
|
||||
env_get(env,ast)
|
||||
elseif isa(ast, Array) || isa(ast, Tuple)
|
||||
map((x) -> EVAL(x,env), ast)
|
||||
elseif isa(ast, Dict)
|
||||
@ -27,15 +28,16 @@ end
|
||||
|
||||
function EVAL(ast, env)
|
||||
while true
|
||||
#println("EVAL: $(printer.pr_str(ast,true))")
|
||||
if !isa(ast, Array) return eval_ast(ast, env) end
|
||||
|
||||
# apply
|
||||
if :def! == ast[1]
|
||||
return set(env, ast[2], EVAL(ast[3], env))
|
||||
return env_set(env, ast[2], EVAL(ast[3], env))
|
||||
elseif symbol("let*") == ast[1]
|
||||
let_env = Env(env)
|
||||
for i = 1:2:length(ast[2])
|
||||
set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
end
|
||||
env = let_env
|
||||
ast = ast[3]
|
||||
@ -88,8 +90,8 @@ end
|
||||
|
||||
# core.jl: defined using Julia
|
||||
repl_env = Env(nothing, core.ns)
|
||||
set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
env_set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
|
||||
# core.mal: defined using the language itself
|
||||
REP("(def! not (fn* (a) (if a false true)))")
|
||||
@ -111,8 +113,11 @@ while true
|
||||
else
|
||||
println("Error: $(string(e))")
|
||||
end
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
# TODO: show at least part of stack
|
||||
if !isa(e, StackOverflowError)
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
end
|
||||
println()
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -19,19 +20,19 @@ end
|
||||
|
||||
function quasiquote(ast)
|
||||
if !ispair(ast)
|
||||
[[:quote], Any[ast]]
|
||||
[[:quote]; Any[ast]]
|
||||
elseif ast[1] == :unquote
|
||||
ast[2]
|
||||
elseif ispair(ast[1]) && ast[1][1] == symbol("splice-unquote")
|
||||
[[:concat], Any[ast[1][2]], Any[quasiquote(ast[2:end])]]
|
||||
[[:concat]; Any[ast[1][2]]; Any[quasiquote(ast[2:end])]]
|
||||
else
|
||||
[[:cons], Any[quasiquote(ast[1])], Any[quasiquote(ast[2:end])]]
|
||||
[[:cons]; Any[quasiquote(ast[1])]; Any[quasiquote(ast[2:end])]]
|
||||
end
|
||||
end
|
||||
|
||||
function eval_ast(ast, env)
|
||||
if typeof(ast) == Symbol
|
||||
get(env,ast)
|
||||
env_get(env,ast)
|
||||
elseif isa(ast, Array) || isa(ast, Tuple)
|
||||
map((x) -> EVAL(x,env), ast)
|
||||
elseif isa(ast, Dict)
|
||||
@ -43,15 +44,16 @@ end
|
||||
|
||||
function EVAL(ast, env)
|
||||
while true
|
||||
#println("EVAL: $(printer.pr_str(ast,true))")
|
||||
if !isa(ast, Array) return eval_ast(ast, env) end
|
||||
|
||||
# apply
|
||||
if :def! == ast[1]
|
||||
return set(env, ast[2], EVAL(ast[3], env))
|
||||
return env_set(env, ast[2], EVAL(ast[3], env))
|
||||
elseif symbol("let*") == ast[1]
|
||||
let_env = Env(env)
|
||||
for i = 1:2:length(ast[2])
|
||||
set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
end
|
||||
env = let_env
|
||||
ast = ast[3]
|
||||
@ -109,8 +111,8 @@ end
|
||||
|
||||
# core.jl: defined using Julia
|
||||
repl_env = Env(nothing, core.ns)
|
||||
set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
env_set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
|
||||
# core.mal: defined using the language itself
|
||||
REP("(def! not (fn* (a) (if a false true)))")
|
||||
@ -132,8 +134,11 @@ while true
|
||||
else
|
||||
println("Error: $(string(e))")
|
||||
end
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
# TODO: show at least part of stack
|
||||
if !isa(e, StackOverflowError)
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
end
|
||||
println()
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -19,27 +20,27 @@ end
|
||||
|
||||
function quasiquote(ast)
|
||||
if !ispair(ast)
|
||||
[[:quote], Any[ast]]
|
||||
[[:quote]; Any[ast]]
|
||||
elseif ast[1] == :unquote
|
||||
ast[2]
|
||||
elseif ispair(ast[1]) && ast[1][1] == symbol("splice-unquote")
|
||||
[[:concat], Any[ast[1][2]], Any[quasiquote(ast[2:end])]]
|
||||
[[:concat]; Any[ast[1][2]]; Any[quasiquote(ast[2:end])]]
|
||||
else
|
||||
[[:cons], Any[quasiquote(ast[1])], Any[quasiquote(ast[2:end])]]
|
||||
[[:cons]; Any[quasiquote(ast[1])]; Any[quasiquote(ast[2:end])]]
|
||||
end
|
||||
end
|
||||
|
||||
function ismacroCall(ast, env)
|
||||
return isa(ast, Array) &&
|
||||
isa(ast[1], Symbol) &&
|
||||
find(env, ast[1]) != nothing &&
|
||||
isa(get(env, ast[1]), MalFunc) &&
|
||||
get(env, ast[1]).ismacro
|
||||
env_find(env, ast[1]) != nothing &&
|
||||
isa(env_get(env, ast[1]), MalFunc) &&
|
||||
env_get(env, ast[1]).ismacro
|
||||
end
|
||||
|
||||
function macroexpand(ast, env)
|
||||
while ismacroCall(ast, env)
|
||||
mac = get(env, ast[1])
|
||||
mac = env_get(env, ast[1])
|
||||
ast = mac.fn(ast[2:end]...)
|
||||
end
|
||||
ast
|
||||
@ -47,7 +48,7 @@ end
|
||||
|
||||
function eval_ast(ast, env)
|
||||
if typeof(ast) == Symbol
|
||||
get(env,ast)
|
||||
env_get(env,ast)
|
||||
elseif isa(ast, Array) || isa(ast, Tuple)
|
||||
map((x) -> EVAL(x,env), ast)
|
||||
elseif isa(ast, Dict)
|
||||
@ -67,11 +68,11 @@ function EVAL(ast, env)
|
||||
if !isa(ast, Array) return ast end
|
||||
|
||||
if :def! == ast[1]
|
||||
return set(env, ast[2], EVAL(ast[3], env))
|
||||
return env_set(env, ast[2], EVAL(ast[3], env))
|
||||
elseif symbol("let*") == ast[1]
|
||||
let_env = Env(env)
|
||||
for i = 1:2:length(ast[2])
|
||||
set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
end
|
||||
env = let_env
|
||||
ast = ast[3]
|
||||
@ -84,7 +85,7 @@ function EVAL(ast, env)
|
||||
elseif :defmacro! == ast[1]
|
||||
func = EVAL(ast[3], env)
|
||||
func.ismacro = true
|
||||
return set(env, ast[2], func)
|
||||
return env_set(env, ast[2], func)
|
||||
elseif :macroexpand == ast[1]
|
||||
return macroexpand(ast[2], env)
|
||||
elseif :do == ast[1]
|
||||
@ -135,8 +136,8 @@ end
|
||||
|
||||
# core.jl: defined using Julia
|
||||
repl_env = Env(nothing, core.ns)
|
||||
set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
env_set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
|
||||
# core.mal: defined using the language itself
|
||||
REP("(def! not (fn* (a) (if a false true)))")
|
||||
@ -161,8 +162,11 @@ while true
|
||||
else
|
||||
println("Error: $(string(e))")
|
||||
end
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
# TODO: show at least part of stack
|
||||
if !isa(e, StackOverflowError)
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
end
|
||||
println()
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -19,27 +20,27 @@ end
|
||||
|
||||
function quasiquote(ast)
|
||||
if !ispair(ast)
|
||||
[[:quote], Any[ast]]
|
||||
[[:quote]; Any[ast]]
|
||||
elseif ast[1] == :unquote
|
||||
ast[2]
|
||||
elseif ispair(ast[1]) && ast[1][1] == symbol("splice-unquote")
|
||||
[[:concat], Any[ast[1][2]], Any[quasiquote(ast[2:end])]]
|
||||
[[:concat]; Any[ast[1][2]]; Any[quasiquote(ast[2:end])]]
|
||||
else
|
||||
[[:cons], Any[quasiquote(ast[1])], Any[quasiquote(ast[2:end])]]
|
||||
[[:cons]; Any[quasiquote(ast[1])]; Any[quasiquote(ast[2:end])]]
|
||||
end
|
||||
end
|
||||
|
||||
function ismacroCall(ast, env)
|
||||
return isa(ast, Array) &&
|
||||
isa(ast[1], Symbol) &&
|
||||
find(env, ast[1]) != nothing &&
|
||||
isa(get(env, ast[1]), MalFunc) &&
|
||||
get(env, ast[1]).ismacro
|
||||
env_find(env, ast[1]) != nothing &&
|
||||
isa(env_get(env, ast[1]), MalFunc) &&
|
||||
env_get(env, ast[1]).ismacro
|
||||
end
|
||||
|
||||
function macroexpand(ast, env)
|
||||
while ismacroCall(ast, env)
|
||||
mac = get(env, ast[1])
|
||||
mac = env_get(env, ast[1])
|
||||
ast = mac.fn(ast[2:end]...)
|
||||
end
|
||||
ast
|
||||
@ -47,7 +48,7 @@ end
|
||||
|
||||
function eval_ast(ast, env)
|
||||
if typeof(ast) == Symbol
|
||||
get(env,ast)
|
||||
env_get(env,ast)
|
||||
elseif isa(ast, Array) || isa(ast, Tuple)
|
||||
map((x) -> EVAL(x,env), ast)
|
||||
elseif isa(ast, Dict)
|
||||
@ -67,11 +68,11 @@ function EVAL(ast, env)
|
||||
if !isa(ast, Array) return ast end
|
||||
|
||||
if :def! == ast[1]
|
||||
return set(env, ast[2], EVAL(ast[3], env))
|
||||
return env_set(env, ast[2], EVAL(ast[3], env))
|
||||
elseif symbol("let*") == ast[1]
|
||||
let_env = Env(env)
|
||||
for i = 1:2:length(ast[2])
|
||||
set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
end
|
||||
env = let_env
|
||||
ast = ast[3]
|
||||
@ -84,7 +85,7 @@ function EVAL(ast, env)
|
||||
elseif :defmacro! == ast[1]
|
||||
func = EVAL(ast[3], env)
|
||||
func.ismacro = true
|
||||
return set(env, ast[2], func)
|
||||
return env_set(env, ast[2], func)
|
||||
elseif :macroexpand == ast[1]
|
||||
return macroexpand(ast[2], env)
|
||||
elseif symbol("try*") == ast[1]
|
||||
@ -100,7 +101,7 @@ function EVAL(ast, env)
|
||||
e = string(e)
|
||||
end
|
||||
if length(ast) > 2 && ast[3][1] == symbol("catch*")
|
||||
return EVAL(ast[3][3], Env(env, {ast[3][2]}, {e}))
|
||||
return EVAL(ast[3][3], Env(env, Any[ast[3][2]], Any[e]))
|
||||
else
|
||||
rethrow(exc)
|
||||
end
|
||||
@ -153,8 +154,8 @@ end
|
||||
|
||||
# core.jl: defined using Julia
|
||||
repl_env = Env(nothing, core.ns)
|
||||
set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
env_set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
|
||||
# core.mal: defined using the language itself
|
||||
REP("(def! not (fn* (a) (if a false true)))")
|
||||
@ -179,8 +180,11 @@ while true
|
||||
else
|
||||
println("Error: $(string(e))")
|
||||
end
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
# TODO: show at least part of stack
|
||||
if !isa(e, StackOverflowError)
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
end
|
||||
println()
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
|
||||
push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
|
||||
import readline_mod
|
||||
import reader
|
||||
import printer
|
||||
@ -19,27 +20,27 @@ end
|
||||
|
||||
function quasiquote(ast)
|
||||
if !ispair(ast)
|
||||
[[:quote], Any[ast]]
|
||||
[[:quote]; Any[ast]]
|
||||
elseif ast[1] == :unquote
|
||||
ast[2]
|
||||
elseif ispair(ast[1]) && ast[1][1] == symbol("splice-unquote")
|
||||
[[:concat], Any[ast[1][2]], Any[quasiquote(ast[2:end])]]
|
||||
[[:concat]; Any[ast[1][2]]; Any[quasiquote(ast[2:end])]]
|
||||
else
|
||||
[[:cons], Any[quasiquote(ast[1])], Any[quasiquote(ast[2:end])]]
|
||||
[[:cons]; Any[quasiquote(ast[1])]; Any[quasiquote(ast[2:end])]]
|
||||
end
|
||||
end
|
||||
|
||||
function ismacroCall(ast, env)
|
||||
return isa(ast, Array) &&
|
||||
isa(ast[1], Symbol) &&
|
||||
find(env, ast[1]) != nothing &&
|
||||
isa(get(env, ast[1]), MalFunc) &&
|
||||
get(env, ast[1]).ismacro
|
||||
env_find(env, ast[1]) != nothing &&
|
||||
isa(env_get(env, ast[1]), MalFunc) &&
|
||||
env_get(env, ast[1]).ismacro
|
||||
end
|
||||
|
||||
function macroexpand(ast, env)
|
||||
while ismacroCall(ast, env)
|
||||
mac = get(env, ast[1])
|
||||
mac = env_get(env, ast[1])
|
||||
ast = mac.fn(ast[2:end]...)
|
||||
end
|
||||
ast
|
||||
@ -47,7 +48,7 @@ end
|
||||
|
||||
function eval_ast(ast, env)
|
||||
if typeof(ast) == Symbol
|
||||
get(env,ast)
|
||||
env_get(env,ast)
|
||||
elseif isa(ast, Array) || isa(ast, Tuple)
|
||||
map((x) -> EVAL(x,env), ast)
|
||||
elseif isa(ast, Dict)
|
||||
@ -67,11 +68,11 @@ function EVAL(ast, env)
|
||||
if !isa(ast, Array) return ast end
|
||||
|
||||
if :def! == ast[1]
|
||||
return set(env, ast[2], EVAL(ast[3], env))
|
||||
return env_set(env, ast[2], EVAL(ast[3], env))
|
||||
elseif symbol("let*") == ast[1]
|
||||
let_env = Env(env)
|
||||
for i = 1:2:length(ast[2])
|
||||
set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
|
||||
end
|
||||
env = let_env
|
||||
ast = ast[3]
|
||||
@ -84,7 +85,7 @@ function EVAL(ast, env)
|
||||
elseif :defmacro! == ast[1]
|
||||
func = EVAL(ast[3], env)
|
||||
func.ismacro = true
|
||||
return set(env, ast[2], func)
|
||||
return env_set(env, ast[2], func)
|
||||
elseif :macroexpand == ast[1]
|
||||
return macroexpand(ast[2], env)
|
||||
elseif symbol("try*") == ast[1]
|
||||
@ -100,7 +101,7 @@ function EVAL(ast, env)
|
||||
e = string(e)
|
||||
end
|
||||
if length(ast) > 2 && ast[3][1] == symbol("catch*")
|
||||
return EVAL(ast[3][3], Env(env, {ast[3][2]}, {e}))
|
||||
return EVAL(ast[3][3], Env(env, Any[ast[3][2]], Any[e]))
|
||||
else
|
||||
rethrow(exc)
|
||||
end
|
||||
@ -153,8 +154,8 @@ end
|
||||
|
||||
# core.jl: defined using Julia
|
||||
repl_env = Env(nothing, core.ns)
|
||||
set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
|
||||
env_set(repl_env, symbol("*ARGV*"), ARGS[2:end])
|
||||
|
||||
# core.mal: defined using the language itself
|
||||
REP("(def! *host-language* \"julia\")")
|
||||
@ -181,8 +182,11 @@ while true
|
||||
else
|
||||
println("Error: $(string(e))")
|
||||
end
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
# TODO: show at least part of stack
|
||||
if !isa(e, StackOverflowError)
|
||||
bt = catch_backtrace()
|
||||
Base.show_backtrace(STDERR, bt)
|
||||
end
|
||||
println()
|
||||
end
|
||||
end
|
||||
|
@ -39,7 +39,7 @@ function equal_Q(a, b)
|
||||
|
||||
if sequential_Q(a)
|
||||
tuple(a...) == tuple(b...)
|
||||
elseif isa(a,String)
|
||||
elseif isa(a,AbstractString)
|
||||
a == b
|
||||
else
|
||||
a === b
|
||||
|
Loading…
Reference in New Issue
Block a user