home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / FUZZY.ZIP / EXECUTE.B < prev    next >
Text File  |  1986-11-30  |  16KB  |  399 lines

  1. -------------------------------------------------------------------------------
  2. --                                                                           --
  3. --  Separate Unit:  Execute -- Execute operators for Prover                  --
  4. --                                                                           --
  5. --  Author:  Bradley L. Richards                                             --
  6. --                                                                           --
  7. --     Version     Date     Notes . . .                                      --
  8. --    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    --
  9. --       1.0    - - - - -   Never existed.  First version implemented after  --
  10. --                            Parser et al reached version 2.0               --
  11. --       2.0    20 Jun 86   Initial Version                                  --
  12. --       2.05   13 Jul 86   Split into separate spec and package files       --
  13. --       2.1    21 Jul 86   Demonstration version -- initial predicates      --
  14. --                            implemented; initial debugging completed       --
  15. --       2.2    28 Jul 86   Initial operational version -- 20 predicates     --
  16. --                            implemented, plus lots of squashed bugs        --
  17. --       2.3    19 Aug 86   Use AVL trees for rule_base, add many reserved   --
  18. --                            predicates, and split output routines into     --
  19. --                            package print_stuff.                           --
  20. --       2.4    31 Aug 86   Split do_reserved into separate file             --
  21. --       2.5     1 Sep 86   Split execute into separate file                 --
  22. --    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    --
  23. --                                                                           --
  24. --  Description:  This file contains the routine Execute.  Given an AST      --
  25. --       operator node which has its operands defined, this routine will     --
  26. --       execute that operator (and any operators beneath it) and alter      --
  27. --       the AST to reflect the result.                                      --
  28. --                                                                           --
  29. --       It is possible that an error will creep in and the operands will    --
  30. --       not be of the appropriate types.  In this case notify the user of   --
  31. --       the error.  If thorough type-checking were included in the parser   --
  32. --       then the only way this error could arise would be through variable  --
  33. --       bindings.                                                           --
  34. --                                                                           --
  35. -------------------------------------------------------------------------------
  36.  
  37. separate(prover)
  38. procedure execute( operator : in out AST_ptr; bindings : in out binding_list;
  39.            level : natural; failed : in out boolean  ) is
  40.     temp : AST_ptr := null;
  41.     is_int_1, is_int_2, use_threshold : boolean := false;
  42.     matched, unified : boolean;
  43.     int_result, trash : integer;
  44.     fp_1, fp_2, fp_result : float;
  45.     fuzzy_1, fuzzy_2, fuzzy_result : fuzzy_values;
  46.     left_value, right_value : argument_ptr;
  47.     temp_bindings : binding_list;
  48.  
  49.   
  50.   procedure binary_arithmetic is
  51.     begin
  52.       --
  53.       --  Execute a binary arithmetic operator
  54.       --
  55.       lookup(operator.left_operand,level,bindings,left_value,trash);
  56.       lookup(operator.right_operand,level,bindings,right_value,trash);
  57.       if (left_value.is_a = integer_num) and
  58.          (right_value.is_a = integer_num) then
  59.         if operator.binary_op = asterisk then
  60.       int_result := left_value.int_num * right_value.int_num;
  61.         elsif operator.binary_op = minus then
  62.       int_result := left_value.int_num - right_value.int_num;
  63.         elsif operator.binary_op = rw_mod then
  64.       int_result := left_value.int_num mod right_value.int_num;
  65.         elsif operator.binary_op = plus then
  66.       int_result := left_value.int_num + right_value.int_num;
  67.         else -- operator.binary_op = slash
  68.       int_result := left_value.int_num / right_value.int_num;
  69.         end if;
  70.         temp := new AST'(integer_num,int_result);
  71.       else
  72.         if left_value.is_a = integer_num then
  73.       fp_1 := float(left_value.int_num);
  74.         elsif left_value.is_a = float_num then
  75.       fp_1 := left_value.fp_num;
  76.         else
  77.       error(no_pointer,"invalid type to arithmetic operator");
  78.       failed := true;
  79.         end if;
  80.         if right_value.is_a = integer_num then
  81.       fp_2 := float(right_value.int_num);
  82.         elsif right_value.is_a = float_num then
  83.       fp_2 := right_value.fp_num;
  84.         else
  85.       error(no_pointer,"invalid type to arithmetic operator");
  86.       failed := true;
  87.         end if;
  88.         if not failed then
  89.           if operator.binary_op = asterisk then
  90.         fp_result := fp_1 * fp_2;
  91.           elsif operator.binary_op = minus then
  92.         fp_result := fp_1 - fp_2;
  93.           elsif operator.binary_op = rw_mod then
  94.         error(no_pointer,"'mod' only valid for integer arguments");
  95.         failed := true;
  96.           elsif operator.binary_op = plus then
  97.         fp_result := fp_1 + fp_2;
  98.           else -- operator.binary_op = slash
  99.         fp_result := fp_1 / fp_2;
  100.           end if;
  101.       if not failed then
  102.             temp := new AST'(float_num,fp_result);
  103.       end if;
  104.         end if;
  105.       end if;
  106.     end binary_arithmetic;
  107.  
  108.  
  109.   procedure binary_logic is
  110.     begin
  111.       --
  112.       --  Execute logic operator
  113.       --
  114.       if operator.left_operand.node_type = fuzzy_value then
  115.         fuzzy_1 := operator.left_operand.fuzzy_num;
  116.       elsif operator.left_operand.node_type = threshold_marker then
  117.         fuzzy_1 := operator.left_operand.fuzzy_value;
  118.         threshold := operator.left_operand.threshold;
  119.         use_threshold := true;
  120.       else
  121.         failed := true;
  122.     put("Error -- fuzzy operator "); put(operator.binary_op);
  123.     put(" given invalid operand of type ");
  124.     put(operator.left_operand.node_type); new_line;
  125.       end if;
  126.       if operator.right_operand.node_type = fuzzy_value then
  127.         fuzzy_2 := operator.right_operand.fuzzy_num;
  128.       elsif operator.right_operand.node_type = threshold_marker then
  129.         fuzzy_2 := operator.right_operand.fuzzy_value;
  130.         threshold := operator.right_operand.threshold;
  131.         use_threshold := true;
  132.       else
  133.         failed := true;
  134.     put("fuzzy operator "); put(operator.binary_op);
  135.     put(" given invalid operand of type ");
  136.     put(operator.right_operand.node_type); new_line;
  137.       end if;
  138.       if failed then
  139.     fuzzy_result := 0.0;
  140.       else
  141.         if operator.binary_op = bar then
  142.           fp_result := fuzzy_1 + fuzzy_2 - (fuzzy_1 * fuzzy_2);
  143.           --
  144.           --  Occasionally borderline inaccuracies in floating point
  145.           --  arithmetic cause a result greater than one, which in turn
  146.           --  causes a constraint error.
  147.           --
  148.           if fp_result > 1.0 then
  149.         fuzzy_result := 1.0;
  150.           else
  151.         fuzzy_result := fp_result;
  152.           end if;
  153.         elsif operator.binary_op = comma then
  154.           if fuzzy_1 < fuzzy_2 then
  155.         fuzzy_result := fuzzy_1;
  156.           else
  157.         fuzzy_result := fuzzy_2;
  158.           end if;
  159.         elsif operator.binary_op = hat then
  160.           fuzzy_result := fuzzy_1 * fuzzy_2;
  161.         else -- operator.binary_op = semicolon
  162.           if fuzzy_1 > fuzzy_2 then
  163.         fuzzy_result := fuzzy_1;
  164.           else
  165.         fuzzy_result := fuzzy_2;
  166.           end if;
  167.         end if;
  168.       end if;
  169.       if use_threshold then
  170.         temp := new AST'(threshold_marker, fuzzy_result, threshold);
  171.       else
  172.         temp := new AST'(fuzzy_value, fuzzy_result);
  173.       end if;
  174.       current_truth := fuzzy_result;
  175.     end binary_logic;
  176.  
  177.  
  178.   procedure binding_comparator is
  179.     begin
  180.       --
  181.       --  Execute a comparator
  182.       --
  183.       temp_bindings := bindings;
  184.       unify_arg(operator.left_operand, operator.right_operand, level,
  185.               level, temp_bindings, unified);
  186.       if (unified xor (operator.binary_op /= not_equal)) then
  187.         temp := new AST'(fuzzy_value, 0.0);
  188.         current_truth := 0.0;
  189.     failed := true;
  190.       else
  191.         temp := new AST'(fuzzy_value, 1.0);
  192.         current_truth := 1.0;
  193.       end if;
  194.       if not (operator.binary_op = not_equal) then -- save the bindings
  195.         bindings := temp_bindings;
  196.       end if;
  197.     end binding_comparator;
  198.  
  199.  
  200.   procedure comparator is
  201.     begin
  202.       --
  203.       --  Execute a comparator
  204.       --
  205.       lookup(operator.left_operand,level,bindings,left_value,trash);
  206.       lookup(operator.right_operand,level,bindings,right_value,trash);
  207.       if (left_value.is_a = right_value.is_a) or
  208.          ((left_value.is_a = integer_num) and (right_value.is_a = float_num)) or
  209.          ((left_value.is_a = float_num) and (right_value.is_a = integer_num)) then
  210.         -- possible to compare the two
  211.         case left_value.is_a is
  212.       when predicate =>
  213.         if (operator.binary_op = equality) or
  214.            (operator.binary_op = not_equality) then
  215.           matched := left_value.name.name = right_value.name.name;
  216.         elsif operator.binary_op = less_than then
  217.           matched := left_value.name.name < right_value.name.name;
  218.         elsif operator.binary_op = greater_than then
  219.           matched := left_value.name.name > right_value.name.name;
  220.         elsif operator.binary_op = less_or_equal then
  221.           matched := left_value.name.name <= right_value.name.name;
  222.         else -- operator.binary_op = greater_or_equal then
  223.           matched := left_value.name.name >= right_value.name.name;
  224.         end if;
  225.       when variable =>
  226.         if (operator.binary_op = equality) or
  227.            (operator.binary_op = not_equality) then
  228.           matched := (left_value.v_name.name = right_value.v_name.name);
  229.         else
  230.           error(no_pointer,"uninstantiated variable to <, =<, >, or >=");
  231.         failed := true;
  232.         end if;
  233.       when integer_num | float_num =>
  234.         if left_value.is_a = integer_num then
  235.           fp_1 := float(left_value.int_num);
  236.         else
  237.           fp_1 := left_value.fp_num;
  238.         end if;
  239.         if right_value.is_a = integer_num then
  240.           fp_2 := float(right_value.int_num);
  241.         else
  242.           fp_2 := right_value.fp_num;
  243.         end if;
  244.         if (operator.binary_op = equality) or
  245.            (operator.binary_op = not_equality) then
  246.           matched := fp_1 = fp_2;
  247.         elsif operator.binary_op = less_than then
  248.           matched := fp_1 < fp_2;
  249.         elsif operator.binary_op = greater_than then
  250.           matched := fp_1 > fp_2;
  251.         elsif operator.binary_op = less_or_equal then
  252.           matched := fp_1 <= fp_2;
  253.         else -- operator.binary_op = greater_or_equal then
  254.           matched := fp_1 >= fp_2;
  255.         end if;
  256.       when character_lit =>
  257.         if (operator.binary_op = equality) or
  258.            (operator.binary_op = not_equality) then
  259.           matched := left_value.char = right_value.char;
  260.         elsif operator.binary_op = less_than then
  261.           matched := left_value.char < right_value.char;
  262.         elsif operator.binary_op = greater_than then
  263.           matched := left_value.char > right_value.char;
  264.         elsif operator.binary_op = less_or_equal then
  265.           matched := left_value.char <= right_value.char;
  266.         else -- operator.binary_op = greater_or_equal then
  267.           matched := left_value.char >= right_value.char;
  268.         end if;
  269.       when others =>
  270.       put("Error -- comparator "); put(operator.node_type);
  271.       put(" received invalid operand of type ");
  272.       put(left_value.is_a); new_line;
  273.         failed := true;
  274.       end case;
  275.       else
  276.     matched := false;
  277.     if (left_value.is_a = variable) or (right_value.is_a = variable) then
  278.       if (operator.binary_op /= equality) and
  279.          (operator.binary_op /= not_equality) then
  280.         error(no_pointer, "uninstantiated variable to <, =<, >, or >=");
  281.         failed := true;
  282.       -- else
  283.         -- no error since == and \== can have uninstantiated variables
  284.       end if;
  285.     else
  286.       if (operator.binary_op /= equality) and
  287.          (operator.binary_op /= not_equality) then
  288.         error(no_pointer, "cannot compare different node types");
  289.         failed := true;
  290.       -- else
  291.         -- no error since == and \== can compare different node types
  292.       end if;
  293.     end if;
  294.       end if;
  295.       if operator.binary_op = not_equality then
  296.         matched := not matched;
  297.       end if;
  298.       if matched and (not failed) then
  299.         temp := new AST'(fuzzy_value, 1.0);
  300.         current_truth := 1.0;
  301.       else
  302.         temp := new AST'(fuzzy_value, 0.0);
  303.         current_truth := 0.0;
  304.     failed := true;
  305.       end if;
  306.     end comparator;
  307.  
  308.  
  309.   procedure unary_logic is
  310.     begin
  311.       --
  312.       --  Execute a unary logic operator.  Turns out "not" is the only one
  313.       --
  314.       if operator.operand.node_type = fuzzy_value then
  315.     fuzzy_1 := operator.operand.fuzzy_num;
  316.       elsif operator.operand.node_type = threshold_marker then
  317.     fuzzy_1 := operator.operand.fuzzy_value;
  318.     use_threshold := true;
  319.       else
  320.     put("fuzzy operator "); put(operator.unary_op);
  321.     put(" given invalid operand of type ");
  322.     put(operator.operand.node_type); new_line;
  323.         failed := true;
  324.       end if;
  325.       if failed then
  326.     fuzzy_result := 0.0;
  327.       else
  328.         fuzzy_result := 1.0 - fuzzy_1;
  329.       end if;
  330.       if use_threshold then
  331.     temp := new AST'(threshold_marker, fuzzy_result, threshold);
  332.       else
  333.         temp := new AST'(fuzzy_value, fuzzy_result);
  334.       end if;
  335.       current_truth := fuzzy_result;
  336.     end unary_logic;
  337.  
  338.  
  339.   begin -- execute
  340.     case operator.node_type is
  341.       when binary_operator =>
  342.     --
  343.     --  If the operands are themselves operators, execute them
  344.     --
  345.     if (operator.left_operand.node_type = binary_operator) or
  346.        (operator.left_operand.node_type = binary_operator) then
  347.       execute(operator.left_operand, bindings, level, failed);
  348.     end if;
  349.     if (operator.right_operand.node_type = binary_operator) or
  350.        (operator.right_operand.node_type = binary_operator) then
  351.       execute(operator.right_operand, bindings, level, failed);
  352.     end if;
  353.     --
  354.     --  If successful so far, execute this operator
  355.     --
  356.     if not failed then
  357.       case operator.binary_op is
  358.         when asterisk | minus | rw_mod | plus | slash => binary_arithmetic;
  359.         when equal | rw_is | not_equal => binding_comparator;
  360.         when equality | not_equality | less_than | greater_than |
  361.              less_or_equal | greater_or_equal => comparator;
  362.         when bar | comma | hat | semicolon => binary_logic;
  363.         when others =>
  364.           error(no_pointer, "binary operator not implemented");
  365.           failed := true;
  366.         end case;
  367.     end if;
  368.  
  369.       when unary_operator =>
  370.     --
  371.     --  If the operands are themselves operators, execute them
  372.     --
  373.     if (operator.operand.node_type = binary_operator) or
  374.        (operator.operand.node_type = binary_operator) then
  375.       execute(operator.operand, bindings, level, failed);
  376.     end if;
  377.     --
  378.     --  If successful so far, execute this operator
  379.     --
  380.     if not failed then
  381.       case operator.unary_op is
  382.         when rw_not => unary_logic;
  383.         when others =>
  384.           warning(no_pointer, "unary operator not implemented");
  385.           failed := true;
  386.         end case;
  387.     end if;
  388.  
  389.       when others =>
  390.     error(no_pointer, "invalid operator node to 'execute'");
  391.     failed := true;
  392.       end case;
  393.     --
  394.     --  Now release everything from this operator on down
  395.     --
  396.     release(operator, null);
  397.     operator := temp;
  398.   end execute;
  399.