home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_se / e_when.e < prev    next >
Text File  |  1999-06-05  |  13KB  |  493 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://SmallEiffel.loria.fr
  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.    e_inspect: E_INSPECT is
  117.       do
  118.          Result := when_list.e_inspect;
  119.       end;
  120.  
  121. feature {WHEN_LIST}
  122.  
  123.    compile_to_jvm(else_position: POSITION; remainder: INTEGER) is
  124.          -- Where `remainder' is the number of E_WHEN after Current.
  125.       local
  126.          point3, point4, bi, bs: INTEGER;
  127.          must_test: BOOLEAN;
  128.          ca: like code_attribute;
  129.       do
  130.          ca := code_attribute;
  131.          if remainder > 0 then
  132.             must_test := true;
  133.          elseif run_control.no_check then
  134.             must_test := true;
  135.          else -- boost :
  136.             must_test := else_position /= Void;
  137.          end;
  138.          points1.clear;
  139.          if must_test then
  140.             from
  141.                bi := values.lower;
  142.             until
  143.                bi > values.upper
  144.             loop
  145.                from
  146.                   bs := bi + 1;
  147.                until
  148.                   bs > values.upper or else not values.item(bs)
  149.                loop
  150.                   bs := bs + 1;
  151.                end;
  152.                bs := bs - 1;
  153.                --
  154.                if bi = bs then
  155.                   ca.opcode_dup;
  156.                   ca.opcode_push_integer(bi);
  157.                   points1.add_last(ca.opcode_if_icmpeq);
  158.                else
  159.                   ca.opcode_dup;
  160.                   ca.opcode_push_integer(bi);
  161.                   point3 := ca.opcode_if_icmplt;
  162.                   ca.opcode_dup;
  163.                   ca.opcode_push_integer(bs);
  164.                   points1.add_last(ca.opcode_if_icmple);
  165.                   ca.resolve_u2_branch(point3);
  166.                end;
  167.                from
  168.                   bi := bs + 1;
  169.                until
  170.                   bi > values.upper or else values.item(bi)
  171.                loop
  172.                   bi := bi + 1;
  173.                end;
  174.             end;
  175.             point4 := ca.opcode_goto;
  176.          end;
  177.          ca.resolve_with(points1);
  178.          if compound /= Void then
  179.             compound.compile_to_jvm;
  180.          end;
  181.          point2 := ca.opcode_goto;
  182.          if must_test then
  183.             ca.resolve_u2_branch(point4);
  184.          end;
  185.       end;
  186.  
  187.    compile_to_jvm_resolve_branch is
  188.       do
  189.          code_attribute.resolve_u2_branch(point2);
  190.       end;
  191.  
  192.    compile_to_c is
  193.       local
  194.          bi, bs: INTEGER;
  195.       do
  196.          cpp.put_string("%Nif(");
  197.          from
  198.             bi := values.lower;
  199.          until
  200.             bi > values.upper
  201.          loop
  202.             from
  203.                bs := bi + 1;
  204.             until
  205.                bs > values.upper or else not values.item(bs)
  206.             loop
  207.                bs := bs + 1;
  208.             end;
  209.             bs := bs - 1;
  210.             --
  211.             cpp.put_character('(');
  212.             if bi = bs then
  213.                cpp.put_integer(bi);
  214.                cpp.put_string("==");
  215.                cpp.put_inspect;
  216.             else
  217.                cpp.put_character('(');
  218.                cpp.put_integer(bi);
  219.                cpp.put_string("<=");
  220.                cpp.put_inspect;
  221.                cpp.put_string(")&&(");
  222.                cpp.put_inspect;
  223.                cpp.put_string("<=");
  224.                cpp.put_integer(bs);
  225.                cpp.put_character(')');
  226.             end;
  227.             cpp.put_character(')');
  228.             --
  229.             from
  230.                bi := bs + 1;
  231.             until
  232.                bi > values.upper or else values.item(bi)
  233.             loop
  234.                bi := bi + 1;
  235.             end;
  236.             if bi <= values.upper then
  237.                cpp.put_string("||");
  238.             end;
  239.          end;
  240.          cpp.put_string("){%N");
  241.          if compound /= Void then
  242.             compound.compile_to_c;
  243.          end;
  244.          cpp.put_string(fz_12);
  245.       end;
  246.  
  247.    pretty_print is
  248.       local
  249.          i: INTEGER;
  250.       do
  251.          fmt.keyword(fz_when);
  252.          fmt.level_incr;
  253.          if header_comment /= Void then
  254.             header_comment.pretty_print;
  255.          end;
  256.          if list /= Void then
  257.             from
  258.                i := list.lower;
  259.             until
  260.                i > list.upper
  261.             loop
  262.                list.item(i).pretty_print;
  263.                i := i + 1;
  264.                if i <= list.upper then
  265.                   fmt.put_character(',');
  266.                end;
  267.             end;
  268.          end;
  269.          fmt.level_decr;
  270.          fmt.keyword(fz_then);
  271.          fmt.level_incr;
  272.          if compound /= Void then
  273.             compound.pretty_print;
  274.          end;
  275.          fmt.level_decr;
  276.       end;
  277.  
  278.    includes_integer(v: INTEGER): BOOLEAN is
  279.       do
  280.          Result := ((values /= Void) and then
  281.                     values.valid_index(v) and then
  282.                     values.item(v));
  283.       end;
  284.  
  285. feature {WHEN_LIST,E_WHEN}
  286.  
  287.    to_runnable_integer(wl: like when_list): like Current is
  288.       require
  289.          wl /= Void;
  290.       local
  291.          ct: TYPE;
  292.          ne, i: INTEGER;
  293.          when_item: WHEN_ITEM;
  294.       do
  295.          if when_list = Void then
  296.             ne := nb_errors;
  297.             when_list := wl;
  298.             if list = Void then
  299.                eh.add_position(e_inspect.start_position);
  300.                error(start_position,em2);
  301.             else
  302.                from
  303.                   i := list.lower;
  304.                until
  305.                   i > list.upper or else nb_errors - ne > 0
  306.                loop
  307.                   when_item := list.item(i).to_runnable_integer(Current);
  308.                   if when_item = Void then
  309.                      error(start_position,em1);
  310.                   else
  311.                      list.put(when_item,i);
  312.                   end;
  313.                   i := i + 1;
  314.                end;
  315.             end;
  316.             if compound /= Void then
  317.                ct := small_eiffel.top_rf.current_type;
  318.                compound := compound.to_runnable(ct);
  319.                if compound = Void then
  320.                   error(start_position,em1);
  321.                end;
  322.             end;
  323.             Result := Current;
  324.          else
  325.             !!Result.from_e_when(Current);
  326.             Result := Result.to_runnable_integer(wl);
  327.          end;
  328.       ensure
  329.          Result.when_list = wl
  330.       end;
  331.  
  332.    to_runnable_character(wl: like when_list): like Current is
  333.       require
  334.          wl /= Void;
  335.       local
  336.          ct: TYPE;
  337.          ne, i: INTEGER;
  338.          when_item: WHEN_ITEM;
  339.       do
  340.          if when_list = Void then
  341.             ne := nb_errors;
  342.             when_list := wl;
  343.             if list = Void then
  344.                eh.add_position(e_inspect.start_position);
  345.                error(start_position,em2);
  346.             else
  347.                from
  348.                   i := list.lower;
  349.                until
  350.                   i > list.upper or else nb_errors - ne > 0
  351.                loop
  352.                   when_item := list.item(i).to_runnable_character(Current);
  353.                   if when_item = Void then
  354.                      error(start_position,em1);
  355.                   else
  356.                      list.put(when_item,i);
  357.                   end;
  358.                   i := i + 1;
  359.                end;
  360.             end;
  361.             if compound /= Void then
  362.                ct := small_eiffel.top_rf.current_type;
  363.                compound := compound.to_runnable(ct);
  364.                if compound = Void then
  365.                   error(start_position,em1);
  366.                end;
  367.             end;
  368.             Result := Current;
  369.          else
  370.             !!Result.from_e_when(Current);
  371.             Result := Result.to_runnable_character(wl);
  372.          end;
  373.       ensure
  374.          Result.when_list = wl
  375.       end;
  376.  
  377. feature {WHEN_ITEM_1}
  378.  
  379.    add_when_item_1(wi1: WHEN_ITEM_1) is
  380.       require
  381.          wi1 /= Void
  382.       local
  383.          v: INTEGER;
  384.       do
  385.          v := wi1.expression_value;
  386.          if e_inspect.includes(v) then
  387.             err_occ(v,wi1.start_position);
  388.          elseif values = Void then
  389.             !!values.make(v,v);
  390.             values.put(true,v);
  391.          else
  392.             values.force(true,v);
  393.          end;
  394.       ensure
  395.          e_inspect.includes(wi1.expression_value);
  396.       end;
  397.  
  398. feature {WHEN_ITEM_2}
  399.  
  400.    add_when_item_2(wi2: WHEN_ITEM_2) is
  401.       require
  402.          wi2 /= Void
  403.       local
  404.          l, u, i: INTEGER;
  405.       do
  406.          l := wi2.lower_value;
  407.          u := wi2.upper_value;
  408.          if l >= u then
  409.             error(wi2.start_position,"Not a good slice.");
  410.          end;
  411.          if nb_errors = 0 then
  412.             from
  413.                i := l;
  414.             until
  415.                i > u
  416.             loop
  417.                if e_inspect.includes(i) then
  418.                   err_occ(i,wi2.start_position);
  419.                   i := u + 1;
  420.                else
  421.                   i := i + 1;
  422.                end;
  423.             end;
  424.          end;
  425.          if nb_errors = 0 then
  426.             if values = Void then
  427.                !!values.make(l,u);
  428.                values.set_all_with(true);
  429.             else
  430.                values.force(true,l);
  431.                values.force(true,u);
  432.                values.set_slice_with(true,l,u);
  433.             end;
  434.          end;
  435.       end;
  436.  
  437. feature {EIFFEL_PARSER}
  438.  
  439.    add_value(v: EXPRESSION) is
  440.       require
  441.          v /= Void;
  442.       local
  443.          element: WHEN_ITEM
  444.       do
  445.          !WHEN_ITEM_1!element.make(v);
  446.          if list = Void then
  447.             list := <<element>>;
  448.          else
  449.             list.add_last(element);
  450.          end;
  451.       end;
  452.  
  453.    add_slice(min, max: EXPRESSION) is
  454.       require
  455.          min /= Void;
  456.          max /= Void;
  457.       local
  458.          element: WHEN_ITEM;
  459.       do
  460.          !WHEN_ITEM_2!element.make(min,max);
  461.          if list = Void then
  462.             list := <<element>>;
  463.          else
  464.             list.add_last(element);
  465.          end;
  466.       end;
  467.  
  468.    set_compound(c: like compound) is
  469.       do
  470.          compound := c;
  471.       ensure
  472.          compound = c
  473.       end;
  474.  
  475. feature {NONE}
  476.  
  477.    err_occ(v: INTEGER; p: POSITION) is
  478.       do
  479.          eh.add_position(e_inspect.start_position);
  480.          eh.append("Second occurrence for this value (");
  481.          eh.append(v.to_string);
  482.          error(p,") in the same inspect.");
  483.       end;
  484.  
  485. feature {NONE}
  486.  
  487.    em1: STRING is "Bad when clause.";
  488.    em2: STRING is "Empty when clause in inspect.";
  489.  
  490. end -- E_WHEN
  491.  
  492.  
  493.