summaryrefslogtreecommitdiff
path: root/src/kompsos.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/kompsos.adb')
-rw-r--r--src/kompsos.adb514
1 files changed, 136 insertions, 378 deletions
diff --git a/src/kompsos.adb b/src/kompsos.adb
index d531f25..e525f23 100644
--- a/src/kompsos.adb
+++ b/src/kompsos.adb
@@ -8,7 +8,8 @@
with
- Ada.Unchecked_Deallocation;
+ Ada.Unchecked_Deallocation,
+ Kompsos.Collector;
package body Kompsos is
@@ -52,6 +53,40 @@ package body Kompsos is
+ -- Worlds --
+
+ procedure Free is new Ada.Unchecked_Deallocation (World_Component, World_Component_Access);
+
+
+ procedure Initialize
+ (This : in out World) is
+ begin
+ This.Actual := null;
+ end Initialize;
+
+
+ procedure Adjust
+ (This : in out World) is
+ begin
+ if This.Actual /= null then
+ This.Actual.Counter := This.Actual.Counter + 1;
+ end if;
+ end Adjust;
+
+
+ procedure Finalize
+ (This : in out World) is
+ begin
+ if This.Actual /= null then
+ This.Actual.Counter := This.Actual.Counter - 1;
+ if This.Actual.Counter = 0 then
+ Free (This.Actual);
+ end if;
+ end if;
+ end Finalize;
+
+
+
-----------------
-- Datatypes --
@@ -156,31 +191,18 @@ package body Kompsos is
-- Worlds --
- function Hold
- (This : in World)
- return World_Holders.Holder is
- begin
- return World_Holders.To_Holder (World_Root'Class (This));
- end Hold;
-
-
- function Ptr
- (This : in out World_Holders.Holder)
- return World_Access is
- begin
- return World (This.Reference.Element.all)'Unchecked_Access;
- end Ptr;
-
-
- procedure Swap
- (Left, Right : in out World_Holders.Holder)
+ function Static
+ (Item : in State)
+ return World'Class
is
- Temp : World_Holders.Holder;
+ use type State_Vectors.Vector;
begin
- Temp.Move (Left);
- Left.Move (Right);
- Right.Move (Temp);
- end Swap;
+ return Result : constant World := (Ada.Finalization.Controlled with
+ Actual => new World_Component'(
+ (Kind => Static_Node,
+ Counter => 1,
+ Stc_States => State_Vectors.Empty_Vector & Item)));
+ end Static;
@@ -203,255 +225,6 @@ package body Kompsos is
- -- Unification --
-
- function Fully_Contains
- (This : in State;
- Item : in Term'Class)
- return Boolean is
- begin
- case Item.Kind is
- when Null_Term | Atom_Term =>
- return True;
- when Var_Term =>
- return This.Ident.Contains (Item.Var.Ident);
- when Pair_Term =>
- return Fully_Contains (This, Item.Left) and then Fully_Contains (This, Item.Right);
- end case;
- end Fully_Contains;
-
-
- function Walk
- (This : in State;
- Item : in Term'Class)
- return Term'Class is
- begin
- if Item.Kind = Var_Term and then
- This.Subst.Contains (This.Ident.Element (Item.Var.Ident))
- then
- return Walk (This, This.Subst.Constant_Reference (This.Ident.Element (Item.Var.Ident)));
- else
- return Item;
- end if;
- end Walk;
-
-
- function Do_Unify
- (Potential : in State;
- Left, Right : in Term'Class;
- Extended : out State)
- return Boolean
- is
- Real_Left : Term'Class := Left;
- Real_Right : Term'Class := Right;
- begin
- -- Check for Variable validity with respect to State
- if not Fully_Contains (Potential, Real_Left) or
- not Fully_Contains (Potential, Real_Right)
- then
- return False;
- end if;
-
- -- Resolve Variable substitution
- if Left.Kind = Var_Term then
- Real_Left := Walk (Potential, Real_Left);
- end if;
- if Right.Kind = Var_Term then
- Real_Right := Walk (Potential, Real_Right);
- end if;
-
- -- Unify equal Variable/Atom/Null Terms
- if (Real_Left.Kind = Var_Term and then
- Real_Right.Kind = Var_Term and then
- Real_Left = Real_Right) or else
- (Real_Left.Kind = Atom_Term and then
- Real_Right.Kind = Atom_Term and then
- Real_Left = Real_Right) or else
- (Real_Left.Kind = Null_Term and Real_Right.Kind = Null_Term)
- then
- Extended := Potential;
- return True;
- end if;
-
- -- Unify Variable and other Terms by introducing a new substitution
- if Real_Left.Kind = Var_Term then
- Extended := Potential;
- Extended.Subst.Insert (Extended.Ident.Element (Real_Left.Var.Ident), Term (Real_Right));
- return True;
- end if;
- if Real_Right.Kind = Var_Term then
- Extended := Potential;
- Extended.Subst.Insert (Extended.Ident.Element (Real_Right.Var.Ident), Term (Real_Left));
- return True;
- end if;
-
- -- Unify Pair Terms by unifying each corresponding part
- if Real_Left.Kind = Pair_Term and then Real_Right.Kind = Pair_Term then
- declare
- Middle : State;
- begin
- return Do_Unify (Potential, Real_Left.Left, Real_Right.Left, Middle) and then
- Do_Unify (Middle, Real_Left.Right, Real_Right.Right, Extended);
- end;
- end if;
-
- -- Not sure how things get here, but if all else fails
- return False;
- end Do_Unify;
-
-
-
- -- Lazy World Generation --
-
- function Call_Lazy
- (This : in World;
- Data : in Lazy_Holders.Holder)
- return World
- is
- Ref : constant Lazy_Holders.Constant_Reference_Type := Data.Constant_Reference;
- begin
- case Ref.Kind is
- when Zero_Arg =>
- return Ref.ZFunc (This);
- when One_Arg =>
- return Ref.OFunc (This, Ref.OInput);
- when Many_Arg =>
- return Ref.MFunc (This, Term_Array_Holders.Constant_Reference (Ref.MInput));
- end case;
- end Call_Lazy;
-
-
- function Has_State
- (This : in out World;
- Index : in Positive)
- return Boolean is
- begin
- This.Roll_Until (Index);
- return This.Possibles.Last_Index >= Index;
- end Has_State;
-
-
- procedure Roll_Fresh_Gen
- (This : in out World) is
- begin
- Ptr (This.Engine.Frs_World).Rollover;
- for Potential of Ptr (This.Engine.Frs_World).Possibles loop
- Potential.LVars.Append (This.Engine.Frs_Name);
- Potential.Ident.Insert (This.Engine.Frs_Ident, Potential.LVars.Last_Index);
- This.Possibles.Append (Potential);
- end loop;
- if Ptr (This.Engine.Frs_World).Engine.Kind = No_Gen then
- This.Engine := (Kind => No_Gen);
- else
- Ptr (This.Engine.Frs_World).Possibles.Clear;
- end if;
- end Roll_Fresh_Gen;
-
-
- procedure Roll_Unify_Gen
- (This : in out World)
- is
- Extended : State;
- begin
- Ptr (This.Engine.Uni_World).Rollover;
- for Potential of Ptr (This.Engine.Uni_World).Possibles loop
- if Do_Unify (Potential, This.Engine.Uni_Term1, This.Engine.Uni_Term2, Extended) then
- This.Possibles.Append (Extended);
- end if;
- end loop;
- if Ptr (This.Engine.Uni_World).Engine.Kind = No_Gen then
- This.Engine := (Kind => No_Gen);
- else
- Ptr (This.Engine.Uni_World).Possibles.Clear;
- end if;
- end Roll_Unify_Gen;
-
-
- procedure Roll_Disjunct_Gen
- (This : in out World) is
- begin
- Ptr (This.Engine.Dis_World1).Rollover;
- This.Possibles.Append (Ptr (This.Engine.Dis_World1).Possibles);
- if Ptr (This.Engine.Dis_World1).Engine.Kind = No_Gen then
- Ptr (This.Engine.Dis_World2).Rollover; -- why is this line needed?
- This.Possibles.Append (Ptr (This.Engine.Dis_World2).Possibles);
- This.Engine := World (This.Engine.Dis_World2.Element).Engine;
- else
- Ptr (This.Engine.Dis_World1).Possibles.Clear;
- Swap (This.Engine.Dis_World1, This.Engine.Dis_World2);
- end if;
- end Roll_Disjunct_Gen;
-
-
- procedure Roll_Conjunct_Gen
- (This : in out World)
- is
- use type Ada.Containers.Count_Type;
- begin
- Ptr (This.Engine.Con_World).Rollover;
- if Ptr (This.Engine.Con_World).Possibles.Length > 0 then
- declare
- So_Far : constant World :=
- ((Possibles => Ptr (This.Engine.Con_World).Possibles,
- Engine => (Kind => No_Gen)));
- begin
- Ptr (This.Engine.Con_World).Possibles.Clear;
- This := Disjunct (Call_Lazy (So_Far, This.Engine.Con_Data), This);
- end;
- elsif Ptr (This.Engine.Con_World).Engine.Kind = No_Gen then
- This.Engine := (Kind => No_Gen);
- end if;
- end Roll_Conjunct_Gen;
-
-
- procedure Roll_Recurse_Gen
- (This : in out World) is
- begin
- Ptr (This.Engine.Rec_World).Rollover;
- if Ptr (This.Engine.Rec_World).Possibles.Last_Index < This.Engine.Rec_Index then
- if Ptr (This.Engine.Rec_World).Engine.Kind = No_Gen then
- if This.Engine.Rec_Index = 1 then
- This.Engine := (Kind => No_Gen);
- else
- This.Engine.Rec_Index := 1;
- end if;
- end if;
- return;
- end if;
- for Index in Integer range
- This.Engine.Rec_Index .. Ptr (This.Engine.Rec_World).Possibles.Last_Index
- loop
- This.Possibles.Append (Ptr (This.Engine.Rec_World).Possibles (Index));
- end loop;
- This.Engine.Rec_Index := Ptr (This.Engine.Rec_World).Possibles.Last_Index + 1;
- end Roll_Recurse_Gen;
-
-
- procedure Rollover
- (This : in out World) is
- begin
- case This.Engine.Kind is
- when No_Gen => null;
- when Fresh_Gen => This.Roll_Fresh_Gen;
- when Unify_Gen => This.Roll_Unify_Gen;
- when Disjunct_Gen => This.Roll_Disjunct_Gen;
- when Conjunct_Gen => This.Roll_Conjunct_Gen;
- when Recurse_Gen => This.Roll_Recurse_Gen;
- end case;
- end Rollover;
-
-
- procedure Roll_Until
- (This : in out World;
- Index : in Positive) is
- begin
- while This.Possibles.Last_Index < Index and This.Engine.Kind /= No_Gen loop
- This.Rollover;
- end loop;
- end Roll_Until;
-
-
-
-------------------
-- microKanren --
@@ -481,15 +254,15 @@ package body Kompsos is
Name : in Nametag)
return Term
is
- My_ID : constant Generator_ID_Number := Next_Gen;
- begin
- return My_Term : constant Term := Term (T (Variable'(Ident => My_ID, Name => Name))) do
- This.Engine :=
- (Kind => Fresh_Gen,
- Frs_Ident => My_ID,
- Frs_World => Hold (This),
- Frs_Name => Name);
- This.Possibles := State_Vectors.Empty_Vector;
+ My_ID : constant Generator_ID_Number := Next_Gen;
+ My_Var : constant Variable := (Ident => My_ID, Name => Name);
+ begin
+ return My_Term : constant Term := Term (T (My_Var)) do
+ This.Actual := new World_Component'(
+ (Kind => Fresh_Node,
+ Counter => 1,
+ Frs_World => World (This),
+ Frs_Var => My_Var));
end return;
end Fresh;
@@ -552,13 +325,13 @@ package body Kompsos is
Left, Right : in Term'Class)
return World is
begin
- return Result : constant World :=
- (Possibles => State_Vectors.Empty_Vector,
- Engine =>
- (Kind => Unify_Gen,
- Uni_World => Hold (This),
+ return Result : constant World := (Ada.Finalization.Controlled with
+ Actual => new World_Component'(
+ (Kind => Unify_Node,
+ Counter => 1,
+ Uni_World => This,
Uni_Term1 => Term (Left),
- Uni_Term2 => Term (Right)));
+ Uni_Term2 => Term (Right))));
end Unify;
@@ -577,12 +350,12 @@ package body Kompsos is
(Left, Right : in World)
return World is
begin
- return Result : constant World :=
- (Possibles => State_Vectors.Empty_Vector,
- Engine =>
- (Kind => Disjunct_Gen,
- Dis_World1 => Hold (Left),
- Dis_World2 => Hold (Right)));
+ return Result : constant World := (Ada.Finalization.Controlled with
+ Actual => new World_Component'(
+ (Kind => Disjunct_Node,
+ Counter => 1,
+ Dis_World1 => Left,
+ Dis_World2 => Right)));
end Disjunct;
@@ -599,18 +372,20 @@ package body Kompsos is
return World is
begin
if Inputs'Length = 0 then
- return Failed : constant World :=
- (Possibles => State_Vectors.Empty_Vector,
- Engine => (Kind => No_Gen));
+ return Result : constant World := (Ada.Finalization.Controlled with
+ Actual => new World_Component'(
+ (Kind => Static_Node,
+ Counter => 1,
+ Stc_States => State_Vectors.Empty_Vector)));
elsif Inputs'Length = 1 then
return Inputs (Inputs'First);
else
- return Result : constant World :=
- (Possibles => State_Vectors.Empty_Vector,
- Engine =>
- (Kind => Disjunct_Gen,
- Dis_World1 => Hold (Inputs (Inputs'First)),
- Dis_World2 => Hold (Disjunct (Inputs (Inputs'First + 1 .. Inputs'Last)))));
+ return Result : constant World := (Ada.Finalization.Controlled with
+ Actual => new World_Component'(
+ (Kind => Disjunct_Node,
+ Counter => 1,
+ Dis_World1 => Inputs (Inputs'First),
+ Dis_World2 => Disjunct (Inputs (Inputs'First + 1 .. Inputs'Last)))));
end if;
end Disjunct;
@@ -631,12 +406,12 @@ package body Kompsos is
Func : in Junction_Zero_Func)
return World is
begin
- return Result : constant World :=
- (Possibles => State_Vectors.Empty_Vector,
- Engine =>
- (Kind => Conjunct_Gen,
- Con_World => Hold (This),
- Con_Data => Lazy_Holders.To_Holder ((Kind => Zero_Arg, ZFunc => Func))));
+ return Result : constant World := (Ada.Finalization.Controlled with
+ Actual => new World_Component'(
+ (Kind => Conjunct_Node,
+ Counter => 1,
+ Con_World => This,
+ Con_Data => Lazy_Holders.To_Holder ((Kind => Zero_Arg, ZFunc => Func)))));
end Conjunct;
@@ -654,15 +429,15 @@ package body Kompsos is
Input : in Term'Class)
return World is
begin
- return Result : constant World :=
- (Possibles => State_Vectors.Empty_Vector,
- Engine =>
- (Kind => Conjunct_Gen,
- Con_World => Hold (This),
+ return Result : constant World := (Ada.Finalization.Controlled with
+ Actual => new World_Component'(
+ (Kind => Conjunct_Node,
+ Counter => 1,
+ Con_World => This,
Con_Data => Lazy_Holders.To_Holder
((Kind => One_Arg,
OFunc => Func,
- OInput => Term (Input)))));
+ OInput => Term (Input))))));
end Conjunct;
@@ -681,15 +456,15 @@ package body Kompsos is
Inputs : in Term_Array)
return World is
begin
- return Result : constant World :=
- (Possibles => State_Vectors.Empty_Vector,
- Engine =>
- (Kind => Conjunct_Gen,
- Con_World => Hold (This),
+ return Result : constant World := (Ada.Finalization.Controlled with
+ Actual => new World_Component'(
+ (Kind => Conjunct_Node,
+ Counter => 1,
+ Con_World => This,
Con_Data => Lazy_Holders.To_Holder
((Kind => Many_Arg,
MFunc => Func,
- MInput => Term_Array_Holders.To_Holder (Inputs)))));
+ MInput => Term_Array_Holders.To_Holder (Inputs))))));
end Conjunct;
@@ -714,12 +489,11 @@ package body Kompsos is
(This : in World)
return World is
begin
- return Result : constant World :=
- (Possibles => State_Vectors.Empty_Vector,
- Engine =>
- (Kind => Recurse_Gen,
- Rec_World => Hold (This),
- Rec_Index => 1));
+ return Result : constant World := (Ada.Finalization.Controlled with
+ Actual => new World_Component'(
+ (Kind => Recurse_Node,
+ Counter => 1,
+ Rec_World => This)));
end Recurse;
@@ -731,71 +505,55 @@ package body Kompsos is
- -- Forced Evaluation --
+ -- Evaluation --
function Take
- (This : in out World;
- Count : in Positive)
- return State_Array is
+ (This : in World;
+ Count : in Positive)
+ return State_Array
+ is
+ Result : State_Array (1 .. Count);
+ Valid : Natural := 0;
+
+ package Collect is new Collector (This);
begin
- This.Force (Count);
- return Result : State_Array (1 .. Integer'Min (Count, This.Possibles.Last_Index)) do
- for Index in Result'Range loop
- Result (Index) := This.Possibles.Element (Index);
- end loop;
- end return;
+ for Item of Result loop
+ exit when not Collect.Has_Next;
+ Item := Collect.Next;
+ Valid := Valid + 1;
+ end loop;
+ return Result (1 .. Valid);
end Take;
function Take_First
- (This : in out World)
- return State is
+ (This : in World)
+ return State
+ is
+ package Collect is new Collector (This);
begin
- This.Force (1);
- if This.Possibles.Is_Empty then
- return Empty_State;
- else
- return This.Possibles.First_Element;
- end if;
+ return Collect.Next (Empty_State);
end Take_First;
function Take_All
- (This : in out World)
- return State_Array is
- begin
- This.Force_All;
- return Result : State_Array (1 .. Natural (This.Possibles.Length)) do
- for Index in Result'Range loop
- Result (Index) := This.Possibles.Element (Index);
- end loop;
- end return;
- end Take_All;
-
-
- procedure Force
- (This : in out World;
- Count : in Positive) is
- begin
- This.Roll_Until (Count);
- end Force;
-
-
- procedure Force_All
- (This : in out World) is
- begin
- while This.Engine.Kind /= No_Gen loop
- This.Rollover;
- end loop;
- end Force_All;
-
+ (This : in World)
+ return State_Array
+ is
+ package Collect is new Collector (This);
- function Failed
- (This : in out World)
- return Boolean is
+ function Do_Take
+ return State_Array is
+ begin
+ if Collect.Has_Next then
+ return Collect.Next & Do_Take;
+ else
+ return Result : State_Array (1 .. 0);
+ end if;
+ end Do_Take;
begin
- return not This.Has_State (1);
- end Failed;
+ return Do_Take;
+ end Take_All;