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