home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ppcsmalleiffel / lib_se / base_class.e < prev    next >
Encoding:
Text File  |  1998-01-16  |  23.5 KB  |  986 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 BASE_CLASS
  17.    --
  18.    -- Internal representation of an Eiffel source base class.
  19.    --
  20.    
  21. inherit 
  22.    GLOBALS
  23.       redefine fill_tagged_out_memory
  24.       end;
  25.    
  26. creation {EIFFEL_PARSER}
  27.    make
  28.    
  29. feature  
  30.    
  31.    id: INTEGER;
  32.      -- To produce compact C code.
  33.  
  34.    path: STRING;
  35.      -- Access to the corresponding file.
  36.    
  37.    index_list: INDEX_LIST;
  38.      -- For the indexing of the class. 
  39.    
  40.    heading_comment1: COMMENT;
  41.      -- Comment before keyword `class'.
  42.    
  43.    is_deferred: BOOLEAN;
  44.      -- True if class itself is deferred or if at least one 
  45.      -- feature is deferred;
  46.    
  47.    is_expanded: BOOLEAN;
  48.      -- True if class itself is expanded.
  49.    
  50.    base_class_name: CLASS_NAME; -- **** POURQUOI PAS name TOUT SIMPLEMENT ???***
  51.      -- The base_class_name of the class.
  52.    
  53.    formal_generic_list: FORMAL_GENERIC_LIST;
  54.      -- Formal generic args if any.
  55.    
  56.    heading_comment2: COMMENT;
  57.      -- Comment after class name.
  58.    
  59.    obsolete_type_string: MANIFEST_STRING;
  60.      -- To warn user if any.
  61.       
  62.    parent_list: PARENT_LIST;
  63.      -- The contents of the inherit clause if any.
  64.    
  65.    creation_clause_list: CREATION_CLAUSE_LIST;
  66.      -- Constructor list.
  67.    
  68.    feature_clause_list: FEATURE_CLAUSE_LIST;
  69.      -- Features.
  70.    
  71.    invariant_assertion: CLASS_INVARIANT;
  72.      -- If any.
  73.    
  74.    end_comment: COMMENT; 
  75.          -- Comment after end of class.
  76.    
  77. feature {NONE}
  78.    
  79.    feature_dictionary: DICTIONARY[E_FEATURE,STRING];
  80.      -- All features really defined in the current class. 
  81.      -- Thus, it is the same features contained in 
  82.      -- `feature_clause_list' (this dictionary speed up 
  83.      -- feature look up).
  84.      -- To avoid clash between infix and prefix names, 
  85.      -- access key IS NOT `to_string' but `to_key' of class 
  86.      -- NAME.
  87.    
  88.    make is
  89.       require
  90.      eiffel_parser.is_running;
  91.       do
  92.      !!isom.with_capacity(6,1);
  93.      path := unique_string.item(parser_buffer.path);
  94.      !!base_class_name.make_unknown;
  95.      !!feature_dictionary.with_capacity(32);
  96.       end;
  97.    
  98. feature 
  99.  
  100.    fill_tagged_out_memory is
  101.       do
  102.      tagged_out_memory.append(base_class_name.to_string);
  103.       end;
  104.  
  105. feature {SHORT,PARENT_LIST}
  106.  
  107.    up_to_any_in(pl: FIXED_ARRAY[BASE_CLASS]) is
  108.       do
  109.      if is_general then
  110.      else
  111.         if not pl.fast_has(Current) then
  112.            pl.add_last(Current);
  113.         end;
  114.         if parent_list = Void then
  115.            if not pl.fast_has(class_any) then
  116.           pl.add_last(class_any);
  117.            end;
  118.         else
  119.            parent_list.up_to_any_in(pl);
  120.         end;
  121.      end;
  122.       end;
  123.  
  124. feature
  125.    
  126.    expanded_initializer(t: TYPE): RUN_FEATURE_3 is
  127.       require
  128.      t.is_expanded
  129.       do
  130.      if creation_clause_list /= Void then
  131.         Result := creation_clause_list.expanded_initializer(t);
  132.      end;
  133.       end;
  134.    
  135. feature {RUN_CLASS}
  136.    
  137.    check_expanded_with(t: TYPE) is
  138.       require
  139.      t.is_expanded;
  140.      t.base_class = Current
  141.       local
  142.      rf: RUN_FEATURE;
  143.       do
  144.      if is_deferred then
  145.         eh.add_type(t,fz_is_invalid);
  146.         fatal_error(" A deferred class must not be expanded (VTEC.1).");
  147.      end;
  148.      if creation_clause_list /= Void then
  149.         creation_clause_list.check_expanded_with(t); 
  150.      end;
  151.      rf := expanded_initializer(t);
  152.       end;
  153.  
  154. feature {RUN_FEATURE}
  155.    
  156.    once_flag(mark: STRING): BOOLEAN is
  157.      -- Flag used to avoid double C definition of globals
  158.      -- C variables for once routines.
  159.       require
  160.      mark /= Void;
  161.      small_eiffel.is_ready
  162.       do
  163.      if once_mark_list = Void then
  164.         !!once_mark_list.with_capacity(4);
  165.         once_mark_list.add_last(mark);
  166.      elseif once_mark_list.fast_has(mark) then
  167.         Result := true;
  168.      else
  169.         once_mark_list.add_last(mark);
  170.      end;
  171.       end;
  172.  
  173. feature {NONE}
  174.    
  175.    once_mark_list: FIXED_ARRAY[STRING];
  176.            -- When the tag is in the list, the corresponding routine
  177.      -- does not use Current and C code is already written.
  178.    
  179. feature {TYPE_FORMAL_GENERIC}
  180.    
  181.    first_parent_for(other: like Current): PARENT is
  182.      -- Assume `other' is a parent of Current, gives 
  183.      -- the closest PARENT of Current going to `other'.
  184.       require
  185.      is_subclass_of(other);
  186.      parent_list /= Void
  187.       do
  188.      Result := parent_list.first_parent_for(other);
  189.       ensure
  190.      Result /= Void
  191.       end;
  192.    
  193.    next_parent_for(other: like Current; previous: PARENT): like previous is
  194.      -- Gives the next one or Void.
  195.       require
  196.      is_subclass_of(other);
  197.      parent_list /= Void
  198.       do
  199.      Result := parent_list.next_parent_for(other,previous);
  200.       end;
  201.    
  202. feature 
  203.  
  204.    new_name_of(top: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is
  205.      -- Assume, `top_fn' is a valid notation to denote a feature of 
  206.      -- `top'. It computes the corresponding name (taking in 
  207.      -- account possible rename/select) to use the feature down in class 
  208.      -- hierarchy to Current base_class.
  209.       require
  210.      Current = top or else Current.is_subclass_of(top);
  211.      top_fn /= Void
  212.       do
  213.      if Current = top then
  214.         Result := top_fn;
  215.      else
  216.         Result := top.up_to_original(Current,top_fn);
  217.         if Result = Void then
  218.            eh.add_position(top_fn.start_position);
  219.            eh.append(fz_09);
  220.            eh.append(top_fn.to_string);
  221.            eh.append("%" from %"");
  222.            eh.append(top.base_class_name.to_string);
  223.            eh.append("%" not found in %"");
  224.            eh.append(base_class_name.to_string);
  225.            fatal_error("%".");
  226.         end;
  227.      end;
  228.       ensure
  229.      Result /= Void
  230.       end;
  231.  
  232. feature {BASE_CLASS,PARENT}
  233.  
  234.    up_to_original(bottom: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is
  235.       do
  236.      if proper_has(top_fn) then
  237.         if parent_list = Void then
  238.            Result := bottom.new_name_of_original(Current,top_fn);
  239.         else
  240.            Result := parent_list.up_to_original(bottom,top_fn);
  241.            if Result = Void then
  242.           Result := bottom.new_name_of_original(Current,top_fn);
  243.            end;
  244.         end;
  245.      elseif parent_list /= Void then
  246.         Result := parent_list.up_to_original(bottom,top_fn);
  247.      elseif is_general then
  248.      else
  249.         Result := class_any.up_to_original(bottom,top_fn);
  250.      end;
  251.       end;
  252.  
  253. feature {BASE_CLASS}
  254.  
  255.    new_name_of_original(top: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is
  256.      -- Compute rename/select to go down in class hierarchy.
  257.      -- Thus, in the first call, `top_fn' is the name used in `top'.
  258.       require
  259.      top.proper_has(top_fn);
  260.      Current = top or else Current.is_subclass_of(top);
  261.      top_fn /= Void
  262.       do
  263.      if Current = top then
  264.         Result := top_fn;
  265.      elseif is_general then
  266.         Result := top_fn;
  267.      else
  268.         if parent_list = Void then
  269.            Result := class_any.new_name_of(top,top_fn);
  270.         else
  271.            going_up_trace.clear;
  272.            Result := parent_list.going_up(going_up_trace,top,top_fn);
  273.         end;
  274.      end;
  275.       ensure
  276.      Result /= Void
  277.       end;
  278.  
  279. feature {BASE_CLASS,PARENT_LIST,PARENT} 
  280.  
  281.    going_up(trace: FIXED_ARRAY[PARENT]; top: BASE_CLASS; 
  282.         top_fn: FEATURE_NAME;): FEATURE_NAME is
  283.       require
  284.      Current /= top;
  285.       do
  286.      if parent_list = Void then
  287.         Result := class_any.going_up(trace,top,top_fn);
  288.      else
  289.         Result := parent_list.going_up(trace,top,top_fn);
  290.      end;
  291.       end;
  292.  
  293. feature {NONE}
  294.  
  295.    going_up_trace: FIXED_ARRAY[PARENT] is
  296.       once
  297.      !!Result.with_capacity(8);
  298.       end;
  299.    
  300. feature 
  301.    
  302.    mapping_c_in(str: STRING) is
  303.       do
  304.      str.extend('B');
  305.      str.extend('C');
  306.      id.append_in(str);
  307.       end;
  308.    
  309.    mapping_c is
  310.       local
  311.      s: STRING;
  312.       do
  313.      s := "        ";
  314.      s.clear;
  315.      mapping_c_in(s);
  316.      cpp.put_string(s);
  317.       end;
  318.    
  319. feature {EIFFEL_PARSER}
  320.    
  321.    add_index_clause(index_clause: INDEX_CLAUSE) is
  322.       require
  323.      index_clause /= Void
  324.       do
  325.      if index_list = Void then
  326.         !!index_list.make(<<index_clause>>);
  327.      else
  328.         index_list.list.add_last(index_clause);
  329.      end;
  330.       end;
  331.       
  332.    add_creation_clause(cc: CREATION_CLAUSE) is
  333.       require
  334.      cc /= Void
  335.       do
  336.      if creation_clause_list = Void then
  337.         !!creation_clause_list.make(<<cc>>);
  338.      else
  339.         creation_clause_list.add_last(cc);
  340.      end;
  341.       end;
  342.       
  343.    add_feature_clause(fc: FEATURE_CLAUSE) is
  344.       require
  345.      fc /= Void
  346.       do
  347.      if feature_clause_list = Void then
  348.         !!feature_clause_list.make(<<fc>>);
  349.      else
  350.         feature_clause_list.add_last(fc);
  351.      end;
  352.       end;
  353.       
  354.    set_is_deferred is
  355.       do
  356.      if is_expanded then
  357.         error_vtec1;
  358.      end;
  359.      is_deferred := true;
  360.       end;
  361.  
  362.    set_is_expanded is
  363.       do
  364.      if is_deferred then
  365.         error_vtec1;
  366.      end;
  367.      is_expanded := true;
  368.       end;
  369.  
  370.    set_formal_generic_list(fgl: like formal_generic_list) is
  371.       do
  372.      formal_generic_list := fgl; 
  373.       end;
  374.  
  375.    set_heading_comment1(hc: like heading_comment1) is
  376.       do
  377.      heading_comment1 := hc;
  378.       end;
  379.    
  380.    set_heading_comment2(hc: like heading_comment2) is
  381.       do
  382.      heading_comment2 := hc;
  383.       end;
  384.    
  385.    set_parent_list(sp: POSITION; c: COMMENT; l: ARRAY[PARENT]) is
  386.       require
  387.      sp /= Void;
  388.      c /= Void or else l /= Void;
  389.      l /= Void implies not l.empty;
  390.       do
  391.      !!parent_list.make(Current,sp,c,l);
  392.       end;
  393.    
  394.    set_end_comment(ec: like end_comment) is
  395.       do
  396.      end_comment := ec;
  397.       end;
  398.    
  399.    set_obsolete_type_string(ots: like obsolete_type_string) is
  400.       do
  401.      obsolete_type_string := ots;
  402.       end;
  403.    
  404.    set_invariant(sp: POSITION; hc: COMMENT; al: ARRAY[ASSERTION]) is
  405.       do
  406.      if hc /= Void or else al /= Void then
  407.         !!invariant_assertion.make(sp,hc,al);
  408.      end;     
  409.       end;
  410.       
  411.    get_started is
  412.       do
  413.      id := id_provider.item(base_class_name.to_string);
  414.      if feature_clause_list /= Void then
  415.         feature_clause_list.get_started(feature_dictionary);
  416.      end;
  417.      if parent_list /= Void then
  418.         parent_list.get_started;
  419.      end;
  420.      if end_comment /= Void then 
  421.         end_comment.good_end(base_class_name);
  422.      end;
  423.      if parent_list /= Void then
  424.         visited.clear;
  425.         visited.add_last(Current);
  426.         parent_list.inherit_cycle_check;
  427.      end;
  428.      if run_control.all_check and then
  429.         is_deferred and then
  430.         creation_clause_list /= Void 
  431.       then
  432.         eh.add_position(base_class_name.start_position);
  433.         warning(creation_clause_list.start_position,
  434.             "Deferred class should not have %
  435.             %creation clause (VGCP.1).");
  436.      end;
  437.       end;
  438.  
  439. feature 
  440.  
  441.    get_copy: E_FEATURE is
  442.       require
  443.      feature_dictionary.has(us_copy)
  444.       do
  445.      Result := feature_dictionary.at(us_copy);
  446.       ensure
  447.      Result /= Void
  448.       end;
  449.    
  450.    clients_for(fn: FEATURE_NAME): CLIENT_LIST is
  451.      -- Looking up for the clients list when calling
  452.      -- feature `fn' with some object from current class.
  453.      -- Assume `fn' exists.
  454.       require
  455.      has(fn)
  456.       do
  457.      if proper_has(fn) then
  458.         Result := feature_dictionary.at(fn.to_key).clients;
  459.      elseif is_general then
  460.      elseif parent_list = Void then
  461.         Result := class_any.clients_for(fn);
  462.      else
  463.         check
  464.            parent_list.count >= 1
  465.         end;
  466.         Result := parent_list.clients_for(fn);
  467.      end;
  468.       ensure
  469.      Result /= Void
  470.       end;
  471.       
  472.    has_creation_clause: BOOLEAN is
  473.       do
  474.      Result := creation_clause_list /= Void; 
  475.       end;
  476.    
  477.    has_creation(proc_name: FEATURE_NAME): BOOLEAN is
  478.      -- Is `proc_name' the name of a creation procedure ?
  479.      -- Also check that `proc_name' is written in an allowed 
  480.      -- base class for creation.
  481.       require
  482.      proc_name.origin_base_class /= Void
  483.       local
  484.      cc: CREATION_CLAUSE;
  485.      bc: BASE_CLASS;
  486.      cn: CLASS_NAME;
  487.       do
  488.      if creation_clause_list = Void then
  489.         eh.append(base_class_name.to_string);
  490.         eh.append(" has no creation clause.");
  491.         eh.add_position(proc_name.start_position);
  492.         eh.print_as_error;
  493.      else
  494.         cc := creation_clause_list.get_clause(proc_name); 
  495.         if cc = Void then
  496.            eh.append(fz_09);
  497.            eh.append(proc_name.to_string);
  498.            eh.append("%" does not belong to a creation clause of ");
  499.            eh.append(base_class_name.to_string);
  500.            error(proc_name.start_position,fz_dot);
  501.         else
  502.            Result := true;
  503.            bc := proc_name.origin_base_class;
  504.            if bc /= Void then
  505.           cn := bc.base_class_name;
  506.           Result := cc.clients.gives_permission_to(cn);
  507.            end;
  508.         end;
  509.      end;
  510.      if not Result then
  511.         error(proc_name.start_position,"Creation Call not allowed.");
  512.      end;
  513.       end;
  514.    
  515.    root_procedure(proc_name: STRING): PROCEDURE is
  516.      -- Look for the root procedure to start execution here. 
  517.      -- Do some checking on the root class (not deferred, not generic, 
  518.      -- really has `proc_name' as a creation procedure etc.).
  519.      -- Return Void and print errors if needed.
  520.       require
  521.      proc_name /= Void;
  522.       local
  523.      rc: RUN_CLASS;
  524.      f: E_FEATURE;
  525.       do
  526.      if is_generic then
  527.         eh.append(base_class_name.to_string);
  528.         eh.append(" cannot be a root class since it is a generic class.");
  529.         eh.print_as_fatal_error;
  530.      end;
  531.      if is_deferred then
  532.         eh.append(base_class_name.to_string);
  533.         eh.append(" cannot be a root class since it is a deferred class.");
  534.         eh.print_as_fatal_error;
  535.      end;
  536.      mem_rpn.make(proc_name,base_class_name.start_position);
  537.      if not has_creation(mem_rpn) then
  538.         eh.append(base_class_name.to_string);
  539.         eh.extend('/');
  540.         eh.append(proc_name);
  541.         eh.append(" is not a Valid Root.");
  542.         eh.print_as_fatal_error;
  543.      end;
  544.      if not has_feature(proc_name) then
  545.         eh.append(base_class_name.to_string);
  546.         eh.append(" has no feature ");
  547.         eh.append(proc_name);
  548.         eh.append(". Invalid Root.");
  549.         eh.print_as_fatal_error;
  550.      end;
  551.      rc := run_class;
  552.      rc.set_at_run_time;
  553.      f := look_up_for(rc,mem_rpn);
  554.      if f = Void then
  555.         eh.append("Root procedure %"");
  556.         eh.append(proc_name);
  557.         fatal_error("%" not found.");
  558.      end;
  559.      Result ?= f;
  560.      if Result = Void then
  561.         eh.add_position(f.start_position);
  562.         fatal_error("Invalid Root (not a procedure).");
  563.      end;
  564.       end;
  565.    
  566.    run_class: RUN_CLASS is
  567.       local
  568.      rcd: DICTIONARY[RUN_CLASS,STRING];
  569.      name: STRING;
  570.      type: TYPE_CLASS;
  571.       do
  572.      name := base_class_name.to_string;
  573.      if not is_deferred and then not is_generic then
  574.         rcd := small_eiffel.run_class_dictionary;
  575.         if rcd.has(name) then
  576.            Result := rcd.at(name);
  577.         else
  578.            !!type.make(base_class_name);
  579.            Result := type.run_class;
  580.         end;
  581.      else
  582.         error(Void,"BASE_CLASS / does_not_understand.");
  583.      end;     
  584.       end;
  585.    
  586.    current_type: TYPE is
  587.       do
  588.      Result := run_class.current_type;
  589.       end;
  590.       
  591.    is_generic: BOOLEAN is
  592.      -- When class is defined with generic arguments.
  593.       do
  594.      Result := formal_generic_list /= Void;
  595.       end;
  596.    
  597.    proper_has(fn: FEATURE_NAME): BOOLEAN is
  598.      -- True when `fn' is really written in current class. 
  599.       do
  600.      Result := feature_dictionary.has(fn.to_key);
  601.       end; 
  602.    
  603.    is_subclass_of(other: BASE_CLASS): BOOLEAN is
  604.      -- Is Current a subclass of `other' ?
  605.       require
  606.      other /= Current
  607.       do
  608.      if isom.fast_has(other) then
  609.         Result := true;
  610.      else
  611.         if other.is_any then
  612.            Result := true;
  613.         else
  614.            visited.clear; 
  615.            Result := is_subclass_of_aux(other);
  616.         end;
  617.         if Result then
  618.            isom.add_last(other);
  619.         end;
  620.      end;
  621.       end;
  622.    
  623. feature {NONE}
  624.  
  625.    isom: ARRAY[BASE_CLASS];
  626.      -- Memorize results to speed ud `is_subclass_of'.
  627.  
  628.    visited: ARRAY[BASE_CLASS] is
  629.      -- List of all visited classes to detects loops during 
  630.      -- `is_subclass_of' processing.
  631.       once
  632.      !!Result.make(1,20);
  633.       end;
  634.  
  635. feature {PARENT_LIST,BASE_CLASS}
  636.    
  637.    inherit_cycle_check is
  638.       local
  639.      i: INTEGER;
  640.       do
  641.      visited.add_last(Current);
  642.      if visited.first = Current then
  643.         eh.append("Cyclic inheritance graph : ");
  644.         from
  645.            i := 1;
  646.         until
  647.            i > visited.upper
  648.         loop
  649.            eh.append(visited.item(i).base_class_name.to_string);
  650.            if i < visited.upper then
  651.           eh.append(", ");
  652.            end;
  653.            i := i + 1;
  654.         end;
  655.         fatal_error(", ...");
  656.      elseif parent_list /= Void then
  657.         parent_list.inherit_cycle_check;
  658.      end;
  659.       end;
  660.    
  661.    is_subclass_of_aux(c: BASE_CLASS): BOOLEAN is
  662.       require
  663.      not c.is_any;
  664.      Current /= c
  665.       do
  666.      if visited.fast_has(Current) then
  667.      else
  668.         visited.add_last(Current);
  669.         if parent_list /= Void then
  670.            Result := parent_list.has_parent(c);
  671.         elseif not visited.fast_has(class_any) then
  672.            Result := class_any.is_subclass_of_aux(c);
  673.         end;
  674.      end;
  675.       end;
  676.  
  677. feature 
  678.       
  679.    is_any: BOOLEAN is
  680.       do
  681.      Result := us_any = base_class_name.to_string;
  682.       end;
  683.       
  684.    is_general: BOOLEAN is
  685.       do
  686.      Result := us_general = base_class_name.to_string;
  687.       end;
  688.       
  689.    has_redefine(fn: FEATURE_NAME): BOOLEAN is
  690.       require
  691.      fn /= Void
  692.       do
  693.      if parent_list /= Void then
  694.         Result := parent_list.has_redefine(fn)
  695.      end;
  696.       end;
  697.    
  698.    has(fn: FEATURE_NAME): BOOLEAN is
  699.      -- Simple (and speed) look_up to see if `fn' exists here.
  700.       require
  701.      fn /= Void
  702.       do
  703.      if feature_dictionary.has(fn.to_key) then
  704.         Result := true;
  705.      else
  706.         Result := super_has(fn);
  707.      end;
  708.       end;
  709.    
  710.    has_feature(n: STRING): BOOLEAN is
  711.      -- Simple (and speed) look_up to see if one feature of name 
  712.      -- `n' exists here.
  713.       do
  714.      -- **** PB *** SI INFIX_NAME ?????
  715.      mem_fn.make(n,Void);
  716.      Result := has(mem_fn); 
  717.       end;
  718.    
  719. feature
  720.    
  721.    look_up_for(rc: RUN_CLASS; fn: FEATURE_NAME): E_FEATURE is
  722.      -- Gives Void or the good one to compute the runnable 
  723.      -- version of `fn' in `rc'.
  724.      -- All inheritance rules are checked.
  725.       local
  726.      super: E_FEATURE;
  727.      fn_key: STRING;
  728.      cst_att: CST_ATT;
  729.      fnl: FEATURE_NAME_LIST;
  730.      super_fn: like fn;
  731.      i: INTEGER;
  732.       do
  733.      fn_key := fn.to_key;
  734.      if feature_dictionary.has(fn_key) then
  735.         Result := feature_dictionary.at(fn_key);
  736.         super :=  super_look_up_for(rc,fn);
  737.         if super /= Void then
  738.            cst_att ?= super;
  739.            if cst_att /= Void then
  740.           eh.add_position(super.start_position);
  741.           eh.add_position(Result.start_position);
  742.           fatal_error("Constant feature cannot be redefined.");
  743.            end;
  744.            from  
  745.           fnl := super.names;
  746.           i := fnl.count;
  747.            until
  748.           i < 1
  749.            loop
  750.           super_fn := fnl.item(i)
  751.           if super_fn.is_frozen then
  752.              if super_fn.to_key = fn_key then
  753.             eh.add_position(super_fn.start_position);
  754.             eh.add_position(Result.start_position);
  755.             fatal_error("Cannot redefine a frozen feature.");
  756.              end;
  757.           end;
  758.           i := i - 1;
  759.            end;
  760.            if not Result.can_hide(super,rc) then
  761.           eh.add_position(super.start_position);
  762.           eh.add_position(Result.start_position);
  763.           eh.append("Incompatible headings for redefinition.");
  764.           eh.print_as_warning;
  765.            end;
  766.            if super.is_deferred then
  767.            elseif has_redefine(fn) then
  768.            else
  769.           eh.add_position(Result.start_position);
  770.           eh.add_position(super.start_position);
  771.           eh.append("Invalid redefinition in ");
  772.           eh.append(base_class_name.to_string);
  773.           eh.append(". Missing redefine ?");
  774.           eh.print_as_error;
  775.            end;
  776.         end;
  777.      else
  778.         Result := super_look_up_for(rc,fn);
  779.      end;
  780.       end;
  781.    
  782. feature {NONE}   
  783.    
  784.    super_look_up_for(rc: RUN_CLASS; fn: FEATURE_NAME): E_FEATURE is
  785.      -- Same work as `look_up_for' but do not look in current 
  786.      -- base class.
  787.       require
  788.      rc /= Void;
  789.      fn /= Void;
  790.       do
  791.      if parent_list = Void then
  792.         if is_general then
  793.            Result := Void;
  794.         else
  795.            Result := class_any.look_up_for(rc,fn);
  796.         end;
  797.      else
  798.         Result := parent_list.look_up_for(rc,fn);
  799.      end;
  800.       end;
  801.    
  802. feature {RUN_CLASS,PARENT_LIST}
  803.    
  804.    collect_invariant(rc: RUN_CLASS) is
  805.       require
  806.      rc /= Void;
  807.       do
  808.      if parent_list /= Void then
  809.         parent_list.collect_invariant(rc);
  810.      end;
  811.      if invariant_assertion /= Void then
  812.         rc.collect_invariant(invariant_assertion);
  813.      end;
  814.       end;
  815.       
  816. feature {CLASS_INVARIANT,PARENT_LIST}
  817.  
  818.    header_comment_for(ci: CLASS_INVARIANT) is
  819.       local
  820.      ia: like invariant_assertion;
  821.       do
  822.      ia := invariant_assertion;
  823.      if ia /= Void and then ia.header_comment /= Void then
  824.         ci.set_header_comment(ia.header_comment);
  825.      elseif parent_list /= Void then
  826.         parent_list.header_comment_for(ci);
  827.      end;
  828.       end;
  829.  
  830. feature {E_FEATURE,BASE_CLASS,PARENT}
  831.    
  832.    collect_for(code: INTEGER; fn: FEATURE_NAME) is
  833.       require
  834.      code = code_require or else code = code_ensure;
  835.      fn /= Void;
  836.       local
  837.      fn_key: STRING;
  838.       do
  839.      fn_key := fn.to_key;
  840.      if feature_dictionary.has(fn_key) then
  841.         feature_dictionary.at(fn_key).collect_for(code);
  842.      end;
  843.      if parent_list = Void then
  844.         if is_general then
  845.         else
  846.            class_any.collect_for(code,fn);
  847.         end;
  848.      else
  849.         parent_list.collect_for(code,fn);
  850.      end;
  851.       end;
  852.    
  853. feature {NONE}   
  854.    
  855.    mem_fn: SIMPLE_FEATURE_NAME is
  856.       once
  857.      !!Result.make("foo :-)",Void);
  858.       end;
  859.    
  860.    mem_rpn: SIMPLE_FEATURE_NAME is
  861.       once
  862.      !!Result.make("make",Void);
  863.       end;
  864.    
  865. feature {BASE_CLASS}
  866.    
  867.    super_has(fn: FEATURE_NAME): BOOLEAN is
  868.       do
  869.      if parent_list = Void then
  870.         if is_general then
  871.            Result := false;
  872.         else
  873.            Result := class_any.has(fn);
  874.         end;
  875.      else
  876.         Result := parent_list.has(fn);
  877.      end;
  878.       end;
  879.    
  880. feature 
  881.    
  882.    pretty_print is
  883.       do
  884.      fmt.set_indent_level(0);
  885.      if index_list /= Void then
  886.         index_list.pretty_print;
  887.         fmt.indent;
  888.      end;
  889.      if heading_comment1 /= Void then
  890.         heading_comment1.pretty_print;
  891.         fmt.indent;
  892.      end;
  893.      if is_deferred then
  894.         fmt.keyword("deferred");
  895.      elseif is_expanded then
  896.         fmt.keyword(fz_expanded);
  897.      end;
  898.      fmt.keyword("class");
  899.      base_class_name.pretty_print;
  900.      if is_generic then
  901.         formal_generic_list.pretty_print;
  902.      end;
  903.      fmt.indent;
  904.      if obsolete_type_string /= Void then
  905.         fmt.keyword("obsolete");
  906.         obsolete_type_string.pretty_print;
  907.      end;
  908.      fmt.indent;
  909.      if heading_comment2 /= Void then
  910.         heading_comment2.pretty_print;
  911.      end;
  912.      if parent_list /= Void then
  913.         parent_list.pretty_print;
  914.      end;
  915.      if creation_clause_list /= Void then
  916.         creation_clause_list.pretty_print;
  917.      end;     
  918.      if feature_clause_list /= Void then
  919.         feature_clause_list.pretty_print;
  920.      end;
  921.      if invariant_assertion /= Void then
  922.         invariant_assertion.pretty_print;
  923.      end;
  924.      fmt.set_indent_level(0);
  925.      if fmt.zen_mode then
  926.         fmt.skip(0);
  927.      else
  928.         fmt.skip(1);
  929.      end;
  930.      fmt.keyword(fz_end);
  931.      if end_comment /= void and then not end_comment.dummy then
  932.         end_comment.pretty_print;
  933.      elseif not fmt.zen_mode then
  934.         fmt.put_string("-- class ");
  935.         fmt.put_string(base_class_name.to_string);
  936.      end;
  937.      fmt.put_character('%N');
  938.       end;
  939.    
  940. feature {NONE}
  941.  
  942.    error_vtec1 is 
  943.       do
  944.      error(base_class_name.start_position,
  945.            "A class cannot be expanded and deferred (VTEC.1).");
  946.       end;
  947.  
  948. feature {FEATURE_NAME,E_FEATURE}
  949.  
  950.    fatal_undefine(fn: FEATURE_NAME) is
  951.       do
  952.      eh.append("Problem with undefine of %"");
  953.      eh.append(fn.to_string);
  954.      eh.append("%" in %"");
  955.      eh.append(base_class_name.to_string);
  956.      fatal_error("%".");
  957.       end;
  958.  
  959. feature {TYPE,PARENT}
  960.  
  961.    is_a_vncg(t1, t2: TYPE): BOOLEAN is
  962.       -- Direct conformance VNCG
  963.       require
  964.      t1.is_run_type;
  965.      t2.is_run_type;
  966.      t1.base_class = Current;
  967.      t2.generic_list /= Void;
  968.      eh.empty
  969.       do
  970.      if parent_list /= Void then
  971.         Result := parent_list.is_a_vncg(t1.run_type,t2.run_type);
  972.      end;
  973.       ensure
  974.      eh.empty
  975.       end;
  976.  
  977. invariant
  978.    
  979.    path.count > 0;
  980.    
  981.    base_class_name /= Void;
  982.    
  983. end -- BASE_CLASS
  984.  
  985.  
  986.