1 defmodule Mix
.Tasks
.Step4IfFnDo
do
10 {:ok
, env
} = Mal
.Env
.initialize()
11 Mal
.Env
.merge(env
, @initial_env
)
16 IO
.write(:stdio
, "user> ")
17 IO
.read(:stdio
, :line
)
18 |
> read_eval_print(env
)
23 def
eval_ast(ast
, env
) when
is_list(ast
) do
24 Enum
.map(ast
, fn elem
-> eval(elem
, env
) end)
27 def
eval_ast({:symbol
, symbol
}, env
) do
28 case Mal
.Env
.get(env
, symbol
) do
30 :not_found
-> throw({:error
, "invalid symbol #{symbol}"})
34 def
eval_ast(ast
, _env
), do: ast
37 Mal
.Reader
.read_str(input
)
40 defp
eval_bindings([], _env
), do: _env
41 defp
eval_bindings([{:symbol
, key
}, binding | tail
], env
) do
42 evaluated
= eval(binding
, env
)
43 Mal
.Env
.set(env
, key
, evaluated
)
44 eval_bindings(tail
, env
)
46 defp
eval_bindings(_bindings
, _env
), do: throw({:error
, "Unbalanced let* bindings"})
48 defp
eval_if_false([], _env
), do: nil
49 defp
eval_if_false([body
], env
), do: eval(body
, env
)
51 def
eval([{:symbol
, "if"}, condition
, if_true | if_false
], env
) do
52 result
= eval(condition
, env
)
53 if result
== nil
or result
== false
do
54 eval_if_false(if_false
, env
)
60 def
eval([{:symbol
, "do"} | ast
], env
) do
65 def
eval([{:symbol
, "def!"}, {:symbol
, key
}, value], env
) do
66 evaluated
= eval(value, env
)
67 Mal
.Env
.set(env
, key
, evaluated
)
71 def
eval([{:symbol
, "let*"}, bindings
, body
], env
) do
72 {:ok
, let_env
} = Mal
.Env
.initialize(env
)
73 eval_bindings(bindings
, let_env
)
77 def
eval(ast
, env
) when
is_list(ast
) do
78 [func | args
] = eval_ast(ast
, env
)
82 def
eval(ast
, env
), do: eval_ast(ast
, env
)
85 IO
.puts(Mal
.Printer
.print_str(value))
88 def
read_eval_print(:eof
, _env
), do: exit(0)
89 def
read_eval_print(line
, env
) do
94 {:error
, message
} -> IO
.puts("Error: #{message}")