Mal.Env.merge(env, Mal.Core.namespace)
bootstrap(args, env)
load_file(args, env)
- main(env)
+ loop(env)
end
defp load_file([], _env), do: nil
end
end
- def main(env) do
- IO.write(:stdio, "user> ")
- IO.read(:stdio, :line)
+ defp loop(env) do
+ Mal.Core.readline("user> ")
|> read_eval_print(env)
+ |> IO.puts
- main(env)
+ loop(env)
end
- def eval_ast(ast, env) when is_list(ast) do
+ defp eval_ast(ast, env) when is_list(ast) do
Enum.map(ast, fn elem -> eval(elem, env) end)
end
- def eval_ast({:vector, ast}, env) do
+ defp eval_ast(ast, env) when is_map(ast) do
+ for {key, value} <- ast, into: %{} do
+ {eval(key, env), eval(value, env)}
+ end
+ end
+
+ defp eval_ast({:vector, ast}, env) do
{:vector, Enum.map(ast, fn elem -> eval(elem, env) end)}
end
- def eval_ast({:symbol, symbol}, env) do
+ defp eval_ast({:symbol, symbol}, env) do
case Mal.Env.get(env, symbol) do
{:ok, value} -> value
:not_found -> throw({:error, "invalid symbol #{symbol}"})
end
end
- def eval_ast(ast, _env), do: ast
+ defp eval_ast(ast, _env), do: ast
- def read(input) do
+ defp read(input) do
Mal.Reader.read_str(input)
end
|> macroexpand(env)
end
- def macroexpand(ast, env) do
+ defp macroexpand(ast, env) do
if macro_call?(ast, env) do
do_macro_call(ast, env)
else
end
end
- def eval(ast, env) when not is_list(ast), do: eval_ast(ast, env)
- def eval(ast, env) when is_list(ast) do
+ defp eval(ast, env) when not is_list(ast), do: eval_ast(ast, env)
+ defp eval(ast, env) when is_list(ast) do
case macroexpand(ast, env) do
result when is_list(result) -> eval_list(result, env)
result -> result
end
end
- def eval_list([{:symbol, "macroexpand"}, ast], env), do: macroexpand(ast, env)
+ defp eval_list([{:symbol, "macroexpand"}, ast], env), do: macroexpand(ast, env)
- def eval_list([{:symbol, "if"}, condition, if_true | if_false], env) do
+ defp eval_list([{:symbol, "if"}, condition, if_true | if_false], env) do
result = eval(condition, env)
if result == nil or result == false do
case if_false do
end
end
- def eval_list([{:symbol, "do"} | ast], env) do
+ defp eval_list([{:symbol, "do"} | ast], env) do
eval_ast(List.delete_at(ast, -1), env)
eval(List.last(ast), env)
end
- def eval_list([{:symbol, "def!"}, {:symbol, key}, value], env) do
+ defp eval_list([{:symbol, "def!"}, {:symbol, key}, value], env) do
evaluated = eval(value, env)
Mal.Env.set(env, key, evaluated)
evaluated
end
- def eval_list([{:symbol, "defmacro!"}, {:symbol, key}, function], env) do
+ defp eval_list([{:symbol, "defmacro!"}, {:symbol, key}, function], env) do
{:closure, evaluated} = eval(function, env)
macro = {:macro, evaluated}
Mal.Env.set(env, key, macro)
macro
end
- def eval_list([{:symbol, "let*"}, bindings, body], env) do
+ defp eval_list([{:symbol, "let*"}, bindings, body], env) do
let_env = Mal.Env.initialize(env)
eval_bindings(bindings, let_env)
eval(body, let_env)
end
- def eval_list([{:symbol, "fn*"}, {:vector, params}, body], env) do
+ defp eval_list([{:symbol, "fn*"}, {:vector, params}, body], env) do
eval_list([{:symbol, "fn*"}, params, body], env)
end
- def eval_list([{:symbol, "fn*"}, params, body], env) do
+ defp eval_list([{:symbol, "fn*"}, params, body], env) do
param_symbols = for {:symbol, symbol} <- params, do: symbol
closure = fn args ->
{:closure, closure}
end
- def eval_list([{:symbol, "quote"}, arg], _env), do: arg
+ defp eval_list([{:symbol, "quote"}, arg], _env), do: arg
- def eval_list([{:symbol, "quasiquote"}, ast], env) do
+ defp eval_list([{:symbol, "quasiquote"}, ast], env) do
quasiquote(ast, env)
|> eval(env)
end
- def eval_list(ast, env) do
+ defp eval_list(ast, env) do
[func | args] = eval_ast(ast, env)
case func do
{:closure, closure} -> closure.(args)
end
end
- def print(value) do
- IO.puts(Mal.Printer.print_str(value))
+ defp print(value) do
+ Mal.Printer.print_str(value)
end
- def read_eval_print(:eof, _env), do: exit(:normal)
- def read_eval_print(line, env) do
+ defp read_eval_print(:eof, _env), do: exit(:normal)
+ defp read_eval_print(line, env) do
read(line)
|> eval(env)
|> print