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