diff --git a/impls/julia/Dockerfile b/impls/julia/Dockerfile index 90a9410a03..e90d279a49 100644 --- a/impls/julia/Dockerfile +++ b/impls/julia/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:vivid +FROM ubuntu:18.04 MAINTAINER Joel Martin ########################################################## @@ -22,8 +22,11 @@ WORKDIR /mal ########################################################## # Julia -RUN apt-get -y install software-properties-common -RUN apt-add-repository -y ppa:staticfloat/juliareleases -RUN apt-get update -y -RUN apt-get -y install julia - +RUN apt-get -y install wget unzip +RUN \ + mkdir -p /opt && cd /opt && \ + wget https://julialang-s3.julialang.org/bin/linux/x64/1.4/julia-1.4.1-linux-x86_64.tar.gz && \ + tar zxpf julia-1.4.1-linux-x86_64.tar.gz && \ + ln -s /opt/julia-1.4.1/bin/julia /usr/bin/julia + +ENV HOME /mal \ No newline at end of file diff --git a/impls/julia/core.jl b/impls/julia/core.jl index 680d25fd7c..64bb0e8950 100644 --- a/impls/julia/core.jl +++ b/impls/julia/core.jl @@ -68,26 +68,26 @@ function with_meta(obj, meta) end ns = Dict{Any,Any}( - symbol("=") => (a,b) -> types.equal_Q(a, b), + Symbol("=") => (a,b) -> types.equal_Q(a, b), :throw => (a) -> throw(types.MalException(a)), - symbol("nil?") => (a) -> a === nothing, - symbol("true?") => (a) -> a === true, - symbol("false?") => (a) -> a === false, - symbol("string?") => string_Q, - symbol("symbol") => (a) -> symbol(a), - symbol("symbol?") => (a) -> typeof(a) === Symbol, - symbol("keyword") => (a) -> a[1] == '\u029e' ? a : "\u029e$(a)", - symbol("keyword?") => keyword_Q, - symbol("number?") => (a) -> isa(a, AbstractFloat) || isa(a, Int64), - symbol("fn?") => (a) -> isa(a, Function) || (isa(a, types.MalFunc) && !a.ismacro), - symbol("macro?") => (a) -> isa(a, types.MalFunc) && a.ismacro, - - symbol("pr-str") => (a...) -> join(map((e)->pr_str(e, true),a)," "), + Symbol("nil?") => (a) -> a === nothing, + Symbol("true?") => (a) -> a === true, + Symbol("false?") => (a) -> a === false, + Symbol("string?") => string_Q, + Symbol("Symbol") => (a) -> Symbol(a), + Symbol("Symbol?") => (a) -> typeof(a) === Symbol, + Symbol("keyword") => (a) -> a[1] == '\u029e' ? a : "\u029e$(a)", + Symbol("keyword?") => keyword_Q, + Symbol("number?") => (a) -> isa(a, AbstractFloat) || isa(a, Int64), + Symbol("fn?") => (a) -> isa(a, Function) || (isa(a, types.MalFunc) && !a.ismacro), + Symbol("macro?") => (a) -> isa(a, types.MalFunc) && a.ismacro, + + Symbol("pr-str") => (a...) -> join(map((e)->pr_str(e, true),a)," "), :str => (a...) -> join(map((e)->pr_str(e, false),a),""), :prn => (a...) -> println(join(map((e)->pr_str(e, true),a)," ")), :println => (a...) -> println(join(map((e)->pr_str(e, false),a)," ")), - symbol("read-string") => (a) -> reader.read_str(a), + Symbol("read-string") => (a) -> reader.read_str(a), :readline => readline_mod.do_readline, :slurp => (a) -> readall(open(a)), @@ -97,30 +97,30 @@ ns = Dict{Any,Any}( :>= => >=, :+ => +, :- => -, - symbol("*") => *, + Symbol("*") => *, :/ => div, - symbol("time-ms") => () -> round(Int, time()*1000), + Symbol("time-ms") => () -> round(Int, time()*1000), :list => (a...) -> Any[a...], - symbol("list?") => (a) -> isa(a, Array), + Symbol("list?") => (a) -> isa(a, Array), :vector => (a...) -> tuple(a...), - symbol("vector?") => (a) -> isa(a, Tuple), - symbol("hash-map") => types.hash_map, - symbol("map?") => (a) -> isa(a, Dict), + Symbol("vector?") => (a) -> isa(a, Tuple), + Symbol("hash-map") => types.hash_map, + Symbol("map?") => (a) -> isa(a, Dict), :assoc => (a, b...) -> merge(a, types.hash_map(b...)), :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, + Symbol("contains?") => haskey, :keys => (a) -> [keys(a)...], :vals => (a) -> [values(a)...], - symbol("sequential?") => types.sequential_Q, + Symbol("sequential?") => types.sequential_Q, :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) -> a === nothing || isempty(a) ? nothing : first(a), :rest => (a) -> a === nothing ? Any[] : Any[a[2:end]...], - symbol("empty?") => isempty, + Symbol("empty?") => isempty, :count => (a) -> a == nothing ? 0 : length(a), :apply => do_apply, :map => do_map, @@ -129,9 +129,9 @@ ns = Dict{Any,Any}( :seq => do_seq, :meta => (a) -> isa(a,types.MalFunc) ? a.meta : nothing, - symbol("with-meta") => with_meta, + Symbol("with-meta") => with_meta, :atom => (a) -> types.Atom(a), - symbol("atom?") => (a) -> isa(a,types.Atom), + Symbol("atom?") => (a) -> isa(a,types.Atom), :deref => (a) -> a.val, :reset! => (a,b) -> a.val = b, :swap! => (a,b,c...) -> a.val = do_apply(b, a.val, c), diff --git a/impls/julia/env.jl b/impls/julia/env.jl index 2451b51fa9..f1274f4f55 100644 --- a/impls/julia/env.jl +++ b/impls/julia/env.jl @@ -2,7 +2,7 @@ module env export Env, env_set, env_find, env_get -type Env +struct Env outer::Any data::Dict{Symbol,Any} end diff --git a/impls/julia/printer.jl b/impls/julia/printer.jl index 44e0b1e850..dbd2d04c22 100644 --- a/impls/julia/printer.jl +++ b/impls/julia/printer.jl @@ -17,9 +17,9 @@ function pr_str(obj, print_readably=true) ":$(obj[3:end])" elseif _r str = replace(replace(replace(obj, - "\\", "\\\\"), - "\"", "\\\""), - "\n", "\\n") + "\\" => "\\\\"), + "\"" => "\\\""), + "\n" => "\\n") "\"$(str)\"" else obj diff --git a/impls/julia/reader.jl b/impls/julia/reader.jl index 2a46cc4f57..07380938de 100644 --- a/impls/julia/reader.jl +++ b/impls/julia/reader.jl @@ -4,7 +4,7 @@ export read_str import types -type Reader +mutable struct Reader tokens position::Int64 end @@ -33,15 +33,15 @@ end function read_atom(rdr) token = next(rdr) - if ismatch(r"^-?[0-9]+$", token) + if match(r"^-?[0-9]+$", token) !== nothing parse(Int,token) - elseif ismatch(r"^-?[0-9][0-9.]*$", token) + elseif match(r"^-?[0-9][0-9.]*$", token) !== nothing float(token) - elseif ismatch(r"^\"(?:\\.|[^\\\"])*\"$", token) - replace(token[2:end-1], r"\\.", (r) -> get(Dict("\\n"=>"\n", + elseif match(r"^\"(?:\\.|[^\\\"])*\"$", token) !== nothing + replace(token[2:end-1], r"\\." => (r) -> get(Dict("\\n"=>"\n", "\\\""=>"\"", "\\\\"=>"\\"), r, r)) - elseif ismatch(r"^\".*$", token) + elseif match(r"^\".*$", token) !== nothing error("expected '\"', got EOF") elseif token[1] == ':' "\u029e$(token[2:end])" @@ -52,7 +52,7 @@ function read_atom(rdr) elseif token == "false" false else - symbol(token) + Symbol(token) end end @@ -95,14 +95,14 @@ function 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 ')'") diff --git a/impls/julia/readline_mod.jl b/impls/julia/readline_mod.jl index 94c47f762f..308021dc7e 100644 --- a/impls/julia/readline_mod.jl +++ b/impls/julia/readline_mod.jl @@ -4,8 +4,8 @@ export do_readline function do_readline(prompt) print(prompt) - flush(STDOUT) - line = readline(STDIN) + flush(stdout) + line = readline(stdin) if line == "" return nothing end diff --git a/impls/julia/step1_read_print.jl b/impls/julia/step1_read_print.jl index 604b1f9c3d..dd1b40e41d 100755 --- a/impls/julia/step1_read_print.jl +++ b/impls/julia/step1_read_print.jl @@ -37,7 +37,7 @@ while true println("Error: $(string(e))") end bt = catch_backtrace() - Base.show_backtrace(STDERR, bt) + Base.show_backtrace(stderr, bt) println() end end diff --git a/impls/julia/step3_env.jl b/impls/julia/step3_env.jl index 91f80ca25c..7958b8a866 100755 --- a/impls/julia/step3_env.jl +++ b/impls/julia/step3_env.jl @@ -31,7 +31,7 @@ function EVAL(ast, env) # apply if :def! == ast[1] env_set(env, ast[2], EVAL(ast[3], env)) - elseif symbol("let*") == ast[1] + elseif Symbol("let*") == ast[1] let_env = Env(env) for i = 1:2:length(ast[2]) env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env)) diff --git a/impls/julia/step4_if_fn_do.jl b/impls/julia/step4_if_fn_do.jl index 0e33713e31..381ebae9e8 100755 --- a/impls/julia/step4_if_fn_do.jl +++ b/impls/julia/step4_if_fn_do.jl @@ -32,7 +32,7 @@ function EVAL(ast, env) # apply if :def! == ast[1] env_set(env, ast[2], EVAL(ast[3], env)) - elseif symbol("let*") == ast[1] + elseif Symbol("let*") == ast[1] let_env = Env(env) for i = 1:2:length(ast[2]) env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env)) @@ -51,7 +51,7 @@ function EVAL(ast, env) else EVAL(ast[3], env) end - elseif symbol("fn*") == ast[1] + elseif Symbol("fn*") == ast[1] (args...) -> EVAL(ast[3], Env(env, ast[2], Any[args...])) else el = eval_ast(ast, env) diff --git a/impls/julia/step5_tco.jl b/impls/julia/step5_tco.jl index 6869048cda..669f9c77df 100755 --- a/impls/julia/step5_tco.jl +++ b/impls/julia/step5_tco.jl @@ -35,7 +35,7 @@ function EVAL(ast, env) # apply if :def! == ast[1] return env_set(env, ast[2], EVAL(ast[3], env)) - elseif symbol("let*") == ast[1] + elseif Symbol("let*") == ast[1] let_env = Env(env) for i = 1:2:length(ast[2]) env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env)) @@ -60,7 +60,7 @@ function EVAL(ast, env) ast = ast[3] # TCO loop end - elseif symbol("fn*") == ast[1] + elseif Symbol("fn*") == ast[1] return MalFunc( (args...) -> EVAL(ast[3], Env(env, ast[2], Any[args...])), ast[3], env, ast[2]) diff --git a/impls/julia/step6_file.jl b/impls/julia/step6_file.jl index 5d251dd7bd..27949825cf 100755 --- a/impls/julia/step6_file.jl +++ b/impls/julia/step6_file.jl @@ -35,7 +35,7 @@ function EVAL(ast, env) # apply if :def! == ast[1] return env_set(env, ast[2], EVAL(ast[3], env)) - elseif symbol("let*") == ast[1] + elseif Symbol("let*") == ast[1] let_env = Env(env) for i = 1:2:length(ast[2]) env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env)) @@ -60,7 +60,7 @@ function EVAL(ast, env) ast = ast[3] # TCO loop end - elseif symbol("fn*") == ast[1] + elseif Symbol("fn*") == ast[1] return MalFunc( (args...) -> EVAL(ast[3], Env(env, ast[2], Any[args...])), ast[3], env, ast[2]) @@ -92,7 +92,7 @@ end # core.jl: defined using Julia repl_env = Env(nothing, core.ns) env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env)) -env_set(repl_env, symbol("*ARGV*"), ARGS[2:end]) +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)))") diff --git a/impls/julia/step7_quote.jl b/impls/julia/step7_quote.jl index 91395bc2fc..06d7bd8f44 100755 --- a/impls/julia/step7_quote.jl +++ b/impls/julia/step7_quote.jl @@ -23,7 +23,7 @@ function quasiquote(ast) [[:quote]; Any[ast]] elseif ast[1] == :unquote ast[2] - elseif ispair(ast[1]) && ast[1][1] == symbol("splice-unquote") + elseif ispair(ast[1]) && ast[1][1] == Symbol("splice-unquote") [[:concat]; Any[ast[1][2]]; Any[quasiquote(ast[2:end])]] else [[:cons]; Any[quasiquote(ast[1])]; Any[quasiquote(ast[2:end])]] @@ -51,7 +51,7 @@ function EVAL(ast, env) # apply if :def! == ast[1] return env_set(env, ast[2], EVAL(ast[3], env)) - elseif symbol("let*") == ast[1] + elseif Symbol("let*") == ast[1] let_env = Env(env) for i = 1:2:length(ast[2]) env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env)) @@ -81,7 +81,7 @@ function EVAL(ast, env) ast = ast[3] # TCO loop end - elseif symbol("fn*") == ast[1] + elseif Symbol("fn*") == ast[1] return MalFunc( (args...) -> EVAL(ast[3], Env(env, ast[2], Any[args...])), ast[3], env, ast[2]) @@ -113,7 +113,7 @@ end # core.jl: defined using Julia repl_env = Env(nothing, core.ns) env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env)) -env_set(repl_env, symbol("*ARGV*"), ARGS[2:end]) +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)))") diff --git a/impls/julia/step8_macros.jl b/impls/julia/step8_macros.jl index 7ca18bde5a..a0cb7c1326 100755 --- a/impls/julia/step8_macros.jl +++ b/impls/julia/step8_macros.jl @@ -23,7 +23,7 @@ function quasiquote(ast) [[:quote]; Any[ast]] elseif ast[1] == :unquote ast[2] - elseif ispair(ast[1]) && ast[1][1] == symbol("splice-unquote") + elseif ispair(ast[1]) && ast[1][1] == Symbol("splice-unquote") [[:concat]; Any[ast[1][2]]; Any[quasiquote(ast[2:end])]] else [[:cons]; Any[quasiquote(ast[1])]; Any[quasiquote(ast[2:end])]] @@ -71,7 +71,7 @@ function EVAL(ast, env) if :def! == ast[1] return env_set(env, ast[2], EVAL(ast[3], env)) - elseif symbol("let*") == ast[1] + elseif Symbol("let*") == ast[1] let_env = Env(env) for i = 1:2:length(ast[2]) env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env)) @@ -107,7 +107,7 @@ function EVAL(ast, env) ast = ast[3] # TCO loop end - elseif symbol("fn*") == ast[1] + elseif Symbol("fn*") == ast[1] return MalFunc( (args...) -> EVAL(ast[3], Env(env, ast[2], Any[args...])), ast[3], env, ast[2]) @@ -139,7 +139,7 @@ end # core.jl: defined using Julia repl_env = Env(nothing, core.ns) env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env)) -env_set(repl_env, symbol("*ARGV*"), ARGS[2:end]) +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)))") diff --git a/impls/julia/step9_try.jl b/impls/julia/step9_try.jl index 26459b26f7..c2fe8eacc8 100755 --- a/impls/julia/step9_try.jl +++ b/impls/julia/step9_try.jl @@ -23,7 +23,7 @@ function quasiquote(ast) [[:quote]; Any[ast]] elseif ast[1] == :unquote ast[2] - elseif ispair(ast[1]) && ast[1][1] == symbol("splice-unquote") + elseif ispair(ast[1]) && ast[1][1] == Symbol("splice-unquote") [[:concat]; Any[ast[1][2]]; Any[quasiquote(ast[2:end])]] else [[:cons]; Any[quasiquote(ast[1])]; Any[quasiquote(ast[2:end])]] @@ -71,7 +71,7 @@ function EVAL(ast, env) if :def! == ast[1] return env_set(env, ast[2], EVAL(ast[3], env)) - elseif symbol("let*") == ast[1] + elseif Symbol("let*") == ast[1] let_env = Env(env) for i = 1:2:length(ast[2]) env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env)) @@ -90,7 +90,7 @@ function EVAL(ast, env) return env_set(env, ast[2], func) elseif :macroexpand == ast[1] return macroexpand(ast[2], env) - elseif symbol("try*") == ast[1] + elseif Symbol("try*") == ast[1] try return EVAL(ast[2], env) catch exc @@ -102,7 +102,7 @@ function EVAL(ast, env) else e = string(e) end - if length(ast) > 2 && ast[3][1] == symbol("catch*") + if length(ast) > 2 && ast[3][1] == Symbol("catch*") return EVAL(ast[3][3], Env(env, Any[ast[3][2]], Any[e])) else rethrow(exc) @@ -125,7 +125,7 @@ function EVAL(ast, env) ast = ast[3] # TCO loop end - elseif symbol("fn*") == ast[1] + elseif Symbol("fn*") == ast[1] return MalFunc( (args...) -> EVAL(ast[3], Env(env, ast[2], Any[args...])), ast[3], env, ast[2]) @@ -157,7 +157,7 @@ end # core.jl: defined using Julia repl_env = Env(nothing, core.ns) env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env)) -env_set(repl_env, symbol("*ARGV*"), ARGS[2:end]) +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)))") diff --git a/impls/julia/stepA_mal.jl b/impls/julia/stepA_mal.jl index 629c698036..8f717d42de 100755 --- a/impls/julia/stepA_mal.jl +++ b/impls/julia/stepA_mal.jl @@ -23,7 +23,7 @@ function quasiquote(ast) [[:quote]; Any[ast]] elseif ast[1] == :unquote ast[2] - elseif ispair(ast[1]) && ast[1][1] == symbol("splice-unquote") + elseif ispair(ast[1]) && ast[1][1] == Symbol("splice-unquote") [[:concat]; Any[ast[1][2]]; Any[quasiquote(ast[2:end])]] else [[:cons]; Any[quasiquote(ast[1])]; Any[quasiquote(ast[2:end])]] @@ -71,7 +71,7 @@ function EVAL(ast, env) if :def! == ast[1] return env_set(env, ast[2], EVAL(ast[3], env)) - elseif symbol("let*") == ast[1] + elseif Symbol("let*") == ast[1] let_env = Env(env) for i = 1:2:length(ast[2]) env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env)) @@ -90,7 +90,7 @@ function EVAL(ast, env) return env_set(env, ast[2], func) elseif :macroexpand == ast[1] return macroexpand(ast[2], env) - elseif symbol("try*") == ast[1] + elseif Symbol("try*") == ast[1] try return EVAL(ast[2], env) catch exc @@ -102,7 +102,7 @@ function EVAL(ast, env) else e = string(e) end - if length(ast) > 2 && ast[3][1] == symbol("catch*") + if length(ast) > 2 && ast[3][1] == Symbol("catch*") return EVAL(ast[3][3], Env(env, Any[ast[3][2]], Any[e])) else rethrow(exc) @@ -125,7 +125,7 @@ function EVAL(ast, env) ast = ast[3] # TCO loop end - elseif symbol("fn*") == ast[1] + elseif Symbol("fn*") == ast[1] return MalFunc( (args...) -> EVAL(ast[3], Env(env, ast[2], Any[args...])), ast[3], env, ast[2]) @@ -157,7 +157,7 @@ end # core.jl: defined using Julia repl_env = Env(nothing, core.ns) env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env)) -env_set(repl_env, symbol("*ARGV*"), ARGS[2:end]) +env_set(repl_env, Symbol("*ARGV*"), ARGS[2:end]) # core.mal: defined using the language itself REP("(def! *host-language* \"julia\")") @@ -186,7 +186,7 @@ while true # TODO: show at least part of stack if !isa(e, StackOverflowError) bt = catch_backtrace() - Base.show_backtrace(STDERR, bt) + Base.show_backtrace(stderr, bt) end println() end diff --git a/impls/julia/types.jl b/impls/julia/types.jl index ba735784fa..d27247bccd 100644 --- a/impls/julia/types.jl +++ b/impls/julia/types.jl @@ -4,11 +4,11 @@ export MalException, MalFunc, sequential_Q, equal_Q, hash_map, Atom import Base.copy -type MalException <: Exception +struct MalException <: Exception malval end -type MalFunc +mutable struct MalFunc fn::Function ast env @@ -72,10 +72,8 @@ function hash_map(lst...) hm end -type Atom +struct Atom val end end - -