--          This file is part of SmartEiffel The GNU Eiffel Compiler.
--       Copyright (C) 1994-2002 LORIA - INRIA - U.H.P. Nancy 1 - FRANCE
--          Dominique COLNET and Suzanne COLLIN - SmartEiffel@loria.fr
--                       http://SmartEiffel.loria.fr
-- SmartEiffel is  free  software;  you can  redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the Free
-- Software  Foundation;  either  version  2, or (at your option)  any  later
-- version. SmartEiffel is distributed in the hope that it will be useful,but
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
-- for  more  details.  You  should  have  received a copy of the GNU General
-- Public  License  along  with  SmartEiffel;  see the file COPYING.  If not,
-- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-- Boston, MA 02111-1307, USA.
--
class NATIVE_JAVA

-- defines mini language for external clause for interfacing to Java classes
-- examples:
--
-- object creation:                  JAVA class java.lang.String new (char[])
-- object cast:                      JAVA class java.lang.String checkcast
-- object instanceof:                JAVA class java.lang.String instanceof
--                                   JAVA class int[] instanceof
-- static method call:               JAVA class java.lang.String method static java.lang.String valueOf(char[])
-- method call:                      JAVA class java.lang.String method int length()
-- interface method call:            JAVA interface java.lang.Comparable method int compareTo(java.lang.Object)
-- static field read:                JAVA class MyClass get field static int theClassInteger
-- static field write:               JAVA class MyClass set field static int theClassInteger
-- instance field read:              JAVA class MyClass get field int aInstanceInteger
-- instance field write:             JAVA class MyClass set field int aInstanceInteger
-- array creation:                   JAVA array java.lang.Object new
--                                   JAVA array int new
-- array length:                     JAVA array java.lang.Object length
--                                   JAVA array int length
-- array read:                       JAVA array java.lang.Object get
--                                   JAVA array int get
-- array write:                      JAVA array java.lang.Object set
--                                   JAVA array int set
-- multidimensional array creation:  JAVA multiarray 2 java.lang.Object new
--                                   JAVA multiarray 2 int new
-- multidimensional array length:    JAVA multiarray 2 java.lang.Object length
--                                   JAVA multiarray 2 int length
-- multidimensional array read:      JAVA multiarray 2 java.lang.Object get
--                                   JAVA multiarray 2 int get
-- multidimensional array write:     JAVA multiarray 2 java.lang.Object set
--                                   JAVA multiarray 2 int set
-- throw exception:                  JAVA exception java.lang.Exception throw
-- get exception (in rescue clause): JAVA exception java.lang.Exception get
-- declare method synchronized:      JAVA synchronized
-- monitor enter:                    JAVA monitorenter
-- monitor exit:                     JAVA monitorexit
-- declare field transient:          JAVA transient
-- declare field volatile:           JAVA volatile

inherit 
   NATIVE
   FROZEN_STRING_LIST

creation make

feature

   class_keyword_index: INTEGER is 2
   class_name_index: INTEGER is 3
   member_index: INTEGER is 4
   min_method_token_count: INTEGER is 6
   min_field_token_count: INTEGER is 7
   new_class_count: INTEGER is 5
   new_descriptor_index: INTEGER is 5
   simple_token_count: INTEGER is 2
   simple_index: INTEGER is 2
   simple_class_token_count: INTEGER is 4
   array_count: INTEGER is 4
   exception_count: INTEGER is 4
   multiarray_count: INTEGER is 5
   multiarray_dimensions_index: INTEGER is 3
   multiarray_class_name_index: INTEGER is 4
   multiaray_member_index: INTEGER is 5

feature

   parse_external_tag is
      local
         s: STRING
         i: INTEGER
         next_index: INTEGER
      do
         s := external_tag.to_string
         tokens.clear
         s.split_in( tokens )
         
         if tokens.valid_index(class_keyword_index) 
            and tokens.valid_index(class_name_index) 
            and then tokens.item(class_keyword_index).is_equal( once "class" ) 
            then
            is_class := True
            jvm_class_name := tokens.item(class_name_index)
            jvm_class_descriptor := java_to_jvm_class_descriptor(jvm_class_name)
         end
         
         if tokens.valid_index(class_keyword_index) 
            and tokens.valid_index(class_name_index) 
            and then tokens.item(class_keyword_index).is_equal( once "interface" ) 
            then
            is_interface := True
            jvm_class_name := tokens.item(class_name_index)
            jvm_class_descriptor := java_to_jvm_class_descriptor(jvm_class_name)
         end
         
         if tokens.count = new_class_count and then tokens.item(member_index).is_equal( once "new" ) then
            is_class_new := True
            tmp_name.clear
            from
               i := new_descriptor_index
            until
               i > tokens.count
            loop
               tmp_name.append( tokens.item(i) )
               i := i + 1
            end
            tmp_name.remove_all_occurrences( ' ' )
            tmp_name.remove_all_occurrences( '%T' )
            tmp_name.remove_all_occurrences( '%N' )

            i := tmp_name.index_of( '(', 1 )
            jvm_method_descriptor := get_method_descriptor( once "void", tmp_name.substring( i+1, tmp_name.count ) )

         end
               
         if tokens.count >= min_method_token_count and then tokens.item(member_index).is_equal( once "method" ) then
            if tokens.count >= (min_method_token_count+1) and then tokens.item(member_index+1).is_equal( once "static" ) then
               is_static_method := True
               next_index := member_index + 2
            else
               if is_class then
                  is_method := True
               elseif is_interface then
                  is_interface_method := True
               end
               next_index := member_index + 1
            end

            jvm_field_or_return_type := tokens.item(next_index) 
            
            tmp_name.clear
            from
               i := next_index + 1
            until
               i > tokens.count
            loop
               tmp_name.append( tokens.item(i) )
               i := i + 1
            end
            tmp_name.remove_all_occurrences( ' ' )
            tmp_name.remove_all_occurrences( '%T' )
            tmp_name.remove_all_occurrences( '%N' )
             
            i := tmp_name.index_of( '(', 1 )
            jvm_method_name := tmp_name.substring( 1, i-1 )
            jvm_method_descriptor := get_method_descriptor( jvm_field_or_return_type, tmp_name.substring( i+1, tmp_name.count ) )
            
         end

         if tokens.count >= min_field_token_count and then 
            (  tokens.item(member_index+1).is_equal( once "field" ) 
               and tokens.item(member_index).is_equal( once "get" ) )
            then
            if tokens.count >= (min_field_token_count+1) and then tokens.item(member_index+2).is_equal( once "static" ) then
               is_static_field_get := True
               next_index := member_index + 3
            else
               is_field_get := True
               next_index := member_index + 2
            end
            jvm_field_or_return_type := tokens.item(next_index) 
            jvm_field_descriptor := java_to_jvm_descriptor( tokens.item(next_index) )
            jvm_field_name := tokens.item(next_index+1)            
         end

         if tokens.count >= min_field_token_count and then 
            (  tokens.item(member_index+1).is_equal( once "field" ) 
               and tokens.item(member_index).is_equal( once "set" ) )
            then
            if tokens.count >= (min_field_token_count+1) and then tokens.item(member_index+2).is_equal( once "static" ) then
               is_static_field_set := True
               next_index := member_index + 3
            else
               is_field_set := True
               next_index := member_index + 2
            end
            jvm_field_or_return_type := tokens.item(next_index) 
            jvm_field_descriptor := java_to_jvm_descriptor( tokens.item(next_index) )
            jvm_field_name := tokens.item(next_index+1)            
         end
         
         if tokens.count = simple_class_token_count and then tokens.item(member_index).is_equal( once "checkcast" ) then
            is_checkcast := True
         end
         
         if tokens.count = simple_class_token_count and then tokens.item(member_index).is_equal( once "instanceof" ) then
            is_instanceof := True
         end
         
         if tokens.count = simple_token_count and then tokens.item(simple_index).is_equal( once "synchronized" ) then
            is_synchronized := True
         end
         
         if tokens.count = simple_token_count and then tokens.item(simple_index).is_equal( once "monitorenter" ) then
            is_monitorenter := True
         end
         
         if tokens.count = simple_token_count and then tokens.item(simple_index).is_equal( once "monitorexit" ) then
            is_monitorexit := True
         end
         
         if tokens.count = simple_token_count and then tokens.item(simple_index).is_equal( once "transient" ) then
            is_transient := True
         end
         
         if tokens.count = simple_token_count and then tokens.item(simple_index).is_equal( once "volatile" ) then
            is_volatile := True
         end
         
         if tokens.count = array_count and then tokens.item(class_keyword_index).is_equal( once "array" ) then
            is_array := True
            jvm_array_type := tokens.item(class_name_index)
            jvm_array_descriptor := java_to_jvm_descriptor( jvm_array_type )
            if tokens.item(member_index).is_equal( once "length" ) then
               is_array_length := True
            elseif tokens.item(member_index).is_equal( once "get" ) then
               is_array_get := True
            elseif tokens.item(member_index).is_equal( once "set" ) then
               is_array_set := True
            elseif tokens.item(member_index).is_equal( once "new" ) then
               is_array_new := True
            end
         end
         
         if tokens.count = multiarray_count and then 
            (  tokens.item(class_keyword_index).is_equal( once "multiarray" ) 
               and tokens.item(multiarray_dimensions_index).is_integer )
            then
            is_multiarray := True
            jvm_multiarray_dimensions_count := tokens.item(multiarray_dimensions_index).to_integer
            jvm_array_type := tokens.item(multiarray_class_name_index)
            jvm_array_descriptor := java_to_jvm_descriptor( jvm_array_type )
            jvm_multiarray_descriptor := java_to_jvm_descriptor_multiarray( jvm_array_type, jvm_multiarray_dimensions_count )
            if tokens.item(multiaray_member_index).is_equal( once "length" ) then
               is_array_length := True
            elseif tokens.item(multiaray_member_index).is_equal( once "get" ) then
               is_array_get := True
            elseif tokens.item(multiaray_member_index).is_equal( once "set" ) then
               is_array_set := True
            elseif tokens.item(multiaray_member_index).is_equal( once "new" ) then
               is_array_new := True
            end
         end
         
         if tokens.count = exception_count and then tokens.item(class_keyword_index).is_equal( once "exception" ) then
            is_exception := True
            jvm_exception_type := tokens.item(class_name_index)
            jvm_exception_descriptor := java_to_jvm_descriptor( jvm_exception_type )
            if tokens.item(member_index).is_equal( once "throw" ) then
               is_exception_throw := True
            elseif tokens.item(member_index).is_equal( once "get" ) then
               is_exception_get := True
            end
         end
         
      end


   check_external_tag( rf: RUN_FEATURE ) is
      local
         b: BOOLEAN
      do
         
-- class 
        
         if is_class and then ( jvm_class_name /= Void and is_class_new and jvm_method_descriptor /= Void ) then
            b := True
         end
         
         if is_class and then ( jvm_class_name /= Void and is_static_method and jvm_method_descriptor /= Void ) then
            b := True
         end
         
         if is_class and then ( jvm_class_name /= Void and is_method and jvm_method_descriptor /= Void ) then
            b := True
         end
         
         if is_class and then ( jvm_class_name /= Void and is_static_field_get and jvm_field_descriptor /= Void ) then
            b := True
         end
         
         if is_class and then ( jvm_class_name /= Void and is_static_field_set and jvm_field_descriptor /= Void ) then
            b := True
         end
         
         if is_class and then ( jvm_class_name /= Void and is_field_get and jvm_field_descriptor /= Void ) then
            b := True
         end
         
         if is_class and then ( jvm_class_name /= Void and is_field_set and jvm_field_descriptor /= Void ) then
            b := True
         end

-- interface 
         
         if is_interface and then ( jvm_class_name /= Void and is_interface_method and jvm_method_descriptor /= Void ) then
            b := True
         end
         
         if is_interface and then ( jvm_class_name /= Void and is_static_field_get and jvm_method_descriptor /= Void ) then
            b := True
         end

-- array
         
         if is_array and then ( is_array_new and jvm_array_descriptor /= Void ) then
            b := True
         end
         
         if is_array and then ( is_array_get and jvm_array_descriptor /= Void ) then
            b := True
         end
         
         if is_array and then ( is_array_set and jvm_array_descriptor /= Void ) then
            b := True
         end
         
         if is_array and then ( is_array_length ) then
            b := True
         end
         
-- multiarray
         
         if is_multiarray and then ( is_array_new and jvm_array_descriptor /= Void and jvm_multiarray_dimensions_count > 0 ) then
            b := True
         end
         
         if is_multiarray and then ( is_array_get and jvm_array_descriptor /= Void and jvm_multiarray_dimensions_count > 0 ) then
            b := True
         end
         
         if is_multiarray and then ( is_array_set and jvm_array_descriptor /= Void and jvm_multiarray_dimensions_count > 0 ) then
            b := True
         end
         
         if is_multiarray and then ( is_array_length and jvm_multiarray_dimensions_count > 0 ) then
            b := True
         end
         
-- exception
         
         if is_exception and then ( is_exception_get ) then
            b := True
         end
         
         if is_exception and then ( is_exception_throw ) then
            b := True
         end
         
-- checkcast
         
         if is_class and then ( is_checkcast and jvm_class_name /= Void ) then
            b := True
         end
         
-- instanceof
         
         if is_class and then ( is_instanceof and jvm_class_name /= Void ) then
            b := True
         end
         
-- singles
         
         if is_synchronized or is_monitorenter or is_monitorexit or is_transient or is_volatile then
            b := True
         end
         
         if b = False then
            fe_c2jvm( rf )
         end
         
      end
      
      notify_external_assignments(args: FORMAL_ARG_LIST; rt: E_TYPE) is
         do
            assignment_handler.from_external(start_position, args, rt)
         end
   
feature

   tokens: ARRAY[STRING] is
      once
         create Result.with_capacity( 20, 1 )
      end
   
   method_parameters: ARRAY[STRING] is
      once
         create Result.with_capacity( 20, 1 )
      end
   
   is_class: BOOLEAN
   is_interface: BOOLEAN
   
   is_class_new: BOOLEAN
   
   is_static_method: BOOLEAN
   is_method: BOOLEAN
   is_interface_method: BOOLEAN
   is_static_field_get: BOOLEAN
   is_static_field_set: BOOLEAN
   is_field_get: BOOLEAN
   is_field_set: BOOLEAN
        
   is_array: BOOLEAN 
   is_array_get: BOOLEAN
   is_array_set: BOOLEAN
   is_array_new: BOOLEAN
   is_array_length: BOOLEAN
   jvm_array_type: STRING
   jvm_array_descriptor: STRING
   
   is_multiarray: BOOLEAN 
   jvm_multiarray_dimensions_count: INTEGER
   jvm_multiarray_descriptor: STRING
         
   is_exception: BOOLEAN
   is_exception_get: BOOLEAN
   is_exception_throw: BOOLEAN

   is_checkcast: BOOLEAN
   is_instanceof: BOOLEAN
   is_synchronized: BOOLEAN
   is_monitorenter: BOOLEAN
   is_monitorexit: BOOLEAN
   is_transient: BOOLEAN
   is_volatile: BOOLEAN
         
   jvm_class_name: STRING
   jvm_class_descriptor: STRING
   jvm_method_name: STRING
   jvm_field_name: STRING
   jvm_method_descriptor: STRING
   jvm_field_or_return_type: STRING
   jvm_field_descriptor: STRING

   jvm_exception_type: STRING
   jvm_exception_descriptor: STRING
            
feature

   use_current(er: EXTERNAL_ROUTINE): BOOLEAN is
      do
      end;

   jvm_mapping_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
      local
         space, stack_space, i, j, idx, idx_class: INTEGER;
         ca: like code_attribute;
         s: STRING
      do
         parse_external_tag
         check_external_tag( rf8 )
         
         s := external_tag.to_string
      	if s.has_substring(once "class") then
      	   space := 2
         end
         
         ca := code_attribute;
  
         if is_static_method then      
            space := jvm.push_arguments;
            idx := constant_pool.idx_methodref3(jvm_class_descriptor, jvm_method_name, jvm_method_descriptor);
            space := rf8.result_type.jvm_stack_space - space;
            ca.opcode_invokestatic(idx,space);
         end
         
         if is_class_new then      
            idx_class := constant_pool.idx_class2(jvm_class_descriptor);
            idx := constant_pool.idx_methodref3(jvm_class_descriptor, fz_35, jvm_method_descriptor);
            ca.opcode_new(idx_class);
            ca.opcode_dup
            space := -jvm.push_arguments;
            ca.opcode_invokespecial(idx,space);
         end

         if is_method then      
            space := jvm.push_arguments;
            idx := constant_pool.idx_methodref3(jvm_class_descriptor, jvm_method_name, jvm_method_descriptor);
            space := rf8.result_type.jvm_stack_space - space;
            ca.opcode_invokevirtual(idx,space);
         end

         if is_interface_method then      
            stack_space := jvm.push_arguments;
            idx := constant_pool.idx_interface_methodref3(jvm_class_descriptor, jvm_method_name, jvm_method_descriptor);
            space := rf8.result_type.jvm_stack_space - stack_space;
            ca.opcode_invokeinterface(idx,space,stack_space);
         end

         if is_static_field_get then      
            space := jvm.push_arguments;
            idx := constant_pool.idx_fieldref3(jvm_class_descriptor, jvm_field_name, jvm_field_descriptor);
            space := rf8.result_type.jvm_stack_space - space;
            ca.opcode_getstatic(idx,space);
         end

         if is_field_get then      
            space := jvm.push_arguments;
            idx := constant_pool.idx_fieldref3(jvm_class_descriptor, jvm_field_name, jvm_field_descriptor);
            space := rf8.result_type.jvm_stack_space - space;
            ca.opcode_getfield(idx,space);
         end

         if is_checkcast then      
            space := jvm.push_arguments;
            idx_class := constant_pool.idx_class2(jvm_class_descriptor);
            space := rf8.result_type.jvm_stack_space - space;
            ca.opcode_checkcast(idx_class);
         end

         if is_instanceof then      
            space := jvm.push_arguments;
            idx_class := constant_pool.idx_class2(jvm_class_descriptor);
            space := rf8.result_type.jvm_stack_space - space;
            ca.opcode_instanceof(idx_class);
         end

         if is_array_new and is_array then      
            space := jvm.push_arguments;
            if jvm_array_descriptor.is_equal( once "Z" ) then
               ca.opcode_newarray(4);
            elseif jvm_array_descriptor.is_equal( once "C" ) then
               ca.opcode_newarray(5);
            elseif jvm_array_descriptor.is_equal( once "F" ) then
               ca.opcode_newarray(6);
            elseif jvm_array_descriptor.is_equal( once "D" ) then
               ca.opcode_newarray(7);
            elseif jvm_array_descriptor.is_equal( once "B" ) then
               ca.opcode_newarray(8);
            elseif jvm_array_descriptor.is_equal( once "S" ) then
               ca.opcode_newarray(9);
            elseif jvm_array_descriptor.is_equal( once "I" ) then
               ca.opcode_newarray(10);
            elseif jvm_array_descriptor.is_equal( once "J" ) then
               ca.opcode_newarray(11);
            else
               idx_class := constant_pool.idx_class2(jvm_array_descriptor);
               space := rf8.result_type.jvm_stack_space - space;
               ca.opcode_anewarray(idx_class);
            end
         end

         if is_array_get and is_array then      
            space := jvm.push_arguments;
            if jvm_array_descriptor.is_equal( "Z" ) then
               ca.opcode_baload
            elseif jvm_array_descriptor.is_equal( "C" ) then
               ca.opcode_caload
            elseif jvm_array_descriptor.is_equal( "F" ) then
               ca.opcode_faload
            elseif jvm_array_descriptor.is_equal( "D" ) then
               ca.opcode_daload
            elseif jvm_array_descriptor.is_equal( "B" ) then
               ca.opcode_baload
            elseif jvm_array_descriptor.is_equal( "S" ) then
               ca.opcode_saload
            elseif jvm_array_descriptor.is_equal( "I" ) then
               ca.opcode_iaload
            elseif jvm_array_descriptor.is_equal( "J" ) then
               ca.opcode_laload
            else
               ca.opcode_aaload
            end
         end

         if is_array_length and is_array then
            space := jvm.push_arguments;
            ca.opcode_arraylength
         end

         if is_array_new and is_multiarray then      
            space := jvm.push_arguments;
            idx_class := constant_pool.idx_class2(jvm_multiarray_descriptor);
            space := rf8.result_type.jvm_stack_space - space;
            ca.opcode_multianewarray(idx_class, jvm_multiarray_dimensions_count);
         end

         if is_array_get and is_multiarray then      
            space := jvm.push_ith_argument(1);
            from 
               i := jvm.arg_count
               j := 1
            until
               i < 2
            loop
               if j /= jvm_multiarray_dimensions_count then
                  space := jvm.push_ith_argument(i);
                  ca.opcode_aaload
               else
                  space := jvm.push_ith_argument(i);
                  if jvm_array_descriptor.is_equal( "Z" ) then
                     ca.opcode_baload
                  elseif jvm_array_descriptor.is_equal( "C" ) then
                     ca.opcode_caload
                  elseif jvm_array_descriptor.is_equal( "F" ) then
                     ca.opcode_faload
                  elseif jvm_array_descriptor.is_equal( "D" ) then
                     ca.opcode_daload
                  elseif jvm_array_descriptor.is_equal( "B" ) then
                     ca.opcode_baload
                  elseif jvm_array_descriptor.is_equal( "S" ) then
                     ca.opcode_saload
                  elseif jvm_array_descriptor.is_equal( "I" ) then
                     ca.opcode_iaload
                  elseif jvm_array_descriptor.is_equal( "J" ) then
                     ca.opcode_laload
                  else
                     ca.opcode_aaload
                  end
               end
               i := i - 1
               j := j + 1
            end
         end

         if is_array_length and is_multiarray then      
            space := jvm.push_ith_argument(1);
            from 
               i := jvm.arg_count
            until
               i < 2
            loop
               space := jvm.push_ith_argument(i);
               ca.opcode_aaload
               i := i - 1
            end
            
            ca.opcode_arraylength
            
         end

         if is_exception_get then      
            idx := constant_pool.idx_string( "Exceptions" )
            ca.opcode_aload( jvm.current_frame.jvm_max_locals - 1 )
         end

      end;

   jvm_define_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
      do
      end;

   jvm_mapping_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
      local
         space, stack_space, i, j, idx, idx_name: INTEGER;
         ca: like code_attribute;
         s: STRING
      do
         parse_external_tag
         check_external_tag( rf7 )
         
         s := external_tag.to_string
      	if s.has_substring(once "class") then
      	   space := 2
         end
  
         ca := code_attribute;

         if is_static_method then      
            space := jvm.push_arguments;
            idx := constant_pool.idx_methodref3(jvm_class_descriptor, jvm_method_name, jvm_method_descriptor);
            ca.opcode_invokestatic(idx,space);
         end
         
         if is_method then      
            space := -jvm.push_arguments;
            idx := constant_pool.idx_methodref3(jvm_class_descriptor, jvm_method_name, jvm_method_descriptor);
            ca.opcode_invokevirtual(idx,space);
         end

         if is_interface_method then      
            space := -jvm.push_arguments;
            stack_space := -space
            idx := constant_pool.idx_interface_methodref3(jvm_class_descriptor, jvm_method_name, jvm_method_descriptor);
            ca.opcode_invokeinterface(idx,space,stack_space);
         end

         if is_static_field_set then      
            idx := constant_pool.idx_fieldref3(jvm_class_descriptor, jvm_field_name, jvm_field_descriptor);
            space := -jvm.push_arguments;
            ca.opcode_putstatic(idx,space);
         end

         if is_field_set then      
            idx := constant_pool.idx_fieldref3(jvm_class_descriptor, jvm_field_name, jvm_field_descriptor);
            space := -jvm.push_arguments;
            ca.opcode_putfield(idx,space);
         end

         if is_array_set and is_array then
            space := jvm.push_arguments;
            if jvm_array_descriptor.is_equal( "Z" ) then
               ca.opcode_bastore
            elseif jvm_array_descriptor.is_equal( "C" ) then
               ca.opcode_castore
            elseif jvm_array_descriptor.is_equal( "F" ) then
               ca.opcode_fastore
            elseif jvm_array_descriptor.is_equal( "D" ) then
               ca.opcode_dastore
            elseif jvm_array_descriptor.is_equal( "B" ) then
               ca.opcode_bastore
            elseif jvm_array_descriptor.is_equal( "S" ) then
               ca.opcode_sastore
            elseif jvm_array_descriptor.is_equal( "I" ) then
               ca.opcode_iastore
            elseif jvm_array_descriptor.is_equal( "J" ) then
               ca.opcode_lastore
            else
               ca.opcode_aastore
            end
         end

         if is_array_set and is_multiarray then      
            space := jvm.push_ith_argument(1);
            from 
               i := jvm.arg_count
               j := 1
            until
               i < 3
            loop
               if i /= 3 then
                  space := jvm.push_ith_argument(i);
                  ca.opcode_aaload
               elseif j = jvm_multiarray_dimensions_count then
                  space := jvm.push_ith_argument(i);
                  space := jvm.push_ith_argument(2);
                  if jvm_array_descriptor.is_equal( "Z" ) then
                     ca.opcode_bastore
                  elseif jvm_array_descriptor.is_equal( "C" ) then
                     ca.opcode_castore
                  elseif jvm_array_descriptor.is_equal( "F" ) then
                     ca.opcode_fastore
                  elseif jvm_array_descriptor.is_equal( "D" ) then
                     ca.opcode_dastore
                  elseif jvm_array_descriptor.is_equal( "B" ) then
                     ca.opcode_bastore
                  elseif jvm_array_descriptor.is_equal( "S" ) then
                     ca.opcode_sastore
                  elseif jvm_array_descriptor.is_equal( "I" ) then
                     ca.opcode_iastore
                  elseif jvm_array_descriptor.is_equal( "J" ) then
                     ca.opcode_lastore
                  else
                     ca.opcode_aastore
                  end
               else
                  space := jvm.push_ith_argument(i);
                  space := jvm.push_ith_argument(2);
                  ca.opcode_aastore
               end
               i := i - 1
               j := j + 1
            end
         end

         if is_synchronized then      
      	   method_info.set_synchronized
         end

         if is_monitorenter then      
            space := -jvm.push_arguments;
            ca.opcode_monitorenter
         end

         if is_monitorexit then      
            space := -jvm.push_arguments;
            ca.opcode_monitorexit
         end

         if is_exception_throw then      
            space := jvm.push_arguments;
            ca.opcode_athrow;
         end

         if is_transient then      
            s := jvm.ith_argument_as_manifest_string(1)
            if s /= Void then
               idx_name := constant_pool.idx_utf8(s);
               field_info.field_set_transient( idx_name )
            end
         end

         if is_volatile then      
            s := jvm.ith_argument_as_manifest_string(1)
            if s /= Void then
               idx_name := constant_pool.idx_utf8(s);
               field_info.field_set_volatile( idx_name )
            end
         end

      end;

   jvm_define_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
      do
      end;

   jvm_add_method_for_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
      do
      end;

   jvm_add_method_for_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
      do
      end;


feature

   frozen stupid_switch_function(run_time_set: RUN_TIME_SET; name: STRING): BOOLEAN is
      do
         check false end;
      end;

   frozen stupid_switch_procedure(run_time_set: RUN_TIME_SET; name: STRING): BOOLEAN is
      do
         check false end;
      end;

   frozen c_define_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
      do
         fe_c2c(rf7)
      end;

   frozen c_mapping_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
      do
         fe_c2c(rf7)
      end;

   frozen c_define_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
      do
         fe_c2c(rf8)
      end;

   frozen c_mapping_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
      do
         fe_c2c(rf8)
      end;

feature {NONE}

   idx_fieldref(er: EXTERNAL_ROUTINE): INTEGER is
      local
         i: integer;
         alias_string: STRING;
         cp: like constant_pool;
      do
         cp := constant_pool;
         alias_string := er.alias_string;
         if alias_string = Void then
            error_handler.add_position(er.start_position);
            fatal_error(
             "Missing %"alias%" field description (see %
             %external.html documentation).");
         end;
         from
            i := 1;
            tmp_class.clear;
         until
            alias_string.item(i) = '.'
         loop
            tmp_class.extend(alias_string.item(i));
            i := i + 1;
         end;
         from
            i := i + 1;
            tmp_name.clear;
         until
            alias_string.item(i) = ' '
         loop
            tmp_name.extend(alias_string.item(i));
            i := i + 1;
         end;
         from
            i := i + 1;
            tmp_descriptor.clear;
         until
            i > alias_string.count
         loop
            tmp_descriptor.extend(alias_string.item(i));
            i := i + 1;
         end;
         Result := cp.idx_fieldref3(tmp_class,tmp_name,tmp_descriptor);
      end;

   idx_utf8ref(er: EXTERNAL_ROUTINE): INTEGER is
      local
         alias_string: STRING;
         cp: like constant_pool;
      do
         cp := constant_pool;
         alias_string := er.alias_string;
         if alias_string = Void then
            error_handler.add_position(er.start_position);
            fatal_error(
             "Missing %"alias%" field description (see %
             %external.html documentation).");
         end;
         Result := cp.idx_utf8(alias_string);
      end;

   idx_interface_methodref(er: EXTERNAL_ROUTINE): INTEGER is
      local
         i: integer;
         alias_string: STRING;
         cp: like constant_pool;
      do
         cp := constant_pool;
         alias_string := er.alias_string;
         if alias_string = Void then
            error_handler.add_position(er.start_position);
            fatal_error(
             "Missing %"alias%" field description (see %
             %external.html documentation).");
         end;
         from
            i := 1;
            tmp_class.clear;
         until
            alias_string.item(i) = '.'
         loop
            tmp_class.extend(alias_string.item(i));
            i := i + 1;
         end;
         from
            i := i + 1;
            tmp_name.clear;
         until
            alias_string.item(i) = ' '
         loop
            tmp_name.extend(alias_string.item(i));
            i := i + 1;
         end;
         from
            i := i + 1;
            tmp_descriptor.clear;
         until
            i > alias_string.count
         loop
            tmp_descriptor.extend(alias_string.item(i));
            i := i + 1;
         end;
         Result := cp.idx_interface_methodref3(tmp_class,tmp_name,tmp_descriptor);
      end;

   tmp_class: STRING is
      once
         !!Result.make(32);
      end;

   tmp_name: STRING is
      once
         !!Result.make(32);
      end;

   tmp_descriptor: STRING is
      once
         !!Result.make(32);
      end;

   spec_string: STRING is
      once
         create Result.make( 64 )
      end
   
   string_buffer: STRING is
      once
         create Result.make(256);
      end;

   get_method_descriptor( return_type: STRING; parameter_string: STRING ): STRING is
      local
         i: INTEGER
         amp: ARRAY[STRING]
      do
         amp := get_method_parameters( parameter_string )
         create Result.make( 256 )
         
         Result.extend( '(' )
         
         from
            i := 1
         until
            i > amp.count
         loop
            Result.append( java_to_jvm_descriptor( amp.item(i) ) )
            i := i + 1
         end
         
         Result.extend( ')' )

         Result.append( java_to_jvm_descriptor( return_type ) )
         
      end
         
   get_method_parameters( s: STRING ): ARRAY[STRING] is
      local
         state, i: INTEGER;
         -- state = 0: waiting next word.
         -- state = 1: inside a new word.
         c: CHARACTER;
      do
         Result := method_parameters
         Result.clear
         if s.count > 0 then
            from
               i := 1;
            until
               i > s.count
            loop
               c := s.item(i);
               if state = 0 then
                  if c /= ',' and c /= ')' then
                     string_buffer.clear;
                     string_buffer.append_character(c);
                     state := 1;
                  end;
               else
                  if c /= ',' and c /= ')' then
                     string_buffer.append_character(c);
                  else
                     Result.add_last(string_buffer.twin);
                     state := 0;
                  end;
               end;
               i := i + 1;
            end;
            if state = 1 then
               Result.add_last(string_buffer.twin);
            end;
         end;
      end;
      
   
--   Xjava_to_jvm_class_descriptor( s: STRING ): STRING is
--      local
--         i: INTEGER
--         ac: INTEGER
--      do
--         create Result.make_from_string( s )
--         
---- check for array         
--
--         i := Result.index_of( '[', 1 )
--         if i /= 0 then
--            ac := Result.occurrences( '[' )
--            Result.remove_all_occurrences( '[' )
--            Result.remove_all_occurrences( ']' )
--         end
--         
---- change dots to slashes         
--
--         from
--            i := 1
--         until
--            i > Result.count
--         loop
--            if Result.item(i) = '.' then
--               Result.put( '/', i )
--            end
--            i := i + 1
--         end
--
---- if was array, add preceeding [s
--
--         if ac /= 0 then
--            Result.precede( 'L' )
--            Result.extend( ';' )
--            from
--               i := 1
--            until
--               i > ac
--            loop
--               Result.precede( '[' )
--               i := i + 1
--            end
--            
--         end
--         
--      end
   
   java_to_jvm_class_descriptor( s: STRING ): STRING is
      local
         i: INTEGER
         ac: INTEGER
         is_primitive: BOOLEAN
      do
         create Result.make_from_string( s )
         
-- check for array         

         i := Result.index_of( '[', 1 )
         if i /= 0 then
            ac := Result.occurrences( '[' )
            Result.remove_all_occurrences( '[' )
            Result.remove_all_occurrences( ']' )
         end
         
-- check for primitive type and convert

			if Result.is_equal( once "boolean" ) then
				Result.make_from_string( once "Z" )
				is_primitive := True
			elseif Result.is_equal( once "char" ) then
				Result.make_from_string( once "C" )
				is_primitive := True
			elseif Result.is_equal( once "byte" ) then
				Result.make_from_string( once "B" )
				is_primitive := True
			elseif Result.is_equal( once "short" ) then
				Result.make_from_string( once "S" )
				is_primitive := True
			elseif Result.is_equal( once "int" ) then
				Result.make_from_string( once "I" )
				is_primitive := True
			elseif Result.is_equal( once "long" ) then
				Result.make_from_string( once "J" )
				is_primitive := True
			elseif Result.is_equal( once "float" ) then
				Result.make_from_string( once "F" )
				is_primitive := True
			elseif Result.is_equal( once "double" ) then
				Result.make_from_string( once "D" )
				is_primitive := True
			elseif Result.is_equal( once "void" ) then
				Result.make_from_string( once "V" )
         else -- is class
         
-- change dots to slashes         

            from
               i := 1
            until
               i > Result.count
            loop
               if Result.item(i) = '.' then
                  Result.put( '/', i )
               end
               i := i + 1
            end

         end
      
-- if was array, add preceeding L, post ;, and preceeding [s

         if ac /= 0 then
            if not is_primitive then
               Result.extend( ';' )
               Result.precede( 'L' )
            end
            from
               i := 1
            until
               i > ac
            loop
               Result.precede( '[' )
               i := i + 1
            end
            
         end
         
      end
      
   java_to_jvm_descriptor( s: STRING ): STRING is
      local
         i: INTEGER
         ac: INTEGER
      do
         create Result.make_from_string( s )
         
-- check for array         

         i := Result.index_of( '[', 1 )
         if i /= 0 then
            ac := Result.occurrences( '[' )
            Result.remove_all_occurrences( '[' )
            Result.remove_all_occurrences( ']' )
         end
         
-- check for primitive type and convert

			if Result.is_equal( once "boolean" ) then
				Result.make_from_string( once "Z" )
			elseif Result.is_equal( once "char" ) then
				Result.make_from_string( once "C" )
			elseif Result.is_equal( once "byte" ) then
				Result.make_from_string( once "B" )
			elseif Result.is_equal( once "short" ) then
				Result.make_from_string( once "S" )
			elseif Result.is_equal( once "int" ) then
				Result.make_from_string( once "I" )
			elseif Result.is_equal( once "long" ) then
				Result.make_from_string( once "J" )
			elseif Result.is_equal( once "float" ) then
				Result.make_from_string( once "F" )
			elseif Result.is_equal( once "double" ) then
				Result.make_from_string( once "D" )
			elseif Result.is_equal( once "void" ) then
				Result.make_from_string( once "V" )
         else -- is class
         
-- change dots to slashes         

            from
               i := 1
            until
               i > Result.count
            loop
               if Result.item(i) = '.' then
                  Result.put( '/', i )
               end
               i := i + 1
            end

-- add leading L and trailing ;

            Result.precede( 'L' )
            Result.extend( ';' )

         end
      
-- if was array, add preceeding [s

         if ac /= 0 then
            from
               i := 1
            until
               i > ac
            loop
               Result.precede( '[' )
               i := i + 1
            end
            
         end
         
      end
      
   java_to_jvm_descriptor_multiarray(s: STRING; dims: INTEGER): STRING is
      local
         i: INTEGER
      do
         Result := java_to_jvm_descriptor( s )
         from
            i := 1
         until
            i > dims
         loop
            Result.precede('[')
            i := i + 1
         end
         
      end
         
end -- NATIVE_JAVA

