home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ppcsmalleiffel / lib_se / parent.e < prev    next >
Encoding:
Text File  |  1998-01-16  |  16.3 KB  |  702 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
  17.    --   
  18.    -- To store the inheritance options for one parent of a class.
  19.    --
  20.  
  21. inherit 
  22.    GLOBALS
  23.       redefine fill_tagged_out_memory 
  24.       end;
  25.  
  26. creation {EIFFEL_PARSER} make 
  27.  
  28. feature 
  29.    
  30.    parent_list: PARENT_LIST;
  31.      -- Corresponding one;
  32.    
  33.    type: TYPE;
  34.      -- Declaration type mark of the parent.
  35.    
  36.    comment: COMMENT;
  37.      -- Associated heading comment.
  38.  
  39. feature {PARENT} -- Optionnal list in syntaxical order :
  40.    
  41.    rename_list: RENAME_LIST;
  42.    
  43.    export_list: EXPORT_LIST;
  44.  
  45.    undefine_list: FEATURE_NAME_LIST
  46.  
  47.    redefine_list: FEATURE_NAME_LIST;
  48.  
  49.    select_list: FEATURE_NAME_LIST;
  50.  
  51. feature {NONE}
  52.    
  53.    make(t: like type) is
  54.       require
  55.      t /= Void;
  56.      not t.is_anchored;
  57.      t.start_position /= Void;
  58.       do
  59.      type := t;
  60.      if forbidden_parent_list.fast_has(type.written_mark) then
  61.         eh.add_position(type.start_position);
  62.         eh.append("You cannot inherit %"");
  63.         eh.append(type.written_mark);
  64.         fatal_error("%" (not yet implemented).");
  65.      end;
  66.       ensure
  67.      type = t
  68.       end;
  69.    
  70. feature 
  71.  
  72.    start_position: POSITION is
  73.       do
  74.      Result := type.start_position;
  75.       end;
  76.    
  77.    has_undefine(fn: FEATURE_NAME): BOOLEAN is
  78.       do
  79.      if undefine_list /= Void then
  80.         Result := undefine_list.has(fn);
  81.      end;
  82.       end;
  83.    
  84.    look_up_for(rc: RUN_CLASS; fn: FEATURE_NAME): E_FEATURE is
  85.       require
  86.      rc /= Void;
  87.      fn /= Void
  88.       local
  89.      fn2: like fn;
  90.      f: E_FEATURE;
  91.       do
  92.      if rename_list = Void or else not rename_list.affect(fn) then
  93.         f := type.look_up_for(rc,fn);
  94.         Result := apply_undefine(f,fn);
  95.      else
  96.         fn2 := rename_list.to_old_name(fn);
  97.         if fn2 /= fn then
  98.            f := type.look_up_for(rc,fn2);
  99.            Result := apply_undefine(f,fn2);
  100.         else
  101.            check
  102.           fn /= rename_list.to_new_name(fn);
  103.            end;
  104.            f := type.look_up_for(rc,fn);
  105.            if f = Void then
  106.           eh.add_position(fn.start_position);
  107.           eh.append(fz_09);
  108.           eh.append(fn.to_string);
  109.           fatal_error("%" is not a feature of the parent.");
  110.            end;
  111.         end;        
  112.      end;
  113.       end;
  114.    
  115.    collect_for(code: INTEGER; fn: FEATURE_NAME) is
  116.       require
  117.      code = code_require or else code = code_ensure;
  118.      fn /= Void
  119.       local
  120.      fn2: like fn;
  121.       do
  122.      if rename_list = Void or else not rename_list.affect(fn) then
  123.         type.base_class.collect_for(code,fn);
  124.      else
  125.         fn2 := rename_list.to_old_name(fn);
  126.         if fn2 /= fn then
  127.            type.base_class.collect_for(code,fn2);
  128.         end;
  129.      end;
  130.       end;
  131.       
  132.    has_redefine(fn: FEATURE_NAME): BOOLEAN is
  133.       require
  134.      fn /= Void
  135.       do
  136.      if redefine_list /= Void then
  137.         Result := redefine_list.has(fn);
  138.      end;
  139.       end;
  140.    
  141.    fill_tagged_out_memory is
  142.       local
  143.      p: POSITION;
  144.       do
  145.      p := start_position;
  146.      if p /= Void then
  147.         p.fill_tagged_out_memory;
  148.      end;
  149.       end;
  150.  
  151. feature {PARENT_LIST}
  152.  
  153.    multiple_check(other: like Current) is
  154.      -- Note : is called twice (whith swap) for each couple of
  155.      -- parents.
  156.       require
  157.      other /= Current;
  158.      parent_list = other.parent_list
  159.       local
  160.      bc1, bc2: BASE_CLASS;
  161.      i: INTEGER;
  162.      fn1, fn2: FEATURE_NAME;
  163.       do
  164.      bc1 := type.base_class;
  165.      bc2 := other.type.base_class;
  166.      if bc1 = bc2 or else 
  167.         bc1.is_subclass_of(bc2) or else
  168.         bc2.is_subclass_of(bc1)
  169.       then
  170.         if redefine_list /= Void then
  171.            from
  172.           i := redefine_list.count
  173.            until
  174.           i = 0
  175.            loop
  176.           fn1 := redefine_list.item(i);
  177.           if other.rename_list = Void then
  178.           elseif other.rename_list.affect(fn1) then
  179.              fn2 := other.rename_list.to_new_name(fn1);
  180.              if fn2 /= fn1 then
  181.             if select_list /= Void then
  182.                if select_list.has(fn1) then
  183.                   if other.select_list /= Void then
  184.                  if other.select_list.has(fn2) then
  185.                     select_conflict(fn1,fn2);
  186.                  end;
  187.                   end;
  188.                elseif other.select_list = Void then
  189.                   missing_select(fn1,fn2);
  190.                elseif not other.select_list.has(fn2) then
  191.                   missing_select(fn1,fn2);
  192.                end;
  193.             elseif other.select_list = Void then
  194.                missing_select(fn1,fn2);
  195.             elseif not other.select_list.has(fn2) then
  196.                missing_select(fn1,fn2);
  197.             end;
  198.              else
  199.              end;
  200.           end;
  201.           i := i - 1;
  202.            end;
  203.         end;
  204.      else
  205.         -- Nothing because of swapped duplicate call.
  206.      end;
  207.       end;
  208.  
  209.    smallest_ancestor(ctx: TYPE): TYPE is
  210.       require
  211.      ctx.is_run_type;
  212.       do
  213.      if type.is_generic then
  214.         Result := type.to_runnable(ctx);
  215.      else
  216.         Result := type;
  217.      end;
  218.       ensure
  219.      Result.is_run_type;
  220.       end;
  221.  
  222.    do_rename(fn: FEATURE_NAME): like fn is
  223.       do
  224.      if rename_list = Void then
  225.         Result := fn;
  226.      else
  227.         Result := rename_list.to_new_name(fn);
  228.      end;
  229.       end;
  230.    
  231. feature {EIFFEL_PARSER}
  232.    
  233.    set_comment(c: like comment) is
  234.       do
  235.      comment := c;
  236.       end;
  237.    
  238.    add_rename(rp: RENAME_PAIR) is
  239.       require
  240.      rp /= Void
  241.       do
  242.      if rename_list = Void then
  243.         !!rename_list.make(<<rp>>);
  244.      else
  245.         rename_list.add_last(rp);
  246.      end;
  247.       end;
  248.    
  249.    set_export(el: EXPORT_LIST) is
  250.       require
  251.      el /= Void
  252.       do
  253.      export_list := el;
  254.       ensure
  255.      export_list = el
  256.       end;
  257.    
  258.    set_undefine(fl: ARRAY[FEATURE_NAME]) is
  259.       require
  260.      fl /= Void
  261.       do
  262.      !!undefine_list.make(fl);
  263.       end;
  264.    
  265.    set_redefine(fl: ARRAY[FEATURE_NAME]) is
  266.       require
  267.      fl /= Void;
  268.       do
  269.      !!redefine_list.make(fl);
  270.       end;
  271.    
  272.    set_select(fl: ARRAY[FEATURE_NAME]) is
  273.       require
  274.      fl /= Void
  275.       do
  276.      !!select_list.make(fl);
  277.       end;
  278.    
  279. feature {PARENT_LIST}
  280.  
  281.    is_a_vncg(t1, t2: TYPE): BOOLEAN is
  282.       require
  283.      t1.run_type = t1;
  284.      t2.run_type = t2;
  285.      t2.generic_list /= Void;
  286.      eh.empty
  287.       local
  288.      rank, i: INTEGER;
  289.      gl, gl1, gl2: ARRAY[TYPE];
  290.      tfg: TYPE_FORMAL_GENERIC;
  291.      rt: TYPE;
  292.      type_bc, t2_bc: BASE_CLASS;
  293.      type_bcn, t2_bcn: STRING;
  294.       do
  295.      type_bc := type.base_class;
  296.      type_bcn := type_bc.base_class_name.to_string;
  297.      t2_bc := t2.base_class;
  298.      t2_bcn := t2_bc.base_class_name.to_string;
  299.      if type_bcn = t2_bcn then -- Here is a good parent :
  300.         gl := type.generic_list;
  301.         gl2 := t2.generic_list;
  302.         if gl = Void or else gl.count /= gl2.count then
  303.            eh.add_position(type.start_position);
  304.            eh.add_position(t2.start_position);
  305.            fatal_error("Bad number of generic arguments.");
  306.         end;
  307.         if t1.is_generic then 
  308.            gl1 := t1.generic_list;
  309.            from
  310.           Result := true;
  311.           i := gl2.count;
  312.            until
  313.           not Result or else i = 0
  314.            loop
  315.           if gl.item(i).is_formal_generic then
  316.              tfg ?= gl.item(i);
  317.              check
  318.             tfg /= Void
  319.              end;
  320.              rank := tfg.rank;
  321.              Result :=  gl1.item(rank).is_a(gl2.item(i));
  322.           else
  323.              --
  324.              -- eh.add_type(type," is the good parent. ");
  325.              -- eh.add_type(t1," is T1. ");
  326.              -- eh.add_type(t2," is T2. ");
  327.              -- eh.print_as_warning;
  328.              --
  329.              rt := gl.item(i).to_runnable(t1).run_type;
  330.              Result := rt.is_a(gl2.item(i));
  331.           end;
  332.           i := i - 1;
  333.            end;
  334.         else
  335.            Result := type.is_a(t2);
  336.         end;
  337.         if not Result then
  338.            eh.cancel;
  339.         end;
  340.      elseif type_bc.is_subclass_of(t2_bc) then
  341.         if t1.is_generic then
  342.            rt := type.to_runnable(t1).run_type;
  343.            Result := type_bc.is_a_vncg(rt,t2);
  344.         else
  345.            Result := type_bc.is_a_vncg(type,t2);
  346.         end;
  347.         if not Result then
  348.            eh.cancel;
  349.         end;
  350.      end;
  351.       ensure
  352.      eh.empty
  353.       end;
  354.  
  355.    has(fn: FEATURE_NAME): BOOLEAN is
  356.       do
  357.      if rename_list = Void then
  358.         Result := type.base_class.has(fn);
  359.      else
  360.         Result := type.base_class.has(rename_list.to_old_name(fn));
  361.      end;
  362.       end;
  363.    
  364.    clients_for(fn: FEATURE_NAME): CLIENT_LIST is
  365.       require
  366.      fn /= Void
  367.       local
  368.      old_fn: like fn;
  369.       do
  370.      if rename_list = Void then
  371.         if export_list = Void then
  372.            Result := type.base_class.clients_for(fn);
  373.         else
  374.            Result := export_list.clients_for(fn);
  375.            if Result = Void then
  376.           Result := type.base_class.clients_for(fn);
  377.            end;
  378.         end;
  379.      else
  380.         old_fn := rename_list.to_old_name(fn);
  381.         if export_list = Void then
  382.            Result := type.base_class.clients_for(old_fn);
  383.         else
  384.            Result := export_list.clients_for(old_fn);
  385.            if Result = Void then
  386.           Result := type.base_class.clients_for(old_fn);
  387.            end;
  388.         end;
  389.      end;
  390.       end;
  391.    
  392.    pretty_print is
  393.       local
  394.      end_needed: BOOLEAN;
  395.       do
  396.      fmt.set_indent_level(1);
  397.      fmt.indent;
  398.      type.pretty_print;
  399.      if rename_list = Void and then
  400.         export_list = Void and then
  401.         undefine_list = Void and then
  402.         redefine_list = Void and then
  403.         select_list = Void then
  404.         fmt.put_character(';');
  405.      end;
  406.      if comment /= Void then
  407.         fmt.put_character(' ');
  408.         comment.pretty_print;
  409.      end;
  410.      if rename_list /= Void then
  411.         end_needed := true;
  412.         rename_list.pretty_print;
  413.      end;
  414.      if export_list /= Void then
  415.         end_needed := true;
  416.         export_list.pretty_print;
  417.      end;
  418.      if undefine_list /= Void then
  419.         end_needed := true;
  420.         fmt.set_indent_level(2);
  421.         fmt.indent;
  422.         fmt.keyword("undefine");
  423.         undefine_list.pretty_print;
  424.      end;
  425.      if redefine_list /= Void then
  426.         end_needed := true;
  427.         fmt.set_indent_level(2);
  428.         fmt.indent;
  429.         fmt.keyword("redefine");
  430.         redefine_list.pretty_print;
  431.      end;
  432.      if select_list /= Void then
  433.         end_needed := true;
  434.         fmt.set_indent_level(2);
  435.         fmt.indent;
  436.         fmt.keyword("select");
  437.         select_list.pretty_print;
  438.      end;
  439.      if end_needed then
  440.         fmt.set_indent_level(2);
  441.         fmt.indent;
  442.         fmt.keyword("end;");
  443.      end;
  444.      fmt.set_indent_level(1);
  445.      fmt.indent;
  446.       end;
  447.    
  448.    get_started(pl: like parent_list) is
  449.       require
  450.      pl /= Void;
  451.       local
  452.      i: INTEGER;
  453.      wbc, pbc: BASE_CLASS;
  454.      fn, old_fn, new_fn: FEATURE_NAME;
  455.      all_check: BOOLEAN;
  456.       do
  457.      all_check := run_control.all_check;
  458.      parent_list := pl;
  459.      pbc := type.base_class;
  460.      wbc := parent_list.base_class;
  461.      if all_check and then rename_list /= Void then
  462.         rename_list.get_started(pbc);
  463.      end;
  464.      if all_check and then undefine_list /= Void then
  465.         from  
  466.            i := undefine_list.count;
  467.         until
  468.            i = 0
  469.         loop
  470.            fn := undefine_list.item(i);
  471.            old_fn := get_old_name(fn);
  472.            if old_fn = Void and then not pbc.has(fn) then
  473.           eh.add_position(fn.start_position);
  474.           fatal_error("Cannot undefine unexistant feature (VDUS.1).");
  475.            end;
  476.            i := i - 1;
  477.         end;
  478.      end;
  479.      if redefine_list /= Void then
  480.         from
  481.            i := redefine_list.count;
  482.         until
  483.            i = 0 
  484.         loop
  485.            fn := redefine_list.item(i);
  486.            if not wbc.proper_has(fn) then
  487.           eh.add_position(fn.start_position);
  488.           fatal_error("Redefinition not found.");
  489.            end;
  490.            if all_check then
  491.           old_fn := get_old_name(fn);
  492.           if old_fn = Void and then not pbc.has(fn) then
  493.              eh.add_position(fn.start_position);
  494.              fatal_error("Cannot redefine unexistant feature (VDRS.1).");
  495.           end;
  496.            end;
  497.            i := i - 1;
  498.         end;
  499.      end;
  500.      if all_check and then select_list /= Void then
  501.         from
  502.            i := select_list.count;
  503.         until
  504.            i = 0 
  505.         loop
  506.            fn := select_list.item(i);
  507.            old_fn := get_old_name(fn);
  508.            if old_fn = Void and then not pbc.has(fn) then
  509.           eh.add_position(fn.start_position);
  510.           fatal_error(em1);
  511.            end;
  512.            new_fn := get_new_name(fn);
  513.            if new_fn /= Void then
  514.           if get_old_name(new_fn) = Void then
  515.              eh.add_position(new_fn.start_position);
  516.              eh.add_position(fn.start_position);
  517.              fatal_error(em1);
  518.           end;
  519.            end;
  520.            i := i - 1;
  521.         end;
  522.      end;
  523.       ensure
  524.      parent_list = pl
  525.       end;
  526.  
  527. feature {NONE}
  528.  
  529.    forbidden_parent_list: ARRAY[STRING] is
  530.       once
  531.      Result := <<us_none,us_boolean,us_integer,us_character,
  532.              us_real,us_double,us_bit,us_pointer,
  533.              us_native_array>>;
  534.       end;
  535.  
  536. feature {NONE}
  537.  
  538.    get_old_name(fn: FEATURE_NAME): like fn is
  539.       do
  540.      if rename_list /= Void then
  541.         Result := rename_list.to_old_name(fn);
  542.         if Result = fn then
  543.            Result := Void;
  544.         end;
  545.      end;
  546.       end;
  547.  
  548.    get_new_name(fn: FEATURE_NAME): like fn is
  549.       do
  550.      if rename_list /= Void then
  551.         Result := rename_list.to_new_name(fn);
  552.         if Result = fn then
  553.            Result := Void;
  554.         end;
  555.      end;
  556.       end;
  557.  
  558.    check_no_old_name(fn: FEATURE_NAME) is
  559.       local
  560.      old_name: like fn;
  561.       do
  562.      if rename_list /= Void then
  563.         old_name := rename_list.to_old_name(fn);
  564.         if old_name /= fn then
  565.            eh.add_position(fn.start_position);
  566.            eh.add_position(old_name.start_position);
  567.            eh.append("Feature %"");
  568.            eh.append(old_name.to_string);
  569.            fatal_error("%" is renamed.");
  570.         end;
  571.      end;
  572.       end;
  573.  
  574. feature {PARENT}
  575.  
  576.    going_down(trace: FIXED_ARRAY[PARENT]; fn: FEATURE_NAME;): FEATURE_NAME is
  577.       require
  578.      trace /= Void;
  579.      fn /= Void
  580.       local
  581.      previous: like Current;
  582.       do
  583.      if rename_list = Void then
  584.         Result := fn;
  585.      else
  586.         Result := rename_list.to_new_name(fn);
  587.      end;
  588.      if not trace.empty then
  589.         previous := trace.last;
  590.         trace.remove_last;
  591.         Result := previous.going_down(trace,Result);
  592.      end;
  593.       ensure
  594.      Result /= Void
  595.       end;
  596.  
  597. feature {PARENT_LIST}
  598.  
  599.    up_to_original(bottom: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is
  600.       local
  601.      old_name: FEATURE_NAME;
  602.      bc: BASE_CLASS;
  603.       do
  604.      bc := type.base_class;
  605.      if rename_list = Void then
  606.         Result := bc.up_to_original(bottom,top_fn);
  607.      elseif rename_list.affect(top_fn) then
  608.         old_name := rename_list.to_old_name(top_fn);
  609.         if old_name /= top_fn then
  610.            Result := bc.up_to_original(bottom,old_name);
  611.         end;
  612.      else
  613.         Result := bc.up_to_original(bottom,top_fn);
  614.      end;
  615.       end;
  616.  
  617.    going_up(trace: FIXED_ARRAY[PARENT]; top: BASE_CLASS; 
  618.         top_fn: FEATURE_NAME;): FEATURE_NAME is
  619.       local
  620.      bc: BASE_CLASS;
  621.       do
  622.      bc := type.base_class;
  623.      if bc = top then
  624.         Result := going_down(trace,top_fn);
  625.      elseif bc.is_general then
  626.         Result := going_down(trace,top_fn);
  627.      elseif bc.is_subclass_of(top) then
  628.         trace.add_last(Current);
  629.         Result := bc.going_up(trace,top,top_fn);
  630.      end;
  631.       end;
  632.  
  633.    has_select_for(fn: FEATURE_NAME): BOOLEAN is
  634.       do
  635.      if select_list /= Void then
  636.         Result := select_list.has(fn);
  637.      end;
  638.       end;
  639.  
  640. feature {NONE}
  641.  
  642.    apply_undefine(f: E_FEATURE; fn: FEATURE_NAME): E_FEATURE is
  643.       local
  644.      fnkey: STRING;
  645.      index: INTEGER;
  646.       do
  647.      if has_undefine(fn) then
  648.         fnkey := fn.to_key;
  649.         if undefine_memory1 = Void then
  650.            undefine_memory1 := <<fnkey>>;
  651.            Result := f.try_to_undefine(fn,parent_list.base_class);
  652.            undefine_memory2 := <<Result>>;
  653.         else
  654.            index := undefine_memory1.fast_index_of(fnkey);
  655.            if index > undefine_memory1.upper then
  656.           undefine_memory1.add_last(fnkey);
  657.           Result := f.try_to_undefine(fn,parent_list.base_class);
  658.           undefine_memory2.add_last(Result);
  659.            else
  660.           Result := undefine_memory2.item(index);
  661.            end;
  662.         end;
  663.      else
  664.         Result := f;
  665.      end;
  666.       end;
  667.  
  668.    undefine_memory1: ARRAY[STRING];
  669.  
  670.    undefine_memory2: ARRAY[E_FEATURE];
  671.  
  672. feature {NONE}
  673.  
  674.    select_conflict(fn1, fn2: FEATURE_NAME) is
  675.       do
  676.      eh.add_position(fn1.start_position)
  677.      eh.add_position(fn2.start_position)
  678.      eh.append("Select conflict for those features.");
  679.      eh.print_as_fatal_error;
  680.       end;
  681.  
  682.    missing_select(fn1, fn2: FEATURE_NAME) is
  683.       do
  684.      eh.add_position(fn1.start_position)
  685.      eh.add_position(fn2.start_position)
  686.      eh.append("Missing select clause for those features.");
  687.      eh.print_as_fatal_error;
  688.       end;
  689.  
  690. feature
  691.  
  692.    em1: STRING is "Cannot select unexistant feature (VMSS).";
  693.  
  694. invariant
  695.    
  696.    not type.is_anchored;
  697.    
  698.    type.start_position /= Void;
  699.    
  700. end -- PARENT
  701.  
  702.