DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / ada / step2_eval.adb
CommitLineData
988812a6
CM
1with Ada.Containers.Hashed_Maps;
2with Ada.Strings.Unbounded.Hash;
9a6f4925 3with Ada.Text_IO;
6d91af72 4with Ada.Exceptions;
9a6f4925
CM
5with Printer;
6with Reader;
18e21187 7with Smart_Pointers;
9a6f4925
CM
8with Types;
9
10procedure Step2_Eval is
11
18e21187
CM
12 use Types;
13
988812a6
CM
14 -- primitive functions on Smart_Pointer,
15 function "+" is new Arith_Op ("+", "+");
16 function "-" is new Arith_Op ("-", "-");
17 function "*" is new Arith_Op ("*", "*");
18 function "/" is new Arith_Op ("/", "/");
19
20 -- Take a list with two parameters and produce a single result
21 -- using the Op access-to-function parameter.
22 function Reduce2
23 (Op : Binary_Func_Access; LH : Mal_Handle)
24 return Mal_Handle is
25 Left, Right : Mal_Handle;
26 L, Rest_List : List_Mal_Type;
27 begin
28 L := Deref_List (LH).all;
29 Left := Car (L);
30 Rest_List := Deref_List (Cdr (L)).all;
31 Right := Car (Rest_List);
32 return Op (Left, Right);
33 end Reduce2;
34
35
36 function Plus (Rest_Handle : Mal_Handle)
37 return Types.Mal_Handle is
38 begin
39 return Reduce2 (Step2_Eval."+"'Unrestricted_Access, Rest_Handle);
40 end Plus;
41
42
43 function Minus (Rest_Handle : Mal_Handle)
44 return Types.Mal_Handle is
45 begin
46 return Reduce2 (Step2_Eval."-"'Unrestricted_Access, Rest_Handle);
47 end Minus;
48
49
50 function Mult (Rest_Handle : Mal_Handle)
51 return Types.Mal_Handle is
52 begin
53 return Reduce2 (Step2_Eval."*"'Unrestricted_Access, Rest_Handle);
54 end Mult;
55
56
57 function Divide (Rest_Handle : Mal_Handle)
58 return Types.Mal_Handle is
59 begin
60 return Reduce2 (Step2_Eval."/"'Unrestricted_Access, Rest_Handle);
61 end Divide;
62
63
64 package String_Mal_Hash is new Ada.Containers.Hashed_Maps
65 (Key_Type => Ada.Strings.Unbounded.Unbounded_String,
66 Element_Type => Smart_Pointers.Smart_Pointer,
67 Hash => Ada.Strings.Unbounded.Hash,
68 Equivalent_Keys => Ada.Strings.Unbounded."=",
69 "=" => Smart_Pointers."=");
70
71 Not_Found : exception;
72
73 function Get (M : String_Mal_Hash.Map; K : String) return Mal_Handle is
74 use String_Mal_Hash;
75 C : Cursor;
76 begin
77 C := Find (M, Ada.Strings.Unbounded.To_Unbounded_String (K));
78 if C = No_Element then
79 raise Not_Found;
80 else
81 return Element (C);
82 end if;
83 end Get;
84
85
86 Repl_Env : String_Mal_Hash.Map;
87
88
89 function Eval (Param : Types.Mal_Handle; Env : String_Mal_Hash.Map)
18e21187
CM
90 return Types.Mal_Handle;
91
988812a6 92
18e21187
CM
93 Debug : Boolean := False;
94
95
b5bad5ea
CM
96 function Read (Param : String) return Types.Mal_Handle is
97 begin
98 return Reader.Read_Str (Param);
99 end Read;
18e21187
CM
100
101
18e21187 102 function Eval_Ast
988812a6 103 (Ast : Mal_Handle; Env : String_Mal_Hash.Map)
18e21187
CM
104 return Mal_Handle is
105
106 function Call_Eval (A : Mal_Handle) return Mal_Handle is
107 begin
108 return Eval (A, Env);
109 end Call_Eval;
110
111 begin
112
113 case Deref (Ast).Sym_Type is
114
115 when Sym =>
116
117 declare
118 Sym : Mal_String := Deref_Sym (Ast).Get_Sym;
119 begin
120 -- if keyword, return it. Otherwise look it up in the environment.
121 if Sym(1) = ':' then
122 return Ast;
123 else
988812a6 124 return Get (Env, Sym);
18e21187
CM
125 end if;
126 exception
988812a6 127 when Not_Found =>
564a4525 128 raise Not_Found with ("'" & Sym & "' not found");
18e21187
CM
129 end;
130
131 when List =>
132
133 return Map (Call_Eval'Unrestricted_Access, Deref_List_Class (Ast).all);
134
135 when others => return Ast;
136
137 end case;
138
139 end Eval_Ast;
140
141
988812a6 142 function Eval (Param : Mal_Handle; Env : String_Mal_Hash.Map)
18e21187
CM
143 return Mal_Handle is
144 First_Elem : Mal_Handle;
145 begin
146
147 if Debug then
148 Ada.Text_IO.Put_Line ("Evaling " & Deref (Param).To_String);
149 end if;
150
151 if Deref (Param).Sym_Type = List and then
152 Deref_List (Param).Get_List_Type = List_List then
153
154 declare
155 Evaled_H, First_Param : Mal_Handle;
156 Evaled_List : List_Mal_Type;
585e06e4 157 Param_List : List_Mal_Type;
18e21187 158 begin
585e06e4
CM
159 Param_List := Deref_List (Param).all;
160
161 -- Deal with empty list..
162 if Param_List.Length = 0 then
163 return Param;
164 end if;
165
18e21187
CM
166 Evaled_H := Eval_Ast (Param, Env);
167 Evaled_List := Deref_List (Evaled_H).all;
168 First_Param := Car (Evaled_List);
1c28e560 169 return Call_Func (Deref_Func (First_Param).all, Cdr (Evaled_List));
18e21187
CM
170 end;
171
172 else -- Not a List_List
173
174 return Eval_Ast (Param, Env);
175
176 end if;
177
178 end Eval;
9a6f4925
CM
179
180
fbad73cb 181 function Print (Param : Types.Mal_Handle) return String is
9a6f4925
CM
182 begin
183 return Printer.Pr_Str (Param);
184 end Print;
185
18e21187 186
988812a6 187 function Rep (Param : String; Env : String_Mal_Hash.Map) return String is
fbad73cb 188 AST, Evaluated_AST : Types.Mal_Handle;
9a6f4925
CM
189 begin
190
191 AST := Read (Param);
192
193 if Types.Is_Null (AST) then
194 return "";
195 else
b5bad5ea 196 Evaluated_AST := Eval (AST, Env);
9a6f4925
CM
197 return Print (Evaluated_AST);
198 end if;
199
311cbfc0 200 end Rep;
9a6f4925
CM
201
202begin
203
988812a6
CM
204 String_Mal_Hash.Include
205 (Container => Repl_Env,
206 Key => Ada.Strings.Unbounded.To_Unbounded_String ("+"),
207 New_Item => New_Func_Mal_Type ("+", Plus'Unrestricted_access));
208
209 String_Mal_Hash.Include
210 (Container => Repl_Env,
211 Key => Ada.Strings.Unbounded.To_Unbounded_String ("-"),
212 New_Item => New_Func_Mal_Type ("-", Minus'Unrestricted_access));
213
214 String_Mal_Hash.Include
215 (Container => Repl_Env,
216 Key => Ada.Strings.Unbounded.To_Unbounded_String ("*"),
217 New_Item => New_Func_Mal_Type ("*", Mult'Unrestricted_access));
218
219 String_Mal_Hash.Include
220 (Container => Repl_Env,
221 Key => Ada.Strings.Unbounded.To_Unbounded_String ("/"),
222 New_Item => New_Func_Mal_Type ("/", Divide'Unrestricted_access));
9a6f4925
CM
223
224 loop
6d91af72
CM
225 begin
226 Ada.Text_IO.Put ("user> ");
311cbfc0
CM
227 exit when Ada.Text_IO.End_Of_File;
228 Ada.Text_IO.Put_Line (Rep (Ada.Text_IO.Get_Line, Repl_Env));
6d91af72 229 exception
6d91af72
CM
230 when E : others =>
231 Ada.Text_IO.Put_Line
232 (Ada.Text_IO.Standard_Error,
233 Ada.Exceptions.Exception_Information (E));
234 end;
9a6f4925 235 end loop;
9a6f4925 236end Step2_Eval;