1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-13 11:23:59 +03:00
mal/ada/envs.adb

169 lines
4.5 KiB
Ada
Raw Normal View History

2015-04-05 22:27:47 +03:00
with Ada.Text_IO;
2015-04-19 20:08:51 +03:00
with Types;
2015-04-02 01:36:29 +03:00
with Unchecked_Deallocation;
package body Envs is
2015-04-19 20:08:51 +03:00
procedure Init is
2015-04-02 01:36:29 +03:00
begin
2015-04-19 20:08:51 +03:00
New_Env;
Set (Current, "+", Types.New_Atom_Mal_Type ("+"));
Set (Current, "-", Types.New_Atom_Mal_Type ("-"));
Set (Current, "*", Types.New_Atom_Mal_Type ("*"));
Set (Current, "/", Types.New_Atom_Mal_Type ("/"));
Set (Current, "<", Types.New_Atom_Mal_Type ("<"));
Set (Current, "<=", Types.New_Atom_Mal_Type ("<="));
Set (Current, ">", Types.New_Atom_Mal_Type (">"));
Set (Current, ">=", Types.New_Atom_Mal_Type (">="));
Set (Current, "=", Types.New_Atom_Mal_Type ("="));
Set (Current, "true", Types.New_Bool_Mal_Type (True));
Set (Current, "false", Types.New_Bool_Mal_Type (False));
Set (Current, "list", Types.New_Atom_Mal_Type ("list"));
Set (Current, "nil", Types.New_Atom_Mal_Type ("nil"));
end Init;
function Is_Null (E : Env_Handle) return Boolean is
use Smart_Pointers;
begin
return Smart_Pointer (E) = Null_Smart_Pointer;
end Is_Null;
function New_Env (Outer : Env_Handle) return Env_Handle is
use Smart_Pointers;
Level : Natural;
begin
if Is_Null (Outer) then
Level := 0;
else
Level := Deref (Outer).Level + 1;
end if;
if Debug then
Ada.Text_IO.Put_Line
("Envs: Creating at level " & Natural'Image (Level));
end if;
return Env_Handle (Smart_Pointers.New_Ptr (new Env'
(Base_Class with The_Map => String_Mal_Hash.Empty_Map,
Outer_Env => Outer,
Level => Level)));
end New_Env;
procedure Set
(E : Env_Handle;
Key : String;
Elem : Smart_Pointers.Smart_Pointer) is
begin
if Debug then
Ada.Text_IO.Put_Line
("Envs: Setting " & Key &
" to " & Types.Deref (Elem).To_String &
" at level " & Natural'Image (Deref (E).Level));
end if;
2015-04-02 01:36:29 +03:00
String_Mal_Hash.Include
2015-04-19 20:08:51 +03:00
(Container => Deref (E).The_Map,
2015-04-02 01:36:29 +03:00
Key => Ada.Strings.Unbounded.To_Unbounded_String (Key),
2015-04-19 20:08:51 +03:00
New_Item => Elem);
2015-04-02 23:40:22 +03:00
end Set;
2015-04-02 01:36:29 +03:00
2015-04-05 22:27:47 +03:00
2015-04-19 20:08:51 +03:00
function Get (E : Env_Handle; Key: String)
return Smart_Pointers.Smart_Pointer is
use String_Mal_Hash;
C : Cursor;
2015-04-05 22:27:47 +03:00
2015-04-19 20:08:51 +03:00
begin
if Debug then
Ada.Text_IO.Put_Line
("Envs: Finding " & Key &
" at level " & Natural'Image (Deref (E).Level));
end if;
2015-04-05 22:27:47 +03:00
2015-04-19 20:08:51 +03:00
C := Find (Deref (E).The_Map,
Ada.Strings.Unbounded.To_Unbounded_String (Key));
2015-04-05 22:27:47 +03:00
2015-04-19 20:08:51 +03:00
if C = No_Element then
if Is_Null (Deref (E).Outer_Env) then
raise Not_Found;
2015-04-05 22:27:47 +03:00
else
2015-04-19 20:08:51 +03:00
return Get (Deref (E).Outer_Env, Key);
2015-04-05 22:27:47 +03:00
end if;
2015-04-19 20:08:51 +03:00
else
return Element (C);
end if;
2015-04-05 22:27:47 +03:00
2015-04-02 23:40:22 +03:00
end Get;
2015-04-02 01:36:29 +03:00
2015-04-19 20:08:51 +03:00
-- Sym and Exprs are lists. Bind Sets Keys in Syms to the corresponding
-- expression in Exprs.
procedure Bind (E : Env_Handle; Syms, Exprs : Types.List_Mal_Type) is
use Types;
S, Expr : List_Mal_Type;
begin
S := Syms;
Expr := Exprs;
while not Is_Null (S) and not Is_Null (Expr) loop
Set (E, Deref_Atom (Car (S)).Get_Atom, Car (Expr));
S := Deref_List (Cdr (S)).all;
Expr := Deref_List (Cdr (Expr)).all;
end loop;
end Bind;
2015-04-02 01:36:29 +03:00
function String_Hash (Key : Ada.Strings.Unbounded.Unbounded_String)
return Ada.Containers.Hash_Type is
use Ada.Containers;
Res : Ada.Containers.Hash_Type;
Str_Len : Natural;
begin
Res := 0;
Str_Len := Ada.Strings.Unbounded.Length (Key);
for I in 1..Str_Len loop
Res := Res * 16 +
Character'Pos (Ada.Strings.Unbounded.Element (Key, I));
end loop;
return Res;
end String_Hash;
procedure New_Env is
begin
2015-04-19 20:08:51 +03:00
Current := New_Env (Current);
2015-04-02 01:36:29 +03:00
end New_Env;
2015-04-19 20:08:51 +03:00
procedure Free is new Unchecked_Deallocation (Env, Env_Ptr);
2015-04-02 01:36:29 +03:00
procedure Delete_Env is
begin
2015-04-19 20:08:51 +03:00
-- Always leave one Env!
if not Is_Null (Deref (Current).Outer_Env) then
Current := Deref (Current).Outer_Env;
-- The old Current is finalized *if* there are no references to it.
-- Note closures may refer to the old env.
2015-04-05 22:27:47 +03:00
end if;
2015-04-02 01:36:29 +03:00
end Delete_Env;
2015-04-19 20:08:51 +03:00
function Get_Current return Env_Handle is
begin
return Current;
end Get_Current;
function Deref (SP : Env_Handle) return Env_Ptr is
begin
return Env_Ptr (Smart_Pointers.Deref (Smart_Pointers.Smart_Pointer (SP)));
end Deref;
2015-04-02 01:36:29 +03:00
end Envs;