home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_se / type_generic.e < prev    next >
Text File  |  1999-06-05  |  17KB  |  697 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 TYPE_GENERIC
  17.    --
  18.    -- For all generic declarations (except ARRAY) :
  19.    --        x : FOO[BAR];
  20.    --
  21.  
  22. inherit  TYPE;
  23.  
  24. creation make
  25.  
  26. creation {TYPE_GENERIC} make_runnable
  27.  
  28. feature
  29.  
  30.    base_class_name: CLASS_NAME;
  31.  
  32.    generic_list: ARRAY[TYPE];
  33.  
  34.    written_mark: STRING;
  35.  
  36. feature {NONE}
  37.  
  38.    run_type_memory: like Current;
  39.          -- The final `is_written_runnable' corresponding type when runnable.
  40.  
  41. feature
  42.  
  43.    is_generic: BOOLEAN is true;
  44.  
  45.    is_basic_eiffel_expanded: BOOLEAN is false;
  46.  
  47.    is_array: BOOLEAN is false;
  48.  
  49.    is_none: BOOLEAN is false;
  50.  
  51.    is_any: BOOLEAN is false;
  52.  
  53.    is_like_current: BOOLEAN is false;
  54.  
  55.    is_like_argument: BOOLEAN is false;
  56.  
  57.    is_like_feature: BOOLEAN is false;
  58.  
  59.    jvm_method_flags: INTEGER is 17;
  60.  
  61. feature {NONE}
  62.  
  63.    make(bcn: like base_class_name; gl: like generic_list) is
  64.       require
  65.          bcn /= Void;
  66.          gl.lower = 1;
  67.          not gl.empty
  68.       local
  69.          i: INTEGER;
  70.          t: TYPE;
  71.       do
  72.          base_class_name := bcn;
  73.          generic_list := gl;
  74.          from
  75.             tmp_mark.copy(bcn.to_string);
  76.             tmp_mark.extend('[');
  77.             i := 1;
  78.          until
  79.             i > gl.upper
  80.          loop
  81.             t := gl.item(i);
  82.             tmp_mark.append(t.written_mark);
  83.             i := i + 1;
  84.             if i <= gl.upper then
  85.                tmp_mark.extend(',');
  86.             end;
  87.          end;
  88.          tmp_mark.extend(']');
  89.          written_mark := string_aliaser.item(tmp_mark);
  90.       ensure
  91.          base_class_name = bcn;
  92.          generic_list = gl;
  93.          written_mark /= Void
  94.       end;
  95.  
  96.    make_runnable(model: like Current; gl: like generic_list) is
  97.       local
  98.          i: INTEGER;
  99.          t: TYPE;
  100.       do
  101.          base_class_name := model.base_class_name;
  102.          generic_list := gl;
  103.          from
  104.             tmp_mark.copy(base_class_name.to_string);
  105.             tmp_mark.extend('[');
  106.             i := 1;
  107.          until
  108.             i > gl.upper
  109.          loop
  110.             t := gl.item(i);
  111.             tmp_mark.append(t.run_time_mark);
  112.             i := i + 1;
  113.             if i <= gl.upper then
  114.                tmp_mark.extend(',');
  115.             end;
  116.          end;
  117.          tmp_mark.extend(']');
  118.          written_mark := string_aliaser.item(tmp_mark);
  119.          run_type_memory := Current;
  120.       ensure
  121.          written_mark = run_time_mark;
  122.          is_written_runnable
  123.       end;
  124.  
  125. feature
  126.  
  127.    static_base_class_name: CLASS_NAME is
  128.       do
  129.          Result := base_class_name;
  130.       end;
  131.  
  132.    is_written_runnable: BOOLEAN is
  133.       local
  134.          i: INTEGER;
  135.          t: TYPE;
  136.       do
  137.          if run_type_memory = Current then
  138.             Result := true;
  139.          elseif run_type_memory = Void then
  140.             from
  141.                Result := true;
  142.                i := generic_list.upper;
  143.             until
  144.                not Result or else i = 0
  145.             loop
  146.                t := generic_list.item(i);
  147.                if t.is_run_type then
  148.                   if t.run_type = t then
  149.                   else
  150.                      Result := false;
  151.                   end;
  152.                else
  153.                   Result := false;
  154.                end;
  155.                i := i - 1;
  156.             end;
  157.             if Result then
  158.                run_type_memory := Current;
  159.                basic_checks;
  160.             end;
  161.          end;
  162.       end;
  163.  
  164.    is_run_type: BOOLEAN is
  165.       do
  166.          if run_type_memory /= Void then
  167.             Result := true;
  168.          elseif is_written_runnable then
  169.             Result := true;
  170.          end;
  171.       end;
  172.  
  173.    run_type: like Current is
  174.       do
  175.          if is_run_type then
  176.             Result := run_type_memory;
  177.          end;
  178.       end;
  179.  
  180.    run_class: RUN_CLASS is
  181.       do
  182.          if is_run_type then
  183.             Result := small_eiffel.run_class(run_type_memory);
  184.          end;
  185.       end;
  186.  
  187.    to_runnable(ct: TYPE): like Current is
  188.       local
  189.          i: INTEGER;
  190.          rgl: like generic_list;
  191.          t1, t2: TYPE;
  192.          rt: like Current;
  193.       do
  194.          if is_written_runnable then
  195.             Result := Current;
  196.          else
  197.             from
  198.                rgl := generic_list.twin;
  199.                i := rgl.upper;
  200.             until
  201.                i = 0
  202.             loop
  203.                t1 := rgl.item(i);
  204.                t2 := t1.to_runnable(ct);
  205.                if t2 = Void or else not t2.is_run_type then
  206.                   eh.add_type(t1,fz_is_invalid);
  207.                   eh.print_as_error;
  208.                   i := 0;
  209.                else
  210.                   rgl.put(t2,i);
  211.                end;
  212.                t2 := t2.run_type;
  213.                if t2.is_expanded then
  214.                   t2.run_class.set_at_run_time;
  215.                end;
  216.                i := i - 1;
  217.             end;
  218.             !!rt.make_runnable(Current,rgl);
  219.             if run_type_memory = Void then
  220.                run_type_memory := rt;
  221.                Result := Current;
  222.             else
  223.                Result := twin;
  224.                Result.set_run_type_memory(rt);
  225.             end;
  226.             Result.run_type.basic_checks;
  227.          end;
  228.       end;
  229.  
  230.    space_for_variable: INTEGER is
  231.       do
  232.          if is_reference then
  233.             Result := space_for_pointer;
  234.          else
  235.             Result := standard_space_for_object;
  236.          end;
  237.       end;
  238.  
  239.    space_for_object: INTEGER is
  240.       do
  241.          Result := standard_space_for_object;
  242.       end;
  243.  
  244.    expanded_initializer: RUN_FEATURE_3 is
  245.       do
  246.          if is_expanded then
  247.             Result := base_class.expanded_initializer(Current);
  248.          end;
  249.       end;
  250.  
  251.    is_expanded: BOOLEAN is
  252.       do
  253.          Result := base_class.is_expanded;
  254.       end;
  255.  
  256.    is_reference: BOOLEAN is
  257.       do
  258.          Result := not base_class.is_expanded;
  259.       end;
  260.  
  261.    is_user_expanded: BOOLEAN is
  262.       do
  263.          Result := base_class.is_expanded;
  264.       end;
  265.  
  266.    is_dummy_expanded: BOOLEAN is
  267.       do
  268.          if is_user_expanded then
  269.             Result := run_class.writable_attributes = Void;
  270.          end;
  271.       end;
  272.  
  273.    id: INTEGER is
  274.       do
  275.          Result := run_class.id;
  276.       end;
  277.  
  278.    run_time_mark: STRING is
  279.       do
  280.          if is_run_type then
  281.             Result := run_type_memory.written_mark;
  282.          end;
  283.       end;
  284.  
  285.    used_as_reference is
  286.       do
  287.          if is_expanded then
  288.             run_class.used_as_reference;
  289.          end;
  290.       end;
  291.  
  292.    to_reference is
  293.       do
  294.          if is_expanded then
  295.             cpp.to_reference(Current,run_class.to_reference);
  296.          end;
  297.       end;
  298.  
  299.    jvm_descriptor_in(str: STRING) is
  300.       do
  301.          if is_reference then
  302.             str.append(jvm_root_descriptor);
  303.          else
  304.             run_class.jvm_type_descriptor_in(str);
  305.          end;
  306.       end;
  307.  
  308.    jvm_target_descriptor_in(str: STRING) is
  309.       do
  310.       end;
  311.  
  312.    jvm_return_code is
  313.       do
  314.          code_attribute.opcode_areturn;
  315.       end;
  316.  
  317.    jvm_check_class_invariant is
  318.       do
  319.          standard_jvm_check_class_invariant;
  320.       end;
  321.  
  322.    jvm_push_local(offset: INTEGER) is
  323.       do
  324.          code_attribute.opcode_aload(offset);
  325.       end;
  326.  
  327.    jvm_push_default: INTEGER is
  328.       do
  329.          Result := 1;
  330.          if is_expanded then
  331.             run_class.jvm_expanded_push_default;
  332.          else
  333.             code_attribute.opcode_aconst_null;
  334.          end;
  335.       end;
  336.  
  337.    jvm_write_local(offset: INTEGER) is
  338.       do
  339.          code_attribute.opcode_astore(offset);
  340.       end;
  341.  
  342.    jvm_xnewarray is
  343.       local
  344.          idx: INTEGER;
  345.       do
  346.          if is_reference then
  347.             idx := constant_pool.idx_jvm_root_class;
  348.          else
  349.             check
  350.                is_user_expanded
  351.             end;
  352.             idx := run_class.jvm_constant_pool_index;
  353.          end;
  354.          code_attribute.opcode_anewarray(idx);
  355.       end;
  356.  
  357.    jvm_xastore is
  358.       do
  359.          code_attribute.opcode_aastore;
  360.       end;
  361.  
  362.    jvm_xaload is
  363.       do
  364.          code_attribute.opcode_aaload;
  365.       end;
  366.  
  367.    jvm_if_x_eq: INTEGER is
  368.       do
  369.          Result := code_attribute.opcode_if_acmpeq;
  370.       end;
  371.  
  372.    jvm_if_x_ne: INTEGER is
  373.       do
  374.          Result := code_attribute.opcode_if_acmpne;
  375.       end;
  376.  
  377.    jvm_to_reference is
  378.       do
  379.       end;
  380.  
  381.    jvm_expanded_from_reference(other: TYPE): INTEGER is
  382.       do
  383.          check
  384.             false
  385.          end;
  386.       end;
  387.  
  388.    jvm_convert_to(destination: TYPE): INTEGER is
  389.       do
  390.          if is_reference then
  391.             if destination.is_reference then
  392.                Result := 1;
  393.             else
  394.                Result := destination.jvm_expanded_from_reference(Current)
  395.             end;
  396.          elseif destination.is_reference then
  397.             jvm_to_reference;
  398.             Result := 1;
  399.          else
  400.             Result := 1;
  401.          end;
  402.       end;
  403.  
  404.    jvm_standard_is_equal is
  405.       local
  406.          rc: RUN_CLASS;
  407.          wa: ARRAY[RUN_FEATURE_2];
  408.       do
  409.          rc := run_class;
  410.          wa := rc.writable_attributes;
  411.          jvm.std_is_equal(rc,wa);
  412.       end;
  413.  
  414.    c_header_pass1 is
  415.       do
  416.          standard_c_typedef;
  417.       end;
  418.  
  419.    c_header_pass2 is
  420.       do
  421.       end;
  422.  
  423.    c_header_pass3 is
  424.       do
  425.          if is_expanded then
  426.             if need_c_struct then
  427.                standard_c_struct;
  428.             end;
  429.             standard_c_object_model;
  430.          end;
  431.       end;
  432.  
  433.    c_header_pass4 is
  434.       do
  435.          if is_reference then
  436.             if need_c_struct then
  437.                standard_c_struct;
  438.                standard_c_object_model;
  439.             end;
  440.          end;
  441.          standard_c_print_function;
  442.       end;
  443.  
  444.    c_initialize is
  445.       do
  446.          if run_type_memory.is_expanded then
  447.             c_initialize_expanded;
  448.          else
  449.             cpp.put_string(fz_null);
  450.          end;
  451.       end;
  452.  
  453.    c_initialize_in(str: STRING) is
  454.       do
  455.          if is_expanded then
  456.             if need_c_struct then
  457.                run_class.c_object_model_in(str);
  458.             else
  459.                str.extend('0');
  460.             end;
  461.          else
  462.             str.append(fz_null);
  463.          end;
  464.       end;
  465.  
  466.    smallest_ancestor(other: TYPE): TYPE is
  467.       local
  468.          rto: TYPE;
  469.       do
  470.          rto := other.run_type;
  471.          if other.is_none then
  472.             Result := Current;
  473.          elseif rto.is_any then
  474.             Result := rto;
  475.          elseif rto.is_a(run_type) then
  476.             Result := run_type_memory;
  477.          else
  478.             eh.cancel;
  479.             if run_type.is_a(rto) then
  480.                Result := rto;
  481.             else
  482.                eh.cancel;
  483.                if rto.is_generic then
  484.                   Result := type_any;
  485.                   -- *** PAS FIN DU TOUT ;-)
  486.                   -- *** FAIRE COMME DANS TYPE_CLASS.
  487.                else
  488.                   Result := rto.smallest_ancestor(Current);
  489.                end;
  490.             end;
  491.          end;
  492.       end;
  493.  
  494.    is_a(other: TYPE): BOOLEAN is
  495.       local
  496.          i: INTEGER;
  497.          t1, t2: TYPE;
  498.       do
  499.          if other.is_none then
  500.          elseif run_class = other.run_class then
  501.             Result := true;
  502.          elseif other.is_generic then
  503.             if base_class = other.base_class then
  504.                from
  505.                   Result := true;
  506.                   i := generic_list.upper
  507.                until
  508.                   not Result or else i = 0
  509.                loop
  510.                   t1 := generic_list.item(i).run_type;
  511.                   t2 := other.generic_list.item(i).run_type;
  512.                   if t1.is_a(t2) then
  513.                      i := i - 1;
  514.                   else
  515.                      Result := false;
  516.                      eh.append(fz_bga);
  517.                   end;
  518.                end;
  519.             elseif base_class.is_subclass_of(other.base_class) then
  520.                Result := base_class.is_a_vncg(Current,other);
  521.             end;
  522.          else
  523.             check
  524.                not other.is_generic;
  525.             end;
  526.             if base_class.is_subclass_of(other.base_class) then
  527.                Result := true;
  528.             end;
  529.          end;
  530.          if not Result then
  531.             eh.add_type(Current,fz_inako);
  532.             eh.add_type(other," (TYPE_GENERIC).");
  533.          end;
  534.       end;
  535.  
  536.    start_position: POSITION is
  537.       do
  538.          Result := base_class_name.start_position;
  539.       end;
  540.  
  541.    need_c_struct: BOOLEAN is
  542.       do
  543.          if is_dummy_expanded then
  544.          elseif is_expanded then
  545.             Result := true;
  546.          elseif run_class.is_tagged then
  547.             Result := true;
  548.          else
  549.             Result := run_class.writable_attributes /= Void;
  550.          end;
  551.       end;
  552.  
  553.    c_type_for_argument_in(str: STRING) is
  554.       do
  555.          if is_reference then
  556.             str.append(fz_t0_star);
  557.          elseif is_dummy_expanded then
  558.             str.append(fz_int);
  559.          else
  560.             str.extend('T');
  561.             id.append_in(str);
  562.             str.extend('*');
  563.          end;
  564.       end;
  565.  
  566.    c_type_for_target_in(str: STRING) is
  567.       do
  568.          if is_dummy_expanded then
  569.             str.append(fz_int);
  570.          else
  571.             str.extend('T');
  572.             id.append_in(str);
  573.             str.extend('*');
  574.          end;
  575.       end;
  576.  
  577.    c_type_for_result_in(str: STRING) is
  578.       do
  579.          if is_reference then
  580.             str.append(fz_t0_star);
  581.          elseif is_dummy_expanded then
  582.             str.append(fz_int);
  583.          else
  584.             str.extend('T');
  585.             id.append_in(str);
  586.          end;
  587.       end;
  588.  
  589.    has_creation(fn: FEATURE_NAME): BOOLEAN is
  590.       do
  591.          Result := base_class.has_creation(fn);
  592.       end;
  593.  
  594. feature {RUN_CLASS,TYPE}
  595.  
  596.    need_gc_mark_function: BOOLEAN is
  597.       do
  598.          if is_reference then
  599.             Result := true;
  600.          else
  601.             Result := run_class.gc_mark_to_follow;
  602.          end;
  603.       end;
  604.  
  605.    just_before_gc_mark_in(str: STRING) is
  606.       do
  607.          if is_reference then
  608.             standard_just_before_gc_mark_in(str);
  609.          end;
  610.       end;
  611.  
  612.    gc_info_in(str: STRING) is
  613.       do
  614.          if is_reference then
  615.             standard_gc_info_in(str);
  616.          end;
  617.       end;
  618.  
  619.    gc_define1 is
  620.       do
  621.          if is_reference then
  622.             standard_gc_define1;
  623.          end;
  624.       end;
  625.  
  626.    gc_define2 is
  627.       do
  628.          if is_reference then
  629.             standard_gc_define2;
  630.          else
  631.             standard_gc_define2_for_expanded;
  632.          end;
  633.       end;
  634.  
  635. feature {TYPE_GENERIC}
  636.  
  637.    basic_checks is
  638.       local
  639.          bc: BASE_CLASS;
  640.          fgl: FORMAL_GENERIC_LIST;
  641.       do
  642.          bc := base_class;
  643.          fgl := bc.formal_generic_list;
  644.          if fgl = Void then
  645.             eh.add_position(start_position);
  646.             eh.append(bc.name.to_string);
  647.             fatal_error(" is not a generic class.");
  648.          elseif fgl.count /= generic_list.count then
  649.             eh.add_position(start_position);
  650.             eh.add_position(fgl.start_position);
  651.             fatal_error(fz_bnga);
  652.          end;
  653.       end;
  654.  
  655. feature {TYPE_GENERIC}
  656.  
  657.    set_run_type_memory(rt: like Current) is
  658.       require
  659.          rt /= Void
  660.       do
  661.          run_type_memory := rt;
  662.       ensure
  663.          run_type_memory = rt
  664.       end;
  665.  
  666. feature {NONE}
  667.  
  668.    tmp_mark: STRING is
  669.       once
  670.          !!Result.make(16);
  671.       end;
  672.  
  673. feature {TYPE}
  674.  
  675.    frozen short_hook is
  676.       local
  677.          i: INTEGER;
  678.       do
  679.          short_print.a_class_name(base_class_name);
  680.          short_print.hook_or("open_sb","[");
  681.          from
  682.             i := 1;
  683.          until
  684.             i > generic_list.count
  685.          loop
  686.             generic_list.item(i).short_hook;
  687.             if i < generic_list.count then
  688.                short_print.hook_or("tm_sep",",");
  689.             end;
  690.             i := i + 1;
  691.          end;
  692.          short_print.hook_or("close_sb","]");
  693.       end;
  694.  
  695. end -- TYPE_GENERIC
  696.  
  697.