Commit | Line | Data |
---|---|---|
988812a6 CM |
1 | with Ada.Containers.Hashed_Maps; |
2 | with Ada.Strings.Unbounded.Hash; | |
9a6f4925 | 3 | with Ada.Text_IO; |
6d91af72 | 4 | with Ada.Exceptions; |
9a6f4925 CM |
5 | with Printer; |
6 | with Reader; | |
18e21187 | 7 | with Smart_Pointers; |
9a6f4925 CM |
8 | with Types; |
9 | ||
10 | procedure 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 | |
202 | begin | |
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 | 236 | end Step2_Eval; |