Ada: fix infinite loop when evaling a vector (core.mal)
[jackhill/mal.git] / ada / step9_try.adb
CommitLineData
18a94a9f
CM
1with Ada.Command_Line;
2with Ada.Exceptions;
3with Ada.Text_IO;
4with Ada.IO_Exceptions;
5with Core;
6with Envs;
7with Evaluation;
8with Printer;
9with Reader;
10with Types;
11
12procedure Step9_Try is
13
14 function Read (Param : String) return Types.Mal_Handle is
15 begin
16 return Reader.Read_Str (Param);
17 end Read;
18
19
20 -- Eval can't be here because there are function pointers that point
21 -- at it. Thus it must be at library level. See evaluation.ads
22
23
24 function Print (Param : Types.Mal_Handle) return String is
25 begin
26 return Printer.Pr_Str (Param);
27 end Print;
28
29 function Rep (Param : String) return String is
30 AST, Evaluated_AST : Types.Mal_Handle;
31 begin
32
33 AST := Read (Param);
34
35 if Types.Is_Null (AST) then
36 return "";
37 else
38 Evaluated_AST := Evaluation.Eval (AST, Envs.Get_Current);
39 return Print (Evaluated_AST);
40 end if;
41
42 end Rep;
43
44 S : String (1..Reader.Max_Line_Len);
45 Last : Natural;
46 Cmd_Args : Natural;
47 Command_Args : Types.Mal_Handle;
48 Command_List : Types.List_Ptr;
49 File_Processed : Boolean := False;
50
51begin
52
53 -- Core init also creates the first environment.
54 -- This is needed for the def!'s below.
55 Core.Init;
56
57 declare
58 Not_S : String :=
59 Rep ("(def! not (fn* (a) (if a false true)))");
60 LF_S : String :=
61 Rep ("(def! load-file (fn* (f) (eval (read-string (str ""(do "" (slurp f) "")"")))))");
62 Cond_S : String :=
63 Rep ("(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)))))))");
64 Or_S : String :=
65 Rep ("(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))");
66 pragma Unreferenced (Not_S, LF_S, Cond_S, Or_S);
67 begin
68 null;
69 end;
70
71 Cmd_Args := 0;
72 Command_Args := Types.New_List_Mal_Type (Types.List_List);
73 Command_List := Types.Deref_List (Command_Args);
74
75 while Ada.Command_Line.Argument_Count > Cmd_Args loop
76
77 Cmd_Args := Cmd_Args + 1;
78 if Ada.Command_Line.Argument (Cmd_Args) = "-d" then
79 Evaluation.Debug := True;
80 elsif Ada.Command_Line.Argument (Cmd_Args) = "-e" then
81 Envs.Debug := True;
82 else
83 if not File_Processed then
84-- declare
85-- F_S : String :=
86ADa.Text_IO.Put_Line (
87 Rep ("(load-file """ & Ada.Command_Line.Argument (Cmd_Args) & """)")
88);
89-- begin
90-- null;
91-- end;
92 File_Processed := True;
93 else
94 Command_List.Append
51fa7633 95 (Types.New_Symbol_Mal_Type (Ada.Command_Line.Argument (Cmd_Args)));
18a94a9f
CM
96 end if;
97 end if;
98
99 end loop;
100
101 Envs.Set (Envs.Get_Current, "*ARGV*", Command_Args);
102
103 loop
104 begin
105 Ada.Text_IO.Put ("user> ");
106 Ada.Text_IO.Get_Line (S, Last);
107 Ada.Text_IO.Put_Line (Rep (S (1..Last)));
108 exception
109 when Ada.IO_Exceptions.End_Error => raise;
110 when E : others =>
111 Ada.Text_IO.Put_Line
112 (Ada.Text_IO.Standard_Error,
113 Ada.Exceptions.Exception_Information (E));
114 end;
115 end loop;
116
117exception
118 when Ada.IO_Exceptions.End_Error => null;
119 -- i.e. exit without textual output
120end Step9_Try;