Commit | Line | Data |
---|---|---|
18a94a9f CM |
1 | with Ada.Command_Line; |
2 | with Ada.Exceptions; | |
3 | with Ada.Text_IO; | |
18a94a9f CM |
4 | with Core; |
5 | with Envs; | |
18e21187 | 6 | with Eval_Callback; |
18a94a9f CM |
7 | with Printer; |
8 | with Reader; | |
18e21187 | 9 | with Smart_Pointers; |
18a94a9f CM |
10 | with Types; |
11 | ||
12 | procedure Step9_Try is | |
13 | ||
18e21187 CM |
14 | use Types; |
15 | ||
18e21187 CM |
16 | function Eval (AParam : Types.Mal_Handle; AnEnv : Envs.Env_Handle) |
17 | return Types.Mal_Handle; | |
18 | ||
19 | Debug : Boolean := False; | |
20 | ||
21 | ||
b5bad5ea CM |
22 | function Read (Param : String) return Types.Mal_Handle is |
23 | begin | |
24 | return Reader.Read_Str (Param); | |
25 | end Read; | |
26 | ||
18e21187 CM |
27 | |
28 | function Def_Fn (Args : List_Mal_Type; Env : Envs.Env_Handle) | |
29 | return Mal_Handle is | |
30 | Name, Fn_Body, Res : Mal_Handle; | |
31 | begin | |
32 | Name := Car (Args); | |
33 | pragma Assert (Deref (Name).Sym_Type = Sym, | |
34 | "Def_Fn: expected atom as name"); | |
b5bad5ea | 35 | Fn_Body := Nth (Args, 1); |
18e21187 | 36 | Res := Eval (Fn_Body, Env); |
b5bad5ea | 37 | Envs.Set (Env, Deref_Sym (Name).Get_Sym, Res); |
18e21187 CM |
38 | return Res; |
39 | end Def_Fn; | |
40 | ||
41 | ||
42 | function Def_Macro (Args : List_Mal_Type; Env : Envs.Env_Handle) | |
43 | return Mal_Handle is | |
44 | Name, Fn_Body, Res : Mal_Handle; | |
45 | Lambda_P : Lambda_Ptr; | |
46 | begin | |
47 | Name := Car (Args); | |
48 | pragma Assert (Deref (Name).Sym_Type = Sym, | |
49 | "Def_Macro: expected atom as name"); | |
50 | Fn_Body := Car (Deref_List (Cdr (Args)).all); | |
51 | Res := Eval (Fn_Body, Env); | |
52 | Lambda_P := Deref_Lambda (Res); | |
53 | Lambda_P.Set_Is_Macro (True); | |
b5bad5ea | 54 | Envs.Set (Env, Deref_Sym (Name).Get_Sym, Res); |
18e21187 CM |
55 | return Res; |
56 | end Def_Macro; | |
57 | ||
58 | ||
59 | function Macro_Expand (Ast : Mal_Handle; Env : Envs.Env_Handle) | |
60 | return Mal_Handle is | |
61 | Res : Mal_Handle; | |
62 | E : Envs.Env_Handle; | |
63 | LMT : List_Mal_Type; | |
64 | LP : Lambda_Ptr; | |
65 | begin | |
66 | ||
67 | Res := Ast; | |
68 | E := Env; | |
69 | ||
70 | loop | |
71 | ||
72 | if Deref (Res).Sym_Type /= List then | |
73 | exit; | |
74 | end if; | |
75 | ||
76 | LMT := Deref_List (Res).all; | |
77 | ||
78 | -- Get the macro in the list from the env | |
79 | -- or return null if not applicable. | |
80 | LP := Get_Macro (Res, E); | |
81 | ||
82 | exit when LP = null or else not LP.Get_Is_Macro; | |
83 | ||
84 | declare | |
85 | Fn_List : Mal_Handle := Cdr (LMT); | |
86 | Params : List_Mal_Type; | |
87 | begin | |
88 | E := Envs.New_Env (E); | |
89 | ||
90 | Params := Deref_List (LP.Get_Params).all; | |
91 | if Envs.Bind (E, Params, Deref_List (Fn_List).all) then | |
92 | ||
311cbfc0 | 93 | Res := Eval (LP.Get_Expr, E); |
18e21187 CM |
94 | |
95 | end if; | |
96 | ||
97 | end; | |
98 | ||
99 | end loop; | |
100 | ||
101 | return Res; | |
102 | ||
103 | end Macro_Expand; | |
104 | ||
105 | ||
106 | function Eval_As_Boolean (MH : Mal_Handle) return Boolean is | |
107 | Res : Boolean; | |
108 | begin | |
109 | case Deref (MH).Sym_Type is | |
311cbfc0 | 110 | when Bool => |
18e21187 | 111 | Res := Deref_Bool (MH).Get_Bool; |
8083b525 CM |
112 | when Nil => |
113 | return False; | |
18e21187 CM |
114 | -- when List => |
115 | -- declare | |
116 | -- L : List_Mal_Type; | |
117 | -- begin | |
118 | -- L := Deref_List (MH).all; | |
119 | -- Res := not Is_Null (L); | |
120 | -- end; | |
121 | when others => -- Everything else | |
122 | Res := True; | |
123 | end case; | |
124 | return Res; | |
125 | end Eval_As_Boolean; | |
126 | ||
127 | ||
128 | function Eval_Ast | |
129 | (Ast : Mal_Handle; Env : Envs.Env_Handle) | |
130 | return Mal_Handle is | |
131 | ||
132 | function Call_Eval (A : Mal_Handle) return Mal_Handle is | |
133 | begin | |
134 | return Eval (A, Env); | |
135 | end Call_Eval; | |
136 | ||
137 | begin | |
138 | ||
139 | case Deref (Ast).Sym_Type is | |
140 | ||
141 | when Sym => | |
142 | ||
143 | declare | |
144 | Sym : Mal_String := Deref_Sym (Ast).Get_Sym; | |
145 | begin | |
146 | -- if keyword, return it. Otherwise look it up in the environment. | |
147 | if Sym(1) = ':' then | |
148 | return Ast; | |
149 | else | |
150 | return Envs.Get (Env, Sym); | |
151 | end if; | |
152 | exception | |
153 | when Envs.Not_Found => | |
564a4525 | 154 | raise Envs.Not_Found with ("'" & Sym & "' not found"); |
18e21187 CM |
155 | end; |
156 | ||
157 | when List => | |
158 | ||
159 | return Map (Call_Eval'Unrestricted_Access, Deref_List_Class (Ast).all); | |
160 | ||
18e21187 CM |
161 | when others => return Ast; |
162 | ||
163 | end case; | |
164 | ||
165 | end Eval_Ast; | |
166 | ||
fbfe6784 NB |
167 | function Starts_With (Ast : Mal_Handle; Symbol : String) return Boolean is |
168 | A0 : Mal_Handle; | |
169 | begin | |
170 | if Deref (Ast).Sym_Type /= List | |
171 | or else Deref_List_Class (Ast).Get_List_Type /= List_List | |
172 | or else Deref_List (Ast).Is_Null | |
173 | then | |
174 | return False; | |
175 | end if; | |
176 | A0 := Deref_List (Ast).Car; | |
177 | return Deref (A0).Sym_Type = Sym | |
178 | and then Deref_Sym (A0).Get_Sym = Symbol; | |
179 | end Starts_With; | |
18e21187 CM |
180 | |
181 | function Quasi_Quote_Processing (Param : Mal_Handle) return Mal_Handle is | |
fbfe6784 | 182 | Res, Elt, New_Res : Mal_Handle; |
18e21187 | 183 | L : List_Ptr; |
18e21187 CM |
184 | begin |
185 | ||
186 | if Debug then | |
187 | Ada.Text_IO.Put_Line ("QuasiQt " & Deref (Param).To_String); | |
188 | end if; | |
189 | ||
fbfe6784 NB |
190 | if Deref (Param).Sym_Type not in Sym | List then |
191 | -- No need to quote, Eval would not affect these anyway. | |
192 | return Param; | |
193 | end if; | |
18e21187 | 194 | |
18e21187 | 195 | if Deref (Param).Sym_Type /= List or else |
fbfe6784 | 196 | Deref_List_Class (Param).Get_List_Type = Hashed_List then |
18e21187 CM |
197 | |
198 | -- return a new list containing: a symbol named "quote" and ast. | |
fbfe6784 NB |
199 | Res := New_List_Mal_Type (List_List); |
200 | L := Deref_List (Res); | |
18e21187 CM |
201 | L.Append (New_Symbol_Mal_Type ("quote")); |
202 | L.Append (Param); | |
203 | return Res; | |
204 | ||
205 | end if; | |
206 | ||
18e21187 | 207 | -- if the first element of ast is a symbol named "unquote": |
fbfe6784 | 208 | if Starts_With (Param, "unquote") then |
18e21187 | 209 | -- return the second element of ast.` |
fbfe6784 | 210 | return Deref_List_Class (Param).Nth (1); |
18e21187 CM |
211 | |
212 | end if; | |
213 | ||
fbfe6784 | 214 | Res := New_List_Mal_Type (List_List); |
18e21187 | 215 | |
fbfe6784 NB |
216 | for I in reverse 0 .. Deref_List_Class (Param).Length - 1 loop |
217 | Elt := Deref_List_Class (Param).Nth (I); | |
218 | New_Res := New_List_Mal_Type (List_List); | |
219 | L := Deref_List (New_Res); | |
220 | if Starts_With (Elt, "splice-unquote") then | |
18e21187 | 221 | L.Append (New_Symbol_Mal_Type ("concat")); |
fbfe6784 NB |
222 | L.Append (Deref_List (Elt).Nth (1)); |
223 | else | |
224 | L.Append (New_Symbol_Mal_Type ("cons")); | |
225 | L.Append (Quasi_Quote_Processing (Elt)); | |
18e21187 | 226 | end if; |
fbfe6784 NB |
227 | L.Append (Res); |
228 | Res := New_Res; | |
229 | end loop; | |
18e21187 | 230 | |
fbfe6784 NB |
231 | if Deref_List_Class (Param).Get_List_Type = Vector_List then |
232 | New_Res := New_List_Mal_Type (List_List); | |
233 | L := Deref_List (New_Res); | |
234 | L.Append (New_Symbol_Mal_Type ("vec")); | |
235 | L.Append (Res); | |
236 | Res := New_Res; | |
18e21187 CM |
237 | end if; |
238 | ||
18e21187 CM |
239 | return Res; |
240 | ||
241 | end Quasi_Quote_Processing; | |
242 | ||
243 | ||
244 | function Catch_Processing | |
245 | (Try_Line : Mal_Handle; | |
246 | ExStr : Mal_Handle; | |
247 | Env : Envs.Env_Handle) | |
248 | return Mal_Handle is | |
249 | ||
250 | L, CL, CL2, CL3 : List_Mal_Type; | |
251 | C : Mal_Handle; | |
252 | New_Env : Envs.Env_Handle; | |
253 | ||
254 | begin | |
255 | ||
256 | L := Deref_List (Try_Line).all; | |
257 | C := Car (L); | |
258 | -- CL is the list with the catch in. | |
259 | CL := Deref_List (C).all; | |
260 | ||
261 | CL2 := Deref_List (Cdr (CL)).all; | |
262 | New_Env := Envs.New_Env (Env); | |
263 | Envs.Set (New_Env, Deref_Sym (Car (CL2)).Get_Sym, ExStr); | |
264 | ||
265 | CL3 := Deref_List (Cdr (CL2)).all; | |
266 | return Eval (Car (CL3), New_Env); | |
267 | end Catch_Processing; | |
268 | ||
269 | ||
270 | function Eval (AParam : Mal_Handle; AnEnv : Envs.Env_Handle) | |
271 | return Mal_Handle is | |
272 | Param : Mal_Handle; | |
273 | Env : Envs.Env_Handle; | |
274 | First_Param, Rest_Params : Mal_Handle; | |
275 | Rest_List, Param_List : List_Mal_Type; | |
276 | begin | |
277 | ||
278 | Param := AParam; | |
279 | Env := AnEnv; | |
280 | ||
b5bad5ea | 281 | <<Tail_Call_Opt>> |
18e21187 CM |
282 | |
283 | if Debug then | |
284 | Ada.Text_IO.Put_Line ("Evaling " & Deref (Param).To_String); | |
285 | end if; | |
286 | ||
287 | Param := Macro_Expand (Param, Env); | |
288 | ||
289 | if Debug then | |
290 | Ada.Text_IO.Put_Line ("After expansion " & Deref (Param).To_String); | |
291 | end if; | |
292 | ||
293 | if Deref (Param).Sym_Type = List and then | |
294 | Deref_List (Param).Get_List_Type = List_List then | |
295 | ||
296 | Param_List := Deref_List (Param).all; | |
74a87bd5 CM |
297 | |
298 | -- Deal with empty list.. | |
299 | if Param_List.Length = 0 then | |
300 | return Param; | |
301 | end if; | |
302 | ||
18e21187 CM |
303 | First_Param := Car (Param_List); |
304 | Rest_Params := Cdr (Param_List); | |
305 | Rest_List := Deref_List (Rest_Params).all; | |
306 | ||
307 | if Deref (First_Param).Sym_Type = Sym and then | |
308 | Deref_Sym (First_Param).Get_Sym = "def!" then | |
309 | return Def_Fn (Rest_List, Env); | |
310 | elsif Deref (First_Param).Sym_Type = Sym and then | |
311 | Deref_Sym (First_Param).Get_Sym = "defmacro!" then | |
312 | return Def_Macro (Rest_List, Env); | |
313 | elsif Deref (First_Param).Sym_Type = Sym and then | |
314 | Deref_Sym (First_Param).Get_Sym = "macroexpand" then | |
315 | return Macro_Expand (Car (Rest_List), Env); | |
316 | elsif Deref (First_Param).Sym_Type = Sym and then | |
317 | Deref_Sym (First_Param).Get_Sym = "let*" then | |
318 | declare | |
319 | Defs, Expr, Res : Mal_Handle; | |
320 | E : Envs.Env_Handle; | |
321 | begin | |
322 | E := Envs.New_Env (Env); | |
323 | Defs := Car (Rest_List); | |
324 | Deref_List_Class (Defs).Add_Defs (E); | |
325 | Expr := Car (Deref_List (Cdr (Rest_List)).all); | |
326 | Param := Expr; | |
327 | Env := E; | |
328 | goto Tail_Call_Opt; | |
329 | -- was: | |
330 | -- Res := Eval (Expr, E); | |
331 | -- return Res; | |
332 | end; | |
333 | elsif Deref (First_Param).Sym_Type = Sym and then | |
334 | Deref_Sym (First_Param).Get_Sym = "do" then | |
335 | declare | |
336 | D : List_Mal_Type; | |
337 | E : Mal_Handle; | |
338 | begin | |
339 | ||
340 | if Debug then | |
341 | Ada.Text_IO.Put_Line ("Do-ing " & To_String (Rest_List)); | |
342 | end if; | |
343 | ||
344 | if Is_Null (Rest_List) then | |
345 | return Rest_Params; | |
346 | end if; | |
347 | ||
348 | -- Loop processes Evals all but last entry | |
349 | D := Rest_List; | |
350 | loop | |
351 | E := Car (D); | |
352 | D := Deref_List (Cdr (D)).all; | |
353 | exit when Is_Null (D); | |
354 | E := Eval (E, Env); | |
355 | end loop; | |
356 | ||
357 | Param := E; | |
358 | goto Tail_Call_Opt; | |
359 | ||
360 | end; | |
361 | elsif Deref (First_Param).Sym_Type = Sym and then | |
362 | Deref_Sym (First_Param).Get_Sym = "if" then | |
363 | declare | |
364 | Args : List_Mal_Type := Rest_List; | |
365 | ||
366 | Cond, True_Part, False_Part : Mal_Handle; | |
367 | Cond_Bool : Boolean; | |
368 | pragma Assert (Length (Args) = 2 or Length (Args) = 3, | |
369 | "If_Processing: not 2 or 3 parameters"); | |
370 | L : List_Mal_Type; | |
371 | begin | |
372 | ||
373 | Cond := Eval (Car (Args), Env); | |
374 | ||
375 | Cond_Bool := Eval_As_Boolean (Cond); | |
376 | ||
377 | if Cond_Bool then | |
378 | L := Deref_List (Cdr (Args)).all; | |
379 | ||
380 | Param := Car (L); | |
381 | goto Tail_Call_Opt; | |
382 | -- was: return Eval (Car (L), Env); | |
383 | else | |
384 | if Length (Args) = 3 then | |
385 | L := Deref_List (Cdr (Args)).all; | |
386 | L := Deref_List (Cdr (L)).all; | |
387 | ||
388 | Param := Car (L); | |
389 | goto Tail_Call_Opt; | |
390 | -- was: return Eval (Car (L), Env); | |
391 | else | |
8083b525 | 392 | return New_Nil_Mal_Type; |
18e21187 CM |
393 | end if; |
394 | end if; | |
395 | end; | |
396 | ||
397 | elsif Deref (First_Param).Sym_Type = Sym and then | |
398 | Deref_Sym (First_Param).Get_Sym = "fn*" then | |
399 | ||
400 | return New_Lambda_Mal_Type | |
401 | (Params => Car (Rest_List), | |
402 | Expr => Nth (Rest_List, 1), | |
403 | Env => Env); | |
404 | ||
405 | elsif Deref (First_Param).Sym_Type = Sym and then | |
406 | Deref_Sym (First_Param).Get_Sym = "quote" then | |
407 | ||
408 | return Car (Rest_List); | |
409 | ||
fbfe6784 NB |
410 | elsif Deref (First_Param).Sym_Type = Sym and then |
411 | Deref_Sym (First_Param).Get_Sym = "quasiquoteexpand" then | |
412 | ||
413 | return Quasi_Quote_Processing (Car (Rest_List)); | |
414 | ||
18e21187 CM |
415 | elsif Deref (First_Param).Sym_Type = Sym and then |
416 | Deref_Sym (First_Param).Get_Sym = "quasiquote" then | |
417 | ||
418 | Param := Quasi_Quote_Processing (Car (Rest_List)); | |
419 | goto Tail_Call_Opt; | |
420 | ||
421 | elsif Deref (First_Param).Sym_Type = Sym and then | |
422 | Deref_Sym (First_Param).Get_Sym = "try*" then | |
423 | ||
dd7a4f55 JM |
424 | if Length (Rest_List) = 1 then |
425 | return Eval (Car (Rest_List), Env); | |
426 | end if; | |
18e21187 CM |
427 | declare |
428 | Res : Mal_Handle; | |
429 | begin | |
430 | return Eval (Car (Rest_List), Env); | |
431 | exception | |
432 | when Mal_Exception => | |
433 | Res := Catch_Processing | |
434 | (Cdr (Rest_List), | |
435 | Types.Mal_Exception_Value, | |
436 | Env); | |
437 | Types.Mal_Exception_Value := | |
438 | Smart_Pointers.Null_Smart_Pointer; | |
439 | return Res; | |
440 | when E : others => | |
441 | return Catch_Processing | |
442 | (Cdr (Rest_List), | |
443 | New_String_Mal_Type | |
444 | (Ada.Exceptions.Exception_Message (E)), | |
445 | Env); | |
446 | end; | |
447 | ||
448 | else | |
449 | ||
450 | -- The APPLY section. | |
451 | declare | |
452 | Evaled_H : Mal_Handle; | |
453 | begin | |
454 | Evaled_H := Eval_Ast (Param, Env); | |
455 | ||
456 | Param_List := Deref_List (Evaled_H).all; | |
457 | ||
458 | First_Param := Car (Param_List); | |
459 | Rest_Params := Cdr (Param_List); | |
460 | Rest_List := Deref_List (Rest_Params).all; | |
461 | ||
462 | if Deref (First_Param).Sym_Type = Func then | |
1c28e560 | 463 | return Call_Func (Deref_Func (First_Param).all, Rest_Params); |
18e21187 CM |
464 | elsif Deref (First_Param).Sym_Type = Lambda then |
465 | declare | |
466 | ||
467 | L : Lambda_Mal_Type; | |
468 | E : Envs.Env_Handle; | |
469 | Param_Names : List_Mal_Type; | |
470 | Res : Mal_Handle; | |
471 | ||
472 | begin | |
473 | ||
474 | L := Deref_Lambda (First_Param).all; | |
475 | E := Envs.New_Env (L.Get_Env); | |
476 | ||
477 | Param_Names := Deref_List (L.Get_Params).all; | |
478 | ||
479 | if Envs.Bind (E, Param_Names, Deref_List (Rest_Params).all) then | |
480 | ||
481 | Param := L.Get_Expr; | |
482 | Env := E; | |
483 | goto Tail_Call_Opt; | |
484 | -- was: return Eval (L.Get_Expr, E); | |
485 | ||
486 | else | |
487 | ||
dd7a4f55 | 488 | raise Runtime_Exception with "Bind failed in Apply"; |
18e21187 CM |
489 | |
490 | end if; | |
491 | ||
492 | end; | |
493 | ||
494 | else -- neither a Lambda or a Func | |
dd7a4f55 | 495 | raise Runtime_Exception with "Deref called on non-Func/Lambda"; |
18e21187 CM |
496 | end if; |
497 | ||
498 | end; | |
499 | ||
500 | end if; | |
501 | ||
502 | else -- not a List_List | |
503 | ||
504 | return Eval_Ast (Param, Env); | |
505 | ||
506 | end if; | |
507 | ||
508 | end Eval; | |
18a94a9f CM |
509 | |
510 | ||
511 | function Print (Param : Types.Mal_Handle) return String is | |
512 | begin | |
513 | return Printer.Pr_Str (Param); | |
514 | end Print; | |
515 | ||
b5bad5ea CM |
516 | function Rep (Param : String; Env : Envs.Env_Handle) return String is |
517 | AST, Evaluated_AST : Types.Mal_Handle; | |
18a94a9f CM |
518 | begin |
519 | ||
b5bad5ea | 520 | AST := Read (Param); |
18a94a9f | 521 | |
b5bad5ea CM |
522 | if Types.Is_Null (AST) then |
523 | return ""; | |
524 | else | |
525 | Evaluated_AST := Eval (AST, Env); | |
526 | return Print (Evaluated_AST); | |
527 | end if; | |
18a94a9f | 528 | |
311cbfc0 | 529 | end Rep; |
18a94a9f | 530 | |
b5bad5ea CM |
531 | |
532 | Repl_Env : Envs.Env_Handle; | |
533 | ||
534 | ||
535 | -- These two ops use Repl_Env directly. | |
536 | ||
537 | ||
538 | procedure RE (Str : Mal_String) is | |
539 | Discarded : Mal_Handle; | |
540 | begin | |
541 | Discarded := Eval (Read (Str), Repl_Env); | |
542 | end RE; | |
543 | ||
544 | ||
1c28e560 | 545 | function Do_Eval (Rest_Handle : Mal_Handle) |
b5bad5ea CM |
546 | return Types.Mal_Handle is |
547 | First_Param : Mal_Handle; | |
548 | Rest_List : Types.List_Mal_Type; | |
549 | begin | |
550 | Rest_List := Deref_List (Rest_Handle).all; | |
551 | First_Param := Car (Rest_List); | |
552 | return Eval_Callback.Eval.all (First_Param, Repl_Env); | |
553 | end Do_Eval; | |
554 | ||
555 | ||
f049dc3a | 556 | Cmd_Args, File_Param : Natural; |
18a94a9f CM |
557 | Command_Args : Types.Mal_Handle; |
558 | Command_List : Types.List_Ptr; | |
559 | File_Processed : Boolean := False; | |
560 | ||
561 | begin | |
562 | ||
18e21187 CM |
563 | -- Save a function pointer back to the Eval function. |
564 | -- Can't use 'Access here because of Ada rules but 'Unrestricted_Access is OK | |
565 | -- as we know Eval will be in scope for the lifetime of the program. | |
566 | Eval_Callback.Eval := Eval'Unrestricted_Access; | |
567 | ||
b5bad5ea CM |
568 | Repl_Env := Envs.New_Env; |
569 | ||
18a94a9f CM |
570 | -- Core init also creates the first environment. |
571 | -- This is needed for the def!'s below. | |
b5bad5ea CM |
572 | Core.Init (Repl_Env); |
573 | ||
574 | -- Register the eval command. This needs to be done here rather than Core.Init | |
575 | -- as it requires direct access to Repl_Env. | |
576 | Envs.Set (Repl_Env, "eval", New_Func_Mal_Type ("eval", Do_Eval'Unrestricted_Access)); | |
577 | ||
578 | RE ("(def! not (fn* (a) (if a false true)))"); | |
e6d41de4 | 579 | RE ("(def! load-file (fn* (f) (eval (read-string (str ""(do "" (slurp f) ""\nnil)"")))))"); |
b5bad5ea | 580 | RE ("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw ""odd number of forms to cond"")) (cons 'cond (rest (rest xs)))))))"); |
18a94a9f | 581 | |
dd7a4f55 JM |
582 | -- Command line processing. |
583 | ||
18a94a9f CM |
584 | Cmd_Args := 0; |
585 | Command_Args := Types.New_List_Mal_Type (Types.List_List); | |
586 | Command_List := Types.Deref_List (Command_Args); | |
587 | ||
588 | while Ada.Command_Line.Argument_Count > Cmd_Args loop | |
589 | ||
590 | Cmd_Args := Cmd_Args + 1; | |
591 | if Ada.Command_Line.Argument (Cmd_Args) = "-d" then | |
18e21187 | 592 | Debug := True; |
18a94a9f CM |
593 | elsif Ada.Command_Line.Argument (Cmd_Args) = "-e" then |
594 | Envs.Debug := True; | |
f049dc3a CM |
595 | elsif not File_Processed then |
596 | File_Param := Cmd_Args; | |
597 | File_Processed := True; | |
18a94a9f | 598 | else |
f049dc3a | 599 | Command_List.Append |
9c38eb6d | 600 | (Types.New_String_Mal_Type (Ada.Command_Line.Argument (Cmd_Args))); |
18a94a9f CM |
601 | end if; |
602 | ||
603 | end loop; | |
604 | ||
b5bad5ea | 605 | Envs.Set (Repl_Env, "*ARGV*", Command_Args); |
18a94a9f | 606 | |
f049dc3a | 607 | if File_Processed then |
b5bad5ea | 608 | RE ("(load-file """ & Ada.Command_Line.Argument (File_Param) & """)"); |
453a89a0 CM |
609 | else |
610 | loop | |
611 | begin | |
612 | Ada.Text_IO.Put ("user> "); | |
311cbfc0 CM |
613 | exit when Ada.Text_IO.End_Of_File; |
614 | Ada.Text_IO.Put_Line (Rep (Ada.Text_IO.Get_Line, Repl_Env)); | |
453a89a0 | 615 | exception |
453a89a0 CM |
616 | when E : others => |
617 | Ada.Text_IO.Put_Line | |
618 | (Ada.Text_IO.Standard_Error, | |
dd7a4f55 JM |
619 | "Error: " & Ada.Exceptions.Exception_Information (E)); |
620 | if Types.Mal_Exception_Value /= Smart_Pointers.Null_Smart_Pointer then | |
621 | Ada.Text_IO.Put_Line | |
622 | (Ada.Text_IO.Standard_Error, | |
623 | Printer.Pr_Str (Types.Mal_Exception_Value)); | |
624 | Types.Mal_Exception_Value := Smart_Pointers.Null_Smart_Pointer; | |
625 | end if; | |
453a89a0 CM |
626 | end; |
627 | end loop; | |
f049dc3a | 628 | end if; |
18a94a9f | 629 | end Step9_Try; |