home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_se / e_feature.e < prev    next >
Text File  |  1999-06-05  |  12KB  |  430 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. deferred class E_FEATURE
  17.    --
  18.    -- For all possible Features : procedure, function, attribute,
  19.    -- constants, once procedure, once function, ...
  20.    --
  21.  
  22. inherit GLOBALS;
  23.  
  24. feature
  25.  
  26.    base_class: BASE_CLASS;
  27.          -- The class where the feature is really written.
  28.  
  29.    names: FEATURE_NAME_LIST;
  30.          -- All the names of the feature.
  31.  
  32.    arguments: FORMAL_ARG_LIST is
  33.          -- Arguments if any.
  34.       deferred
  35.       end;
  36.  
  37.    result_type: TYPE is
  38.          -- Result type if any.
  39.       deferred
  40.       end;
  41.  
  42.    header_comment: COMMENT;
  43.          -- Header comment for a routine or following comment for
  44.          -- an attribute.
  45.  
  46.    obsolete_mark: MANIFEST_STRING is
  47.          -- The `obsolete' mark if any.
  48.       deferred
  49.       end;
  50.  
  51.    require_assertion: E_REQUIRE is
  52.          -- Not Void if any.
  53.       deferred
  54.       end;
  55.  
  56.    ensure_assertion: E_ENSURE is
  57.          -- Not Void if any.
  58.       deferred
  59.       end;
  60.  
  61.    clients: CLIENT_LIST;
  62.          -- Authorized clients list of the corresponding feature
  63.          -- clause in the base definition class.
  64.  
  65.    is_deferred: BOOLEAN is
  66.          -- Is it a deferred feature ?
  67.       deferred
  68.       end;
  69.  
  70.    frozen mapping_c_name_in(str: STRING) is
  71.       do
  72.          base_class.mapping_c_in(str);
  73.          str.append(first_name.to_key);
  74.       end;
  75.  
  76.    frozen mapping_c_name is
  77.       local
  78.          s: STRING;
  79.       do
  80.          s := "    ";
  81.          s.clear;
  82.          mapping_c_name_in(s);
  83.          cpp.put_string(s);
  84.       end;
  85.  
  86.    frozen base_class_name: CLASS_NAME is
  87.          -- Name of the class where the feature is really written.
  88.       do
  89.          Result := base_class.name;
  90.       end;
  91.  
  92.    frozen first_name: FEATURE_NAME is
  93.          -- Return the principal (first) name of the feature.
  94.       do
  95.          Result := names.item(1);
  96.       ensure
  97.          Result /= void
  98.       end;
  99.  
  100.    start_position: POSITION is
  101.       do
  102.          Result := first_name.start_position;
  103.       end;
  104.  
  105.    to_run_feature(t: TYPE; fn: FEATURE_NAME): RUN_FEATURE is
  106.          -- If possible, gives the checked runnable feature for `t'.
  107.          -- Note: corresponding run_class dictionary is updated
  108.          --       with this new feature.
  109.       require
  110.          t.is_run_type;
  111.          fn /= Void;
  112.       deferred
  113.       ensure
  114.          Result /= Void implies t.run_class.at(fn) = Result;
  115.          Result = Void implies nb_errors > 0
  116.       end;
  117.  
  118.    can_hide(other: E_FEATURE; rc: RUN_CLASS): BOOLEAN is
  119.          -- True when headings of Current can be hide with
  120.          -- heading of `other' in `rc'.
  121.       require
  122.          Current /= other;
  123.       do
  124.          if result_type /= other.result_type then
  125.             if result_type = Void or else other.result_type = Void then
  126.                eh.add_position(other.start_position);
  127.                error(start_position,"One has Result but not the other.");
  128.             end;
  129.          end;
  130.          if arguments /= other.arguments then
  131.             if arguments = Void or else other.arguments = Void then
  132.                eh.add_position(other.start_position);
  133.                error(start_position,"One has argument(s) but not the other.");
  134.             elseif arguments.count /= other.arguments.count then
  135.                eh.add_position(other.start_position);
  136.                error(start_position,"Incompatible number of arguments.");
  137.             end;
  138.          end;
  139.          if nb_errors = 0 then
  140.             if result_type /= Void then
  141.                if not result_type.is_a_in(other.result_type,rc) then
  142.                   eh.append(em1);
  143.                   eh.append(rc.current_type.run_time_mark);
  144.                   eh.append(fz_dot);
  145.                   eh.print_as_error;
  146.                end;
  147.             end;
  148.          end;
  149.          if nb_errors = 0 then
  150.             if arguments /= Void then
  151.                if not arguments.is_a_in(other.arguments,rc) then
  152.                   eh.add_position(other.start_position);
  153.                   eh.add_position(start_position)
  154.                   eh.append(em1);
  155.                   eh.append(rc.current_type.run_time_mark);
  156.                   eh.append(fz_dot);
  157.                   eh.print_as_error;
  158.                end;
  159.             end;
  160.          end;
  161.          Result := nb_errors = 0;
  162.          if Result then
  163.             merge_header_comments(other);
  164.          end;
  165.       end;
  166.  
  167.    frozen check_obsolete(caller: POSITION) is
  168.       require
  169.          caller /= Void
  170.       do
  171.          if obsolete_mark /= Void then
  172.             if not small_eiffel.short_flag then
  173.                eh.add_position(caller);
  174.                eh.append("This feature is obsolete :%N");
  175.                eh.append(obsolete_mark.to_string);
  176.                eh.add_position(start_position);
  177.                eh.print_as_warning;
  178.             end
  179.          end;
  180.       end;
  181.  
  182.    set_header_comment(hc: like header_comment) is
  183.       do
  184.          header_comment := hc;
  185.       end;
  186.  
  187.    pretty_print is
  188.       require
  189.          fmt.indent_level = 1;
  190.       deferred
  191.       ensure
  192.          fmt.indent_level = 1;
  193.       end;
  194.  
  195.    frozen pretty_print_profile is
  196.       do
  197.          pretty_print_names;
  198.          fmt.set_indent_level(2);
  199.          pretty_print_arguments;
  200.          fmt.set_indent_level(3);
  201.          if result_type /= Void then
  202.             fmt.put_string(": ");
  203.             result_type.pretty_print;
  204.          end;
  205.       end;
  206.  
  207. feature {PARENT_LIST}
  208.  
  209.    frozen is_merge_with(other: E_FEATURE; rc: RUN_CLASS): BOOLEAN is
  210.          -- True when headings of Current can be merge with heading
  211.          -- of `other' in `rc'.
  212.       require
  213.          Current /= other;
  214.          eh.empty
  215.       do
  216.          Result := is_merge_with1(other);
  217.          if Result then
  218.             if is_deferred then
  219.                if other.is_deferred then
  220.                else
  221.                   Result := is_merge_with2(other,rc);
  222.                end;
  223.             else
  224.                Result := is_merge_with2(other,rc);
  225.             end;
  226.             if Result then
  227.                merge_header_comments(other);
  228.             end;
  229.          end;
  230.       ensure
  231.          Result = eh.empty
  232.       end;
  233.  
  234. feature {PARENT}
  235.  
  236.    frozen try_to_undefine(fn: FEATURE_NAME; bc: BASE_CLASS):
  237.       DEFERRED_ROUTINE is
  238.          -- Compute the corresponding deferred feature for `Current'.
  239.          -- This occurs for example when `bc' has an undefine clause 
  240.          -- for `fn' which refer to `Current'.
  241.          -- The Result is never Void because `fatal_error' may be called. 
  242.          -- Also check VDUS.
  243.       require
  244.          fn /= Void;
  245.          bc.name.is_subclass_of(base_class_name)
  246.       local
  247.          fn2: FEATURE_NAME;
  248.       do
  249.          -- For (VDUS) :
  250.          eh.add_position(fn.start_position);
  251.          fn2 :=  names.feature_name(fn.to_key);
  252.          if fn2 /= Void then
  253.             fn2.undefine_in(bc);
  254.          end;
  255.          eh.cancel;
  256.          --
  257.          Result := try_to_undefine_aux(fn,bc);
  258.          if Result /= Void then
  259.             Result.set_clients(clients);
  260.             merge_header_comments(Result);
  261.          else
  262.             bc.fatal_undefine(fn);
  263.          end;
  264.       ensure
  265.          Result /= Void
  266.       end;
  267.  
  268. feature {FEATURE_CLAUSE,E_FEATURE}
  269.  
  270.    set_clients(c: like clients) is
  271.       require
  272.          c /= Void;
  273.       do
  274.          clients := c;
  275.       ensure
  276.          clients = c;
  277.       end;
  278.  
  279. feature {FEATURE_CLAUSE}
  280.  
  281.    add_into(fd: DICTIONARY[E_FEATURE,STRING]) is
  282.          -- Also check for multiple definitions.
  283.       local
  284.          i: INTEGER;
  285.          fn: FEATURE_NAME;
  286.       do
  287.          base_class := names.item(1).start_position.base_class;
  288.          from
  289.             i := 1;
  290.          until
  291.             i > names.count
  292.          loop
  293.             fn := names.item(i);
  294.             if fd.has(fn.to_key) then
  295.                fn := fd.at(fn.to_key).first_name;
  296.                eh.add_position(fn.start_position);
  297.                eh.add_position(names.item(i).start_position);
  298.                eh.append("Double definition of feature ");
  299.                eh.append(fn.to_string);
  300.                eh.append(fz_dot);
  301.                eh.print_as_error;
  302.             else
  303.                fd.put(Current,fn.to_key);
  304.             end;
  305.             i := i + 1;
  306.          end;
  307.       end;
  308.  
  309. feature {C_PRETTY_PRINTER}
  310.  
  311.    stupid_switch(up_rf: RUN_FEATURE; r: ARRAY[RUN_CLASS]): BOOLEAN is
  312.          -- True when it is stupid to perform such a switch.
  313.          -- Assume all `base_feature' of `r' is Current.
  314.       require
  315.          run_control.boost;
  316.          small_eiffel.is_ready;
  317.          up_rf.base_feature = Current;
  318.          up_rf.run_class.running = r;
  319.          r.count > 1
  320.       deferred
  321.       end;
  322.  
  323. feature {E_FEATURE}
  324.  
  325.    frozen is_merge_with2aux(other: E_FEATURE; rc: RUN_CLASS): BOOLEAN is
  326.       do
  327.          Result := true;
  328.          if result_type /= Void then
  329.             Result := result_type.is_a_in(other.result_type,rc);
  330.          end;
  331.          if Result and then arguments /= Void then
  332.             Result := arguments.is_a_in(other.arguments,rc);
  333.          end;
  334.       end;
  335.  
  336. feature {NONE}
  337.  
  338.    frozen pretty_print_names is
  339.          -- Print only the names of the feature.
  340.       local
  341.          i: INTEGER;
  342.       do
  343.          from
  344.             i := 1;
  345.             names.item(i).declaration_pretty_print;
  346.             i := i + 1;
  347.          until
  348.             i > names.count
  349.          loop
  350.             fmt.put_string(", ");
  351.             names.item(i).declaration_pretty_print;
  352.             i := i + 1;
  353.          end;
  354.       end;
  355.  
  356.    pretty_print_arguments is
  357.       deferred
  358.       end;
  359.  
  360.    make_e_feature(n: like names) is
  361.       require
  362.          n.count >= 1;
  363.       do
  364.          names := n;
  365.       ensure
  366.          names = n
  367.       end;
  368.  
  369.    try_to_undefine_aux(fn: FEATURE_NAME;
  370.                        bc: BASE_CLASS): DEFERRED_ROUTINE is
  371.       require
  372.          fn /= Void;
  373.          bc /= Void
  374.       deferred
  375.       end;
  376.  
  377.    em1: STRING is " Cannot inherit these features in "
  378.  
  379.    frozen merge_header_comments(other: E_FEATURE) is
  380.          -- Falling down of the `header_comment' for command short.
  381.       do
  382.          if small_eiffel.short_flag then
  383.             if header_comment = Void then
  384.                header_comment := other.header_comment;
  385.             elseif other.header_comment = Void then
  386.                other.set_header_comment(header_comment);
  387.             end;
  388.          end;
  389.       end;
  390.  
  391.    frozen is_merge_with1(other: E_FEATURE): BOOLEAN is
  392.          -- Step 1 : check for the number of arguments and
  393.          -- for the existance of a result type.
  394.       require
  395.          Current /= other;
  396.          eh.empty
  397.       do
  398.          if result_type = Void then
  399.             Result := other.result_type = Void;
  400.          else
  401.             Result := other.result_type /= Void;
  402.          end;
  403.          if Result then
  404.             if arguments = Void then
  405.                Result := other.arguments = Void;
  406.             else
  407.                Result := other.arguments /= Void;
  408.             end;
  409.          end;
  410.       ensure
  411.          Result = eh.empty
  412.       end;
  413.  
  414.    frozen is_merge_with2(other: E_FEATURE; rc: RUN_CLASS): BOOLEAN is
  415.          -- Step 2 : check for arguments/result compatibility.
  416.       do
  417.          Result := is_merge_with2aux(other,rc);
  418.          if not Result then
  419.             eh.cancel;
  420.             Result := other.is_merge_with2aux(Current,rc);
  421.          end;
  422.       end;
  423.  
  424. invariant
  425.  
  426.    names /= Void;
  427.  
  428. end -- E_FEATURE
  429.  
  430.