5 package body Evaluation
is
9 -- primitive functions on Smart_Pointer,
10 function "+" is new Op
("+", "+");
11 function "-" is new Op
("-", "-");
12 function "*" is new Op
("*", "*");
13 function "/" is new Op
("/", "/");
15 function "<" is new Rel_Op
("<", "<");
16 function "<=" is new Rel_Op
("<=", "<=");
17 function ">" is new Rel_Op
(">", ">");
18 function ">=" is new Rel_Op
(">=", ">=");
21 procedure Add_Defs
(Defs
: List_Mal_Type
; Env
: Envs
.Env_Handle
) is
25 Ada
.Text_IO
.Put_Line
("Add_Defs " & To_String
(Defs
));
28 while not Is_Null
(D
) loop
29 L
:= Deref_List
(Cdr
(D
)).all;
32 Deref_Atom
(Car
(D
)).Get_Atom
,
34 D
:= Deref_List
(Cdr
(L
)).all;
39 -- function Fn_Processing
41 -- Fn_List : Mal_Handle;
42 -- Env : Envs.Env_Handle)
43 -- return Mal_Handle is
45 -- Params : List_Mal_Type;
46 -- E : Envs.Env_Handle;
48 -- -- Deal with right associativity...
49 -- E := Envs.New_Env (Env);
50 -- Params := Deref_List (L.Get_Params).all;
51 -- Envs.Bind (E, Params, Deref_List (Fn_List).all);
52 -- Set_Env (L.all, E);
54 -- return Eval (L.Get_Expr, E);
59 function Fn_Processing
62 Env
: Envs
.Env_Handle
)
65 Params
: List_Mal_Type
;
66 -- E : Envs.Env_Handle;
69 -- Deal with right associativity...
71 Params
:= Deref_List
(L
.Get_Params
).all;
72 Envs
.Bind
(Envs
.Get_Current
, Params
, Deref_List
(Fn_List
).all);
73 Set_Env
(L
.all, Envs
.Get_Current
);
75 Res
:= Eval
(L
.Get_Expr
, Envs
.Get_Current
);
82 function Apply
(Func
: Types
.Mal_Handle
; Params
: Types
.Mal_Handle
)
83 return Types
.Mal_Handle
is
88 Args
:= Deref_List
(Params
).all;
93 ("Applying " & To_String
(Deref
(Func
).all) &
94 " to " & Args
.To_String
);
98 case Deref
(Func
).Sym_Type
is
103 Atom_P
: Types
.Atom_Ptr
;
105 Atom_P
:= Types
.Deref_Atom
(Func
);
106 if Atom_P
.Get_Atom
= "+" then
107 return Reduce
("+"'Access, Args);
108 elsif Atom_P.Get_Atom = "-" then
109 return Reduce ("-"'Access, Args
);
110 elsif Atom_P
.Get_Atom
= "*" then
111 return Reduce
("*"'Access, Args);
112 elsif Atom_P.Get_Atom = "/" then
113 return Reduce ("/"'Access, Args
);
114 elsif Atom_P
.Get_Atom
= "<" then
115 return Reduce
("<"'Access, Args);
116 elsif Atom_P.Get_Atom = "<=" then
117 return Reduce ("<="'Access, Args
);
118 elsif Atom_P
.Get_Atom
= ">" then
119 return Reduce
(">"'Access, Args);
120 elsif Atom_P.Get_Atom = ">=" then
121 return Reduce (">="'Access, Args
);
122 elsif Atom_P
.Get_Atom
= "=" then
123 return Reduce
(Types
."="'Access, Args);
124 elsif Atom_P.Get_Atom = "list" then
125 return New_List_Mal_Type (The_List => Args);
134 Lam := Deref_Lambda (Func);
135 return Fn_Processing (Lam, Params, Lam.Get_Env);
138 when Error => return Func;
143 return Smart_Pointers.Null_Smart_Pointer;
147 function Def_Fn (Args : Types.List_Mal_Type; Env : Envs.Env_Handle) return Types.Mal_Handle is
149 Name, Fn_Body, Res : Mal_Handle;
152 pragma Assert (Deref (Name).Sym_Type = Atom,
153 "Def_Fn: expected atom as name");
154 Fn_Body := Car (Deref_List (Cdr (Args)).all);
155 Res := Eval (Fn_Body, Env);
156 Envs.Set (Envs.Get_Current, Deref_Atom (Name).Get_Atom, Res);
161 function Let_Processing (Args : Types.List_Mal_Type; Env : Envs.Env_Handle)
162 return Types.Mal_Handle is
164 Defs, Expr, Res : Mal_Handle;
168 Add_Defs (Deref_List (Defs).all, Envs.Get_Current);
169 Expr := Car (Deref_List (Cdr (Args)).all);
170 Res := Eval (Expr, Envs.Get_Current);
176 function Eval_As_Boolean (MH : Types.Mal_Handle) return Boolean is
180 case Deref (MH).Sym_Type is
182 Res := Deref_Bool (MH).Get_Bool;
184 return not (Deref_Atom (MH).Get_Atom = "nil");
187 -- L : List_Mal_Type;
189 -- L := Deref_List (MH).all;
190 -- Res := not Is_Null (L);
192 when others => -- Everything else
199 function If_Processing (Args : Types.List_Mal_Type; Env : Envs.Env_Handle)
200 return Types.Mal_Handle is
202 Cond, True_Part, False_Part : Mal_Handle;
204 pragma Assert (Length (Args) = 2 or Length (Args) = 3,
205 "If_Processing: not 2 or 3 parameters");
209 Cond := Eval (Car (Args), Env);
211 Cond_Bool := Eval_As_Boolean (Cond);
214 L := Deref_List (Cdr (Args)).all;
215 return Eval (Car (L), Env);
217 if Length (Args) = 3 then
218 L := Deref_List (Cdr (Args)).all;
219 L := Deref_List (Cdr (L)).all;
220 return Eval (Car (L), Env);
222 return New_Atom_Mal_Type ("nil");
229 (Ast : Types.Mal_Handle; Env : Envs.Env_Handle)
230 return Types.Mal_Handle is
233 function Call_Eval (A : Mal_Handle) return Mal_Handle is
235 return Eval (A, Env);
240 case Deref (Ast).Sym_Type is
245 Sym : Mal_String := Deref_Atom (Ast).Get_Atom;
247 -- if keyword or nil (which may represent False)...
251 return Envs.Get (Env, Sym);
254 when Envs.Not_Found =>
255 return New_Error_Mal_Type ("'" & Sym & "' not found");
260 return Map (Call_Eval'Unrestricted_Access, Deref_List (Ast).all);
262 when others => return Ast;
269 function Do_Processing (Do_List : Types.List_Mal_Type; Env : Envs.Env_Handle)
270 return Types.Mal_Handle is
273 Res : Mal_Handle := Smart_Pointers.Null_Smart_Pointer;
276 Ada.Text_IO.Put_Line ("Do-ing " & To_String (Do_List));
279 while not Is_Null (D) loop
280 Res := Eval_Ast (Car (D), Env);
281 D := Deref_List (Cdr(D)).all;
287 function List_Processing (L : Types.Mal_Handle; Env : Envs.Env_Handle)
288 return Types.Mal_Handle is
290 pragma Assert (Deref (L).Sym_Type = List,
291 "List_Processing: expected a list");
292 Evaled_List : List_Mal_Type;
293 Func, Args : Mal_Handle;
295 Evaled_List := Deref_List (Eval_Ast (L, Env)).all;
296 Func := Car (Evaled_List);
297 Args := Cdr (Evaled_List);
298 return Apply (Func, Args);
302 function Eval_As_List (MH : Types.Mal_Handle) return List_Mal_Type is
304 case Deref (MH).Sym_Type is
305 when List => return Deref_List (MH).all;
307 if Deref_Atom (MH).Get_Atom = "nil" then
308 return Null_List (List_List);
312 raise Evaluation_Error with "Expecting a List";
313 return Null_List (List_List);
317 function Eval_List (L : Types.Mal_Handle; Env : Envs.Env_Handle)
318 return Types.Mal_Handle is
321 pragma Assert (Deref (L).Sym_Type = List,
322 "Eval_List: expected a List");
323 LMT, Rest_List : List_Mal_Type;
324 First_Elem, Rest_Handle : Mal_Handle;
328 LMT := Deref_List (L).all;
330 First_Elem := Car (LMT);
332 Rest_List := Deref_List (Cdr (LMT)).all;
334 case Deref (First_Elem).Sym_Type is
341 Atom_P := Deref_Atom (First_Elem);
342 if Atom_P.Get_Atom = "def!" then
343 return Def_Fn (Rest_List, Env);
344 elsif Atom_P.Get_Atom = "let*" then
345 return Let_Processing (Rest_List, Env);
346 elsif Atom_P.Get_Atom = "do" then
347 return Do_Processing (Rest_List, Env);
348 elsif Atom_P.Get_Atom = "if" then
349 return If_Processing (Rest_List, Env);
350 elsif Atom_P.Get_Atom = "list?" then
352 First_Param, Evaled_List : Mal_Handle;
354 First_Param := Car (Rest_List);
355 Evaled_List := Eval (First_Param, Env);
356 return New_Bool_Mal_Type
357 (Deref (Evaled_List).Sym_Type = List and then
358 Deref_List (Evaled_List).Get_List_Type = List_List);
360 elsif Atom_P.Get_Atom = "empty?" then
362 First_Param, Evaled_List : Mal_Handle;
363 List : List_Mal_Type;
365 First_Param := Car (Rest_List);
366 Evaled_List := Eval (First_Param, Env);
367 List := Deref_List (Evaled_List).all;
368 return New_Bool_Mal_Type (Is_Null (List));
370 elsif Atom_P.Get_Atom = "count" then
372 First_Param, Evaled_List : Mal_Handle;
373 List : List_Mal_Type;
375 First_Param := Car (Rest_List);
376 Evaled_List := Eval (First_Param, Env);
377 List := Eval_As_List (Evaled_List);
378 return New_Int_Mal_Type (Length (List));
380 else -- not a special form
381 return List_Processing (L, Env);
388 (Deref_Lambda (First_Elem),
392 when Error => return First_Elem;
394 when others => return List_Processing (L, Env);
401 function Eval (Param : Types.Mal_Handle; Env : Envs.Env_Handle)
402 return Types.Mal_Handle is
404 First_Elem : Mal_Handle;
408 Ada.Text_IO.Put_Line ("Evaling " & Deref (Param).To_String);
411 if Deref (Param).Sym_Type = List and then
412 Deref_List (Param).all.Get_List_Type = List_List then
414 return Eval_List (Param, Env);
418 return Eval_Ast (Param, Env);