1 -- This started out as a simple public variant record.
2 -- Then smart pointers were added. They were part of the Mal_Type and
3 -- were required to be public because of the dependencies and
4 -- how the variant record was public. Not very Ada-like.
5 -- The third version bites the bullet and delares Mal_Type as tagged.
6 -- Smart pointers are an OO version in a separate package.
7 -- The Doubly_Linked_Lists have been replaced with a tree-like list instead...
8 -- The tree-like list has been replaced with a singly linked list. Sigh.
10 -- WARNING! This code contains:
11 -- Recursive data structures.
12 -- Object-based smart pointers.
13 -- Object-oriented code.
16 -- Chris M Moore 25/03/2015
18 with Ada
.Strings
.Unbounded
;
24 -- Some simple types. Not supposed to use the standard types directly.
26 subtype Mal_Float
is Float;
27 subtype Mal_Integer
is Integer;
28 subtype Mal_String
is String;
30 -- Start off with the top-level abstract type.
32 subtype Mal_Handle
is Smart_Pointers
.Smart_Pointer
;
34 function "=" (A
, B
: Mal_Handle
) return Mal_Handle
;
36 function "=" (A
, B
: Mal_Handle
) return Boolean;
38 type Sym_Types
is (Nil
, Bool
, Int
, Floating
, Str
, Sym
, Atom
, Node
,
39 List
, Func
, Lambda
, Error
);
41 type Mal_Type
is abstract new Smart_Pointers
.Base_Class
with private;
43 function Sym_Type
(T
: Mal_Type
) return Sym_Types
is abstract;
45 function Get_Meta
(T
: Mal_Type
) return Mal_Handle
;
47 procedure Set_Meta
(T
: in out Mal_Type
'Class; SP
: Mal_Handle
);
49 function Copy
(M
: Mal_Handle
) return Mal_Handle
;
51 function To_String
(T
: Mal_Type
'Class; Print_Readably
: Boolean := True)
54 function Is_Macro_Call
(T
: Mal_Type
'Class; Env
: Envs
.Env_Handle
) return Boolean;
56 type Mal_Ptr
is access all Mal_Type
'Class;
58 -- A helper function that just view converts the smart pointer to
59 -- a Mal_Type'Class pointer.
60 function Deref
(S
: Mal_Handle
) return Mal_Ptr
;
62 -- A helper function to detect null smart pointers.
63 function Is_Null
(S
: Mal_Handle
) return Boolean;
65 -- Derived types. All boilerplate from here.
67 type Nil_Mal_Type
is new Mal_Type
with private;
69 function New_Nil_Mal_Type
return Mal_Handle
;
71 overriding
function Sym_Type
(T
: Nil_Mal_Type
) return Sym_Types
;
74 type Int_Mal_Type
is new Mal_Type
with private;
76 function New_Int_Mal_Type
(Int
: Mal_Integer
) return Mal_Handle
;
78 overriding
function Sym_Type
(T
: Int_Mal_Type
) return Sym_Types
;
80 function Get_Int_Val
(T
: Int_Mal_Type
) return Mal_Integer
;
82 type Int_Ptr
is access all Int_Mal_Type
;
84 function Deref_Int
(SP
: Mal_Handle
) return Int_Ptr
;
87 type Float_Mal_Type
is new Mal_Type
with private;
89 function New_Float_Mal_Type
(Floating
: Mal_Float
) return Mal_Handle
;
91 overriding
function Sym_Type
(T
: Float_Mal_Type
) return Sym_Types
;
93 function Get_Float_Val
(T
: Float_Mal_Type
) return Mal_Float
;
95 type Float_Ptr
is access all Float_Mal_Type
;
97 function Deref_Float
(SP
: Mal_Handle
) return Float_Ptr
;
100 type Bool_Mal_Type
is new Mal_Type
with private;
102 function New_Bool_Mal_Type
(Bool
: Boolean) return Mal_Handle
;
104 overriding
function Sym_Type
(T
: Bool_Mal_Type
) return Sym_Types
;
106 function Get_Bool
(T
: Bool_Mal_Type
) return Boolean;
108 type Bool_Ptr
is access all Bool_Mal_Type
;
110 function Deref_Bool
(SP
: Mal_Handle
) return Bool_Ptr
;
113 type String_Mal_Type
is new Mal_Type
with private;
115 function New_String_Mal_Type
(Str
: Mal_String
) return Mal_Handle
;
117 overriding
function Sym_Type
(T
: String_Mal_Type
) return Sym_Types
;
119 function Get_String
(T
: String_Mal_Type
) return Mal_String
;
121 type String_Ptr
is access all String_Mal_Type
;
123 function Deref_String
(SP
: Mal_Handle
) return String_Ptr
;
126 type Symbol_Mal_Type
is new Mal_Type
with private;
128 function New_Symbol_Mal_Type
(Str
: Mal_String
) return Mal_Handle
;
130 overriding
function Sym_Type
(T
: Symbol_Mal_Type
) return Sym_Types
;
132 function Get_Sym
(T
: Symbol_Mal_Type
) return Mal_String
;
134 type Sym_Ptr
is access all Symbol_Mal_Type
;
136 function Deref_Sym
(S
: Mal_Handle
) return Sym_Ptr
;
140 type Atom_Mal_Type
is new Mal_Type
with private;
142 function New_Atom_Mal_Type
(MH
: Mal_Handle
) return Mal_Handle
;
144 overriding
function Sym_Type
(T
: Atom_Mal_Type
) return Sym_Types
;
146 function Get_Atom
(T
: Atom_Mal_Type
) return Mal_Handle
;
148 procedure Set_Atom
(T
: in out Atom_Mal_Type
; New_Val
: Mal_Handle
);
150 type Atom_Ptr
is access all Atom_Mal_Type
;
152 function Deref_Atom
(S
: Mal_Handle
) return Atom_Ptr
;
156 type Error_Mal_Type
is new Mal_Type
with private;
158 function New_Error_Mal_Type
(Str
: Mal_String
) return Mal_Handle
;
160 overriding
function Sym_Type
(T
: Error_Mal_Type
) return Sym_Types
;
165 type List_Types
is (List_List
, Vector_List
, Hashed_List
);
166 function Opening
(LT
: List_Types
) return Character;
167 function Closing
(LT
: List_Types
) return Character;
169 type List_Mal_Type
is new Mal_Type
with private;
171 function "=" (A
, B
: List_Mal_Type
) return Boolean;
173 function New_List_Mal_Type
174 (List_Type
: List_Types
;
175 The_First_Node
: Mal_Handle
:= Smart_Pointers
.Null_Smart_Pointer
)
178 function New_List_Mal_Type
179 (The_List
: List_Mal_Type
)
182 type Handle_Lists
is array (Positive range <>) of Mal_Handle
;
184 -- Make a new list of the form: (Handle_List(1), Handle_List(2)...)
185 function Make_New_List
(Handle_List
: Handle_Lists
) return Mal_Handle
;
187 overriding
function Sym_Type
(T
: List_Mal_Type
) return Sym_Types
;
189 function Get_List_Type
(L
: List_Mal_Type
) return List_Types
;
191 function Prepend
(Op
: Mal_Handle
; To_List
: List_Mal_Type
)
194 procedure Append
(To_List
: in out List_Mal_Type
; Op
: Mal_Handle
);
196 function Length
(L
: List_Mal_Type
) return Natural;
198 function Nth
(L
: List_Mal_Type
; N
: Natural) return Mal_Handle
;
200 procedure Add_Defs
(Defs
: List_Mal_Type
; Env
: Envs
.Env_Handle
);
202 -- Get the first item in the list:
203 function Car
(L
: List_Mal_Type
) return Mal_Handle
;
205 -- Get the rest of the list (second item onwards)
206 function Cdr
(L
: List_Mal_Type
) return Mal_Handle
;
208 type Func_Access
is access
209 function (Elem
: Mal_Handle
)
213 (Func_Ptr
: Func_Access
;
217 type Binary_Func_Access
is access
218 function (A
, B
: Mal_Handle
)
222 (Func_Ptr
: Binary_Func_Access
;
226 function Is_Null
(L
: List_Mal_Type
) return Boolean;
228 function Null_List
(L
: List_Types
) return List_Mal_Type
;
230 function Pr_Str
(T
: List_Mal_Type
; Print_Readably
: Boolean := True)
233 function Cat_Str
(T
: List_Mal_Type
; Print_Readably
: Boolean := True)
236 function Concat
(Rest_Handle
: List_Mal_Type
)
237 return Types
.Mal_Handle
; -- a new list
239 -- Duplicate copies the list (logically). This is to allow concatenation,
240 -- The result is always a List_List.
241 function Duplicate
(The_List
: List_Mal_Type
) return Mal_Handle
;
243 type List_Ptr
is access all List_Mal_Type
;
245 function Deref_List
(SP
: Mal_Handle
) return List_Ptr
;
247 type List_Class_Ptr
is access all List_Mal_Type
'Class;
249 function Deref_List_Class
(SP
: Mal_Handle
) return List_Class_Ptr
;
252 type Func_Mal_Type
is new Mal_Type
with private;
254 type Builtin_Func
is access
255 function (MH
: Mal_Handle
) return Mal_Handle
;
257 function New_Func_Mal_Type
(Str
: Mal_String
; F
: Builtin_Func
)
260 overriding
function Sym_Type
(T
: Func_Mal_Type
) return Sym_Types
;
262 function Get_Func_Name
(T
: Func_Mal_Type
) return Mal_String
;
265 (FMT
: Func_Mal_Type
; Rest_List
: Mal_Handle
)
268 type Func_Ptr
is access all Func_Mal_Type
;
270 function Deref_Func
(S
: Mal_Handle
) return Func_Ptr
;
274 type Lambda_Mal_Type
is new Mal_Type
with private;
276 function New_Lambda_Mal_Type
277 (Params
: Mal_Handle
; Expr
: Mal_Handle
; Env
: Envs
.Env_Handle
)
280 overriding
function Sym_Type
(T
: Lambda_Mal_Type
) return Sym_Types
;
282 function Get_Env
(L
: Lambda_Mal_Type
) return Envs
.Env_Handle
;
284 procedure Set_Env
(L
: in out Lambda_Mal_Type
; Env
: Envs
.Env_Handle
);
286 function Get_Params
(L
: Lambda_Mal_Type
) return Mal_Handle
;
288 function Get_Expr
(L
: Lambda_Mal_Type
) return Mal_Handle
;
290 function Get_Is_Macro
(L
: Lambda_Mal_Type
) return Boolean;
292 procedure Set_Is_Macro
(L
: in out Lambda_Mal_Type
; B
: Boolean);
295 (L
: Lambda_Mal_Type
;
296 Param_List
: Mal_Handle
) return Mal_Handle
;
298 type Lambda_Ptr
is access all Lambda_Mal_Type
;
300 function Get_Macro
(T
: Mal_Handle
; Env
: Envs
.Env_Handle
) return Lambda_Ptr
;
302 function Deref_Lambda
(SP
: Mal_Handle
) return Lambda_Ptr
;
305 with function Int_Op
(A
, B
: Mal_Integer
) return Mal_Integer
;
306 with function Float_Op
(A
, B
: Mal_Float
) return Mal_Float
;
307 function Arith_Op
(A
, B
: Mal_Handle
) return Mal_Handle
;
310 with function Int_Rel_Op
(A
, B
: Mal_Integer
) return Boolean;
311 with function Float_Rel_Op
(A
, B
: Mal_Float
) return Boolean;
312 function Rel_Op
(A
, B
: Mal_Handle
) return Mal_Handle
;
314 Runtime_Exception
: exception;
316 Mal_Exception
: exception; -- So tempting to call this Mal_Function but...
318 Mal_Exception_Value
: Mal_Handle
; -- Used by mal's throw command
322 type Mal_Type
is abstract new Smart_Pointers
.Base_Class
with record
326 -- Not allowed to be abstract and private. RM 3.9.3(10)
327 -- So if you call this it'll just raise an exception.
328 function To_Str
(T
: Mal_Type
; Print_Readably
: Boolean := True)
331 type Nil_Mal_Type
is new Mal_Type
with null record;
333 overriding
function To_Str
(T
: Nil_Mal_Type
; Print_Readably
: Boolean := True)
336 type Int_Mal_Type
is new Mal_Type
with record
337 Int_Val
: Mal_Integer
;
340 overriding
function To_Str
(T
: Int_Mal_Type
; Print_Readably
: Boolean := True)
343 type Float_Mal_Type
is new Mal_Type
with record
344 Float_Val
: Mal_Float
;
347 overriding
function To_Str
(T
: Float_Mal_Type
; Print_Readably
: Boolean := True)
350 type Bool_Mal_Type
is new Mal_Type
with record
354 overriding
function To_Str
(T
: Bool_Mal_Type
; Print_Readably
: Boolean := True)
357 type String_Mal_Type
is new Mal_Type
with record
358 The_String
: Ada
.Strings
.Unbounded
.Unbounded_String
;
361 overriding
function To_Str
(T
: String_Mal_Type
; Print_Readably
: Boolean := True)
364 type Symbol_Mal_Type
is new Mal_Type
with record
365 The_Symbol
: Ada
.Strings
.Unbounded
.Unbounded_String
;
368 overriding
function To_Str
(T
: Symbol_Mal_Type
; Print_Readably
: Boolean := True)
371 type Atom_Mal_Type
is new Mal_Type
with record
372 The_Atom
: Mal_Handle
;
375 overriding
function To_Str
(T
: Atom_Mal_Type
; Print_Readably
: Boolean := True)
378 type Func_Mal_Type
is new Mal_Type
with record
379 Func_Name
: Ada
.Strings
.Unbounded
.Unbounded_String
;
380 Func_P
: Builtin_Func
;
383 overriding
function To_Str
(T
: Func_Mal_Type
; Print_Readably
: Boolean := True)
386 type Error_Mal_Type
is new Mal_Type
with record
387 Error_Msg
: Ada
.Strings
.Unbounded
.Unbounded_String
;
390 overriding
function To_Str
(T
: Error_Mal_Type
; Print_Readably
: Boolean := True)
394 -- Nodes have to be a differnt type from a List;
395 -- otherwise how do you represent a list within a list?
396 type Node_Mal_Type
is new Mal_Type
with record
398 Next
: Mal_Handle
; -- This is always a Node_Mal_Type handle
401 function New_Node_Mal_Type
403 Next
: Mal_Handle
:= Smart_Pointers
.Null_Smart_Pointer
)
406 overriding
function Sym_Type
(T
: Node_Mal_Type
) return Sym_Types
;
408 overriding
function To_Str
409 (T
: Node_Mal_Type
; Print_Readably
: Boolean := True)
412 type Node_Ptr
is access all Node_Mal_Type
;
414 function Deref_Node
(SP
: Mal_Handle
) return Node_Ptr
;
417 type List_Mal_Type
is new Mal_Type
with record
418 List_Type
: List_Types
;
419 The_List
: Mal_Handle
;
420 Last_Elem
: Mal_Handle
;
423 overriding
function To_Str
424 (T
: List_Mal_Type
; Print_Readably
: Boolean := True)
427 type Container_Cursor
is tagged record
428 The_Node
: Node_Ptr
:= null;
431 type Lambda_Mal_Type
is new Mal_Type
with record
432 Params
, Expr
: Mal_Handle
;
433 Env
: Envs
.Env_Handle
;
437 overriding
function To_Str
438 (T
: Lambda_Mal_Type
; Print_Readably
: Boolean := True)