Sfoglia il codice sorgente

* rewrote isbinaryoverloadable to use a case. it's now much easier
to understand what is happening

peter 23 anni fa
parent
commit
18fd47a47a
1 ha cambiato i file con 259 aggiunte e 119 eliminazioni
  1. 259 119
      compiler/htypechk.pas

+ 259 - 119
compiler/htypechk.pas

@@ -77,13 +77,11 @@ interface
 
     { is overloading of this operator allowed for this
       binary operator }
-    function isbinaryoperatoroverloadable(ld, rd,dd : tdef;
-             treetyp : tnodetype) : boolean;
+    function isbinaryoperatoroverloadable(ld, rd,dd : tdef; treetyp : tnodetype) : boolean;
 
     { is overloading of this operator allowed for this
       unary operator }
-    function isunaryoperatoroverloadable(rd,dd : tdef;
-             treetyp : tnodetype) : boolean;
+    function isunaryoperatoroverloadable(rd,dd : tdef; treetyp : tnodetype) : boolean;
 
     { check operator args and result type }
     function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
@@ -137,132 +135,270 @@ implementation
       TValidAssigns=set of TValidAssign;
 
 
-    { ld is the left type definition
-      rd the right type definition
-      dd the result type definition  or voiddef if unkown }
-    function isbinaryoperatoroverloadable(ld, rd, dd : tdef;
-             treetyp : tnodetype) : boolean;
+    function isbinaryoperatoroverloadable(ld,rd,dd : tdef; treetyp : tnodetype) : boolean;
       begin
-        isbinaryoperatoroverloadable:=
-           (treetyp=starstarn) or
-           (ld.deftype=recorddef) or
-           (rd.deftype=recorddef) or
-           (ld.deftype=variantdef) or
-           (rd.deftype=variantdef) or
-           ((rd.deftype=pointerdef) and
-            not(is_dynamic_array(ld) and
-                is_voidpointer(rd)) and
-            not(is_pchar(rd) and
-                (is_chararray(ld) or
-                 (ld.deftype=stringdef) or
-                 (treetyp=addn))) and
-            (not(ld.deftype in [pointerdef,objectdef,classrefdef,procvardef]) or
-             not (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,subn])
-            ) and
-            (not is_integer(ld) or not (treetyp in [addn,subn]))
-           ) or
-           ((ld.deftype=pointerdef) and
-            not(is_dynamic_array(rd) and
-                is_voidpointer(ld)) and
-            not(is_pchar(ld) and
-                (is_chararray(rd) or
-                 (rd.deftype=stringdef) or
-                 (treetyp=addn))) and
-            (not(rd.deftype in [stringdef,pointerdef,objectdef,classrefdef,procvardef]) and
-             ((not is_integer(rd) and (rd.deftype<>objectdef)
-               and (rd.deftype<>classrefdef)) or
-              not (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,addn,subn])
-             )
-            )
-           ) or
-           { array def, but not mmx or chararray+[char,string,chararray] }
-           ((ld.deftype=arraydef) and
-            not((cs_mmx in aktlocalswitches) and
-                is_mmx_able_array(ld)) and
-            not(is_dynamic_array(ld) and
-                is_voidpointer(rd)) and
-            not(is_chararray(ld) and
-                (is_char(rd) or
-                 is_pchar(rd) or
-                 { char array + int = pchar + int, fix for web bug 1377 (JM) }
-                 is_integer(rd) or
-                 (rd.deftype=stringdef) or
-                 is_chararray(rd)))
-           ) or
-           ((rd.deftype=arraydef) and
-            not((cs_mmx in aktlocalswitches) and
-                is_mmx_able_array(rd)) and
-            not(is_dynamic_array(rd) and
-                is_voidpointer(ld)) and
-            not(is_chararray(rd) and
-                (is_char(ld) or
-                 is_pchar(ld) or
-                 (ld.deftype=stringdef) or
-                 is_chararray(ld)))
-           ) or
-           { <> and = are defined for classes }
-           (
-            (ld.deftype=objectdef) and
-            not((treetyp in [equaln,unequaln]) and is_class_or_interface(ld))
-           ) or
-           (
-            (rd.deftype=objectdef) and
-            not((treetyp in [equaln,unequaln]) and is_class_or_interface(rd))
-           )
-           or
-           { allow other operators that + on strings }
-           (
-            (is_char(rd) or
-             is_pchar(rd) or
-             (rd.deftype=stringdef) or
-             is_chararray(rd) or
-             is_char(ld) or
-             is_pchar(ld) or
-             (ld.deftype=stringdef) or
-             is_chararray(ld)
-             ) and
-             not(treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
-             not(is_pchar(ld) and
-                 (is_integer(rd) or (rd.deftype=pointerdef)) and
-                 (treetyp=subn)
-                )
-            );
+        { everything is possible, the exceptions will be
+          handled below }
+        isbinaryoperatoroverloadable:=false;
+        { power ** is always possible }
+        if (treetyp=starstarn) then
+         begin
+           isbinaryoperatoroverloadable:=true;
+           exit;
+         end;
+        case ld.deftype of
+          recorddef,
+          variantdef :
+            begin
+              isbinaryoperatoroverloadable:=true;
+              exit;
+            end;
+          procvardef :
+            begin
+              if (rd.deftype in [pointerdef,procdef,procvardef]) and
+                 (treetyp in [equaln,unequaln]) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+            end;
+          pointerdef :
+            begin
+              if (rd.deftype in [pointerdef,objectdef,classrefdef,procvardef]) and
+                 (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,addn,subn]) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+
+              { don't allow operations on pointer/integer }
+              if is_integer(rd) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+
+              { don't allow pchar+string }
+              if is_pchar(ld) and
+                 (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
+                 (is_chararray(rd) or
+                  is_char(rd) or
+                  (rd.deftype=stringdef)) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+
+              isbinaryoperatoroverloadable:=true;
+            end;
+          arraydef :
+            begin
+              { not mmx }
+              if (cs_mmx in aktlocalswitches) and
+                 is_mmx_able_array(ld) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+              { not chararray+[char,string,chararray] }
+              if is_chararray(ld) and
+                 (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
+                 (is_char(rd) or
+                  is_pchar(rd) or
+                  is_integer(rd) or
+                  (rd.deftype=stringdef) or
+                  is_chararray(rd)) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+
+              isbinaryoperatoroverloadable:=true;
+            end;
+          objectdef :
+            begin
+              { <> and = are defined for classes }
+              if (treetyp in [equaln,unequaln]) and
+                 is_class_or_interface(ld) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+              isbinaryoperatoroverloadable:=true;
+            end;
+          stringdef :
+            begin
+              if ((rd.deftype=stringdef) or
+                  is_char(rd) or
+                  is_pchar(rd) or
+                  is_chararray(rd)) and
+                 (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+              isbinaryoperatoroverloadable:=true;
+            end;
+        end;
+
+        { Also check the right def. There can be some duplicated code
+          that is never reached. But to place everything in one big
+          case is unmaintainable }
+        case rd.deftype of
+          recorddef,
+          variantdef :
+            begin
+              isbinaryoperatoroverloadable:=true;
+              exit;
+            end;
+          procvardef :
+            begin
+              if (ld.deftype in [pointerdef,procdef,procvardef]) and
+                 (treetyp in [equaln,unequaln]) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+              isbinaryoperatoroverloadable:=true;
+            end;
+          pointerdef :
+            begin
+              if (ld.deftype in [pointerdef,objectdef,classrefdef,procvardef]) and
+                 (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,addn,subn]) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+
+              { don't allow operations on pointer/integer }
+              if is_integer(ld) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+
+              { don't allow pchar+string }
+              if is_pchar(rd) and
+                 (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
+                 (is_chararray(ld) or
+                  is_char(ld) or
+                  (ld.deftype=stringdef)) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+
+              isbinaryoperatoroverloadable:=true;
+            end;
+          arraydef :
+            begin
+              { not mmx }
+              if (cs_mmx in aktlocalswitches) and
+                 is_mmx_able_array(rd) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+              { not chararray+[char,string,chararray] }
+              if is_chararray(rd) and
+                 (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
+                 (is_char(ld) or
+                  is_pchar(ld) or
+                  is_integer(ld) or
+                  (ld.deftype=stringdef) or
+                  is_chararray(ld)) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+              isbinaryoperatoroverloadable:=true;
+            end;
+          objectdef :
+            begin
+              { <> and = are defined for classes }
+              if (treetyp in [equaln,unequaln]) and
+                 is_class_or_interface(rd) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+              isbinaryoperatoroverloadable:=true;
+            end;
+          stringdef :
+            begin
+              if ((ld.deftype=stringdef) or
+                  is_char(ld) or
+                  is_pchar(ld) or
+                  is_chararray(ld)) and
+                 (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) then
+               begin
+                 isbinaryoperatoroverloadable:=false;
+                 exit;
+               end;
+              isbinaryoperatoroverloadable:=true;
+            end;
+        end;
       end;
 
 
-    function isunaryoperatoroverloadable(rd,dd : tdef;
-             treetyp : tnodetype) : boolean;
+    function isunaryoperatoroverloadable(rd,dd : tdef; treetyp : tnodetype) : boolean;
       begin
         isunaryoperatoroverloadable:=false;
-        { what assignment overloading should be allowed ?? }
-        if (treetyp=assignn) then
-          begin
-            isunaryoperatoroverloadable:=true;
-             { this already get tbs0261 to fail
-             isunaryoperatoroverloadable:=not is_equal(rd,dd); PM }
-          end
-        { should we force that rd and dd are equal ?? }
-        else if (treetyp=subn { unaryminusn }) then
-          begin
-            isunaryoperatoroverloadable:=
-              not is_integer(rd) and not (rd.deftype=floatdef)
+        case treetyp of
+          assignn :
+            begin
+              if (rd.deftype=orddef) and
+                 (dd.deftype=orddef) then
+               begin
+                 isunaryoperatoroverloadable:=false;
+                 exit;
+               end;
+              isunaryoperatoroverloadable:=true;
+            end;
+
+          subn :
+            begin
+              if is_integer(rd) or
+                 (rd.deftype=floatdef) then
+               begin
+                 isunaryoperatoroverloadable:=false;
+                 exit;
+               end;
+
 {$ifdef SUPPORT_MMX}
-              and not ((cs_mmx in aktlocalswitches) and
-              is_mmx_able_array(rd))
+              if (cs_mmx in aktlocalswitches) and
+                 is_mmx_able_array(rd) then
+               begin
+                 isunaryoperatoroverloadable:=false;
+                 exit;
+               end;
 {$endif SUPPORT_MMX}
-              ;
-          end
-        else if (treetyp=notn) then
-          begin
-            isunaryoperatoroverloadable:=not is_integer(rd) and not is_boolean(rd)
+              isunaryoperatoroverloadable:=true;
+            end;
+
+          notn :
+            begin
+              if is_integer(rd) or
+                 is_boolean(rd) then
+               begin
+                 isunaryoperatoroverloadable:=false;
+                 exit;
+               end;
+
 {$ifdef SUPPORT_MMX}
-              and not ((cs_mmx in aktlocalswitches) and
-              is_mmx_able_array(rd))
+              if (cs_mmx in aktlocalswitches) and
+                 is_mmx_able_array(rd) then
+               begin
+                 isunaryoperatoroverloadable:=false;
+                 exit;
+               end;
 {$endif SUPPORT_MMX}
-              ;
-          end;
+              isunaryoperatoroverloadable:=true;
+            end;
+        end;
       end;
 
+
     function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
       var
         ld,rd,dd : tdef;
@@ -975,7 +1111,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.51  2002-11-25 17:43:17  peter
+  Revision 1.52  2002-11-27 22:11:59  peter
+    * rewrote isbinaryoverloadable to use a case. it's now much easier
+      to understand what is happening
+
+  Revision 1.51  2002/11/25 17:43:17  peter
     * splitted defbase in defutil,symutil,defcmp
     * merged isconvertable and is_equal into compare_defs(_ext)
     * made operator search faster by walking the list only once