Browse Source

+ Java interface support, mostly the same as Objective-C protocols
(generalised some error messages that were specific to protocols
so they can also be used for Java interfaces)
o note, Java interface support requires a fix to Jasmin 2.4:
http://sourceforge.net/tracker/?func=detail&aid=2897170&group_id=100746&atid=628212

git-svn-id: branches/jvmbackend@18344 -

Jonas Maebe 14 years ago
parent
commit
83dc297346
7 changed files with 325 additions and 249 deletions
  1. 49 5
      compiler/agjasmin.pas
  2. 9 9
      compiler/msg/errore.msg
  3. 4 4
      compiler/msgidx.inc
  4. 201 200
      compiler/msgtxt.inc
  5. 27 16
      compiler/nobj.pas
  6. 25 10
      compiler/pdecobj.pas
  7. 10 5
      compiler/symdef.pas

+ 49 - 5
compiler/agjasmin.pas

@@ -388,7 +388,10 @@ implementation
 
 
     procedure TJasminAssembler.WriteExtraHeader(obj: tobjectdef);
     procedure TJasminAssembler.WriteExtraHeader(obj: tobjectdef);
       var
       var
+        superclass,
+        intf: tobjectdef;
         n: string;
         n: string;
+        i: longint;
       begin
       begin
         { JVM 1.5+ }
         { JVM 1.5+ }
         AsmWriteLn('.bytecode 49.0');
         AsmWriteLn('.bytecode 49.0');
@@ -399,6 +402,8 @@ implementation
         else
         else
           n:=InputFileName;
           n:=InputFileName;
         AsmWriteLn('.source '+ExtractFileName(n));
         AsmWriteLn('.source '+ExtractFileName(n));
+
+        { class/interface name }
         if not assigned(obj) then
         if not assigned(obj) then
           begin
           begin
             { fake class type for unit -> name=unitname and
             { fake class type for unit -> name=unitname and
@@ -408,13 +413,41 @@ implementation
           end
           end
         else
         else
           begin
           begin
-            AsmWriteLn('.class '+obj.objextname^);
-            if assigned(obj.childof) then
+            case obj.objecttype of
+              odt_javaclass:
+                begin
+                  AsmWriteLn('.class '+obj.objextname^);
+                  superclass:=obj.childof;
+                end;
+              odt_interfacejava:
+                begin
+                  AsmWriteLn('.interface abstract '+obj.objextname^);
+                  { interfaces must always specify Java.lang.object as
+                    superclass }
+                  superclass:=java_jlobject;
+                end
+              else
+                internalerror(2011010906);
+            end;
+            { superclass }
+            if assigned(superclass) then
               begin
               begin
                 AsmWrite('.super ');
                 AsmWrite('.super ');
-                if assigned(obj.childof.import_lib) then
-                  AsmWrite(obj.childof.import_lib^+'/');
-                AsmWriteln(obj.childof.objextname^);
+                if assigned(superclass.import_lib) then
+                  AsmWrite(superclass.import_lib^+'/');
+                AsmWriteln(superclass.objextname^);
+              end;
+            { implemented interfaces }
+            if assigned(obj.ImplementedInterfaces) then
+              begin
+                for i:=0 to obj.ImplementedInterfaces.count-1 do
+                  begin
+                    intf:=TImplementedInterface(obj.ImplementedInterfaces[i]).IntfDef;
+                    AsmWrite('.implements ');
+                    if assigned(intf.import_lib) then
+                      AsmWrite(intf.import_lib^+'/');
+                    AsmWriteln(intf.objextname^);
+                  end;
               end;
               end;
           end;
           end;
         AsmLn;
         AsmLn;
@@ -492,6 +525,17 @@ implementation
 
 
     procedure TJasminAssembler.WriteProcDef(pd: tprocdef);
     procedure TJasminAssembler.WriteProcDef(pd: tprocdef);
       begin
       begin
+        { abstract method? }
+        if is_javainterface(tdef(pd.owner.defowner)) or
+           (po_abstractmethod in pd.procoptions) then
+          begin
+            AsmWrite('.method ');
+            AsmWriteln(pd.mangledname(true));
+            AsmWriteln('.end method');
+            AsmLn;
+            exit;
+          end;
+
         WriteTree(pd.exprasmlist);
         WriteTree(pd.exprasmlist);
       end;
       end;
 
 

+ 9 - 9
compiler/msg/errore.msg

@@ -1254,16 +1254,16 @@ parser_e_no_objc_published=03271_E_Objective-C classes cannot have published sec
 parser_f_need_objc=03272_F_This module requires an Objective-C mode switch to be compiled
 parser_f_need_objc=03272_F_This module requires an Objective-C mode switch to be compiled
 % This error indicates the use of Objective-C language features without an Objective-C mode switch
 % This error indicates the use of Objective-C language features without an Objective-C mode switch
 % active. Enable one via the -M command line switch, or the {\$modeswitch x} directive.
 % active. Enable one via the -M command line switch, or the {\$modeswitch x} directive.
-parser_e_must_use_override_objc=03273_E_Inherited methods can only be overridden in Objective-C, add "override" (inherited method defined in $1)
-parser_h_should_use_override_objc=03274_H_Inherited methods can only be overridden in Objective-C, add "override" (inherited method defined in $1).
-% It is not possible to \var{reintroduce} methods in Objective-C like in Object Pascal. Methods with the same
+parser_e_must_use_override=03273_E_Inherited methods can only be overridden in Objective-C and Java, add "override" (inherited method defined in $1)
+parser_h_should_use_override=03274_H_Inherited methods can only be overridden in Objective-C and Java, add "override" (inherited method defined in $1).
+% It is not possible to \var{reintroduce} methods in Objective-C or Java like in Object Pascal. Methods with the same
 % name always map to the same virtual method entry. In order to make this clear in the source code,
 % name always map to the same virtual method entry. In order to make this clear in the source code,
 % the compiler always requires the \var{override} directive to be specified when implementing overriding
 % the compiler always requires the \var{override} directive to be specified when implementing overriding
-% Objective-C methods in Pascal. If the implementation is external, this rule is relaxed because Objective-C
-% does not have any \var{override}-style keyword (since it's the default and only behaviour in that language),
+% Objective-C or Java methods in Pascal. If the implementation is external, this rule is relaxed because Objective-C and Java
+% do not have any \var{override}-style keyword (since it's the default and only behaviour in these languages),
 % which makes it hard for automated header conversion tools to include it everywhere.
 % which makes it hard for automated header conversion tools to include it everywhere.
 % The type in which the inherited method is defined is explicitly mentioned, because this may either
 % The type in which the inherited method is defined is explicitly mentioned, because this may either
-% be an objcclass or an objccategory.
+% be an objcclass or an objccategory in case of Objective-C.
 parser_e_objc_message_name_changed=03275_E_Message name "$1" in inherited class is different from message name "$2" in current class.
 parser_e_objc_message_name_changed=03275_E_Message name "$1" in inherited class is different from message name "$2" in current class.
 % An overriding Objective-C method cannot have a different message name than an inherited method. The reason
 % An overriding Objective-C method cannot have a different message name than an inherited method. The reason
 % is that these message names uniquely define the message to the Objective-C runtime, which means that
 % is that these message names uniquely define the message to the Objective-C runtime, which means that
@@ -1350,9 +1350,9 @@ parser_f_no_generic_inside_generic=03297_F_Declaration of generic class inside a
 % (guarded by internal error 200511173 in tscannerfile.startrecordtokens).
 % (guarded by internal error 200511173 in tscannerfile.startrecordtokens).
 % Since generics are implemented by recording tokens, it is not possible to
 % Since generics are implemented by recording tokens, it is not possible to
 % have declaration of generic class inside another generic class.
 % have declaration of generic class inside another generic class.
-parser_e_forward_protocol_declaration_must_be_resolved=03298_E_Forward declaration of objcprotocol "$1" must be resolved before an objcclass can conform to it
-% An objcprotocol must be fully defined before classes can conform to it.
-% This error occurs in the following situation:
+parser_e_forward_intf_declaration_must_be_resolved=03298_E_Forward declaration "$1" must be resolved before a class can conform to or implement it
+% An Objective-C protocol or Java Interface must be fully defined before classes can conform to it.
+% This error occurs in the following situation (example for Objective-C, but the same goes for Java interfaces):
 % \begin{verbatim}
 % \begin{verbatim}
 %  Type MyProtocol = objcprotoocl;
 %  Type MyProtocol = objcprotoocl;
 %       ChildClass = Class(NSObject,MyProtocol)
 %       ChildClass = Class(NSObject,MyProtocol)

+ 4 - 4
compiler/msgidx.inc

@@ -364,8 +364,8 @@ const
   parser_h_no_objc_parent=03270;
   parser_h_no_objc_parent=03270;
   parser_e_no_objc_published=03271;
   parser_e_no_objc_published=03271;
   parser_f_need_objc=03272;
   parser_f_need_objc=03272;
-  parser_e_must_use_override_objc=03273;
-  parser_h_should_use_override_objc=03274;
+  parser_e_must_use_override=03273;
+  parser_h_should_use_override=03274;
   parser_e_objc_message_name_changed=03275;
   parser_e_objc_message_name_changed=03275;
   parser_e_unique_unsupported=03276;
   parser_e_unique_unsupported=03276;
   parser_e_no_category_as_types=03277;
   parser_e_no_category_as_types=03277;
@@ -389,7 +389,7 @@ const
   parser_e_objc_missing_enumeration_defs=03295;
   parser_e_objc_missing_enumeration_defs=03295;
   parser_e_no_procvarnested_const=03296;
   parser_e_no_procvarnested_const=03296;
   parser_f_no_generic_inside_generic=03297;
   parser_f_no_generic_inside_generic=03297;
-  parser_e_forward_protocol_declaration_must_be_resolved=03298;
+  parser_e_forward_intf_declaration_must_be_resolved=03298;
   parser_e_no_record_published=03299;
   parser_e_no_record_published=03299;
   parser_e_no_destructor_in_records=03300;
   parser_e_no_destructor_in_records=03300;
   parser_e_class_methods_only_static_in_records=03301;
   parser_e_class_methods_only_static_in_records=03301;
@@ -900,7 +900,7 @@ const
   option_info=11024;
   option_info=11024;
   option_help_pages=11025;
   option_help_pages=11025;
 
 
-  MsgTxtSize = 60995;
+  MsgTxtSize = 61005;
 
 
   MsgIdxMax : array[1..20] of longint=(
   MsgIdxMax : array[1..20] of longint=(
     26,89,314,103,85,54,111,23,202,63,
     26,89,314,103,85,54,111,23,202,63,

File diff suppressed because it is too large
+ 201 - 200
compiler/msgtxt.inc


+ 27 - 16
compiler/nobj.pas

@@ -281,11 +281,13 @@ implementation
               not(po_virtualmethod in pd.procoptions) or
               not(po_virtualmethod in pd.procoptions) or
               (
               (
                { new one does not have reintroduce in case of an objccategory }
                { new one does not have reintroduce in case of an objccategory }
-               (is_objccategory(_class) and not(po_reintroduce in pd.procoptions)) or
-               { new one does not have override in case of objpas/objc class/helper/intf/proto }
-               (
-                (is_class_or_interface_or_objc(_class) or is_objectpascal_helper(_class)) and
-                not is_objccategory(_class) and not(po_overridingmethod in pd.procoptions)
+               (is_objccategory(_class) and
+                 not(po_reintroduce in pd.procoptions)) or
+               { new one does not have override in case of objpas/objc/java class/intf/proto }
+               ((is_class_or_interface_or_objc(_class) or is_objectpascal_helper(_class)) and
+                not is_objccategory(_class) and
+                not is_java_class_or_interface(_class) and
+                not(po_overridingmethod in pd.procoptions)
                )
                )
               )
               )
              ) then
              ) then
@@ -296,7 +298,8 @@ implementation
                  ) then
                  ) then
                 begin
                 begin
                   if not(po_reintroduce in pd.procoptions) then
                   if not(po_reintroduce in pd.procoptions) then
-                    if not(is_objc_class_or_protocol(_class)) then
+                    if not(is_objc_class_or_protocol(_class)) and
+                       not(is_java_class_or_interface(_class)) then
                       MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false))
                       MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false))
                     else
                     else
                       begin
                       begin
@@ -308,10 +311,12 @@ implementation
 
 
                           In case of external classes, we only give a hint,
                           In case of external classes, we only give a hint,
                           because requiring override everywhere may make
                           because requiring override everywhere may make
-                          automated header translation tools too complex.  }
+                          automated header translation tools too complex.
+
+                          The same goes for Java. }
                         if not(oo_is_external in _class.objectoptions) then
                         if not(oo_is_external in _class.objectoptions) then
                           if not is_objccategory(_class) then
                           if not is_objccategory(_class) then
-                            MessagePos1(pd.fileinfo,parser_e_must_use_override_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil))
+                            MessagePos1(pd.fileinfo,parser_e_must_use_override,FullTypeName(tdef(vmtpd.owner.defowner),nil))
                           else
                           else
                             MessagePos1(pd.fileinfo,parser_e_must_use_reintroduce_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil))
                             MessagePos1(pd.fileinfo,parser_e_must_use_reintroduce_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil))
                         { there may be a lot of these in auto-translated
                         { there may be a lot of these in auto-translated
@@ -319,7 +324,7 @@ implementation
                           the hint will be shown  }
                           the hint will be shown  }
                         else if CheckVerbosity(V_Hint) then
                         else if CheckVerbosity(V_Hint) then
                           if not is_objccategory(_class) then
                           if not is_objccategory(_class) then
-                            MessagePos1(pd.fileinfo,parser_h_should_use_override_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil))
+                            MessagePos1(pd.fileinfo,parser_h_should_use_override,FullTypeName(tdef(vmtpd.owner.defowner),nil))
                           else
                           else
                             MessagePos1(pd.fileinfo,parser_h_should_use_reintroduce_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil));
                             MessagePos1(pd.fileinfo,parser_h_should_use_reintroduce_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil));
                         { no new entry, but copy the message name if any from
                         { no new entry, but copy the message name if any from
@@ -397,11 +402,12 @@ implementation
                      if not(po_reintroduce in pd.procoptions) then
                      if not(po_reintroduce in pd.procoptions) then
                        begin
                        begin
                          if not is_object(_class) and
                          if not is_object(_class) and
-                            not is_objc_class_or_protocol(_class) then
+                            not is_objc_class_or_protocol(_class) and
+                            not is_java_class_or_interface(_class) then
                            MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false))
                            MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false))
                          else
                          else
                            { objects don't allow starting a new virtual tree
                            { objects don't allow starting a new virtual tree
-                             and neither does Objective-C }
+                             and neither do Objective-C or Java }
                            MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,vmtpd.fullprocname(false));
                            MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,vmtpd.fullprocname(false));
                        end;
                        end;
                      { disable/hide old VMT entry }
                      { disable/hide old VMT entry }
@@ -771,7 +777,8 @@ implementation
           end;
           end;
         build_interface_mappings;
         build_interface_mappings;
         if assigned(_class.ImplementedInterfaces) and
         if assigned(_class.ImplementedInterfaces) and
-           not(is_objc_class_or_protocol(_class)) then
+           not(is_objc_class_or_protocol(_class)) and
+           not(is_java_class_or_interface(_class)) then
           begin
           begin
             { Optimize interface tables to reuse wrappers }
             { Optimize interface tables to reuse wrappers }
             intf_optimize_vtbls;
             intf_optimize_vtbls;
@@ -788,9 +795,11 @@ implementation
         ImplIntf : TImplementedInterface;
         ImplIntf : TImplementedInterface;
         i: longint;
         i: longint;
       begin
       begin
-        { Find Procdefs implementing the interfaces }
+        { Find Procdefs implementing the interfaces (both Objective-C protocols
+          and Java interfaces can have multiple parent interfaces, but in that
+          case obviously no implementations are required) }
         if assigned(_class.ImplementedInterfaces) and
         if assigned(_class.ImplementedInterfaces) and
-           (_class.objecttype<>odt_objcprotocol) then
+           not(_class.objecttype in [odt_objcprotocol,odt_interfacejava]) then
           begin
           begin
             { Collect implementor functions into the tImplementedInterface.procdefs }
             { Collect implementor functions into the tImplementedInterface.procdefs }
             case _class.objecttype of
             case _class.objecttype of
@@ -802,11 +811,13 @@ implementation
                       intf_get_procdefs_recursive(ImplIntf,ImplIntf.IntfDef)
                       intf_get_procdefs_recursive(ImplIntf,ImplIntf.IntfDef)
                     end;
                     end;
                 end;
                 end;
-              odt_objcclass:
+              odt_objcclass,
+              odt_javaclass:
                 begin
                 begin
                   { Object Pascal interfaces are afterwards optimized via the
                   { Object Pascal interfaces are afterwards optimized via the
                     intf_optimize_vtbls() method, but we can't do this for
                     intf_optimize_vtbls() method, but we can't do this for
-                    protocols -> check for duplicates here already. }
+                    protocols/Java interfaces -> check for duplicates here
+                    already. }
                   handledprotocols:=tfpobjectlist.create(false);
                   handledprotocols:=tfpobjectlist.create(false);
                   for i:=0 to _class.ImplementedInterfaces.count-1 do
                   for i:=0 to _class.ImplementedInterfaces.count-1 do
                     begin
                     begin

+ 25 - 10
compiler/pdecobj.pas

@@ -280,17 +280,31 @@ implementation
       end;
       end;
 
 
 
 
-    procedure handleImplementedProtocol(intfdef : tobjectdef);
+    procedure handleImplementedProtocolOrJavaIntf(intfdef : tobjectdef);
       begin
       begin
         intfdef:=find_real_class_definition(intfdef,false);
         intfdef:=find_real_class_definition(intfdef,false);
-        if not is_objcprotocol(intfdef) then
-          begin
-             Message1(type_e_protocol_type_expected,intfdef.typename);
-             exit;
-          end;
+        case current_objectdef.objecttype of
+          odt_objcclass,
+          odt_objccategory,
+          odt_objcprotocol:
+            if not is_objcprotocol(intfdef) then
+              begin
+                 Message1(type_e_protocol_type_expected,intfdef.typename);
+                 exit;
+              end;
+          odt_javaclass,
+          odt_interfacejava:
+            if not is_javainterface(intfdef) then
+              begin
+                Message1(type_e_interface_type_expected,intfdef.typename);
+                exit
+              end;
+          else
+            internalerror(2011010807);
+        end;
         if ([oo_is_forward,oo_is_formal] * intfdef.objectoptions <> []) then
         if ([oo_is_forward,oo_is_formal] * intfdef.objectoptions <> []) then
           begin
           begin
-             Message1(parser_e_forward_protocol_declaration_must_be_resolved,intfdef.objrealname^);
+             Message1(parser_e_forward_intf_declaration_must_be_resolved,intfdef.objrealname^);
              exit;
              exit;
           end;
           end;
         if current_objectdef.find_implemented_interface(intfdef)<>nil then
         if current_objectdef.find_implemented_interface(intfdef)<>nil then
@@ -321,7 +335,7 @@ implementation
              if intf then
              if intf then
                handleImplementedInterface(tobjectdef(hdef))
                handleImplementedInterface(tobjectdef(hdef))
              else
              else
-               handleImplementedProtocol(tobjectdef(hdef));
+               handleImplementedProtocolOrJavaIntf(tobjectdef(hdef));
           end;
           end;
       end;
       end;
 
 
@@ -425,7 +439,8 @@ implementation
                 Message(parser_e_abstract_and_sealed_conflict);
                 Message(parser_e_abstract_and_sealed_conflict);
             end;
             end;
           odt_cppclass,
           odt_cppclass,
-          odt_javaclass:
+          odt_javaclass,
+          odt_interfacejava:
             get_cpp_or_java_class_external_status(current_objectdef);
             get_cpp_or_java_class_external_status(current_objectdef);
           odt_objcclass,odt_objcprotocol,odt_objccategory:
           odt_objcclass,odt_objcprotocol,odt_objccategory:
             get_objc_class_or_protocol_external_status(current_objectdef);
             get_objc_class_or_protocol_external_status(current_objectdef);
@@ -598,7 +613,7 @@ implementation
                   if current_objectdef.objecttype=odt_class then
                   if current_objectdef.objecttype=odt_class then
                     handleImplementedInterface(intfchildof)
                     handleImplementedInterface(intfchildof)
                   else
                   else
-                    handleImplementedProtocol(intfchildof);
+                    handleImplementedProtocolOrJavaIntf(intfchildof);
                 readImplementedInterfacesAndProtocols(current_objectdef.objecttype=odt_class);
                 readImplementedInterfacesAndProtocols(current_objectdef.objecttype=odt_class);
               end;
               end;
             consume(_RKLAMMER);
             consume(_RKLAMMER);

+ 10 - 5
compiler/symdef.pas

@@ -4213,7 +4213,6 @@ implementation
         { see tprocdef.jvmmangledname for description of the format }
         { see tprocdef.jvmmangledname for description of the format }
         if fordefinition then
         if fordefinition then
           begin
           begin
-            { definition: visibility/static }
             case visibility of
             case visibility of
               vis_hidden,
               vis_hidden,
               vis_strictprivate:
               vis_strictprivate:
@@ -4230,6 +4229,8 @@ implementation
             if (procsym.owner.symtabletype in [globalsymtable,staticsymtable,localsymtable]) or
             if (procsym.owner.symtabletype in [globalsymtable,staticsymtable,localsymtable]) or
                (po_staticmethod in procoptions) then
                (po_staticmethod in procoptions) then
               tmpresult:=tmpresult+'static ';
               tmpresult:=tmpresult+'static ';
+            if is_javainterface(tdef(owner.defowner)) then
+              tmpresult:=tmpresult+'abstract ';
           end
           end
         else
         else
           begin
           begin
@@ -4528,7 +4529,7 @@ implementation
         if objecttype in [odt_interfacecorba,odt_interfacecom,odt_dispinterface] then
         if objecttype in [odt_interfacecorba,odt_interfacecom,odt_dispinterface] then
           prepareguid;
           prepareguid;
         { setup implemented interfaces }
         { setup implemented interfaces }
-        if objecttype in [odt_class,odt_objcclass,odt_objcprotocol,odt_interfacejava] then
+        if objecttype in [odt_class,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava] then
           ImplementedInterfaces:=TFPObjectList.Create(true)
           ImplementedInterfaces:=TFPObjectList.Create(true)
         else
         else
           ImplementedInterfaces:=nil;
           ImplementedInterfaces:=nil;
@@ -5068,8 +5069,12 @@ implementation
    function tobjectdef.is_related(d : tdef) : boolean;
    function tobjectdef.is_related(d : tdef) : boolean;
      var
      var
         hp : tobjectdef;
         hp : tobjectdef;
+        realself: tobjectdef;
      begin
      begin
-        if self=d then
+        if (d.typ=objectdef) then
+          d:=find_real_class_definition(tobjectdef(d),false);
+        realself:=find_real_class_definition(self,false);
+        if realself=d then
           begin
           begin
             is_related:=true;
             is_related:=true;
             exit;
             exit;
@@ -5085,7 +5090,7 @@ implementation
            inheritance }
            inheritance }
         if (objecttype in [odt_objcprotocol,odt_interfacejava]) then
         if (objecttype in [odt_objcprotocol,odt_interfacejava]) then
           begin
           begin
-            is_related:=is_related_interface_multiple(self,d);
+            is_related:=is_related_interface_multiple(realself,d);
             exit
             exit
           end;
           end;
 
 
@@ -5112,7 +5117,7 @@ implementation
             exit;
             exit;
           end;
           end;
 
 
-        hp:=childof;
+        hp:=realself.childof;
         while assigned(hp) do
         while assigned(hp) do
           begin
           begin
              if hp=d then
              if hp=d then

Some files were not shown because too many files changed in this diff