Change quasiquote algorithm
[jackhill/mal.git] / impls / ada / envs.adb
CommitLineData
09c532ba 1with Ada.Text_IO;
13ce1681 2with Types;
9a6f4925
CM
3with Unchecked_Deallocation;
4
5package body Envs is
6
7
13ce1681
CM
8 function Is_Null (E : Env_Handle) return Boolean is
9 use Smart_Pointers;
10 begin
b5bad5ea 11 return E = Null_Env_Handle;
13ce1681
CM
12 end Is_Null;
13
14
b5bad5ea 15 function New_Env (Outer : Env_Handle := Null_Env_Handle) return Env_Handle is
13ce1681
CM
16 use Smart_Pointers;
17 Level : Natural;
18 begin
19 if Is_Null (Outer) then
20 Level := 0;
21 else
22 Level := Deref (Outer).Level + 1;
23 end if;
24 if Debug then
25 Ada.Text_IO.Put_Line
26 ("Envs: Creating at level " & Natural'Image (Level));
27 end if;
28 return Env_Handle (Smart_Pointers.New_Ptr (new Env'
29 (Base_Class with The_Map => String_Mal_Hash.Empty_Map,
30 Outer_Env => Outer,
31 Level => Level)));
32 end New_Env;
33
34
35 procedure Set
36 (E : Env_Handle;
37 Key : String;
38 Elem : Smart_Pointers.Smart_Pointer) is
39 begin
40 if Debug then
41 Ada.Text_IO.Put_Line
42 ("Envs: Setting " & Key &
43 " to " & Types.Deref (Elem).To_String &
44 " at level " & Natural'Image (Deref (E).Level));
45 end if;
9a6f4925 46 String_Mal_Hash.Include
13ce1681 47 (Container => Deref (E).The_Map,
9a6f4925 48 Key => Ada.Strings.Unbounded.To_Unbounded_String (Key),
13ce1681 49 New_Item => Elem);
c4b822cd 50 end Set;
9a6f4925 51
09c532ba 52
13ce1681
CM
53 function Get (E : Env_Handle; Key: String)
54 return Smart_Pointers.Smart_Pointer is
55
56 use String_Mal_Hash;
57 C : Cursor;
09c532ba 58
13ce1681
CM
59 begin
60
61 if Debug then
62 Ada.Text_IO.Put_Line
63 ("Envs: Finding " & Key &
64 " at level " & Natural'Image (Deref (E).Level));
65 end if;
09c532ba 66
13ce1681
CM
67 C := Find (Deref (E).The_Map,
68 Ada.Strings.Unbounded.To_Unbounded_String (Key));
09c532ba 69
13ce1681
CM
70 if C = No_Element then
71
72 if Is_Null (Deref (E).Outer_Env) then
73 raise Not_Found;
09c532ba 74 else
13ce1681 75 return Get (Deref (E).Outer_Env, Key);
09c532ba
CM
76 end if;
77
13ce1681
CM
78 else
79 return Element (C);
80 end if;
09c532ba 81
c4b822cd 82 end Get;
9a6f4925
CM
83
84
efaad1ce
CM
85 procedure Set_Outer
86 (E : Env_Handle; Outer_Env : Env_Handle) is
87 begin
88 -- Attempt to avoid making loops.
89 if Deref (E).Level /= 0 then
90 Deref (E).Outer_Env := Outer_Env;
91 end if;
92 end Set_Outer;
93
94
95 function To_String (E : Env_Handle) return String is
96 use String_Mal_Hash, Ada.Strings.Unbounded;
97 C : Cursor;
98 Res : Unbounded_String;
99 begin
100 C := First (Deref (E).The_Map);
101 while C /= No_Element loop
102 Append (Res, Key (C) & " => " & Types.To_String (Types.Deref (Element (C)).all) & ", ");
103 C := Next (C);
104 end loop;
105 return To_String (Res);
106 end To_String;
107
108
13ce1681 109 -- Sym and Exprs are lists. Bind Sets Keys in Syms to the corresponding
c3244bcf 110 -- expression in Exprs. Returns true if all the parameters were bound.
b5bad5ea 111 function Bind (Env : Env_Handle; Syms, Exprs : Types.List_Mal_Type)
c3244bcf 112 return Boolean is
13ce1681
CM
113 use Types;
114 S, Expr : List_Mal_Type;
51fa7633 115 First_Sym : Sym_Ptr;
13ce1681
CM
116 begin
117 S := Syms;
118 Expr := Exprs;
a90ea3c7 119 while not Is_Null (S) loop
c3244bcf 120
51fa7633 121 First_Sym := Deref_Sym (Car (S));
c3244bcf 122
51fa7633 123 if First_Sym.Get_Sym = "&" then
a90ea3c7 124 S := Deref_List (Cdr (S)).all;
51fa7633 125 First_Sym := Deref_Sym (Car (S));
b5bad5ea 126 Set (Env, First_Sym.Get_Sym, New_List_Mal_Type (Expr));
c3244bcf 127 return True;
a90ea3c7 128 end if;
c3244bcf 129
b5bad5ea 130 Set (Env, First_Sym.Get_Sym, Car (Expr));
13ce1681 131 S := Deref_List (Cdr (S)).all;
a90ea3c7 132 exit when Is_Null (Expr);
13ce1681 133 Expr := Deref_List (Cdr (Expr)).all;
c3244bcf 134
13ce1681 135 end loop;
c3244bcf 136 return Is_Null (S);
13ce1681
CM
137 end Bind;
138
139
13ce1681
CM
140 function Deref (SP : Env_Handle) return Env_Ptr is
141 begin
142 return Env_Ptr (Smart_Pointers.Deref (Smart_Pointers.Smart_Pointer (SP)));
143 end Deref;
144
145
9a6f4925 146end Envs;