home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ppcsmalleiffel / lib_se / run_class.e < prev    next >
Encoding:
Text File  |  1998-01-16  |  31.4 KB  |  1,469 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  4. --                       http://www.loria.fr/SmallEiffel
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it 
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later 
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License 
  11. -- for  more  details.  You  should  have  received a copy of the GNU General 
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class RUN_CLASS
  17.    --
  18.    -- Only for class with objects at execution time.
  19.    --
  20.    
  21. inherit 
  22.    GLOBALS
  23.       redefine fill_tagged_out_memory
  24.       end;
  25.    
  26. creation {SMALL_EIFFEL} make
  27.    
  28. feature
  29.    
  30.    current_type: TYPE;
  31.      -- Runnable corresponding one.
  32.    
  33.    id: INTEGER;
  34.      -- Id of the receiver to produce C code. 
  35.    
  36.    at_run_time: BOOLEAN;
  37.      -- True if `current_type' is really created (only when 
  38.      -- direct instances of `current_type' exists at run time).
  39.    
  40.    running: ARRAY[RUN_CLASS];
  41.      -- Void or the set of all `at_run_time' directly compatible 
  42.      -- run classes. A run class is directly compatible with one
  43.      -- another only when it can be directly substitute with 
  44.      -- current run class.
  45.      -- Thus, if current run class is reference, `running' are all 
  46.      -- reference run classes. If current run class is expanded, 
  47.      -- `running' has only one element (the current class itself).
  48.    
  49.    invariant_assertion: CLASS_INVARIANT;
  50.      -- Collected Runnable invariant if any.
  51.  
  52.    compile_to_c_done: BOOLEAN;
  53.          -- True if `compile_to_c' has already be called.
  54.  
  55. feature {RUN_CLASS,RUN_FEATURE}
  56.    
  57.    feature_dictionary: DICTIONARY[RUN_FEATURE,STRING];
  58.      -- Access to the runnable version of a feature.
  59.      -- To avoid clash between infix and prefix names, 
  60.      -- `to_key' of class NAME is used as entry.
  61.    
  62. feature {NONE}
  63.  
  64.    tagged_mem: INTEGER;
  65.      -- 0 when not computed, 1 when tagged or -1
  66.  
  67. feature {NONE}
  68.    
  69.    make(t: like current_type) is
  70.       require
  71.      t.run_type = t;
  72.      not small_eiffel.is_ready
  73.       local
  74.      run_string: STRING;
  75.      rcd: DICTIONARY[RUN_CLASS,STRING];
  76.      rc: RUN_CLASS;
  77.      r: like runnable;
  78.      i: INTEGER;
  79.       do
  80.      compile_to_c_done := true;
  81.      current_type := t;
  82.      !!actuals_clients.with_capacity(16);
  83.      run_string := t.run_time_mark;
  84.      id := id_provider.item(run_string);
  85.      check
  86.         not small_eiffel.run_class_dictionary.has(run_string);
  87.      end;
  88.      if small_eiffel.is_ready then
  89.         warning(Void,"Internal Warning #1 in RUN_CLASS.");
  90.      end;
  91.      if small_eiffel.run_class_dictionary.has(run_string) then
  92.         warning(Void,"Internal Warning #2 in RUN_CLASS.");
  93.      end;
  94.      small_eiffel.run_class_dictionary.put(Current,run_string);
  95.      !!feature_dictionary.with_capacity(64);
  96.      small_eiffel.incr_magic_count;
  97.      if t.is_expanded then
  98.         set_at_run_time;
  99.         t.base_class.check_expanded_with(t);
  100.      else
  101.         from
  102.            rcd := small_eiffel.run_class_dictionary;
  103.            i := 1;
  104.         until
  105.            i > rcd.count
  106.         loop
  107.            rc := rcd.item(i);
  108.            if rc.at_run_time and then 
  109.           rc.current_type.is_reference and then
  110.           rc.is_a(Current)
  111.         then
  112.           add_running(rc);
  113.            end;
  114.            i := i + 1;
  115.         end;
  116.      end;
  117.      if run_control.invariant_check then
  118.         ci_collector.clear;
  119.         base_class.collect_invariant(Current);
  120.         r := runnable(ci_collector,current_type,Void);
  121.         if r /= Void then
  122.            !!invariant_assertion.from_runnable(r); 
  123.         end;
  124.      end;
  125.       ensure
  126.      current_type = t;
  127.       end;
  128.    
  129. feature
  130.  
  131.    is_tagged: BOOLEAN is
  132.       require
  133.      small_eiffel.is_ready
  134.       do
  135.      if tagged_mem = 0 then
  136.         if current_type.is_expanded then
  137.            tagged_mem := -1;
  138.         elseif at_run_time then 
  139.            if run_control.boost then
  140.           if small_eiffel.is_tagged(Current) then
  141.              tagged_mem := 1;
  142.           else
  143.              tagged_mem := -1;
  144.           end;
  145.            else
  146.           tagged_mem := 1;
  147.            end;
  148.         end;
  149.      end;
  150.      Result := tagged_mem = 1;
  151.       ensure
  152.      tagged_mem /= 0
  153.       end;
  154.    
  155.    is_expanded: BOOLEAN is
  156.       do
  157.      Result := current_type.is_expanded;
  158.       end;
  159.    
  160.    writable_attributes: ARRAY[RUN_FEATURE_2] is
  161.      -- Computed and ordered array of writable attributes.
  162.      -- Storage in C struct is to be done in reverse 
  163.      -- order (from `upper' to `lower').
  164.      -- Order is done according to the level of attribute 
  165.      -- definition in the inheritance graph to allow more 
  166.      -- stupid switch to be removed.
  167.       require
  168.      small_eiffel.is_ready;
  169.      at_run_time
  170.       local
  171.      rf2: RUN_FEATURE_2;
  172.      i: INTEGER;
  173.       do
  174.      if writable_attributes_mem = Void then
  175.         from
  176.            i := 1;
  177.         until
  178.            i > feature_dictionary.count
  179.         loop
  180.            rf2 ?= feature_dictionary.item(i);
  181.            if rf2 /= Void then
  182.           if writable_attributes_mem = Void then
  183.              writable_attributes_mem := <<rf2>>;
  184.           else
  185.              writable_attributes_mem.add_last(rf2);
  186.           end;
  187.            end;
  188.            i := i + 1;
  189.         end;
  190.         if writable_attributes_mem /= Void then
  191.            sort_wam(writable_attributes_mem);
  192.         end;
  193.      end;
  194.      Result := writable_attributes_mem;
  195.       ensure
  196.      Result /= Void implies Result.lower = 1
  197.       end;
  198.    
  199. feature 
  200.    
  201.    get_rf(cpc: CALL_PROC_CALL): RUN_FEATURE is
  202.      -- Compute or simply fetch the corresponding RUN_FEATURE.
  203.      -- Exporting rules are automatically checked and possible
  204.      -- rename are also done using `start_position' of
  205.      -- `cpc.feature_name'.
  206.      -- No return when an error occurs because `fatal_error'
  207.      -- is called.
  208.       require
  209.      cpc.target.is_checked;
  210.      cpc.target.result_type.run_class = Current;
  211.       local
  212.          target: EXPRESSION;
  213.      is_current: BOOLEAN;
  214.      fn1, fn2: FEATURE_NAME;
  215.      wbc, wbc2: BASE_CLASS;
  216.      trt, constraint: TYPE;
  217.      tfg: TYPE_FORMAL_GENERIC;
  218.       do
  219.      target := cpc.target;
  220.      trt := target.result_type;
  221.      is_current := target.is_current;
  222.      fn1 := cpc.feature_name;
  223.      wbc := fn1.start_position.base_class;
  224.      if is_current or else trt.is_like_current then
  225.         fn2 := trt.base_class.new_name_of(wbc,fn1);
  226.         if fn2 /= fn1 then
  227.            eh.add_position(fn1.start_position);
  228.            Result := get_or_fatal_error(fn2);
  229.            eh.cancel;
  230.         else
  231.            Result := get_or_fatal_error(fn1);
  232.         end;
  233.      elseif trt.is_formal_generic then
  234.         tfg ?= trt;
  235.         check
  236.            tfg /= Void
  237.         end;
  238.         constraint := tfg.constraint;
  239.         if constraint = Void then
  240.            Result := get_or_fatal_error(fn1);
  241.         elseif not trt.is_a(constraint) then
  242.            eh.print_as_error;
  243.            eh.add_position(cpc.feature_name.start_position);
  244.            eh.append("Constraint genericity violation.");
  245.            eh.print_as_fatal_error;
  246.         else
  247.            wbc2 := constraint.start_position.base_class;
  248.            if wbc2 = wbc or else wbc.is_subclass_of(wbc2) then
  249.           fn2 := trt.base_class.new_name_of(constraint.base_class,fn1);
  250.           Result := get_or_fatal_error(fn2);
  251.            else
  252.           Result := get_or_fatal_error(fn1);
  253.            end;
  254.         end;
  255.      else
  256.         Result := get_or_fatal_error(fn1);
  257.      end;
  258.      Result.add_client(Current);
  259.      if nb_errors = 0 and then 
  260.         not is_current and then
  261.         not Result.is_exported_in(wbc.base_class_name) then
  262.         eh.add_position(Result.start_position);
  263.         eh.append(" Cannot use feature %"");
  264.         eh.append(fn1.to_string);
  265.         error(cpc.feature_name.start_position,"%" here.");
  266.      end;
  267.       ensure
  268.      Result /= Void
  269.       end;
  270.  
  271.    get_rf_with(fn: FEATURE_NAME): RUN_FEATURE is
  272.      -- Compute or simply fetch the corresponding RUN_FEATURE.
  273.      -- Possible rename are also done using `start_position' of
  274.      -- `fn'. No return when an error occurs because `fatal_error'
  275.      -- is called.
  276.       require
  277.      base_class = fn.start_position.base_class or else
  278.      base_class.is_subclass_of(fn.start_position.base_class)
  279.       local
  280.      fn2: FEATURE_NAME;
  281.      wbc: BASE_CLASS;
  282.       do
  283.      wbc := fn.start_position.base_class;
  284.      fn2 := base_class.new_name_of(wbc,fn);
  285.      if fn2 /= fn then
  286.         eh.add_position(fn.start_position);
  287.         Result := get_or_fatal_error(fn2);
  288.         eh.cancel;
  289.      else
  290.         Result := get_or_fatal_error(fn2);
  291.      end;
  292.       ensure
  293.      Result /= Void
  294.       end;
  295.  
  296.    dynamic(up_rf: RUN_FEATURE): RUN_FEATURE is
  297.      -- Assume the current type of `up_rf' is a kind of 
  298.      -- `current_type'. The result is the concrete one
  299.      -- according to dynamic dispatch rules.
  300.       require
  301.      up_rf /= Void;
  302.      Current.is_a(up_rf.run_class)
  303.       local
  304.      fn, up_fn: FEATURE_NAME;
  305.      up_type: TYPE;
  306.       do
  307.      up_type := up_rf.current_type;
  308.      if Current = up_type.run_class then
  309.         Result := up_rf;
  310.      else
  311.         up_fn := up_rf.name;
  312.         fn := base_class.new_name_of(up_type.base_class,up_fn);
  313.         Result := get_or_fatal_error(fn);
  314.      end;
  315.       ensure
  316.      Result /= Void;
  317.      Result.run_class = Current;
  318.       end;
  319.  
  320. feature
  321.    
  322.    base_class: BASE_CLASS is
  323.      -- Corresponding base class.
  324.       do
  325.      Result := current_type.base_class;
  326.       ensure
  327.      Result /= Void
  328.       end;
  329.    
  330.    base_class_name: CLASS_NAME is
  331.      -- Corresponding base class name.
  332.       do
  333.      Result := current_type.base_class_name;
  334.       ensure
  335.      Result /= Void
  336.       end;
  337.  
  338. feature 
  339.    
  340.    set_at_run_time is
  341.      -- Set Current `at_run_time' and do needed update of others 
  342.      -- instances of RUN_CLASS.
  343.       require
  344.      not base_class.is_deferred;
  345.      empty_eh_check
  346.       local
  347.      rcd: DICTIONARY[RUN_CLASS,STRING];
  348.      rc: RUN_CLASS;
  349.      i: INTEGER;
  350.       do
  351.      if not at_run_time  then
  352.         at_run_time := true;
  353.         compile_to_c_done := false;
  354.         add_running(Current);
  355.         small_eiffel.incr_magic_count;
  356.         if current_type.is_reference then
  357.            from
  358.           rcd := small_eiffel.run_class_dictionary;
  359.           i := 1;
  360.            until
  361.           i > rcd.count
  362.            loop
  363.           rc := rcd.item(i);
  364.           if Current.is_a(rc) then
  365.              rc.add_running(Current);
  366.           end;
  367.           i := i + 1;
  368.            end;
  369.         end;
  370.      end;
  371.       ensure
  372.      at_run_time;
  373.      running.has(Current);
  374.      empty_eh_check;
  375.       end;
  376.    
  377. feature {TYPE}
  378.  
  379.    gc_mark_to_follow: BOOLEAN is
  380.       require
  381.      at_run_time
  382.       local
  383.      i: INTEGER;
  384.      r: like running;
  385.      rc: like Current;
  386.       do
  387.      from
  388.         r := running;
  389.         i := r.upper;
  390.      until
  391.         Result or else i = 0
  392.      loop
  393.         rc := r.item(i);
  394.         if rc.at_run_time then
  395.            Result := rc.need_gc_mark;
  396.         end;
  397.         i := i - 1;
  398.      end;
  399.       end;
  400.  
  401.    gc_mark_in(str: STRING) is
  402.       require
  403.      gc_mark_to_follow
  404.       local
  405.      i: INTEGER;
  406.      wa: ARRAY[RUN_FEATURE_2];
  407.      rf2: RUN_FEATURE_2;
  408.       do
  409.      wa := writable_attributes;
  410.      if wa /= Void then
  411.         from
  412.            i := wa.upper;
  413.         until
  414.            i = 0
  415.         loop
  416.            rf2 := wa.item(i);
  417.            if rf2.result_type.run_class.at_run_time then
  418.           gc_handler.call_gc_mark(str,rf2);
  419.            end;
  420.            i := i - 1;
  421.         end;
  422.      end;
  423.       end;
  424.    
  425. feature {TYPE}
  426.  
  427.    c_object_model_in(str: STRING) is
  428.       local
  429.      wa: like writable_attributes;
  430.      i: INTEGER;
  431.      rf2: RUN_FEATURE_2;
  432.      t: TYPE;
  433.       do
  434.      wa := writable_attributes;
  435.      if wa = Void then
  436.         if is_tagged then
  437.            str.extend('{');
  438.            id.append_in(str);
  439.            str.extend('}');
  440.         else
  441.            current_type.c_initialize_in(str);
  442.         end;
  443.      else
  444.         str.extend('{');
  445.         if is_tagged then
  446.            id.append_in(str);
  447.            str.extend(',');
  448.         end;
  449.         from
  450.            i := wa.upper;
  451.         until
  452.            i = 0
  453.         loop
  454.            rf2 := wa.item(i);
  455.            t := rf2.result_type;
  456.            t.c_initialize_in(str);
  457.            i := i - 1;
  458.            if i > 0 then
  459.           str.extend(',');
  460.            end;
  461.         end;
  462.         str.extend('}');
  463.      end;
  464.       end;
  465.  
  466. feature {SMALL_EIFFEL}
  467.    
  468.    falling_down is
  469.       -- Falling down of Current `feature_dictionary' in `running'.
  470.       local
  471.      rf: RUN_FEATURE;
  472.      i: INTEGER;
  473.       do
  474.      from
  475.         i := 1;
  476.      until
  477.         i > feature_dictionary.count
  478.      loop
  479.         rf := feature_dictionary.item(i);
  480.         rf.fall_down;
  481.         i := i + 1;
  482.      end;
  483.       end;
  484.  
  485.    afd_check is
  486.      -- After Falling Down Check.
  487.       local
  488.      rf: RUN_FEATURE;
  489.      i: INTEGER;
  490.       do
  491.      from
  492.         i := 1;
  493.      until
  494.         i > feature_dictionary.count
  495.      loop
  496.         rf := feature_dictionary.item(i);
  497.         rf.afd_check;
  498.         i := i + 1;
  499.      end;
  500.       end;
  501.  
  502. feature {SMALL_EIFFEL}
  503.  
  504.    c_header_pass1 is
  505.       require
  506.      cpp.on_h
  507.       do
  508.      if at_run_time then
  509.         current_type.c_header_pass1;
  510.      end;
  511.       ensure
  512.      cpp.on_h
  513.       end;
  514.    
  515.    c_header_pass2 is
  516.       require
  517.      cpp.on_h
  518.       do
  519.      if at_run_time then
  520.         current_type.c_header_pass2;
  521.      end;
  522.       ensure
  523.      cpp.on_h
  524.       end;
  525.    
  526.    c_header_pass3 is
  527.       require
  528.      cpp.on_h
  529.       do
  530.      if at_run_time then
  531.         current_type.c_header_pass3;
  532.      end;
  533.       ensure
  534.      cpp.on_h
  535.       end;
  536.    
  537.    c_header_pass4 is
  538.       require
  539.      cpp.on_h
  540.       do
  541.      if at_run_time then
  542.         current_type.c_header_pass4;
  543.      end;
  544.       ensure
  545.      cpp.on_h
  546.       end;
  547.    
  548. feature {GC_HANDLER}
  549.  
  550.    gc_define1 is
  551.       require
  552.      gc_handler.is_on
  553.       do
  554.      if at_run_time then
  555.         current_type.gc_define1;
  556.      end;
  557.       end;
  558.    
  559.    gc_define2 is
  560.       require
  561.      gc_handler.is_on
  562.       do
  563.      if at_run_time then
  564.         current_type.gc_define2;
  565.      end;
  566.       end;
  567.    
  568.    gc_info_in(str: STRING) is
  569.      -- Produce C code to print GC information.
  570.       require
  571.      gc_handler.is_on;
  572.      gc_handler.info_flag
  573.       do
  574.      if at_run_time then
  575.         current_type.gc_info_in(str);
  576.      end;
  577.       end;
  578.  
  579.    call_gc_sweep_in(body: STRING) is
  580.       require
  581.      gc_handler.is_on
  582.       do
  583.      if at_run_time then
  584.         current_type.call_gc_sweep_in(body);
  585.      end;
  586.       end;
  587.  
  588.    gc_initialize is
  589.      -- Produce code to initialize GC in the main C function.
  590.       require
  591.      gc_handler.is_on
  592.       do
  593.      if at_run_time then
  594.         current_type.gc_initialize;
  595.      end;
  596.       end;
  597.  
  598. feature {RUN_CLASS}
  599.    
  600.    fill_up_with(rc: RUN_CLASS; fd: like feature_dictionary) is
  601.      -- Fill up `feature_dictionary' with all features coming from
  602.      -- `rc' X `fd'.
  603.       require
  604.      rc /= Current;
  605.      is_a(rc);
  606.      fd /= Void;
  607.       local
  608.      bc1, bc2: BASE_CLASS;
  609.      fn1, fn2: FEATURE_NAME;
  610.      rf: RUN_FEATURE;
  611.      i: INTEGER;
  612.       do
  613.      from
  614.         i := 1;
  615.         bc1 := rc.base_class;
  616.         bc2 := base_class;
  617.      until
  618.         i > fd.count
  619.      loop
  620.         rf := fd.item(i);
  621.         if rf.fall_in(Current) then
  622.            fn1 := rf.name;
  623.            fn2 := bc2.name_of(bc1,fn1);
  624.            rf := get_feature(fn2);
  625.         end;
  626.         i := i + 1;
  627.      end;
  628.       end;
  629.    
  630.    add_running(rc: RUN_CLASS) is
  631.       require
  632.      rc /= Void;
  633.       do
  634.      if running = Void then
  635.         running := <<rc>>;
  636.      else
  637.         if not running.fast_has(rc) then
  638.            running.add_last(rc);
  639.         end;
  640.      end;
  641.       end;
  642.    
  643.    is_a(other: like Current): BOOLEAN is
  644.      -- Does not print an error message wathever the result can be.
  645.       require
  646.      other /= Void;
  647.      empty_eh_check
  648.       local
  649.      t1, t2: TYPE;
  650.       do
  651.      if other = Current then
  652.         Result := true;
  653.      else
  654.         t1 := current_type;
  655.         t2 := other.current_type;
  656.         if t1.is_basic_eiffel_expanded and then 
  657.            t2.is_basic_eiffel_expanded then
  658.         else
  659.            Result := t1.is_a(t2);
  660.            if not Result then
  661.           eh.cancel;
  662.            end;
  663.         end;
  664.      end;
  665.       ensure
  666.      empty_eh_check;
  667.      nb_errors = old nb_errors
  668.       end;
  669.    
  670. feature 
  671.  
  672.    fill_tagged_out_memory is
  673.       do
  674.      tagged_out_memory.append(current_type.run_time_mark);
  675.       end;
  676.  
  677. feature {E_FEATURE}
  678.    
  679.    at(fn: FEATURE_NAME): RUN_FEATURE is
  680.      -- Simple look in the dictionary to see if the feature
  681.      -- is already computed.
  682.       require
  683.      fn /= Void;
  684.       local
  685.      to_key: STRING;
  686.       do
  687.      to_key := fn.to_key;
  688.      if feature_dictionary.has(to_key) then
  689.         Result := feature_dictionary.at(to_key);
  690.      end;
  691.       end;
  692.    
  693. feature 
  694.    
  695.    get_feature_with(n: STRING): RUN_FEATURE is
  696.      -- Assume that `fn' is really the final name in current 
  697.      -- RUN_CLASS. Don't look for rename.
  698.      -- Also assume that `n' is a SIMPLE_NAME.
  699.       require
  700.      n /= Void;
  701.       local
  702.      sfn: SIMPLE_FEATURE_NAME;
  703.       do
  704.      if feature_dictionary.has(n) then
  705.         Result := feature_dictionary.at(n);
  706.      else
  707.         !!sfn.make(n,Void);
  708.         Result := get_feature(sfn);
  709.      end;
  710.       end;
  711.  
  712. feature
  713.    
  714.    get_copy: RUN_FEATURE is
  715.       do
  716.      Result := get_rf_with(class_general.get_copy.first_name);
  717.       end;
  718.  
  719. feature 
  720.  
  721.    get_feature(fn: FEATURE_NAME): RUN_FEATURE is
  722.      -- Assume that `fn' is really the final name in current 
  723.      -- RUN_CLASS. Don't look for rename.
  724.       require
  725.      fn /= Void
  726.       local
  727.      f: E_FEATURE;
  728.      fn_key: STRING;
  729.      bc: BASE_CLASS;
  730.       do
  731.      fn_key := fn.to_key;
  732.      if feature_dictionary.has(fn_key) then
  733.         Result := feature_dictionary.at(fn_key);
  734.      else
  735.         check 
  736.            not small_eiffel.is_ready;
  737.         end;
  738.         bc := base_class;
  739.         f := bc.look_up_for(Current,fn);
  740.         if f = Void then
  741.            efnf(bc,fn);
  742.         else
  743.            Result := f.to_run_feature(current_type,fn);
  744.            if Result /= Void  then
  745.           store_feature(Result);
  746.            else
  747.           efnf(bc,fn);
  748.            end;
  749.         end;
  750.      end;
  751.       end;
  752.  
  753. feature {NONE}
  754.  
  755.    get_or_fatal_error(fn: FEATURE_NAME): RUN_FEATURE is
  756.       do
  757.      Result := get_feature(fn);
  758.      if Result = Void then
  759.         eh.add_position(fn.start_position);
  760.         eh.append("Feature ");
  761.         eh.append(fn.to_string);
  762.         eh.append(" not found when starting look up from ");
  763.         eh.add_type(current_type,fz_dot);
  764.         eh.print_as_fatal_error;
  765.      end;
  766.       end;
  767.    
  768. feature {NONE}
  769.    
  770.    store_feature(rf: like get_feature) is
  771.      -- To update the dictionary from outside.
  772.      -- Note : this routine is necessary because of recursive call.
  773.       require
  774.      rf.run_class = Current
  775.       local
  776.      rf_key: STRING;
  777.       do
  778.      rf_key := rf.name.to_key;
  779.      if feature_dictionary.has(rf_key) then
  780.         check
  781.            feature_dictionary.at(rf_key) = rf
  782.         end;
  783.      else
  784.         feature_dictionary.put(rf,rf_key);
  785.         small_eiffel.incr_magic_count;
  786.      end;
  787.       ensure
  788.      get_feature(rf.name) = rf
  789.       end;
  790.  
  791. feature {JVM}
  792.  
  793.    jvm_define_class_invariant is
  794.      -- If needed, call the invariant for the pushed value.
  795.       local
  796.      ia: like invariant_assertion;
  797.       do
  798.      if run_control.invariant_check then
  799.         ia := invariant_assertion;
  800.         if ia /= Void then
  801.            jvm.define_class_invariant_method(ia);
  802.         end;
  803.      end;
  804.       end;
  805.  
  806. feature {JVM,TYPE} 
  807.  
  808.    jvm_check_class_invariant is
  809.      -- If needed, call the invariant for the pushed value.
  810.       local
  811.      ia: like invariant_assertion;
  812.      idx: INTEGER;
  813.      ca: like code_attribute;
  814.      cp: like constant_pool;
  815.       do
  816.      if run_control.invariant_check then
  817.         ia := invariant_assertion;
  818.         if ia /= Void then
  819.            ca := code_attribute;
  820.            cp := constant_pool;
  821.            ca.opcode_dup;
  822.            idx := cp.idx_methodref3(fully_qualified_name,fz_invariant,fz_29);
  823.            ca.opcode_invokevirtual(idx,-1);
  824.         end;
  825.      end;
  826.       end;
  827.  
  828. feature {SMALL_EIFFEL}
  829.  
  830.    compile_to_jvm is
  831.       require
  832.      at_run_time
  833.       local
  834.      i: INTEGER;
  835.      rf: RUN_FEATURE;
  836.       do
  837.      echo.put_character('%T');
  838.      echo.put_string(current_type.run_time_mark);
  839.      echo.put_character('%N');
  840.      jvm.start_new_class(Current);
  841.      from
  842.         i := 1;
  843.      until
  844.         i > feature_dictionary.count
  845.      loop
  846.         rf := feature_dictionary.item(i);
  847.         jvm.set_current_frame(rf);
  848.         rf.jvm_field_or_method;
  849.         i := i + 1;
  850.      end;
  851.      jvm.prepare_fields;
  852.      jvm.prepare_methods;
  853.      jvm.finish_class;
  854.       end;
  855.  
  856. feature {MANIFEST_ARRAY}
  857.  
  858.    fully_qualified_name: STRING is
  859.       do
  860.      tmp_string.copy(jvm.output_name);
  861.      tmp_string.extend('/');
  862.      tmp_string.append(unqualified_name);
  863.      Result := tmp_string;
  864.       end;
  865.  
  866. feature {RUN_FEATURE}
  867.  
  868.    jvm_invoke(idx, stack_level: INTEGER) is
  869.       local
  870.      ct: like current_type;
  871.       do
  872.      ct := current_type;
  873.      if ct.is_reference then
  874.         code_attribute.opcode_invokevirtual(idx,stack_level);
  875.      elseif ct.is_basic_eiffel_expanded then
  876.         code_attribute.opcode_invokestatic(idx,stack_level);
  877.      elseif writable_attributes = Void then
  878.         code_attribute.opcode_invokestatic(idx,stack_level);
  879.      else
  880.         code_attribute.opcode_invokevirtual(idx,stack_level);
  881.      end;
  882.       end;
  883.  
  884. feature {TYPE}
  885.  
  886.    jvm_expanded_return_code is
  887.       require
  888.      is_expanded
  889.       do
  890.      if writable_attributes = Void then
  891.         code_attribute.opcode_ireturn;
  892.      else
  893.         code_attribute.opcode_areturn;
  894.      end;
  895.       end;
  896.  
  897.    jvm_expanded_push_local(offset: INTEGER) is
  898.       require
  899.      is_expanded
  900.       do
  901.      if writable_attributes = Void then
  902.         code_attribute.opcode_iload(offset);
  903.      else
  904.         code_attribute.opcode_aload(offset);
  905.      end;
  906.       end;
  907.    
  908.    jvm_expanded_write_local(offset: INTEGER) is
  909.       require
  910.      is_expanded
  911.       do
  912.      if writable_attributes = Void then
  913.         code_attribute.opcode_istore(offset);
  914.      else
  915.         code_attribute.opcode_astore(offset);
  916.      end;
  917.       end;
  918.  
  919.    jvm_expanded_xastore is
  920.       require
  921.      is_expanded
  922.       do
  923.      if writable_attributes = Void then
  924.         code_attribute.opcode_bastore;
  925.      else
  926.         code_attribute.opcode_aastore;
  927.      end;
  928.       end;
  929.    
  930.    jvm_expanded_xaload is
  931.       require
  932.      is_expanded
  933.       do
  934.      if writable_attributes = Void then
  935.         code_attribute.opcode_baload;
  936.      else
  937.         code_attribute.opcode_aaload;
  938.      end;
  939.       end;
  940.    
  941.    jvm_expanded_if_x_eq: INTEGER is
  942.       require
  943.      is_expanded
  944.       do
  945.      if writable_attributes = Void then
  946.         Result := code_attribute.opcode_if_icmpeq;
  947.      else
  948.         Result := code_attribute.opcode_if_acmpeq;
  949.      end;
  950.       end;
  951.    
  952.    jvm_expanded_if_x_ne: INTEGER is
  953.       require
  954.      is_expanded
  955.       do
  956.      if writable_attributes = Void then
  957.         Result := code_attribute.opcode_if_icmpne;
  958.      else
  959.         Result := code_attribute.opcode_if_acmpne;
  960.      end;
  961.       end;
  962.    
  963. feature
  964.  
  965.    jvm_expanded_descriptor_in(str: STRING) is
  966.      -- Append the good descriptor in `str' when `current_type'
  967.      -- `is_expanded'.
  968.       require
  969.      current_type.is_expanded;
  970.      str /= Void
  971.       local
  972.      ct: TYPE;
  973.       do
  974.      ct := current_type;
  975.      if ct.is_user_expanded then
  976.         if writable_attributes = Void then
  977.            str.extend('B');
  978.         else
  979.            str.append(jvm_root_descriptor);
  980.         end;
  981.      else
  982.         ct.jvm_descriptor_in(str);
  983.      end;
  984.       end;
  985.  
  986. feature
  987.  
  988.    jvm_push_default is
  989.      -- Poduce bytecode to push the default value.
  990.       require
  991.      current_type.is_reference
  992.       local
  993.      i, idx: INTEGER;
  994.      wa: ARRAY[RUN_FEATURE_2];
  995.      rf2: RUN_FEATURE_2;
  996.      t2: TYPE;
  997.      ca: like code_attribute;
  998.      cp: like constant_pool;
  999.       do
  1000.      ca := code_attribute;
  1001.      idx := fully_qualified_constant_pool_index;
  1002.      ca.opcode_new(idx);
  1003.      wa := writable_attributes;
  1004.      if wa /= Void then
  1005.         from
  1006.            i := wa.upper;
  1007.            cp := constant_pool;
  1008.         until
  1009.            i = 0
  1010.         loop
  1011.            rf2 := wa.item(i);
  1012.            t2 := rf2.result_type.run_type;
  1013.            if t2.is_user_expanded then
  1014.           ca.opcode_dup;
  1015.           t2.run_class.jvm_expanded_push_default;
  1016.           idx := cp.idx_fieldref(rf2);
  1017.           ca.opcode_putfield(idx,-2);
  1018.            elseif t2.is_bit then
  1019.           ca.opcode_dup;
  1020.           idx := t2.jvm_push_default;
  1021.           idx := cp.idx_fieldref(rf2);
  1022.           ca.opcode_putfield(idx,-2);
  1023.            end;
  1024.            i := i - 1;
  1025.         end;
  1026.      end;
  1027.       end;
  1028.  
  1029.    jvm_expanded_push_default is
  1030.      -- Push the corresponding new user's expanded (either dummy 
  1031.      -- or not, initializer is automatically applied).
  1032.       require
  1033.      current_type.is_user_expanded
  1034.       local
  1035.      ca: like code_attribute;
  1036.      rf: RUN_FEATURE;
  1037.      wa: ARRAY[RUN_FEATURE_2];
  1038.      rf2: RUN_FEATURE_2;
  1039.      idx, i: INTEGER;
  1040.      t: TYPE;
  1041.       do
  1042.      ca := code_attribute;
  1043.      wa := writable_attributes;
  1044.      if wa = Void then
  1045.         ca.opcode_iconst_0;
  1046.      else
  1047.         idx := fully_qualified_constant_pool_index;
  1048.         code_attribute.opcode_new(idx);
  1049.         from
  1050.            i := wa.upper;
  1051.         until
  1052.            i = 0
  1053.         loop
  1054.            rf2 := wa.item(i);
  1055.            t := rf2.result_type;
  1056.            if t.is_user_expanded then
  1057.           ca.opcode_dup;
  1058.           t.run_class.jvm_expanded_push_default;
  1059.           idx := constant_pool.idx_fieldref(rf2);
  1060.           ca.opcode_putfield(idx,-2);
  1061.            end;
  1062.            i := i - 1;
  1063.         end;
  1064.      end;
  1065.      rf := base_class.expanded_initializer(current_type);
  1066.      if rf /= Void then
  1067.         jvm.push_expanded_initialize(rf);
  1068.         rf.mapping_jvm;
  1069.         jvm.pop;
  1070.      end;
  1071.       end;
  1072.  
  1073. feature {JVM}
  1074.  
  1075.    unqualified_name: STRING is
  1076.       local
  1077.      ct: TYPE;
  1078.      type_bit: TYPE_BIT;
  1079.       do
  1080.      -- *** DISPATCHER DANS TYPE_* ???
  1081.      ct := current_type;
  1082.      if ct.is_generic then
  1083.         ucpn.clear;
  1084.         ucpn.extend('_');
  1085.         ucpn.append(ct.base_class_name.to_string);
  1086.         ucpn.to_lower;
  1087.         id.append_in(ucpn);
  1088.      elseif ct.is_bit then
  1089.         type_bit ?= ct;
  1090.         ucpn.copy(us_bit);
  1091.         type_bit.nb.append_in(ucpn);
  1092.         ucpn.to_lower;
  1093.      else
  1094.         ucpn.copy(ct.base_class_name.to_string);
  1095.         ucpn.to_lower;
  1096.      end;
  1097.      Result := ucpn;
  1098.       end;
  1099.  
  1100. feature
  1101.  
  1102.    fully_qualified_constant_pool_index: INTEGER is
  1103.       do
  1104.      Result := constant_pool.idx_class2(fully_qualified_name);
  1105.       end;
  1106.  
  1107. feature {SMALL_EIFFEL,TYPE}
  1108.  
  1109.    demangling is
  1110.       require
  1111.      cpp.on_h
  1112.       local
  1113.      str: STRING;
  1114.      r: like running;
  1115.      i: INTEGER;
  1116.       do
  1117.      str := "";
  1118.      str.clear;
  1119.      if at_run_time then
  1120.         str.extend('A');
  1121.         if current_type.is_reference and then not is_tagged then
  1122.            str.extend('*');
  1123.         else
  1124.            str.extend(' ');
  1125.         end;
  1126.      else
  1127.         str.extend('D');
  1128.         str.extend(' ');
  1129.      end;
  1130.      r := running;
  1131.      if r /= Void then
  1132.         r.count.append_in(str);
  1133.      end;
  1134.      from
  1135.      until
  1136.         str.count > 4
  1137.      loop
  1138.         str.extend(' ');
  1139.      end;
  1140.      str.extend('T');
  1141.      id.append_in(str);
  1142.      from
  1143.      until
  1144.         str.count > 10
  1145.      loop
  1146.         str.extend(' ');
  1147.      end;
  1148.      current_type.demangling_in(str);
  1149.      if r /= Void then
  1150.         from
  1151.            str.extend(' ');
  1152.            i := r.upper;
  1153.         until
  1154.            i = 0
  1155.         loop
  1156.            r.item(i).id.append_in(str);
  1157.            i := i - 1;
  1158.            if i > 0 then
  1159.           str.extend(',');
  1160.            end;
  1161.         end;
  1162.      end;
  1163.      str.extend('%N');
  1164.      cpp.put_string(str);
  1165.       ensure
  1166.      cpp.on_h
  1167.       end;
  1168.  
  1169. feature {SMALL_EIFFEL,RUN_CLASS}
  1170.  
  1171.    compile_to_c(deep: INTEGER) is
  1172.      -- Produce C code for features of Current. The `deep'
  1173.      -- indicator is used to sort the C output in the best order 
  1174.      -- (more C  inlinings are possible when basic functions are 
  1175.      -- produced first). As there is not always a total order 
  1176.      -- between clients, the `deep' avoid infinite track.
  1177.      -- When `deep' is greater than 0, C code writting 
  1178.          -- is produced whatever the real client relation is.
  1179.       require
  1180.      cpp.on_c;
  1181.      deep >= 0
  1182.       local
  1183.      i: INTEGER;
  1184.      rc1, rc2: like Current;
  1185.      cc1, cc2: INTEGER;
  1186.       do
  1187.      if compile_to_c_done then
  1188.      elseif not at_run_time then
  1189.         compile_to_c_done := true;
  1190.      elseif deep = 0 then
  1191.         really_compile_to_c;
  1192.      else
  1193.         i := actuals_clients.upper;
  1194.         if i >= 0 then
  1195.            from
  1196.           rc1 := Current;
  1197.           cc1 := i + 1;
  1198.            until
  1199.           i = 0
  1200.            loop
  1201.           rc2 := actuals_clients.item(i);
  1202.           if not rc2.compile_to_c_done then
  1203.              cc2 := rc2.actuals_clients.count;
  1204.              if cc2 > cc1 then
  1205.             rc1 := rc2;
  1206.             cc1 := cc2;
  1207.              end;
  1208.           end;
  1209.           i := i - 1;
  1210.            end;
  1211.            if rc1 = Current then
  1212.           really_compile_to_c;
  1213.            else
  1214.           rc1.compile_to_c(deep - 1);
  1215.            end;
  1216.         end;
  1217.      end;
  1218.       ensure
  1219.      cpp.on_c
  1220.       end;
  1221.  
  1222. feature {NONE}
  1223.  
  1224.    really_compile_to_c is
  1225.       require
  1226.      at_run_time
  1227.       local
  1228.      i: INTEGER;
  1229.      rf: RUN_FEATURE;
  1230.       do
  1231.      compile_to_c_done := true;
  1232.      cpp.split_c_start_run_class;
  1233.      echo.put_character('%T');
  1234.      echo.put_string(current_type.run_time_mark);
  1235.      echo.put_character('%N');
  1236.      from
  1237.         i := 1;
  1238.      until
  1239.         i > feature_dictionary.count
  1240.      loop
  1241.         rf := feature_dictionary.item(i);
  1242.         rf.c_define;
  1243.         i := i + 1;
  1244.      end;
  1245.      if run_control.invariant_check then
  1246.         if invariant_assertion /= Void then
  1247.            invariant_assertion.c_define;
  1248.         end;
  1249.      end;
  1250.       ensure
  1251.      compile_to_c_done
  1252.       end;
  1253.  
  1254. feature {RUN_CLASS}
  1255.  
  1256.    actuals_clients: FIXED_ARRAY[RUN_CLASS];
  1257.  
  1258. feature {RUN_FEATURE}
  1259.  
  1260.    add_client(rc: RUN_CLASS) is
  1261.       require
  1262.      rc /= Void
  1263.       local
  1264.      i: INTEGER;
  1265.       do
  1266.      i := actuals_clients.fast_index_of(rc);
  1267.      if i > actuals_clients.upper then
  1268.         actuals_clients.add_last(rc);
  1269.      end;
  1270.       end;
  1271.    
  1272. feature {BASE_CLASS}
  1273.    
  1274.    collect_invariant(ia: like invariant_assertion) is
  1275.       require
  1276.      ia /= Void;
  1277.       do
  1278.      ia.add_into(ci_collector);
  1279.       end;
  1280.  
  1281. feature {NONE}   
  1282.    
  1283.    writable_attributes_mem: like writable_attributes;
  1284.    
  1285.    ci_collector: ARRAY[ASSERTION] is
  1286.      -- The Class Invariant Collector.
  1287.       once
  1288.      !!Result.make(1,10);
  1289.       end;
  1290.  
  1291. feature 
  1292.  
  1293.    offset_of(rf2: RUN_FEATURE_2): INTEGER is
  1294.      -- Compute the displacement to access `rf2' in the corresponding 
  1295.      -- C struct to remove a possible stupid switch.
  1296.      -- Result is in number of bytes.
  1297.       require
  1298.      at_run_time;
  1299.      writable_attributes.fast_has(rf2);
  1300.      small_eiffel.is_ready
  1301.       local
  1302.      wa: like writable_attributes;
  1303.      t: TYPE;
  1304.      i: INTEGER;
  1305.       do
  1306.      if is_tagged then
  1307.         Result := (1).object_size;
  1308.      end;
  1309.      from
  1310.         wa := writable_attributes;
  1311.         i := wa.upper;
  1312.      invariant
  1313.         i > 0
  1314.      until
  1315.         wa.item(i) = rf2
  1316.      loop
  1317.         t := wa.item(i).result_type;
  1318.         Result := Result + t.space_for_variable;
  1319.         i := i - 1;
  1320.      end;
  1321.       end;
  1322.  
  1323. feature {NONE}
  1324.  
  1325.    sort_wam(wam: like writable_attributes) is
  1326.      -- Sort `wam' to common attribute at the end.
  1327.       require
  1328.      wam.lower = 1
  1329.       local
  1330.      min, max, buble: INTEGER;
  1331.      moved: BOOLEAN;
  1332.       do
  1333.      from  
  1334.         max := wam.upper;
  1335.         min := 1;
  1336.         moved := true;
  1337.      until
  1338.         not moved
  1339.      loop
  1340.         moved := false;
  1341.         if max - min > 0 then
  1342.            from  
  1343.           buble := min + 1;
  1344.            until
  1345.           buble > max
  1346.            loop
  1347.           if gt(wam.item(buble - 1),wam.item(buble)) then
  1348.              wam.swap(buble - 1,buble);
  1349.              moved := true;
  1350.           end;
  1351.           buble := buble + 1;
  1352.            end;
  1353.            max := max - 1;
  1354.         end;
  1355.         if moved and then max - min > 0 then
  1356.            from  
  1357.           moved := false;
  1358.           buble := max - 1;
  1359.            until
  1360.           buble < min
  1361.            loop
  1362.           if gt(wam.item(buble),wam.item(buble + 1)) then
  1363.              wam.swap(buble,buble + 1);
  1364.              moved := true;
  1365.           end;
  1366.           buble := buble - 1;
  1367.            end;
  1368.            min := min + 1;
  1369.         end;
  1370.      end;
  1371.       end;
  1372.  
  1373.    gt(rf1, rf2: RUN_FEATURE_2): BOOLEAN is
  1374.      -- True if it is better to set attribute `rf1' before
  1375.      -- attribute `rf2'.
  1376.       local
  1377.      bc1, bc2: BASE_CLASS;
  1378.      bf1, bf2: E_FEATURE;
  1379.      bcn1, bcn2: CLASS_NAME;
  1380.       do
  1381.      bf1 := rf1.base_feature;
  1382.      bf2 := rf2.base_feature;
  1383.      bc1 := bf1.base_class;
  1384.      bc2 := bf2.base_class;
  1385.      bcn1 := bc1.base_class_name;
  1386.      bcn2 := bc2.base_class_name;
  1387.      if bcn1.to_string = bcn2.to_string then
  1388.         Result := bf1.start_position.before(bf2.start_position);
  1389.      elseif bcn2.is_subclass_of(bcn1) then
  1390.         Result := true;
  1391.      elseif bcn1.is_subclass_of(bcn2) then
  1392.      elseif bc1.parent_list = Void then
  1393.         if bc2.parent_list = Void then
  1394.            Result := bcn1.to_string < bcn2.to_string;
  1395.         else
  1396.            Result := true;
  1397.         end;
  1398.      elseif bc2.parent_list = Void then
  1399.      else
  1400.         Result := bc2.parent_list.count < bc1.parent_list.count 
  1401.      end;
  1402.       end;
  1403.  
  1404. feature {NONE}
  1405.  
  1406.    efnf(bc: BASE_CLASS; fn: FEATURE_NAME) is
  1407.       require
  1408.      bc /= Void;
  1409.      fn /= Void
  1410.       do
  1411.      eh.append("Current type is ");
  1412.      eh.append(current_type.run_time_mark);
  1413.      eh.append(". There is no feature ");
  1414.      eh.append(fn.to_string);
  1415.      eh.append(" in class ");
  1416.      eh.append(bc.base_class_name.to_string);
  1417.      error(fn.start_position,fz_dot);
  1418.       end;
  1419.  
  1420. feature {NONE}
  1421.  
  1422.    tmp_string: STRING is
  1423.       once
  1424.      !!Result.make(32);
  1425.       end;
  1426.  
  1427. feature {NONE}
  1428.  
  1429.    ucpn: STRING is
  1430.       once
  1431.      !!Result.make(32);
  1432.       end;
  1433.  
  1434. feature {RUN_CLASS}
  1435.  
  1436.    need_gc_mark: BOOLEAN is
  1437.       require
  1438.      at_run_time
  1439.       local
  1440.      i: INTEGER;
  1441.      wa: like writable_attributes;
  1442.      rf2: RUN_FEATURE_2;
  1443.      t: TYPE;
  1444.      rc: RUN_CLASS;
  1445.       do
  1446.      wa := writable_attributes;
  1447.      if wa /= Void then
  1448.         from
  1449.            i := wa.upper;
  1450.         until
  1451.            Result or else i = 0
  1452.         loop
  1453.            rf2 := wa.item(i);
  1454.            t := rf2.result_type;
  1455.            Result := t.need_gc_mark_function;
  1456.            i := i - 1;
  1457.         end;
  1458.      end;
  1459.       end;
  1460.  
  1461. invariant
  1462.    
  1463.    current_type.run_type = current_type;
  1464.    
  1465.    current_type.is_expanded implies running.is_equal(<<Current>>)
  1466.  
  1467. end -- RUN_CLASS
  1468.  
  1469.