3 push!(LOAD_PATH, pwd(), "/usr/share/julia/base")
18 (isa(ast, Array) || isa(ast, Tuple)) && length(ast) > 0
21 function quasiquote(ast)
24 elseif ast[1] == :unquote
26 elseif ispair(ast[1]) && ast[1][1] == symbol("splice-unquote")
27 [[:concat]; Any[ast[1][2]]; Any[quasiquote(ast[2:end])]]
29 [[:cons]; Any[quasiquote(ast[1])]; Any[quasiquote(ast[2:end])]]
33 function ismacroCall(ast, env)
34 return isa(ast, Array) &&
36 isa(ast[1], Symbol) &&
37 env_find(env, ast[1]) != nothing &&
38 isa(env_get(env, ast[1]), MalFunc) &&
39 env_get(env, ast[1]).ismacro
42 function macroexpand(ast, env)
43 while ismacroCall(ast, env)
44 mac = env_get(env, ast[1])
45 ast = mac.fn(ast[2:end]...)
50 function eval_ast(ast, env)
51 if typeof(ast) == Symbol
53 elseif isa(ast, Array) || isa(ast, Tuple)
54 map((x) -> EVAL(x,env), ast)
56 [EVAL(x[1],env) => EVAL(x[2], env) for x=ast]
62 function EVAL(ast, env)
64 #println("EVAL: $(printer.pr_str(ast,true))")
65 if !isa(ast, Array) return eval_ast(ast, env) end
68 ast = macroexpand(ast, env)
69 if !isa(ast, Array) return eval_ast(ast, env) end
70 if isempty(ast) return ast end
73 return env_set(env, ast[2], EVAL(ast[3], env))
74 elseif symbol("let*") == ast[1]
76 for i = 1:2:length(ast[2])
77 env_set(let_env, ast[2][i], EVAL(ast[2][i+1], let_env))
82 elseif :quote == ast[1]
84 elseif :quasiquote == ast[1]
85 ast = quasiquote(ast[2])
87 elseif :defmacro! == ast[1]
88 func = EVAL(ast[3], env)
90 return env_set(env, ast[2], func)
91 elseif :macroexpand == ast[1]
92 return macroexpand(ast[2], env)
94 eval_ast(ast[2:end-1], env)
98 cond = EVAL(ast[2], env)
99 if cond === nothing || cond === false
110 elseif symbol("fn*") == ast[1]
112 (args...) -> EVAL(ast[3], Env(env, ast[2], Any[args...])),
115 el = eval_ast(ast, env)
116 f, args = el[1], el[2:end]
119 env = Env(f.env, f.params, args)
136 return PRINT(EVAL(READ(str), repl_env))
139 # core.jl: defined using Julia
140 repl_env = Env(nothing, core.ns)
141 env_set(repl_env, :eval, (ast) -> EVAL(ast, repl_env))
142 env_set(repl_env, symbol("*ARGV*"), ARGS[2:end])
144 # core.mal: defined using the language itself
145 REP("(def! not (fn* (a) (if a false true)))")
146 REP("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))")
147 REP("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))")
148 REP("(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))")
152 REP("(load-file \"$(ARGS[1])\")")
157 line = readline_mod.do_readline("user> ")
158 if line === nothing break end
162 if isa(e, ErrorException)
163 println("Error: $(e.msg)")
165 println("Error: $(string(e))")
167 # TODO: show at least part of stack
168 if !isa(e, StackOverflowError)
169 bt = catch_backtrace()
170 Base.show_backtrace(STDERR, bt)