home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_se / parent_list.e < prev    next >
Text File  |  1999-06-05  |  17KB  |  684 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 PARENT_LIST
  17.    --
  18.    -- To store the parent list of a class.
  19.    --
  20.  
  21. inherit GLOBALS;
  22.  
  23. creation make
  24.  
  25. feature
  26.  
  27.    base_class: BASE_CLASS;
  28.          -- Where the parent list is written.
  29.  
  30.    start_position: POSITION;
  31.          -- Of the keyword "inherit".
  32.  
  33.    heading_comment: COMMENT;
  34.          -- Global comment of the inherit clause.
  35.  
  36. feature {NONE}
  37.  
  38.    list: ARRAY[PARENT];
  39.  
  40. feature {NONE}
  41.  
  42.    make(bc: like base_class; sp: like start_position;
  43.         hc: like heading_comment; l: like list) is
  44.       require
  45.          bc /= Void;
  46.          sp /= Void;
  47.          l.lower = 1 and not l.empty;
  48.       do
  49.          base_class := bc;
  50.          heading_comment := hc;
  51.          start_position := sp;
  52.          list := l;
  53.       ensure
  54.          base_class = bc;
  55.          start_position = sp;
  56.          heading_comment = hc;
  57.          list = l;
  58.       end;
  59.  
  60. feature
  61.  
  62.    count: INTEGER is
  63.       do
  64.          Result := list.upper;
  65.       end;
  66.  
  67.    up_to_any_in(pl: FIXED_ARRAY[BASE_CLASS]) is
  68.       local
  69.          i: INTEGER;
  70.          p: PARENT;
  71.          bc: BASE_CLASS;
  72.       do
  73.          from
  74.             i := list.upper;
  75.          until
  76.             i = 0
  77.          loop
  78.             p := list.item(i);
  79.             bc := p.base_class;
  80.             if not pl.fast_has(bc) then
  81.                pl.add_last(bc);
  82.             end;
  83.             i := i - 1;
  84.          end;
  85.          from
  86.             i := list.upper;
  87.          until
  88.             i = 0
  89.          loop
  90.             p := list.item(i);
  91.             bc := p.base_class;
  92.             if bc /= class_any then
  93.                bc.up_to_any_in(pl);
  94.             end;
  95.             i := i - 1;
  96.          end;
  97.       end;
  98.  
  99.    base_class_name: CLASS_NAME is
  100.       do
  101.          Result := base_class.name;
  102.       end;
  103.  
  104.    has_redefine(fn: FEATURE_NAME): BOOLEAN is
  105.       require
  106.          fn /= Void
  107.       local
  108.          i: INTEGER;
  109.       do
  110.          from
  111.             i := 1;
  112.          until
  113.             Result or else i > list.upper
  114.          loop
  115.             Result := list.item(i).has_redefine(fn);
  116.             i := i + 1;
  117.          end;
  118.       end;
  119.  
  120. feature {BASE_CLASS}
  121.  
  122.    up_to_original(bottom: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is
  123.       local
  124.          p1, p2: PARENT;
  125.          fn1, fn2, new_fn: FEATURE_NAME;
  126.          i: INTEGER;
  127.       do
  128.          from
  129.             i := list.upper;
  130.          until
  131.             i = 0 or else fn1 /= Void
  132.          loop
  133.             p1 := list.item(i);
  134.             fn1 := p1.up_to_original(bottom,top_fn);
  135.             i := i - 1;
  136.          end;
  137.          from
  138.          until
  139.             i = 0
  140.          loop
  141.             p2 := list.item(i);
  142.             fn2 := p2.up_to_original(bottom,top_fn);
  143.             if fn2 /= Void then
  144.                new_fn := p2.do_rename(top_fn);
  145.                if p2.has_select_for(new_fn) then
  146.                   p1 := p2;
  147.                   fn1 := fn2;
  148.                end;
  149.             end;
  150.             i := i - 1;
  151.          end;
  152.          if fn1 /= Void then
  153.             if fn1.to_string /= top_fn.to_string then
  154.                Result := repeated_inheritance(p1,fn1,top_fn);
  155.             else
  156.                Result := fn1;
  157.             end;
  158.          end;
  159.       end;
  160.  
  161.    clients_for(fn: FEATURE_NAME): CLIENT_LIST is
  162.       require
  163.          fn /= Void
  164.       local
  165.          i: INTEGER;
  166.          cl: CLIENT_LIST;
  167.       do
  168.          from
  169.             i := list.upper;
  170.          until
  171.             i = 0
  172.          loop
  173.             cl := list.item(i).clients_for(fn);
  174.             if Result = Void then
  175.                Result := cl;
  176.             elseif cl /= Void then
  177.                Result := Result.append(cl);
  178.             end;
  179.             if Result = Void then
  180.                i := i - 1;
  181.             elseif Result.gives_permission_to_any then
  182.                i := 0;
  183.             else
  184.                eh.cancel;
  185.                i := i - 1;
  186.             end;
  187.          end;
  188.       end;
  189.  
  190.    going_up(trace: FIXED_ARRAY[PARENT]; top: BASE_CLASS;
  191.             top_fn: FEATURE_NAME;): FEATURE_NAME is
  192.       require
  193.          top /= Void;
  194.          top_fn /= Void
  195.       local
  196.          i: INTEGER;
  197.          p1, p2: PARENT;
  198.          fn1, fn2: FEATURE_NAME;
  199.       do
  200.          from
  201.             i := list.upper;
  202.          until
  203.             fn1 /= Void or else i = 0
  204.          loop
  205.             p1 := list.item(i);
  206.             fn1 := p1.going_up(trace,top,top_fn);
  207.             i := i - 1;
  208.          end;
  209.          from
  210.          until
  211.             i = 0
  212.          loop
  213.             p2 := list.item(i);
  214.             fn2 := p2.going_up(trace,top,top_fn);
  215.             if fn2 /= Void then
  216.                if p2.has_select_for(fn2) then
  217.                   p1 := p2;
  218.                   fn1 := fn2;
  219.                end;
  220.             end;
  221.             i := i - 1;
  222.          end;
  223.          Result := fn1;
  224.       end;
  225.  
  226.    is_a_vncg(t1, t2: TYPE): BOOLEAN is
  227.       require
  228.          t1.run_type = t1;
  229.          t2.run_type = t2;
  230.          t2.generic_list /= Void;
  231.          eh.empty
  232.       local
  233.          i: INTEGER;
  234.       do
  235.          from
  236.             i := list.upper;
  237.          until
  238.             Result or else i = 0
  239.          loop
  240.             Result := list.item(i).is_a_vncg(t1,t2);
  241.             i := i - 1;
  242.          end;
  243.       ensure
  244.          eh.empty
  245.       end;
  246.  
  247.    e_feature(fn: FEATURE_NAME): E_FEATURE is
  248.       local
  249.          i: INTEGER;
  250.       do
  251.          from
  252.             i := list.upper;
  253.          until
  254.             Result /= Void or else i = 0
  255.          loop
  256.             Result := list.item(i).e_feature(fn);
  257.             i := i - 1;
  258.          end;
  259.       end;
  260.  
  261.    collect_invariant(rc: RUN_CLASS) is
  262.       require
  263.          rc /= Void
  264.       local
  265.          i: INTEGER;
  266.       do
  267.          from
  268.             i := list.upper;
  269.          until
  270.             i = 0
  271.          loop
  272.             list.item(i).base_class.collect_invariant(rc);
  273.             i := i - 1;
  274.          end;
  275.       end;
  276.  
  277.    inherit_cycle_check is
  278.       local
  279.          i: INTEGER;
  280.          p: PARENT;
  281.          bc: BASE_CLASS;
  282.       do
  283.          from
  284.             i := list.upper;
  285.          until
  286.             i = 0
  287.          loop
  288.             p := list.item(i);
  289.             bc := p.base_class;
  290.             if bc = Void then
  291.                eh.add_position(p.start_position);
  292.                fatal_error(fz_cnf);
  293.             else
  294.                bc.inherit_cycle_check;
  295.             end;
  296.             i := i - 1;
  297.          end;
  298.       end;
  299.  
  300.    has_parent(c: BASE_CLASS): BOOLEAN is
  301.       require
  302.          not c.is_any
  303.       local
  304.          i: INTEGER;
  305.          bc: BASE_CLASS;
  306.       do
  307.          from
  308.             i := list.upper;
  309.          until
  310.             i = 0
  311.          loop
  312.             bc := list.item(i).base_class;
  313.             if c = bc then
  314.                Result := true;
  315.                i := 0;
  316.             elseif bc.is_subclass_of_aux(c) then
  317.                Result := true;
  318.                i := 0;
  319.             else
  320.                i := i - 1;
  321.             end;
  322.          end;
  323.       end;
  324.  
  325.    first_parent_for(c: BASE_CLASS): PARENT is
  326.          -- Gives the first parent going to `c'.
  327.       local
  328.          i: INTEGER;
  329.          pbc: BASE_CLASS;
  330.       do
  331.          from
  332.             i := 1;
  333.          until
  334.             Result /= Void
  335.          loop
  336.             Result := list.item(i);
  337.             pbc := Result.base_class;
  338.             if pbc = c then
  339.             elseif pbc.is_subclass_of(c) then
  340.             else
  341.                Result := Void;
  342.             end;
  343.             i := i + 1;
  344.          end;
  345.       ensure
  346.          Result /= Void
  347.       end;
  348.  
  349.    next_parent_for(c: BASE_CLASS; previous: PARENT): like previous is
  350.          -- Gives the next one or Void.
  351.       local
  352.          i: INTEGER;
  353.          pbc: BASE_CLASS;
  354.       do
  355.          from
  356.             from
  357.                i := 1;
  358.             until
  359.                Result = previous
  360.             loop
  361.                Result := list.item(i);
  362.                i := i + 1;
  363.             end;
  364.             Result := Void;
  365.          until
  366.             Result /= Void or else i > list.count
  367.          loop
  368.             Result := list.item(i);
  369.             pbc := Result.base_class;
  370.             if pbc = c then
  371.             elseif pbc.is_subclass_of(c) then
  372.             else
  373.                Result := Void;
  374.             end;
  375.             i := i + 1;
  376.          end;
  377.       end;
  378.  
  379.    header_comment_for(ci: CLASS_INVARIANT) is
  380.       local
  381.          i: INTEGER;
  382.       do
  383.          from
  384.             i := list.upper;
  385.          until
  386.             i = 0 or else ci.header_comment /= Void
  387.          loop
  388.             list.item(i).base_class.header_comment_for(ci);
  389.             i := i - 1;
  390.          end;
  391.       end;
  392.  
  393.    get_started is
  394.       local
  395.          i1, i2: INTEGER;
  396.          p1, p2: PARENT;
  397.       do
  398.          from
  399.             i1 := list.upper;
  400.          until
  401.             i1 = 0
  402.          loop
  403.             list.item(i1).get_started(Current);
  404.             i1 := i1 - 1;
  405.          end;
  406.          if list.upper > 1 then
  407.             -- Checking select :
  408.             from
  409.                i2 := list.upper;
  410.             until
  411.                i2 = 1
  412.             loop
  413.                from
  414.                   i1 := 1;
  415.                invariant
  416.                   i1 < i2 + 1
  417.                variant
  418.                   i2 - i1
  419.                until
  420.                   i1 = i2
  421.                loop
  422.                   p1 := list.item(i1);
  423.                   p2 := list.item(i2);
  424.                   p1.multiple_check(p2);
  425.                   p2.multiple_check(p1);
  426.                   i1 := i1 + 1;
  427.                end;
  428.                i2 := i2 - 1;
  429.             end;
  430.          end;
  431.       end;
  432.  
  433.    look_up_for(rc: RUN_CLASS; fn: FEATURE_NAME): E_FEATURE is
  434.       local
  435.          i: INTEGER;
  436.          p1, p2: PARENT;
  437.          f1, f2: E_FEATURE;
  438.       do
  439.          from
  440.             i := list.upper;
  441.          until
  442.             f1 /= Void or else i = 0
  443.          loop
  444.             p1 := list.item(i);
  445.             f1 := p1.look_up_for(rc,fn);
  446.             i := i - 1;
  447.          end;
  448.          from
  449.          until
  450.             i = 0
  451.          loop
  452.             p2 := list.item(i);
  453.             f2 := p2.look_up_for(rc,fn);
  454.             if f2 = Void then
  455.             elseif f1 = f2 then
  456.             elseif not f2.is_merge_with(f1,rc) then
  457.                eh.add_position(start_position);
  458.                eh.add_position(f1.start_position);
  459.                eh.add_position(f2.start_position);
  460.                fatal_error(fz_ich);
  461.             elseif f2.is_deferred then
  462.             elseif f1.is_deferred then
  463.                f1 := f2;
  464.                p1 := p2;
  465.             elseif p1.has_redefine(fn) then
  466.                if p2.has_redefine(fn) then
  467.                else
  468.                   eh.add_position(fn.start_position);
  469.                   eh.add_position(p2.start_position);
  470.                   eh.add_position(f2.start_position);
  471.                   eh.append(em1);
  472.                   eh.print_as_fatal_error;
  473.                end;
  474.             elseif p2.has_redefine(fn) then
  475.                eh.add_position(fn.start_position);
  476.                eh.add_position(p1.start_position);
  477.                eh.add_position(f1.start_position);
  478.                eh.append(em1);
  479.                eh.print_as_fatal_error;
  480.             else
  481.                eh.add_position(p2.start_position);
  482.                eh.add_position(p1.start_position);
  483.                eh.add_position(f1.start_position);
  484.                eh.add_position(f2.start_position);
  485.                eh.append(em1);
  486.                eh.print_as_fatal_error;
  487.             end;
  488.             i := i - 1;
  489.          end;
  490.          Result := f1;
  491.       end;
  492.  
  493.    collect_assertion(fn: FEATURE_NAME) is
  494.       require
  495.          fn /= Void
  496.       local
  497.          i: INTEGER;
  498.          p1, p2: PARENT;
  499.          fn1, fn2: FEATURE_NAME;
  500.       do
  501.          from
  502.             i := list.upper;
  503.          until
  504.             i = 0
  505.          loop
  506.             p2 := list.item(i);
  507.             fn2 := p2.name_in_parent(fn);
  508.             if fn2 /= Void and then p2.has_select_for(fn) then
  509.                p1 := p2;
  510.                fn1 := fn2;
  511.             end;
  512.             i := i - 1;
  513.          end;
  514.          if fn1 /= Void then
  515.             p1.base_class.collect_assertion(fn1);
  516.          else
  517.             from
  518.                i := list.upper;
  519.             until
  520.                i = 0
  521.             loop
  522.                p1 := list.item(i);
  523.                fn1 := p1.name_in_parent(fn);
  524.                if fn1 /= Void then
  525.                   p1.base_class.collect_assertion(fn1);
  526.                end;
  527.                i := i - 1;
  528.             end;
  529.          end;
  530.       end;
  531.  
  532.    pretty_print is
  533.       local
  534.          i: INTEGER;
  535.       do
  536.          fmt.set_indent_level(0);
  537.          if fmt.zen_mode then
  538.             fmt.indent;
  539.          else
  540.             fmt.skip(1);
  541.          end;
  542.          fmt.keyword("inherit");
  543.          fmt.set_indent_level(1);
  544.          fmt.indent;
  545.          if heading_comment /= Void then
  546.             heading_comment.pretty_print;
  547.          end;
  548.          from
  549.             i := 1;
  550.          until
  551.             i > list.upper
  552.          loop
  553.             list.item(i).pretty_print;
  554.             i := i + 1;
  555.          end;
  556.       end;
  557.  
  558.    smallest_ancestor(type, other: TYPE): TYPE is
  559.       require
  560.          type.base_class.parent_list = Current;
  561.          other.base_class.parent_list /= Void;
  562.          type.is_run_type;
  563.          other.is_run_type;
  564.       local
  565.          i: INTEGER;
  566.          p: PARENT;
  567.          sa: TYPE;
  568.       do
  569.          from
  570.             i := list.upper;
  571.          until
  572.             i = 0
  573.          loop
  574.             p := list.item(i);
  575.             sa := p.runnable_type(other);
  576.             if Result = Void then
  577.                Result := sa;
  578.             else
  579.                Result := sa.smallest_ancestor(Result);
  580.             end;
  581.             if Result.is_any then
  582.                i := 0;
  583.             else
  584.                i := i - 1;
  585.             end;
  586.          end;
  587.       ensure
  588.          Result.is_run_type;
  589.       end;
  590.  
  591. feature {E_PRECURSOR}
  592.  
  593.    precursor_for(p: E_PRECURSOR; wrf: RUN_FEATURE): EFFECTIVE_ROUTINE is
  594.          -- Look for the feature for `p' which is written inside `wrf'.
  595.       require
  596.          p /= Void;
  597.          wrf /= Void
  598.       local
  599.          i: INTEGER;
  600.          parent: PARENT;
  601.          f2: like precursor_for;
  602.       do
  603.          from
  604.             i := list.upper;
  605.          until
  606.             Result /= Void or else i = 0
  607.          loop
  608.             parent := list.item(i);
  609.             Result := parent.precursor_for(p,wrf);
  610.             i := i - 1;
  611.          end;
  612.          if Result = Void then
  613.             eh.add_position(p.start_position);
  614.             fatal_error("Precursor routine not found.");
  615.          end;
  616.          if run_control.all_check then
  617.             from
  618.             until
  619.                i = 0
  620.             loop
  621.                parent := list.item(i);
  622.                f2 := parent.precursor_for(p,wrf);
  623.                if f2 /= Void and then f2 /= Result then
  624.                   eh.add_position(p.start_position);
  625.                   eh.add_position(Result.start_position);
  626.                   eh.add_position(f2.start_position);
  627.                   fatal_error("Multiple Precursor found (must use %
  628.                               % { ... } selection.");
  629.                end;
  630.                i := i - 1;
  631.             end;
  632.          end;
  633.       end;
  634.  
  635. feature {NONE}
  636.  
  637.    repeated_inheritance(p1: PARENT; fn1, top_fn: FEATURE_NAME): FEATURE_NAME is
  638.       require
  639.          p1 /= void;
  640.          fn1 /= Void;
  641.          top_fn /= Void
  642.       local
  643.          i: INTEGER;
  644.          p2: PARENT;
  645.          bc1: BASE_CLASS;
  646.       do
  647.          from
  648.             bc1 := p1.base_class;
  649.             i := list.upper;
  650.          until
  651.             i = 0
  652.          loop
  653.             p2 := list.item(i);
  654.             if p1 /= p2 then
  655.                if bc1 = p2.base_class then
  656.                   if p2.do_rename(fn1).to_string = top_fn.to_string then
  657.                      Result := top_fn;
  658.                   elseif p1.do_rename(fn1).to_string = top_fn.to_string then
  659.                      Result := top_fn;
  660.                   end;
  661.                end;
  662.             end;
  663.             i := i - 1;
  664.          end;
  665.          if Result = Void then
  666.             Result := fn1;
  667.          end;
  668.       ensure
  669.          top_fn /= Void
  670.       end;
  671.  
  672.    em1: STRING is "Inheritance clash.";
  673.  
  674. invariant
  675.  
  676.    base_class /= Void;
  677.  
  678.    list.lower = 1;
  679.  
  680.    not list.empty;
  681.  
  682. end -- PARENT_LIST
  683.  
  684.