def macro_call?(ast, env)
list = ast.unwrap
return false unless list.is_a? Mal::List
+ return false if list.empty?
sym = list.first.unwrap
return false unless sym.is_a? Mal::Symbol
# 'next' in 'do...end' has a bug in crystal 0.7.1
# https://github.com/manastech/crystal/issues/659
while true
- return eval_ast(ast, env) unless ast.unwrap.is_a? Mal::List
+ list = ast.unwrap
+
+ return eval_ast(ast, env) unless list.is_a? Mal::List
+ return ast if list.empty?
ast = macroexpand(ast, env)
when "macroexpand"
macroexpand(list[1], env)
when "try*"
- catch_list = list[2].unwrap
+ catch_list = list.size >= 3 ? list[2].unwrap : Mal::Type.new(nil)
return eval(list[1], env) unless catch_list.is_a? Mal::List
catch_head = catch_list.first.unwrap
Mal.rep "(def! not (fn* (a) (if a false true)))"
Mal.rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))"
Mal.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)))))))"
-Mal.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))))))))"
argv = Mal::List.new
REPL_ENV.set("*ARGV*", Mal::Type.new argv)
while line = Readline.readline("user> ", true)
begin
puts Mal.rep(line)
+ rescue e : Mal::RuntimeException
+ STDERR.puts "Error: #{pr_str(e.thrown, true)}"
rescue e
- STDERR.puts e
+ STDERR.puts "Error: #{e}"
end
end