Browse Source

fcl-passrc: resolver: type helper set

git-svn-id: trunk@41294 -
Mattias Gaertner 6 years ago
parent
commit
1b6c69e079
2 changed files with 75 additions and 15 deletions
  1. 66 12
      packages/fcl-passrc/src/pasresolver.pp
  2. 9 3
      packages/fcl-passrc/tests/tcresolver.pas

+ 66 - 12
packages/fcl-passrc/src/pasresolver.pp

@@ -1995,6 +1995,7 @@ type
     function ParentNeedsExprResult(El: TPasExpr): boolean;
     function ParentNeedsExprResult(El: TPasExpr): boolean;
     function GetReference_ConstructorType(Ref: TResolvedReference; Expr: TPasExpr): TPasResolverResult;
     function GetReference_ConstructorType(Ref: TResolvedReference; Expr: TPasExpr): TPasResolverResult;
     function GetParamsValueRef(Params: TParamsExpr): TResolvedReference;
     function GetParamsValueRef(Params: TParamsExpr): TResolvedReference;
+    function GetSetType(const ResolvedSet: TPasResolverResult): TPasSetType;
     function IsDynArray(TypeEl: TPasType; OptionalOpenArray: boolean = true): boolean;
     function IsDynArray(TypeEl: TPasType; OptionalOpenArray: boolean = true): boolean;
     function IsOpenArray(TypeEl: TPasType): boolean;
     function IsOpenArray(TypeEl: TPasType): boolean;
     function IsDynOrOpenArray(TypeEl: TPasType): boolean;
     function IsDynOrOpenArray(TypeEl: TPasType): boolean;
@@ -8859,6 +8860,22 @@ end;
 
 
 procedure TPasResolver.ResolveSubIdent(El: TBinaryExpr;
 procedure TPasResolver.ResolveSubIdent(El: TBinaryExpr;
   Access: TResolvedRefAccess);
   Access: TResolvedRefAccess);
+
+  function SearchInTypeHelpers(aType: TPasType; IdentEl: TPasElement): boolean;
+  var
+    DotScope: TPasDotBaseScope;
+  begin
+    if aType=nil then exit(false);
+    DotScope:=PushHelperDotScope(aType);
+    if DotScope=nil then exit(false);
+    if IdentEl is TPasType then
+      // e.g. TFlag.HelperProc
+      DotScope.OnlyTypeMembers:=true;
+    ResolveExpr(El.right,Access);
+    PopScope;
+    Result:=true;
+  end;
+
 var
 var
   aModule: TPasModule;
   aModule: TPasModule;
   ClassEl: TPasClassType;
   ClassEl: TPasClassType;
@@ -8869,6 +8886,7 @@ var
   RecordScope: TPasDotClassOrRecordScope;
   RecordScope: TPasDotClassOrRecordScope;
   LTypeEl: TPasType;
   LTypeEl: TPasType;
   DotScope: TPasDotBaseScope;
   DotScope: TPasDotBaseScope;
+  SetType: TPasSetType;
 begin
 begin
   if El.CustomData is TResolvedReference then
   if El.CustomData is TResolvedReference then
     exit; // for example, when a.b has a dotted unit name
     exit; // for example, when a.b has a dotted unit name
@@ -8951,7 +8969,7 @@ begin
       end
       end
     else if LTypeEl.ClassType=TPasEnumType then
     else if LTypeEl.ClassType=TPasEnumType then
       begin
       begin
-      if LeftResolved.IdentEl is TPasType then
+      if LeftResolved.IdentEl is TPasEnumType then
         begin
         begin
         // e.g. TShiftState.ssAlt
         // e.g. TShiftState.ssAlt
         DotScope:=PushEnumDotScope(TPasEnumType(LTypeEl));
         DotScope:=PushEnumDotScope(TPasEnumType(LTypeEl));
@@ -8965,16 +8983,12 @@ begin
     if (LeftResolved.BaseType in btAllStandardTypes)
     if (LeftResolved.BaseType in btAllStandardTypes)
         or (LeftResolved.BaseType=btContext) then
         or (LeftResolved.BaseType=btContext) then
       begin
       begin
-      DotScope:=PushHelperDotScope(LeftResolved.HiTypeEl);
-      if DotScope<>nil then
-        begin
-        if LeftResolved.IdentEl is TPasType then
-          // e.g. TSet.HelperProc
-          DotScope.OnlyTypeMembers:=true;
-        ResolveExpr(El.right,Access);
-        PopScope;
-        exit;
-        end;
+      if SearchInTypeHelpers(LeftResolved.HiTypeEl,LeftResolved.IdentEl) then exit;
+      end
+    else if LeftResolved.BaseType=btSet then
+      begin
+      SetType:=GetSetType(LeftResolved);
+      if SearchInTypeHelpers(SetType,LeftResolved.IdentEl) then exit;
       end;
       end;
     end;
     end;
 
 
@@ -11691,7 +11705,7 @@ begin
             and (ParamResolved.LoTypeEl.ClassType=TPasArrayType)
             and (ParamResolved.LoTypeEl.ClassType=TPasArrayType)
             and IsDynArray(ToLoType)
             and IsDynArray(ToLoType)
             and IsDynArray(ParamResolved.LoTypeEl) then
             and IsDynArray(ParamResolved.LoTypeEl) then
-          // typecast array
+          // typecast dyn array to dyn array
           KeepWriteFlags:=true;
           KeepWriteFlags:=true;
         end
         end
       else
       else
@@ -22007,6 +22021,46 @@ begin
     end;
     end;
 end;
 end;
 
 
+function TPasResolver.GetSetType(const ResolvedSet: TPasResolverResult
+  ): TPasSetType;
+var
+  IdentEl: TPasElement;
+  aType: TPasType;
+  C: TClass;
+begin
+  Result:=nil;
+  if ResolvedSet.BaseType=btSet then
+    begin
+    IdentEl:=ResolvedSet.IdentEl;
+    if IdentEl=nil then exit;
+    C:=IdentEl.ClassType;
+    if (C=TPasVariable)
+        or (C=TPasConst) then
+      aType:=TPasVariable(IdentEl).VarType
+    else if C=TPasProperty then
+      aType:=GetPasPropertyType(TPasProperty(IdentEl))
+    else if C=TPasArgument then
+      aType:=TPasArgument(IdentEl).ArgType
+    else if C.InheritsFrom(TPasProcedure)
+        and (TPasProcedure(IdentEl).ProcType is TPasFunctionType) then
+      aType:=TPasFunctionType(TPasProcedure(IdentEl).ProcType).ResultEl.ResultType
+    else if C=TPasSetType then
+      exit(TPasSetType(IdentEl))
+    else
+      exit;
+    if aType.ClassType=TPasSetType then
+      Result:=TPasSetType(aType);
+    end
+  else if ResolvedSet.BaseType=btContext then
+    begin
+    if ResolvedSet.LoTypeEl.ClassType=TPasSetType then
+      if ResolvedSet.HiTypeEl.ClassType=TPasSetType then
+        Result:=TPasSetType(ResolvedSet.HiTypeEl)
+      else
+        Result:=TPasSetType(ResolvedSet.LoTypeEl);
+    end;
+end;
+
 function TPasResolver.IsDynArray(TypeEl: TPasType; OptionalOpenArray: boolean
 function TPasResolver.IsDynArray(TypeEl: TPasType; OptionalOpenArray: boolean
   ): boolean;
   ): boolean;
 begin
 begin

+ 9 - 3
packages/fcl-passrc/tests/tcresolver.pas

@@ -17073,6 +17073,7 @@ begin
   '  TSetOfEnum = set of TEnum;',
   '  TSetOfEnum = set of TEnum;',
   '  THelper = type helper for TSetOfEnum',
   '  THelper = type helper for TSetOfEnum',
   '    procedure Fly;',
   '    procedure Fly;',
+  '    class procedure Run; static;',
   '  end;',
   '  end;',
   'procedure THelper.Fly;',
   'procedure THelper.Fly;',
   'begin',
   'begin',
@@ -17080,11 +17081,16 @@ begin
   '  Self:=[green];',
   '  Self:=[green];',
   '  Include(Self,blue);',
   '  Include(Self,blue);',
   'end;',
   'end;',
+  'class procedure THelper.Run;',
+  'begin',
+  'end;',
   'var s: TSetOfEnum;',
   'var s: TSetOfEnum;',
   'begin',
   'begin',
-  // todo: '  s.Fly;',
-  // not supported: [green].Fly
-  // todo: with s do Fly
+  '  s.Fly;',
+  //'  with s do Fly;',
+  '  TSetOfEnum.Run;',
+  //'  with TSetOfEnum do Run;',
+  //'  [green].Fly', not supported
   '']);
   '']);
   ParseProgram;
   ParseProgram;
 end;
 end;