1 defmodule Mix
.Tasks
.Step4IfFnDo
do
3 env
= Mal
.Env
.initialize()
4 Mal
.Env
.merge(env
, Mal
.Core
.namespace
)
10 read_eval_print("(def! not (fn* (a) (if a false true)))", env
)
14 IO
.write(:stdio
, "user> ")
15 IO
.read(:stdio
, :line
)
16 |
> read_eval_print(env
)
21 def
eval_ast(ast
, env
) when
is_list(ast
) do
22 Enum
.map(ast
, fn elem
-> eval(elem
, env
) end)
25 def
eval_ast({:symbol
, symbol
}, env
) do
26 case Mal
.Env
.get(env
, symbol
) do
28 :not_found
-> throw({:error
, "invalid symbol #{symbol}"})
32 def
eval_ast(ast
, _env
), do: ast
35 Mal
.Reader
.read_str(input
)
38 defp
eval_bindings([], _env
), do: _env
39 defp
eval_bindings([{:symbol
, key
}, binding | tail
], env
) do
40 evaluated
= eval(binding
, env
)
41 Mal
.Env
.set(env
, key
, evaluated
)
42 eval_bindings(tail
, env
)
44 defp
eval_bindings(_bindings
, _env
), do: throw({:error
, "Unbalanced let* bindings"})
46 def
eval([{:symbol
, "if"}, condition
, if_true | if_false
], env
) do
47 result
= eval(condition
, env
)
48 if result
== nil
or result
== false
do
51 [body
] -> eval(body
, env
)
58 def
eval([{:symbol
, "do"} | ast
], env
) do
59 eval_ast(List
.delete_at(ast
, -1), env
)
60 eval(List
.last(ast
), env
)
63 def
eval([{:symbol
, "def!"}, {:symbol
, key
}, value], env
) do
64 evaluated
= eval(value, env
)
65 Mal
.Env
.set(env
, key
, evaluated
)
69 def
eval([{:symbol
, "let*"}, bindings
, body
], env
) do
70 let_env
= Mal
.Env
.initialize(env
)
71 eval_bindings(bindings
, let_env
)
75 def
eval([{:symbol
, "fn*"}, params
, body
], env
) do
76 param_symbols
= for {:symbol
, symbol
} <- params
, do: symbol
79 inner
= Mal
.Env
.initialize(env
, param_symbols
, args
)
86 def
eval(ast
, env
) when
is_list(ast
) do
87 [func | args
] = eval_ast(ast
, env
)
89 {:closure
, closure
} -> closure
.(args
)
94 def
eval(ast
, env
), do: eval_ast(ast
, env
)
97 IO
.puts(Mal
.Printer
.print_str(value))
100 def
read_eval_print(:eof
, _env
), do: exit(0)
101 def
read_eval_print(line
, env
) do
106 {:error
, message
} -> IO
.puts("Error: #{message}")