home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_se / run_class.e < prev    next >
Text File  |  1999-06-05  |  49KB  |  1,768 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 RUN_CLASS
  17.    --
  18.    -- Only for class with objects at execution time.
  19.    --
  20.  
  21. inherit GLOBALS;
  22.  
  23. creation {SMALL_EIFFEL} make
  24.  
  25. feature
  26.  
  27.    current_type: TYPE;
  28.          -- Runnable corresponding one.
  29.  
  30.    id: INTEGER;
  31.          -- Id of the receiver to produce C code.
  32.  
  33.    at_run_time: BOOLEAN;
  34.          -- True if `current_type' is really created (only when
  35.          -- direct instances of `current_type' exists at run time).
  36.  
  37.    running: ARRAY[RUN_CLASS];
  38.          -- Void or the set of all `at_run_time' directly compatible
  39.          -- run classes. A run class is directly compatible with one
  40.          -- another only when it can be directly substitute with
  41.          -- current run class.
  42.          -- Thus, if current run class is reference, `running' are all
  43.          -- reference run classes. If current run class is expanded,
  44.          -- `running' has only one element (the current class itself).
  45.  
  46.    class_invariant: CLASS_INVARIANT;
  47.          -- Collected Runnable invariant if any.
  48.  
  49.    compile_to_c_done: BOOLEAN;
  50.          -- True if `compile_to_c' has already be called.
  51.  
  52. feature {RUN_CLASS}
  53.  
  54.    feature_dictionary: DICTIONARY[RUN_FEATURE,STRING];
  55.          -- Access to the runnable version of a feature.
  56.          -- To avoid clash between infix and prefix names,
  57.          -- `to_key' of class NAME is used as entry.
  58.  
  59. feature {NONE}
  60.  
  61.    tagged_mem: INTEGER;
  62.          -- 0 when not computed, 1 when tagged or -1
  63.  
  64. feature {NONE}
  65.  
  66.    make(t: like current_type) is
  67.       require
  68.          t.run_type = t
  69.       local
  70.          run_string: STRING;
  71.          rcd: DICTIONARY[RUN_CLASS,STRING];
  72.          rc: RUN_CLASS;
  73.          i: INTEGER;
  74.       do
  75.          compile_to_c_done := true;
  76.          current_type := t;
  77.          !!actuals_clients.with_capacity(16);
  78.          run_string := t.run_time_mark;
  79.          id := id_provider.item(run_string);
  80.          check
  81.             not small_eiffel.run_class_dictionary.has(run_string);
  82.          end;
  83.          small_eiffel.run_class_dictionary.put(Current,run_string);
  84.          !!feature_dictionary.make;
  85.          small_eiffel.incr_magic_count;
  86.          if t.is_expanded then
  87.             set_at_run_time;
  88.             t.base_class.check_expanded_with(t);
  89.          else
  90.             from
  91.                rcd := small_eiffel.run_class_dictionary;
  92.                i := 1;
  93.             until
  94.                i > rcd.count
  95.             loop
  96.                rc := rcd.item(i);
  97.                if rc.at_run_time and then
  98.                   rc.current_type.is_reference and then
  99.                   rc.is_running_of(Current)
  100.                 then
  101.                   add_running(rc);
  102.                end;
  103.                i := i + 1;
  104.             end;
  105.          end;
  106.       ensure
  107.          current_type = t
  108.       end;
  109.  
  110. feature
  111.  
  112.    is_tagged: BOOLEAN is
  113.       require
  114.          small_eiffel.is_ready
  115.       do
  116.          if tagged_mem = 0 then
  117.             if current_type.is_expanded then
  118.                tagged_mem := -1;
  119.             elseif at_run_time then
  120.                if run_control.boost then
  121.                   if small_eiffel.is_tagged(Current) then
  122.                      tagged_mem := 1;
  123.                   else
  124.                      tagged_mem := -1;
  125.                   end;
  126.                else
  127.                   tagged_mem := 1;
  128.                end;
  129.             end;
  130.          end;
  131.          Result := tagged_mem = 1;
  132.       ensure
  133.          tagged_mem /= 0
  134.       end;
  135.  
  136.    is_expanded: BOOLEAN is
  137.       do
  138.          Result := current_type.is_expanded;
  139.       end;
  140.  
  141.    writable_attributes: ARRAY[RUN_FEATURE_2] is
  142.          -- Computed and ordered array of writable attributes.
  143.          -- Storage in C struct is to be done in reverse
  144.          -- order (from `upper' to `lower').
  145.          -- Order is done according to the level of attribute
  146.          -- definition in the inheritance graph to allow more
  147.          -- stupid switch to be removed.
  148.       require
  149.          small_eiffel.is_ready;
  150.          at_run_time
  151.       local
  152.          rf2: RUN_FEATURE_2;
  153.          i: INTEGER;
  154.       do
  155.          if writable_attributes_mem = Void then
  156.             from
  157.                i := 1;
  158.             until
  159.                i > feature_dictionary.count
  160.             loop
  161.                rf2 ?= feature_dictionary.item(i);
  162.                if rf2 /= Void then
  163.                   if writable_attributes_mem = Void then
  164.                      writable_attributes_mem := <<rf2>>;
  165.                   else
  166.                      writable_attributes_mem.add_last(rf2);
  167.                   end;
  168.                end;
  169.                i := i + 1;
  170.             end;
  171.             if writable_attributes_mem /= Void then
  172.                sort_wam(writable_attributes_mem);
  173.             end;
  174.          end;
  175.          Result := writable_attributes_mem;
  176.       ensure
  177.          Result /= Void implies Result.lower = 1
  178.       end;
  179.  
  180.    is_running_of(other: like Current): BOOLEAN is
  181.          -- Can the Current RUN_CLASS be used in place of `other'.
  182.       require
  183.          other /= Void
  184.       local
  185.          t1, t2: TYPE;
  186.       do
  187.          if other = Current then
  188.             Result := true;
  189.          else
  190.             t1 := current_type;
  191.             t2 := other.current_type;
  192.             if t1.is_basic_eiffel_expanded and then
  193.                t2.is_basic_eiffel_expanded then
  194.             else
  195.                Result := t1.is_a(t2);
  196.                if not Result then
  197.                   eh.cancel;
  198.                end;
  199.             end;
  200.          end;
  201.       ensure
  202.          nb_errors = old nb_errors
  203.       end;
  204.  
  205. feature -- For implicit conversion from expanded to reference :
  206.  
  207.    used_as_reference is
  208.       require
  209.          current_type.is_expanded;
  210.          not current_type.is_basic_eiffel_expanded
  211.       local
  212.          rtm: STRING;
  213.          type_ref_to_exp: TYPE_REF_TO_EXP;
  214.       do
  215.          rtm := current_type.run_time_mark;
  216.          if not to_reference_memory.has(rtm) then
  217.             !!type_ref_to_exp.make(current_type);
  218.             to_reference_memory.put(type_ref_to_exp,rtm);
  219.          end;
  220.       end;
  221.  
  222.    to_reference: TYPE is
  223.       do
  224.          Result := to_reference_memory.at(current_type.run_time_mark);
  225.       end;
  226.  
  227. feature {TYPE}
  228.  
  229.    jvm_to_reference is
  230.          -- Produce code to convert the pushed expanded into the
  231.          -- corresponding TYPE_REF_TO_EXP type.
  232.       require
  233.          current_type.is_expanded
  234.       local
  235.          ref_type: TYPE;
  236.       do
  237.          ref_type := to_reference;
  238.          ref_type.run_class.jvm_reference_from(current_type);
  239.       end;
  240.  
  241. feature {RUN_CLASS}
  242.  
  243.    jvm_reference_from(exp_type: TYPE) is
  244.       require
  245.          exp_type.is_expanded
  246.       local
  247.          idx: INTEGER;
  248.          ca: like code_attribute;
  249.          cp: like constant_pool;
  250.       do
  251.          ca := code_attribute;
  252.          cp := constant_pool;
  253.          idx := jvm_constant_pool_index;
  254.          ca.opcode_new(idx);
  255.          ca.opcode_dup;
  256.          idx := cp.idx_methodref1(idx,fz_35,fz_29);
  257.          ca.opcode_invokespecial(idx,-1);
  258.          ca.opcode_dup_x1;
  259.          ca.opcode_swap;
  260.          tmp_string.clear;
  261.          exp_type.jvm_descriptor_in(tmp_string);
  262.          idx := cp.idx_fieldref3(fully_qualified_name,as_item,tmp_string);
  263.          ca.opcode_putfield(idx,-2);
  264.       end;
  265.  
  266. feature {TYPE_LIKE_FEATURE}
  267.  
  268.    get_result_type(fn: FEATURE_NAME): TYPE is
  269.          -- Computes only the result type of `fn' when this feature
  270.          -- is not yet runnable.
  271.          -- Possible rename is also done using the `start_position' of
  272.          -- `fn'. No return when an error occurs because `fatal_error'
  273.          -- is called.
  274.       require
  275.          not small_eiffel.is_ready
  276.       local
  277.          fn2: FEATURE_NAME;
  278.          wbc: BASE_CLASS;
  279.          rf: RUN_FEATURE;
  280.          fn2_key: STRING;
  281.          f: E_FEATURE;
  282.          bc: BASE_CLASS;
  283.       do
  284.          wbc := fn.start_position.base_class;
  285.          fn2 := base_class.new_name_of(wbc,fn);
  286.          fn2_key := fn2.to_key;
  287.          if feature_dictionary.has(fn2_key) then
  288.             rf := feature_dictionary.at(fn2_key);
  289.             Result := rf.result_type;
  290.             if Result.is_run_type then
  291.                Result := Result.run_type;
  292.             else
  293.                Result := Result.to_runnable(current_type);
  294.                Result := Result.run_type;
  295.             end;
  296.          else
  297.             bc := base_class;
  298.             f := bc.look_up_for(Current,fn2);
  299.             if f = Void then
  300.                efnf(bc,fn2);
  301.                eh.add_position(fn.start_position);
  302.                eh.add_position(fn2.start_position);
  303.                fatal_error(" Anchor not found.");
  304.             else
  305.                Result := f.result_type;
  306.                if Result = Void  then
  307.                   eh.add_position(f.start_position);
  308.                   eh.add_position(fn.start_position);
  309.                   eh.add_position(fn2.start_position);
  310.                   fatal_error(" Anchor found is a procedure.");
  311.                else
  312.                   Result := Result.to_runnable(current_type);
  313.                   Result := Result.run_type;
  314.                end;
  315.             end;
  316.          end;
  317.       ensure
  318.          Result = Result.run_type
  319.       end;
  320.  
  321. feature
  322.  
  323.    get_rf_with(fn: FEATURE_NAME): RUN_FEATURE is
  324.          -- Compute or simply fetch the corresponding RUN_FEATURE.
  325.          -- Possible rename are also done using `start_position' of
  326.          -- `fn'. No return when an error occurs because `fatal_error'
  327.          -- is called.
  328.       require
  329.          base_class = fn.start_position.base_class or else
  330.          base_class.is_subclass_of(fn.start_position.base_class)
  331.       local
  332.          fn2: FEATURE_NAME;
  333.          wbc: BASE_CLASS;
  334.       do
  335.          wbc := fn.start_position.base_class;
  336.          fn2 := base_class.new_name_of(wbc,fn);
  337.          if fn2 /= fn then
  338.             eh.add_position(fn.start_position);
  339.             Result := get_or_fatal_error(fn2);
  340.             eh.cancel;
  341.          else
  342.             Result := get_or_fatal_error(fn2);
  343.          end;
  344.       ensure
  345.          Result /= Void
  346.       end;
  347.  
  348.    dynamic(up_rf: RUN_FEATURE): RUN_FEATURE is
  349.          -- Assume the current type of `up_rf' is a kind of
  350.          -- `current_type'. The result is the concrete one
  351.          -- according to dynamic dispatch rules.
  352.       require
  353.          up_rf /= Void;
  354.          is_running_of(up_rf.run_class)
  355.       local
  356.          fn, up_fn: FEATURE_NAME;
  357.          up_type: TYPE;
  358.       do
  359.          up_type := up_rf.current_type;
  360.          if Current = up_type.run_class then
  361.             Result := up_rf;
  362.          else
  363.             up_fn := up_rf.name;
  364.             fn := base_class.new_name_of(up_type.base_class,up_fn);
  365.             Result := get_or_fatal_error(fn);
  366.          end;
  367.       ensure
  368.          Result /= Void;
  369.          Result.run_class = Current;
  370.       end;
  371.  
  372. feature
  373.  
  374.    base_class: BASE_CLASS is
  375.          -- Corresponding base class.
  376.       do
  377.          Result := current_type.base_class;
  378.       ensure
  379.          Result /= Void
  380.       end;
  381.  
  382.    base_class_name: CLASS_NAME is
  383.          -- Corresponding base class name.
  384.       do
  385.          Result := current_type.base_class_name;
  386.       ensure
  387.          Result /= Void
  388.       end;
  389.  
  390. feature
  391.  
  392.    set_at_run_time is
  393.          -- Set Current `at_run_time' and do needed update of others
  394.          -- instances of RUN_CLASS.
  395.       require
  396.          not base_class.is_deferred
  397.       local
  398.          rcd: DICTIONARY[RUN_CLASS,STRING];
  399.          rc: RUN_CLASS;
  400.          i: INTEGER;
  401.       do
  402.          if not at_run_time  then
  403.             check
  404.                not small_eiffel.is_ready
  405.             end;
  406.             at_run_time := true;
  407.             compile_to_c_done := false;
  408.             add_running(Current);
  409.             small_eiffel.incr_magic_count;
  410.             if current_type.is_reference then
  411.                from
  412.                   rcd := small_eiffel.run_class_dictionary;
  413.                   i := 1;
  414.                until
  415.                   i > rcd.count
  416.                loop
  417.                   rc := rcd.item(i);
  418.                   if Current.is_running_of(rc) then
  419.                      rc.add_running(Current);
  420.                   end;
  421.                   i := i + 1;
  422.                end;
  423.             end;
  424.          end;
  425.       ensure
  426.          at_run_time;
  427.          running.has(Current)
  428.       end;
  429.  
  430. feature {TYPE}
  431.  
  432.    gc_mark_to_follow: BOOLEAN is
  433.       -- *** TO REMOVE ***
  434.       local
  435.          i: INTEGER;
  436.          r: like running;
  437.          rc: like Current;
  438.       do
  439.          r := running;
  440.          if r /= Void then
  441.             from
  442.                i := r.upper;
  443.             until
  444.                Result or else i = 0
  445.             loop
  446.                rc := r.item(i);
  447.                if rc = Current then
  448.                   Result := need_gc_mark;
  449.                else
  450.                   Result := rc.current_type.need_gc_mark_function;
  451.                end;
  452.                i := i - 1;
  453.             end;
  454.          end;
  455.       end;
  456.  
  457. feature {TYPE}
  458.  
  459.    c_print_function is
  460.       require
  461.          run_control.no_check
  462.       local
  463.          body: STRING;
  464.          ct, t: TYPE;
  465.          i: INTEGER;
  466.          wa: like writable_attributes;
  467.          rf2: RUN_FEATURE_2;
  468.       do
  469.          body := "... (to change ;-)";
  470.          ct := current_type;
  471.          tmp_string.copy("void se_prinT");
  472.          id.append_in(tmp_string);
  473.          tmp_string.append("(T");
  474.          id.append_in(tmp_string);
  475.          if ct.is_reference then
  476.             tmp_string.extend('*');
  477.          end;
  478.          tmp_string.append("*o)");
  479.          body.clear;
  480.          if ct.is_reference then
  481.             body.append("if(*o==NULL){%N%
  482.                         %fprintf(SE_ERR,%"Void%");%N%
  483.                         %return;%N}%N");
  484.          end;
  485.          body.append("fprintf(SE_ERR,%"");
  486.          body.append(ct.run_time_mark);
  487.          body.append("%");%N");
  488.          if ct.is_reference or else ct.is_native_array then
  489.             body.append("fprintf(SE_ERR,%"#%%p%",*o);%N");
  490.          end;
  491.          wa := writable_attributes;
  492.          if wa /= Void then
  493.             body.append("fprintf(SE_ERR,%"\n\t[ %");%N");
  494.             from
  495.                i := wa.upper;
  496.             until
  497.                i = 0
  498.             loop
  499.                rf2 := wa.item(i);
  500.                t := rf2.result_type;
  501.                body.append("fprintf(SE_ERR,%"");
  502.                body.append(rf2.name.to_string);
  503.                body.append(" = %");%Nse_prinT");
  504.                if t.is_expanded then
  505.                   t.id.append_in(body);
  506.                elseif t.is_string then
  507.                   body.extend('7');
  508.                else
  509.                   body.extend('0');
  510.                end;
  511.                body.append("((void*)(&((*o)");
  512.                if ct.is_reference then
  513.                   body.append("->");
  514.                else
  515.                   body.extend('.');
  516.                end;
  517.                body.extend('_');
  518.                body.append(rf2.name.to_string);
  519.                body.append(")));%N");
  520.                i := i - 1;
  521.                if i > 0 then
  522.                   body.append("fprintf(SE_ERR,%"\n\t  %");%N");
  523.                end;
  524.             end;
  525.             body.append("fprintf(SE_ERR,%"\n\t]%");%N");
  526.          end;
  527.          cpp.put_c_function(tmp_string,body);
  528.       end;
  529.  
  530.    c_object_model_in(str: STRING) is
  531.       local
  532.          wa: like writable_attributes;
  533.          i: INTEGER;
  534.          rf2: RUN_FEATURE_2;
  535.          t: TYPE;
  536.       do
  537.          wa := writable_attributes;
  538.          if wa = Void then
  539.             if is_tagged then
  540.                str.extend('{');
  541.                id.append_in(str);
  542.                str.extend('}');
  543.             else
  544.                current_type.c_initialize_in(str);
  545.             end;
  546.          else
  547.             str.extend('{');
  548.             if is_tagged then
  549.                id.append_in(str);
  550.                str.extend(',');
  551.             end;
  552.             from
  553.                i := wa.upper;
  554.             until
  555.                i = 0
  556.             loop
  557.                rf2 := wa.item(i);
  558.                t := rf2.result_type;
  559.                t.c_initialize_in(str);
  560.                i := i - 1;
  561.                if i > 0 then
  562.                   str.extend(',');
  563.                end;
  564.             end;
  565.             str.extend('}');
  566.          end;
  567.       end;
  568.  
  569. feature {SMALL_EIFFEL}
  570.  
  571.    falling_down is
  572.       -- Falling down of Current `feature_dictionary' in `running'.
  573.       local
  574.          rf: RUN_FEATURE;
  575.          i: INTEGER;
  576.       do
  577.          from
  578.             i := 1;
  579.          until
  580.             i > feature_dictionary.count
  581.          loop
  582.             rf := feature_dictionary.item(i);
  583.             rf.fall_down;
  584.             i := i + 1;
  585.          end;
  586.          prepare_strip;
  587.          gc_handler.falling_down(Current);
  588.       end;
  589.  
  590.    afd_check is
  591.          -- After Falling Down Check.
  592.       local
  593.          rf: RUN_FEATURE;
  594.          i: INTEGER;
  595.          rc: like Current;
  596.          rt: TYPE;
  597.       do
  598.          runnable_class_invariant;
  599.          from
  600.             i := 1;
  601.          until
  602.             i > feature_dictionary.count
  603.          loop
  604.             rf := feature_dictionary.item(i);
  605.             rf.afd_check;
  606.             rt := rf.result_type;
  607.             if rt /= Void then
  608.                if rt.is_none then
  609.                else
  610.                   rc := rt.run_class;
  611.                end;
  612.             end;
  613.             i := i + 1;
  614.          end;
  615.          if class_invariant /= Void then
  616.             class_invariant.afd_check;
  617.          end;
  618.       end;
  619.  
  620. feature {SHORT}
  621.  
  622.    runnable_class_invariant is
  623.       do
  624.          if not runnable_class_invariant_done then
  625.             runnable_class_invariant_done := true;
  626.             if run_control.invariant_check then
  627.                if at_run_time or else small_eiffel.short_flag then
  628.                   assertion_collector.invariant_start;
  629.                   base_class.collect_invariant(Current);
  630.                   class_invariant := assertion_collector.invariant_end(current_type);
  631.                end;
  632.             end;
  633.          end;
  634.       end;
  635.  
  636. feature
  637.  
  638.    c_header_pass1 is
  639.       require
  640.          cpp.on_h
  641.       do
  642.          if at_run_time then
  643.             if c_header_pass_level_done < 1 then
  644.                current_type.c_header_pass1;
  645.                c_header_pass_level_done := 1;
  646.             end;
  647.          end;
  648.       ensure
  649.          cpp.on_h
  650.       end;
  651.  
  652.    c_header_pass2 is
  653.       require
  654.          cpp.on_h
  655.       do
  656.          if at_run_time then
  657.             if c_header_pass_level_done < 2 then
  658.                current_type.c_header_pass2;
  659.                c_header_pass_level_done := 2;
  660.             end;
  661.          end;
  662.       ensure
  663.          cpp.on_h
  664.       end;
  665.  
  666.    c_header_pass3 is
  667.       require
  668.          cpp.on_h
  669.       local
  670.          i: INTEGER;
  671.          attribute_type: TYPE;
  672.       do
  673.          if at_run_time then
  674.             if c_header_pass_level_done < 3 then
  675.                if current_type.is_user_expanded and then
  676.                   writable_attributes /= Void
  677.                 then
  678.                   from
  679.                      i := writable_attributes.upper;
  680.                   until
  681.                      i = 0
  682.                   loop
  683.                      attribute_type := writable_attributes.item(i).result_type;
  684.                      if attribute_type.is_expanded then
  685.                         attribute_type.run_class.c_header_pass3;
  686.                      end;
  687.                      i := i - 1;
  688.                   end;
  689.                end;
  690.                current_type.c_header_pass3;
  691.                c_header_pass_level_done := 3;
  692.             end;
  693.          end;
  694.       ensure
  695.          cpp.on_h
  696.       end;
  697.  
  698.    c_header_pass4 is
  699.       require
  700.          cpp.on_h
  701.       do
  702.          if at_run_time then
  703.             if c_header_pass_level_done < 4 then
  704.                current_type.c_header_pass4;
  705.                c_header_pass_level_done := 4;
  706.             end;
  707.          end;
  708.       ensure
  709.          cpp.on_h
  710.       end;
  711.  
  712. feature {GC_HANDLER}
  713.  
  714.    get_memory_dispose: RUN_FEATURE_3 is
  715.       local
  716.          memory, bc: BASE_CLASS;
  717.       do
  718.          memory := small_eiffel.memory_class_used;
  719.          if memory /= Void then
  720.             bc := base_class;
  721.             if memory /= bc and then bc.is_subclass_of(memory) then
  722.                if bc.has_simple_feature_name(as_dispose) then
  723.                   Result ?= get_feature_with(as_dispose);
  724.                   if Result /= Void then
  725.                      Result := Result.memory_dispose;
  726.                  end;
  727.                end;
  728.             end;
  729.          end;
  730.       end;
  731.  
  732.    gc_define1 is
  733.       require
  734.          not gc_handler.is_off
  735.       do
  736.          if at_run_time then
  737.             current_type.gc_define1;
  738.          end;
  739.       end;
  740.  
  741.    gc_define2 is
  742.       require
  743.          not gc_handler.is_off
  744.       do
  745.          if at_run_time then
  746.             current_type.gc_define2;
  747.          end;
  748.       end;
  749.  
  750.    gc_info_in(str: STRING) is
  751.          -- Produce C code to print GC information.
  752.       require
  753.          not gc_handler.is_off;
  754.          gc_handler.info_flag
  755.       do
  756.          if at_run_time then
  757.             current_type.gc_info_in(str);
  758.          end;
  759.       end;
  760.  
  761.    just_before_gc_mark_in(body: STRING) is
  762.       require
  763.          not gc_handler.is_off
  764.       do
  765.          if at_run_time then
  766.             current_type.just_before_gc_mark_in(body);
  767.          end;
  768.       end;
  769.  
  770.    gc_initialize is
  771.          -- Produce code to initialize GC in the main C function.
  772.       require
  773.          not gc_handler.is_off
  774.       do
  775.          if at_run_time then
  776.             current_type.gc_initialize;
  777.          end;
  778.       end;
  779.  
  780. feature {TYPE}
  781.  
  782.    gc_mark_fixed_size(is_unmarked: BOOLEAN; body: STRING) is
  783.          -- The main purpose is to compute for example the best
  784.          -- body for the gc_markXXX function. In fact, this
  785.          -- feature may be called to produce C code when C variable
  786.          -- `o' is not NULL and when `o' is of some concrete type
  787.          -- (Tid*) where `id' is the one of the current RUN_CLASS.
  788.          -- Finally, when `is_unmarked' is true, object `o' is unmarked.
  789.       require
  790.          not gc_handler.is_off;
  791.          not current_type.is_native_array;
  792.          at_run_time
  793.       local
  794.          rf2: RUN_FEATURE_2;
  795.          t: TYPE;
  796.          rc: RUN_CLASS;
  797.          i: INTEGER;
  798.       do
  799.          wa_buf.clear;
  800.          wa_cyclic_buf.clear;
  801.          if writable_attributes /= Void then
  802.             from
  803.                i := writable_attributes.upper;
  804.             until
  805.                i = 0
  806.             loop
  807.                rf2 := writable_attributes.item(i);
  808.                t := rf2.result_type;
  809.                if t.need_gc_mark_function then
  810.                   rc :=  t.run_class;
  811.                   wa_cycle.clear;
  812.                   wa_cycle.add_last(rf2);
  813.                   if rc.is_wa_cycle(Current) then
  814.                      wa_cyclic_buf.add_last(rf2);
  815.                   else
  816.                      wa_buf.add_last(rf2);
  817.                   end;
  818.                end;
  819.                i := i - 1;
  820.             end;
  821.          end;
  822.          if wa_buf.empty and then wa_cyclic_buf.empty then
  823.             gc_set_fsoh_marked_in(body);
  824.          else
  825.             if wa_cyclic_buf.upper >= 0 then
  826.                body.append("begin:%N");
  827.             end;
  828.             if not is_unmarked then
  829.                body.append(
  830.                   "if(((gc");
  831.                id.append_in(body);
  832.                body.append(
  833.                   "*)o)->header.flag==FSOH_UNMARKED){%N");
  834.             end;
  835.             gc_set_fsoh_marked_in(body);
  836.             from -- Ordinary attributes :
  837.                i := wa_buf.upper;
  838.             until
  839.                i < 0
  840.             loop
  841.                rf2 := wa_buf.item(i);
  842.                mark_attribute(body,rf2);
  843.                i := i - 1;
  844.             end;
  845.             from -- Cyclic attributes :
  846.                i := wa_cyclic_buf.upper;
  847.             until
  848.                i < 0
  849.             loop
  850.                rf2 := wa_cyclic_buf.item(i);
  851.                t := rf2.result_type;
  852.                rc :=  t.run_class;
  853.                wa_cycle.clear;
  854.                wa_cycle.add_last(rf2);
  855.                if rc.is_wa_cycle(Current) then
  856.                end;
  857.                if i = 0 and then
  858.                   wa_cycle.count = 1 and then
  859.                   rc.running /= Void and then
  860.                   rc.running.count = 1 and then
  861.                   rc.running.first = Current
  862.                 then
  863.                   body.append("o=(void*)o->_");
  864.                   body.append(rf2.name.to_string);
  865.                   body.append(";%Nif((o!=NULL)");
  866.                   if is_unmarked then
  867.                      body.append("&&(((gc");
  868.                      id.append_in(body);
  869.                      body.append(
  870.                         "*)o)->header.flag==FSOH_UNMARKED))");
  871.                   else
  872.                      body.extend(')');
  873.                   end;
  874.                   body.append("goto begin;%N");
  875.                else
  876.                   mark_attribute(body,rf2);
  877.                end;
  878.                i := i - 1;
  879.             end;
  880.             if not is_unmarked then
  881.                body.extend('}');
  882.             end;
  883.          end;
  884.       end;
  885.  
  886. feature {TYPE}
  887.  
  888.    gc_align_mark_fixed_size(body: STRING) is
  889.          -- Compute the best body for gc_align_markXXX of
  890.          -- a fixed_size object.
  891.       require
  892.          not gc_handler.is_off;
  893.          not current_type.is_native_array;
  894.          at_run_time
  895.       do
  896.          body.append("gc");
  897.          id.append_in(body);
  898.          body.append(
  899.             "*b=(void*)(&(c->first_object));%N%
  900.             %if((c->header.state_type==FSO_STORE_CHUNK)%
  901.             %&&(((char*)p)>=((char*)store");
  902.          id.append_in(body);
  903.          body.append(
  904.             ")))return;%N%
  905.             %if(((char*)p)>((char*)(b+(c->count_minus_one))))return;%N%
  906.             %if(((char*)p)<((char*)b))return;%N%
  907.             %if(((((char*)p)-((char*)b))%%sizeof(*p))==0){%N%
  908.             %if(p->header.flag==FSOH_UNMARKED){%N%
  909.             %T");
  910.          id.append_in(body);
  911.          body.append("*o=(void*)p;%N");
  912.          gc_mark_fixed_size(true,body);
  913.          body.append("}%N}%N");
  914.       end;
  915.  
  916. feature {RUN_CLASS}
  917.  
  918.    fill_up_with(rc: RUN_CLASS; fd: like feature_dictionary) is
  919.          -- Fill up `feature_dictionary' with all features coming from
  920.          -- `rc' X `fd'.
  921.       require
  922.          rc /= Current;
  923.          is_running_of(rc);
  924.          fd /= Void;
  925.       local
  926.          bc1, bc2: BASE_CLASS;
  927.          fn1, fn2: FEATURE_NAME;
  928.          rf: RUN_FEATURE;
  929.          i: INTEGER;
  930.       do
  931.          from
  932.             i := 1;
  933.             bc1 := rc.base_class;
  934.             bc2 := base_class;
  935.          until
  936.             i > fd.count
  937.          loop
  938.             rf := fd.item(i);
  939.             if rf.fall_in(Current) then
  940.                fn1 := rf.name;
  941.                fn2 := bc2.name_of(bc1,fn1);
  942.                rf := get_feature(fn2);
  943.             end;
  944.             i := i + 1;
  945.          end;
  946.       end;
  947.  
  948.    add_running(rc: RUN_CLASS) is
  949.       require
  950.          rc /= Void;
  951.       do
  952.          if running = Void then
  953.             running := <<rc>>;
  954.          else
  955.             if not running.fast_has(rc) then
  956.                running.add_last(rc);
  957.             end;
  958.          end;
  959.       end;
  960.  
  961. feature {E_FEATURE}
  962.  
  963.    at(fn: FEATURE_NAME): RUN_FEATURE is
  964.          -- Simple look in the dictionary to see if the feature
  965.          -- is already computed.
  966.       require
  967.          fn /= Void;
  968.       local
  969.          to_key: STRING;
  970.       do
  971.          to_key := fn.to_key;
  972.          if feature_dictionary.has(to_key) then
  973.             Result := feature_dictionary.at(to_key);
  974.          end;
  975.       end;
  976.  
  977. feature {E_STRIP}
  978.  
  979.    set_strip_used is
  980.       do
  981.          strip_used := true;
  982.       end;
  983.  
  984. feature
  985.  
  986.    get_feature_with(n: STRING): RUN_FEATURE is
  987.          -- Assume that `n' is really the final name in
  988.          -- current RUN_CLASS.
  989.       require
  990.          n /= Void;
  991.       local
  992.          sfn: SIMPLE_FEATURE_NAME;
  993.       do
  994.          if feature_dictionary.has(n) then
  995.             Result := feature_dictionary.at(n);
  996.          else
  997.             !!sfn.make(n,Void);
  998.             Result := get_feature(sfn);
  999.          end;
  1000.       end;
  1001.  
  1002. feature
  1003.  
  1004.    get_copy: RUN_FEATURE is
  1005.       do
  1006.          Result := get_rf_with(class_general.get_copy.first_name);
  1007.       end;
  1008.  
  1009. feature
  1010.  
  1011.    get_feature(fn: FEATURE_NAME): RUN_FEATURE is
  1012.          -- Assume that `fn' is really the final name in current
  1013.          -- RUN_CLASS. Don't look for rename.
  1014.       require
  1015.          fn /= Void
  1016.       local
  1017.          f: E_FEATURE;
  1018.          fn_key: STRING;
  1019.          bc: BASE_CLASS;
  1020.       do
  1021.          fn_key := fn.to_key;
  1022.          if feature_dictionary.has(fn_key) then
  1023.             Result := feature_dictionary.at(fn_key);
  1024.          else
  1025.             check
  1026.                not small_eiffel.is_ready;
  1027.             end;
  1028.             bc := base_class;
  1029.             f := bc.look_up_for(Current,fn);
  1030.             if f = Void then
  1031.                efnf(bc,fn);
  1032.             else
  1033.                Result := f.to_run_feature(current_type,fn);
  1034.                if Result /= Void  then
  1035.                   store_feature(Result);
  1036.                else
  1037.                   efnf(bc,fn);
  1038.                end;
  1039.             end;
  1040.          end;
  1041.       end;
  1042.  
  1043. feature {JVM}
  1044.  
  1045.    jvm_define_class_invariant is
  1046.          -- If needed, call the invariant for the pushed value.
  1047.       local
  1048.          ia: like class_invariant;
  1049.       do
  1050.          if run_control.invariant_check then
  1051.             ia := class_invariant;
  1052.             if ia /= Void then
  1053.                jvm.define_class_invariant_method(ia);
  1054.             end;
  1055.          end;
  1056.       end;
  1057.  
  1058. feature {JVM,TYPE}
  1059.  
  1060.    jvm_check_class_invariant is
  1061.          -- If needed, call the invariant for the stack-top object.
  1062.          -- If invariant is correct, the same stack-top object is left
  1063.          -- on the stack.
  1064.       local
  1065.          ia: like class_invariant;
  1066.          idx: INTEGER;
  1067.          ca: like code_attribute;
  1068.          cp: like constant_pool;
  1069.       do
  1070.          if run_control.invariant_check then
  1071.             ia := class_invariant;
  1072.             if ia /= Void then
  1073.                ca := code_attribute;
  1074.                cp := constant_pool;
  1075.                ca.opcode_dup;
  1076.                opcode_checkcast;
  1077.                idx := cp.idx_methodref3(fully_qualified_name,fz_invariant,fz_29);
  1078.                ca.opcode_invokevirtual(idx,-1);
  1079.             end;
  1080.          end;
  1081.       end;
  1082.  
  1083. feature {SMALL_EIFFEL}
  1084.  
  1085.    compile_to_jvm is
  1086.       require
  1087.          at_run_time
  1088.       local
  1089.          i: INTEGER;
  1090.          rf: RUN_FEATURE;
  1091.          type_ref_to_exp: TYPE_REF_TO_EXP;
  1092.       do
  1093.          echo.put_character('%T');
  1094.          echo.put_string(current_type.run_time_mark);
  1095.          echo.put_character('%N');
  1096.          jvm.start_new_class(Current);
  1097.          from
  1098.             i := 1;
  1099.          until
  1100.             i > feature_dictionary.count
  1101.          loop
  1102.             rf := feature_dictionary.item(i);
  1103.             jvm.set_current_frame(rf);
  1104.             rf.jvm_field_or_method;
  1105.             i := i + 1;
  1106.          end;
  1107.          type_ref_to_exp ?= current_type;
  1108.          if type_ref_to_exp = Void then
  1109.             jvm.prepare_fields;
  1110.          else
  1111.             type_ref_to_exp.jvm_prepare_item_field;
  1112.          end;
  1113.          jvm.prepare_methods;
  1114.          jvm.finish_class;
  1115.       end;
  1116.  
  1117. feature {MANIFEST_ARRAY}
  1118.  
  1119.    fully_qualified_name: STRING is
  1120.       do
  1121.          if fully_qualified_name_memory = Void then
  1122.             fully_qualified_name_memory2.copy(jvm.output_name);
  1123.             fully_qualified_name_memory2.extend('/');
  1124.             fully_qualified_name_memory2.append(unqualified_name);
  1125.             !!fully_qualified_name_memory.copy(fully_qualified_name_memory2);
  1126.          end;
  1127.          Result := fully_qualified_name_memory;
  1128.       end;
  1129.  
  1130. feature {TYPE}
  1131.  
  1132.    jvm_type_descriptor_in(str: STRING) is
  1133.          -- Append in `str' the appropriate JVM type descriptor.
  1134.       require
  1135.          at_run_time;
  1136.          running.fast_has(Current)
  1137.       do
  1138.          check
  1139.             current_type.is_user_expanded
  1140.          end;
  1141.          str.extend('L');
  1142.          str.append(fully_qualified_name);
  1143.          str.extend(';');
  1144.       end;
  1145.  
  1146. feature {RUN_FEATURE}
  1147.  
  1148.    jvm_invoke(idx, stack_level: INTEGER) is
  1149.       local
  1150.          ct: like current_type;
  1151.       do
  1152.          ct := current_type;
  1153.          inspect
  1154.             ct.jvm_method_flags
  1155.          when 17 then
  1156.             code_attribute.opcode_invokevirtual(idx,stack_level);
  1157.          when 9 then
  1158.             code_attribute.opcode_invokestatic(idx,stack_level);
  1159.          end;
  1160.       end;
  1161.  
  1162. feature
  1163.  
  1164.    jvm_basic_new is
  1165.          -- Poduce bytecode to push a new created object with the
  1166.          -- basic default value (the corresponding creation procedure
  1167.          -- if any is not called).
  1168.       local
  1169.          i, idx: INTEGER;
  1170.          wa: ARRAY[RUN_FEATURE_2];
  1171.          rf2: RUN_FEATURE_2;
  1172.          t2: TYPE;
  1173.          ca: like code_attribute;
  1174.          cp: like constant_pool;
  1175.       do
  1176.          ca := code_attribute;
  1177.          cp := constant_pool;
  1178.          idx := jvm_constant_pool_index;
  1179.          ca.opcode_new(idx);
  1180.          ca.opcode_dup;
  1181.            idx := cp.idx_methodref1(idx,fz_35,fz_29);
  1182.          ca.opcode_invokespecial(idx,-1);
  1183.          wa := writable_attributes;
  1184.          if wa /= Void then
  1185.             from
  1186.                i := wa.upper;
  1187.             until
  1188.                i = 0
  1189.             loop
  1190.                rf2 := wa.item(i);
  1191.                t2 := rf2.result_type.run_type;
  1192.                if t2.is_user_expanded then
  1193.                   ca.opcode_dup;
  1194.                   t2.run_class.jvm_expanded_push_default;
  1195.                   idx := cp.idx_fieldref(rf2);
  1196.                   ca.opcode_putfield(idx,-2);
  1197.                elseif t2.is_bit then
  1198.                   ca.opcode_dup;
  1199.                   idx := t2.jvm_push_default;
  1200.                   idx := cp.idx_fieldref(rf2);
  1201.                   ca.opcode_putfield(idx,-2);
  1202.                end;
  1203.                i := i - 1;
  1204.             end;
  1205.          end;
  1206.       end;
  1207.  
  1208. feature {TYPE,RUN_CLASS,NATIVE_SMALL_EIFFEL}
  1209.  
  1210.    jvm_expanded_push_default is
  1211.          -- Push the corresponding new user's expanded (either dummy
  1212.          -- or not, initializer is automatically applied).
  1213.       require
  1214.          current_type.is_user_expanded
  1215.       local
  1216.          rf: RUN_FEATURE;
  1217.       do
  1218.          jvm_basic_new;
  1219.          rf := base_class.expanded_initializer(current_type);
  1220.          if rf /= Void then
  1221.             jvm.push_expanded_initialize(rf);
  1222.             rf.mapping_jvm;
  1223.             jvm.pop;
  1224.          end;
  1225.       end;
  1226.  
  1227. feature {JVM}
  1228.  
  1229.    unqualified_name: STRING is
  1230.          -- Also used for the corresponding file name.
  1231.       local
  1232.          ct: TYPE;
  1233.       do
  1234.          ct := current_type;
  1235.          unqualified_name_memory.copy(ct.run_time_mark);
  1236.          unqualified_name_memory.to_lower;
  1237.          unqualified_name_memory.replace_all('[','O');
  1238.          unqualified_name_memory.replace_all(']','F');
  1239.          unqualified_name_memory.replace_all(' ','_');
  1240.          unqualified_name_memory.replace_all(',','_');
  1241.          Result := unqualified_name_memory;
  1242.       end;
  1243.  
  1244. feature
  1245.  
  1246.    jvm_constant_pool_index: INTEGER is
  1247.          -- The fully qualified index in the constant pool.
  1248.       do
  1249.          Result := constant_pool.idx_class2(fully_qualified_name);
  1250.       end;
  1251.  
  1252. feature {SMALL_EIFFEL,TYPE}
  1253.  
  1254.    demangling is
  1255.       require
  1256.          cpp.on_h
  1257.       local
  1258.          str: STRING;
  1259.          r: like running;
  1260.          i: INTEGER;
  1261.       do
  1262.          str := "";
  1263.          str.clear;
  1264.          if at_run_time then
  1265.             str.extend('A');
  1266.             if current_type.is_reference and then not is_tagged then
  1267.                str.extend('*');
  1268.             else
  1269.                str.extend(' ');
  1270.             end;
  1271.          else
  1272.             str.extend('D');
  1273.             str.extend(' ');
  1274.          end;
  1275.          r := running;
  1276.          if r /= Void then
  1277.             r.count.append_in(str);
  1278.          end;
  1279.          from
  1280.          until
  1281.             str.count > 4
  1282.          loop
  1283.             str.extend(' ');
  1284.          end;
  1285.          str.extend('T');
  1286.          id.append_in(str);
  1287.          from
  1288.          until
  1289.             str.count > 10
  1290.          loop
  1291.             str.extend(' ');
  1292.          end;
  1293.          current_type.demangling_in(str);
  1294.          if r /= Void then
  1295.             from
  1296.                str.extend(' ');
  1297.                i := r.upper;
  1298.             until
  1299.                i = 0
  1300.             loop
  1301.                r.item(i).id.append_in(str);
  1302.                i := i - 1;
  1303.                if i > 0 then
  1304.                   str.extend(',');
  1305.                end;
  1306.             end;
  1307.          end;
  1308.          str.extend('%N');
  1309.          cpp.put_string(str);
  1310.       ensure
  1311.          cpp.on_h
  1312.       end;
  1313.  
  1314. feature {SMALL_EIFFEL,RUN_CLASS}
  1315.  
  1316.    compile_to_c(deep: INTEGER) is
  1317.          -- Produce C code for features of Current. The `deep'
  1318.          -- indicator is used to sort the C output in the best order
  1319.          -- (more C  inlinings are possible when basic functions are
  1320.          -- produced first). As there is not always a total order
  1321.          -- between clients, the `deep' avoid infinite track.
  1322.          -- When `deep' is greater than 0, C code writting
  1323.          -- is produced whatever the real client relation is.
  1324.       require
  1325.          cpp.on_c;
  1326.          deep >= 0
  1327.       local
  1328.          i: INTEGER;
  1329.          rc1, rc2: like Current;
  1330.          cc1, cc2: INTEGER;
  1331.       do
  1332.          if compile_to_c_done then
  1333.          elseif not at_run_time then
  1334.             compile_to_c_done := true;
  1335.          elseif deep = 0 then
  1336.             really_compile_to_c;
  1337.          else
  1338.             i := actuals_clients.upper;
  1339.             if i >= 0 then
  1340.                from
  1341.                   rc1 := Current;
  1342.                   cc1 := i + 1;
  1343.                until
  1344.                   i = 0
  1345.                loop
  1346.                   rc2 := actuals_clients.item(i);
  1347.                   if not rc2.compile_to_c_done then
  1348.                      cc2 := rc2.actuals_clients.count;
  1349.                      if cc2 > cc1 then
  1350.                         rc1 := rc2;
  1351.                         cc1 := cc2;
  1352.                      end;
  1353.                   end;
  1354.                   i := i - 1;
  1355.                end;
  1356.                if rc1 = Current then
  1357.                   really_compile_to_c;
  1358.                else
  1359.                   rc1.compile_to_c(deep - 1);
  1360.                end;
  1361.             end;
  1362.          end;
  1363.       ensure
  1364.          cpp.on_c
  1365.       end;
  1366.  
  1367. feature {RUN_CLASS}
  1368.  
  1369.    actuals_clients: FIXED_ARRAY[RUN_CLASS];
  1370.  
  1371. feature {CREATION_CALL_3_4,RUN_FEATURE}
  1372.  
  1373.    add_client(rc: RUN_CLASS) is
  1374.       require
  1375.          rc /= Void
  1376.       local
  1377.          i: INTEGER;
  1378.       do
  1379.          i := actuals_clients.fast_index_of(rc);
  1380.          if i > actuals_clients.upper then
  1381.             actuals_clients.add_last(rc);
  1382.          end;
  1383.       end;
  1384.  
  1385. feature
  1386.  
  1387.    offset_of(rf2: RUN_FEATURE_2): INTEGER is
  1388.          -- Compute the displacement to access `rf2' in the corresponding
  1389.          -- C struct to remove a possible stupid switch.
  1390.          -- Result is in number of bytes.
  1391.       require
  1392.          at_run_time;
  1393.          writable_attributes.fast_has(rf2);
  1394.          small_eiffel.is_ready
  1395.       local
  1396.          wa: like writable_attributes;
  1397.          t: TYPE;
  1398.          i: INTEGER;
  1399.       do
  1400.          if is_tagged then
  1401.             Result := (1).object_size;
  1402.          end;
  1403.          from
  1404.             wa := writable_attributes;
  1405.             i := wa.upper;
  1406.          invariant
  1407.             i > 0
  1408.          until
  1409.             wa.item(i) = rf2
  1410.          loop
  1411.             t := wa.item(i).result_type;
  1412.             Result := Result + t.space_for_variable;
  1413.             i := i - 1;
  1414.          end;
  1415.       end;
  1416.  
  1417. feature
  1418.  
  1419.    wa_buf: FIXED_ARRAY[RUN_FEATURE_2] is
  1420.       once
  1421.          !!Result.with_capacity(24);
  1422.       end;
  1423.  
  1424.    wa_cyclic_buf: FIXED_ARRAY[RUN_FEATURE_2] is
  1425.       once
  1426.          !!Result.with_capacity(24);
  1427.       end;
  1428.  
  1429. feature {RUN_CLASS}
  1430.  
  1431.    is_wa_cycle(origin: like Current): BOOLEAN is
  1432.       do
  1433.          if Current = origin then
  1434.             Result := true;
  1435.          end;
  1436.       end;
  1437.  
  1438. feature {RUN_FEATURE_2}
  1439.  
  1440.    force_c_recompilation_comment(rf2: RUN_FEATURE_2) is
  1441.       require
  1442.          at_run_time;
  1443.          writable_attributes.fast_has(rf2);
  1444.          small_eiffel.is_ready
  1445.       do
  1446.          cpp.put_recompilation_comment(offset_of(rf2));
  1447.       end;
  1448.  
  1449. feature -- Some usefull JVM opcode :
  1450.  
  1451.    opcode_checkcast is
  1452.          -- May produce a `checkcast' opcode depending on
  1453.          -- `current_type' Java byte-code mapping.
  1454.       local
  1455.          ct: TYPE;
  1456.          idx: INTEGER;
  1457.       do
  1458.          ct := current_type;
  1459.          if ct.is_basic_eiffel_expanded then
  1460.          elseif ct.is_native_array then
  1461.             tmp_string.clear;
  1462.             ct.jvm_target_descriptor_in(tmp_string);
  1463.             idx := constant_pool.idx_class2(tmp_string);
  1464.             code_attribute.opcode_checkcast(idx);
  1465.          elseif ct.is_bit then
  1466.          else
  1467.             idx := jvm_constant_pool_index;
  1468.             code_attribute.opcode_checkcast(idx);
  1469.          end;
  1470.       end;
  1471.  
  1472.    opcode_instanceof is
  1473.       require
  1474.          not current_type.is_basic_eiffel_expanded
  1475.       local
  1476.          idx: INTEGER;
  1477.       do
  1478.          idx := jvm_constant_pool_index;
  1479.          code_attribute.opcode_instanceof(idx);
  1480.       end;
  1481.  
  1482.    opcode_getfield(rf2: RUN_FEATURE_2): INTEGER is
  1483.          -- Produce a `checkcast'/`getfield' for the given
  1484.          -- attribute of the top object of the stack.
  1485.          -- stack: ... object => ... value
  1486.       local
  1487.          idx: INTEGER;
  1488.       do
  1489.          opcode_checkcast;
  1490.          idx := constant_pool.idx_fieldref(rf2);
  1491.          Result := rf2.result_type.jvm_stack_space - 1;
  1492.          code_attribute.opcode_getfield(idx,Result);
  1493.       end;
  1494.  
  1495. feature {RUN_FEATURE}
  1496.  
  1497.    add_rf(rf: RUN_FEATURE; key: STRING) is
  1498.       do
  1499.          check
  1500.             not feature_dictionary.has(key)
  1501.          end;
  1502.          feature_dictionary.put(rf,key);
  1503.       end;
  1504.  
  1505. feature {NONE}
  1506.  
  1507.    mark_attribute(body: STRING; rf2: RUN_FEATURE_2) is
  1508.       do
  1509.          tmp_string.copy("o->_");
  1510.          tmp_string.append(rf2.name.to_string);
  1511.          tmp_string.append(fz_open_c_comment);
  1512.          offset_of(rf2).append_in(tmp_string);
  1513.          tmp_string.append(fz_close_c_comment);
  1514.          gc_handler.mark_for(body,tmp_string,rf2.result_type.run_class);
  1515.       end;
  1516.  
  1517.    gc_set_fsoh_marked_in(body: STRING) is
  1518.       do
  1519.          if current_type.is_reference then
  1520.             body.append("((gc");
  1521.             id.append_in(body);
  1522.             body.append("*)o)->header.flag=FSOH_MARKED;%N");
  1523.          end;
  1524.       end;
  1525.  
  1526.    need_gc_mark: BOOLEAN is
  1527.       require
  1528.          at_run_time
  1529.       local
  1530.          i: INTEGER;
  1531.          wa: like writable_attributes;
  1532.          rf2: RUN_FEATURE_2;
  1533.          t: TYPE;
  1534.       do
  1535.          wa := writable_attributes;
  1536.          if wa /= Void then
  1537.             from
  1538.                i := wa.upper;
  1539.             until
  1540.                Result or else i = 0
  1541.             loop
  1542.                rf2 := wa.item(i);
  1543.                t := rf2.result_type;
  1544.                Result := t.need_gc_mark_function;
  1545.                i := i - 1;
  1546.             end;
  1547.          end;
  1548.       end;
  1549.  
  1550.    wa_cycle: FIXED_ARRAY[RUN_FEATURE_2] is
  1551.       once
  1552.          !!Result.with_capacity(24);
  1553.       end;
  1554.  
  1555.    tmp_string: STRING is
  1556.       once
  1557.          !!Result.make(32);
  1558.       end;
  1559.  
  1560.    efnf(bc: BASE_CLASS; fn: FEATURE_NAME) is
  1561.       require
  1562.          bc /= Void;
  1563.          fn /= Void
  1564.       do
  1565.          eh.append("Current type is ");
  1566.          eh.append(current_type.run_time_mark);
  1567.          eh.append(". There is no feature ");
  1568.          eh.append(fn.to_string);
  1569.          eh.append(" in class ");
  1570.          eh.append(bc.name.to_string);
  1571.          error(fn.start_position,fz_dot);
  1572.       end;
  1573.  
  1574.    sort_wam(wam: like writable_attributes) is
  1575.          -- Sort `wam' to common attribute at the end.
  1576.       require
  1577.          wam.lower = 1
  1578.       local
  1579.          min, max, buble: INTEGER;
  1580.          moved: BOOLEAN;
  1581.       do
  1582.          from
  1583.             max := wam.upper;
  1584.             min := 1;
  1585.             moved := true;
  1586.          until
  1587.             not moved
  1588.          loop
  1589.             moved := false;
  1590.             if max - min > 0 then
  1591.                from
  1592.                   buble := min + 1;
  1593.                until
  1594.                   buble > max
  1595.                loop
  1596.                   if gt(wam.item(buble - 1),wam.item(buble)) then
  1597.                      wam.swap(buble - 1,buble);
  1598.                      moved := true;
  1599.                   end;
  1600.                   buble := buble + 1;
  1601.                end;
  1602.                max := max - 1;
  1603.             end;
  1604.             if moved and then max - min > 0 then
  1605.                from
  1606.                   moved := false;
  1607.                   buble := max - 1;
  1608.                until
  1609.                   buble < min
  1610.                loop
  1611.                   if gt(wam.item(buble),wam.item(buble + 1)) then
  1612.                      wam.swap(buble,buble + 1);
  1613.                      moved := true;
  1614.                   end;
  1615.                   buble := buble - 1;
  1616.                end;
  1617.                min := min + 1;
  1618.             end;
  1619.          end;
  1620.       end;
  1621.  
  1622.    gt(rf1, rf2: RUN_FEATURE_2): BOOLEAN is
  1623.          -- True if it is better to set attribute `rf1' before
  1624.          -- attribute `rf2'.
  1625.       local
  1626.          bc1, bc2: BASE_CLASS;
  1627.          bf1, bf2: E_FEATURE;
  1628.          bcn1, bcn2: CLASS_NAME;
  1629.       do
  1630.          bf1 := rf1.base_feature;
  1631.          bf2 := rf2.base_feature;
  1632.          bc1 := bf1.base_class;
  1633.          bc2 := bf2.base_class;
  1634.          bcn1 := bc1.name;
  1635.          bcn2 := bc2.name;
  1636.          if bcn1.to_string = bcn2.to_string then
  1637.             Result := bf1.start_position.before(bf2.start_position);
  1638.          elseif bcn2.is_subclass_of(bcn1) then
  1639.             Result := true;
  1640.          elseif bcn1.is_subclass_of(bcn2) then
  1641.          elseif bc1.parent_list = Void then
  1642.             if bc2.parent_list = Void then
  1643.                Result := bcn1.to_string < bcn2.to_string;
  1644.             else
  1645.                Result := true;
  1646.             end;
  1647.          elseif bc2.parent_list = Void then
  1648.          else
  1649.             Result := bc2.parent_list.count < bc1.parent_list.count
  1650.          end;
  1651.       end;
  1652.  
  1653.    writable_attributes_mem: like writable_attributes;
  1654.  
  1655.    really_compile_to_c is
  1656.       require
  1657.          at_run_time
  1658.       local
  1659.          i: INTEGER;
  1660.          rf: RUN_FEATURE;
  1661.       do
  1662.          compile_to_c_done := true;
  1663.          echo.put_character('%T');
  1664.          echo.put_string(current_type.run_time_mark);
  1665.          echo.put_character('%N');
  1666.          from
  1667.             i := 1;
  1668.          until
  1669.             i > feature_dictionary.count
  1670.          loop
  1671.             rf := feature_dictionary.item(i);
  1672.             rf.c_define;
  1673.             i := i + 1;
  1674.          end;
  1675.          if run_control.invariant_check then
  1676.             if class_invariant /= Void then
  1677.                class_invariant.c_define;
  1678.             end;
  1679.          end;
  1680.          cpp.finished_run_class;
  1681.       ensure
  1682.          compile_to_c_done
  1683.       end;
  1684.  
  1685.    unqualified_name_memory: STRING is
  1686.       once
  1687.          !!Result.make(32);
  1688.       end;
  1689.  
  1690.    fully_qualified_name_memory: STRING;
  1691.  
  1692.    fully_qualified_name_memory2: STRING is
  1693.       once
  1694.          !!Result.make(256);
  1695.       end;
  1696.  
  1697.    store_feature(rf: like get_feature) is
  1698.          -- To update the dictionary from outside.
  1699.          -- Note : this routine is necessary because of recursive call.
  1700.       require
  1701.          rf.run_class = Current
  1702.       local
  1703.          rf_key: STRING;
  1704.       do
  1705.          rf_key := rf.name.to_key;
  1706.          if feature_dictionary.has(rf_key) then
  1707.             check
  1708.                feature_dictionary.at(rf_key) = rf
  1709.             end;
  1710.          else
  1711.             feature_dictionary.put(rf,rf_key);
  1712.             small_eiffel.incr_magic_count;
  1713.          end;
  1714.       ensure
  1715.          get_feature(rf.name) = rf
  1716.       end;
  1717.  
  1718.    get_or_fatal_error(fn: FEATURE_NAME): RUN_FEATURE is
  1719.       do
  1720.          Result := get_feature(fn);
  1721.          if Result = Void then
  1722.             eh.add_position(fn.start_position);
  1723.             eh.append("Feature ");
  1724.             eh.append(fn.to_string);
  1725.             eh.append(" not found when starting look up from ");
  1726.             eh.add_type(current_type,fz_dot);
  1727.             eh.print_as_fatal_error;
  1728.          end;
  1729.       end;
  1730.  
  1731.    strip_used: BOOLEAN;
  1732.  
  1733.    prepare_strip is
  1734.       local
  1735.          rf2: RUN_FEATURE_2;
  1736.          i: INTEGER;
  1737.       do
  1738.          if strip_used then
  1739.             from
  1740.                i := 1;
  1741.             until
  1742.                i > feature_dictionary.count
  1743.             loop
  1744.                rf2 ?= feature_dictionary.item(i);
  1745.                if rf2 /= Void then
  1746.                   rf2.result_type.used_as_reference;
  1747.                end;
  1748.                i := i + 1;
  1749.             end;
  1750.          end;
  1751.       end;
  1752.  
  1753.    to_reference_memory: DICTIONARY[TYPE_REF_TO_EXP,STRING] is
  1754.       once
  1755.          !!Result.make;
  1756.       end;
  1757.  
  1758.    runnable_class_invariant_done: BOOLEAN;
  1759.  
  1760.    c_header_pass_level_done: INTEGER;
  1761.  
  1762. invariant
  1763.  
  1764.    current_type.run_type = current_type;
  1765.  
  1766. end -- RUN_CLASS
  1767.  
  1768.