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
*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
### 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
# 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
export ns
function concat(args...)
- res = {}
+ res = []
for a=args
- res = [res, Any[a...]]
+ res = [res; Any[a...]]
end
res
end
new_obj
end
-ns = {
+ns = Dict{Any,Any}(
symbol("=") => (a,b) -> types.equal_Q(a, b),
:throw => (a) -> throw(types.MalException(a)),
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),""),
:- => -,
symbol("*") => *,
:/ => div,
+ symbol("time-ms") => () -> round(Int, time()*1000),
:list => (a...) -> Any[a...],
symbol("list?") => (a) -> isa(a, Array),
: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),
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,
:deref => (a) -> a.val,
:reset! => (a,b) -> a.val = b,
:swap! => (a,b,c...) -> a.val = do_apply(b, a.val, c),
- }
+ )
end
module env
-export Env, set, find, get
+export Env, env_set, env_find, env_get
type Env
outer::Any
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
"[$(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,
"\\", "\\\\"),
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)
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 ')'")
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
# READ
# REPL
function REP(str)
- return PRINT(EVAL(READ(str), {}))
+ return PRINT(EVAL(READ(str), []))
end
while true
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
# REPL
function REP(str)
- return PRINT(EVAL(READ(str), {}))
+ return PRINT(EVAL(READ(str), []))
end
while true
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
end
# REPL
-repl_env = {:+ => +,
- :- => -,
- :* => *,
- :/ => div}
+repl_env = Dict{Any,Any}(:+ => +,
+ :- => -,
+ :* => *,
+ :/ => div)
function REP(str)
return PRINT(EVAL(READ(str), repl_env))
end
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
# 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)
# 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
# REPL
repl_env = Env(nothing,
- {:+ => +,
- :- => -,
- :* => *,
- :/ => div})
+ Dict{Any,Any}(:+ => +,
+ :- => -,
+ :* => *,
+ :/ => div))
function REP(str)
return PRINT(EVAL(READ(str), repl_env))
end
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
# 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)
# 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]
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
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
# 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)
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]
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
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
# 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)
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]
# 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)))")
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
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
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)
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]
# 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)))")
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
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
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
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)
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]
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]
# 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)))")
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
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
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
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)
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]
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]
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
# 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)))")
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
#!/usr/bin/env julia
+push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
import readline_mod
import reader
import printer
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
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)
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]
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]
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
# 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\")")
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
if sequential_Q(a)
tuple(a...) == tuple(b...)
- elseif isa(a,String)
+ elseif isa(a,AbstractString)
a == b
else
a === b