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