Browse Source

fcl-passrc: pasresolver: allow adding custom arram params

git-svn-id: trunk@35713 -
Mattias Gaertner 8 years ago
parent
commit
d4c801b708
1 changed files with 127 additions and 66 deletions
  1. 127 66
      packages/fcl-passrc/src/pasresolver.pp

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

@@ -1065,6 +1065,11 @@ type
     procedure ResolveParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
     procedure ResolveParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
     procedure ResolveFuncParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
     procedure ResolveFuncParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
     procedure ResolveArrayParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
     procedure ResolveArrayParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
+    procedure ResolveArrayParamsArgs(Params: TParamsExpr;
+      const ResolvedValue: TPasResolverResult; Access: TResolvedRefAccess); virtual;
+    function ResolveBracketOperatorClass(Params: TParamsExpr;
+      const ResolvedValue: TPasResolverResult; ClassScope: TPasClassScope;
+      Access: TResolvedRefAccess): boolean; virtual;
     procedure ResolveSetParamsExpr(Params: TParamsExpr); virtual;
     procedure ResolveSetParamsExpr(Params: TParamsExpr); virtual;
     procedure ResolveArrayValues(El: TArrayValues); virtual;
     procedure ResolveArrayValues(El: TArrayValues); virtual;
     procedure FinishModule(CurModule: TPasModule); virtual;
     procedure FinishModule(CurModule: TPasModule); virtual;
@@ -1091,6 +1096,8 @@ type
     procedure FinishArgument(El: TPasArgument); virtual;
     procedure FinishArgument(El: TPasArgument); virtual;
     procedure FinishAncestors(aClass: TPasClassType); virtual;
     procedure FinishAncestors(aClass: TPasClassType); virtual;
     procedure FinishParamExpressionAccess(Expr: TPasExpr; Access: TResolvedRefAccess);
     procedure FinishParamExpressionAccess(Expr: TPasExpr; Access: TResolvedRefAccess);
+    procedure FinishPropertyParamAccess(Params: TParamsExpr;
+      Prop: TPasProperty);
     procedure ReplaceProcScopeImplArgsWithDeclArgs(ImplProcScope: TPasProcedureScope);
     procedure ReplaceProcScopeImplArgsWithDeclArgs(ImplProcScope: TPasProcedureScope);
     procedure CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure);
     procedure CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure);
     procedure CheckPendingForwards(El: TPasElement);
     procedure CheckPendingForwards(El: TPasElement);
@@ -1100,6 +1107,9 @@ type
     procedure ComputeArrayParams(Params: TParamsExpr;
     procedure ComputeArrayParams(Params: TParamsExpr;
       out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
       out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
       StartEl: TPasElement);
       StartEl: TPasElement);
+    procedure ComputeArrayParams_Class(Params: TParamsExpr;
+      var ResolvedEl: TPasResolverResult; ClassScope: TPasClassScope;
+      Flags: TPasResolverComputeFlags; StartEl: TPasElement); virtual;
     procedure ComputeFuncParams(Params: TParamsExpr;
     procedure ComputeFuncParams(Params: TParamsExpr;
       out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
       out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
       StartEl: TPasElement);
       StartEl: TPasElement);
@@ -1354,6 +1364,7 @@ type
     function IsOpenArray(TypeEl: TPasType): boolean;
     function IsOpenArray(TypeEl: TPasType): boolean;
     function IsDynOrOpenArray(TypeEl: TPasType): boolean;
     function IsDynOrOpenArray(TypeEl: TPasType): boolean;
     function IsClassMethod(El: TPasElement): boolean;
     function IsClassMethod(El: TPasElement): boolean;
+    function IsExternalClassName(aClass: TPasClassType; const ExtName: string): boolean;
     function IsProcedureType(const ResolvedEl: TPasResolverResult): boolean;
     function IsProcedureType(const ResolvedEl: TPasResolverResult): boolean;
     function IsArrayType(const ResolvedEl: TPasResolverResult): boolean;
     function IsArrayType(const ResolvedEl: TPasResolverResult): boolean;
     function IsTypeCast(Params: TParamsExpr): boolean;
     function IsTypeCast(Params: TParamsExpr): boolean;
@@ -4065,6 +4076,24 @@ begin
     end;
     end;
 end;
 end;
 
 
+procedure TPasResolver.FinishPropertyParamAccess(Params: TParamsExpr;
+  Prop: TPasProperty);
+var
+  i: Integer;
+  ParamAccess: TResolvedRefAccess;
+begin
+  for i:=0 to length(Params.Params)-1 do
+    begin
+    ParamAccess:=rraRead;
+    if i<Prop.Args.Count then
+      case TPasArgument(Prop.Args[i]).Access of
+      argVar: ParamAccess:=rraVarParam;
+      argOut: ParamAccess:=rraOutParam;
+      end;
+    FinishParamExpressionAccess(Params.Params[i],ParamAccess);
+    end;
+end;
+
 procedure TPasResolver.ReplaceProcScopeImplArgsWithDeclArgs(
 procedure TPasResolver.ReplaceProcScopeImplArgsWithDeclArgs(
   ImplProcScope: TPasProcedureScope);
   ImplProcScope: TPasProcedureScope);
 var
 var
@@ -5070,55 +5099,34 @@ end;
 
 
 procedure TPasResolver.ResolveArrayParamsExpr(Params: TParamsExpr;
 procedure TPasResolver.ResolveArrayParamsExpr(Params: TParamsExpr;
   Access: TResolvedRefAccess);
   Access: TResolvedRefAccess);
+var
+  ResolvedEl: TPasResolverResult;
 
 
-  procedure FinishPropertyParamAccess(Prop: TPasProperty);
+  procedure ResolveValueName(Value: TPasElement; ArrayName: string);
   var
   var
-    i: Integer;
-    ParamAccess: TResolvedRefAccess;
+    FindData: TPRFindData;
+    Ref: TResolvedReference;
+    DeclEl: TPasElement;
   begin
   begin
-    for i:=0 to length(Params.Params)-1 do
-      begin
-      ParamAccess:=rraRead;
-      if i<Prop.Args.Count then
-        case TPasArgument(Prop.Args[i]).Access of
-        argVar: ParamAccess:=rraVarParam;
-        argOut: ParamAccess:=rraOutParam;
-        end;
-      FinishParamExpressionAccess(Params.Params[i],ParamAccess);
-      end;
+    // e.g. Name[]
+    DeclEl:=FindElementWithoutParams(ArrayName,FindData,Value,true);
+    Ref:=CreateReference(DeclEl,Value,Access,@FindData);
+    CheckFoundElement(FindData,Ref);
+    ComputeElement(Value,ResolvedEl,[rcSkipTypeAlias]);
   end;
   end;
 
 
 var
 var
-  ArrayName: String;
-  FindData: TPRFindData;
-  DeclEl: TPasElement;
-  ResolvedEl, ResolvedArg: TPasResolverResult;
-  ArgExp, Value: TPasExpr;
-  Ref: TResolvedReference;
-  PropEl: TPasProperty;
-  ClassScope: TPasClassScope;
+  Value: TPasExpr;
   SubParams: TParamsExpr;
   SubParams: TParamsExpr;
-  i: Integer;
 begin
 begin
-  DeclEl:=nil;
   Value:=Params.Value;
   Value:=Params.Value;
   if (Value.ClassType=TPrimitiveExpr)
   if (Value.ClassType=TPrimitiveExpr)
       and (TPrimitiveExpr(Value).Kind=pekIdent) then
       and (TPrimitiveExpr(Value).Kind=pekIdent) then
-    begin
     // e.g. Name[]
     // e.g. Name[]
-    ArrayName:=TPrimitiveExpr(Value).Value;
-    // find first
-    DeclEl:=FindElementWithoutParams(ArrayName,FindData,Value,true);
-    Ref:=CreateReference(DeclEl,Params.Value,Access,@FindData);
-    CheckFoundElement(FindData,Ref);
-    ComputeElement(Value,ResolvedEl,[rcSkipTypeAlias]);
-    end
+    ResolveValueName(Value,TPrimitiveExpr(Value).Value)
   else if (Value.ClassType=TSelfExpr) then
   else if (Value.ClassType=TSelfExpr) then
-    begin
     // e.g. Self[]
     // e.g. Self[]
-    ResolveNameExpr(Value,'Self',Access);
-    ComputeElement(Value,ResolvedEl,[rcSkipTypeAlias]);
-    end
+    ResolveValueName(Value,'Self')
   else if Value.ClassType=TParamsExpr then
   else if Value.ClassType=TParamsExpr then
     begin
     begin
     SubParams:=TParamsExpr(Value);
     SubParams:=TParamsExpr(Value);
@@ -5138,11 +5146,23 @@ begin
   {$IFDEF VerbosePasResolver}
   {$IFDEF VerbosePasResolver}
   writeln('TPasResolver.ResolveArrayParamsExpr Value=',GetObjName(Value),' ',GetResolverResultDesc(ResolvedEl));
   writeln('TPasResolver.ResolveArrayParamsExpr Value=',GetObjName(Value),' ',GetResolverResultDesc(ResolvedEl));
   {$ENDIF}
   {$ENDIF}
-  if ResolvedEl.BaseType in btAllStrings then
+  ResolveArrayParamsArgs(Params,ResolvedEl,Access);
+end;
+
+procedure TPasResolver.ResolveArrayParamsArgs(Params: TParamsExpr;
+  const ResolvedValue: TPasResolverResult; Access: TResolvedRefAccess);
+var
+  ArgExp: TPasExpr;
+  ResolvedArg: TPasResolverResult;
+  PropEl: TPasProperty;
+  ClassScope: TPasClassScope;
+  i: Integer;
+begin
+  if ResolvedValue.BaseType in btAllStrings then
     begin
     begin
-    // string -> check that ResolvedEl is not merely a type, but has a value
-    if not ResolvedElHasValue(ResolvedEl) then
-      RaiseXExpectedButYFound(20170216152548,'variable',ResolvedEl.TypeEl.ElementTypeName,Params);
+    // string -> check that ResolvedValue is not merely a type, but has a value
+    if not ResolvedElHasValue(ResolvedValue) then
+      RaiseXExpectedButYFound(20170216152548,'variable',ResolvedValue.TypeEl.ElementTypeName,Params);
     // check single argument
     // check single argument
     if length(Params.Params)<1 then
     if length(Params.Params)<1 then
       RaiseMsg(20170216152204,nMissingParameterX,
       RaiseMsg(20170216152204,nMissingParameterX,
@@ -5161,38 +5181,27 @@ begin
     FinishParamExpressionAccess(ArgExp,rraRead);
     FinishParamExpressionAccess(ArgExp,rraRead);
     exit;
     exit;
     end
     end
-  else if (ResolvedEl.IdentEl is TPasProperty)
-      and (TPasProperty(ResolvedEl.IdentEl).Args.Count>0) then
+  else if (ResolvedValue.IdentEl is TPasProperty)
+      and (TPasProperty(ResolvedValue.IdentEl).Args.Count>0) then
     begin
     begin
-    PropEl:=TPasProperty(ResolvedEl.IdentEl);
+    PropEl:=TPasProperty(ResolvedValue.IdentEl);
     CheckCallPropertyCompatibility(PropEl,Params,true);
     CheckCallPropertyCompatibility(PropEl,Params,true);
-    FinishPropertyParamAccess(PropEl);
+    FinishPropertyParamAccess(Params,PropEl);
     exit;
     exit;
     end
     end
-  else if ResolvedEl.BaseType=btContext then
+  else if ResolvedValue.BaseType=btContext then
     begin
     begin
-    if ResolvedEl.TypeEl.ClassType=TPasClassType then
+    if ResolvedValue.TypeEl.ClassType=TPasClassType then
       begin
       begin
-      ClassScope:=ResolvedEl.TypeEl.CustomData as TPasClassScope;
-      PropEl:=ClassScope.DefaultProperty;
-      if PropEl<>nil then
-        begin
-        // class has default property
-        if (ResolvedEl.IdentEl is TPasType) and (not PropEl.IsClass) then
-          RaiseMsg(20170216152213,nIllegalQualifier,sIllegalQualifier,['['],Params);
-        if Params.Value.CustomData is TResolvedReference then
-          TResolvedReference(Params.Value.CustomData).Access:=rraRead;
-        CreateReference(PropEl,Params,Access);
-        CheckCallPropertyCompatibility(PropEl,Params,true);
-        FinishPropertyParamAccess(PropEl);
+      ClassScope:=ResolvedValue.TypeEl.CustomData as TPasClassScope;
+      if ResolveBracketOperatorClass(Params,ResolvedValue,ClassScope,Access) then
         exit;
         exit;
-        end;
       end
       end
-    else if ResolvedEl.TypeEl.ClassType=TPasArrayType then
+    else if ResolvedValue.TypeEl.ClassType=TPasArrayType then
       begin
       begin
-      if ResolvedEl.IdentEl is TPasType then
+      if ResolvedValue.IdentEl is TPasType then
         RaiseMsg(20170216152215,nIllegalQualifier,sIllegalQualifier,['['],Params);
         RaiseMsg(20170216152215,nIllegalQualifier,sIllegalQualifier,['['],Params);
-      CheckCallArrayCompatibility(TPasArrayType(ResolvedEl.TypeEl),Params,true);
+      CheckCallArrayCompatibility(TPasArrayType(ResolvedValue.TypeEl),Params,true);
       for i:=0 to length(Params.Params)-1 do
       for i:=0 to length(Params.Params)-1 do
         FinishParamExpressionAccess(Params.Params[i],rraRead);
         FinishParamExpressionAccess(Params.Params[i],rraRead);
       exit;
       exit;
@@ -5201,6 +5210,28 @@ begin
   RaiseMsg(20170216152217,nIllegalQualifier,sIllegalQualifier,['['],Params);
   RaiseMsg(20170216152217,nIllegalQualifier,sIllegalQualifier,['['],Params);
 end;
 end;
 
 
+function TPasResolver.ResolveBracketOperatorClass(Params: TParamsExpr;
+  const ResolvedValue: TPasResolverResult; ClassScope: TPasClassScope;
+  Access: TResolvedRefAccess): boolean;
+var
+  PropEl: TPasProperty;
+begin
+  PropEl:=ClassScope.DefaultProperty;
+  if PropEl<>nil then
+    begin
+    // class has default property
+    if (ResolvedValue.IdentEl is TPasType) and (not PropEl.IsClass) then
+      RaiseMsg(20170216152213,nIllegalQualifier,sIllegalQualifier,['['],Params);
+    if Params.Value.CustomData is TResolvedReference then
+      TResolvedReference(Params.Value.CustomData).Access:=rraRead;
+    CreateReference(PropEl,Params,Access);
+    CheckCallPropertyCompatibility(PropEl,Params,true);
+    FinishPropertyParamAccess(Params,PropEl);
+    exit(true);
+    end;
+  Result:=false;
+end;
+
 procedure TPasResolver.ResolveSetParamsExpr(Params: TParamsExpr);
 procedure TPasResolver.ResolveSetParamsExpr(Params: TParamsExpr);
 // e.g. resolving '[1,2..3]'
 // e.g. resolving '[1,2..3]'
 begin
 begin
@@ -6089,16 +6120,18 @@ begin
     if TypeEl.ClassType=TPasClassType then
     if TypeEl.ClassType=TPasClassType then
       begin
       begin
       ClassScope:=TypeEl.CustomData as TPasClassScope;
       ClassScope:=TypeEl.CustomData as TPasClassScope;
-      if ClassScope.DefaultProperty=nil then
-        RaiseInternalError(20161010151747);
-      ComputeIndexProperty(ClassScope.DefaultProperty);
+      if ClassScope.DefaultProperty<>nil then
+        ComputeIndexProperty(ClassScope.DefaultProperty)
+      else
+        ComputeArrayParams_Class(Params,ResolvedEl,ClassScope,Flags,StartEl);
       end
       end
     else if TypeEl.ClassType=TPasClassOfType then
     else if TypeEl.ClassType=TPasClassOfType then
       begin
       begin
       ClassScope:=TPasClassOfType(TypeEl).DestType.CustomData as TPasClassScope;
       ClassScope:=TPasClassOfType(TypeEl).DestType.CustomData as TPasClassScope;
-      if ClassScope.DefaultProperty=nil then
+      if ClassScope.DefaultProperty<>nil then
+        ComputeIndexProperty(ClassScope.DefaultProperty)
+      else
         RaiseInternalError(20161010174916);
         RaiseInternalError(20161010174916);
-      ComputeIndexProperty(ClassScope.DefaultProperty);
       end
       end
     else if TypeEl.ClassType=TPasArrayType then
     else if TypeEl.ClassType=TPasArrayType then
       begin
       begin
@@ -6133,6 +6166,18 @@ begin
     RaiseNotYetImplemented(20160928174212,Params,GetResolverResultDesc(ResolvedEl));
     RaiseNotYetImplemented(20160928174212,Params,GetResolverResultDesc(ResolvedEl));
 end;
 end;
 
 
+procedure TPasResolver.ComputeArrayParams_Class(Params: TParamsExpr;
+  var ResolvedEl: TPasResolverResult; ClassScope: TPasClassScope;
+  Flags: TPasResolverComputeFlags; StartEl: TPasElement);
+begin
+  RaiseInternalError(20161010174916);
+  if Params=nil then ;
+  if ClassScope=nil then ;
+  if Flags=[] then ;
+  if StartEl=nil then ;
+  SetResolverIdentifier(ResolvedEl,btNone,nil,nil,[]);
+end;
+
 procedure TPasResolver.ComputeFuncParams(Params: TParamsExpr; out
 procedure TPasResolver.ComputeFuncParams(Params: TParamsExpr; out
   ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
   ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
   StartEl: TPasElement);
   StartEl: TPasElement);
@@ -10550,6 +10595,22 @@ begin
        or (El.ClassType=TPasClassOperator));
        or (El.ClassType=TPasClassOperator));
 end;
 end;
 
 
+function TPasResolver.IsExternalClassName(aClass: TPasClassType;
+  const ExtName: string): boolean;
+var
+  AncestorScope: TPasClassScope;
+begin
+  Result:=false;
+  if aClass=nil then exit;
+  while (aClass<>nil) and aClass.IsExternal do
+    begin
+    if aClass.ExternalName=ExtName then exit(true);
+    AncestorScope:=(aClass.CustomData as TPasClassScope).AncestorScope;
+    if AncestorScope=nil then exit;
+    aClass:=AncestorScope.Element as TPasClassType;
+  end;
+end;
+
 function TPasResolver.IsProcedureType(const ResolvedEl: TPasResolverResult
 function TPasResolver.IsProcedureType(const ResolvedEl: TPasResolverResult
   ): boolean;
   ): boolean;
 begin
 begin