home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ppcsmalleiffel / lib_se / e_when.e < prev    next >
Encoding:
Text File  |  1998-01-16  |  10.4 KB  |  496 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  4. --                       http://www.loria.fr/SmallEiffel
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it 
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later 
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License 
  11. -- for  more  details.  You  should  have  received a copy of the GNU General 
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class E_WHEN
  17.    --
  18.    -- To store a when clause of an inspect instruction.
  19.    --
  20.    
  21. inherit GLOBALS;
  22.    
  23. creation {EIFFEL_PARSER}
  24.    make
  25.    
  26. creation {E_WHEN,WHEN_LIST}
  27.    from_e_when
  28.    
  29. feature 
  30.    
  31.    start_position: POSITION;
  32.      -- Of the first character of keyword "when".
  33.  
  34. feature {E_WHEN}
  35.    
  36.    list: ARRAY[WHEN_ITEM];
  37.       
  38. feature 
  39.    
  40.    header_comment: COMMENT;
  41.      -- Of the when clause.
  42.    
  43.    compound: COMPOUND;
  44.      -- Of the when clause if any.
  45.    
  46.    when_list: WHEN_LIST;
  47.      -- Corresponding one when checked.
  48.  
  49.    values: ARRAY[BOOLEAN];
  50.      -- True when the corresponding index is in the when.
  51.  
  52. feature {NONE}
  53.  
  54.    points1: FIXED_ARRAY[INTEGER] is
  55.      -- To reach the `compound'.
  56.       once
  57.      !!Result.with_capacity(12);
  58.       end;
  59.  
  60.    point2: INTEGER;
  61.      -- To go outside the E_INSPECT.
  62.    
  63. feature {EIFFEL_PARSER}
  64.    
  65.    make(sp: like start_position; hc: like header_comment) is
  66.       require
  67.      sp /= Void
  68.       do
  69.      start_position := sp;
  70.      header_comment := hc;
  71.       ensure      
  72.      start_position = sp;
  73.       end;
  74.    
  75. feature {WHEN_LIST}
  76.    
  77.    afd_check is
  78.       do
  79.      if compound /= Void then
  80.         compound.afd_check;
  81.      end;
  82.       end;
  83.  
  84. feature {NONE}
  85.    
  86.    from_e_when(other: like Current) is
  87.       local
  88.      i: INTEGER;
  89.      when_item: WHEN_ITEM;
  90.       do
  91.      start_position := other.start_position;
  92.      list := other.list.twin;
  93.      from  
  94.         i := list.lower;
  95.      until
  96.         i > list.upper
  97.      loop
  98.         when_item := list.item(i).twin;
  99.         when_item.clear_e_when;
  100.         list.put(when_item,i);
  101.         i := i + 1;
  102.      end;
  103.      header_comment := other.header_comment;
  104.      compound := other.compound; 
  105.       end;
  106.    
  107. feature 
  108.    
  109.    use_current: BOOLEAN is
  110.       do
  111.      if compound /= Void then
  112.         Result := compound.use_current;
  113.      end;
  114.       end;
  115.    
  116.    current_type: TYPE is
  117.       require
  118.      when_list /= Void
  119.       do
  120.      Result := when_list.current_type;
  121.       end;
  122.    
  123.    e_inspect: E_INSPECT is
  124.       do
  125.      Result := when_list.e_inspect;
  126.       end;
  127.    
  128. feature {WHEN_LIST}
  129.    
  130.    compile_to_jvm(else_position: POSITION; remainder: INTEGER) is
  131.      -- Where `remainder' is the number of E_WHEN after Current.
  132.       local
  133.      point3, point4, bi, bs: INTEGER;
  134.      must_test: BOOLEAN;
  135.      ca: like code_attribute;
  136.       do
  137.      ca := code_attribute;
  138.      if remainder > 0 then
  139.         must_test := true;
  140.      elseif run_control.no_check then
  141.         must_test := true;
  142.      else -- boost :
  143.         must_test := else_position /= Void;
  144.      end;
  145.      points1.clear;
  146.      if must_test then
  147.         from  
  148.            bi := values.lower;
  149.         until
  150.            bi > values.upper
  151.         loop
  152.            from  
  153.           bs := bi + 1;
  154.            until
  155.           bs > values.upper or else not values.item(bs)
  156.            loop
  157.           bs := bs + 1;
  158.            end;
  159.            bs := bs - 1;
  160.            -- 
  161.            if bi = bs then
  162.           ca.opcode_dup;
  163.           ca.opcode_push_integer(bi);
  164.           points1.add_last(ca.opcode_if_icmpeq);
  165.            else
  166.           ca.opcode_dup;
  167.           ca.opcode_push_integer(bi);
  168.           point3 := ca.opcode_if_icmplt;
  169.           ca.opcode_dup;
  170.           ca.opcode_push_integer(bs);
  171.           points1.add_last(ca.opcode_if_icmple);
  172.           ca.resolve_u2_branch(point3);
  173.            end;
  174.            from  
  175.           bi := bs + 1;
  176.            until
  177.           bi > values.upper or else values.item(bi)
  178.            loop
  179.           bi := bi + 1;
  180.            end;
  181.         end;
  182.         point4 := ca.opcode_goto;
  183.      end;
  184.      ca.resolve_with(points1);
  185.      if compound /= Void then
  186.         compound.compile_to_jvm;
  187.      end;
  188.      point2 := ca.opcode_goto;
  189.      if must_test then
  190.         ca.resolve_u2_branch(point4);
  191.      end;
  192.       end;
  193.  
  194.    compile_to_jvm_resolve_branch is
  195.       do
  196.      code_attribute.resolve_u2_branch(point2);
  197.       end;
  198.  
  199.    compile_to_c is
  200.       local
  201.      bi, bs: INTEGER;
  202.       do
  203.      cpp.put_string("%Nif(");
  204.      from  
  205.         bi := values.lower;
  206.      until
  207.         bi > values.upper
  208.      loop
  209.         from  
  210.            bs := bi + 1;
  211.         until
  212.            bs > values.upper or else not values.item(bs)
  213.         loop
  214.            bs := bs + 1;
  215.         end;
  216.         bs := bs - 1;
  217.         -- 
  218.         cpp.put_character('(');
  219.         if bi = bs then
  220.            cpp.put_integer(bi);
  221.            cpp.put_string("==");
  222.            cpp.put_inspect;
  223.         else
  224.            cpp.put_character('(');
  225.            cpp.put_integer(bi);
  226.            cpp.put_string("<=");
  227.            cpp.put_inspect;
  228.            cpp.put_string(")&&(");
  229.            cpp.put_inspect;
  230.            cpp.put_string("<=");
  231.            cpp.put_integer(bs);
  232.            cpp.put_character(')');
  233.         end;
  234.         cpp.put_character(')');
  235.         -- 
  236.         from  
  237.            bi := bs + 1;
  238.         until
  239.            bi > values.upper or else values.item(bi)
  240.         loop
  241.            bi := bi + 1;
  242.         end;
  243.         if bi <= values.upper then
  244.            cpp.put_string("||");
  245.         end;
  246.      end;
  247.      cpp.put_string("){%N");
  248.      if compound /= Void then
  249.         compound.compile_to_c;
  250.      end;
  251.      cpp.put_string(fz_12);
  252.       end;
  253.    
  254.    pretty_print is
  255.       local
  256.      i: INTEGER;
  257.       do
  258.      fmt.keyword(fz_when);
  259.      fmt.level_incr;
  260.      if header_comment /= Void then
  261.         header_comment.pretty_print;
  262.      end;
  263.      if list /= Void then
  264.         from  
  265.            i := list.lower;
  266.         until
  267.            i > list.upper
  268.         loop
  269.            list.item(i).pretty_print;
  270.            i := i + 1;
  271.            if i <= list.upper then
  272.           fmt.put_character(',');
  273.            end;
  274.         end;
  275.      end;
  276.      fmt.level_decr;
  277.      fmt.keyword(fz_then);
  278.      fmt.level_incr;
  279.      if compound /= Void then
  280.         compound.pretty_print;
  281.      end;
  282.      fmt.level_decr;
  283.       end;
  284.    
  285.    includes_integer(v: INTEGER): BOOLEAN is
  286.       do
  287.      Result := ((values /= Void) and then 
  288.             values.valid_index(v) and then
  289.             values.item(v));
  290.       end;
  291.    
  292. feature {WHEN_LIST,E_WHEN}
  293.    
  294.    to_runnable_integer(wl: like when_list): like Current is
  295.       require
  296.      wl /= Void;
  297.       local
  298.      ne, i: INTEGER;
  299.      when_item: WHEN_ITEM;
  300.       do
  301.      if when_list = Void then
  302.         ne := nb_errors;
  303.         when_list := wl;
  304.         if list = Void then
  305.            eh.add_position(e_inspect.start_position);
  306.            error(start_position,em2);
  307.         else
  308.            from  
  309.           i := list.lower;
  310.            until
  311.           i > list.upper or else nb_errors - ne > 0
  312.            loop
  313.           when_item := list.item(i).to_runnable_integer(Current);
  314.           if when_item = Void then
  315.              error(start_position,em1);
  316.           else
  317.              list.put(when_item,i);
  318.           end;
  319.           i := i + 1;
  320.            end;
  321.         end;
  322.         if compound /= Void then
  323.            compound := compound.to_runnable(current_type);
  324.            if compound = Void then
  325.           error(start_position,em1);
  326.            end;
  327.         end;
  328.         Result := Current;
  329.      else
  330.         !!Result.from_e_when(Current);
  331.         Result := Result.to_runnable_integer(wl);
  332.      end;
  333.       ensure
  334.      Result.when_list = wl
  335.       end;
  336.    
  337.    to_runnable_character(wl: like when_list): like Current is
  338.       require
  339.      wl /= Void;
  340.       local
  341.      ne, i: INTEGER;
  342.      when_item: WHEN_ITEM;
  343.       do
  344.      if when_list = Void then
  345.         ne := nb_errors;
  346.         when_list := wl;
  347.         if list = Void then
  348.            eh.add_position(e_inspect.start_position);
  349.            error(start_position,em2);
  350.         else
  351.            from  
  352.           i := list.lower;
  353.            until
  354.           i > list.upper or else nb_errors - ne > 0
  355.            loop
  356.           when_item := list.item(i).to_runnable_character(Current);
  357.           if when_item = Void then
  358.              error(start_position,em1);
  359.           else
  360.              list.put(when_item,i);
  361.           end;
  362.           i := i + 1;
  363.            end;
  364.         end;
  365.         if compound /= Void then
  366.            compound := compound.to_runnable(current_type);
  367.            if compound = Void then
  368.           error(start_position,em1);
  369.            end;
  370.         end;
  371.         Result := Current;
  372.      else
  373.         !!Result.from_e_when(Current);
  374.         Result := Result.to_runnable_character(wl);
  375.      end;
  376.       ensure
  377.      Result.when_list = wl
  378.       end;
  379.    
  380. feature {WHEN_ITEM_1}
  381.    
  382.    add_when_item_1(wi1: WHEN_ITEM_1) is
  383.       require
  384.      wi1 /= Void
  385.       local
  386.      v: INTEGER;
  387.       do
  388.      v := wi1.expression_value;
  389.      if e_inspect.includes(v) then
  390.         err_occ(v,wi1.start_position);
  391.      elseif values = Void then
  392.         !!values.make(v,v);
  393.         values.put(true,v);
  394.      else
  395.         values.force(true,v);
  396.      end;
  397.       ensure
  398.      e_inspect.includes(wi1.expression_value);
  399.       end;
  400.    
  401. feature {WHEN_ITEM_2}
  402.    
  403.    add_when_item_2(wi2: WHEN_ITEM_2) is
  404.       require
  405.      wi2 /= Void
  406.       local
  407.      l, u, i: INTEGER;
  408.       do
  409.      l := wi2.lower_value;
  410.      u := wi2.upper_value;
  411.      if l >= u then
  412.         error(wi2.start_position,"Not a good slice.");
  413.      end;
  414.      if nb_errors = 0 then
  415.         from  
  416.            i := l;
  417.         until
  418.            i > u
  419.         loop
  420.            if e_inspect.includes(i) then
  421.           err_occ(i,wi2.start_position);
  422.           i := u + 1;
  423.            else
  424.           i := i + 1;
  425.            end;
  426.         end;
  427.      end;
  428.      if nb_errors = 0 then
  429.         if values = Void then
  430.            !!values.make(l,u);
  431.            values.set_all_with(true);
  432.         else
  433.            values.force(true,l);
  434.            values.force(true,u);
  435.            values.set_slice_with(true,l,u);
  436.         end;
  437.      end;
  438.       end;
  439.    
  440. feature {EIFFEL_PARSER}
  441.    
  442.    add_value(v: EXPRESSION) is
  443.       require
  444.      v /= Void;
  445.       local
  446.      element: WHEN_ITEM_1
  447.       do      
  448.      !!element.make(v);
  449.      if list = Void then
  450.         list := <<element>>;
  451.      else
  452.         list.add_last(element);
  453.      end;
  454.       end;
  455.  
  456.    add_slice(min, max: EXPRESSION) is
  457.       require
  458.      min /= Void;
  459.      max /= Void;
  460.       local
  461.      element: WHEN_ITEM_2;
  462.       do
  463.      !!element.make(min,max);
  464.      if list = Void then
  465.         list := <<element>>;
  466.      else
  467.         list.add_last(element);
  468.      end;
  469.       end;
  470.  
  471.    set_compound(c: like compound) is
  472.       do
  473.      compound := c;
  474.       ensure
  475.      compound = c
  476.       end;
  477.  
  478. feature {NONE}
  479.    
  480.    err_occ(v: INTEGER; p: POSITION) is
  481.       do
  482.      eh.add_position(e_inspect.start_position);
  483.      eh.append("Second occurrence for this value (");
  484.      eh.append(v.to_string);
  485.      error(p,") in the same inspect."); 
  486.       end;
  487.    
  488. feature {NONE}
  489.    
  490.    em1: STRING is "Bad when clause.";
  491.    em2: STRING is "Empty when clause in inspect.";
  492.  
  493. end -- E_WHEN
  494.  
  495.  
  496.