1
1
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:
Joel Martin 2015-10-24 15:39:13 -05:00
parent eb76b9fbce
commit 8248463181
19 changed files with 151 additions and 116 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,
"\\", "\\\\"),

View File

@ -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 ')'")

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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