2015-03-15 22:56:09 +03:00
|
|
|
with Ada.Characters.Latin_1;
|
|
|
|
with Ada.Text_IO;
|
2015-03-19 00:12:54 +03:00
|
|
|
with Ada.Unchecked_Deallocation;
|
2015-03-15 22:56:09 +03:00
|
|
|
|
|
|
|
package body Types is
|
|
|
|
|
|
|
|
package ACL renames Ada.Characters.Latin_1;
|
|
|
|
|
2015-03-17 01:48:48 +03:00
|
|
|
|
2015-03-23 01:37:42 +03:00
|
|
|
-- Smart Pointers section.
|
|
|
|
|
|
|
|
overriding procedure Adjust (Object : in out Smart_Pointer) is
|
|
|
|
begin
|
|
|
|
if Object.Pointer /= null then
|
|
|
|
Object.Pointer.Ref_Count := Object.Pointer.Ref_Count + 1;
|
|
|
|
end if;
|
|
|
|
end Adjust;
|
|
|
|
|
|
|
|
procedure Free is
|
|
|
|
new Ada.Unchecked_Deallocation (Mal_Type, Mal_Type_Accessor);
|
|
|
|
|
|
|
|
overriding procedure Finalize (Object : in out Smart_Pointer) is
|
|
|
|
begin
|
|
|
|
if Object.Pointer /= null then
|
|
|
|
Object.Pointer.Ref_Count := Object.Pointer.Ref_Count - 1;
|
|
|
|
if Object.Pointer.Ref_Count = 0 then
|
|
|
|
Free (Object.Pointer);
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end Finalize;
|
|
|
|
|
|
|
|
function New_Ptr (Mal_Type : Mal_Type_Accessor) return Smart_Pointer is
|
|
|
|
begin
|
|
|
|
return Smart_Pointer'
|
|
|
|
(Ada.Finalization.Controlled with Pointer => Mal_Type);
|
|
|
|
end New_Ptr;
|
|
|
|
|
|
|
|
function Deref (Ptr : Smart_Pointer) return Mal_Type_Accessor is
|
|
|
|
begin
|
|
|
|
return Ptr.Pointer;
|
|
|
|
end Deref;
|
|
|
|
|
|
|
|
|
2015-03-17 01:48:48 +03:00
|
|
|
function Opening (LT : List_Types) return Character is
|
|
|
|
Res : Character;
|
|
|
|
begin
|
|
|
|
case LT is
|
|
|
|
when List_List =>
|
|
|
|
Res := '(';
|
|
|
|
when Vector_List =>
|
|
|
|
Res := '[';
|
|
|
|
when Hashed_List =>
|
|
|
|
Res := '{';
|
|
|
|
end case;
|
|
|
|
return Res;
|
|
|
|
end Opening;
|
|
|
|
|
|
|
|
|
|
|
|
function Closing (LT : List_Types) return Character is
|
|
|
|
Res : Character;
|
|
|
|
begin
|
|
|
|
case LT is
|
|
|
|
when List_List =>
|
|
|
|
Res := ')';
|
|
|
|
when Vector_List =>
|
|
|
|
Res := ']';
|
|
|
|
when Hashed_List =>
|
|
|
|
Res := '}';
|
|
|
|
end case;
|
|
|
|
return Res;
|
|
|
|
end Closing;
|
|
|
|
|
|
|
|
|
2015-03-19 01:30:45 +03:00
|
|
|
function Mal_Type_To_String (T : Mal_Type) return String is
|
2015-03-15 22:56:09 +03:00
|
|
|
use Ada.Strings.Unbounded;
|
|
|
|
begin
|
|
|
|
case T.Sym_Type is
|
|
|
|
when Int =>
|
|
|
|
declare
|
2015-03-21 19:40:03 +03:00
|
|
|
Res : String := Mal_Integer'Image (T.Int_Val);
|
2015-03-15 22:56:09 +03:00
|
|
|
begin
|
|
|
|
if Res (1) = ' ' then
|
|
|
|
return Res (2..Res'Last);
|
|
|
|
else
|
2015-03-17 01:48:48 +03:00
|
|
|
return Res;
|
|
|
|
end if;
|
|
|
|
end;
|
|
|
|
when Floating =>
|
|
|
|
declare
|
2015-03-21 19:40:03 +03:00
|
|
|
Res : String := Mal_Float'Image (T.Float_Val);
|
2015-03-17 01:48:48 +03:00
|
|
|
begin
|
|
|
|
if Res (1) = ' ' then
|
|
|
|
return Res (2..Res'Last);
|
|
|
|
else
|
|
|
|
return Res;
|
2015-03-15 22:56:09 +03:00
|
|
|
end if;
|
|
|
|
end;
|
|
|
|
when List =>
|
|
|
|
|
|
|
|
declare
|
|
|
|
UBS : Unbounded_String := Null_Unbounded_String;
|
|
|
|
C : Lists.Cursor;
|
|
|
|
use type Lists.Cursor;
|
|
|
|
First_Pass : Boolean := True;
|
|
|
|
begin
|
2015-03-17 01:48:48 +03:00
|
|
|
|
2015-03-15 22:56:09 +03:00
|
|
|
if Lists.Is_Empty (T.The_List) then
|
2015-03-17 01:48:48 +03:00
|
|
|
return Opening (T.List_Type) & Closing (T.List_Type);
|
2015-03-15 22:56:09 +03:00
|
|
|
end if;
|
2015-03-17 01:48:48 +03:00
|
|
|
|
2015-03-15 22:56:09 +03:00
|
|
|
C := Lists.First (T.The_List);
|
|
|
|
loop
|
|
|
|
if First_Pass then
|
|
|
|
First_Pass := False;
|
|
|
|
else
|
|
|
|
Append (UBS, " ");
|
|
|
|
end if;
|
2015-03-23 01:37:42 +03:00
|
|
|
UBStrings.Append (UBS, To_String (Deref (Lists.Element (C)).all));
|
2015-03-15 22:56:09 +03:00
|
|
|
exit when C = Lists.Last (T.The_List);
|
|
|
|
C := Lists.Next (C);
|
|
|
|
end loop;
|
2015-03-17 01:48:48 +03:00
|
|
|
return Opening (T.List_Type) &
|
|
|
|
To_String (UBS) &
|
|
|
|
Closing (T.List_Type);
|
2015-03-15 22:56:09 +03:00
|
|
|
end;
|
|
|
|
when Sym =>
|
|
|
|
return "" & T.Symbol;
|
|
|
|
when Str =>
|
|
|
|
-- The_String includes the quotation marks.
|
|
|
|
return To_String (T.The_String);
|
|
|
|
when Atom =>
|
|
|
|
return To_String (T.The_Atom);
|
2015-03-16 01:00:31 +03:00
|
|
|
when Unitary =>
|
|
|
|
case T.The_Function is
|
|
|
|
when Quote =>
|
2015-03-23 01:37:42 +03:00
|
|
|
return "(quote " & To_String (Deref (T.The_Operand).all) & ")";
|
2015-03-16 01:00:31 +03:00
|
|
|
when Unquote =>
|
2015-03-23 01:37:42 +03:00
|
|
|
return "(unquote " & To_String (Deref (T.The_Operand).all) & ")";
|
2015-03-16 01:00:31 +03:00
|
|
|
when Quasiquote =>
|
2015-03-23 01:37:42 +03:00
|
|
|
return "(quasiquote " & To_String (Deref (T.The_Operand).all) & ")";
|
2015-03-16 01:00:31 +03:00
|
|
|
when Splice_Unquote =>
|
|
|
|
return
|
2015-03-23 01:37:42 +03:00
|
|
|
"(splice-unquote " & To_String (Deref (T.The_Operand).all) & ")";
|
2015-03-20 01:19:13 +03:00
|
|
|
when Deref =>
|
|
|
|
return
|
2015-03-23 01:37:42 +03:00
|
|
|
"(deref " & To_String (Deref (T.The_Operand).all) & ")";
|
2015-03-16 01:00:31 +03:00
|
|
|
end case;
|
2015-03-19 00:12:54 +03:00
|
|
|
when Error =>
|
|
|
|
return To_String (T.Error_Msg);
|
2015-03-15 22:56:09 +03:00
|
|
|
end case;
|
2015-03-19 01:30:45 +03:00
|
|
|
end Mal_Type_To_String;
|
|
|
|
|
|
|
|
|
|
|
|
function To_String (T : Mal_Type) return String is
|
|
|
|
begin
|
2015-03-23 01:37:42 +03:00
|
|
|
if T.Meta /= Null_Smart_Pointer then
|
2015-03-19 01:30:45 +03:00
|
|
|
return "(with-meta " &
|
|
|
|
Mal_Type_To_String (T) & " " &
|
2015-03-23 01:37:42 +03:00
|
|
|
Mal_Type_To_String (Deref (T.Meta).all) & ")";
|
2015-03-19 01:30:45 +03:00
|
|
|
else
|
|
|
|
return Mal_Type_To_String (T);
|
|
|
|
end if;
|
2015-03-15 22:56:09 +03:00
|
|
|
end To_String;
|
|
|
|
|
2015-03-19 00:12:54 +03:00
|
|
|
|
2015-03-15 22:56:09 +03:00
|
|
|
end Types;
|