home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / ai / alsptype.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  209.8 KB  |  6,279 lines

  1. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. --aitypesspc.ada
  3. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4. ---------------------------------------------------------------------------
  5.  
  6. -- AI_Data_Types package specification
  7.  
  8. -- The following specification describes a set of packages which provide
  9. -- facilities necessary to emulate the capabilities which are commonly used
  10. -- in Artificial Intelligence (AI) applications, but not directly supported
  11. -- in Ada.
  12.  
  13. -- These facilities are:
  14. --    
  15. --    (1) Definitions of the primary data object to be used throughout
  16. --        this package, the symbolic expression.
  17. --
  18. --    (2) Symbolic expression operators.  These include functions and
  19. --        procedures for the creation, selection, manipulation and 
  20. --        destruction of symbolic expressions.
  21. --
  22. --    (3) Packages which define generic AI Objects generally found 
  23. --        useful in AI applications: patterns, rules and rulebases.
  24.  
  25. -- Developing Organization:  Software Architecture & Engineering
  26. --                           1600 Wilson Boulevard, Suite 500
  27. --                           Arlington, VA  22209
  28. --
  29. -- Contact:  Michael A. Jaskowiak
  30.  
  31. ---------------------------------------------------------------------------
  32.  
  33. with Text_Io; use Text_Io;
  34. generic 
  35.  
  36.    type Atomic_Literal is private;
  37.  
  38.    with function Is_Equal (Literal_Arg1, Literal_Arg2 : in Atomic_Literal) 
  39.       return Boolean;
  40.  
  41.    Lookahead : in out Character;
  42.  
  43.    with procedure Get (Input_File : in File_Type;
  44.                Literal_Result : in out Atomic_Literal);
  45.  
  46.    with procedure Put (Output_File : in File_Type;
  47.                Literal_Arg : in Atomic_Literal);
  48.  
  49. package AI_Data_Types is
  50.  
  51.    package Symbolic_Expressions is
  52.        
  53.       type S_Expr is private;
  54.  
  55.       Null_S_Expr : constant S_Expr;
  56.  
  57.       -------------------------------------------------------------------------
  58.  
  59.       --    Function:     Is_Null
  60.       --    Description:  Determines if S_Expr_Arg = Null_S_Expr.
  61.       --    Exceptions Raised:  None.
  62.  
  63.       function Is_Null (S_Expr_Arg : in S_Expr) return Boolean;
  64.  
  65.       -------------------------------------------------------------------------
  66.  
  67.       --    Function:     Is_Atomic
  68.       --    Description:  Determines if S_Expr_Arg is null or if it
  69.       --                  contains a atomic variable or user-defined literal.
  70.       --    Exceptions Raised:  None.
  71.  
  72.       function Is_Atomic (S_Expr_Arg : in S_Expr) return Boolean;
  73.  
  74.       -------------------------------------------------------------------------
  75.  
  76.       --    Function:     Is_Non_Atomic
  77.       --    Description:  Determines if S_Expr_Arg is a null or
  78.       --                  non-atomic expression.
  79.       --    Exceptions Raised:  None.
  80.  
  81.       function Is_Non_Atomic (S_Expr_Arg : in S_Expr) return Boolean;
  82.  
  83.       -------------------------------------------------------------------------
  84.  
  85.       --    Function:     Is_Variable
  86.       --    Description:  Determines if S_Expr_Arg is an non-null
  87.       --                  atomic expression containing a variable.
  88.       --    Exceptions Raised:  None.
  89.  
  90.       function Is_Variable (S_Expr_Arg : in S_Expr) return Boolean;
  91.  
  92.       -------------------------------------------------------------------------
  93.  
  94.       --    Function:     Is_Equal
  95.       --    Description:  Determines if two symbolic expressions are equivalent.
  96.       --    Exceptions Raised:  None.
  97.  
  98.       function Is_Equal (S_Expr_Arg1, S_Expr_Arg2 : in S_Expr) return Boolean;
  99.  
  100.       -------------------------------------------------------------------------
  101.  
  102.       --    Function:     Is_Member
  103.       --    Description:  Determines if the S_Expr_Arg is a top-level member
  104.       --                  of the given Non_Atomic_Arg.
  105.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  106.  
  107.       function Is_Member (S_Expr_Arg, Non_Atomic_Arg : in S_Expr) return Boolean;
  108.       -------------------------------------------------------------------------
  109.  
  110.       --    Function:     Create_Atomic_Literal
  111.       --    Description:  Returns an atomic expression containing
  112.       --                  the given Literal_Arg.
  113.       --    Exceptions Raised:  None.
  114.  
  115.       function Create_Atomic_Literal (Literal_Arg : in Atomic_Literal)
  116.      return S_Expr;
  117.  
  118.       -------------------------------------------------------------------------
  119.  
  120.       --    Function:     Create_Atomic_Variable
  121.       --    Description:  Creates an atomic variable with the given 
  122.       --                  name and with its tag initialized to 0.
  123.       --    Exceptions Raised:  None.
  124.  
  125.       function Create_Atomic_Variable (Name : in String) return S_Expr;
  126.  
  127.       -------------------------------------------------------------------------
  128.  
  129.       --    Procedure:    Set_Variable_Tag
  130.       --    Description:  Set the tag of the given variable to the given number.
  131.       --    Exceptions Raised:  Non_Atomic_Expression - if Atomic_Arg is nonatomic.
  132.       --                        Not_A_Variable
  133.       --                            - if the argument does not contain an atomic
  134.       --                              variable.
  135.  
  136.       procedure Set_Variable_Tag (Atomic_Arg : in S_Expr; New_Tag : in Natural);
  137.  
  138.       -------------------------------------------------------------------------
  139.  
  140.       --    Function:     Return_Atomic_Literal
  141.       --    Description:  Returns the atomic literal contained within the 
  142.       --                  given expression.
  143.       --    Exceptions Raised:   Non_Atomic_Expression
  144.       --                            -- if the argument is non-atomic.
  145.       --                         Not_A_Literal
  146.       --                            -- if the argument does not contain an atomic
  147.       --                               literal.
  148.  
  149.       function Return_Atomic_Literal (Atomic_Arg : in S_Expr)
  150.      return Atomic_Literal;
  151.  
  152.       -------------------------------------------------------------------------
  153.  
  154.       --    Function:     Return_Variable_Tag
  155.       --    Description:  Get the tag of the given variable.
  156.       --    Exceptions Raised:  Non_Atomic_Expression - if Atomic_Arg is nonatomic.
  157.       --                        Not_A_Variable
  158.       --                            - if the argument does not contain an atomic
  159.       --                              variable.
  160.  
  161.       function Return_Variable_Tag (Atomic_Arg : in S_Expr) return Natural;
  162.  
  163.       -------------------------------------------------------------------------
  164.  
  165.       --    Function:     Return_Variable_Name
  166.       --    Description:  Returns the name of the variable contained within the
  167.       --                  argument (concatenated with its tag, if non-zero.)
  168.       --    Exceptions Raised:  Non_Atomic_Expression - if Atomic_Arg is nonatomic.
  169.       --                        Not_A_Variable
  170.       --                            - if the argument does not contain an atomic
  171.       --                              variable.
  172.  
  173.       function Return_Variable_Name (Atomic_Arg : in S_Expr) return String;
  174.  
  175.       -------------------------------------------------------------------------
  176.  
  177.       --    Procedure:    Free
  178.       --    Description:  Frees the given symbolic expression.
  179.       --    Exceptions Raised:  None.
  180.  
  181.       procedure Free (S_Expr_Arg : in out S_Expr);
  182.  
  183.       -------------------------------------------------------------------------
  184.  
  185.       --    Function:     Return_And_Free
  186.       --    Description:  Provides a way for decrementing the ref-count of a
  187.       --                  symbolic expression bound to a local variable being
  188.       --                  returned from a function.
  189.       --    Exceptions Raised:  None.
  190.  
  191.       function Return_And_Free (S_Expr_Arg : in S_Expr) return S_Expr;
  192.  
  193.       -------------------------------------------------------------------------
  194.  
  195.       --    Procedure:    Bind
  196.       --    Description:  Sets the value of Current_Value to New_Value.
  197.       --    Exceptions Raised:  None.
  198.  
  199.       procedure Bind (Current_Value : in out S_Expr; New_Value : in S_Expr);
  200.  
  201.       -------------------------------------------------------------------------
  202.  
  203.       --    Procedure:    Get 
  204.       --    Description:  Read a symbolic expression from the given file.
  205.       --    Exceptions Raised: Extra_Separator, Missing_Separator,
  206.       --                       Improper_Input, Invalid_Variable_Name.
  207.  
  208.       procedure Get (Input_File : in File_Type; S_Expr_Result : in out S_Expr);
  209.  
  210.       -------------------------------------------------------------------------
  211.  
  212.       --    Procedure:    Get 
  213.       --    Description:  Read a symbolic expression from
  214.       --                  the current input file.
  215.       --    Exceptions Raised: Extra_Separator, Missing_Separator,
  216.       --                       Improper_Input, Invalid_Variable_Name.
  217.  
  218.       procedure Get (S_Expr_Result : in out S_Expr);
  219.  
  220.       -------------------------------------------------------------------------
  221.  
  222.       --    Procedure:    Put
  223.       --    Description:  Print the structure of the input symbolic expression
  224.       --                  to the specified output file.
  225.       --    Exceptions Raised: None.
  226.  
  227.       procedure Put (Output_File : in File_Type; S_Expr_Arg : in S_Expr);
  228.  
  229.       -------------------------------------------------------------------------
  230.  
  231.       --    Procedure:    Put 
  232.       --    Description:  Print the structure of the input symbolic expression
  233.       --                  to the current default output file.
  234.       --    Exceptions Raised: None.
  235.  
  236.       procedure Put (S_Expr_Arg : in S_Expr);
  237.  
  238.       -------------------------------------------------------------------------
  239.  
  240.       --    Function:     Prefix 
  241.       --    Description:  If the second argument is atomic, Prefix returns
  242.       --                  an expression, X, such that First(X)=First_Value
  243.       --                  and First (Rest (X)) = Rest_Value.  Otherwise, it returns
  244.       --                  an expression, Y, such that First(Y) = First_Value and
  245.       --                  Rest(Y) = Rest_Value.
  246.       --    Exceptions Raised: None.
  247.  
  248.       function Prefix (First_Value : in S_Expr;
  249.                Rest_Value  : in S_Expr := Null_S_Expr) return S_Expr;
  250.  
  251.       -------------------------------------------------------------------------
  252.  
  253.       --    Function:     "&" 
  254.       --    Description:  Returns a symbolic expression composed of the elements
  255.       --                  of each of the input arguments.
  256.       --    Exceptions Raised:  None.
  257.  
  258.       function "&" (S_Expr_Arg1, S_Expr_Arg2 : in S_Expr) return S_Expr;
  259.  
  260.       -------------------------------------------------------------------------
  261.  
  262.       --    Function:     Length 
  263.       --    Description:  Returns 0 for atomic expressions or the number of 
  264.       --                  top level components for non-atomic expressions.
  265.       --    Exceptions Raised:  None.
  266.  
  267.       function Length (S_Expr_Arg : in S_Expr) return Natural;
  268.  
  269.       -------------------------------------------------------------------------
  270.  
  271.       --    Function:     First 
  272.       --    Description:  Returns the first component of the non-null,
  273.       --                  non-atomic input argument.
  274.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  275.  
  276.       function First (Non_Atomic_Arg : in S_Expr) return S_Expr;
  277.  
  278.       -------------------------------------------------------------------------
  279.  
  280.       --    Function:     Rest 
  281.       --    Description:  Returns all components of the non-null, non-atomic
  282.       --                  input argument except the first.
  283.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  284.  
  285.       function Rest (Non_Atomic_Arg : in S_Expr) return S_Expr;
  286.  
  287.       -------------------------------------------------------------------------
  288.  
  289.       --    Function:     Last 
  290.       --    Description:  Returns the last component of the non-null,
  291.       --                  non-atomic input argument.
  292.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  293.  
  294.       function Last (Non_Atomic_Arg : in S_Expr) return S_Expr;
  295.  
  296.       -------------------------------------------------------------------------
  297.  
  298.       --    Function:     Nth 
  299.       --    Description:  Returns the position-th component of the non-null,
  300.       --                  non-atomic input argument.
  301.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  302.       --                        Invalid_Position - if Position > # of components
  303.  
  304.       function Nth (Non_Atomic_Arg : in S_Expr;
  305.             Position : in Positive) return S_Expr;
  306.  
  307.       -------------------------------------------------------------------------
  308.  
  309.       --    Function:     Nth_First 
  310.       --    Description:  Returns the result of calling the function First n
  311.       --                  times, each time using the result of the previous call
  312.       --                  as the argument for the new iteration.
  313.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  314.       --                        Invalid_Repetitions - if Repetitions > maximum
  315.       --                                              depth of the expression.
  316.  
  317.       function Nth_First (Non_Atomic_Arg : in S_Expr;
  318.               Repetitions : in Positive) return S_Expr;
  319.  
  320.       -------------------------------------------------------------------------
  321.  
  322.       --    Function:     Nth_Rest 
  323.       --    Description:  Returns the result of calling the function Rest n
  324.       --                  times, each time using the result of the previous call
  325.       --                  as the argument for the new iteration.
  326.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  327.       --                        Invalid_Repetitions - if Repetitions > maximum
  328.       --                                              length of the expression.
  329.  
  330.       function Nth_Rest (Non_Atomic_Arg : in S_Expr;
  331.              Repetitions : in Positive) return S_Expr;
  332.  
  333.       -------------------------------------------------------------------------
  334.  
  335.       --    Function:     Reverse_S_Expr 
  336.       --    Description:  Returns a non-atomic symbolic expression with the 
  337.       --                  components of the given argument in reverse order.
  338.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  339.  
  340.       function Reverse_S_Expr (Non_Atomic_Arg : in S_Expr) return S_Expr;
  341.  
  342.       -------------------------------------------------------------------------
  343.  
  344.       --    Function:     Delete 
  345.       --    Description:  Deletes all top level occurences of the first argument
  346.       --                  from the second.
  347.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  348.  
  349.       function Delete (S_Expr_Arg, Non_Atomic_Arg : in S_Expr) return S_Expr;
  350.  
  351.       -------------------------------------------------------------------------
  352.  
  353.       --    Function:     Replace 
  354.       --    Description:  Replaces all top level occurences of the first
  355.       --                  argument in the third with the second.
  356.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  357.  
  358.       function Replace (S_Expr_Arg1, S_Expr_Arg2, Non_Atomic_Arg : in S_Expr)
  359.      return S_Expr;
  360.  
  361.       -------------------------------------------------------------------------
  362.  
  363.       --    Function:     Flatten 
  364.       --    Description:  Returns a non-atomic expression which has as component
  365.       --                  all atomic components and all atomic components of all
  366.       --                  the non-atomic expressions within the given argument.
  367.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  368.  
  369.       function Flatten (Non_Atomic_Arg : in S_Expr) return S_Expr;
  370.  
  371.       -------------------------------------------------------------------------
  372.  
  373.       --    Function:     "And" 
  374.       --    Description:  Returns a non-atomic expression which contains as 
  375.       --                  components all components which are both in the first
  376.       --                  argument AND in the second argument with no duplicates
  377.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg1 or
  378.       --                                            Non_Atomic_Arg2 is 
  379.       --                                            non-null atomic.
  380.  
  381.       function "And" (Non_Atomic_Arg1, Non_Atomic_Arg2 : in S_Expr)
  382.      return S_Expr;
  383.  
  384.       -------------------------------------------------------------------------
  385.  
  386.       --    Function:     "Or" 
  387.       --    Description:  Returns a non-atomic expression which contains as 
  388.       --                  components all components which are either in the 1st
  389.       --                  argument OR in the second argument with no duplicates.
  390.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg1 or
  391.       --                                            Non_Atomic_Arg2 is
  392.       --                                            non-null atomic.
  393.  
  394.       function "Or" (Non_Atomic_Arg1, Non_Atomic_Arg2 : in S_Expr)
  395.      return S_Expr;
  396.  
  397.       -------------------------------------------------------------------------
  398.  
  399.       --    Function:     "-" 
  400.       --    Description:  Returns a non-atomic expression which contains as 
  401.       --                  components all those components of the first argument
  402.       --                  which are not contained within the second with no
  403.       --                  duplicates.
  404.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg1 or
  405.       --                                            Non_Atomic_Arg2 is
  406.       --                                            non-null atomic.
  407.  
  408.       function "-" (Non_Atomic_Arg1, Non_Atomic_Arg2 : in S_Expr) return S_Expr;
  409.  
  410.       -------------------------------------------------------------------------
  411.  
  412.       --    Function:     "Xor" 
  413.       --    Description:  Returns a non-atomic expression which contains as
  414.       --                  components all those components of the first argument
  415.       --                  which are not components of the second and all those
  416.       --                  components of the second argument which are not 
  417.       --                  components of the first with no duplicates.
  418.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg1 or
  419.       --                                            Non_Atomic_Arg2 is
  420.       --                                            non-null atomic.
  421.  
  422.       function "Xor" (Non_Atomic_Arg1, Non_Atomic_Arg2 : in S_Expr)
  423.      return S_Expr;
  424.  
  425.       -------------------------------------------------------------------------
  426.  
  427.       --    Function:     Associate 
  428.       --    Description:  Returns the first component of A_Table whose
  429.       --                  Search_Position-th component is equivalent to the Key.
  430.       --    Exceptions Raised:  Atomic_Expression - if A_Table is atomic.
  431.  
  432.       function Associate (Key, A_Table : in S_Expr;
  433.               Search_Position : Positive := 1) return S_Expr;
  434.  
  435.       -------------------------------------------------------------------------
  436.  
  437.       --    Function:     Associate_All 
  438.       --    Description:  Returns a non-atomic expression containing ALL the
  439.       --                  components of A_Table whose Search_Position-th
  440.       --                  component is equivalent to the Key.
  441.       --    Exceptions Raised:  Atomic_Expression - if A_Table is atomic.
  442.  
  443.       function Associate_All (Key, A_Table : in S_Expr;
  444.                   Search_Position : Positive := 1) return S_Expr;
  445.  
  446.       Atomic_Expression, Non_Atomic_Expression, Invalid_Position,
  447.       Missing_Separator, Extra_Separator, Improper_Input,
  448.       Invalid_Variable_Name, Not_A_Literal, Not_A_Variable,
  449.       Invalid_Repetitions : exception;
  450.  
  451.    private
  452.  
  453.       type Atomic_Expr_Kind is (Literal, Variable);
  454.      
  455.       type Var_Kind is (Var1,  Var2,  Var3,  Var4,  Var5,
  456.             Var6,  Var7,  Var8,  Var9,  Var10,
  457.             Var11, Var12, Var13, Var14, Var15);
  458.  
  459.       type Atomic_Variable (Kind : Var_Kind := Var1) is
  460.      record
  461.         Tag  : Natural;
  462.         case Kind is
  463.            when Var1  => Var1  : String (1 .. 1);
  464.            when Var2  => Var2  : String (1 .. 2);
  465.            when Var3  => Var3  : String (1 .. 3);
  466.            when Var4  => Var4  : String (1 .. 4);
  467.            when Var5  => Var5  : String (1 .. 5);
  468.            when Var6  => Var6  : String (1 .. 6);
  469.            when Var7  => Var7  : String (1 .. 7);
  470.            when Var8  => Var8  : String (1 .. 8);
  471.            when Var9  => Var9  : String (1 .. 9);
  472.            when Var10 => Var10 : String (1 .. 10);
  473.            when Var11 => Var11 : String (1 .. 11);
  474.            when Var12 => Var12 : String (1 .. 12);
  475.            when Var13 => Var13 : String (1 .. 13);
  476.            when Var14 => Var14 : String (1 .. 14);
  477.            when Var15 => Var15 : String (1 .. 15);
  478.         end case;
  479.      end record;
  480.  
  481.       type Atomic_Expr (Kind : Atomic_Expr_Kind := Literal) is
  482.      record
  483.         case Kind is
  484.            when Literal  => Literal : Atomic_Literal; 
  485.            when Variable => Variable : Atomic_Variable; 
  486.         end case;
  487.      end record;
  488.  
  489.       type Node_Category is (Atomic, Non_Atomic);
  490.  
  491.       type Node (Category : Node_Category);
  492.     
  493.       type S_Expr is access Node;
  494.     
  495.       Null_S_Expr : constant S_Expr := null;
  496.  
  497.       type Node (Category : Node_Category) is
  498.      record
  499.         Ref_Count : Natural;
  500.         case Category is
  501.            when Atomic     => Value : Atomic_Expr; 
  502.                   Next_Free : S_Expr;
  503.            when Non_Atomic => First, Rest : S_Expr; 
  504.         end case;
  505.      end record;
  506.  
  507.    end Symbolic_Expressions;
  508.  
  509.    package Patterns is
  510.  
  511.       package SE renames Symbolic_Expressions;
  512.  
  513.       subtype Pattern is SE.S_Expr;
  514.       Null_Pattern : Pattern renames SE.Null_S_Expr;
  515.        
  516.       -------------------------------------------------------------------------
  517.  
  518.       --    Function:     Is_Null
  519.       --    Description:  Determines if Pattern_Arg = Null_Pattern.
  520.       --    Exceptions Raised:  None.
  521.  
  522.       function Is_Null (Pattern_Arg : in Pattern) return Boolean;
  523.  
  524.       -------------------------------------------------------------------------
  525.  
  526.       --    Function:     Is_Equal
  527.       --    Description:  Determines if two patterns are equal by determining 
  528.       --                  if their instantiations are equal.
  529.       --    Exceptions Raised:  None.
  530.  
  531.       function Is_Equal (Pattern1, Pattern2 : in Pattern) return Boolean;
  532.  
  533.       -------------------------------------------------------------------------
  534.  
  535.       --    Function:     Create_Pattern
  536.       --    Description:  Creates a pattern. The symbolic expression forms the 
  537.       --                  pattern's template and the pattern's variable binding
  538.       --                  context is set to null.
  539.       --    Exceptions Raised:  None.
  540.  
  541.       function Create_Pattern (Template : in SE.S_Expr;
  542.                    Bindings : in SE.S_Expr:= SE.Null_S_Expr)
  543.      return Pattern;
  544.  
  545.       ----------------------------------------------------------------------
  546.  
  547.       --    Function:     Tag_Variables
  548.       --    Description:  Tags all variables within a pattern with the same
  549.       --                  tag.  This can be used to make a particular pattern
  550.       --                  unique with respect to other patterns.
  551.       --    Exceptions Raised:  None.
  552.  
  553.       procedure Tag_Variables (Pattern_Arg : in Pattern; Tag : in Natural);
  554.  
  555.       -------------------------------------------------------------------------
  556.  
  557.       --    Function:     Get_Template
  558.       --    Description:  Returns the template portion of the given pattern.
  559.       --    Exceptions Raised:  None.
  560.  
  561.       function Get_Template (Pattern_Arg : in Pattern) return SE.S_Expr;
  562.  
  563.       -------------------------------------------------------------------------
  564.  
  565.       --    Function:     Instantiate
  566.       --    Description:  Returns a symbolic expression created by replacing 
  567.       --                  all variables in the pattern argument's template with
  568.       --                  their current bindings (found in the variable binding
  569.       --                  context).
  570.       --    Exceptions Raised:  None.
  571.  
  572.       function Instantiate (Pattern_Arg : in Pattern) return SE.S_Expr;
  573.  
  574.       -------------------------------------------------------------------------
  575.  
  576.       --    Function:     Get_Bindings
  577.       --    Description:  Returns a symbolic expression representing the current
  578.       --                  bindings of the variables found in the pattern
  579.       --                  argument's template.
  580.       --    Exceptions Raised:  None.
  581.  
  582.       function Get_Bindings (Pattern_Arg : in Pattern) return SE.S_Expr;
  583.  
  584.       -------------------------------------------------------------------------
  585.  
  586.       --    Function:     Set_Bindings
  587.       --    Description:  Sets the variable binding context for the pattern
  588.       --                  to the specified context.  NOTE: This function can 
  589.       --                  also be used to erase the current context by setting 
  590.       --                  the bindings to null.
  591.       --    Exceptions Raised:  None.
  592.  
  593.       function Set_Bindings (Pattern_Arg : in Pattern;
  594.                  Bindings : in SE.S_Expr) return Pattern;
  595.  
  596.       procedure Bind (Current_Value : in out Pattern;  New_Value : in Pattern)
  597.      renames SE.Bind;
  598.  
  599.       procedure Free (Pattern_Arg : in out Pattern) renames SE.Free;
  600.  
  601.       function Return_And_Free (Pattern_Arg : in Pattern) return Pattern
  602.      renames SE.Return_And_Free;
  603.  
  604.       -------------------------------------------------------------------------
  605.  
  606.       --    Function:     First
  607.       --    Description:  Returns a pattern whose template consists of the 
  608.       --                  first component of the argument.  The variable binding
  609.       --                  context of the new pattern is the same as that of the
  610.       --                  argument.
  611.       --    Exceptions Raised:  Atomic_Template -- if the pattern template
  612.       --                                           is an atomic expression.
  613.  
  614.       function First (Pattern_Arg : in Pattern) return Pattern;
  615.  
  616.       -------------------------------------------------------------------------
  617.  
  618.       --    Function:     Rest
  619.       --    Description:  Returns a pattern whose template consists of the all 
  620.       --                  but the first component of the argument.  The variable
  621.       --                  binding context of the new pattern is the same as that
  622.       --                  of the argument.
  623.       --    Exceptions Raised:  Atomic_Template -- if the pattern template
  624.       --                                           is an atomic expression.
  625.  
  626.       function Rest (Pattern_Arg : in Pattern) return Pattern;
  627.  
  628.       -------------------------------------------------------------------------
  629.  
  630.       --    Function:     Match
  631.       --    Description:  If the two pattern arguments can be made identical by
  632.       --                  variable substitution, Is_Match will be set to True
  633.       --                  and the variable binding contexts of Pattern1 and 
  634.       --                  Pattern2 will contain the particular set of bindings
  635.       --                  which made the patterns identical.  Otherwise,Is_Match
  636.       --                  will be False and the variable binding contexts for
  637.       --                  the two patterns will remain unchanged.
  638.       --    References:   The pattern matching algorithms used are based upon 
  639.       --                  those found in the following reference:
  640.       --
  641.       --                  Wilensky, Robert.  LISPCRAFT. 
  642.       --                  New York: W. W. Norton & Co., Inc., 1984.
  643.       --    Exceptions Raised:  None.
  644.  
  645.       procedure Match (Pattern1, Pattern2 : in out Pattern;
  646.                Is_Match : out Boolean);
  647.  
  648.       -------------------------------------------------------------------------
  649.  
  650.       --    Procedure:    Get 
  651.       --    Description:  Read a pattern from the specified input file.
  652.       --    Exceptions Raised: None.
  653.  
  654.       procedure Get (Input_File : in File_Type;
  655.              Pattern_Result : in out Pattern);
  656.  
  657.       -------------------------------------------------------------------------
  658.  
  659.       --    Procedure:    Get 
  660.       --    Description:  Read a pattern from the current default input file.
  661.       --    Exceptions Raised: None.
  662.  
  663.       procedure Get (Pattern_Result : in out Pattern);
  664.  
  665.       -------------------------------------------------------------------------
  666.  
  667.       --    Procedure:    Put
  668.       --    Description:  Print the structure of the input pattern
  669.       --                  to the specified output file.
  670.       --    Exceptions Raised:  None.
  671.  
  672.       procedure Put (Output_File : in File_Type; Pattern_Arg : in Pattern);
  673.  
  674.       -------------------------------------------------------------------------
  675.  
  676.       --    Procedure:    Put
  677.       --    Description:  Print the structure of the input pattern
  678.       --                  to the current default output file.
  679.       --    Exceptions Raised: None.
  680.  
  681.       procedure Put (Pattern_Arg : in Pattern);
  682.  
  683.       Atomic_Template : exception;
  684.  
  685.    end Patterns;
  686.  
  687.  
  688.    package Rules is
  689.       package SE renames Symbolic_Expressions;
  690.       package PAT renames Patterns;
  691.  
  692.       subtype Rule is PAT.Pattern;
  693.       Null_Rule : Rule renames PAT.Null_Pattern;
  694.  
  695.       -------------------------------------------------------------------------
  696.  
  697.       --    Function:     Create_Rule
  698.       --    Description:  Creates a rule. The symbolic expressions form the 
  699.       --                  rule's template and the rule's variable binding
  700.       --                  context is set to null.
  701.       --    Exceptions Raised:  None.
  702.  
  703.       function Create_Rule (Antecedent,
  704.                 Consequent,
  705.                 Bindings : in SE.S_Expr := SE.Null_S_Expr)
  706.      return Rule;
  707.  
  708.       procedure Tag_Variables (Rule_Arg : in Rule; Tag : in Natural)
  709.      renames PAT.Tag_Variables;
  710.  
  711.       -------------------------------------------------------------------------
  712.  
  713.       --    Function:     Antecedent
  714.       --    Description:  Returns the antecedent of the given rule.
  715.       --    Exceptions Raised:  None.
  716.  
  717.       function Antecedent (Rule_Arg : in Rule) return PAT.Pattern;
  718.  
  719.       -------------------------------------------------------------------------
  720.  
  721.       --    Function:     Consequent
  722.       --    Description:  Returns the consequent of the given rule.
  723.       --    Exceptions Raised:  None.
  724.  
  725.       function Consequent (Rule_Arg : in Rule) return PAT.Pattern;
  726.  
  727.       -------------------------------------------------------------------------
  728.  
  729.       --    Function:     Is_Query
  730.       --    Description:  Determines if the rule is a query.
  731.       --                  A query is a rule which has only a antecedent.
  732.       --    Exceptions Raised:  None.
  733.  
  734.       function Is_Query (Rule_Arg : in Rule) return Boolean;
  735.  
  736.       -------------------------------------------------------------------------
  737.  
  738.       --    Function:     Is_Fact
  739.       --    Description:  Determines if the rule is a fact.
  740.       --                  A fact is a rule which has only a consequent.
  741.       --    Exceptions Raised:  None.
  742.  
  743.       function Is_Fact (Rule_Arg : in Rule) return Boolean;
  744.  
  745.       -------------------------------------------------------------------------
  746.  
  747.       --    Function:     Is_Rule
  748.       --    Description:  Determines if the given rule contains
  749.       --                  both a antecedent and a consequent.
  750.       --    Exceptions Raised:  None.
  751.  
  752.       function Is_Rule (Rule_Arg : in Rule) return Boolean;
  753.  
  754.       function Is_Null (Rule_Arg : in Rule) return Boolean
  755.      renames PAT.Is_Null;
  756.  
  757.       function Is_Equal (Rule1, Rule2 : in Rule) return Boolean
  758.      renames PAT.Is_Equal;
  759.  
  760.       function Get_Template (Rule_Arg : in Rule) return SE.S_Expr
  761.      renames PAT.Get_Template;
  762.  
  763.       function Instantiate (Rule_Arg : in Rule) return SE.S_Expr
  764.      renames PAT.Instantiate;
  765.  
  766.       function Get_Bindings (Rule_Arg : in Rule) return SE.S_Expr
  767.      renames PAT.Get_Bindings;
  768.  
  769.       function Set_Bindings (Rule_Arg : in Rule;
  770.                  Bindings : in SE.S_Expr) return Rule
  771.      renames PAT.Set_Bindings;
  772.  
  773.       procedure Bind (Current_Value : in out Rule;  New_Value : in Rule)
  774.      renames PAT.Bind;
  775.  
  776.       procedure Free (Rule_Arg : in out Rule) renames PAT.Free;
  777.  
  778.       function Return_And_Free (Rule_Arg : in Rule) return Rule
  779.      renames PAT.Return_And_Free;
  780.  
  781.       procedure Match (Rule1, Rule2 : in out Rule; Is_Match : out Boolean)
  782.      renames PAT.Match;
  783.  
  784.       -------------------------------------------------------------------------
  785.  
  786.       --    Procedure:    Get 
  787.       --    Description:  Read a rule from the specified input file.
  788.       --    Exceptions Raised: Invalid_Rule_Format - if the input does not
  789.       --                                             contain both an antecedent
  790.       --                                             and consequent.
  791.  
  792.       procedure Get (Input_File : in File_Type; Rule_Result : in out Rule);
  793.  
  794.       -------------------------------------------------------------------------
  795.  
  796.       --    Procedure:    Get 
  797.       --    Description:  Read a rule from the current default input file.
  798.       --    Exceptions Raised: None.
  799.  
  800.       procedure Get (Rule_Result : in out Rule);
  801.  
  802.       procedure Put (Rule_Arg : in Rule)
  803.      renames PAT.Put;
  804.  
  805.       procedure Put (Output_File : in File_Type; Rule_Arg : in Rule)
  806.      renames PAT.Put;
  807.  
  808.       Atomic_Template : exception renames PAT.Atomic_Template;
  809.       Invalid_Rule_Format : exception;
  810.    end Rules;
  811.  
  812.  
  813.    generic
  814.  
  815.       type Index is ( <> );
  816.  
  817.       with function Key (Rule_Arg : in Rules.Rule) return Index;
  818.  
  819.    package Rulebases is 
  820.       package SE renames Symbolic_Expressions;
  821.       package PAT renames Patterns;
  822.       package RUL renames Rules;
  823.  
  824.       type Rulebase is private;
  825.       Null_Rulebase : constant Rulebase;
  826.  
  827.       -------------------------------------------------------------------------
  828.  
  829.       --    Function:     Is_Null
  830.       --    Description:  Determines if Rulebase_Arg is empty.
  831.       --    Exceptions Raised:  None.
  832.  
  833.       function Is_Null (Rulebase_Arg : in Rulebase) return Boolean;
  834.  
  835.       -------------------------------------------------------------------------
  836.  
  837.       --    Function:     Is_Equal
  838.       --    Description:  Determines if Rulebase_Arg1 is equivalent
  839.       --                  to Rulebase_Arg2.
  840.       --    Exceptions Raised:  None.
  841.  
  842.       function Is_Equal (Rulebase_Arg1, Rulebase_Arg2 : in Rulebase)
  843.      return Boolean;
  844.  
  845.       -------------------------------------------------------------------------
  846.  
  847.       --    Function:     Create_Rulebase
  848.       --    Description:  Creates a rulebase from the given symbolic expression.
  849.       --    Exceptions Raised:  None.
  850.  
  851.       function Create_Rulebase (Template : in SE.S_Expr) return Rulebase;
  852.  
  853.       -------------------------------------------------------------------------
  854.  
  855.       --    Function:     Get_Template
  856.       --    Description:  Returns a symbolic expression representing the
  857.       --                  template for the given rulebase.
  858.       --    Exceptions Raised:  None.
  859.  
  860.       function Get_Template (Rulebase_Arg : in Rulebase) return SE.S_Expr;
  861.  
  862.       -------------------------------------------------------------------------
  863.  
  864.       --    Function:     Assert
  865.       --    Description:  Adds the given rule to the specified rulebase.
  866.       --    Exceptions Raised:  None.
  867.  
  868.       procedure Assert (Rule_Arg : in RUL.Rule; Rulebase_Arg : in out Rulebase);
  869.  
  870.       -------------------------------------------------------------------------
  871.  
  872.       --    Function:     Retract
  873.       --    Description:  Removes all occurrences of the given rule from the 
  874.       --                  specified rulebase.
  875.       --    Exceptions Raised:  None.
  876.  
  877.       procedure Retract (Rule_Arg : in RUL.Rule;
  878.              Rulebase_Arg : in out Rulebase);
  879.  
  880.       -------------------------------------------------------------------------
  881.  
  882.       --    Function:     Retrieve
  883.       --    Description:  Returns a symbolic expression containing instantiated
  884.       --                  versions of all rules which matched the input query.
  885.       --    Exceptions Raised:  None.
  886.  
  887.       function Retrieve (Rule_Arg : in RUL.Rule;
  888.              Rulebase_Arg : in Rulebase) return SE.S_Expr;
  889.  
  890.       -------------------------------------------------------------------------
  891.  
  892.       --    Function:     "And" (Intersection)
  893.       --    Description:  Returns a rulebase containing all those rules
  894.       --                  which are both in Rulebase1 AND Rulebase2.
  895.       --    Exceptions Raised:  None.
  896.  
  897.       function "And" (Rulebase1, Rulebase2 : in Rulebase) return Rulebase;
  898.  
  899.       -------------------------------------------------------------------------
  900.  
  901.       --    Function:     "Or" (Union)
  902.       --    Description:  Returns a rulebase containing all those rules
  903.       --                  which are either in Rulebase1 OR Rulebase2.
  904.       --    Exceptions Raised:  None.
  905.  
  906.       function "Or" (Rulebase1, Rulebase2 : in Rulebase) return Rulebase;
  907.  
  908.       -------------------------------------------------------------------------
  909.  
  910.       --    Function:     "-" (Difference)
  911.       --    Description:  Returns a rulebase containing all those rules
  912.       --                  which are in Rulebase1 but NOT in Rulebase2.
  913.       --    Exceptions Raised:  None.
  914.  
  915.       function "-" (Rulebase1, Rulebase2 : in Rulebase) return Rulebase;
  916.  
  917.       -------------------------------------------------------------------------
  918.  
  919.       --    Function:     "Xor" (Exclusive Or)
  920.       --    Description:  Returns a rulebase containing all those rules
  921.       --                  which are in Rulebase1 but NOT Rulebase2 AND
  922.       --                  all those rules which are in Rulebase2 but NOT
  923.       --                  in Rulebase1.
  924.       --    Exceptions Raised:  None.
  925.  
  926.       function "Xor" (Rulebase1, Rulebase2 : in Rulebase) return Rulebase;
  927.  
  928.       -------------------------------------------------------------------------
  929.  
  930.       --    Function:     Bind 
  931.       --    Description:  Assigns the value of New_Value to Current_Value after
  932.       --                  freeing the value of Current_Value.
  933.       --    Exceptions Raised:  None.
  934.  
  935.       procedure Bind (Current_Value : in out Rulebase;
  936.               New_Value : in Rulebase);
  937.  
  938.       -------------------------------------------------------------------------
  939.  
  940.       --    Function:     Free
  941.       --    Description:  Frees the given rulebase.
  942.       --    Exceptions Raised:  None.
  943.  
  944.       procedure Free (Rulebase_Arg : in out Rulebase);
  945.  
  946.       -------------------------------------------------------------------------
  947.  
  948.       --    Function:     Return_And_Free
  949.       --    Description:  Provides a way for decrementing the ref-count of a
  950.       --                  rulebase bound to a local variable being returned
  951.       --                  from a function.
  952.       --    Exceptions Raised:  None.
  953.  
  954.       function Return_And_Free (Rulebase_Arg : in Rulebase) return Rulebase;
  955.  
  956.       -------------------------------------------------------------------------
  957.  
  958.       --    Procedure:    Get
  959.       --    Description:  Reads a rulebase from the given input file.
  960.       --    Exceptions Raised:  None.
  961.  
  962.       procedure Get (Input_File : in File_Type;
  963.              Rulebase_Result : in out Rulebase);
  964.  
  965.       -------------------------------------------------------------------------
  966.  
  967.       --    Procedure:    Get
  968.       --    Description:  Reads a rulebase from the current default input file.
  969.       --    Exceptions Raised:  None.
  970.  
  971.       procedure Get (Rulebase_Result : in out Rulebase);
  972.  
  973.       -------------------------------------------------------------------------
  974.  
  975.       --    Procedure:    Put
  976.       --    Description:  Prints the contents of a rulebase to the given
  977.       --                  output file.
  978.       --    Exceptions Raised:  None.
  979.  
  980.       procedure Put (Output_File : in File_Type;
  981.              Rulebase_Arg : in Rulebase);
  982.  
  983.       -------------------------------------------------------------------------
  984.  
  985.       --    Procedure:    Put
  986.       --    Description:  Prints the contents of a rulebase to the current
  987.       --                  default output file.
  988.       --    Exceptions Raised:  None.
  989.  
  990.       procedure Put (Rulebase_Arg : in Rulebase);
  991.  
  992.       Invalid_Rulebase_Format : exception;
  993.  
  994.   private
  995.  
  996.       type Rulebase_Node;
  997.     
  998.       type Rulebase is access Rulebase_Node;
  999.     
  1000.       Null_Rulebase : constant Rulebase := null;
  1001.  
  1002.       type Rule_Array is array (Index) of RUL.Rule;
  1003.  
  1004.       type Rulebase_Node is 
  1005.        record
  1006.           Ref_Count : Natural;
  1007.           Next_Free : Rulebase;
  1008.           Rules     : Rule_Array;
  1009.        end record;
  1010.  
  1011.    end Rulebases;
  1012.  
  1013. end AI_Data_Types;
  1014. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1015. --aitypesimp.ada
  1016. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1017. ---------------------------------------------------------------------------
  1018.  
  1019. -- AI_Data_Types package implementation
  1020.  
  1021. -- The following implementation describes a set of packages which provide
  1022. -- facilities necessary to emulate the capabilities which are commonly used
  1023. -- in Artificial Intelligence (AI) applications, but not directly supported
  1024. -- in Ada.
  1025.  
  1026. -- These facilities are:
  1027. --    
  1028. --    (1) Definitions of the primary data object to be used throughout
  1029. --        this package, the symbolic expression.
  1030. --
  1031. --    (2) Symbolic expression operators.  These include functions and
  1032. --        procedures for the creation, selection, manipulation and 
  1033. --        destruction of symbolic expressions.
  1034. --
  1035. --    (3) Packages which define generic AI Objects generally found 
  1036. --        useful in AI applications: patterns, rules and rulebases.
  1037.  
  1038. -- Developing Organization:  Software Architecture & Engineering
  1039. --                           1600 Wilson Boulevard, Suite 500
  1040. --                           Arlington, VA  22209
  1041. --
  1042. -- Contact:  Michael A. Jaskowiak
  1043.  
  1044. ---------------------------------------------------------------------------
  1045.  
  1046. with Integer_Text_Io;
  1047. package body AI_Data_Types is
  1048.  
  1049.    package body Symbolic_Expressions is
  1050.  
  1051.       use Integer_Text_Io;
  1052.  
  1053.       Atomic_Free_List, Non_Atomic_Free_List : S_Expr := Null_S_Expr;
  1054.  
  1055.       -------------------------------------------------------------------------
  1056.  
  1057.       --    Function:     Is_Null
  1058.       --    Visibility:   Exported.
  1059.       --    Description:  Determines if S_Expr_Arg = Null_S_Expr.
  1060.       --
  1061.       --    Exceptions Raised:  None.
  1062.  
  1063.       function Is_Null (S_Expr_Arg : in S_Expr) return Boolean is
  1064.       begin
  1065.      return S_Expr_Arg = Null_S_Expr;
  1066.       end Is_Null;
  1067.  
  1068.       -------------------------------------------------------------------------
  1069.  
  1070.       --    Function:     Is_Atomic
  1071.       --    Visibility:   Exported.
  1072.       --    Description:  Determines if S_Expr_Arg is null or if it
  1073.       --                  contains a atomic variable or user-defined literal.
  1074.       --
  1075.       --    Exceptions Raised:  None.
  1076.  
  1077.       function Is_Atomic (S_Expr_Arg : in S_Expr) return Boolean is
  1078.       begin
  1079.      return Is_Null (S_Expr_Arg) or else S_Expr_Arg.Category = Atomic;
  1080.       end Is_Atomic;
  1081.  
  1082.       -------------------------------------------------------------------------
  1083.  
  1084.       --    Function:     Is_Variable
  1085.       --    Visibility:   Exported.
  1086.       --    Description:  Determines if S_Expr_Arg is an non-null
  1087.       --                  atomic expression containing a variable.
  1088.       --
  1089.       --    Exceptions Raised:  None.
  1090.  
  1091.       function Is_Variable (S_Expr_Arg : in S_Expr) return Boolean is
  1092.       begin
  1093.      return not Is_Null(S_Expr_Arg) and then
  1094.         S_Expr_Arg.Category = Atomic and then
  1095.         S_Expr_Arg.Value.Kind = Variable;
  1096.       end Is_Variable;
  1097.  
  1098.       -------------------------------------------------------------------------
  1099.  
  1100.       --    Function:     Is_Non_Atomic
  1101.       --    Visibility:   Exported.
  1102.       --    Description:  Determines if S_Expr_Arg is a null or
  1103.       --                  non-atomic expression.
  1104.       --
  1105.       --    Exceptions Raised:  None.
  1106.  
  1107.       function Is_Non_Atomic (S_Expr_Arg : in S_Expr) return Boolean is
  1108.       begin
  1109.      return Is_Null(S_Expr_Arg) or else S_Expr_Arg.Category = Non_Atomic;
  1110.       end Is_Non_Atomic;
  1111.  
  1112.       -------------------------------------------------------------------------
  1113.  
  1114.       --    Function:     Create_Atomic_Node
  1115.       --    Visibility:   Internal.
  1116.       --    Description:  Returns an atomic expression containing the given value.
  1117.       --
  1118.       --    Exceptions Raised:  None.
  1119.  
  1120.       function Create_Atomic_Node (Value_Of_Node : in Atomic_Expr) return S_Expr is
  1121.      New_Node : S_Expr := Null_S_Expr;
  1122.       begin
  1123.  
  1124.      -- If the atomic free list is empty, allocate a new node.
  1125.      -- Otherwise, retrieve a node from the free list.
  1126.  
  1127.      if Is_Null (Atomic_Free_List) then
  1128.         New_Node := new Node (Atomic); 
  1129.      else
  1130.         New_Node := Atomic_Free_List;
  1131.         Atomic_Free_List := Atomic_Free_List.Next_Free;
  1132.      end if;
  1133.  
  1134.      -- Initialize the node's reference counter, free list pointer and value.
  1135.  
  1136.      New_Node.Ref_Count := 0;
  1137.      New_Node.Next_Free := Null_S_Expr;
  1138.      New_Node.Value     := Value_Of_Node;
  1139.  
  1140.      return New_Node;
  1141.       end Create_Atomic_Node;
  1142.  
  1143.       -------------------------------------------------------------------------
  1144.  
  1145.       --    Function:     Create_Atomic_Literal
  1146.       --    Visibility:   Exported.
  1147.       --    Description:  Returns an atomic expression containing
  1148.       --                  the given Literal_Arg.
  1149.       --
  1150.       --    Exceptions Raised:  None.
  1151.  
  1152.       function Create_Atomic_Literal (Literal_Arg : in Atomic_Literal)
  1153.      return S_Expr is
  1154.      Atomic_Value : Atomic_Expr (Kind => Literal);
  1155.       begin
  1156.      Atomic_Value.Literal := Literal_Arg;
  1157.      return Create_Atomic_Node (Value_Of_Node => Atomic_Value);
  1158.       end Create_Atomic_Literal;
  1159.  
  1160.       -------------------------------------------------------------------------
  1161.  
  1162.       --    Function:     Create_Atomic_Variable
  1163.       --    Visibility:   Exported.
  1164.       --    Description:  Creates an atomic variable with the given 
  1165.       --                  name and with its tag initialized to 0.
  1166.       --
  1167.       --    Exceptions Raised:  None.
  1168.  
  1169.       function Create_Atomic_Variable (Name : in String) return S_Expr is
  1170.      Var_Name     : String (1 .. Name'Length) := Name;
  1171.      Var_Value    : Atomic_Variable;
  1172.      Atomic_Value : Atomic_Expr (Kind => Variable);
  1173.       begin
  1174.      case Var_Name'Length is
  1175.         when 1  => Var_Value := (Kind => Var1, Tag => 0, Var1  => Var_Name);
  1176.         when 2  => Var_Value := (Kind => Var2, Tag => 0, Var2  => Var_Name);
  1177.         when 3  => Var_Value := (Kind => Var3, Tag => 0, Var3  => Var_Name);
  1178.         when 4  => Var_Value := (Kind => Var4, Tag => 0, Var4  => Var_Name);
  1179.         when 5  => Var_Value := (Kind => Var5, Tag => 0, Var5  => Var_Name);
  1180.         when 6  => Var_Value := (Kind => Var6, Tag => 0, Var6  => Var_Name);
  1181.         when 7  => Var_Value := (Kind => Var7, Tag => 0, Var7  => Var_Name);
  1182.         when 8  => Var_Value := (Kind => Var8, Tag => 0, Var8  => Var_Name);
  1183.         when 9  => Var_Value := (Kind => Var9, Tag => 0, Var9  => Var_Name);
  1184.         when 10 => Var_Value := (Kind => Var10,Tag => 0, Var10 => Var_Name);
  1185.         when 11 => Var_Value := (Kind => Var11,Tag => 0, Var11 => Var_Name);
  1186.         when 12 => Var_Value := (Kind => Var12,Tag => 0, Var12 => Var_Name);
  1187.         when 13 => Var_Value := (Kind => Var13,Tag => 0, Var13 => Var_Name);
  1188.         when 14 => Var_Value := (Kind => Var14,Tag => 0, Var14 => Var_Name);
  1189.         when 15 => Var_Value := (Kind => Var15,Tag => 0, Var15 => Var_Name);
  1190.         when others => raise Constraint_Error;
  1191.      end case;
  1192.       
  1193.      Atomic_Value.Variable := Var_Value;
  1194.      return Create_Atomic_Node (Value_Of_Node => Atomic_Value);
  1195.       end Create_Atomic_Variable;
  1196.  
  1197.       -------------------------------------------------------------------------
  1198.  
  1199.       --    Procedure:    Set_Variable_Tag
  1200.       --    Visibility:   Exported.
  1201.       --    Description:  Set the tag of the given variable to the given number.
  1202.       --
  1203.       --    Exceptions Raised:  Non_Atomic_Expression - if Atomic_Arg is nonatomic.
  1204.       --                        Not_A_Variable
  1205.       --                            - if the argument does not contain an atomic
  1206.       --                              variable.
  1207.  
  1208.       procedure Set_Variable_Tag (Atomic_Arg : in S_Expr; New_Tag : in Natural) is
  1209.       begin
  1210.      if Is_Non_Atomic (Atomic_Arg) then
  1211.         raise Non_Atomic_Expression; 
  1212.      end if;
  1213.  
  1214.      -- If the expression does not contain an atomic variable, complain.
  1215.      -- Otherwise, set the variable's tag value to the value of the new tag.
  1216.  
  1217.      if Atomic_Arg.Value.Kind /= Variable then
  1218.         raise Not_A_Variable;
  1219.      else
  1220.         Atomic_Arg.Value.Variable.Tag := New_Tag;
  1221.      end if;
  1222.       end Set_Variable_Tag;
  1223.  
  1224.       -------------------------------------------------------------------------
  1225.  
  1226.       --    Function:     Create_Non_Atomic_Node
  1227.       --    Visibility:   Internal.
  1228.       --    Description:  Creates a non_atomic expression with the values of 
  1229.       --                  its First and Rest fields set accordingly.
  1230.       --
  1231.       --    Exceptions Raised:   None.
  1232.  
  1233.       function Create_Non_Atomic_Node (Value_Of_First, 
  1234.                        Value_Of_Rest : in S_Expr := Null_S_Expr)
  1235.      return S_Expr is
  1236.      New_Node : S_Expr := Null_S_Expr;
  1237.       begin
  1238.  
  1239.      -- Adjust the reference count of the value assigned to the First field.
  1240.  
  1241.      if not Is_Null(Value_Of_First) then
  1242.         Value_Of_First.Ref_Count := Value_Of_First.Ref_Count + 1;
  1243.      end if;
  1244.  
  1245.      -- Adjust the reference count of the value assigned to the Rest field.
  1246.  
  1247.      if not Is_Null(Value_Of_Rest) then
  1248.         Value_Of_Rest.Ref_Count := Value_Of_Rest.Ref_Count + 1;
  1249.      end if;
  1250.  
  1251.      -- If the non-atomic node free list is empty, allocate a new node.
  1252.      -- Otherwise, retrieve a node from the free list.
  1253.  
  1254.      if Is_Null (Non_Atomic_Free_List) then
  1255.         New_Node := new Node (Non_Atomic);
  1256.      else
  1257.         New_Node := Non_Atomic_Free_List;
  1258.         Non_Atomic_Free_List := Non_Atomic_Free_List.Rest;
  1259.      end if;
  1260.  
  1261.      -- Initialize the node's reference counter, first and rest field values.
  1262.  
  1263.      New_Node.Ref_Count := 0;
  1264.      New_Node.First     := Value_Of_First;
  1265.      New_Node.Rest      := Value_Of_Rest;
  1266.  
  1267.      return New_Node;
  1268.       end Create_Non_Atomic_Node;
  1269.  
  1270.       -------------------------------------------------------------------------
  1271.  
  1272.       --    Function:     Return_Atomic_Literal
  1273.       --    Visibility:   Exported.
  1274.       --    Description:  Returns the atomic literal contained within the 
  1275.       --                  given expression.
  1276.       --
  1277.       --    Exceptions Raised:   Non_Atomic_Expression
  1278.       --                            -- if the argument is non-atomic.
  1279.       --                         Not_A_Literal
  1280.       --                            -- if the argument does not contain an atomic
  1281.       --                               literal.
  1282.  
  1283.       function Return_Atomic_Literal (Atomic_Arg : in S_Expr) 
  1284.      return Atomic_Literal is
  1285.       begin
  1286.      if Is_Non_Atomic (Atomic_Arg) then
  1287.         raise Non_Atomic_Expression; 
  1288.      end if;
  1289.  
  1290.      -- If the expression does not contain an atomic literal, complain.
  1291.      -- Otherwise, return the literal contained within the expression.
  1292.  
  1293.      if Atomic_Arg.Value.Kind /= Literal then
  1294.         raise Not_A_Literal;
  1295.      else
  1296.         return Atomic_Arg.Value.Literal;
  1297.      end if;
  1298.       end Return_Atomic_Literal;
  1299.  
  1300.       -------------------------------------------------------------------------
  1301.  
  1302.       --    Function:     Return_Variable_Name
  1303.       --    Visibility:   Exported.
  1304.       --    Description:  Returns the name of the variable contained within the
  1305.       --                  argument (concatenated with its tag, if non-zero.)
  1306.       -- 
  1307.       --    Exceptions Raised:  Non_Atomic_Expression - if Atomic_Arg is nonatomic.
  1308.       --                        Not_A_Variable
  1309.       --                            - if the argument does not contain an atomic
  1310.       --                              variable.
  1311.  
  1312.       function Return_Variable_Name (Atomic_Arg : in S_Expr) return String is
  1313.       begin
  1314.      if Is_Non_Atomic (Atomic_Arg) then
  1315.         raise Non_Atomic_Expression; 
  1316.      end if;
  1317.  
  1318.      -- If the expression does not contain an atomic variable, complain.
  1319.      -- Otherwise, return the name of the variable contained within the
  1320.      -- argument (concatenated with its tag if non-zero).
  1321.  
  1322.      if Atomic_Arg.Value.Kind /= Variable then
  1323.         raise Not_A_Variable;
  1324.      elsif Atomic_Arg.Value.Variable.Tag = 0 then
  1325.         case Atomic_Arg.Value.Variable.Kind is
  1326.            when Var1  => return Atomic_Arg.Value.Variable.Var1;
  1327.            when Var2  => return Atomic_Arg.Value.Variable.Var2;
  1328.            when Var3  => return Atomic_Arg.Value.Variable.Var3;
  1329.            when Var4  => return Atomic_Arg.Value.Variable.Var4;
  1330.            when Var5  => return Atomic_Arg.Value.Variable.Var5;
  1331.            when Var6  => return Atomic_Arg.Value.Variable.Var6;
  1332.            when Var7  => return Atomic_Arg.Value.Variable.Var7;
  1333.            when Var8  => return Atomic_Arg.Value.Variable.Var8;
  1334.            when Var9  => return Atomic_Arg.Value.Variable.Var9;
  1335.            when Var10 => return Atomic_Arg.Value.Variable.Var10;
  1336.            when Var11 => return Atomic_Arg.Value.Variable.Var11;
  1337.            when Var12 => return Atomic_Arg.Value.Variable.Var12;
  1338.            when Var13 => return Atomic_Arg.Value.Variable.Var13;
  1339.            when Var14 => return Atomic_Arg.Value.Variable.Var14;
  1340.            when Var15 => return Atomic_Arg.Value.Variable.Var15;
  1341.         end case;
  1342.      else
  1343.         declare
  1344.            Tag_Image : constant String
  1345.                   := Natural'Image(Atomic_Arg.Value.Variable.Tag);
  1346.            Tag_Rep : constant String := Tag_Image (2 .. Tag_Image'Last);
  1347.         begin
  1348.            case Atomic_Arg.Value.Variable.Kind is
  1349.           when Var1  => return Atomic_Arg.Value.Variable.Var1 & Tag_Rep;
  1350.           when Var2  => return Atomic_Arg.Value.Variable.Var2 & Tag_Rep;
  1351.           when Var3  => return Atomic_Arg.Value.Variable.Var3 & Tag_Rep;
  1352.           when Var4  => return Atomic_Arg.Value.Variable.Var4 & Tag_Rep;
  1353.           when Var5  => return Atomic_Arg.Value.Variable.Var5 & Tag_Rep;
  1354.           when Var6  => return Atomic_Arg.Value.Variable.Var6 & Tag_Rep;
  1355.           when Var7  => return Atomic_Arg.Value.Variable.Var7 & Tag_Rep;
  1356.           when Var8  => return Atomic_Arg.Value.Variable.Var8 & Tag_Rep;
  1357.           when Var9  => return Atomic_Arg.Value.Variable.Var9 & Tag_Rep;
  1358.           when Var10 => return Atomic_Arg.Value.Variable.Var10 & Tag_Rep;
  1359.           when Var11 => return Atomic_Arg.Value.Variable.Var11 & Tag_Rep;
  1360.           when Var12 => return Atomic_Arg.Value.Variable.Var12 & Tag_Rep;
  1361.           when Var13 => return Atomic_Arg.Value.Variable.Var13 & Tag_Rep;
  1362.           when Var14 => return Atomic_Arg.Value.Variable.Var14 & Tag_Rep;
  1363.           when Var15 => return Atomic_Arg.Value.Variable.Var15 & Tag_Rep;
  1364.            end case;
  1365.         end;
  1366.      end if;
  1367.       end Return_Variable_Name;
  1368.  
  1369.       -------------------------------------------------------------------------
  1370.  
  1371.       --    Function:     Return_Variable_Tag
  1372.       --    Visibility:   Exported.
  1373.       --    Description:  Get the tag of the given variable.
  1374.       --
  1375.       --    Exceptions Raised:  Non_Atomic_Expression - if Atomic_Arg is nonatomic.
  1376.       --                        Not_A_Variable
  1377.       --                            - if the argument does not contain an atomic
  1378.       --                              variable.
  1379.  
  1380.       function Return_Variable_Tag (Atomic_Arg : in S_Expr) return Natural is
  1381.       begin
  1382.      if Is_Non_Atomic (Atomic_Arg) then
  1383.         raise Non_Atomic_Expression; 
  1384.      end if;
  1385.  
  1386.      -- If the expression does not contain an atomic variable, complain.
  1387.      -- Otherwise, return the value of the variable's tag.
  1388.  
  1389.      if Atomic_Arg.Value.Kind /= Variable then
  1390.         raise Not_A_Variable;
  1391.      else
  1392.         return Atomic_Arg.Value.Variable.Tag;
  1393.      end if;
  1394.       end Return_Variable_Tag;
  1395.  
  1396.       -------------------------------------------------------------------------
  1397.  
  1398.       --    Function:     Compare_Variables
  1399.       --    Visibility:   Internal.
  1400.       --    Description:  Determines if two variables are equivalent.
  1401.       --
  1402.       --    Exceptions Raised:  None.
  1403.  
  1404.       function Compare_Variables (S_Expr_Arg1, S_Expr_Arg2 : in S_Expr)
  1405.      return Boolean is
  1406.       begin
  1407.      return Return_Variable_Name (S_Expr_Arg1)
  1408.            = Return_Variable_Name (S_Expr_Arg2);
  1409.       end Compare_Variables;
  1410.  
  1411.       -------------------------------------------------------------------------
  1412.  
  1413.       --    Procedure:    Push
  1414.       --    Visibility:   Internal.
  1415.       --    Description:  Adds the given Element to the top of the given Stack.
  1416.       --
  1417.       --    Exceptions Raised:  None.
  1418.       
  1419.       procedure Push (Element : in S_Expr;
  1420.               Stack   : in out S_Expr) is
  1421.      Temp : S_Expr := Null_S_Expr;
  1422.       begin
  1423.      Temp := Create_Non_Atomic_Node;
  1424.      Temp.First := Element;
  1425.      Temp.Rest := Stack;
  1426.      Stack := Temp;
  1427.       end Push;
  1428.  
  1429.       -------------------------------------------------------------------------
  1430.  
  1431.       --    Procedure:    Pop
  1432.       --    Visibility:   Internal.
  1433.       --    Description:  Retrieves an element from the top of the given Stack.
  1434.       --
  1435.       --    Exceptions Raised: None.
  1436.        
  1437.       procedure Pop (Stack : in out S_Expr;
  1438.              Pop_Result : out S_Expr) is
  1439.      Temp : S_Expr := Null_S_Expr;
  1440.       begin
  1441.      if Is_Null (Stack.First) then
  1442.         Temp := Stack;
  1443.         Stack := Stack.Rest;
  1444.         Temp.Rest := Non_Atomic_Free_List;
  1445.         Non_Atomic_Free_List := Temp;
  1446.         Pop_Result := Null_S_Expr;
  1447.      else
  1448.         Pop_Result := Stack.First.First;
  1449.         Stack.First := Stack.First.Rest;
  1450.      end if;
  1451.       end Pop;
  1452.  
  1453.       -------------------------------------------------------------------------
  1454.  
  1455.       --    Function:     Is_Equal
  1456.       --    Visibility:   Exported.
  1457.       --    Description:  Determines if two symbolic expressions are equivalent.
  1458.       --
  1459.       --    Exceptions Raised:  None.
  1460.  
  1461.       function Is_Equal (S_Expr_Arg1, S_Expr_Arg2 : in S_Expr) return Boolean is
  1462.       begin
  1463.  
  1464.      -- If the two pointers are equivalent, so are the expressions.
  1465.      if S_Expr_Arg1 = S_Expr_Arg2 then
  1466.         return True;
  1467.  
  1468.      -- Otherwise, determine if the expressions are equal by determining
  1469.      -- if they have the same structure and contents.
  1470.  
  1471.      else
  1472.         declare
  1473.            Equal_Arg1     : S_Expr := S_Expr_Arg1;
  1474.            Equal_Arg2     : S_Expr := S_Expr_Arg2;
  1475.            Equal_Result   : Boolean;
  1476.            Stack1, Stack2 : S_Expr := Null_S_Expr;
  1477.         begin
  1478.  
  1479.            -- Loop until it is determined that the two expressions are
  1480.            -- not equal, or either of the stacks containing sub-expressions
  1481.            -- to be compared are empty.
  1482.  
  1483.            loop
  1484.  
  1485.           -- Break the expressions to be compared into sub-expressions
  1486.           -- by pushing the contents of the Rest field of each non-atomic
  1487.           -- expression onto separate stacks and setting each expression
  1488.           -- to the contents of its First field until either of the
  1489.           -- expressions remaining is atomic.
  1490.  
  1491.           while not Is_Atomic (Equal_Arg1) and then
  1492.             not Is_Atomic (Equal_Arg2) loop
  1493.              Push (Equal_Arg1.Rest, Stack1);
  1494.              Push (Equal_Arg2.Rest, Stack2);
  1495.              Equal_Arg1 := Equal_Arg1.First;
  1496.              Equal_Arg2 := Equal_Arg2.First;
  1497.           end loop;
  1498.  
  1499.           -- Compare the expressions resulting from the previous breakdown.
  1500.           -- If either expression is null, both must be.
  1501.  
  1502.           if Is_Null (Equal_Arg1) or else 
  1503.              Is_Null (Equal_Arg2) then
  1504.              Equal_Result := Equal_Arg1 = Equal_Arg2;
  1505.  
  1506.           -- The categories (Atomic, Non_Atomic) of each
  1507.           -- of the expressions must match.
  1508.  
  1509.           elsif Equal_Arg1.Category /= Equal_Arg2.Category then
  1510.              Equal_Result := False;
  1511.  
  1512.           -- At this point, we know both expressions are non-null atomics.
  1513.  
  1514.           else
  1515.  
  1516.              -- The atomic expressions must both be of the same kind
  1517.              -- (Literal or Variable).
  1518.  
  1519.              if Equal_Arg1.Value.Kind /= Equal_Arg2.Value.Kind then
  1520.             Equal_Result := False;
  1521.  
  1522.              -- If both are literals, compare them as such.
  1523.  
  1524.              elsif Equal_Arg1.Value.Kind = Literal then
  1525.             Equal_Result := Is_Equal (Equal_Arg1.Value.Literal,
  1526.                           Equal_Arg2.Value.Literal);
  1527.  
  1528.              -- Otherwise, compare them as variables.
  1529.  
  1530.              else
  1531.             Equal_Result := Compare_Variables (Equal_Arg1, Equal_Arg2);
  1532.              end if;
  1533.           end if;
  1534.  
  1535.           exit when not Equal_Result or else
  1536.                 Is_Null (Stack1) or else
  1537.                 Is_Null (Stack2);
  1538.  
  1539.           -- We haven't exited the loop, so the expressions must be
  1540.           -- equivalent thus far and there must be sub-expressions
  1541.           -- remaining to be compared.  Get the next set of
  1542.           -- sub-expressions and continue the comparison.
  1543.  
  1544.           Pop (Stack1, Equal_Arg1);
  1545.           Pop (Stack2, Equal_Arg2);
  1546.            end loop;
  1547.  
  1548.            return Equal_Result;
  1549.         end;
  1550.      end if;
  1551.       end Is_Equal;
  1552.  
  1553.       -------------------------------------------------------------------------
  1554.  
  1555.       --    Function:     Is_Member
  1556.       --    Visibility:   Exported.
  1557.       --    Description:  Determines if the S_Expr_Arg is a top-level member
  1558.       --                  of the given Non_Atomic_Arg.
  1559.       --
  1560.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  1561.       
  1562.       function Is_Member (S_Expr_Arg, Non_Atomic_Arg : in S_Expr) return Boolean is
  1563.       begin
  1564.  
  1565.      -- Nothing is a member of Null_S_Expr.
  1566.  
  1567.      if Is_Null (Non_Atomic_Arg) then
  1568.         return False;
  1569.  
  1570.      -- Non_Atomic_Arg must be non-atomic.
  1571.  
  1572.      elsif Is_Atomic (Non_Atomic_Arg) then
  1573.         raise Atomic_Expression;
  1574.  
  1575.      -- Continue the search.
  1576.  
  1577.      else
  1578.         declare
  1579.            Member_Arg    : S_Expr := Non_Atomic_Arg;
  1580.            Member_Result : Boolean;
  1581.         begin
  1582.  
  1583.            -- Member_Arg is a pointer to the first component of the 
  1584.            -- symbolic expression. Loop until we have found a component
  1585.            -- which matches S_Expr_Arg (in which case, Is_Member returns
  1586.            -- True) or until there are no components left with which to
  1587.            -- compare it (in which case, Is_Member returns false).
  1588.            loop
  1589.           Member_Result := Is_Equal (S_Expr_Arg, Member_Arg.First);
  1590.           Member_Arg := Member_Arg.Rest;
  1591.  
  1592.           exit when Member_Result or else Is_Null (Member_Arg);
  1593.            end loop;
  1594.            return Member_Result;
  1595.         end;
  1596.      end if;
  1597.       end Is_Member;
  1598.  
  1599.       -------------------------------------------------------------------------
  1600.  
  1601.       --    Procedure:    Free
  1602.       --    Visibility:   Exported.
  1603.       --    Description:  Frees the given symbolic expression.
  1604.       -- 
  1605.       --    Exceptions Raised:  None.
  1606.  
  1607.       procedure Free (S_Expr_Arg : in out S_Expr) is
  1608.      Stack, Temp : S_Expr := Null_S_Expr;
  1609.       begin
  1610.      -- Loop until the stack is empty.
  1611.      loop
  1612.  
  1613.         -- Only non-null symbolic expressions need to be freed.
  1614.         while not Is_Null (S_Expr_Arg) loop
  1615.  
  1616.            -- If the reference count of the symbolic expression is 
  1617.            -- greater than one (there is more than one variable of type
  1618.            -- S_Expr which refers to this structure), we don't want to
  1619.            -- return its storage to the free lists.  Just decrement the
  1620.            -- reference counter.
  1621.  
  1622.            if S_Expr_Arg.Ref_Count > 1 then
  1623.           S_Expr_Arg.Ref_Count := S_Expr_Arg.Ref_Count - 1;
  1624.           S_Expr_Arg := Null_S_Expr;
  1625.  
  1626.            -- If the symbolic expression is non-atomic,
  1627.            -- process its first field, and set the expression to the
  1628.            -- contents of its rest field freeing the non-atomic node
  1629.            -- in the process.
  1630.  
  1631.            elsif Is_Non_Atomic (S_Expr_Arg) then
  1632.           -- Only non-null components have to freed.
  1633.  
  1634.           if not Is_Null (S_Expr_Arg.First) then
  1635.  
  1636.              -- If more than one variable still refers to the
  1637.              -- component being examined, decrement the ref count.
  1638.  
  1639.              if S_Expr_Arg.First.Ref_Count > 1 then
  1640.             S_Expr_Arg.First.Ref_Count :=
  1641.                 S_Expr_Arg.First.Ref_Count - 1;
  1642.  
  1643.              -- If the component is atomic, add it to the 
  1644.              -- atomic free list.
  1645.  
  1646.              elsif Is_Atomic (S_Expr_Arg.First) then
  1647.             S_Expr_Arg.First.Next_Free := Atomic_Free_List;
  1648.             Atomic_Free_List := S_Expr_Arg.First;
  1649.  
  1650.              -- Otherwise, push the non-atomic component
  1651.              -- onto the stack.
  1652.  
  1653.              else
  1654.             Push (S_Expr_Arg.First, Stack);
  1655.              end if;
  1656.           end if;
  1657.  
  1658.           -- Set a pointer to the first non-atomic node in the
  1659.           -- current expression. Make the remaining components
  1660.           -- (the contents of the Rest field) the new current
  1661.           -- expression. Push the non-atomic node onto the non-
  1662.           -- atomic free list by setting the First field of the
  1663.           -- non-atomic node to null, the Rest field to the head
  1664.           -- pointer of the non-atomic free list and the head pointer
  1665.           -- of the non-atomic free list to the new non-atomic node.
  1666.  
  1667.           Temp := S_Expr_Arg;
  1668.           S_Expr_Arg := S_Expr_Arg.Rest;
  1669.           Temp.First := Null_S_Expr;
  1670.           Temp.Rest := Non_Atomic_Free_List;
  1671.           Non_Atomic_Free_List := Temp;
  1672.           
  1673.            -- Otherwise, we have an atomic expression to be freed.
  1674.  
  1675.            else
  1676.           S_Expr_Arg.Next_Free := Atomic_Free_List;
  1677.           Atomic_Free_List := S_Expr_Arg;
  1678.           S_Expr_Arg := Null_S_Expr;
  1679.            end if;
  1680.         end loop;
  1681.  
  1682.         exit when Is_Null (Stack);
  1683.   
  1684.         -- If we haven't exited, there must be more non-atomic
  1685.         -- components to be freed.  Get a new current expression
  1686.         -- off the stack and free up the stack node which was 
  1687.         -- holding it.
  1688.  
  1689.         S_Expr_Arg := Stack.First;
  1690.         Temp := Stack;
  1691.         Stack := Stack.Rest;
  1692.         Temp.First := Null_S_Expr;
  1693.         Temp.Rest := Non_Atomic_Free_List;
  1694.         Non_Atomic_Free_List := Temp;
  1695.      end loop;
  1696.       end Free;
  1697.  
  1698.       -------------------------------------------------------------------------
  1699.  
  1700.       --    Function:     Return_And_Free
  1701.       --    Visibility:   Exported.
  1702.       --    Description:  Provides a way for decrementing the ref-count of a
  1703.       --                  symbolic expression bound to a local variable being
  1704.       --                  returned from a function.
  1705.       -- 
  1706.       --    Exceptions Raised:  None.
  1707.  
  1708.       function Return_And_Free (S_Expr_Arg : in S_Expr) return S_Expr is
  1709.       begin
  1710.      if not Is_Null(S_Expr_Arg) and then
  1711.         S_Expr_Arg.Ref_Count > 0 then
  1712.         S_Expr_Arg.Ref_Count := S_Expr_Arg.Ref_Count - 1;
  1713.      end if;
  1714.  
  1715.      return S_Expr_Arg;
  1716.       end Return_And_Free;
  1717.  
  1718.       -------------------------------------------------------------------------
  1719.  
  1720.       --    Procedure:    Bind
  1721.       --    Visibility:   Exported.
  1722.       --    Description:  Sets the value of Current_Value to New_Value.
  1723.       --
  1724.       --    Exceptions Raised:  None.
  1725.  
  1726.       procedure Bind (Current_Value : in out S_Expr; New_Value : in S_Expr) is
  1727.      Temp_Value : S_Expr := Current_Value;
  1728.       begin
  1729.  
  1730.      -- Ignore cases of Bind (X, X).
  1731.  
  1732.      if Current_Value /= New_Value then
  1733.         Current_Value := New_Value;
  1734.           
  1735.         -- Increment the ref-count.
  1736.  
  1737.         if not Is_Null (Current_Value) then
  1738.            Current_Value.Ref_Count := Current_Value.Ref_Count + 1;
  1739.         end if;
  1740.  
  1741.         -- Free the original symbolic expression.
  1742.  
  1743.         if not Is_Null (Temp_Value) then
  1744.            Free (Temp_Value);
  1745.         end if;
  1746.      end if;
  1747.       end Bind;
  1748.  
  1749.       -------------------------------------------------------------------------
  1750.  
  1751.       --    Procedure:    Print_Non_Atomic_Fl
  1752.       --    Visibility:   Internal.
  1753.       --    Description:  Diagnostic function to print the current contents of
  1754.       --                  the non-atomic free list.
  1755.       --
  1756.       --    Exceptions Raised: None.
  1757.  
  1758.       procedure Print_Non_Atomic_Fl is
  1759.      Temp : S_Expr := Non_Atomic_Free_List;
  1760.       begin
  1761.      Put ("( ");
  1762.  
  1763.      -- Loop until all nodes have been examined.
  1764.  
  1765.      while not Is_Null (Temp) loop
  1766.  
  1767.         -- Make sure that only empty non-atomic nodes are on the
  1768.         -- non-atomic free list by printing "()" if the First field
  1769.         -- of the node is null, "X" if not.
  1770.  
  1771.         if Is_Null (Temp.First) then
  1772.            Put ("() ");
  1773.         else
  1774.            Put ("X ");
  1775.         end if;
  1776.  
  1777.         -- Set the current pointer to next node in the free list.
  1778.  
  1779.         Temp := Temp.Rest;
  1780.      end loop;
  1781.  
  1782.      Put (")");
  1783.       end Print_Non_Atomic_Fl;
  1784.  
  1785.       -------------------------------------------------------------------------
  1786.  
  1787.       --    Procedure:    Print_Atomic_Fl 
  1788.       --    Visibility:   Internal.
  1789.       --    Description:  Diagnostic function to print the contents of the 
  1790.       --                  atomic free list.
  1791.       -- 
  1792.       --    Exceptions Raised:  None.
  1793.  
  1794.       procedure Print_Atomic_Fl is
  1795.      Temp : S_Expr := Atomic_Free_List;
  1796.       begin
  1797.      Put ("( ");
  1798.  
  1799.      -- Loop until all nodes in the atomic free list have been examined.
  1800.  
  1801.      while not Is_Null (Temp) loop
  1802.  
  1803.         -- If the node on the free list is a variable, print the variable
  1804.         -- prefix and the variable name.
  1805.  
  1806.         if Is_Variable (Temp) then
  1807.            Put ("?");
  1808.            Put (Return_Variable_Name (Temp));
  1809.            Put (" ");
  1810.  
  1811.         -- If the node is an atomic literal, print it out.
  1812.  
  1813.         elsif not Is_Non_Atomic (Temp) then
  1814.            Put (Current_Output, Return_Atomic_Literal (Temp));
  1815.            Put (" ");
  1816.  
  1817.         -- Otherwise, indicate that something's wrong by printing an "X".
  1818.  
  1819.         else
  1820.            Put ("X ");
  1821.         end if;
  1822.  
  1823.         Temp := Temp.Next_Free;
  1824.      end loop;
  1825.  
  1826.      Put (")");
  1827.       end Print_Atomic_Fl;
  1828.  
  1829.       -------------------------------------------------------------------------
  1830.  
  1831.       --    Procedure:    Get 
  1832.       --    Visibility:   Exported.
  1833.       --    Description:  Read a symbolic expression from the given file.
  1834.       --
  1835.       --    Exceptions Raised: Extra_Separator,, Missing_Separator
  1836.       --                       Impromper_Input, Invalid_Varable_Name.
  1837.  
  1838.       procedure Get (Input_File : in File_Type;
  1839.              S_Expr_Result : in out S_Expr) is
  1840.      Input_Char        : Character;
  1841.      Non_Atomic_Prefix : constant Character := '(';
  1842.      Non_Atomic_Suffix : constant Character := ')';
  1843.      Variable_Prefix   : constant Character := '?';
  1844.      Separator         : constant Character := ',';
  1845.      Literal_Value     : Atomic_Literal;
  1846.  
  1847.      ----------------------------------------------------------------------
  1848.  
  1849.      --    Procedure:    Get_Next_Char 
  1850.      --    Visibility:   Internal.
  1851.      --    Description:  Return the next character to be processed.
  1852.      --
  1853.      --    Exceptions Raised: None.
  1854.  
  1855.      procedure Get_Next_Char is
  1856.      begin
  1857.  
  1858.         -- If we've looked at a character previously without
  1859.         -- processing it, make it the next character to be processed.
  1860.  
  1861.         if Lookahead /= ' ' then
  1862.            Input_Char := Lookahead;
  1863.            Lookahead := ' ';
  1864.  
  1865.         -- Otherwise, read the next non-blank character from the file.
  1866.  
  1867.         else
  1868.            loop
  1869.           Get (Input_File, Input_Char);
  1870.           exit when Input_Char /= ' ';
  1871.            end loop;
  1872.         end if;
  1873.      end Get_Next_Char;
  1874.  
  1875.      ----------------------------------------------------------------------
  1876.  
  1877.      --    Function:     Get_Variable_Rep 
  1878.      --    Visibility:   Internal.
  1879.      --    Description:  Returns a string containing the character 
  1880.      --                  representation of the next atomic expression
  1881.      --                  to be processed.
  1882.      --
  1883.      --    Exceptions Raised: None.
  1884.  
  1885.      function Get_Variable_Rep return String is
  1886.         Max_Buffer_Length : constant Natural := 255;
  1887.         Position          : Natural range 0 .. Max_Buffer_Length := 0;
  1888.         Atom_Buffer       : String (1 .. Max_Buffer_Length);
  1889.      begin
  1890.  
  1891.         -- Read characters from the file and put them in a 
  1892.         -- buffer until finding a separator, blank, non-atomic suffix
  1893.         -- or the end of the line.
  1894.  
  1895.         while Input_Char /= Separator and then
  1896.           Input_Char /= ' ' and then
  1897.           Input_Char /= Non_Atomic_Suffix loop
  1898.            Position := Position + 1;
  1899.            Atom_Buffer (Position) := Input_Char;
  1900.  
  1901.            exit when End_Of_Line (Input_File);
  1902.  
  1903.            Get (Input_File, Input_Char);
  1904.         end loop;
  1905.  
  1906.         if Input_Char = Separator or else
  1907.            Input_Char = Non_Atomic_Suffix then
  1908.            Lookahead := Input_Char;
  1909.         end if;
  1910.  
  1911.         return Atom_Buffer (1 .. Position);
  1912.      end Get_Variable_Rep;
  1913.  
  1914.      ----------------------------------------------------------------------
  1915.  
  1916.      --    Procedure:    Check_For_Separator 
  1917.      --    Visibility:   Internal.
  1918.      --    Description:  Determines if there are separator characters
  1919.      --                  where they're supposed to be.
  1920.      --
  1921.      --    Exceptions Raised: None.
  1922.  
  1923.          procedure Check_For_Separator is
  1924.         Original : Character := Input_Char;
  1925.      begin
  1926.         Get_Next_Char;
  1927.  
  1928.         -- Non_Atomic_Suffixes should not have Separators in front of them.
  1929.  
  1930.         if Input_Char = Non_Atomic_Suffix then
  1931.            Lookahead := Non_Atomic_Suffix;
  1932.  
  1933.         -- If we find a Separator ...
  1934.         elsif Input_Char = Separator then
  1935.  
  1936.            -- Get the next character.   If it's a Non_Atomic_Suffix
  1937.            -- or another Separator, there's an extra Separator character.
  1938.            -- Otherwise, just push back the character.
  1939.  
  1940.            Get_Next_Char;
  1941.            if Input_Char = Non_Atomic_Suffix or else
  1942.           Input_Char = Separator then
  1943.           raise Extra_Separator;
  1944.            else
  1945.           Lookahead := Input_Char;
  1946.            end if;
  1947.  
  1948.         -- If we find any other character, we're missing a separator.
  1949.  
  1950.         else
  1951.            raise Missing_Separator;
  1952.         end if;
  1953.  
  1954.         Input_Char := Original;
  1955.      end Check_For_Separator;
  1956.  
  1957.       begin
  1958.      -- Free any previous value.
  1959.  
  1960.      if not Is_Null (S_Expr_Result) then
  1961.         Free (S_Expr_Result);
  1962.      end if;
  1963.  
  1964.      Get_Next_Char;
  1965.  
  1966.      case Input_Char is
  1967.  
  1968.         -- Can't start off with a suffix or separator. 
  1969.  
  1970.         when Non_Atomic_Suffix | Separator =>
  1971.            raise Improper_Input;
  1972.  
  1973.         -- If there's a non-atomic prefix, build a non-atomic expression.
  1974.  
  1975.         when Non_Atomic_Prefix =>
  1976.            Get_Next_Char;
  1977.  
  1978.            -- If we find a non-atomic suffix right after a non-atomic prefix
  1979.            -- return a null.  Otherwise, continue processing the expression.
  1980.  
  1981.            if Input_Char = Non_Atomic_Suffix then
  1982.           S_Expr_Result := Null_S_Expr;
  1983.  
  1984.            -- Can't have a separator character after a prefix.
  1985.  
  1986.            elsif Input_Char = Separator then
  1987.           raise Extra_Separator;
  1988.            else
  1989.  
  1990.           -- Create the first non-atomic node and set a pointer to it.
  1991.  
  1992.           S_Expr_Result := Create_Non_Atomic_Node;
  1993.           declare
  1994.              Current : S_Expr := S_Expr_Result;     -- Roving pointer.
  1995.              Temp_Current : S_Expr := Null_S_Expr;  -- Temp pointer.
  1996.              Dont_Move : Boolean := False;          -- Flag.
  1997.           begin
  1998.              loop
  1999.             case Input_Char is
  2000.  
  2001.                -- If we find a non-atomic suffix, check for a
  2002.                -- separator, then terminate the rest field with
  2003.                -- a null and follow the pointer in the rest field
  2004.                -- (which was placed there on the way down)
  2005.                -- up to the next higher level.
  2006.  
  2007.                when Non_Atomic_Suffix =>
  2008.                   Temp_Current := Current.Rest;
  2009.                   Current.Rest := Null_S_Expr;
  2010.                   Current := Temp_Current;
  2011.  
  2012.                   -- Make sure this isn't the last suffix
  2013.                   -- then check for a separator.
  2014.                   if not Is_Null (Current) then
  2015.                  Check_For_Separator;
  2016.                   end if;
  2017.  
  2018.                -- If we find a prefix, create a non-atomic component
  2019.  
  2020.                when Non_Atomic_Prefix =>
  2021.                  
  2022.                   -- While we keep finding non-atomic prefixes,
  2023.                   -- check for separators (there shouldn't be any)
  2024.                   -- and non-atomic suffixes (for nulls).
  2025.                   -- If there are none, create another non-atomic
  2026.                   -- node, add it to the first field and set the
  2027.                   -- rest field to point to the node we've just
  2028.                   -- added it to.
  2029.  
  2030.                   loop
  2031.                  Get_Next_Char;
  2032.  
  2033.                  if Input_Char = Separator then
  2034.                     raise Extra_Separator;
  2035.                  elsif Input_Char = Non_Atomic_Suffix then
  2036.                     -- Look for separator.
  2037.                     Check_For_Separator;
  2038.                  else
  2039.  
  2040.                     -- NOTE: If we don't find a non-atomic
  2041.                     -- suffix or prefix, we have to add
  2042.                     -- something to the first field.  So,
  2043.                     -- make it the next character to be
  2044.                     -- processed and don't add a non-atomic
  2045.                     -- node to the rest field at the bottom of
  2046.                     -- the loop.
  2047.  
  2048.                     if Input_Char /= Non_Atomic_Prefix then
  2049.                        Lookahead := Input_Char;
  2050.                        Dont_Move := True;
  2051.                     end if;
  2052.                     Bind (Current.First, Create_Non_Atomic_Node);
  2053.                     Current.First.Rest := Current;
  2054.                     Current := Current.First;
  2055.                  end if;
  2056.                  exit when Input_Char /= Non_Atomic_Prefix;
  2057.                   end loop;
  2058.  
  2059.                -- If we find a variable prefix, check for a valid
  2060.                -- (non-null) variable name, create a variable
  2061.                -- and check for a separator.
  2062.  
  2063.                when Variable_Prefix =>
  2064.                   Get_Next_Char;
  2065.                   if Input_Char = Separator or else
  2066.                  Input_Char = Non_Atomic_Prefix or else
  2067.                  Input_Char = Non_Atomic_Suffix then
  2068.                  raise Invalid_Variable_Name;
  2069.                   end if;
  2070.                   Bind (Current.First,
  2071.                     Create_Atomic_Variable (Get_Variable_Rep));
  2072.                   Check_For_Separator;
  2073.  
  2074.                -- Otherwise, create a literal.
  2075.  
  2076.                when others =>
  2077.                   Lookahead := Input_Char;
  2078.                   Get (Input_File, Literal_Value);
  2079.                   Bind (Current.First,
  2080.                     Create_Atomic_Literal (Literal_Value));
  2081.                   Check_For_Separator;
  2082.             end case;
  2083.  
  2084.             exit when Is_Null (Current);
  2085.  
  2086.             Get_Next_Char;
  2087.  
  2088.             -- Determine if a non-atomic node has to be added to
  2089.             -- the rest field of the node currently being processed.
  2090.  
  2091.             -- If we still have to add something to the current node
  2092.             -- or we want to terminate the node, don't add anything.
  2093.             -- Otherwise, add a non-atomic node.
  2094.  
  2095.             if Dont_Move or else
  2096.                Input_Char = Non_Atomic_Suffix then
  2097.                Dont_Move := False;
  2098.             else
  2099.                Temp_Current := Create_Non_Atomic_Node;
  2100.                Temp_Current.Rest := Current.Rest;
  2101.                Current.Rest := Null_S_Expr;
  2102.                Bind (Current.Rest, Temp_Current);
  2103.                Current := Current.Rest;
  2104.             end if;
  2105.              end loop;
  2106.           end;
  2107.            end if;
  2108.  
  2109.         -- If there's a variable prefix, build a variable after
  2110.         -- checking for a valid name.
  2111.  
  2112.         when Variable_Prefix =>
  2113.            Get_Next_Char;
  2114.            if Input_Char = Separator or else
  2115.           Input_Char = Non_Atomic_Prefix or else
  2116.           Input_Char = Non_Atomic_Suffix then
  2117.           raise Invalid_Variable_Name;
  2118.            end if;
  2119.            S_Expr_Result := Create_Atomic_Variable (Get_Variable_Rep);
  2120.  
  2121.         -- Otherwise, build an atomic literal.
  2122.  
  2123.         when others => 
  2124.            Lookahead := Input_Char;
  2125.            Get (Input_File, Literal_Value);
  2126.            S_Expr_Result := Create_Atomic_Literal (Literal_Value);
  2127.      end case;
  2128.  
  2129.      -- Set the ref-count and return the pointer
  2130.      -- to the beginning of the structure created.
  2131.  
  2132.      if not Is_Null (S_Expr_Result) then
  2133.         S_Expr_Result.Ref_Count := 1;
  2134.      end if;
  2135.  
  2136.      exception
  2137.         when others =>
  2138.            Lookahead := ' ';
  2139.            raise;
  2140.       end Get;
  2141.  
  2142.       -------------------------------------------------------------------------
  2143.  
  2144.       --    Procedure:    Get 
  2145.       --    Visibility:   Exported.
  2146.       --    Description:  Read a symbolic expression from
  2147.       --                  the current input file.
  2148.       -- 
  2149.       --    Exceptions Raised: None.
  2150.  
  2151.       procedure Get (S_Expr_Result : in out S_Expr) is
  2152.       begin 
  2153.      Get (Current_Input, S_Expr_Result);
  2154.       end Get;
  2155.  
  2156.       -------------------------------------------------------------------------
  2157.  
  2158.       --    Procedure:    Put
  2159.       --    Visibility:   Exported.
  2160.       --    Description:  Print the structure of the input symbolic expression
  2161.       --                  to the specified output file.
  2162.       -- 
  2163.       --    Exceptions Raised: None.
  2164.  
  2165.       procedure Put (Output_File : in File_Type; S_Expr_Arg : in S_Expr) is
  2166.      Non_Atomic_Prefix : constant Character := '(';
  2167.      Non_Atomic_Suffix : constant Character := ')';
  2168.      Variable_Prefix   : constant Character := '?';
  2169.      Separator         : constant String := ", ";
  2170.  
  2171.      Separator_Needed  : Boolean := False;
  2172.      Stack             : S_Expr  := Null_S_Expr;
  2173.      S_Expr_Ref        : S_Expr  := S_Expr_Arg;
  2174.       begin
  2175.  
  2176.      -- If null, print representation of null: a non-atomic prefix followed
  2177.      -- by a non-atomic suffix.
  2178.  
  2179.      if Is_Null (S_Expr_Ref) then
  2180.         Put (Output_File, Non_Atomic_Prefix);
  2181.         Put (Output_File, Non_Atomic_Suffix);
  2182.      else
  2183.  
  2184.         -- Loop until the symbolic expression has been printed in its entirety.
  2185.  
  2186.         loop
  2187.  
  2188.            -- If the current expression is non-atomic ...
  2189.            if not Is_Atomic (S_Expr_Ref) then
  2190.           if Separator_Needed then
  2191.              Put (Output_File, Separator);
  2192.              Separator_Needed := False;
  2193.           end if;
  2194.  
  2195.           -- Do a depth-first traversal of the current symbolic expression.
  2196.           -- For each non-atomic node, print a non-atomic prefix,
  2197.           -- push the contents of the Rest field onto a stack and 
  2198.           -- set the current symbolic expression to the contents of
  2199.           -- the First field. Continue until the current symbolic 
  2200.           -- expression is atomic.
  2201.  
  2202.           loop
  2203.              Put (Output_File, Non_Atomic_Prefix);
  2204.              Push (S_Expr_Ref.Rest, Stack);
  2205.              S_Expr_Ref := S_Expr_Ref.First;
  2206.              exit when Is_Atomic (S_Expr_Ref);
  2207.           end loop;
  2208.  
  2209.           -- If the current symbolic expression is null, print a prefix.
  2210.  
  2211.           if Is_Null (S_Expr_Ref) then
  2212.              Put (Output_File, Non_Atomic_Prefix);
  2213.           end if;
  2214.            end if;
  2215.  
  2216.            -- If the current symbolic expression is null, print a suffix,
  2217.            -- pop the next expression to be printed (if there is one)
  2218.            -- off the stack and print any necessary separators.
  2219.  
  2220.            if Is_Null (S_Expr_Ref) then
  2221.           Put (Output_File, Non_Atomic_Suffix);
  2222.  
  2223.           if not Is_Null (Stack) then
  2224.              if not Is_Null (Stack.First) then
  2225.             Put (Output_File, Separator);
  2226.              end if;
  2227.           end if;
  2228.  
  2229.           Separator_Needed := False;
  2230.  
  2231.            -- If the current symbolic expression is a variable, print 
  2232.            -- any necessary separators, the variable prefix and the 
  2233.            -- name of the variable.
  2234.  
  2235.            elsif Is_Variable (S_Expr_Ref) then
  2236.           if Separator_Needed then
  2237.              Put (Output_File, Separator);
  2238.           else
  2239.              Separator_Needed := True;
  2240.           end if;
  2241.  
  2242.           Put (Output_File, Variable_Prefix);
  2243.           Put (Output_File, Return_Variable_Name (Atomic_Arg => S_Expr_Ref));
  2244.  
  2245.            -- If the current symbolic expression is atomic, print 
  2246.            -- any necessary separators and the representation of the literal.
  2247.  
  2248.            elsif Is_Atomic (S_Expr_Ref) then
  2249.           if Separator_Needed then
  2250.              Put (Output_File, Separator);
  2251.           else
  2252.              Separator_Needed := True;
  2253.           end if;
  2254.  
  2255.           Put (Output_File, Return_Atomic_Literal (Atomic_Arg => S_Expr_Ref));
  2256.            end if;
  2257.  
  2258.            exit when Is_Null (Stack);
  2259.  
  2260.            -- We haven't exited, so there must be more sub-expressions
  2261.            -- to print.
  2262.  
  2263.            -- If the contents of the first expression on the stack is 
  2264.            -- not null ...
  2265.  
  2266.            if not Is_Null (Stack.First) then
  2267.  
  2268.           -- If the contents of the first component of the first
  2269.           -- expression on the stack is null, print any necessary
  2270.           -- separators and a non-atomic prefix.
  2271.  
  2272.           if Is_Null (Stack.First.First) then
  2273.              if Separator_Needed then
  2274.             Put (Output_File, Separator);
  2275.             Separator_Needed := False;
  2276.              end if;
  2277.              Put (Output_File, Non_Atomic_Prefix);
  2278.           end if;
  2279.            end if;
  2280.  
  2281.            -- Get the next expression off the stack.
  2282.  
  2283.            Pop (Stack, S_Expr_Ref);
  2284.         end loop;
  2285.      end if;
  2286.       end Put;
  2287.  
  2288.       -------------------------------------------------------------------------
  2289.  
  2290.       --    Procedure:    Put 
  2291.       --    Visibility:   Exported.
  2292.       --    Description:  Print the structure of the input symbolic expression
  2293.       --                  to the current default output file.
  2294.       --
  2295.       --    Exceptions Raised: None.
  2296.  
  2297.       procedure Put (S_Expr_Arg : in S_Expr) is
  2298.       begin
  2299.      Put (Current_Output, S_Expr_Arg);
  2300.       end Put;
  2301.  
  2302.       -------------------------------------------------------------------------
  2303.  
  2304.       --    Function:     Prefix 
  2305.       --    Visibility:   Exported.
  2306.       --    Description:  If the second argument is atomic, Prefix returns
  2307.       --                  an expression, X, such that First(X)=First_Value
  2308.       --                  and First (Rest (X)) = Rest_Value.  Otherwise, it returns
  2309.       --                  an expression, Y, such that First(Y) = First_Value and
  2310.       --                  Rest(Y) = Rest_Value.
  2311.       -- 
  2312.       --    Exceptions Raised: None.
  2313.  
  2314.       function Prefix (First_Value : in S_Expr;
  2315.                Rest_Value  : in S_Expr := Null_S_Expr) return S_Expr is
  2316.       begin
  2317.  
  2318.      -- If the second argument is null, create an expression of one component.
  2319.  
  2320.      if Is_Null(Rest_Value) then
  2321.         return Create_Non_Atomic_Node (Value_Of_First => First_Value);
  2322.  
  2323.      -- If the second argument is atomic, create an additional non-atomic
  2324.      -- node, set its First field to the second argument and create an 
  2325.      -- expression from the first argument and newly created non-atomic node.
  2326.  
  2327.      elsif Is_Atomic(Rest_Value) then
  2328.         return Create_Non_Atomic_Node (
  2329.               Value_Of_First => First_Value,
  2330.               Value_Of_Rest => Create_Non_Atomic_Node (
  2331.                       Value_Of_First => Rest_Value));
  2332.  
  2333.      -- Otherwise, return a non-atomic node with its First and Rest fields
  2334.      -- set to the Value_Of_First and Value_of_Rest, respectively.
  2335.  
  2336.      else
  2337.         return Create_Non_Atomic_Node (
  2338.               Value_Of_First => First_Value,
  2339.               Value_Of_Rest => Rest_Value);
  2340.      end if;
  2341.       end Prefix;
  2342.  
  2343.       -------------------------------------------------------------------------
  2344.  
  2345.       --    Function:     Length 
  2346.       --    Visibility:   Exported.
  2347.       --    Description:  Returns 0 for atomic expressions or the number of 
  2348.       --                  top level components for non-atomic expressions.
  2349.       -- 
  2350.       --    Exceptions Raised:  None.
  2351.  
  2352.       function Length (S_Expr_Arg : in S_Expr) return Natural is
  2353.     Length_Value : Natural := 0;
  2354.     Length_Arg   : S_Expr  := S_Expr_Arg;
  2355.       begin
  2356.      if not Is_Atomic (Length_Arg) then
  2357.         loop
  2358.            Length_Value := Length_Value + 1;
  2359.            Length_Arg := Length_Arg.Rest;
  2360.            exit when Is_Null (Length_Arg);
  2361.         end loop;
  2362.      end if;
  2363.  
  2364.      return Length_Value;
  2365.       end Length;
  2366.  
  2367.       -------------------------------------------------------------------------
  2368.  
  2369.       --    Function:     "&" 
  2370.       --    Visibility:   Exported.
  2371.       --    Description:  Returns a symbolic expression composed of the elements
  2372.       --                  of each of the input arguments.
  2373.       --
  2374.       --    Exceptions Raised:  None.
  2375.  
  2376.       function "&" (S_Expr_Arg1, S_Expr_Arg2 : in S_Expr) return S_Expr is
  2377.       begin
  2378.  
  2379.      -- If both arguments are null, they have no elements, return null.
  2380.  
  2381.      if Is_Null (S_Expr_Arg1) and Is_Null (S_Expr_Arg2) then
  2382.         return Null_S_Expr;
  2383.      else
  2384.         declare
  2385.            Front_Arg, Back_Arg : S_Expr := Null_S_Expr;
  2386.         begin
  2387.  
  2388.            -- Create the second part of the result.
  2389.            -- If the second input argument is a non-null atomic expression,
  2390.            -- create a non-atomic node containing the second input argument as
  2391.            -- the value of its first field.  Otherwise, the second part of the
  2392.            -- result is the second input argument itself.
  2393.  
  2394.            if not Is_Non_Atomic (S_Expr_Arg2) then
  2395.           Back_Arg := Create_Non_Atomic_Node(Value_Of_First=> S_Expr_Arg2);
  2396.            else
  2397.           Back_Arg := S_Expr_Arg2;
  2398.            end if;
  2399.  
  2400.            -- Create the result by appending the second part of the result
  2401.            -- (created above) to a copy of the first input argument.
  2402.  
  2403.            -- If the first input argument is a non-null atomic argument,
  2404.            -- create a non-atomic containing a copy of the first input argument
  2405.            -- in its first field and the second part of the result in its
  2406.            -- rest field.
  2407.  
  2408.            if not Is_Non_Atomic (S_Expr_Arg1) then
  2409.           Front_Arg := Create_Non_Atomic_Node(Value_Of_First=>S_Expr_Arg1);
  2410.           Bind (Front_Arg.Rest, Back_Arg);
  2411.  
  2412.            -- If the first input argument is a non-null non-atomic argument,
  2413.            -- create a copy of the first input argument, find the last
  2414.            -- non-atomic node in the copy and set the rest field of the last
  2415.            -- node to the second part of the result.
  2416.  
  2417.            elsif not Is_Atomic (S_Expr_Arg1) then
  2418.           declare
  2419.              Nth_Arg, Current : S_Expr;
  2420.           begin
  2421.              for Position in reverse 1 .. Length (S_Expr_Arg1) loop
  2422.             Nth_Arg := S_Expr_Arg1;
  2423.             for Node_Number in 1 .. Position-1 loop
  2424.                Nth_Arg := Nth_Arg.Rest;
  2425.             end loop;
  2426.             Front_Arg := Prefix (Nth_Arg.First, Front_Arg);
  2427.              end loop;
  2428.  
  2429.              Current := Front_Arg;
  2430.  
  2431.              while not Is_Null (Current.Rest) loop
  2432.             Current := Current.Rest;
  2433.              end loop;
  2434.  
  2435.              Bind (Current.Rest, Back_Arg);
  2436.           end;
  2437.            end if;
  2438.  
  2439.            -- If the first argument turned out to be null, return a pointer
  2440.            -- to the second part of the result.  Otherwise, return the pointer
  2441.            -- to the front of the result.
  2442.  
  2443.            if Is_Null (Front_Arg) then
  2444.           return Back_Arg;
  2445.            else
  2446.           return Front_Arg;
  2447.            end if;
  2448.         end;
  2449.      end if;
  2450.       end "&";
  2451.  
  2452.       -------------------------------------------------------------------------
  2453.  
  2454.       --    Function:     First 
  2455.       --    Visibility:   Exported.
  2456.       --    Description:  Returns the first component of the non-null,
  2457.       --                  non-atomic input argument.
  2458.       -- 
  2459.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2460.  
  2461.       function First (Non_Atomic_Arg : in S_Expr) return S_Expr is
  2462.       begin
  2463.      if Is_Atomic (Non_Atomic_Arg) then
  2464.         raise Atomic_Expression; 
  2465.      end if;
  2466.      return Non_Atomic_Arg.First;
  2467.       end First;
  2468.  
  2469.       -------------------------------------------------------------------------
  2470.  
  2471.       --    Function:     Rest 
  2472.       --    Visibility:   Exported.
  2473.       --    Description:  Returns all components of the non-null, non-atomic
  2474.       --                  input argument except the first.
  2475.       -- 
  2476.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2477.  
  2478.       function Rest (Non_Atomic_Arg : in S_Expr) return S_Expr is
  2479.       begin
  2480.      if Is_Atomic (Non_Atomic_Arg) then
  2481.         raise Atomic_Expression; 
  2482.      end if;
  2483.      return Non_Atomic_Arg.Rest;
  2484.       end Rest;
  2485.  
  2486.       -------------------------------------------------------------------------
  2487.  
  2488.       --    Function:     Last 
  2489.       --    Visibility:   Exported.
  2490.       --    Description:  Returns the last component of the non-null,
  2491.       --                  non-atomic input argument.
  2492.       -- 
  2493.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2494.  
  2495.       function Last (Non_Atomic_Arg : in S_Expr) return S_Expr is
  2496.       begin
  2497.      if Is_Atomic (Non_Atomic_Arg) then
  2498.         raise Atomic_Expression; 
  2499.      end if;
  2500.  
  2501.      declare
  2502.         Last_Arg : S_Expr := Non_Atomic_Arg;
  2503.      begin
  2504.         while not Is_Null (Last_Arg.Rest) loop
  2505.            Last_Arg := Last_Arg.Rest;
  2506.         end loop;
  2507.  
  2508.         return Last_Arg.First;
  2509.      end;
  2510.       end Last;
  2511.  
  2512.       -------------------------------------------------------------------------
  2513.  
  2514.       --    Function:     Nth 
  2515.       --    Visibility:   Exported.
  2516.       --    Description:  Returns the position-th component of the non-null,
  2517.       --                  non-atomic input argument.
  2518.       --
  2519.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2520.       --                        Invalid_Position - if Position > # of components.
  2521.  
  2522.       function Nth (Non_Atomic_Arg : in S_Expr;
  2523.             Position : in Positive) return S_Expr is
  2524.       begin
  2525.      if Is_Atomic (Non_Atomic_Arg) then
  2526.         raise Atomic_Expression; 
  2527.      end if;
  2528.  
  2529.      if Position > Length (Non_Atomic_Arg) then
  2530.         raise Invalid_Position;
  2531.      end if;
  2532.  
  2533.      declare
  2534.         Nth_Arg : S_Expr := Non_Atomic_Arg;
  2535.      begin
  2536.         for Node_Number in 1 .. Position-1 loop
  2537.            Nth_Arg := Nth_Arg.Rest;
  2538.         end loop;
  2539.  
  2540.         return Nth_Arg.First;
  2541.      end;
  2542.       end Nth;
  2543.  
  2544.       -------------------------------------------------------------------------
  2545.  
  2546.       --    Function:     Nth_First 
  2547.       --    Visibility:   Exported.
  2548.       --    Description:  Returns the result of calling the function First n times,
  2549.       --                  each time using the result of the previous call as the
  2550.       --                  argument for the new iteration.
  2551.       --                  
  2552.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2553.       --                        Invalid_Repetitions - if Repetitions > maximum
  2554.       --                                              depth of the expression.
  2555.  
  2556.       function Nth_First (Non_Atomic_Arg : in S_Expr;
  2557.               Repetitions : in Positive) return S_Expr is
  2558.      Nth_First_Arg : S_Expr := Non_Atomic_Arg;
  2559.       begin
  2560.      if Is_Atomic (Non_Atomic_Arg) then
  2561.         raise Atomic_Expression; 
  2562.      end if;
  2563.  
  2564.      for Iteration in 1 .. Repetitions loop
  2565.         Nth_First_Arg := Nth_First_Arg.First;
  2566.         if Is_Atomic(Nth_First_Arg) and then Iteration < Repetitions then
  2567.            raise Invalid_Repetitions;
  2568.         end if;
  2569.      end loop;
  2570.  
  2571.      return Nth_First_Arg;
  2572.       end Nth_First;
  2573.  
  2574.       -------------------------------------------------------------------------
  2575.  
  2576.       --    Function:     Nth_Rest 
  2577.       --    Visibility:   Exported.
  2578.       --    Description:  Returns the result of calling the function Rest n times,
  2579.       --                  each time using the result of the previous call as the
  2580.       --                  argument for the new iteration.
  2581.       --                  
  2582.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2583.       --                        Invalid_Repetitions - if Repetitions > maximum
  2584.       --                                              length of the expression.
  2585.  
  2586.       function Nth_Rest (Non_Atomic_Arg : in S_Expr;
  2587.              Repetitions : in Positive) return S_Expr is
  2588.      Nth_Rest_Arg : S_Expr := Non_Atomic_Arg;
  2589.       begin
  2590.      for Iteration in 1 .. Repetitions loop
  2591.         Nth_Rest_Arg := Nth_Rest_Arg.Rest;
  2592.         if Is_Atomic(Nth_Rest_Arg) and then Iteration < Repetitions then
  2593.            raise Invalid_Repetitions;
  2594.         end if;
  2595.      end loop;
  2596.  
  2597.      return Nth_Rest_Arg;
  2598.       end Nth_Rest;
  2599.  
  2600.       -------------------------------------------------------------------------
  2601.  
  2602.       --    Function:     Reverse_S_Expr 
  2603.       --    Visibility:   Exported.
  2604.       --    Description:  Returns a non-atomic symbolic expression with the 
  2605.       --                  components of the given argument in reverse order.
  2606.       --
  2607.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2608.  
  2609.       function Reverse_S_Expr (Non_Atomic_Arg : in S_Expr) return S_Expr is
  2610.       begin
  2611.      if Is_Atomic (Non_Atomic_Arg) then
  2612.         raise Atomic_Expression; 
  2613.      end if;
  2614.  
  2615.      declare
  2616.         Reverse_Arg    : S_Expr := Non_Atomic_Arg;
  2617.         Reverse_Result : S_Expr := Null_S_Expr;
  2618.      begin
  2619.         
  2620.         -- Create the new symbolic expression by traversing the argument
  2621.         -- forward while building the result backwards.
  2622.  
  2623.         loop
  2624.            Reverse_Result := Prefix (First_Value => Reverse_Arg.First,
  2625.                      Rest_Value  => Reverse_Result);
  2626.            Reverse_Arg := Reverse_Arg.Rest;
  2627.            exit when Is_Null (Reverse_Arg);
  2628.         end loop;
  2629.  
  2630.         return Reverse_Result; 
  2631.      end;
  2632.       end Reverse_S_Expr;
  2633.  
  2634.       -------------------------------------------------------------------------
  2635.  
  2636.       --    Function:     Delete 
  2637.       --    Visibility:   Exported.
  2638.       --    Description:  Deletes all top level occurences of the first argument
  2639.       --                  from the second.
  2640.       --
  2641.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2642.  
  2643.       function Delete (S_Expr_Arg, Non_Atomic_Arg : in S_Expr) return S_Expr is
  2644.       begin
  2645.      if Is_Atomic (Non_Atomic_Arg) then
  2646.         raise Atomic_Expression; 
  2647.      end if;
  2648.  
  2649.      -- If it's not there, we can't delete it.
  2650.  
  2651.      if not Is_Member (S_Expr_Arg, Non_Atomic_Arg) then
  2652.         return Non_Atomic_Arg;
  2653.      else
  2654.         declare
  2655.            Delete_Arg    : S_Expr := Non_Atomic_Arg;
  2656.            Delete_Result : S_Expr := Null_S_Expr;
  2657.         begin
  2658.  
  2659.            -- Loop until the argument is exhausted or until the first component
  2660.            -- which does not match the argument to be delete is found.
  2661.  
  2662.            loop
  2663.           if not Is_Equal (Delete_Arg.First, S_Expr_Arg) then
  2664.              Delete_Result := Prefix (First_Value => Delete_Arg.First);
  2665.           end if;
  2666.  
  2667.           Delete_Arg := Delete_Arg.Rest;
  2668.            
  2669.           exit when Is_Null (Delete_Arg) or else
  2670.                 not Is_Null (Delete_Result);
  2671.            end loop;
  2672.  
  2673.            -- If there are more components to be examined in the argument,
  2674.            -- set a pointer to the current contents of the result.
  2675.  
  2676.            if not Is_Null (Delete_Arg) then
  2677.           declare
  2678.              End_Of_Result : S_Expr := Delete_Result;
  2679.           begin
  2680.  
  2681.              -- Loop through the remainder of the argument, building
  2682.              -- a new expression with those components which do not
  2683.              -- match the expression being deleted.
  2684.  
  2685.              loop
  2686.             if not Is_Equal (Delete_Arg.First, S_Expr_Arg) then
  2687.                Bind (End_Of_Result.Rest,
  2688.                   Prefix (First_Value => Delete_Arg.First));
  2689.                End_Of_Result := End_Of_Result.Rest;
  2690.             end if;
  2691.  
  2692.             Delete_Arg := Delete_Arg.Rest;
  2693.  
  2694.             exit when Is_Null (Delete_Arg);
  2695.              end loop;
  2696.           end;
  2697.            end if;
  2698.  
  2699.            return Delete_Result;
  2700.         end;
  2701.      end if;
  2702.       end Delete;
  2703.  
  2704.       -------------------------------------------------------------------------
  2705.  
  2706.       --    Function:     Replace 
  2707.       --    Visibility:   Exported.
  2708.       --    Description:  Replaces all top level occurences of the first argument
  2709.       --                  in the third with the second.
  2710.       --
  2711.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2712.  
  2713.       function Replace (S_Expr_Arg1, S_Expr_Arg2, Non_Atomic_Arg : in S_Expr)
  2714.      return S_Expr is
  2715.       begin
  2716.      if Is_Atomic (Non_Atomic_Arg) then
  2717.         raise Atomic_Expression; 
  2718.      end if;
  2719.  
  2720.      -- If the expression to be replaced and its replacement are equivalent
  2721.      -- or if the expression to be replaced is not a component of the 
  2722.      -- of the expression being operated upon, the resulting expression
  2723.      -- will be exactly equivalent to the original.
  2724.  
  2725.      if Is_Equal (S_Expr_Arg1, S_Expr_Arg2) or else
  2726.         not Is_Member (S_Expr_Arg1, Non_Atomic_Arg) then 
  2727.         return Non_Atomic_Arg;
  2728.      else
  2729.         declare
  2730.            Replace_Arg    : S_Expr := Non_Atomic_Arg;
  2731.            Replace_Result : S_Expr := Null_S_Expr;
  2732.         begin
  2733.  
  2734.            -- If the first component of the original expression is equal
  2735.            -- to the expression to be replaced, the first component of the
  2736.            -- result will be the replacement expression.  Otherwise, the
  2737.            -- first component of the original and result will be the same.
  2738.  
  2739.            if Is_Equal (Replace_Arg.First, S_Expr_Arg1) then
  2740.           Replace_Result := Prefix (First_Value => S_Expr_Arg2); 
  2741.            else
  2742.           Replace_Result := Prefix (First_Value => Replace_Arg.First);
  2743.            end if;
  2744.  
  2745.            Replace_Arg := Replace_Arg.Rest;
  2746.         
  2747.  
  2748.            -- If there are more components to be examined in the original 
  2749.            -- argument, set a pointer to the current contents of the result.
  2750.  
  2751.            if not Is_Null (Replace_Arg) then
  2752.           declare
  2753.              End_Of_Result : S_Expr := Replace_Result;
  2754.           begin
  2755.  
  2756.              -- Loop through the remainder of the original expression.
  2757.              -- If the component being examined matches the expression to
  2758.              -- be replaced, add the replacement expression to the result.
  2759.              -- Otherwise, add the component being examined to the result.
  2760.  
  2761.              loop
  2762.             if Is_Equal (Replace_Arg.First, S_Expr_Arg1) then
  2763.                Bind (End_Of_Result.Rest,
  2764.                  Prefix (First_Value => S_Expr_Arg2)); 
  2765.             else
  2766.                Bind (End_Of_Result.Rest,
  2767.                  Prefix (First_Value => Replace_Arg.First));
  2768.             end if;
  2769.  
  2770.             End_Of_Result := End_Of_Result.Rest;
  2771.             Replace_Arg := Replace_Arg.Rest;
  2772.  
  2773.             exit when Is_Null (Replace_Arg);
  2774.              end loop;
  2775.           end;
  2776.            end if;
  2777.  
  2778.            return Replace_Result;
  2779.         end;
  2780.      end if;
  2781.       end Replace;
  2782.  
  2783.       -------------------------------------------------------------------------
  2784.  
  2785.       --    Function:     Flatten 
  2786.       --    Visibility:   Exported.
  2787.       --    Description:  Returns a non-atomic expression which has as components 
  2788.       --                  all atomic components and all atomic components of all
  2789.       --                  the non-atomic expressions within the given argument.
  2790.       --
  2791.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg is atomic.
  2792.  
  2793.       function Flatten (Non_Atomic_Arg : in S_Expr) return S_Expr is
  2794.       begin
  2795.      if Is_Atomic (Non_Atomic_Arg) then
  2796.         raise Atomic_Expression; 
  2797.      end if;
  2798.  
  2799.      declare
  2800.         Flatten_Arg : S_Expr := Non_Atomic_Arg;
  2801.         Stack, Flatten_Result : S_Expr := Null_S_Expr;
  2802.      begin
  2803.         
  2804.         -- Loop until finding the first value of the result or 
  2805.         -- the argument is exhausted.
  2806.  
  2807.         loop
  2808.            -- Do a depth-first traversal of the argument, pushing the
  2809.            -- second thru nth components of the argument onto a stack
  2810.            -- and making the first component of the argument the new argument.
  2811.            -- Stop when an atomic expression is found.
  2812.  
  2813.            while not Is_Atomic (Flatten_Arg) loop
  2814.           Push (Flatten_Arg.Rest, Stack);
  2815.           Flatten_Arg := Flatten_Arg.First;
  2816.            end loop;
  2817.  
  2818.            -- If the expression is non-null, add it to the result.
  2819.  
  2820.            if not Is_Null (Flatten_Arg) then
  2821.           Flatten_Result := Prefix (First_Value => Flatten_Arg);
  2822.           Flatten_Arg := Null_S_Expr;
  2823.            end if;
  2824.  
  2825.            exit when (not Is_Null (Flatten_Result)) or else Is_Null (Stack);
  2826.  
  2827.            -- Get the next set of components from the stack.
  2828.  
  2829.            Pop (Stack, Flatten_Arg);
  2830.         end loop;
  2831.  
  2832.         -- If there's more to flatten, continue.
  2833.  
  2834.         if not Is_Null (Stack) then 
  2835.            declare 
  2836.           End_Of_Result : S_Expr := Flatten_Result;
  2837.            begin
  2838.           -- Loop until there are no more component sequences on
  2839.           -- the stack.
  2840.  
  2841.           Pop (Stack, Flatten_Arg);
  2842.  
  2843.           loop
  2844.  
  2845.              -- If the current argument is non-null and non-atomic,
  2846.              -- push all but the first component on the stack and 
  2847.              -- make the first component the current argument.
  2848.  
  2849.              while not Is_Atomic (Flatten_Arg) loop
  2850.             Push (Flatten_Arg.Rest, Stack);
  2851.             Flatten_Arg := Flatten_Arg.First;
  2852.              end loop;
  2853.  
  2854.              -- If the atomic expression found is non-null,
  2855.              -- add it to the result.
  2856.  
  2857.              if not Is_Null (Flatten_Arg) then
  2858.             Bind (End_Of_Result.Rest,
  2859.                   Prefix (First_Value => Flatten_Arg));
  2860.             End_Of_Result := End_Of_Result.Rest;
  2861.              end if;
  2862.  
  2863.              exit when Is_Null (Stack);
  2864.  
  2865.              -- Get the next set of components off the stack.
  2866.  
  2867.              Pop (Stack, Flatten_Arg);
  2868.           end loop;
  2869.            end;
  2870.         end if;
  2871.  
  2872.         return Flatten_Result;
  2873.      end;
  2874.       end Flatten;
  2875.  
  2876.       -------------------------------------------------------------------------
  2877.  
  2878.       --    Function:     "And" 
  2879.       --    Visibility:   Exported.
  2880.       --    Description:  Returns a non-atomic expression which contains as 
  2881.       --                  components all components which are both in the first
  2882.       --                  argument AND in the second argument with no duplicates.
  2883.       --
  2884.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg1 or
  2885.       --                                            Non_Atomic_Arg2 is 
  2886.       --                                            non-null atomic.
  2887.  
  2888.       function "And" (Non_Atomic_Arg1, Non_Atomic_Arg2 : in S_Expr)
  2889.      return S_Expr is
  2890.       begin
  2891.      if not Is_Non_Atomic (Non_Atomic_Arg1) or else
  2892.         not Is_Non_Atomic (Non_Atomic_Arg2) then
  2893.         raise Atomic_Expression; 
  2894.      end if;
  2895.  
  2896.      declare
  2897.         And_Arg1   : S_Expr := Non_Atomic_Arg1;
  2898.         And_Arg2   : S_Expr := Non_Atomic_Arg2;
  2899.         And_Result : S_Expr := Null_S_Expr;
  2900.      begin
  2901.  
  2902.         -- Loop through the first argument.
  2903.  
  2904.         while not Is_Null (And_Arg1) loop
  2905.  
  2906.            -- If the current component of the first argument has not
  2907.            -- been previously added to the result and the current
  2908.            -- component is also a member of the second argument, add
  2909.            -- it to the result.
  2910.  
  2911.            if not Is_Member (And_Arg1.First, And_Result) and then
  2912.           Is_Member (And_Arg1.First, And_Arg2) then
  2913.           
  2914.           And_Result := Prefix (And_Arg1.First, And_Result);
  2915.            end if;
  2916.  
  2917.            And_Arg1 := And_Arg1.Rest;
  2918.         end loop;
  2919.  
  2920.         return And_Result;
  2921.      end;
  2922.       end "And";
  2923.  
  2924.       -------------------------------------------------------------------------
  2925.  
  2926.       --    Function:     "Or" 
  2927.       --    Visibility:   Exported.
  2928.       --    Description:  Returns a non-atomic expression which contains as 
  2929.       --                  components all components which are either in the first
  2930.       --                  argument OR in the second argument with no duplicates.
  2931.       --
  2932.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg1 or
  2933.       --                                            Non_Atomic_Arg2 is
  2934.       --                                            non-null atomic.
  2935.  
  2936.       function "Or" (Non_Atomic_Arg1, Non_Atomic_Arg2 : in S_Expr) return S_Expr is
  2937.       begin
  2938.      if not Is_Non_Atomic (Non_Atomic_Arg1) or else
  2939.         not Is_Non_Atomic (Non_Atomic_Arg2) then
  2940.         raise Atomic_Expression; 
  2941.      end if;
  2942.  
  2943.      declare
  2944.           Or_Arg1   : S_Expr := Non_Atomic_Arg1;
  2945.           Or_Arg2   : S_Expr := Non_Atomic_Arg2;
  2946.           Or_Result : S_Expr := Null_S_Expr;
  2947.      begin
  2948.  
  2949.         -- Loop through the second argument, adding all of
  2950.         -- its components (without duplication) to the result.
  2951.  
  2952.         while not Is_Null (Or_Arg2) loop
  2953.            if not Is_Member (Or_Arg2.First, Or_Result) then
  2954.           Or_Result := Prefix (Or_Arg2.First, Or_Result);
  2955.            end if;
  2956.  
  2957.            Or_Arg2 := Or_Arg2.Rest;
  2958.         end loop;
  2959.  
  2960.         -- Loop through the first argument.
  2961.  
  2962.         while not Is_Null (Or_Arg1) loop
  2963.  
  2964.            -- If the current component of the first argument has not
  2965.            -- been previously added to the result, add it.
  2966.  
  2967.            if not Is_Member (Or_Arg1.First, Or_Result) then
  2968.           Or_Result := Prefix (Or_Arg1.First, Or_Result);
  2969.            end if;
  2970.  
  2971.            Or_Arg1 := Or_Arg1.Rest;
  2972.         end loop;
  2973.  
  2974.         return Or_Result;
  2975.      end;
  2976.       end "Or";
  2977.  
  2978.       -------------------------------------------------------------------------
  2979.  
  2980.       --    Function:     "-" 
  2981.       --    Visibility:   Exported.
  2982.       --    Description:  Returns a non-atomic expression which contains as 
  2983.       --                  components all those components of the first argument
  2984.       --                  which are not contained within the second with no
  2985.       --                  duplicates.
  2986.       --
  2987.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg1 or
  2988.       --                                            Non_Atomic_Arg2 is
  2989.       --                                            non-null atomic.
  2990.  
  2991.       function "-" (Non_Atomic_Arg1, Non_Atomic_Arg2 : in S_Expr) return S_Expr is
  2992.       begin
  2993.      if not Is_Non_Atomic (Non_Atomic_Arg1) or else
  2994.         not Is_Non_Atomic (Non_Atomic_Arg2) then
  2995.         raise Atomic_Expression; 
  2996.      end if;
  2997.  
  2998.      declare
  2999.         Diff_Arg1   : S_Expr := Non_Atomic_Arg1;
  3000.         Diff_Arg2   : S_Expr := Non_Atomic_Arg2;
  3001.         Diff_Result : S_Expr := Null_S_Expr;
  3002.      begin
  3003.  
  3004.         -- Loop through the first argument.
  3005.  
  3006.         while not Is_Null (Diff_Arg1) loop
  3007.  
  3008.            -- If the current component of the first argument is not
  3009.            -- a member of the result or the second argument, add it
  3010.            -- to the result.
  3011.            
  3012.            if not Is_Member (Diff_Arg1.First, Diff_Result) and then
  3013.           not Is_Member (Diff_Arg1.First, Diff_Arg2) then
  3014.           Diff_Result := Prefix (Diff_Arg1.First, Diff_Result);
  3015.            end if;
  3016.  
  3017.            Diff_Arg1 := Diff_Arg1.Rest;
  3018.         end loop;
  3019.  
  3020.         return Diff_Result;
  3021.      end;
  3022.       end "-";
  3023.  
  3024.       -------------------------------------------------------------------------
  3025.  
  3026.       --    Function:     "Xor" 
  3027.       --    Visibility:   Exported.
  3028.       --    Description:  Returns a non-atomic expression which contains as
  3029.       --                  components all those components of the first argument
  3030.       --                  which are not components of the second and all those
  3031.       --                  components of the second argument which are not 
  3032.       --                  components of the first with no duplicates.
  3033.       --
  3034.       --    Exceptions Raised:  Atomic_Expression - if Non_Atomic_Arg1 or
  3035.       --                                            Non_Atomic_Arg2 is
  3036.       --                                            non-null atomic.
  3037.  
  3038.       function "Xor" (Non_Atomic_Arg1, Non_Atomic_Arg2 : in S_Expr)
  3039.      return S_Expr is
  3040.      Or_Arg1, Or_Arg2 : S_Expr;
  3041.      Xor_Result : S_Expr;
  3042.       begin
  3043.      if not Is_Non_Atomic (Non_Atomic_Arg1) or else
  3044.         not Is_Non_Atomic (Non_Atomic_Arg2) then
  3045.         raise Atomic_Expression; 
  3046.      end if;
  3047.  
  3048.      Or_Arg1 := Non_Atomic_Arg1 - Non_Atomic_Arg2;
  3049.      Or_Arg2 := Non_Atomic_Arg2 - Non_Atomic_Arg1;
  3050.  
  3051.      if Is_Null (Or_Arg1) then
  3052.         return Or_Arg2;
  3053.      elsif Is_Null (Or_Arg2) then
  3054.         return Or_Arg1;
  3055.      else
  3056.         Xor_Result := Or_Arg1 OR Or_Arg2;
  3057.         Free (Or_Arg1);
  3058.         Free (Or_Arg2);
  3059.         return Xor_Result;
  3060.      end if;
  3061.  
  3062.       end "Xor";
  3063.  
  3064.       -------------------------------------------------------------------------
  3065.  
  3066.       --    Function:     Associate 
  3067.       --    Visibility:   Exported.
  3068.       --    Description:  Returns the first component of A_Table whose
  3069.       --                  Search_Position-th component is equivalent to the Key.
  3070.       --
  3071.       --    Exceptions Raised:  Atomic_Expression - if A_Table is atomic.
  3072.  
  3073.       function Associate (Key, A_Table : in S_Expr;
  3074.               Search_Position : Positive := 1) return S_Expr is
  3075.       begin
  3076.      if Is_Atomic (A_Table) then
  3077.         raise Atomic_Expression; 
  3078.      end if;
  3079.  
  3080.      declare
  3081.         A_Table_Arg : S_Expr := A_Table;
  3082.         Component   : S_Expr := Null_S_Expr;
  3083.      begin
  3084.  
  3085.         -- Loop until the A_Table is exhausted or a component
  3086.         -- satisfying the necessary criteria is found.
  3087.  
  3088.         loop
  3089.  
  3090.            -- Examine the component only if it has a number of
  3091.            -- components greater or equal to Search_Position.
  3092.  
  3093.            if Length (A_Table_Arg.First) >= Search_Position then
  3094.           Component := A_Table_Arg.First;
  3095.  
  3096.           -- Loop to the correct position within the component.
  3097.  
  3098.           for Component_Number in 1 .. Search_Position-1 loop
  3099.              Component := Component.Rest;
  3100.           end loop;
  3101.  
  3102.           -- Examine the component at the current position.
  3103.  
  3104.           if Is_Equal (Component.First, Key) then
  3105.              return A_Table_Arg.First; 
  3106.           end if;
  3107.            end if;
  3108.          
  3109.            -- We haven't found a match, get the next entry of the A_Table.
  3110.  
  3111.            A_Table_Arg := A_Table_Arg.Rest;
  3112.  
  3113.            exit when Is_Null (A_Table_Arg); 
  3114.         end loop;
  3115.  
  3116.         return Null_S_Expr;
  3117.      end;
  3118.       end Associate;
  3119.  
  3120.       -------------------------------------------------------------------------
  3121.  
  3122.       --    Function:     Associate_All 
  3123.       --    Visibility:   Exported.
  3124.       --    Description:  Returns a non-atomic expression containing ALL the
  3125.       --                  components of A_Table whose Search_Position-th
  3126.       --                  component is equivalent to the Key.
  3127.       --
  3128.       --    Exceptions Raised:  Atomic_Expression - if A_Table is atomic.
  3129.  
  3130.       function Associate_All (Key, A_Table : in S_Expr;
  3131.                   Search_Position : Positive := 1) return S_Expr is
  3132.  
  3133.       begin
  3134.      if Is_Atomic (A_Table) then
  3135.         raise Atomic_Expression; 
  3136.      end if;
  3137.  
  3138.      declare
  3139.         A_Table_Arg       : S_Expr := A_Table;
  3140.         Component,
  3141.         Associate_Result  : S_Expr := Null_S_Expr; 
  3142.      begin
  3143.  
  3144.         -- Loop until finding the first component which satisifies
  3145.         -- the necessary criteria or until the A_Table is exhausted.
  3146.  
  3147.         loop
  3148.  
  3149.            -- Examine the component only if it has a number of
  3150.            -- components greater or equal to Search_Position.
  3151.  
  3152.            if Length (A_Table_Arg.First) >= Search_Position then
  3153.           Component := A_Table_Arg.First;
  3154.  
  3155.           -- Loop to the correct position within the component.
  3156.  
  3157.           for Component_Number in 1 .. Search_Position-1 loop
  3158.              Component := Component.Rest;
  3159.           end loop;
  3160.  
  3161.           -- If the component at the current position matches the 
  3162.           -- Key, add it to the result.
  3163.  
  3164.           if Is_Equal (Component.First, Key) then
  3165.              Associate_Result := Prefix (First_Value => A_Table_Arg.First);
  3166.           end if;
  3167.            end if;
  3168.  
  3169.            A_Table_Arg := A_Table_Arg.Rest;
  3170.  
  3171.            exit when not Is_Null (Associate_Result) or else 
  3172.              Is_Null (A_Table_Arg);
  3173.         end loop;
  3174.  
  3175.         -- If there are further components to search in the A_Table, continue.
  3176.  
  3177.         if not Is_Null (A_Table_Arg) then
  3178.            declare
  3179.           End_Of_Result : S_Expr := Associate_Result;
  3180.            begin
  3181.           
  3182.           -- Loop through the remainder of the A_Table.
  3183.  
  3184.           loop
  3185.  
  3186.              -- Examine the component only if it has a number of
  3187.              -- components greater or equal to Search_Position.
  3188.  
  3189.              if Length (A_Table_Arg.First) >= Search_Position then
  3190.             Component := A_Table_Arg.First;
  3191.  
  3192.             -- Loop to the correct position within the component.
  3193.  
  3194.             for Component_Number in 1 .. Search_Position-1 loop
  3195.                Component := Component.Rest;
  3196.             end loop;
  3197.  
  3198.             -- If the component at the current position matches the 
  3199.             -- Key, add it to the result.
  3200.  
  3201.             if Is_Equal (Component.First, Key) then
  3202.                Bind (End_Of_Result.Rest,
  3203.                   Prefix (First_Value => A_Table_Arg.First));
  3204.  
  3205.                End_Of_Result := End_Of_Result.Rest;
  3206.             end if;
  3207.              end if;
  3208.  
  3209.              A_Table_Arg := A_Table_Arg.Rest;
  3210.  
  3211.              exit when Is_Null (A_Table_Arg);
  3212.           end loop;
  3213.            end;
  3214.         end if;
  3215.  
  3216.         return Associate_Result;
  3217.      end;
  3218.       end Associate_All;
  3219.  
  3220.    end Symbolic_Expressions;
  3221.  
  3222.  
  3223.    package body Patterns is
  3224.  
  3225.       -- A Pattern is a S_Expr whose first component is the pattern template
  3226.       -- and whose second component is the variable binding context.
  3227.  
  3228.       -------------------------------------------------------------------------
  3229.  
  3230.       --    Function:     Is_Null
  3231.       --    Visibility:   Exported.
  3232.       --    Description:  Determines if Pattern_Arg = Null_Pattern.
  3233.       --
  3234.       --    Exceptions Raised:  None.
  3235.  
  3236.       function Is_Null (Pattern_Arg : in Pattern) return Boolean is
  3237.       begin 
  3238.      return SE."=" (SE.S_Expr (Pattern_Arg), SE.S_Expr (Null_Pattern));
  3239.       end Is_Null;
  3240.      
  3241.       -------------------------------------------------------------------------
  3242.  
  3243.       --    Function:     Create_Pattern
  3244.       --    Visibility:   Exported.
  3245.       --    Description:  Creates a pattern. The symbolic expression forms the 
  3246.       --                  pattern's template and the pattern's variable binding
  3247.       --                  context is set to null.
  3248.       --
  3249.       --    Exceptions Raised:  None.
  3250.  
  3251.       function Create_Pattern (Template : in SE.S_Expr;
  3252.                    Bindings : in SE.S_Expr := SE.Null_S_Expr)
  3253.          return Pattern is
  3254.       begin
  3255.      if SE.Is_Null (Template) and then
  3256.         SE.Is_Null (Bindings) then
  3257.         return Null_Pattern;
  3258.      else
  3259.         return Pattern (SE.Prefix (Template, Bindings));
  3260.      end if;
  3261.       end Create_Pattern;
  3262.  
  3263.       -------------------------------------------------------------------------
  3264.  
  3265.       --    Function:     Get_Template
  3266.       --    Visibility:   Exported
  3267.       --    Description:  Returns the template portion of the given pattern.
  3268.       --
  3269.       --    Exceptions Raised:  None.
  3270.  
  3271.       function Get_Template (Pattern_Arg : in Pattern) return SE.S_Expr is
  3272.       begin
  3273.      if Is_Null (Pattern_Arg) then
  3274.         return SE.Null_S_Expr;
  3275.      else
  3276.         return SE.First (SE.S_Expr (Pattern_Arg));
  3277.      end if;
  3278.       end Get_Template;
  3279.  
  3280.       -------------------------------------------------------------------------
  3281.  
  3282.       --    Function:     Get_Bindings
  3283.       --    Visibility:   Exported.
  3284.       --    Description:  Returns a symbolic expression representing the current
  3285.       --                  bindings of the variables found in the pattern
  3286.       --                  argument's template.
  3287.       --
  3288.       --    Exceptions Raised:  None.
  3289.  
  3290.       function Get_Bindings (Pattern_Arg : in Pattern) return SE.S_Expr is
  3291.       begin
  3292.      if Is_Null (Pattern_Arg) then
  3293.         return SE.Null_S_Expr;
  3294.      else
  3295.         return SE.Rest (SE.S_Expr(Pattern_Arg));
  3296.      end if;
  3297.       end Get_Bindings;
  3298.  
  3299.       -------------------------------------------------------------------------
  3300.  
  3301.       --    Function:     Set_Bindings
  3302.       --    Visibility:   Exported.
  3303.       --    Description:  Sets the variable binding context for the pattern
  3304.       --                  to the specified context.  NOTE: This function can 
  3305.       --                  also be used to erase the current context by setting 
  3306.       --                  the bindings to null.
  3307.       --
  3308.       --    Exceptions Raised:  None.
  3309.  
  3310.       function Set_Bindings (Pattern_Arg : in Pattern;
  3311.                  Bindings : in SE.S_Expr) return Pattern is
  3312.       begin
  3313.      return Create_Pattern (Get_Template (Pattern_Arg), Bindings);
  3314.       end Set_Bindings;
  3315.  
  3316.       -------------------------------------------------------------------------
  3317.  
  3318.       --    Function:     First
  3319.       --    Visibility:   Exported.
  3320.       --    Description:  Returns a pattern whose template consists of the 
  3321.       --                  first component of the argument.  The variable binding
  3322.       --                  context of the new pattern is the same as that of the
  3323.       --                  argument.
  3324.       --
  3325.       --    Exceptions Raised:  Atomic_Template -- if the pattern template
  3326.       --                                           is an atomic expression.
  3327.  
  3328.       function First (Pattern_Arg : in Pattern) return Pattern is
  3329.       begin
  3330.      return Create_Pattern (SE.First (Get_Template (Pattern_Arg)),
  3331.                 Get_Bindings (Pattern_Arg));
  3332.      exception
  3333.         when SE.Atomic_Expression => raise Atomic_Template;
  3334.       end First;
  3335.  
  3336.       -------------------------------------------------------------------------
  3337.  
  3338.       --    Function:     Rest
  3339.       --    Visibility:   Exported.
  3340.       --    Description:  Returns a pattern whose template consists of the all 
  3341.       --                  but the first component of the argument.  The variable
  3342.       --                  binding context of the new pattern is the same as that
  3343.       --                  of the argument.
  3344.       --
  3345.       --    Exceptions Raised:  Atomic_Template -- if the pattern template
  3346.       --                                           is an atomic expression.
  3347.  
  3348.       function Rest (Pattern_Arg : in Pattern) return Pattern is
  3349.       begin
  3350.      return Create_Pattern (SE.Rest (Get_Template (Pattern_Arg)),
  3351.                 Get_Bindings (Pattern_Arg));
  3352.      exception
  3353.         when SE.Atomic_Expression => raise Atomic_Template;
  3354.       end Rest;
  3355.  
  3356.       -------------------------------------------------------------------------
  3357.  
  3358.       --    Function:     Instantiate
  3359.       --    Visibility:   Exported.
  3360.       --    Description:  Returns a symbolic expression created by replacing 
  3361.       --                  all variables in the pattern argument's template with
  3362.       --                  their current bindings (found in the variable binding
  3363.       --                  context).
  3364.       --
  3365.       --    Exceptions Raised:  None.
  3366.  
  3367.       function Instantiate (Pattern_Arg : in Pattern) return SE.S_Expr is
  3368.  
  3369.      Bindings, Result : SE.S_Expr;
  3370.  
  3371.      ----------------------------------------------------------------------
  3372.  
  3373.      --    Function:     Create_Inst
  3374.      --    Visibility:   Internal.
  3375.      --    Description:  Returns a symbolic expression created by replacing 
  3376.      --                  all variables in the pattern argument's template
  3377.      --                  with their current bindings (found in the variable
  3378.      --                  binding context).
  3379.      --
  3380.      --    Exceptions Raised:  None.
  3381.  
  3382.      function Create_Inst (Template, Binding_List : in SE.S_Expr)
  3383.         return SE.S_Expr is
  3384.         Var_Value_Pair, Value, Result : SE.S_Expr;
  3385.      begin
  3386.         
  3387.         -- If the template is a variable, check to see if it has a binding.
  3388.  
  3389.         if SE.Is_Variable (Template) then
  3390.            SE.Bind (Var_Value_Pair, SE.Associate (Template, Binding_List));
  3391.  
  3392.            -- If the variable has no binding, return the variable itself.
  3393.            -- Otherwise, examine the expression to which it's bound.
  3394.  
  3395.            if SE.Is_Null (Var_Value_Pair) then
  3396.           SE.Bind (Result, Template);
  3397.            else
  3398.           SE.Bind (Value, SE.First (SE.Rest (Var_Value_Pair)));
  3399.           SE.Bind (Result,
  3400.                Create_Inst (SE.First (SE.Rest (Var_Value_Pair)),
  3401.                     Binding_List));
  3402.            end if;
  3403.  
  3404.         -- If the template is atomic, just return it.
  3405.  
  3406.         elsif SE.Is_Atomic (Template) then
  3407.            SE.Bind (Result, Template);
  3408.  
  3409.         -- Otherwise, build up an expression with the result of examining
  3410.         -- the first and rest sections of the given template.
  3411.  
  3412.         elsif not SE.Is_Atomic (Template) then
  3413.            SE.Bind (Result,
  3414.             SE.Prefix (Create_Inst (SE.First (Template),
  3415.                         Binding_List),
  3416.                    Create_Inst (SE.Rest (Template),
  3417.                         Binding_List)));
  3418.         end if;
  3419.  
  3420.         SE.Free (Var_Value_Pair);
  3421.         return SE.Return_And_Free (Result);
  3422.      end Create_Inst;
  3423.  
  3424.       begin
  3425.      SE.Bind (Bindings, Get_Bindings (Pattern_Arg));
  3426.      if SE.Is_Null (Bindings) then
  3427.         SE.Bind (Result, Get_Template (Pattern_Arg));
  3428.      else
  3429.         SE.Bind (Result,
  3430.              Create_Inst (Get_Template (Pattern_Arg), Bindings));
  3431.      end if;
  3432.  
  3433.      SE.Free (Bindings);
  3434.      return SE.Return_And_Free (Result);
  3435.       end Instantiate;
  3436.  
  3437.       -------------------------------------------------------------------------
  3438.  
  3439.       --    Function:     Is_Equal
  3440.       --    Visibility:   Exported.
  3441.       --    Description:  Determines if two patterns are equal by determining 
  3442.       --                  if their instantiations are equal.
  3443.       --
  3444.       --    Exceptions Raised:  None.
  3445.  
  3446.       function Is_Equal (Pattern1, Pattern2 : in Pattern) return Boolean is
  3447.       begin
  3448.      return SE.Is_Equal (Instantiate (Pattern1), Instantiate (Pattern2));
  3449.       end Is_Equal;
  3450.  
  3451.       ----------------------------------------------------------------------
  3452.  
  3453.       --    Function:     Tag_Variables
  3454.       --    Visibility:   Exported.
  3455.       --    Description:  Tags all variables within a pattern with the same
  3456.       --                  tag.  This can be used to make a particular pattern
  3457.       --                  unique with respect to other patterns.
  3458.       --
  3459.       --    Exceptions Raised:  None.
  3460.  
  3461.       procedure Tag_Variables (Pattern_Arg : in Pattern; Tag : in Natural) is
  3462.  
  3463.      procedure Tag_Expression (Expression : in SE.S_Expr) is
  3464.      begin
  3465.         -- If the template is a variable, set its tag.
  3466.  
  3467.         if SE.Is_Variable (Expression) then
  3468.            SE.Set_Variable_Tag (Expression, Tag);
  3469.  
  3470.         -- Otherwise, tag the variables in the first and rest sections
  3471.         -- of the given template if it's a non-null, non-atomic expression.
  3472.  
  3473.         elsif not SE.Is_Atomic (Expression) then
  3474.            Tag_Expression (SE.First (Expression));
  3475.            Tag_Expression (SE.Rest (Expression));
  3476.         end if;
  3477.      end Tag_Expression;
  3478.  
  3479.       begin
  3480.      Tag_Expression (Get_Template (Pattern_Arg));
  3481.      Tag_Expression (Get_Bindings (Pattern_Arg));
  3482.       end Tag_Variables;
  3483.  
  3484.       -------------------------------------------------------------------------
  3485.  
  3486.       --    Function:     Match
  3487.       --    Visibility:   Exported.
  3488.       --    Description:  If the two pattern arguments can be made identical by
  3489.       --                  variable substitution, Is_Match will be set to True
  3490.       --                  and the variable binding contexts of Pattern1 and 
  3491.       --                  Pattern2 will contain the particular set of bindings
  3492.       --                  which made the patterns identical.  Otherwise,Is_Match
  3493.       --                  will be False and the variable binding contexts for
  3494.       --                  the two patterns will remain unchanged.
  3495.       --    References:   The pattern matching algorithms used are based upon 
  3496.       --                  those found in the following reference:
  3497.       --
  3498.       --                  Wilensky, Robert.  LISPCRAFT. 
  3499.       --                  New York: W. W. Norton & Co., Inc., 1984.
  3500.       --
  3501.       --    Exceptions Raised:  None.
  3502.  
  3503.       procedure Match (Pattern1, Pattern2 : in out Pattern;
  3504.                Is_Match : out Boolean) is
  3505.  
  3506.      Match_Arg1, Match_Arg2, Bindings : SE.S_Expr;
  3507.  
  3508.      ----------------------------------------------------------------------
  3509.  
  3510.      --    Function:     Contained_In
  3511.      --    Visibility:   Internal
  3512.      --    Description:  Determines if the given pattern variable is
  3513.      --                  contained within the given Item.
  3514.      --
  3515.      --    Exceptions Raised:  None.
  3516.  
  3517.      function Contained_In (Pattern_Var, Item, Bindings : in SE.S_Expr)
  3518.         return Boolean is
  3519.  
  3520.         Var_Value_Pair, Var_Binding : SE.S_Expr;
  3521.         Result : Boolean;
  3522.      begin
  3523.  
  3524.         -- If the item is an atomic literal, the variable cannot be 
  3525.         -- contained within it.
  3526.  
  3527.         if SE.Is_Atomic (Item) and then
  3528.            not SE.Is_Variable (Item) then
  3529.            Result := False;
  3530.  
  3531.         -- If the item is a variable, determine if the pattern variable
  3532.         -- and the item are the same variable or if the pattern variable
  3533.         -- occurs within the expression to which the item is bound.
  3534.  
  3535.         elsif SE.Is_Variable (Item) then
  3536.            if SE.Is_Null (Bindings) then 
  3537.           SE.Bind (Var_Binding, SE.Null_S_Expr);
  3538.            else
  3539.           SE.Bind (Var_Value_Pair, SE.Associate (Pattern_Var,Bindings));
  3540.  
  3541.           if SE.Is_Null (Var_Value_Pair) then
  3542.              SE.Bind (Var_Binding, SE.Null_S_Expr);
  3543.           else
  3544.              SE.Bind (Var_Binding, SE.First (SE.Rest (Var_Value_Pair)));
  3545.           end if;
  3546.            end if;
  3547.  
  3548.            Result := SE.Is_Equal (Pattern_Var, Item) or else
  3549.              Contained_In (Pattern_Var, Var_Binding, Bindings);
  3550.  
  3551.         -- Otherwise, determine if the pattern variable is contained within
  3552.         -- the given non-atomic expression.
  3553.  
  3554.         else
  3555.            Result :=
  3556.           Contained_In (Pattern_Var, SE.First (Item), Bindings) or else
  3557.           Contained_In (Pattern_Var, SE.Rest (Item), Bindings);
  3558.         end if;
  3559.  
  3560.         SE.Free (Var_Binding);
  3561.         SE.Free (Var_Value_Pair);
  3562.         return Result;
  3563.      end Contained_In;
  3564.  
  3565.      -- Forward declaration for Match_With_Bindings used
  3566.      -- within Variable_Match.
  3567.  
  3568.      function Match_With_Bindings (S_Expr1, S_Expr2,
  3569.                       Bindings : in SE.S_Expr) return SE.S_Expr;
  3570.  
  3571.      ----------------------------------------------------------------------
  3572.  
  3573.      --    Function:     Variable_Match
  3574.      --    Visibility:   Internal.
  3575.      --    Description:  Determines if the input pattern variable can be 
  3576.      --                  bound to the second argument given the current
  3577.      --                  variable bindings.  The binding list resulting 
  3578.      --                  from this process is returned.
  3579.      --
  3580.      --    Exceptions Raised:  None.
  3581.  
  3582.      function Variable_Match (Pattern_Var, Item, Bindings : in SE.S_Expr)
  3583.         return SE.S_Expr is
  3584.  
  3585.         Var_Value_Pair, Var_Binding, Result : SE.S_Expr;
  3586.      begin
  3587.        
  3588.         -- If the second argument is an equivalent variable, return a 
  3589.         -- symbolic expression whose first component is the current binding
  3590.         -- list.
  3591.  
  3592.         if SE.Is_Equal (Pattern_Var, Item) then
  3593.            SE.Bind (Result, SE.Prefix (Bindings));
  3594.  
  3595.         -- Otherwise, continue the attempt to bind the variable to the item.
  3596.  
  3597.         else
  3598.  
  3599.            -- Lookup the current binding of the variable in the binding list
  3600.  
  3601.            if SE.Is_Null (Bindings) then 
  3602.           SE.Bind (Var_Binding, SE.Null_S_Expr);
  3603.            else
  3604.           SE.Bind (Var_Value_Pair, SE.Associate (Pattern_Var,Bindings));
  3605.  
  3606.           if SE.Is_Null (Var_Value_Pair) then
  3607.              SE.Bind (Var_Binding, SE.Null_S_Expr);
  3608.           else
  3609.              SE.Bind (Var_Binding, SE.First (SE.Rest (Var_Value_Pair)));
  3610.           end if;
  3611.            end if;
  3612.  
  3613.            -- If the variable is currently bound to an expression, determine
  3614.            -- if the two expressions can be made equivalent by variable 
  3615.            -- substitution.
  3616.  
  3617.            if not SE.Is_Null (Var_Binding) then
  3618.           SE.Bind (Result,
  3619.                Match_With_Bindings (Var_Binding, Item, Bindings));
  3620.  
  3621.            -- If the pattern variable is not contained within the expression
  3622.            -- to which we would like to bind it, it may be bound with the 
  3623.            -- current expression and added to the binding list. The 
  3624.            -- augmented binding list is then returned.
  3625.  
  3626.            elsif not Contained_In (Pattern_Var, Item, Bindings) then
  3627.           SE.Bind (Result,
  3628.                SE.Prefix (
  3629.                   SE.Prefix (
  3630.                  SE.Prefix (Pattern_Var, SE.Prefix (Item)),
  3631.                         Bindings)));
  3632.            else
  3633.           SE.Bind (Result, SE.Null_S_Expr);
  3634.            end if;
  3635.         end if;
  3636.  
  3637.         SE.Free (Var_Binding);
  3638.         SE.Free (Var_Value_Pair);
  3639.         return SE.Return_And_Free (Result);
  3640.      end Variable_Match;
  3641.  
  3642.      ----------------------------------------------------------------------
  3643.  
  3644.      --    Function:     Match_With_Bindings
  3645.      --    Visibility:   Internal.
  3646.      --    Description:  Returns a symbolic expression containing the 
  3647.      --                  variable bindings determined during the pattern
  3648.      --                  matching process.
  3649.      --
  3650.      --    Exceptions Raised:  None.
  3651.  
  3652.      function Match_With_Bindings (S_Expr1, S_Expr2, Bindings: in SE.S_Expr)
  3653.         return SE.S_Expr is
  3654.  
  3655.         New_Bindings : SE.S_Expr;
  3656.      begin
  3657.  
  3658.         -- If the first expression is a variable, return the result of
  3659.         -- attempting to bind it to the second expression.
  3660.  
  3661.         if SE.Is_Variable (S_Expr1) then
  3662.            return Variable_Match (S_Expr1, S_Expr2, Bindings);
  3663.  
  3664.         -- If the second expression is a variable, return the result of
  3665.         -- attempting to bind it to the first expression.
  3666.  
  3667.         elsif SE.Is_Variable (S_Expr2) then
  3668.            return Variable_Match (S_Expr2, S_Expr1, Bindings);
  3669.  
  3670.         -- If either argument is atomic, they both have to be to match.
  3671.  
  3672.         elsif SE.Is_Atomic (S_Expr1) or else SE.Is_Atomic (S_Expr2) then 
  3673.  
  3674.            -- If they are equivalent, return a symbolic expression
  3675.            -- whose first component is the current binding list.
  3676.            -- Otherwise, return null.
  3677.  
  3678.            if SE.Is_Equal (S_Expr1, S_Expr2) then
  3679.           return SE.Prefix (Bindings);
  3680.            else
  3681.           return SE.Null_S_Expr;
  3682.            end if;
  3683.  
  3684.         -- Otherwise, attempt to match the non-atomic components.
  3685.  
  3686.         else
  3687.  
  3688.            -- First, match the first components of the arguments.
  3689.  
  3690.            SE.Bind (New_Bindings,
  3691.                 Match_With_Bindings (SE.First (S_Expr1),
  3692.                          SE.First (S_Expr2),
  3693.                          Bindings));
  3694.  
  3695.            -- If variable bindings were found for the first components,
  3696.            -- continue the match.  Otherwise, it's not worth continuing.
  3697.  
  3698.            if not SE.Is_Null (New_Bindings) then
  3699.           SE.Bind (New_Bindings, 
  3700.                Match_With_Bindings (SE.Rest (S_Expr1),
  3701.                         SE.Rest (S_Expr2),
  3702.                         SE.First (New_Bindings)));
  3703.            end if;
  3704.  
  3705.            return SE.Return_And_Free (New_Bindings);
  3706.         end if;
  3707.      end Match_With_Bindings;
  3708.  
  3709.      ----------------------------------------------------------------------
  3710.  
  3711.      --    Function:     Set_Pattern_Bindings
  3712.      --    Visibility:   Internal.
  3713.      --    Description:  Sets the variable binding contexts of the pattern
  3714.      --                  arguments based on the contents of the binding list
  3715.      --
  3716.      --    Exceptions Raised:  None.
  3717.  
  3718.      procedure Set_Pattern_Bindings (Pattern1, Pattern2 : in out Pattern;
  3719.                      Binding_List : in SE.S_Expr) is
  3720.  
  3721.         -------------------------------------------------------------------
  3722.  
  3723.         --    Function:     Create_Bindings
  3724.         --    Visibility:   Internal.
  3725.         --    Description:  Creates a variable binding context by searching
  3726.         --                  the given template for variables and then adding
  3727.         --                  the variable-value pair found in the binding
  3728.         --                  list to the context.
  3729.         --
  3730.         --    Exceptions Raised:  None.
  3731.  
  3732.         function Create_Bindings (Template, Binding_List : in SE.S_Expr)
  3733.            return SE.S_Expr is
  3734.            Var_Value_Pair, Value, Result : SE.S_Expr;
  3735.         begin
  3736.            -- If it's a variable, return the value to which it's bound
  3737.            -- and the values to which any variables within the first
  3738.            -- value are bound.
  3739.  
  3740.            if SE.Is_Variable (Template) then
  3741.           SE.Bind (Var_Value_Pair, SE.Associate(Template,Binding_List));
  3742.  
  3743.           if SE.Is_Null (Var_Value_Pair) then
  3744.              SE.Bind (Result, SE.Null_S_Expr);
  3745.           else
  3746.              SE.Bind (Value, SE.First (SE.Rest (Var_Value_Pair)));
  3747.  
  3748.              if SE.Is_Atomic (Value) and then
  3749.             not SE.Is_Variable (Value) then
  3750.             SE.Bind (Result, SE.Prefix (Var_Value_Pair));
  3751.              else
  3752.             SE.Bind (Result,
  3753.                  SE.Prefix (Var_Value_Pair,
  3754.                      Create_Bindings (Value,Binding_List)));
  3755.              end if;
  3756.           end if;
  3757.  
  3758.            -- Return null for any other atomic values.
  3759.  
  3760.            elsif SE.Is_Atomic (Template) then
  3761.           SE.Bind (Result, SE.Null_S_Expr);
  3762.  
  3763.            -- Otherwise, create a binding list by prefixing the result
  3764.            -- of processing the first component onto the result of
  3765.            -- processing the rest.
  3766.  
  3767.            elsif not SE.Is_Atomic (Template) then
  3768.           SE.Bind (Result, SE."&" (
  3769.                 Create_Bindings (SE.First (Template),Binding_List),
  3770.                 Create_Bindings (SE.Rest (Template),Binding_List)));
  3771.            end if;
  3772.  
  3773.            SE.Free (Var_Value_Pair);
  3774.            SE.Free (Value);
  3775.            return SE.Return_And_Free (Result);
  3776.         end Create_Bindings;
  3777.  
  3778.      begin
  3779.           Bind (Pattern1,
  3780.           Set_Bindings (Pattern1,
  3781.                 SE."Or" (
  3782.                    Get_Bindings (Pattern1),
  3783.                    Create_Bindings (Get_Template (Pattern1),
  3784.                             Binding_List))));
  3785.           Bind (Pattern2,
  3786.           Set_Bindings (Pattern2,
  3787.                 SE."Or" (
  3788.                    Get_Bindings (Pattern2),
  3789.                        Create_Bindings (Get_Template (Pattern2),
  3790.                             Binding_List))));
  3791.  
  3792.      end Set_Pattern_Bindings;
  3793.  
  3794.       begin
  3795.  
  3796.      -- Instantiate the variables found in the template with the 
  3797.      -- values (if any) to which they're bound in the binding context.
  3798.  
  3799.      SE.Bind (Match_Arg1, Instantiate (Pattern1));
  3800.      SE.Bind (Match_Arg2, Instantiate (Pattern2));
  3801.  
  3802.      -- Attempt to match the two templates,
  3803.      -- creating a binding list in the process.
  3804.  
  3805.      SE.Bind (Bindings,
  3806.            Match_With_Bindings (Match_Arg1, Match_Arg2, SE.Null_S_Expr));
  3807.  
  3808.      -- If the match was successful, set the binding contexts of the 
  3809.      -- individual patterns with the bindings found in the binding list.
  3810.      -- Set the value of the boolean result (a null value indicates failure)
  3811.      -- as appropriate.
  3812.  
  3813.      if not SE.Is_Null (Bindings) then
  3814.         SE.Bind (Bindings, SE.First (Bindings));
  3815.         if not SE.Is_Atomic (Bindings) then
  3816.            Set_Pattern_Bindings (Pattern1, Pattern2, Bindings);
  3817.         end if;
  3818.         Is_Match := True;
  3819.      else 
  3820.         Is_Match := False;
  3821.      end if;
  3822.  
  3823.          SE.Free (Match_Arg1);
  3824.          SE.Free (Match_Arg2);
  3825.          SE.Free (Bindings);
  3826.       end Match;
  3827.  
  3828.       -------------------------------------------------------------------------
  3829.  
  3830.       --    Procedure:    Get 
  3831.       --    Visibility:   Exported.
  3832.       --    Description:  Read a pattern from the specified input file.
  3833.       --
  3834.       --    Exceptions Raised: None.
  3835.  
  3836.       procedure Get (Input_File : in File_Type;
  3837.              Pattern_Result : in out Pattern) is
  3838.      S_Expr_Arg : SE.S_Expr;
  3839.       begin
  3840.      SE.Get (Input_File, S_Expr_Arg);
  3841.      Bind (Pattern_Result, Create_Pattern (Template => S_Expr_Arg));
  3842.      SE.Free (S_Expr_Arg);
  3843.       end Get;
  3844.  
  3845.       -------------------------------------------------------------------------
  3846.  
  3847.       --    Procedure:    Get 
  3848.       --    Visibility:   Exported.
  3849.       --    Description:  Read a pattern from the current default input file.
  3850.       --
  3851.       --    Exceptions Raised: None.
  3852.  
  3853.       procedure Get (Pattern_Result : in out Pattern) is
  3854.       begin
  3855.      Get (Current_Input, Pattern_Result);
  3856.       end Get;
  3857.  
  3858.       -------------------------------------------------------------------------
  3859.  
  3860.       --    Procedure:    Put
  3861.       --    Visibility:   Exported.
  3862.       --    Description:  Print the structure of the input pattern
  3863.       --                  to the current default output file.
  3864.       -- 
  3865.       --    Exceptions Raised: None.
  3866.  
  3867.       procedure Put (Pattern_Arg : in Pattern) is
  3868.       begin
  3869.      SE.Put (Current_Output, Instantiate (Pattern_Arg));
  3870.       end Put;
  3871.  
  3872.       -------------------------------------------------------------------------
  3873.  
  3874.       --    Procedure:    Put
  3875.       --    Visibility:   Exported.
  3876.       --    Description:  Print the structure of the input pattern
  3877.       --                  to the specified output file.
  3878.       -- 
  3879.       --    Exceptions Raised:  None.
  3880.  
  3881.       procedure Put (Output_File : in File_Type; Pattern_Arg : in Pattern) is
  3882.       begin
  3883.      SE.Put (Output_File, Instantiate (Pattern_Arg));
  3884.       end Put;
  3885.  
  3886.    end Patterns;
  3887.  
  3888.  
  3889.    package body Rules is
  3890.  
  3891.       -------------------------------------------------------------------------
  3892.  
  3893.       --    Function:     Create_Rule
  3894.       --    Visibility:   Exported.
  3895.       --    Description:  Creates a rule. The symbolic expressions form the 
  3896.       --                  rule's template and the rule's variable binding
  3897.       --                  context is set to null.
  3898.       --
  3899.       --    Exceptions Raised:  None.
  3900.  
  3901.       function Create_Rule (Antecedent,
  3902.                 Consequent,
  3903.                 Bindings : in SE.S_Expr := SE.Null_S_Expr)
  3904.      return Rule is
  3905.       begin
  3906.      if SE.Is_Null (Antecedent) and then
  3907.         SE.Is_Null (Consequent) and then
  3908.         SE.Is_Null (Bindings) then
  3909.         return Null_Rule;
  3910.      else
  3911.         return Rule (
  3912.            PAT.Create_Pattern (SE.Prefix(Antecedent, SE.Prefix(Consequent)),
  3913.                    Bindings));
  3914.      end if;
  3915.       end Create_Rule;
  3916.  
  3917.       -------------------------------------------------------------------------
  3918.  
  3919.       --    Function:     Antecedent
  3920.       --    Visibility:   Exported.
  3921.       --    Description:  Returns the antecedent of the given rule.
  3922.       --
  3923.       --    Exceptions Raised:  None.
  3924.  
  3925.       function Antecedent (Rule_Arg : in Rule) return PAT.Pattern is
  3926.       begin
  3927.      if Is_Null (Rule_Arg) then
  3928.         return PAT.Null_Pattern;
  3929.      else
  3930.         return PAT.Create_Pattern (SE.First (Get_Template (Rule_Arg)),
  3931.                        Get_Bindings (Rule_Arg));
  3932.      end if;
  3933.       end Antecedent;
  3934.  
  3935.       -------------------------------------------------------------------------
  3936.  
  3937.       --    Function:     Consequent
  3938.       --    Visibility:   Exported.
  3939.       --    Description:  Returns the consequent of the given rule.
  3940.       --
  3941.       --    Exceptions Raised:  None.
  3942.  
  3943.       function Consequent (Rule_Arg : in Rule) return PAT.Pattern is
  3944.       begin
  3945.      if Is_Null (Rule_Arg) then
  3946.         return PAT.Null_Pattern;
  3947.      else
  3948.         return PAT.Create_Pattern (
  3949.               SE.First (SE.Rest (Get_Template (Rule_Arg))),
  3950.               Get_Bindings (Rule_Arg));
  3951.      end if;
  3952.       end Consequent;
  3953.  
  3954.       -------------------------------------------------------------------------
  3955.  
  3956.       --    Function:     Is_Query
  3957.       --    Visibility:   Exported.
  3958.       --    Description:  Determines if the rule is a query.
  3959.       --                  A query is a rule which has only a antecedent.
  3960.       --
  3961.       --    Exceptions Raised:  None.
  3962.  
  3963.       function Is_Query (Rule_Arg : in Rule) return Boolean is
  3964.       begin
  3965.      if Is_Null (Rule_Arg) then
  3966.         return False;
  3967.      else
  3968.         return SE.Is_Null (SE.First (SE.Rest (Get_Template (Rule_Arg))));
  3969.      end if;
  3970.       end Is_Query;
  3971.  
  3972.       -------------------------------------------------------------------------
  3973.  
  3974.       --    Function:     Is_Fact
  3975.       --    Visibility:   Exported.
  3976.       --    Description:  Determines if the rule is a fact.
  3977.       --                  A fact is a rule which has only a consequent.
  3978.       --
  3979.       --    Exceptions Raised:  None.
  3980.  
  3981.       function Is_Fact (Rule_Arg : in Rule) return Boolean is
  3982.       begin
  3983.      if Is_Null (Rule_Arg) then
  3984.         return False;
  3985.      else
  3986.         return SE.Is_Null (SE.First (Get_Template (Rule_Arg)));
  3987.      end if;
  3988.       end Is_Fact;
  3989.  
  3990.       -------------------------------------------------------------------------
  3991.  
  3992.       --    Function:     Is_Rule
  3993.       --    Visibility:   Exported.
  3994.       --    Description:  Determines if the given rule contains
  3995.       --                  both a antecedent and a consequent.
  3996.       --
  3997.       --    Exceptions Raised:  None.
  3998.  
  3999.       function Is_Rule (Rule_Arg : in Rule) return Boolean is
  4000.       begin
  4001.      if Is_Null (Rule_Arg) then
  4002.         return False;
  4003.      else
  4004.         return not (Is_Query (Rule_Arg) or else Is_Fact (Rule_Arg));
  4005.      end if;
  4006.       end Is_Rule;
  4007.  
  4008.       -------------------------------------------------------------------------
  4009.  
  4010.       --    Procedure:    Get 
  4011.       --    Visibility:   Exported.
  4012.       --    Description:  Read a rule from the specified input file.
  4013.       --
  4014.       --    Exceptions Raised: Invalid_Rule_Format - if the input does not
  4015.       --                                             contain both an antecedent
  4016.       --                                             and consequent.
  4017.  
  4018.       procedure Get (Input_File : in File_Type; Rule_Result : in out Rule) is
  4019.      S_Expr_Arg : SE.S_Expr;
  4020.       begin
  4021.      SE.Get (Input_File, S_Expr_Arg);
  4022.      if SE.Is_Null (S_Expr_Arg) then
  4023.         Bind (Rule_Result, Null_Rule);
  4024.      else
  4025.         if SE.Length (S_Expr_Arg) /= 2 then
  4026.            SE.Free (S_Expr_Arg);
  4027.            raise Invalid_Rule_Format;
  4028.         else
  4029.            Bind (Rule_Result,
  4030.              Create_Rule (
  4031.             SE.First (S_Expr_Arg), SE.First (SE.Rest(S_Expr_Arg))));
  4032.         end if;
  4033.      end if;
  4034.      SE.Free (S_Expr_Arg);
  4035.       end Get;
  4036.  
  4037.       -------------------------------------------------------------------------
  4038.  
  4039.       --    Procedure:    Get 
  4040.       --    Visibility:   Exported.
  4041.       --    Description:  Read a rule from the current default input file.
  4042.       --
  4043.       --    Exceptions Raised: None.
  4044.  
  4045.       procedure Get (Rule_Result : in out Rule) is
  4046.       begin
  4047.      Get (Current_Input, Rule_Result);
  4048.       end Get;
  4049.  
  4050.    end Rules;
  4051.  
  4052.  
  4053.    package body Rulebases is
  4054.  
  4055.       Rulebase_Free_List : Rulebase := Null_Rulebase;
  4056.  
  4057.       -------------------------------------------------------------------------
  4058.  
  4059.       --    Function:     Is_Null
  4060.       --    Visibility:   Exported.
  4061.       --    Description:  Determines if Rulebase_Arg is empty.
  4062.       --
  4063.       --    Exceptions Raised:  None.
  4064.  
  4065.       function Is_Null (Rulebase_Arg : in Rulebase) return Boolean is
  4066.       begin
  4067.      -- Check if it's really null.
  4068.      if Rulebase_Arg = Null_Rulebase then
  4069.         return True;
  4070.  
  4071.      -- Otherwise, check to see if there are no rules.
  4072.      else
  4073.         declare 
  4074.            Empty : Boolean;
  4075.         begin
  4076.            for Id in Index'First .. Index'Last loop
  4077.           Empty := SE.Is_Null (Rulebase_Arg.Rules(Id));
  4078.           exit when not Empty;
  4079.            end loop;
  4080.            return Empty;
  4081.         end;
  4082.      end if;
  4083.       end Is_Null;
  4084.  
  4085.       -------------------------------------------------------------------------
  4086.  
  4087.       --    Function:     Is_Equal
  4088.       --    Visibility:   Exported.
  4089.       --    Description:  Determines if Rulebase_Arg1 is equivalent
  4090.       --                  to Rulebase_Arg2.
  4091.       --
  4092.       --    Exceptions Raised:  None.
  4093.  
  4094.       function Is_Equal (Rulebase_Arg1, Rulebase_Arg2 : in Rulebase)
  4095.      return Boolean is
  4096.      Result : Boolean;
  4097.       begin
  4098.      -- If one's null the other has to be null to be equal.
  4099.      if Is_Null (Rulebase_Arg1) then
  4100.         Result := Is_Null (Rulebase_Arg2);
  4101.  
  4102.      -- Otherwise, check to see if there are no rules.
  4103.      else
  4104.         for Id in Index'First .. Index'Last loop
  4105.            Result := SE.Is_Null (SE."Xor" (Rulebase_Arg1.Rules(Id),
  4106.                            Rulebase_Arg2.Rules(Id)));
  4107.            exit when not Result;
  4108.         end loop;
  4109.      end if;
  4110.  
  4111.      return Result;
  4112.       end Is_Equal;
  4113.  
  4114.       -------------------------------------------------------------------------
  4115.  
  4116.       --    Function:     Allocate Rulebase
  4117.       --    Visibility:   Internal
  4118.       --    Description:  Allocates a new rulebase with its rule array entries
  4119.       --                  initialized to Null_Rule.
  4120.       --
  4121.       --    Exceptions Raised:  None.
  4122.  
  4123.       function Allocate_Rulebase return Rulebase is
  4124.      New_Rulebase : Rulebase := Null_Rulebase;
  4125.      Array_Of_Rules : Rule_Array := Rule_Array'(others => RUL.Null_Rule);
  4126.       begin
  4127.  
  4128.      -- If the rulebase free list is empty, allocate a new rulebase
  4129.      -- node. Otherwise, retrieve one from the free list.
  4130.  
  4131.      if Is_Null (Rulebase_Free_List) then
  4132.         New_Rulebase := new Rulebase_Node; 
  4133.      else
  4134.         New_Rulebase := Rulebase_Free_List;
  4135.         Rulebase_Free_List := Rulebase_Free_List.Next_Free;
  4136.      end if;
  4137.  
  4138.      -- Initialize the node's reference counter,
  4139.      -- free list pointer and value.
  4140.  
  4141.      New_Rulebase.Ref_Count := 0;
  4142.      New_Rulebase.Next_Free := Null_Rulebase;
  4143.      New_Rulebase.Rules     := Array_Of_Rules;
  4144.  
  4145.      return New_Rulebase;
  4146.       end Allocate_Rulebase;
  4147.  
  4148.       -------------------------------------------------------------------------
  4149.  
  4150.       --    Function:     Create_Rulebase
  4151.       --    Visibility:   Exported.
  4152.       --    Description:  Creates a rulebase from the given symbolic expression.
  4153.       --
  4154.       --    Exceptions Raised:  None.
  4155.  
  4156.       function Create_Rulebase (Template : in SE.S_Expr) return Rulebase is
  4157.      New_Rulebase : Rulebase := Allocate_Rulebase;
  4158.      Temp_Pointer : SE.S_Expr;
  4159.       begin
  4160.      if SE.Is_Null (Template) then
  4161.         return Null_Rulebase;
  4162.      else
  4163.         SE.Bind (Temp_Pointer, Template);
  4164.         while not SE.Is_Null (Temp_Pointer) loop
  4165.            Assert (
  4166.           RUL.Create_Rule (SE.First (SE.First (Temp_Pointer)),
  4167.                    SE.First (SE.Rest (SE.First(Temp_Pointer)))),
  4168.           New_Rulebase);
  4169.            SE.Bind (Temp_Pointer, SE.Rest (Temp_Pointer));
  4170.         end loop;
  4171.      end if;
  4172.  
  4173.      SE.Free (Temp_Pointer);
  4174.      return New_Rulebase;
  4175.  
  4176.      exception
  4177.         when SE.Atomic_Expression | 
  4178.          RUL.Invalid_Rule_Format => 
  4179.            raise Invalid_Rulebase_Format;
  4180.  
  4181.       end Create_Rulebase;
  4182.  
  4183.       -------------------------------------------------------------------------
  4184.  
  4185.       --    Function:     Get_Template
  4186.       --    Visibility:   Exported.
  4187.       --    Description:  Returns a symbolic expression representing the
  4188.       --                  template for the given rulebase.
  4189.       --
  4190.       --    Exceptions Raised:  None.
  4191.  
  4192.       function Get_Template (Rulebase_Arg : in Rulebase) return SE.S_Expr is
  4193.      Template, Slot : SE.S_Expr;
  4194.       begin
  4195.      SE.Bind (Template, SE.Null_S_Expr);
  4196.      if not Is_Null (Rulebase_Arg) then
  4197.         for Id in reverse Index'First .. Index'Last loop
  4198.            SE.Bind (Slot, Rulebase_Arg.Rules(Id));
  4199.            while not SE.Is_Null (Slot) loop
  4200.           SE.Bind (Template,
  4201.              SE.Prefix (RUL.Instantiate (SE.First (Slot)), Template));
  4202.           SE.Bind (Slot, SE.Rest (Slot));
  4203.            end loop;
  4204.         end loop;
  4205.      end if;
  4206.  
  4207.      SE.Free (Slot);
  4208.      return SE.Return_And_Free (Template);
  4209.       end Get_Template;
  4210.  
  4211.       -------------------------------------------------------------------------
  4212.  
  4213.       --    Function:     Free
  4214.       --    Visibility:   Exported.
  4215.       --    Description:  Frees the given rulebase.
  4216.       --
  4217.       --    Exceptions Raised:  None.
  4218.  
  4219.       procedure Free (Rulebase_Arg : in out Rulebase) is
  4220.       begin
  4221.  
  4222.      -- Only non-null rulebases need to be freed.
  4223.  
  4224.      if not Is_Null (Rulebase_Arg) then
  4225.  
  4226.         -- If the reference count of the rulebase is greater than one
  4227.         -- (there is more than one variable of type Rulebase which refers
  4228.         -- to this structure), we don't want to return its storage to the
  4229.         -- free lists.  Just decrement the reference counter.
  4230.  
  4231.         if Rulebase_Arg.Ref_Count > 1 then
  4232.            Rulebase_Arg.Ref_Count := Rulebase_Arg.Ref_Count - 1;
  4233.  
  4234.         -- Otherwise, free all the contents of the rulebase and
  4235.         -- put it on the free list.
  4236.  
  4237.         else
  4238.            for Id in Index'First .. Index'Last loop
  4239.           SE.Free (Rulebase_Arg.Rules(Id));
  4240.            end loop;
  4241.            Rulebase_Arg.Next_Free := Rulebase_Free_List;
  4242.            Rulebase_Free_List := Rulebase_Arg;
  4243.         end if;
  4244.  
  4245.         Rulebase_Arg := Null_Rulebase;
  4246.      end if;
  4247.       end Free;
  4248.  
  4249.       -------------------------------------------------------------------------
  4250.  
  4251.       --    Function:     Return_And_Free
  4252.       --    Visibility:   Exported.
  4253.       --    Description:  Provides a way for decrementing the ref-count of a
  4254.       --                  rulebase bound to a local variable being returned
  4255.       --                  from a function.
  4256.       --
  4257.       --    Exceptions Raised:  None.
  4258.  
  4259.       function Return_And_Free (Rulebase_Arg : in Rulebase) return Rulebase is
  4260.       begin
  4261.      if not Is_Null (Rulebase_Arg) and then
  4262.         Rulebase_Arg.Ref_Count > 0 then
  4263.         Rulebase_Arg.Ref_Count := Rulebase_Arg.Ref_Count - 1;
  4264.      end if;
  4265.  
  4266.      return Rulebase_Arg;
  4267.       end Return_And_Free;
  4268.  
  4269.       -------------------------------------------------------------------------
  4270.  
  4271.       --    Function:     Bind 
  4272.       --    Visibility:   Exported.
  4273.       --    Description:  Assigns the value of New_Value to Current_Value after
  4274.       --                  freeing the value of Current_Value.
  4275.       --
  4276.       --    Exceptions Raised:  None.
  4277.  
  4278.       procedure Bind (Current_Value : in out Rulebase;
  4279.               New_Value : in Rulebase) is
  4280.      Temp_Value : Rulebase := Current_Value;
  4281.       begin
  4282.  
  4283.      -- Ignore cases of Bind (X, X);
  4284.  
  4285.      if Current_Value /= New_Value then
  4286.         Current_Value := New_Value;
  4287.           
  4288.         -- Increment the ref-count.
  4289.  
  4290.         if not Is_Null (Current_Value) then
  4291.            Current_Value.Ref_Count := Current_Value.Ref_Count + 1;
  4292.         end if;
  4293.  
  4294.         -- Free the original rulebase.
  4295.  
  4296.         if not Is_Null (Temp_Value) then
  4297.            Free (Temp_Value);
  4298.         end if;
  4299.      end if;
  4300.       end Bind;
  4301.  
  4302.       -------------------------------------------------------------------------
  4303.  
  4304.       --    Function:     Assert
  4305.       --    Visibility:   Exported.
  4306.       --    Description:  Adds the given rule to the specified rulebase.
  4307.       --
  4308.       --    Exceptions Raised:  None.
  4309.  
  4310.       procedure Assert (Rule_Arg : in RUL.Rule;
  4311.             Rulebase_Arg : in out Rulebase) is
  4312.      Id : Index;
  4313.       begin
  4314.      if Is_Null (Rulebase_Arg) then
  4315.         Bind (Rulebase_Arg, Allocate_Rulebase);
  4316.      end if;
  4317.      Id := Key (Rule_Arg);
  4318.      SE.Bind (Rulebase_Arg.Rules(Id),
  4319.           SE.Prefix(Rule_Arg, Rulebase_Arg.Rules(Id)));
  4320.       end Assert;
  4321.  
  4322.       -------------------------------------------------------------------------
  4323.  
  4324.       --    Function:     Retract
  4325.       --    Visibility:   Exported.
  4326.       --    Description:  Removes all occurrences of the given rule from the 
  4327.       --                  specified rulebase.
  4328.       --
  4329.       --    Exceptions Raised:  None.
  4330.  
  4331.       procedure Retract (Rule_Arg : in RUL.Rule;
  4332.              Rulebase_Arg : in out Rulebase) is
  4333.      Id : Index;
  4334.       begin
  4335.      if not Is_Null (Rulebase_Arg) then
  4336.         Id := Key (Rule_Arg);
  4337.         SE.Bind (Rulebase_Arg.Rules(Id),
  4338.              SE.Delete (Rule_Arg, Rulebase_Arg.Rules(Id)));
  4339.      end if;
  4340.       end Retract;
  4341.  
  4342.       -------------------------------------------------------------------------
  4343.  
  4344.       --    Function:     "And" (Intersection)
  4345.       --    Visibility:   Exported.
  4346.       --    Description:  Returns a rulebase containing all those rules
  4347.       --                  which are both in Rulebase1 AND Rulebase2.
  4348.       --
  4349.       --    Exceptions Raised:  None.
  4350.  
  4351.       function "And" (Rulebase1, Rulebase2 : in Rulebase) return Rulebase is
  4352.      New_Rulebase : Rulebase := Allocate_Rulebase;
  4353.       begin
  4354.      for Id in Index'First .. Index'Last loop
  4355.         SE.Bind (New_Rulebase.Rules(Id),
  4356.              SE."And" (Rulebase1.Rules(Id), Rulebase2.Rules(Id)));
  4357.      end loop;
  4358.      return New_Rulebase;
  4359.       end "And";
  4360.  
  4361.       -------------------------------------------------------------------------
  4362.  
  4363.       --    Function:     "Or" (Union)
  4364.       --    Visibility:   Exported.
  4365.       --    Description:  Returns a rulebase containing all those rules
  4366.       --                  which are either in Rulebase1 OR Rulebase2.
  4367.       --
  4368.       --    Exceptions Raised:  None.
  4369.  
  4370.       function "Or" (Rulebase1, Rulebase2 : in Rulebase) return Rulebase is
  4371.      New_Rulebase : Rulebase := Allocate_Rulebase;
  4372.       begin
  4373.      for Id in Index'First .. Index'Last loop
  4374.         SE.Bind (New_Rulebase.Rules(Id),
  4375.              SE."Or" (Rulebase1.Rules(Id), Rulebase2.Rules(Id)));
  4376.      end loop;
  4377.      return New_Rulebase;
  4378.       end "Or";
  4379.  
  4380.       -------------------------------------------------------------------------
  4381.  
  4382.       --    Function:     "-" (Difference)
  4383.       --    Visibility:   Exported.
  4384.       --    Description:  Returns a rulebase containing all those rules
  4385.       --                  which are in Rulebase1 but NOT in Rulebase2.
  4386.       --
  4387.       --    Exceptions Raised:  None.
  4388.  
  4389.       function "-" (Rulebase1, Rulebase2 : in Rulebase) return Rulebase is
  4390.      New_Rulebase : Rulebase := Allocate_Rulebase;
  4391.       begin
  4392.      for Id in Index'First .. Index'Last loop
  4393.         SE.Bind (New_Rulebase.Rules(Id),
  4394.              SE."-" (Rulebase1.Rules(Id), Rulebase2.Rules(Id)));
  4395.      end loop;
  4396.      return New_Rulebase;
  4397.       end "-";
  4398.  
  4399.       -------------------------------------------------------------------------
  4400.  
  4401.       --    Function:     "Xor" (Exclusive Or)
  4402.       --    Visibility:   Exported.
  4403.       --    Description:  Returns a rulebase containing all those rules
  4404.       --                  which are in Rulebase1 but NOT Rulebase2 AND
  4405.       --                  all those rules which are in Rulebase2 but NOT
  4406.       --                  in Rulebase1.
  4407.       --
  4408.       --    Exceptions Raised:  None.
  4409.  
  4410.       function "Xor" (Rulebase1, Rulebase2 : in Rulebase) return Rulebase is
  4411.      New_Rulebase : Rulebase := Allocate_Rulebase;
  4412.       begin
  4413.      for Id in Index'First .. Index'Last loop
  4414.         SE.Bind (New_Rulebase.Rules(Id),
  4415.              SE."Xor" (Rulebase1.Rules(Id), Rulebase2.Rules(Id)));
  4416.      end loop;
  4417.      return New_Rulebase;
  4418.       end "Xor";
  4419.  
  4420.       -------------------------------------------------------------------------
  4421.  
  4422.       --    Function:     Retrieve
  4423.       --    Visibility:   Exported.
  4424.       --    Description:  Returns a symbolic expression containing instantiated
  4425.       --                  versions of all rules which matched the input query.
  4426.       --
  4427.       --    Exceptions Raised:  None.
  4428.  
  4429.       function Retrieve (Rule_Arg : in RUL.Rule;
  4430.              Rulebase_Arg : in Rulebase) return SE.S_Expr is
  4431.      List_Of_Bindings, Current_Bindings,
  4432.      Antecedent_Var, List_Of_Instantiations : SE.S_Expr;
  4433.      Rule_Antecedent : PAT.Pattern;
  4434.  
  4435.      ----------------------------------------------------------------------
  4436.  
  4437.      --    Procedure:    Query
  4438.      --    Visibility:   Internal.
  4439.      --    Description:  Recursive procedure which follows a backward 
  4440.      --                  chaining algorithm to determine if the input
  4441.      --                  argument matches the information in the rulebase.
  4442.      --
  4443.      --    Exceptions Raised:  None.
  4444.  
  4445.      procedure Query (Query_Arg : in SE.S_Expr) is
  4446.  
  4447.         Rule_Subset, Original_Bindings : SE.S_Expr;
  4448.         New_Rule, Current_Rule : RUL.Rule;
  4449.         Success : Boolean;
  4450.  
  4451.      begin
  4452.  
  4453.         -- Create a new rule with the given query arg.
  4454.         RUL.Bind (New_Rule, RUL.Create_Rule (Antecedent_Var, Query_Arg));
  4455.  
  4456.         -- Get the subset of rules in the rulebase against 
  4457.         -- which we can match the new rule.
  4458.         SE.Bind (Rule_Subset, Rulebase_Arg.Rules (Key (New_Rule)));
  4459.  
  4460.         -- While there are still rules in the subset
  4461.         -- to be matched against ...
  4462.         while not SE.Is_Null (Rule_Subset) loop
  4463.  
  4464.                -- Erase any existing bindings for New_Rule.
  4465.            RUL.Bind (New_Rule, RUL.Set_Bindings (New_Rule, SE.Null_S_Expr));
  4466.  
  4467.            -- Get the first rule in the subset.
  4468.            RUL.Bind (Current_Rule, SE.First (Rule_Subset));
  4469.  
  4470.            -- Match the new rule with the current rule.
  4471.            RUL.Match (New_Rule, Current_Rule, Success);
  4472.  
  4473.            -- If the match succeeded ..
  4474.            if Success then
  4475.  
  4476.           -- Add the bindings of all variables in the new rule
  4477.           -- to the current binding set we're using.
  4478.           SE.Bind (Original_Bindings, Current_Bindings);
  4479.           SE.Bind (Current_Bindings,
  4480.                SE."&" (Current_Bindings,
  4481.                    RUL.Get_Bindings (New_Rule)));
  4482.           
  4483.           -- If the current rule is a fact ..
  4484.           if RUL.Is_Fact (Current_Rule) then
  4485.  
  4486.              -- Add the current binding set to the master
  4487.              -- set of binding sets.
  4488.              SE.Bind (List_Of_Bindings,
  4489.                   SE.Prefix (Current_Bindings, List_Of_Bindings));
  4490.  
  4491.           -- Otherwise, the current rule in the subset must
  4492.           -- actually be a rule.
  4493.           else
  4494.  
  4495.              -- Instantiate the value bound to the variable ?antecedent
  4496.              -- in the new rule and pass it off to a another invocation
  4497.              -- of the Query procedure.
  4498.              Query (PAT.Instantiate (RUL.Antecedent (New_Rule)));
  4499.           end if;
  4500.  
  4501.           -- Undo the bindings contributed by the new rule and
  4502.           -- reset the bindings of the current rule from the subset.
  4503.           SE.Bind (Current_Bindings, Original_Bindings);
  4504.           RUL.Bind (Current_Rule,
  4505.                 RUL.Set_Bindings (Current_Rule, SE.Null_S_Expr));
  4506.            end if;
  4507.  
  4508.            -- Shorten the symbolic expression containing the
  4509.            -- subset of rules to be examined.
  4510.            SE.Bind (Rule_Subset, SE.Rest (Rule_Subset));
  4511.         end loop;
  4512.  
  4513.         RUL.Free (Current_Rule);
  4514.         RUL.Free (New_Rule);
  4515.         SE.Free (Original_Bindings);
  4516.         SE.Free (Rule_Subset);
  4517.      end Query;
  4518.  
  4519.       begin
  4520.      -- Create a variable of the form "?antecedent"
  4521.      -- for use in the Query function.
  4522.      SE.Bind (Antecedent_Var, SE.Create_Atomic_Variable ("antecedent"));
  4523.  
  4524.      -- Extract the antecedent from the given query.
  4525.      PAT.Bind (Rule_Antecedent, RUL.Antecedent (Rule_Arg));
  4526.  
  4527.      -- Pass the instantiated pattern off to the Query function.
  4528.      Query (PAT.Instantiate (Rule_Antecedent));
  4529.  
  4530.      -- If a list of binding sets has been contributed as a
  4531.      -- result of the Query function, make a list of instantiations
  4532.      -- using the given query and the list of binding sets.
  4533.      while not SE.Is_Null (List_Of_Bindings) loop
  4534.         PAT.Bind (Rule_Antecedent,
  4535.               PAT.Set_Bindings (Rule_Antecedent,
  4536.                         SE.First (List_Of_Bindings)));
  4537.         SE.Bind (List_Of_Instantiations,
  4538.              SE.Prefix (PAT.Instantiate (Rule_Antecedent),
  4539.                         List_Of_Instantiations));
  4540.         SE.Bind (List_Of_Bindings, SE.Rest (List_Of_Bindings));
  4541.      end loop;
  4542.  
  4543.      SE.Free (List_Of_Bindings);
  4544.      SE.Free (Current_Bindings);
  4545.      SE.Free (Antecedent_Var);
  4546.      PAT.Free (Rule_Antecedent);
  4547.  
  4548.      -- Return the list of instantiations.
  4549.      return SE.Return_And_Free (List_Of_Instantiations);
  4550.  
  4551.       end Retrieve;
  4552.  
  4553.       -------------------------------------------------------------------------
  4554.  
  4555.       --    Procedure:    Get
  4556.       --    Visibility:   Exported.
  4557.       --    Description:  Reads a rulebase from the given input file.
  4558.       --
  4559.       --    Exceptions Raised:  None.
  4560.  
  4561.       procedure Get (Input_File : in File_Type;
  4562.              Rulebase_Result : in out Rulebase) is
  4563.      S_Expr_Arg : SE.S_Expr;
  4564.       begin
  4565.      SE.Get (Input_File, S_Expr_Arg);
  4566.      Bind (Rulebase_Result, Create_Rulebase (S_Expr_Arg));
  4567.      SE.Free (S_Expr_Arg);
  4568.       end Get;
  4569.  
  4570.       -------------------------------------------------------------------------
  4571.  
  4572.       --    Procedure:    Get
  4573.       --    Visibility:   Exported
  4574.       --    Description:  Reads a rulebase from the current default input file.
  4575.       --
  4576.       --    Exceptions Raised:  None.
  4577.  
  4578.       procedure Get (Rulebase_Result : in out Rulebase) is
  4579.       begin
  4580.      Get (Current_Input, Rulebase_Result);
  4581.       end Get;
  4582.  
  4583.       -------------------------------------------------------------------------
  4584.  
  4585.       --    Procedure:    Put
  4586.       --    Visibility:   Exported.
  4587.       --    Description:  Prints the contents of a rulebase to the given
  4588.       --                  output file.
  4589.       --
  4590.       --    Exceptions Raised:  None.
  4591.  
  4592.       procedure Put (Output_File : in File_Type;
  4593.              Rulebase_Arg : in Rulebase) is
  4594.       begin
  4595.      SE.Put (Output_File, Get_Template (Rulebase_Arg));
  4596.       end Put;
  4597.  
  4598.       -------------------------------------------------------------------------
  4599.  
  4600.       --    Procedure:    Put
  4601.       --    Visibility:   Exported.
  4602.       --    Description:  Prints the contents of a rulebase to the current
  4603.       --                  default output file.
  4604.       --
  4605.       --    Exceptions Raised:  None.
  4606.  
  4607.       procedure Put (Rulebase_Arg : in Rulebase) is
  4608.       begin
  4609.      SE.Put (Current_Output, Get_Template (Rulebase_Arg));
  4610.       end Put;
  4611.  
  4612.    end Rulebases;
  4613.  
  4614. begin
  4615.    Lookahead := ' ';
  4616. end AI_Data_Types;
  4617. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4618. --instspc.ada
  4619. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4620. ---------------------------------------------------------------------------
  4621.  
  4622. -- Inst_Facilities package specification
  4623.  
  4624. -- The following specification describes how the facilities which 
  4625. -- are needed to instantiate the AI_Data_Types package should be defined
  4626. -- and used.
  4627.  
  4628. -- Developing Organization:  Software Architecture & Engineering
  4629. --                           1600 Wilson Boulevard, Suite 500
  4630. --                           Arlington, VA  22209
  4631. --
  4632. -- Contact:  Michael A. Jaskowiak
  4633.  
  4634. ---------------------------------------------------------------------------
  4635.  
  4636. with Text_Io; use Text_Io;
  4637. with Integer_Text_Io; use Integer_Text_Io; 
  4638. with AI_Data_Types;
  4639. package Inst_Facilities is
  4640.  
  4641.    type Literal_Kind is (Int, Length1,  Length2,  Length3,  Length4,  Length5,
  4642.                   Length6,  Length7,  Length8,  Length9,  Length10,
  4643.                   Length11, Length12, Length13, Length14, Length15);
  4644.  
  4645.    type Atomic_Literal (Kind : Literal_Kind := Int) is
  4646.       record
  4647.      case Kind is
  4648.         when Int => Int : Integer;
  4649.         when Length1  => Length1  : String (1 .. 1);
  4650.         when Length2  => Length2  : String (1 .. 2);
  4651.         when Length3  => Length3  : String (1 .. 3);
  4652.         when Length4  => Length4  : String (1 .. 4);
  4653.         when Length5  => Length5  : String (1 .. 5);
  4654.         when Length6  => Length6  : String (1 .. 6);
  4655.         when Length7  => Length7  : String (1 .. 7);
  4656.         when Length8  => Length8  : String (1 .. 8);
  4657.         when Length9  => Length9  : String (1 .. 9);
  4658.         when Length10 => Length10 : String (1 .. 10);
  4659.         when Length11 => Length11 : String (1 .. 11);
  4660.         when Length12 => Length12 : String (1 .. 12);
  4661.         when Length13 => Length13 : String (1 .. 13);
  4662.         when Length14 => Length14 : String (1 .. 14);
  4663.         when Length15 => Length15 : String (1 .. 15);
  4664.      end case;
  4665.       end record;
  4666.  
  4667.    ----------------------------------------------------------------------
  4668.  
  4669.    --    Function:       String_To_Literal
  4670.    --    Description:    Converts the input string to a value of
  4671.    --                    type Atomic_Literal.
  4672.    --    Restrictions:  None.
  4673.  
  4674.    function String_To_Literal (String_Arg : in String)
  4675.       return Atomic_Literal;
  4676.  
  4677.    -------------------------------------------------------------------------
  4678.  
  4679.    --    Function:       Is_Equal
  4680.    --    Description:    Determines if two atomic literals are equivalent.
  4681.    --    Restrictions:   None.
  4682.  
  4683.    function Is_Equal (Lit_Arg1, Lit_Arg2 : in Atomic_Literal)
  4684.       return Boolean;
  4685.  
  4686.    Lookahead : Character := ' ';
  4687.  
  4688.    -------------------------------------------------------------------------
  4689.  
  4690.    --    Procedure:      Get
  4691.    --    Description:    Reads an atomic literal from the given file.
  4692.    --    Restrictions:   None.
  4693.  
  4694.    procedure Get (Input_File : in File_Type;
  4695.           Literal_Result : in out Atomic_Literal);
  4696.  
  4697.    -------------------------------------------------------------------------
  4698.  
  4699.    --    Procedure:      Put
  4700.    --    Description:    Prints the image of the input atomic literal.
  4701.    --    Restrictions:   None.
  4702.  
  4703.    procedure Put (Output_File : in File_Type;
  4704.           Literal_Arg : in Atomic_Literal);
  4705.  
  4706.    package AI_Types is
  4707.       new AI_Data_Types (Atomic_Literal, Is_Equal, Lookahead, Get, Put);
  4708.  
  4709. end Inst_Facilities;
  4710. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4711. --instimp.ada
  4712. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4713. ---------------------------------------------------------------------------
  4714.  
  4715. -- Inst_Facilities package implementation
  4716.  
  4717. -- The following implementation describes how the facilities which 
  4718. -- are needed to instantiate the AI_Data_Types package should be defined
  4719. -- and used.
  4720.  
  4721. -- Developing Organization:  Software Architecture & Engineering
  4722. --                           1600 Wilson Boulevard, Suite 500
  4723. --                           Arlington, VA  22209
  4724. --
  4725. -- Contact:  Michael A. Jaskowiak
  4726.  
  4727. ---------------------------------------------------------------------------
  4728.  
  4729. package body Inst_Facilities is
  4730.  
  4731.    ----------------------------------------------------------------------
  4732.  
  4733.    --    Function:       String_To_Literal
  4734.    --    Description:    Converts the input string to a value of
  4735.    --                    type Atomic_Literal.
  4736.    --    Restrictions:  None.
  4737.  
  4738.    function String_To_Literal (String_Arg : in String)
  4739.       return Atomic_Literal is
  4740.       Atom_Value : Atomic_Literal;
  4741.       Atom_Str   : String (1 .. String_Arg'Length) := String_Arg;
  4742.       Is_Numeric : Boolean := True;
  4743.       Index      : Natural range 0 .. Atom_Str'Last := 1;
  4744.    begin
  4745.       Is_Numeric :=
  4746.      ('0' <= Atom_Str(Index) and Atom_Str(Index) <= '9') or else
  4747.      (Atom_Str(Index) = '-' and Index /= Atom_Str'Last);
  4748.  
  4749.       while Is_Numeric and then
  4750.         Index /= Atom_Str'Last loop
  4751.      Index := Index + 1;
  4752.      Is_Numeric := '0' <= Atom_Str(Index) and Atom_Str(Index) <= '9';
  4753.       end loop;
  4754.  
  4755.       if Is_Numeric then
  4756.      Atom_Value := (Kind => Int, Int => Integer'Value (Atom_Str));
  4757.       else
  4758.      case Atom_Str'Length is
  4759.         when 1  => Atom_Value := (Kind => Length1,  Length1  => Atom_Str);
  4760.         when 2  => Atom_Value := (Kind => Length2,  Length2  => Atom_Str);
  4761.         when 3  => Atom_Value := (Kind => Length3,  Length3  => Atom_Str);
  4762.         when 4  => Atom_Value := (Kind => Length4,  Length4  => Atom_Str);
  4763.         when 5  => Atom_Value := (Kind => Length5,  Length5  => Atom_Str);
  4764.         when 6  => Atom_Value := (Kind => Length6,  Length6  => Atom_Str);
  4765.         when 7  => Atom_Value := (Kind => Length7,  Length7  => Atom_Str);
  4766.         when 8  => Atom_Value := (Kind => Length8,  Length8  => Atom_Str);
  4767.         when 9  => Atom_Value := (Kind => Length9,  Length9  => Atom_Str);
  4768.         when 10 => Atom_Value := (Kind => Length10, Length10 => Atom_Str);
  4769.         when 11 => Atom_Value := (Kind => Length11, Length11 => Atom_Str);
  4770.         when 12 => Atom_Value := (Kind => Length12, Length12 => Atom_Str);
  4771.         when 13 => Atom_Value := (Kind => Length13, Length13 => Atom_Str);
  4772.         when 14 => Atom_Value := (Kind => Length14, Length14 => Atom_Str);
  4773.         when 15 => Atom_Value := (Kind => Length15, Length15 => Atom_Str);
  4774.         when others => raise Constraint_Error;
  4775.      end case;
  4776.       end if;
  4777.  
  4778.       return Atom_Value;
  4779.    end String_To_Literal;
  4780.  
  4781.    -------------------------------------------------------------------------
  4782.  
  4783.    --    Function:       Is_Equal
  4784.    --    Description:    Determines if two atomic literals are equivalent.
  4785.    --    Restrictions:   None.
  4786.  
  4787.    function Is_Equal (Lit_Arg1, Lit_Arg2 : in Atomic_Literal) return Boolean is
  4788.    begin
  4789.       if Lit_Arg1.Kind /= Lit_Arg2.Kind then
  4790.      return False;
  4791.       else
  4792.      case Lit_Arg1.Kind is
  4793.         when Int => return Lit_Arg1.Int  = Lit_Arg2.Int;
  4794.         when Length1  => return Lit_Arg1.Length1  = Lit_Arg2.Length1;
  4795.         when Length2  => return Lit_Arg1.Length2  = Lit_Arg2.Length2;
  4796.         when Length3  => return Lit_Arg1.Length3  = Lit_Arg2.Length3;
  4797.         when Length4  => return Lit_Arg1.Length4  = Lit_Arg2.Length4;
  4798.         when Length5  => return Lit_Arg1.Length5  = Lit_Arg2.Length5;
  4799.         when Length6  => return Lit_Arg1.Length6  = Lit_Arg2.Length6;
  4800.         when Length7  => return Lit_Arg1.Length7  = Lit_Arg2.Length7;
  4801.         when Length8  => return Lit_Arg1.Length8  = Lit_Arg2.Length8;
  4802.         when Length9  => return Lit_Arg1.Length9  = Lit_Arg2.Length9;
  4803.         when Length10 => return Lit_Arg1.Length10 = Lit_Arg2.Length10;
  4804.         when Length11 => return Lit_Arg1.Length11 = Lit_Arg2.Length11;
  4805.         when Length12 => return Lit_Arg1.Length12 = Lit_Arg2.Length12;
  4806.         when Length13 => return Lit_Arg1.Length13 = Lit_Arg2.Length13;
  4807.         when Length14 => return Lit_Arg1.Length14 = Lit_Arg2.Length14;
  4808.         when Length15 => return Lit_Arg1.Length15 = Lit_Arg2.Length15;
  4809.      end case;
  4810.       end if;
  4811.    end Is_Equal;
  4812.  
  4813.    -------------------------------------------------------------------------
  4814.  
  4815.    --    Procedure:      Get
  4816.    --    Description:    Reads an atomic literal from the given file.
  4817.    --    Restrictions:   None.
  4818.  
  4819.    procedure Get (Input_File : in File_Type;
  4820.           Literal_Result : in out Atomic_Literal) is
  4821.  
  4822.       ----------------------------------------------------------------------
  4823.  
  4824.       --    Function:     Get_Atom_Rep 
  4825.       --    Visibility:   Internal.
  4826.       --    Description:  Returns a string containing the character 
  4827.       --                  representation of the next atomic expression
  4828.       --                  to be processed.
  4829.       --
  4830.       --    Exceptions Raised: None.
  4831.  
  4832.       function Get_Atom_Rep return String is
  4833.      Input_Char        : Character;
  4834.      Max_Buffer_Length : constant Natural := 255;
  4835.      Position          : Natural range 0 .. Max_Buffer_Length := 0;
  4836.      Atom_Buffer       : String (1 .. Max_Buffer_Length);
  4837.      Separator         : constant Character := ',';
  4838.      Delimiter         : constant Character := ' ';
  4839.      Non_Atomic_Suffix : constant Character := ')';
  4840.       begin
  4841.  
  4842.          Input_Char := Lookahead;
  4843.      Lookahead := ' ';
  4844.  
  4845.      -- Read characters from the file and put them in a 
  4846.      -- buffer until finding a separator or non-atomic suffix
  4847.      -- or the end of the line.
  4848.  
  4849.      while Input_Char /= Separator and then
  4850.            Input_Char /= Delimiter and then
  4851.            Input_Char /= Non_Atomic_Suffix loop
  4852.         Position := Position + 1;
  4853.         Atom_Buffer (Position) := Input_Char;
  4854.  
  4855.         exit when End_Of_Line (Input_File);
  4856.  
  4857.         Get (Input_File, Input_Char);
  4858.      end loop;
  4859.  
  4860.      if Input_Char = Separator or else
  4861.         Input_Char = Non_Atomic_Suffix then
  4862.         Lookahead := Input_Char;
  4863.      end if;
  4864.  
  4865.      return Atom_Buffer (1 .. Position);
  4866.       end Get_Atom_Rep;
  4867.  
  4868.    begin
  4869.       Literal_Result := String_To_Literal (Get_Atom_Rep);
  4870.    end Get;
  4871.  
  4872.    -------------------------------------------------------------------------
  4873.  
  4874.    --    Procedure:      Put
  4875.    --    Description:    Prints the image of the input atomic literal.
  4876.    --    Restrictions:   None.
  4877.  
  4878.    procedure Put (Output_File : in File_Type;
  4879.           Literal_Arg : in Atomic_Literal) is
  4880.    begin
  4881.       case Literal_Arg.Kind is
  4882.      when Int => Put (File => Output_File,
  4883.               Item => Literal_Arg.Int, Width => 0);
  4884.      when Length1  => Put (Output_File, Literal_Arg.Length1);
  4885.      when Length2  => Put (Output_File, Literal_Arg.Length2);
  4886.      when Length3  => Put (Output_File, Literal_Arg.Length3);
  4887.      when Length4  => Put (Output_File, Literal_Arg.Length4);
  4888.      when Length5  => Put (Output_File, Literal_Arg.Length5);
  4889.      when Length6  => Put (Output_File, Literal_Arg.Length6);
  4890.      when Length7  => Put (Output_File, Literal_Arg.Length7);
  4891.      when Length8  => Put (Output_File, Literal_Arg.Length8);
  4892.      when Length9  => Put (Output_File, Literal_Arg.Length9);
  4893.      when Length10 => Put (Output_File, Literal_Arg.Length10);
  4894.      when Length11 => Put (Output_File, Literal_Arg.Length11);
  4895.      when Length12 => Put (Output_File, Literal_Arg.Length12);
  4896.      when Length13 => Put (Output_File, Literal_Arg.Length13);
  4897.      when Length14 => Put (Output_File, Literal_Arg.Length14);
  4898.      when Length15 => Put (Output_File, Literal_Arg.Length15);
  4899.       end case;
  4900.    end Put;
  4901.  
  4902. end Inst_Facilities;
  4903. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4904. --aitypesdemo.ada
  4905. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4906. ---------------------------------------------------------------------------
  4907.  
  4908. -- AITypesdemo demonstration implementation 
  4909.  
  4910. -- The following subprogram is an implementation of the facilities
  4911. -- used to demonstrate the AI_Data_Types package.
  4912.  
  4913. -- Developing Organization:  Software Architecture & Engineering
  4914. --                           1600 Wilson Boulevard, Suite 500
  4915. --                           Arlington, VA  22209
  4916. --
  4917. -- Contact:  Michael A. Jaskowiak
  4918.  
  4919. ---------------------------------------------------------------------------
  4920.  
  4921. with Text_Io;
  4922. with Integer_Text_Io;
  4923. with Inst_Facilities;
  4924. procedure AITypesdemo is
  4925.    Max_Length    : constant Natural := 8;
  4926.    Stringlength  : Natural range 0 .. Max_Length;
  4927.    Response      : String (1 .. Max_Length)  := (1 .. Max_Length  => ' ');
  4928.  
  4929.    package SE renames Inst_Facilities.AI_Types.Symbolic_Expressions;
  4930.    package PAT renames Inst_Facilities.AI_Types.Patterns;
  4931.    package RUL renames Inst_Facilities.AI_Types.Rules;
  4932.    package TIO renames Text_Io;
  4933.    package ITIO renames Integer_Text_Io;
  4934.    package BIO is new TIO.Enumeration_Io (Boolean);
  4935.  
  4936.    procedure Sexprdemo is 
  4937.  
  4938.       type Functions is (Is_Null, Is_Atomic, Is_Variable, Is_Non_Atomic,
  4939.              Is_Equal, Is_Member, Prefix, Append, First, Rest,
  4940.              Last, Nth, Nth_First, Nth_Rest, Reverse_S_Expr,
  4941.              Delete, Replace, Flatten, Set_And, Set_Or, Set_Differ,
  4942.              Set_Xor, Associate, Associate_All, Length, Help, Quit);
  4943.  
  4944.       package FIO is new TIO.Enumeration_Io (Functions);
  4945.  
  4946.       Function_Name : Functions;
  4947.       Symbol_Exp1, Symbol_Exp2, Symbol_Exp3, Result : SE.S_Expr;
  4948.       Prompt : constant String := " -> ";
  4949.       Spacer : constant String := "    ";
  4950.       Position, Repetitions, Int_Result : Integer;
  4951.       Boolean_Result : Boolean;
  4952.   
  4953.    begin
  4954.       TIO.New_Line;
  4955.       TIO.Put_line(" Entering the Symbolic Expression Demonstration.");
  4956.       TIO.Put_line(" To terminate this demonstration, enter ""quit"" at any time.");
  4957.       TIO.Put_line(" For a list of available operations, enter ""help"".");
  4958.       TIO.New_Line;
  4959.  
  4960.       SE.Bind (Symbol_Exp1, SE.Null_S_Expr);
  4961.       SE.Bind (Symbol_Exp2, SE.Null_S_Expr);
  4962.       SE.Bind (Symbol_Exp3, SE.Null_S_Expr);
  4963.       SE.Bind (Result, SE.Null_S_Expr);
  4964.  
  4965.       loop
  4966.      TIO.New_Line;
  4967.      TIO.Put (Prompt);
  4968.  
  4969.      begin
  4970.         FIO.Get (Function_Name);
  4971.  
  4972.         case Function_Name is
  4973.  
  4974.            when Is_Null =>
  4975.           SE.Get (Symbol_Exp1);
  4976.           Boolean_Result := SE.Is_Null (Symbol_Exp1);
  4977.           TIO.New_Line;
  4978.           TIO.Put (Spacer);
  4979.           BIO.Put (Boolean_Result);
  4980.  
  4981.            when Is_Atomic =>
  4982.           SE.Get (Symbol_Exp1);
  4983.           Boolean_Result := SE.Is_Atomic (Symbol_Exp1);
  4984.           TIO.New_Line;
  4985.           TIO.Put (Spacer);
  4986.           BIO.Put (Boolean_Result);
  4987.  
  4988.            when Is_Variable =>
  4989.           SE.Get (Symbol_Exp1);
  4990.           Boolean_Result := SE.Is_Variable (Symbol_Exp1);
  4991.           TIO.New_Line;
  4992.           TIO.Put (Spacer);
  4993.           BIO.Put (Boolean_Result);
  4994.  
  4995.            when Is_Non_Atomic =>
  4996.           SE.Get (Symbol_Exp1);
  4997.           Boolean_Result := SE.Is_Non_Atomic (Symbol_Exp1);
  4998.           TIO.New_Line;
  4999.           TIO.Put (Spacer);
  5000.           BIO.Put (Boolean_Result);
  5001.  
  5002.            when Is_Equal =>
  5003.           SE.Get (Symbol_Exp1);
  5004.           SE.Get (Symbol_Exp2);
  5005.           Boolean_Result := SE.Is_Equal (Symbol_Exp1, Symbol_Exp2);
  5006.           TIO.New_Line;
  5007.           TIO.Put (Spacer);
  5008.           BIO.Put (Boolean_Result);
  5009.  
  5010.            when Is_Member =>
  5011.           SE.Get (Symbol_Exp1);
  5012.           SE.Get (Symbol_Exp2);
  5013.           Boolean_Result := SE.Is_Member (Symbol_Exp1, Symbol_Exp2);
  5014.           TIO.New_Line;
  5015.           TIO.Put (Spacer);
  5016.           BIO.Put (Boolean_Result);
  5017.  
  5018.            when First =>
  5019.           SE.Get (Symbol_Exp1);
  5020.           SE.Bind (Result, SE.First (Symbol_Exp1));
  5021.           TIO.New_Line;
  5022.           TIO.Put (Spacer);
  5023.           SE.Put (Result);
  5024.  
  5025.            when Rest =>
  5026.           SE.Get (Symbol_Exp1);
  5027.           SE.Bind (Result, SE.Rest (Symbol_Exp1));
  5028.           TIO.New_Line;
  5029.           TIO.Put (Spacer);
  5030.           SE.Put (Result);
  5031.  
  5032.            when Last =>
  5033.           SE.Get (Symbol_Exp1);
  5034.           SE.Bind (Result, SE.Last (Symbol_Exp1));
  5035.           TIO.New_Line;
  5036.           TIO.Put (Spacer);
  5037.           SE.Put (Result);
  5038.  
  5039.            when Nth =>
  5040.           SE.Get (Symbol_Exp1);
  5041.           ITIO.Get (Position);
  5042.           SE.Bind (Result, SE.Nth (Symbol_Exp1, Position));
  5043.           TIO.Put (Spacer);
  5044.           SE.Put (Result);
  5045.  
  5046.            when Nth_First =>
  5047.           SE.Get (Symbol_Exp1);
  5048.           ITIO.Get (Repetitions);
  5049.           SE.Bind (Result, SE.Nth_First (Symbol_Exp1, Repetitions));
  5050.           TIO.Put (Spacer);
  5051.           SE.Put (Result);
  5052.  
  5053.            when Nth_Rest =>
  5054.           SE.Get (Symbol_Exp1);
  5055.           ITIO.Get (Repetitions);
  5056.           SE.Bind (Result, SE.Nth_Rest (Symbol_Exp1, Repetitions));
  5057.           TIO.Put (Spacer);
  5058.           SE.Put (Result);
  5059.  
  5060.            when Prefix =>
  5061.           SE.Get (Symbol_Exp1);
  5062.           SE.Get (Symbol_Exp2);
  5063.           SE.Bind (Result, SE.Prefix (Symbol_Exp1, Symbol_Exp2));
  5064.           TIO.New_Line;
  5065.           TIO.Put (Spacer);
  5066.           SE.Put (Result);
  5067.  
  5068.            when Reverse_S_Expr =>
  5069.           SE.Get (Symbol_Exp1);
  5070.           SE.Bind (Result, SE.Reverse_S_Expr (Symbol_Exp1));
  5071.           TIO.New_Line;
  5072.           TIO.Put (Spacer);
  5073.           SE.Put (Result);
  5074.  
  5075.            when Length =>
  5076.           SE.Get (Symbol_Exp1);
  5077.           Int_Result := SE.Length (Symbol_Exp1);
  5078.           TIO.New_Line;
  5079.           TIO.Put (Spacer);
  5080.           ITIO.Put (Item => Int_Result, Width => 0);
  5081.  
  5082.            when Delete =>
  5083.           SE.Get (Symbol_Exp1);
  5084.           SE.Get (Symbol_Exp2);
  5085.           SE.Bind (Result, SE.Delete (Symbol_Exp1, Symbol_Exp2));
  5086.           TIO.New_Line;
  5087.           TIO.Put (Spacer);
  5088.           SE.Put (Result);
  5089.  
  5090.            when Replace =>
  5091.           SE.Get (Symbol_Exp1);
  5092.           SE.Get (Symbol_Exp2);
  5093.           SE.Get (Symbol_Exp3);
  5094.           SE.Bind (Result,
  5095.                SE.Replace (Symbol_Exp1, Symbol_Exp2, Symbol_Exp3));
  5096.           TIO.New_Line;
  5097.           TIO.Put (Spacer);
  5098.           SE.Put (Result);
  5099.  
  5100.            when Flatten =>
  5101.           SE.Get (Symbol_Exp1);
  5102.           SE.Bind (Result, SE.Flatten (Symbol_Exp1));
  5103.           TIO.New_Line;
  5104.           TIO.Put (Spacer);
  5105.           SE.Put (Result);
  5106.  
  5107.            when Set_And =>
  5108.           SE.Get (Symbol_Exp1);
  5109.           SE.Get (Symbol_Exp2);
  5110.           SE.Bind (Result, SE."And" (Symbol_Exp1, Symbol_Exp2));
  5111.           TIO.New_Line;
  5112.           TIO.Put (Spacer);
  5113.           SE.Put (Result);
  5114.  
  5115.            when Set_Or =>
  5116.           SE.Get (Symbol_Exp1);
  5117.           SE.Get (Symbol_Exp2);
  5118.           SE.Bind (Result, SE."Or" (Symbol_Exp1, Symbol_Exp2));
  5119.           TIO.New_Line;
  5120.           TIO.Put (Spacer);
  5121.           SE.Put (Result);
  5122.  
  5123.            when Set_Differ =>
  5124.           SE.Get (Symbol_Exp1);
  5125.           SE.Get (Symbol_Exp2);
  5126.           SE.Bind (Result, SE."-" (Symbol_Exp1, Symbol_Exp2));
  5127.           TIO.New_Line;
  5128.           TIO.Put (Spacer);
  5129.           SE.Put (Result);
  5130.  
  5131.            when Set_Xor =>
  5132.           SE.Get (Symbol_Exp1);
  5133.           SE.Get (Symbol_Exp2);
  5134.           SE.Bind (Result, SE."Xor" (Symbol_Exp1, Symbol_Exp2));
  5135.           TIO.New_Line;
  5136.           TIO.Put (Spacer);
  5137.           SE.Put (Result);
  5138.  
  5139.            when Associate =>
  5140.           SE.Get (Symbol_Exp1);
  5141.           SE.Get (Symbol_Exp2);
  5142.           ITIO.Get (Position);
  5143.           SE.Bind (Result,
  5144.                SE.Associate (Symbol_Exp1, Symbol_Exp2, Position));
  5145.           TIO.Put (Spacer);
  5146.           SE.Put (Result);
  5147.  
  5148.            when Associate_All =>
  5149.           SE.Get (Symbol_Exp1);
  5150.           SE.Get (Symbol_Exp2);
  5151.           ITIO.Get (Position);
  5152.           SE.Bind (Result,
  5153.                SE.Associate_All (Symbol_Exp1, Symbol_Exp2, Position));
  5154.           TIO.Put (Spacer);
  5155.           SE.Put (Result);
  5156.  
  5157.            when Append =>
  5158.           SE.Get (Symbol_Exp1);
  5159.           SE.Get (Symbol_Exp2);
  5160.           SE.Bind (Result, SE."&" (Symbol_Exp1, Symbol_Exp2));
  5161.           TIO.New_Line;
  5162.           TIO.Put (Spacer);
  5163.           SE.Put (Result);
  5164.  
  5165.            when Help =>
  5166.           TIO.New_Line;
  5167.           TIO.New_Line;
  5168.           TIO.Put_Line (" Available Operations:");
  5169.           TIO.New_Line;
  5170.           TIO.Put_Line ("    Append         Help           Is_Variable  Prefix          Set_Differ");
  5171.           TIO.Put_Line ("    Associate      Is_Atomic      Last         Quit            Set_Or");
  5172.           TIO.Put_Line ("    Associate_All  Is_Equal       Length       Replace         Set_Xor");
  5173.           TIO.Put_Line ("    Delete         Is_Member      Nth          Rest");
  5174.           TIO.Put_Line ("    First          Is_Non_Atomic  Nth_First    Reverse_S_Expr");
  5175.           TIO.Put_Line ("    Flatten        Is_Null        Nth_Rest     Set_And");
  5176.           TIO.New_Line;
  5177.           TIO.Put_Line (" For more specific information, see the User's Manual.");
  5178.  
  5179.            when Quit =>
  5180.           TIO.Skip_Line;
  5181.           TIO.Put_line (" Exiting Symbolic Expression Demonstration.");
  5182.           return;
  5183.  
  5184.            when Others =>
  5185.           TIO.New_Line;
  5186.           TIO.Put (Spacer);
  5187.           TIO.Put ("Not accessible.");
  5188.  
  5189.         end case;
  5190.  
  5191.  
  5192.         exception
  5193.            when TIO.Data_Error =>
  5194.           TIO.Put (Spacer);
  5195.           TIO.Put ("Incorrect function name, try again.");
  5196.            when SE.Improper_Input =>
  5197.           TIO.Put (Spacer);
  5198.           TIO.Put ("Input error, try again.");
  5199.            when SE.Atomic_Expression =>
  5200.           TIO.Put (Spacer);
  5201.           TIO.Put ("Input must be non-atomic, try again.");
  5202.            when SE.Non_Atomic_Expression =>
  5203.           TIO.Put (Spacer);
  5204.           TIO.Put ("Input must be atomic, try again.");
  5205.            when SE.Invalid_Position =>
  5206.           TIO.Put (Spacer);
  5207.           TIO.Put ("No value at that position, try again.");
  5208.            when SE.Missing_Separator =>
  5209.           TIO.Put (Spacer);
  5210.           TIO.Put ("Input is missing a separator, try again.");
  5211.            when SE.Extra_Separator =>
  5212.           TIO.Put (Spacer);
  5213.           TIO.Put ("Input has an extra separator, try again.");
  5214.            when SE.Invalid_Repetitions =>
  5215.           TIO.Put (Spacer);
  5216.           TIO.Put ("Invalid number of repetitions, try again.");
  5217.      end;
  5218.  
  5219.      TIO.Skip_Line;
  5220.      SE.Free (Symbol_Exp1);
  5221.      SE.Free (Symbol_Exp2);
  5222.      SE.Free (Symbol_Exp3);
  5223.      SE.Free (Result);
  5224.       end loop;
  5225.  
  5226.    end Sexprdemo;
  5227.  
  5228.    procedure Patdemo is 
  5229.  
  5230.       type Functions is (Is_Null1, Is_Null2, Is_Equal, Create_Pattern1,
  5231.              Create_Pattern2, Get_Template1, Get_Template2,
  5232.              Set_Bindings1, Set_Bindings2, Get_Bindings1,
  5233.              Get_Bindings2, Instantiate1, Instantiate2,
  5234.              First1, First2, Rest1, Rest2, Match, Help,
  5235.              Tag_Variables1, Tag_Variables2, Free1, Free2, Quit);
  5236.  
  5237.       package FIO is new TIO.Enumeration_Io (Functions);
  5238.  
  5239.       Function_Name : Functions;
  5240.       S_Expr_Result : SE.S_Expr;
  5241.       Pattern1, Pattern2, Pattern_Result : PAT.Pattern;
  5242.       Prompt : constant String := " -> ";
  5243.       Spacer : constant String := "    ";
  5244.       Boolean_Result : Boolean;
  5245.       Tag_Value : Natural;
  5246.   
  5247.    begin
  5248.       TIO.New_Line;
  5249.       TIO.Put_Line(" Entering the Pattern Demonstration.");
  5250.       TIO.Put_Line(" To terminate this demonstration, enter ""quit"" at any time.");
  5251.       TIO.Put_line(" For a list of available operations, enter ""help"".");
  5252.       TIO.New_Line;
  5253.  
  5254.       PAT.Bind (Pattern1, PAT.Null_Pattern);
  5255.       PAT.Bind (Pattern2, PAT.Null_Pattern);
  5256.       PAT.Bind (Pattern_Result, PAT.Null_Pattern);
  5257.       SE.Bind (S_Expr_Result, SE.Null_S_Expr);
  5258.  
  5259.       loop
  5260.      TIO.New_Line;
  5261.      TIO.Put (Prompt);
  5262.  
  5263.      begin
  5264.         FIO.Get (Function_Name);
  5265.  
  5266.         case Function_Name is
  5267.  
  5268.            when Is_Null1 =>
  5269.           Boolean_Result := PAT.Is_Null (Pattern1);
  5270.           TIO.New_Line;
  5271.           TIO.Put (Spacer);
  5272.           BIO.Put (Boolean_Result);
  5273.  
  5274.            when Is_Null2 =>
  5275.           Boolean_Result := PAT.Is_Null (Pattern2);
  5276.           TIO.New_Line;
  5277.           TIO.Put (Spacer);
  5278.           BIO.Put (Boolean_Result);
  5279.  
  5280.            when Is_Equal =>
  5281.           Boolean_Result := PAT.Is_Equal (Pattern1, Pattern2);
  5282.           TIO.New_Line;
  5283.           TIO.Put (Spacer);
  5284.           BIO.Put (Boolean_Result);
  5285.  
  5286.            
  5287.            when Create_Pattern1 =>
  5288.           PAT.Get (Pattern1);
  5289.           TIO.New_Line;
  5290.           TIO.Put (Spacer);
  5291.           PAT.Put (Pattern1);
  5292.  
  5293.            when Create_Pattern2 =>
  5294.           PAT.Get (Pattern2);
  5295.           TIO.New_Line;
  5296.           TIO.Put (Spacer);
  5297.           PAT.Put (Pattern2);
  5298.  
  5299.            when Get_Template1 =>
  5300.           SE.Bind (S_Expr_Result, PAT.Get_Template (Pattern1));
  5301.           TIO.New_Line;
  5302.           TIO.Put (Spacer);
  5303.           SE.Put (S_Expr_Result);
  5304.  
  5305.            when Get_Template2 =>
  5306.           SE.Bind (S_Expr_Result, PAT.Get_Template (Pattern2));
  5307.           TIO.New_Line;
  5308.           TIO.Put (Spacer);
  5309.           SE.Put (S_Expr_Result);
  5310.  
  5311.            when Set_Bindings1 =>
  5312.           SE.Get (S_Expr_Result);
  5313.           PAT.Bind (Pattern1,
  5314.                 PAT.Set_Bindings (Pattern1, S_Expr_Result));
  5315.           TIO.New_Line;
  5316.           TIO.Put (Spacer);
  5317.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern1));
  5318.           SE.Put (S_Expr_Result);
  5319.  
  5320.            when Set_Bindings2 =>
  5321.           SE.Get (S_Expr_Result);
  5322.           PAT.Bind (Pattern2,
  5323.                 PAT.Set_Bindings (Pattern2, S_Expr_Result));
  5324.           TIO.New_Line;
  5325.           TIO.Put (Spacer);
  5326.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern2));
  5327.           SE.Put (S_Expr_Result);
  5328.  
  5329.            when Get_Bindings1 =>
  5330.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern1));
  5331.           TIO.New_Line;
  5332.           TIO.Put (Spacer);
  5333.           SE.Put (S_Expr_Result);
  5334.  
  5335.            when Get_Bindings2 =>
  5336.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern2));
  5337.           TIO.New_Line;
  5338.           TIO.Put (Spacer);
  5339.           SE.Put (S_Expr_Result);
  5340.  
  5341.            when Instantiate1 =>
  5342.           SE.Bind (S_Expr_Result, PAT.Instantiate (Pattern1));
  5343.           TIO.New_Line;
  5344.           TIO.Put (Spacer);
  5345.           SE.Put (S_Expr_Result);
  5346.  
  5347.            when Instantiate2 =>
  5348.           SE.Bind (S_Expr_Result, PAT.Instantiate (Pattern2));
  5349.           TIO.New_Line;
  5350.           TIO.Put (Spacer);
  5351.           SE.Put (S_Expr_Result);
  5352.  
  5353.            when First1 =>
  5354.           PAT.Bind (Pattern_Result, PAT.First (Pattern1));
  5355.           TIO.New_Line;
  5356.           TIO.Put (Spacer);
  5357.           PAT.Put (Pattern_Result);
  5358.  
  5359.            when First2 =>
  5360.           PAT.Bind (Pattern_Result, PAT.First (Pattern2));
  5361.           TIO.New_Line;
  5362.           TIO.Put (Spacer);
  5363.           PAT.Put (Pattern_Result);
  5364.  
  5365.            when Rest1 =>
  5366.           PAT.Bind (Pattern_Result, PAT.Rest (Pattern1));
  5367.           TIO.New_Line;
  5368.           TIO.Put (Spacer);
  5369.           PAT.Put (Pattern_Result);
  5370.           
  5371.            when Rest2 =>
  5372.           PAT.Bind (Pattern_Result, PAT.Rest (Pattern2));
  5373.           TIO.New_Line;
  5374.           TIO.Put (Spacer);
  5375.           PAT.Put (Pattern_Result);
  5376.           
  5377.            when Match =>
  5378.           SE.Bind (S_Expr_Result, PAT.Get_Template (Pattern1));
  5379.           TIO.New_Line;
  5380.           TIO.Put (Spacer);
  5381.           TIO.Put ("Initial Template of Pattern1: ");
  5382.           SE.Put (S_Expr_Result);
  5383.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern1));
  5384.           TIO.New_Line;
  5385.           TIO.Put (Spacer);
  5386.           TIO.Put ("Initial Bindings of Pattern1: ");
  5387.           SE.Put (S_Expr_Result);
  5388.           SE.Bind (S_Expr_Result, PAT.Get_Template (Pattern2));
  5389.           TIO.New_Line;
  5390.           TIO.Put (Spacer);
  5391.           TIO.Put ("Initial Template of Pattern2: ");
  5392.           SE.Put (S_Expr_Result);
  5393.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern2));
  5394.           TIO.New_Line;
  5395.           TIO.Put (Spacer);
  5396.           TIO.Put ("Initial Bindings of Pattern2: ");
  5397.           SE.Put (S_Expr_Result);
  5398.           PAT.Match (Pattern1, Pattern2, Boolean_Result);
  5399.           TIO.New_Line;
  5400.           TIO.Put (Spacer);
  5401.           TIO.Put ("Result of Match: ");
  5402.           BIO.Put (Boolean_Result);
  5403.           SE.Bind (S_Expr_Result, PAT.Get_Template (Pattern1));
  5404.           TIO.New_Line;
  5405.           TIO.Put (Spacer);
  5406.           TIO.Put ("Final Template of Pattern1: ");
  5407.           SE.Put (S_Expr_Result);
  5408.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern1));
  5409.           TIO.New_Line;
  5410.           TIO.Put (Spacer);
  5411.           TIO.Put ("Final Bindings of Pattern1: ");
  5412.           SE.Put (S_Expr_Result);
  5413.           SE.Bind (S_Expr_Result, PAT.Get_Template (Pattern2));
  5414.           TIO.New_Line;
  5415.           TIO.Put (Spacer);
  5416.           TIO.Put ("Final Template of Pattern2: ");
  5417.           SE.Put (S_Expr_Result);
  5418.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern2));
  5419.           TIO.New_Line;
  5420.           TIO.Put (Spacer);
  5421.           TIO.Put ("Final Bindings of Pattern2: ");
  5422.           SE.Put (S_Expr_Result);
  5423.           SE.Bind (S_Expr_Result, PAT.Instantiate (Pattern1));
  5424.           TIO.New_Line;
  5425.           TIO.Put (Spacer);
  5426.           TIO.Put ("Instantiation of Pattern1: ");
  5427.           SE.Put (S_Expr_Result);
  5428.           SE.Bind (S_Expr_Result, PAT.Instantiate (Pattern2));
  5429.           TIO.New_Line;
  5430.           TIO.Put (Spacer);
  5431.           TIO.Put ("Instantiation of Pattern2: ");
  5432.           SE.Put (S_Expr_Result);
  5433.  
  5434.            when Tag_Variables1 =>
  5435.           ITIO.Get (Tag_Value);
  5436.           PAT.Tag_Variables (Pattern1, Tag_Value);
  5437.           SE.Bind (S_Expr_Result, PAT.Get_Template (Pattern1));
  5438.           TIO.New_Line;
  5439.           TIO.Put (Spacer);
  5440.           TIO.Put ("Template of Pattern1: ");
  5441.           SE.Put (S_Expr_Result);
  5442.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern1));
  5443.           TIO.New_Line;
  5444.           TIO.Put (Spacer);
  5445.           TIO.Put ("Bindings of Pattern1: ");
  5446.           SE.Put (S_Expr_Result);
  5447.  
  5448.            when Tag_Variables2 =>
  5449.           ITIO.Get (Tag_Value);
  5450.           PAT.Tag_Variables (Pattern2, Tag_Value);
  5451.           SE.Bind (S_Expr_Result, PAT.Get_Template (Pattern2));
  5452.           TIO.New_Line;
  5453.           TIO.Put (Spacer);
  5454.           TIO.Put ("Template of Pattern2: ");
  5455.           SE.Put (S_Expr_Result);
  5456.           SE.Bind (S_Expr_Result, PAT.Get_Bindings (Pattern2));
  5457.           TIO.New_Line;
  5458.           TIO.Put (Spacer);
  5459.           TIO.Put ("Bindings of Pattern2: ");
  5460.           SE.Put (S_Expr_Result);
  5461.  
  5462.            when Free1 =>
  5463.           PAT.Free (Pattern1);
  5464.           TIO.New_Line;
  5465.           TIO.Put (Spacer);
  5466.           PAT.Put (Pattern1);
  5467.  
  5468.            when Free2 =>
  5469.           PAT.Free (Pattern2);
  5470.           TIO.New_Line;
  5471.           TIO.Put (Spacer);
  5472.           PAT.Put (Pattern2);
  5473.  
  5474.            when Help =>
  5475.           TIO.New_Line;
  5476.           TIO.New_Line;
  5477.           TIO.Put_Line (" Available Operations:");
  5478.           TIO.New_Line;
  5479.           TIO.Put_Line ("    Create_Pattern1  Free2          Help          Is_Null2  Set_Bindings1");
  5480.           TIO.Put_Line ("    Create_Pattern2  Get_Bindings1  Instantiate1  Match     Set_Bindings2");
  5481.           TIO.Put_Line ("    First1           Get_Bindings2  Instantiate2  Quit      Tag_Variables1");
  5482.           TIO.Put_Line ("    First2           Get_Template1  Is_Equal      Rest1     Tag_Variables2");
  5483.           TIO.Put_Line ("    Free1            Get_Template2  Is_Null1      Rest2");
  5484.           TIO.New_Line;
  5485.           TIO.Put_Line (" For more specific information, see the User's Manual.");
  5486.  
  5487.            when Quit =>
  5488.           TIO.Skip_Line;
  5489.           TIO.Put_Line (" Exiting Pattern Demonstration.");
  5490.           return;
  5491.  
  5492.            when Others =>
  5493.           TIO.New_Line;
  5494.           TIO.Put (Spacer);
  5495.           TIO.Put ("Not accessible.");
  5496.         end case;
  5497.  
  5498.  
  5499.         exception
  5500.            when TIO.Data_Error =>
  5501.           TIO.Put (Spacer);
  5502.           TIO.Put ("Incorrect function name, try again.");
  5503.            when PAT.Atomic_Template =>
  5504.           TIO.Put (Spacer);
  5505.           TIO.Put ("Input must be non-atomic, try again.");
  5506.            when SE.Improper_Input =>
  5507.           TIO.Put (Spacer);
  5508.           TIO.Put ("Input error, try again.");
  5509.            when SE.Atomic_Expression =>
  5510.           TIO.Put (Spacer);
  5511.           TIO.Put ("Input must be non-atomic, try again.");
  5512.            when SE.Non_Atomic_Expression =>
  5513.           TIO.Put (Spacer);
  5514.           TIO.Put ("Input must be atomic, try again.");
  5515.            when SE.Invalid_Position =>
  5516.           TIO.Put (Spacer);
  5517.           TIO.Put ("No value at that position, try again.");
  5518.            when SE.Missing_Separator =>
  5519.           TIO.Put (Spacer);
  5520.           TIO.Put ("Input is missing a separator, try again.");
  5521.            when SE.Extra_Separator =>
  5522.           TIO.Put (Spacer);
  5523.           TIO.Put ("Input has an extra separator, try again.");
  5524.            when SE.Invalid_Repetitions =>
  5525.           TIO.Put (Spacer);
  5526.           TIO.Put ("Invalid number of repetitions, try again.");
  5527.      end;
  5528.  
  5529.      TIO.Skip_Line;
  5530.      SE.Free (S_Expr_Result);
  5531.       end loop;
  5532.  
  5533.    end Patdemo;
  5534.  
  5535.    procedure Ruledemo is 
  5536.  
  5537.       type Functions is (Is_Null1, Is_Null2, Is_Equal, Create_Rule1,
  5538.              Create_Rule2, Get_Template1, Get_Template2,
  5539.              Set_Bindings1, Set_Bindings2, Get_Bindings1,
  5540.              Get_Bindings2, Instantiate1, Instantiate2,
  5541.              Antecedent1, Antecedent2, Consequent1, Consequent2,
  5542.              Match, Is_Fact1, Is_Fact2, Is_Query1, Is_Query2,
  5543.              Is_Rule1, Is_Rule2, Tag_Variables1, Tag_Variables2,
  5544.              Free1, Free2, Help, Quit);
  5545.  
  5546.       package FIO is new Text_Io.Enumeration_Io(Functions);
  5547.  
  5548.       Function_Name : Functions;
  5549.       S_Expr_Result : SE.S_Expr;
  5550.       Pattern_Result : PAT.Pattern;
  5551.       Rule1, Rule2 : RUL.Rule;
  5552.       Prompt : constant String := " -> ";
  5553.       Spacer : constant String := "    ";
  5554.       Boolean_Result : Boolean;
  5555.       Tag_Value : Natural;
  5556.   
  5557.    begin
  5558.       TIO.New_Line;
  5559.       TIO.Put_line(" Entering the Rule Demonstration.");
  5560.       TIO.Put_line(" To terminate this demonstration, enter ""quit"" at any time.");
  5561.       TIO.Put_line(" For a list of available operations, enter ""help"".");
  5562.       TIO.New_Line;
  5563.  
  5564.       RUL.Bind (Rule1, RUL.Null_Rule);
  5565.       RUL.Bind (Rule1, RUL.Null_Rule);
  5566.       PAT.Bind (Pattern_Result, PAT.Null_Pattern);
  5567.       SE.Bind (S_Expr_Result, SE.Null_S_Expr);
  5568.  
  5569.       loop
  5570.      TIO.New_Line;
  5571.      TIO.Put (Prompt);
  5572.  
  5573.      begin
  5574.         FIO.Get (Function_Name);
  5575.  
  5576.         case Function_Name is
  5577.  
  5578.            when Is_Null1 =>
  5579.           Boolean_Result := RUL.Is_Null (Rule1);
  5580.           TIO.New_Line;
  5581.           TIO.Put (Spacer);
  5582.           BIO.Put (Boolean_Result);
  5583.  
  5584.            when Is_Null2 =>
  5585.           Boolean_Result := RUL.Is_Null (Rule2);
  5586.           TIO.New_Line;
  5587.           TIO.Put (Spacer);
  5588.           BIO.Put (Boolean_Result);
  5589.  
  5590.            when Is_Fact1 =>
  5591.           Boolean_Result := RUL.Is_Fact (Rule1);
  5592.           TIO.New_Line;
  5593.           TIO.Put (Spacer);
  5594.           BIO.Put (Boolean_Result);
  5595.  
  5596.            when Is_Fact2 =>
  5597.           Boolean_Result := RUL.Is_Fact (Rule2);
  5598.           TIO.New_Line;
  5599.           TIO.Put (Spacer);
  5600.           BIO.Put (Boolean_Result);
  5601.  
  5602.            when Is_Query1 =>
  5603.           Boolean_Result := RUL.Is_Query (Rule1);
  5604.           TIO.New_Line;
  5605.           TIO.Put (Spacer);
  5606.           BIO.Put (Boolean_Result);
  5607.  
  5608.            when Is_Query2 =>
  5609.           Boolean_Result := RUL.Is_Query (Rule2);
  5610.           TIO.New_Line;
  5611.           TIO.Put (Spacer);
  5612.           BIO.Put (Boolean_Result);
  5613.  
  5614.            when Is_Rule1 =>
  5615.           Boolean_Result := RUL.Is_Rule (Rule1);
  5616.           TIO.New_Line;
  5617.           TIO.Put (Spacer);
  5618.           BIO.Put (Boolean_Result);
  5619.  
  5620.            when Is_Rule2 =>
  5621.           Boolean_Result := RUL.Is_Rule (Rule2);
  5622.           TIO.New_Line;
  5623.           TIO.Put (Spacer);
  5624.           BIO.Put (Boolean_Result);
  5625.  
  5626.            when Is_Equal =>
  5627.           Boolean_Result := RUL.Is_Equal (Rule1, Rule2);
  5628.           TIO.New_Line;
  5629.           TIO.Put (Spacer);
  5630.           BIO.Put (Boolean_Result);
  5631.  
  5632.            when Create_Rule1 =>
  5633.           RUL.Get (Rule1);
  5634.           TIO.New_Line;
  5635.           TIO.Put (Spacer);
  5636.           RUL.Put (Rule1);
  5637.  
  5638.            when Create_Rule2 =>
  5639.           RUL.Get (Rule2);
  5640.           TIO.New_Line;
  5641.           TIO.Put (Spacer);
  5642.           RUL.Put (Rule2);
  5643.  
  5644.            when Get_Template1 =>
  5645.           SE.Bind (S_Expr_Result, RUL.Get_Template (Rule1));
  5646.           TIO.New_Line;
  5647.           TIO.Put (Spacer);
  5648.           SE.Put (S_Expr_Result);
  5649.  
  5650.            when Get_Template2 =>
  5651.           SE.Bind (S_Expr_Result, RUL.Get_Template (Rule2));
  5652.           TIO.New_Line;
  5653.           TIO.Put (Spacer);
  5654.           SE.Put (S_Expr_Result);
  5655.  
  5656.            when Set_Bindings1 =>
  5657.           SE.Get (S_Expr_Result);
  5658.           RUL.Bind (Rule1,
  5659.                 RUL.Set_Bindings (Rule1, S_Expr_Result));
  5660.           TIO.New_Line;
  5661.           TIO.Put (Spacer);
  5662.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule1));
  5663.           SE.Put (S_Expr_Result);
  5664.  
  5665.            when Set_Bindings2 =>
  5666.           SE.Get (S_Expr_Result);
  5667.           RUL.Bind (Rule2,
  5668.                 RUL.Set_Bindings (Rule2, S_Expr_Result));
  5669.           TIO.New_Line;
  5670.           TIO.Put (Spacer);
  5671.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule2));
  5672.           SE.Put (S_Expr_Result);
  5673.  
  5674.            when Get_Bindings1 =>
  5675.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule1));
  5676.           TIO.New_Line;
  5677.           TIO.Put (Spacer);
  5678.           SE.Put (S_Expr_Result);
  5679.  
  5680.            when Get_Bindings2 =>
  5681.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule2));
  5682.           TIO.New_Line;
  5683.           TIO.Put (Spacer);
  5684.           SE.Put (S_Expr_Result);
  5685.  
  5686.            when Instantiate1 =>
  5687.           SE.Bind (S_Expr_Result, RUL.Instantiate (Rule1));
  5688.           TIO.New_Line;
  5689.           TIO.Put (Spacer);
  5690.           SE.Put (S_Expr_Result);
  5691.  
  5692.            when Instantiate2 =>
  5693.           SE.Bind (S_Expr_Result, RUL.Instantiate (Rule2));
  5694.           TIO.New_Line;
  5695.           TIO.Put (Spacer);
  5696.           SE.Put (S_Expr_Result);
  5697.           
  5698.            when Antecedent1 =>
  5699.           PAT.Bind (Pattern_Result, RUL.Antecedent (Rule1));
  5700.           TIO.New_Line;
  5701.           TIO.Put (Spacer);
  5702.           PAT.Put (Pattern_Result);
  5703.  
  5704.            when Antecedent2 =>
  5705.           PAT.Bind (Pattern_Result, RUL.Antecedent (Rule2));
  5706.           TIO.New_Line;
  5707.           TIO.Put (Spacer);
  5708.           PAT.Put (Pattern_Result);
  5709.  
  5710.            when Consequent1 =>
  5711.           PAT.Bind (Pattern_Result, RUL.Consequent (Rule1));
  5712.           TIO.New_Line;
  5713.           TIO.Put (Spacer);
  5714.           PAT.Put (Pattern_Result);
  5715.  
  5716.            when Consequent2 =>
  5717.           PAT.Bind (Pattern_Result, RUL.Consequent (Rule2));
  5718.           TIO.New_Line;
  5719.           TIO.Put (Spacer);
  5720.           PAT.Put (Pattern_Result);
  5721.  
  5722.            when Match =>
  5723.           SE.Bind (S_Expr_Result, RUL.Get_Template (Rule1));
  5724.           TIO.New_Line;
  5725.           TIO.Put (Spacer);
  5726.           TIO.Put ("Initial Template of Rule1: ");
  5727.           SE.Put (S_Expr_Result);
  5728.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule1));
  5729.           TIO.New_Line;
  5730.           TIO.Put (Spacer);
  5731.           TIO.Put ("Initial Bindings of Rule1: ");
  5732.           SE.Put (S_Expr_Result);
  5733.           SE.Bind (S_Expr_Result, RUL.Get_Template (Rule2));
  5734.           TIO.New_Line;
  5735.           TIO.Put (Spacer);
  5736.           TIO.Put ("Initial Template of Rule2: ");
  5737.           SE.Put (S_Expr_Result);
  5738.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule2));
  5739.           TIO.New_Line;
  5740.           TIO.Put (Spacer);
  5741.           TIO.Put ("Initial Bindings of Rule2: ");
  5742.           SE.Put (S_Expr_Result);
  5743.           RUL.Match (Rule1, Rule2, Boolean_Result);
  5744.           TIO.New_Line;
  5745.           TIO.Put (Spacer);
  5746.           TIO.Put ("Result of Match: ");
  5747.           BIO.Put (Boolean_Result);
  5748.           SE.Bind (S_Expr_Result, RUL.Get_Template (Rule1));
  5749.           TIO.New_Line;
  5750.           TIO.Put (Spacer);
  5751.           TIO.Put ("Final Template of Rule1: ");
  5752.           SE.Put (S_Expr_Result);
  5753.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule1));
  5754.           TIO.New_Line;
  5755.           TIO.Put (Spacer);
  5756.           TIO.Put ("Final Bindings of Rule1: ");
  5757.           SE.Put (S_Expr_Result);
  5758.           SE.Bind (S_Expr_Result, RUL.Get_Template (Rule2));
  5759.           TIO.New_Line;
  5760.           TIO.Put (Spacer);
  5761.           TIO.Put ("Final Template of Rule2: ");
  5762.           SE.Put (S_Expr_Result);
  5763.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule2));
  5764.           TIO.New_Line;
  5765.           TIO.Put (Spacer);
  5766.           TIO.Put ("Final Bindings of Rule2: ");
  5767.           SE.Put (S_Expr_Result);
  5768.           SE.Bind (S_Expr_Result, RUL.Instantiate (Rule1));
  5769.           TIO.New_Line;
  5770.           TIO.Put (Spacer);
  5771.           TIO.Put ("Instantiation of Rule1: ");
  5772.           SE.Put (S_Expr_Result);
  5773.           SE.Bind (S_Expr_Result, RUL.Instantiate (Rule2));
  5774.           TIO.New_Line;
  5775.           TIO.Put (Spacer);
  5776.           TIO.Put ("Instantiation of Rule2: ");
  5777.           SE.Put (S_Expr_Result);
  5778.  
  5779.            when Tag_Variables1 =>
  5780.           ITIO.Get (Tag_Value);
  5781.           RUL.Tag_Variables (Rule1, Tag_Value);
  5782.           SE.Bind (S_Expr_Result, RUL.Get_Template (Rule1));
  5783.           TIO.New_Line;
  5784.           TIO.Put (Spacer);
  5785.           TIO.Put ("Template of Rule1: ");
  5786.           SE.Put (S_Expr_Result);
  5787.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule1));
  5788.           TIO.New_Line;
  5789.           TIO.Put (Spacer);
  5790.           TIO.Put ("Bindings of Rule1: ");
  5791.           SE.Put (S_Expr_Result);
  5792.  
  5793.            when Tag_Variables2 =>
  5794.           ITIO.Get (Tag_Value);
  5795.           RUL.Tag_Variables (Rule2, Tag_Value);
  5796.           SE.Bind (S_Expr_Result, RUL.Get_Template (Rule2));
  5797.           TIO.New_Line;
  5798.           TIO.Put (Spacer);
  5799.           TIO.Put ("Template of Rule2: ");
  5800.           SE.Put (S_Expr_Result);
  5801.           SE.Bind (S_Expr_Result, RUL.Get_Bindings (Rule2));
  5802.           TIO.New_Line;
  5803.           TIO.Put (Spacer);
  5804.           TIO.Put ("Bindings of Rule2: ");
  5805.           SE.Put (S_Expr_Result);
  5806.  
  5807.            when Free1 =>
  5808.           RUL.Free (Rule1);
  5809.           TIO.New_Line;
  5810.           TIO.Put (Spacer);
  5811.           RUL.Put (Rule1);
  5812.  
  5813.            when Free2 =>
  5814.           RUL.Free (Rule2);
  5815.           TIO.New_Line;
  5816.           TIO.Put (Spacer);
  5817.           RUL.Put (Rule2);
  5818.  
  5819.            when Help =>
  5820.           TIO.New_Line;
  5821.           TIO.New_Line;
  5822.           TIO.Put_Line (" Available Operations:");
  5823.           TIO.New_Line;
  5824.           TIO.Put_Line ("    Antecedent1   Free1          Help          Is_Null1   Match");
  5825.           TIO.Put_Line ("    Antecedent2   Free2          Instantiate1  Is_Null2   Quit");
  5826.           TIO.Put_Line ("    Consequent1   Get_Bindings1  Instantiate2  Is_Query1  Set_Bindings1");
  5827.           TIO.Put_Line ("    Consequent2   Get_Bindings2  Is_Equal      Is_Query2  Set_Bindings2");
  5828.           TIO.Put_Line ("    Create_Rule1  Get_Template1  Is_Fact1      Is_Rule1   Tag_Variables1");
  5829.           TIO.Put_Line ("    Create_Rule2  Get_Template2  Is_Fact2      Is_Rule2   Tag_Variables2");
  5830.           TIO.New_Line;
  5831.           TIO.Put_Line (" For more specific information, see the User's Manual.");
  5832.  
  5833.            when Quit =>
  5834.           TIO.Skip_Line;
  5835.           TIO.Put_Line (" Exiting Rule Demonstration.");
  5836.           return;
  5837.  
  5838.            when Others =>
  5839.           TIO.New_Line;
  5840.           TIO.Put (Spacer);
  5841.           TIO.Put ("Not accessible.");
  5842.         end case;
  5843.  
  5844.  
  5845.         exception
  5846.            when TIO.Data_Error =>
  5847.           TIO.Put (Spacer);
  5848.           TIO.Put ("Incorrect function name, try again.");
  5849.            when RUL.Invalid_Rule_Format =>
  5850.           TIO.Put (Spacer);
  5851.           TIO.Put ("Improper rule format, try again.");
  5852.            when RUL.Atomic_Template =>
  5853.           TIO.Put (Spacer);
  5854.           TIO.Put ("Input must be non-atomic, try again.");
  5855.            when SE.Improper_Input =>
  5856.           TIO.Put (Spacer);
  5857.           TIO.Put ("Input error, try again.");
  5858.            when SE.Atomic_Expression =>
  5859.           TIO.Put (Spacer);
  5860.           TIO.Put ("Input must be non-atomic, try again.");
  5861.            when SE.Non_Atomic_Expression =>
  5862.           TIO.Put (Spacer);
  5863.           TIO.Put ("Input must be atomic, try again.");
  5864.            when SE.Invalid_Position =>
  5865.           TIO.Put (Spacer);
  5866.           TIO.Put ("No value at that position, try again.");
  5867.            when SE.Missing_Separator =>
  5868.           TIO.Put (Spacer);
  5869.           TIO.Put ("Input is missing a separator, try again.");
  5870.            when SE.Extra_Separator =>
  5871.           TIO.Put (Spacer);
  5872.           TIO.Put ("Input has an extra separator, try again.");
  5873.  
  5874. --   The following exception handler is commented out because it appears
  5875. --   that DEC Ada allows a maximum of only nine exception handlers per frame.
  5876. --
  5877. --           when SE.Invalid_Repetitions =>
  5878. --          TIO.Put (Spacer);
  5879. --          TIO.Put ("Invalid number of repetitions, try again.");
  5880.      end;
  5881.  
  5882.      TIO.Skip_Line;
  5883.      SE.Free (S_Expr_Result);
  5884.      PAT.Free (Pattern_Result);
  5885.       end loop;
  5886.  
  5887.    end Ruledemo;
  5888.  
  5889.    procedure Rbdemo is 
  5890.       use Inst_Facilities;  -- Use clause needed because values of an
  5891.                 -- enumerated type (Literal_Kind) declared
  5892.                 -- outside of a compilation unit are not
  5893.                 -- being recognized.  Is this standard behavior?
  5894.  
  5895.       type Functions is (Create_Rulebase1, Create_Rulebase2,
  5896.              Assert1, Assert2, Retract1, Retract2,
  5897.              Get_Template1, Get_Template2, Free1, Free2,
  5898.              Is_Null1, Is_Null2, Retrieve1, Retrieve2, Help,
  5899.              Is_Equal, Rb_And, Rb_Or, Rb_Differ, Rb_Xor, Quit);
  5900.  
  5901.       package FIO is new TIO.Enumeration_Io (Functions);
  5902.  
  5903.       type Rb_Index is (loves, friends, wife, husband, father, mother, parent);
  5904.  
  5905.       Invalid_Index : exception;
  5906.  
  5907.       function Rb_Key (Rule_Arg : in RUL.Rule) return Rb_Index is
  5908.      Literal_Val : Inst_Facilities.Atomic_Literal;
  5909.       begin
  5910.      Literal_Val := SE.Return_Atomic_Literal (
  5911.                SE.First (
  5912.                   PAT.Instantiate (RUL.Consequent (Rule_Arg))));
  5913.      case Literal_Val.Kind is
  5914.         when Int => raise Invalid_Index;
  5915.         when Length1  => return Rb_Index'Value (Literal_Val.Length1);
  5916.         when Length2  => return Rb_Index'Value (Literal_Val.Length2);
  5917.         when Length3  => return Rb_Index'Value (Literal_Val.Length3);
  5918.         when Length4  => return Rb_Index'Value (Literal_Val.Length4);
  5919.         when Length5  => return Rb_Index'Value (Literal_Val.Length5);
  5920.         when Length6  => return Rb_Index'Value (Literal_Val.Length6);
  5921.         when Length7  => return Rb_Index'Value (Literal_Val.Length7);
  5922.         when Length8  => return Rb_Index'Value (Literal_Val.Length8);
  5923.         when Length9  => return Rb_Index'Value (Literal_Val.Length9);
  5924.         when Length10 => return Rb_Index'Value (Literal_Val.Length10);
  5925.         when Length11 => return Rb_Index'Value (Literal_Val.Length11);
  5926.         when Length12 => return Rb_Index'Value (Literal_Val.Length12);
  5927.         when Length13 => return Rb_Index'Value (Literal_Val.Length13);
  5928.         when Length14 => return Rb_Index'Value (Literal_Val.Length14);
  5929.         when Length15 => return Rb_Index'Value (Literal_Val.Length15);
  5930.      end case;
  5931.  
  5932.      exception
  5933.         when Constraint_Error => raise Invalid_Index;
  5934.       end Rb_Key;
  5935.  
  5936.       package RB is new Inst_Facilities.AI_Types.Rulebases (Rb_Index, Rb_Key);
  5937.  
  5938.       procedure Print (Print_Arg : in SE.S_Expr) is
  5939.      S_Expr_Arg : SE.S_Expr;
  5940.       begin
  5941.      SE.Bind (S_Expr_Arg, Print_Arg);
  5942.      TIO.Put ("(");
  5943.      while not SE.Is_Null (S_Expr_Arg) loop
  5944.         SE.Put (SE.First (S_Expr_Arg));
  5945.         SE.Bind (S_Expr_Arg, SE.Rest (S_Expr_Arg));
  5946.         if not SE.Is_Null (S_Expr_Arg) then
  5947.            TIO.New_Line;
  5948.            TIO.Put ("     ");
  5949.         end if;
  5950.      end loop;
  5951.      TIO.Put (")");
  5952.       end Print;
  5953.    begin
  5954.       declare
  5955.      Function_Name : Functions;
  5956.      S_Expr_Result : SE.S_Expr;
  5957.      Rule_Arg : RUL.Rule;
  5958.      Rulebase1, Rulebase2, Rulebase_Result : RB.Rulebase;
  5959.      Prompt : constant String := " -> ";
  5960.      Spacer : constant String := "    ";
  5961.      Boolean_Result : Boolean;
  5962.       begin 
  5963.      TIO.New_Line;
  5964.      TIO.Put_line(" Entering the Rulebase Demonstration.");
  5965.      TIO.Put_line(" To terminate this demonstration, enter ""quit"" at any time.");
  5966.      TIO.Put_line(" For a list of available operations, enter ""help"".");
  5967.      TIO.New_Line;
  5968.  
  5969.      RB.Bind (Rulebase1, RB.Null_Rulebase);
  5970.      SE.Bind (S_Expr_Result, SE.Null_S_Expr);
  5971.      RUL.Bind (Rule_Arg, RUL.Null_Rule);
  5972.  
  5973.      loop
  5974.         TIO.New_Line;
  5975.         TIO.Put (Prompt);
  5976.  
  5977.         begin
  5978.            FIO.Get (Function_Name);
  5979.  
  5980.            case Function_Name is
  5981.  
  5982.           when Create_Rulebase1 =>
  5983.              RB.Get (Rulebase1);
  5984.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase1));
  5985.              TIO.New_Line;
  5986.              TIO.Put (Spacer);
  5987.              Print (S_Expr_Result);
  5988.  
  5989.           when Create_Rulebase2 =>
  5990.              RB.Get (Rulebase2);
  5991.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase2));
  5992.              TIO.New_Line;
  5993.              TIO.Put (Spacer);
  5994.              Print (S_Expr_Result);
  5995.  
  5996.           when Assert1 =>
  5997.              RUL.Get (Rule_Arg);
  5998.              RB.Assert (Rule_Arg, Rulebase1);
  5999.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase1));
  6000.              TIO.New_Line;
  6001.              TIO.Put (Spacer);
  6002.              Print (S_Expr_Result);
  6003.  
  6004.           when Assert2 =>
  6005.              RUL.Get (Rule_Arg);
  6006.              RB.Assert (Rule_Arg, Rulebase2);
  6007.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase2));
  6008.              TIO.New_Line;
  6009.              TIO.Put (Spacer);
  6010.              Print (S_Expr_Result);
  6011.  
  6012.           when Retract1 =>
  6013.              RUL.Get (Rule_Arg);
  6014.              RB.Retract (Rule_Arg, Rulebase1);
  6015.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase1));
  6016.              TIO.New_Line;
  6017.              TIO.Put (Spacer);
  6018.              Print (S_Expr_Result);
  6019.  
  6020.           when Retract2 =>
  6021.              RUL.Get (Rule_Arg);
  6022.              RB.Retract (Rule_Arg, Rulebase2);
  6023.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase2));
  6024.              TIO.New_Line;
  6025.              TIO.Put (Spacer);
  6026.              Print (S_Expr_Result);
  6027.  
  6028.           when Get_Template1 =>
  6029.              TIO.New_Line;
  6030.              TIO.Put (Spacer);
  6031.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase1));
  6032.              Print (S_Expr_Result);
  6033.  
  6034.           when Get_Template2 =>
  6035.              TIO.New_Line;
  6036.              TIO.Put (Spacer);
  6037.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase2));
  6038.              Print (S_Expr_Result);
  6039.  
  6040.           when Free1 =>
  6041.              RB.Free (Rulebase1);
  6042.              TIO.New_Line;
  6043.              TIO.Put (Spacer);
  6044.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase1));
  6045.              Print (S_Expr_Result);
  6046.  
  6047.           when Free2 =>
  6048.              RB.Free (Rulebase2);
  6049.              TIO.New_Line;
  6050.              TIO.Put (Spacer);
  6051.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase2));
  6052.              Print (S_Expr_Result);
  6053.  
  6054.           when Is_Null1 =>
  6055.              Boolean_Result := RB.Is_Null (Rulebase1);
  6056.              TIO.New_Line;
  6057.              TIO.Put (Spacer);
  6058.              BIO.Put (Boolean_Result);
  6059.  
  6060.           when Is_Null2 =>
  6061.              Boolean_Result := RB.Is_Null (Rulebase2);
  6062.              TIO.New_Line;
  6063.              TIO.Put (Spacer);
  6064.              BIO.Put (Boolean_Result);
  6065.  
  6066.           when Retrieve1 =>
  6067.              RUL.Get (Rule_Arg);
  6068.              RUL.Tag_Variables (Rule_Arg, 42);
  6069.              SE.Bind (S_Expr_Result, RB.Retrieve (Rule_Arg, Rulebase1));
  6070.              TIO.New_Line;
  6071.              TIO.Put (Spacer);
  6072.              Print (S_Expr_Result);
  6073.  
  6074.           when Retrieve2 =>
  6075.              RUL.Get (Rule_Arg);
  6076.              RUL.Tag_Variables (Rule_Arg, 42);
  6077.              SE.Bind (S_Expr_Result, RB.Retrieve (Rule_Arg, Rulebase2));
  6078.              TIO.New_Line;
  6079.              TIO.Put (Spacer);
  6080.              Print (S_Expr_Result);
  6081.  
  6082.           when Is_Equal =>
  6083.              Boolean_Result := RB.Is_Equal (Rulebase1, Rulebase2);
  6084.              TIO.New_Line;
  6085.              TIO.Put (Spacer);
  6086.              BIO.Put (Boolean_Result);
  6087.  
  6088.           when Rb_And =>
  6089.              RB.Bind (Rulebase_Result, RB."And" (Rulebase1, Rulebase2));
  6090.              TIO.New_Line;
  6091.              TIO.Put (Spacer);
  6092.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase_Result));
  6093.              Print (S_Expr_Result);
  6094.  
  6095.           when Rb_Or =>
  6096.              RB.Bind (Rulebase_Result, RB."Or" (Rulebase1, Rulebase2));
  6097.              TIO.New_Line;
  6098.              TIO.Put (Spacer);
  6099.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase_Result));
  6100.              Print (S_Expr_Result);
  6101.  
  6102.           when Rb_Differ =>
  6103.              RB.Bind (Rulebase_Result, RB."-" (Rulebase1, Rulebase2));
  6104.              TIO.New_Line;
  6105.              TIO.Put (Spacer);
  6106.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase_Result));
  6107.              Print (S_Expr_Result);
  6108.  
  6109.           when Rb_Xor =>
  6110.              RB.Bind (Rulebase_Result, RB."Xor" (Rulebase1, Rulebase2));
  6111.              TIO.New_Line;
  6112.              TIO.Put (Spacer);
  6113.              SE.Bind (S_Expr_Result, RB.Get_Template (Rulebase_Result));
  6114.              Print (S_Expr_Result);
  6115.  
  6116.           when Help =>
  6117.              TIO.New_Line;
  6118.              TIO.New_Line;
  6119.              TIO.Put_Line (" Available Operations:");
  6120.              TIO.New_Line;
  6121.              TIO.Put_Line ("    Assert1            Get_Template1   Quit       Retract2");
  6122.              TIO.Put_Line ("    Assert2            Get_Template2   Rb_And     Retrieve1");
  6123.              TIO.Put_Line ("    Create_Rulebase1   Help            Rb_Differ  Retrieve2");
  6124.              TIO.Put_Line ("    Create_Rulebase2   Is_Equal        Rb_Or");
  6125.              TIO.Put_Line ("    Free1              Is_Null1        Rb_Xor");
  6126.              TIO.Put_Line ("    Free2              Is_Null2        Retract1");
  6127.              TIO.New_Line;
  6128.              TIO.Put_Line (" For more specific information, see the User's Manual.");
  6129.  
  6130.           when Quit =>
  6131.              TIO.Skip_Line;
  6132.              TIO.Put_Line (" Exiting Rulebase Demonstration.");
  6133.              return;
  6134.  
  6135.           when Others =>
  6136.              TIO.New_Line;
  6137.              TIO.Put (Spacer);
  6138.              TIO.Put ("Not accessible.");
  6139.            end case;
  6140.  
  6141.  
  6142.            exception
  6143.           when TIO.Data_Error =>
  6144.              TIO.Put (Spacer);
  6145.              TIO.Put ("Incorrect function name, try again.");
  6146.           when RUL.Atomic_Template =>
  6147.              TIO.Put (Spacer);
  6148.              TIO.Put ("Input must be non-atomic, try again.");
  6149.           when RUL.Invalid_Rule_Format =>
  6150.              TIO.Put (Spacer);
  6151.              TIO.Put ("Improper rule format, try again.");
  6152.           when Invalid_Index =>
  6153.              TIO.Put (Spacer);
  6154.              TIO.Put ("Improper relation, try again.");
  6155.           when SE.Improper_Input =>
  6156.              TIO.Put (Spacer);
  6157.              TIO.Put ("Input error, try again.");
  6158.           when SE.Atomic_Expression =>
  6159.              TIO.Put (Spacer);
  6160.              TIO.Put ("Input must be non-atomic, try again.");
  6161.           when SE.Non_Atomic_Expression =>
  6162.              TIO.Put (Spacer);
  6163.              TIO.Put ("Input must be atomic, try again.");
  6164.           when SE.Missing_Separator =>
  6165.              TIO.Put (Spacer);
  6166.              TIO.Put ("Input is missing a separator, try again.");
  6167.           when SE.Extra_Separator =>
  6168.              TIO.Put (Spacer);
  6169.              TIO.Put ("Input has an extra separator, try again.");
  6170.  
  6171. --   The following exception handlers are commented out because it appears
  6172. --   that DEC Ada allows a maximum of only nine exception handlers per frame.
  6173. --
  6174. --          when SE.Invalid_Position =>
  6175. --             TIO.Put (Spacer);
  6176. --             TIO.Put ("No value at that position, try again.");
  6177. --          when SE.Invalid_Repetitions =>
  6178. --             TIO.Put (Spacer);
  6179. --             TIO.Put ("Invalid number of repetitions, try again.");
  6180.  
  6181.         end;
  6182.  
  6183.         TIO.Skip_Line;
  6184.         SE.Free (S_Expr_Result);
  6185.         RUL.Free (Rule_Arg);
  6186.         RB.Free (Rulebase_Result);
  6187.      end loop;
  6188.       end;
  6189.    end Rbdemo;
  6190.  
  6191. begin
  6192.    TIO.New_Line;
  6193.    TIO.Put_Line (" Welcome to the AI Data Types Demonstration.");
  6194.    TIO.Put_Line (" To terminate this demonstration, enter ""quit"" at any time.");
  6195.    TIO.New_Line;
  6196.  
  6197.    loop
  6198.       loop
  6199.      begin
  6200.         TIO.Put_Line (" Choose number of desired demonstration: ");
  6201.         TIO.New_Line;
  6202.         TIO.Put_Line ("    1. Symbolic_Expression");
  6203.         TIO.Put_Line ("    2. Pattern");
  6204.         TIO.Put_Line ("    3. Rule");
  6205.         TIO.Put_Line ("    4. Rulebase");
  6206.         TIO.New_Line;
  6207.         TIO.Put (" >> ");
  6208.         TIO.Get_Line (Response, Stringlength);
  6209.         if Stringlength = 0 then
  6210.            TIO.New_Line;
  6211.         elsif Response (1 .. Stringlength) = "quit" then
  6212.            TIO.New_Line;
  6213.            TIO.Put_Line (" Exiting AI Data Types Demonstration.");
  6214.            return;
  6215.         else
  6216.            case Integer'Value (Response (1 .. Stringlength)) is
  6217.           when 1 =>
  6218.              TIO.New_Line;
  6219.              Sexprdemo;
  6220.              TIO.New_Line;
  6221.              exit;
  6222.           when 2 =>
  6223.              TIO.New_Line;
  6224.              Patdemo;
  6225.              TIO.New_Line;
  6226.              exit;
  6227.           when 3 =>
  6228.              TIO.New_Line;
  6229.              Ruledemo;
  6230.              TIO.New_Line;
  6231.              exit;
  6232.           when 4 =>
  6233.              TIO.New_Line;
  6234.              Rbdemo;
  6235.              TIO.New_Line;
  6236.              exit;
  6237.           when others =>
  6238.              TIO.New_Line;
  6239.              TIO.Put_Line (" Demonstration number must be 1, 2, 3 or 4, try again.");
  6240.              TIO.New_Line;
  6241.            end case;
  6242.         end if;
  6243.  
  6244.         exception
  6245.            when Constraint_Error =>
  6246.           TIO.New_Line;
  6247.           TIO.Put_Line (" Demonstration number must be 1, 2, 3 or 4, try again.");
  6248.               TIO.New_Line;
  6249.          end;
  6250.       end loop;
  6251.  
  6252.       loop
  6253.      TIO.New_Line;
  6254.      TIO.Put_Line (" Would you like to try another demonstration? (y/n)");
  6255.      TIO.Put (" >> ");
  6256.      TIO.Get_Line (Response, Stringlength);
  6257.      if Stringlength = 0 then
  6258.         TIO.New_Line;
  6259.      elsif Response (1 .. Stringlength) = "y" then
  6260.         TIO.New_Line;
  6261.         TIO.New_Line;
  6262.         exit;
  6263.      elsif Response (1 .. Stringlength) = "n" then
  6264.         TIO.New_Line;
  6265.         TIO.Put_Line (" Exiting AI Data Types Demonstration.");
  6266.         return;
  6267.      elsif Response (1 .. Stringlength) = "quit" then
  6268.         TIO.New_Line;
  6269.         TIO.Put_Line (" Exiting AI Data Types Demonstration.");
  6270.         return;
  6271.      else
  6272.         TIO.New_Line;
  6273.         TIO.Put_Line (" Response must be ""y"" or ""n"", try again.");
  6274.      end if;
  6275.       end loop;
  6276.    end loop;
  6277.  
  6278. end AITypesdemo;
  6279.