Support multiple let* binding clauses
[jackhill/mal.git] / elixir / lib / mal / env.ex
1 defmodule Mal.Env do
2 def initialize(outer \\ nil) do
3 Agent.start_link(fn ->
4 %{outer: outer, env: %{}}
5 end)
6 end
7
8 def set(pid, key, value) do
9 Agent.update(pid, fn map ->
10 %{map | :env => Map.put(map.env, key, value)}
11 end)
12 end
13
14 def merge(pid, env_values) do
15 Agent.update(pid, fn map ->
16 %{map | :env => Map.merge(map.env, env_values)}
17 end)
18 end
19
20 def find(pid, key) do
21 Agent.get(pid, fn map ->
22 case Map.has_key?(map.env, key) do
23 true -> pid
24 false -> map.outer && find(map.outer, key)
25 end
26 end)
27 end
28
29 def retrieve_key(pid, key) do
30 Agent.get(pid, fn map ->
31 case Map.fetch(map.env, key) do
32 {:ok, value} -> {:ok, value}
33 :error -> :not_found
34 end
35 end)
36 end
37
38 def get(pid, key) do
39 case find(pid, key) do
40 nil -> :not_found
41 env -> retrieve_key(env, key)
42 end
43 end
44 end