|
@@ -563,6 +563,7 @@ type
|
|
|
bfInsertArray,
|
|
|
bfDeleteArray,
|
|
|
bfTypeInfo,
|
|
|
+ bfGetTypeKind,
|
|
|
bfAssert,
|
|
|
bfNew,
|
|
|
bfDispose,
|
|
@@ -600,6 +601,7 @@ const
|
|
|
'Insert',
|
|
|
'Delete',
|
|
|
'TypeInfo',
|
|
|
+ 'GetTypeKind',
|
|
|
'Assert',
|
|
|
'New',
|
|
|
'Dispose',
|
|
@@ -1423,10 +1425,23 @@ type
|
|
|
//ToDo: proStaticArrayConcat, // concat works with static arrays, returning a dynamic array
|
|
|
proProcTypeWithoutIsNested, // proc types can use nested procs without 'is nested'
|
|
|
proMethodAddrAsPointer, // can assign @method to a pointer
|
|
|
- proSafecallAllowsDefault // allow assigning a default calling convetnion to a SafeCall proc
|
|
|
+ proSafecallAllowsDefault // allow assigning a default calling convention to a SafeCall proc
|
|
|
);
|
|
|
TPasResolverOptions = set of TPasResolverOption;
|
|
|
|
|
|
+ { TPasResolverHub }
|
|
|
+
|
|
|
+ TPasResolverHub = class
|
|
|
+ private
|
|
|
+ FOwner: TObject;
|
|
|
+ public
|
|
|
+ FinishedInterfaceCount: integer;
|
|
|
+ constructor Create(TheOwner: TObject); virtual;
|
|
|
+ procedure Reset; virtual;
|
|
|
+ property Owner: TObject read FOwner;
|
|
|
+ end;
|
|
|
+ TPasResolverHubClass = class of TPasResolverHub;
|
|
|
+
|
|
|
TPasResolverStep = (
|
|
|
prsInit,
|
|
|
prsParsing,
|
|
@@ -1480,6 +1495,8 @@ type
|
|
|
FDefaultScope: TPasDefaultScope;
|
|
|
FDynArrayMaxIndex: TMaxPrecInt;
|
|
|
FDynArrayMinIndex: TMaxPrecInt;
|
|
|
+ FFinishedInterfaceIndex: integer;
|
|
|
+ FHub: TPasResolverHub;
|
|
|
FLastCreatedData: array[TResolveDataListKind] of TResolveData;
|
|
|
FLastElement: TPasElement;
|
|
|
FLastMsg: string;
|
|
@@ -1757,6 +1774,8 @@ type
|
|
|
function FindUsedUnitname(const aName: string; aMod: TPasModule): TPasModule;
|
|
|
procedure FinishAssertCall(Proc: TResElDataBuiltInProc;
|
|
|
Params: TParamsExpr); virtual;
|
|
|
+ function FindSystemIdentifier(const aUnitName, aName: string;
|
|
|
+ ErrorEl: TPasElement): TPasElement; virtual;
|
|
|
function FindSystemClassType(const aUnitName, aClassName: string;
|
|
|
ErrorEl: TPasElement): TPasClassType; virtual;
|
|
|
function FindSystemClassTypeAndConstructor(const aUnitName, aClassName: string;
|
|
@@ -1767,6 +1786,8 @@ type
|
|
|
function FindTVarRec(ErrorEl: TPasElement): TPasRecordType; virtual;
|
|
|
function GetTVarRec(El: TPasArrayType): TPasRecordType; virtual;
|
|
|
function FindDefaultConstructor(aClass: TPasClassType): TPasConstructor; virtual;
|
|
|
+ function GetTypeInfoParamType(Param: TPasExpr;
|
|
|
+ out ParamResolved: TPasResolverResult; LoType: boolean): TPasType; virtual;
|
|
|
protected
|
|
|
// constant evaluation
|
|
|
fExprEvaluator: TResExprEvaluator;
|
|
@@ -2012,6 +2033,12 @@ type
|
|
|
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
|
|
procedure BI_TypeInfo_OnGetCallResult(Proc: TResElDataBuiltInProc;
|
|
|
Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
|
|
|
+ function BI_GetTypeKind_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
|
|
|
+ Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
|
|
+ procedure BI_GetTypeKind_OnGetCallResult(Proc: TResElDataBuiltInProc;
|
|
|
+ Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
|
|
|
+ procedure BI_GetTypeKind_OnEval(Proc: TResElDataBuiltInProc;
|
|
|
+ Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue); virtual;
|
|
|
function BI_Assert_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
|
|
|
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
|
|
procedure BI_Assert_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
|
|
@@ -2197,8 +2224,7 @@ type
|
|
|
procedure CheckUseAsType(aType: TPasElement; id: TMaxPrecInt;
|
|
|
ErrorEl: TPasElement);
|
|
|
function CheckCallProcCompatibility(ProcType: TPasProcedureType;
|
|
|
- Params: TParamsExpr; RaiseOnError: boolean;
|
|
|
- SetReferenceFlags: boolean = false): integer;
|
|
|
+ Params: TParamsExpr; RaiseOnError: boolean; SetReferenceFlags: boolean = false): integer;
|
|
|
function CheckCallPropertyCompatibility(PropEl: TPasProperty;
|
|
|
Params: TParamsExpr; RaiseOnError: boolean): integer;
|
|
|
function CheckCallArrayCompatibility(ArrayEl: TPasArrayType;
|
|
@@ -2256,6 +2282,7 @@ type
|
|
|
PosEl: TPasElement; RaiseIfConst: boolean = true): boolean;
|
|
|
function ResolvedElIsClassOrRecordInstance(const ResolvedEl: TPasResolverResult): boolean;
|
|
|
// utility functions
|
|
|
+ function GetResolver(El: TPasElement): TPasResolver;
|
|
|
function ElHasModeSwitch(El: TPasElement; ms: TModeSwitch): boolean;
|
|
|
function GetElModeSwitches(El: TPasElement): TModeSwitches;
|
|
|
function ElHasBoolSwitch(El: TPasElement; bs: TBoolSwitch): boolean;
|
|
@@ -2363,10 +2390,12 @@ type
|
|
|
function FindLocalBuiltInSymbol(El: TPasElement): TPasElement; virtual;
|
|
|
function GetFirstSection(WithUnitImpl: boolean): TPasSection;
|
|
|
function GetLastSection: TPasSection;
|
|
|
+ function GetParentSection(El: TPasElement): TPasSection;
|
|
|
function FindUsedUnitInSection(aMod: TPasModule; Section: TPasSection): TPasUsesUnit;
|
|
|
function GetShiftAndMaskForLoHiFunc(BaseType: TResolverBaseType;
|
|
|
isLoFunc: Boolean; out Mask: LongWord): Integer;
|
|
|
public
|
|
|
+ property Hub: TPasResolverHub read FHub write FHub;
|
|
|
// options
|
|
|
property Options: TPasResolverOptions read FOptions write FOptions;
|
|
|
property AnonymousElTypePostfix: String read FAnonymousElTypePostfix
|
|
@@ -2381,15 +2410,16 @@ type
|
|
|
property ExprEvaluator: TResExprEvaluator read fExprEvaluator;
|
|
|
property DynArrayMinIndex: TMaxPrecInt read FDynArrayMinIndex write FDynArrayMinIndex;
|
|
|
property DynArrayMaxIndex: TMaxPrecInt read FDynArrayMaxIndex write FDynArrayMaxIndex;
|
|
|
+ property StoreSrcColumns: boolean read FStoreSrcColumns write FStoreSrcColumns; {
|
|
|
+ If true Line and Column is mangled together in TPasElement.SourceLineNumber.
|
|
|
+ Use method UnmangleSourceLineNumber to extract. }
|
|
|
// parsed values
|
|
|
property DefaultNameSpace: String read FDefaultNameSpace;
|
|
|
property RootElement: TPasModule read FRootElement write SetRootElement;
|
|
|
property Step: TPasResolverStep read FStep;
|
|
|
property ActiveHelpers: TPRHelperEntryArray read FActiveHelpers;
|
|
|
+ property FinishedInterfaceIndex: integer read FFinishedInterfaceIndex;
|
|
|
// scopes
|
|
|
- property StoreSrcColumns: boolean read FStoreSrcColumns write FStoreSrcColumns; {
|
|
|
- If true Line and Column is mangled together in TPasElement.SourceLineNumber.
|
|
|
- Use method UnmangleSourceLineNumber to extract. }
|
|
|
property Scopes[Index: integer]: TPasScope read GetScopes;
|
|
|
property ScopeCount: integer read FScopeCount;
|
|
|
property TopScope: TPasScope read FTopScope;
|
|
@@ -3063,6 +3093,18 @@ begin
|
|
|
str(a,Result);
|
|
|
end;
|
|
|
|
|
|
+{ TPasResolverHub }
|
|
|
+
|
|
|
+constructor TPasResolverHub.Create(TheOwner: TObject);
|
|
|
+begin
|
|
|
+ FOwner:=TheOwner;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TPasResolverHub.Reset;
|
|
|
+begin
|
|
|
+ FinishedInterfaceCount:=0;
|
|
|
+end;
|
|
|
+
|
|
|
{ TPRSpecializedItem }
|
|
|
|
|
|
destructor TPRSpecializedItem.Destroy;
|
|
@@ -5823,6 +5865,8 @@ begin
|
|
|
if not IsUnitIntfFinished(Section.GetModule) then
|
|
|
RaiseInternalError(20171214004323,'TPasResolver.FinishInterfaceSection "'+RootElement.Name+'" "'+Section.GetModule.Name+'" IsUnitIntfFinished=false');
|
|
|
{$ENDIF}
|
|
|
+ inc(Hub.FinishedInterfaceCount);
|
|
|
+ FFinishedInterfaceIndex:=Hub.FinishedInterfaceCount;
|
|
|
NotifyPendingUsedInterfaces;
|
|
|
if Section=nil then ;
|
|
|
end;
|
|
@@ -6562,6 +6606,9 @@ begin
|
|
|
|
|
|
if ResolvedEl.LoTypeEl is TPasGenericTemplateType then
|
|
|
begin
|
|
|
+ if ResolvedEl.LoTypeEl=El then
|
|
|
+ RaiseMsg(20200820185313,nTypeCycleFound,sTypeCycleFound,[],
|
|
|
+ GetGenericConstraintErrorEl(ConEl,El));
|
|
|
// ok
|
|
|
if length(El.Constraints)>1 then
|
|
|
RaiseXIsNotAValidConstraint(20190831213645,ResolvedEl.HiTypeEl.Name);
|
|
@@ -10828,6 +10875,11 @@ begin
|
|
|
[GetElementTypeName(FoundEl)+' '+FoundEl.Name],NameExpr);
|
|
|
CheckTemplParams(GenTemplates,TemplParams);
|
|
|
FoundEl:=GetSpecializedEl(NameExpr,FoundEl,TemplParams);
|
|
|
+ if FoundEl is TPasProcedure then
|
|
|
+ begin
|
|
|
+ // check if params fit the implicit specialized function
|
|
|
+ CheckCallProcCompatibility(TPasProcedure(FoundEl).ProcType,Params,true);
|
|
|
+ end;
|
|
|
end
|
|
|
else if (GenTemplates<>nil) and (GenTemplates.Count>0) then
|
|
|
begin
|
|
@@ -10839,12 +10891,12 @@ begin
|
|
|
try
|
|
|
CheckTemplParams(GenTemplates,InferenceParams);
|
|
|
FoundEl:=GetSpecializedEl(NameExpr,FoundEl,InferenceParams);
|
|
|
+ // check if params fit the implicit specialized function
|
|
|
+ CheckCallProcCompatibility(TPasProcedure(FoundEl).ProcType,Params,true);
|
|
|
finally
|
|
|
ReleaseElementList(InferenceParams{$IFDEF CheckPasTreeRefCount},RefIdInferenceParamsExpr{$ENDIF});
|
|
|
FreeAndNil(InferenceParams);
|
|
|
end;
|
|
|
- // check if params fit the implicit specialized function
|
|
|
- CheckCallProcCompatibility(TPasProcedure(FoundEl).ProcType,Params,true);
|
|
|
end
|
|
|
else
|
|
|
// GenericType() -> missing type params
|
|
@@ -11780,6 +11832,8 @@ var
|
|
|
C: TClass;
|
|
|
ModScope: TPasModuleScope;
|
|
|
begin
|
|
|
+ if Hub=nil then
|
|
|
+ RaiseNotYetImplemented(20200815182122,El);
|
|
|
if TopScope<>DefaultScope then
|
|
|
RaiseInvalidScopeForElement(20160922163504,El);
|
|
|
ModScope:=TPasModuleScope(PushScope(El,FScopeClass_Module));
|
|
@@ -14848,13 +14902,12 @@ begin
|
|
|
CreateReference(aConstructor,Params,rraRead);
|
|
|
end;
|
|
|
|
|
|
-function TPasResolver.FindSystemClassType(const aUnitName, aClassName: string;
|
|
|
- ErrorEl: TPasElement): TPasClassType;
|
|
|
+function TPasResolver.FindSystemIdentifier(const aUnitName, aName: string;
|
|
|
+ ErrorEl: TPasElement): TPasElement;
|
|
|
var
|
|
|
aMod, UtilsMod: TPasModule;
|
|
|
SectionScope: TPasSectionScope;
|
|
|
Identifier: TPasIdentifier;
|
|
|
- El: TPasElement;
|
|
|
begin
|
|
|
Result:=nil;
|
|
|
|
|
@@ -14870,17 +14923,27 @@ begin
|
|
|
// find class in interface
|
|
|
if UtilsMod.InterfaceSection=nil then
|
|
|
if ErrorEl<>nil then
|
|
|
- RaiseIdentifierNotFound(20200523224831,aUnitName+'.'+aClassName,ErrorEl)
|
|
|
+ RaiseIdentifierNotFound(20200523224831,aUnitName+'.'+aName,ErrorEl)
|
|
|
else
|
|
|
exit;
|
|
|
SectionScope:=NoNil(UtilsMod.InterfaceSection.CustomData) as TPasSectionScope;
|
|
|
- Identifier:=SectionScope.FindLocalIdentifier(aClassName);
|
|
|
+ Identifier:=SectionScope.FindLocalIdentifier(aName);
|
|
|
if Identifier=nil then
|
|
|
if ErrorEl<>nil then
|
|
|
- RaiseIdentifierNotFound(20200523224841,aUnitName+'.'+aClassName,ErrorEl)
|
|
|
+ RaiseIdentifierNotFound(20200523224841,aUnitName+'.'+aName,ErrorEl)
|
|
|
else
|
|
|
exit;
|
|
|
- El:=Identifier.Element;
|
|
|
+ Result:=Identifier.Element;
|
|
|
+end;
|
|
|
+
|
|
|
+function TPasResolver.FindSystemClassType(const aUnitName, aClassName: string;
|
|
|
+ ErrorEl: TPasElement): TPasClassType;
|
|
|
+var
|
|
|
+ El: TPasElement;
|
|
|
+begin
|
|
|
+ Result:=nil;
|
|
|
+
|
|
|
+ El:=FindSystemIdentifier(aUnitName,aClassName,ErrorEl);
|
|
|
if not (El is TPasClassType) then
|
|
|
if ErrorEl<>nil then
|
|
|
RaiseXExpectedButYFound(20180119172517,'class '+aClassName,GetElementTypeName(El),ErrorEl)
|
|
@@ -15086,6 +15149,37 @@ begin
|
|
|
until false;
|
|
|
end;
|
|
|
|
|
|
+function TPasResolver.GetTypeInfoParamType(Param: TPasExpr; out
|
|
|
+ ParamResolved: TPasResolverResult; LoType: boolean): TPasType;
|
|
|
+var
|
|
|
+ Decl: TPasElement;
|
|
|
+begin
|
|
|
+ Result:=nil;
|
|
|
+ // check type or var
|
|
|
+ ComputeElement(Param,ParamResolved,[rcNoImplicitProc]);
|
|
|
+ Decl:=ParamResolved.IdentEl;
|
|
|
+ if Decl=nil then exit;
|
|
|
+ if Decl is TPasType then
|
|
|
+ Result:=TPasType(Decl)
|
|
|
+ else if Decl is TPasVariable then
|
|
|
+ Result:=TPasVariable(Decl).VarType
|
|
|
+ else if Decl.ClassType=TPasArgument then
|
|
|
+ Result:=TPasArgument(Decl).ArgType
|
|
|
+ else if Decl.ClassType=TPasResultElement then
|
|
|
+ Result:=TPasResultElement(Decl).ResultType
|
|
|
+ else if (Decl is TPasProcedure)
|
|
|
+ and (TPasProcedure(Decl).ProcType is TPasFunctionType) then
|
|
|
+ Result:=TPasFunctionType(TPasProcedure(Decl).ProcType).ResultEl.ResultType;
|
|
|
+ {$IFDEF VerbosePasResolver}
|
|
|
+ {AllowWriteln}
|
|
|
+ if Result=nil then
|
|
|
+ writeln('TPasResolver.GetTypeInfoParamType Decl=',GetObjName(Decl),' ParamResolved=',GetResolverResultDbg(ParamResolved));
|
|
|
+ {AllowWriteln-}
|
|
|
+ {$ENDIF}
|
|
|
+ if LoType then
|
|
|
+ Result:=ResolveAliasType(Result);
|
|
|
+end;
|
|
|
+
|
|
|
procedure TPasResolver.OnExprEvalLog(Sender: TResExprEvaluator;
|
|
|
const id: TMaxPrecInt; MsgType: TMessageType; MsgNumber: integer;
|
|
|
const Fmt: String; Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
|
|
@@ -19932,47 +20026,18 @@ function TPasResolver.BI_TypeInfo_OnGetCallCompatibility(
|
|
|
var
|
|
|
Params: TParamsExpr;
|
|
|
Param: TPasExpr;
|
|
|
- Decl: TPasElement;
|
|
|
- ParamResolved: TPasResolverResult;
|
|
|
aType: TPasType;
|
|
|
+ ParamResolved: TPasResolverResult;
|
|
|
begin
|
|
|
Result:=cIncompatible;
|
|
|
if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
|
|
|
exit;
|
|
|
Params:=TParamsExpr(Expr);
|
|
|
|
|
|
- // check type or var
|
|
|
Param:=Params.Params[0];
|
|
|
- ComputeElement(Param,ParamResolved,[rcNoImplicitProc]);
|
|
|
- Decl:=ParamResolved.IdentEl;
|
|
|
- aType:=nil;
|
|
|
- if (Decl<>nil) then
|
|
|
- begin
|
|
|
- if Decl is TPasType then
|
|
|
- aType:=TPasType(Decl)
|
|
|
- else if Decl is TPasVariable then
|
|
|
- aType:=TPasVariable(Decl).VarType
|
|
|
- else if Decl.ClassType=TPasArgument then
|
|
|
- aType:=TPasArgument(Decl).ArgType
|
|
|
- else if Decl.ClassType=TPasResultElement then
|
|
|
- aType:=TPasResultElement(Decl).ResultType
|
|
|
- else if (Decl is TPasProcedure)
|
|
|
- and (TPasProcedure(Decl).ProcType is TPasFunctionType) then
|
|
|
- aType:=TPasFunctionType(TPasProcedure(Decl).ProcType).ResultEl.ResultType;
|
|
|
- {$IFDEF VerbosePasResolver}
|
|
|
- {AllowWriteln}
|
|
|
- if aType=nil then
|
|
|
- writeln('TPasResolver.BI_TypeInfo_OnGetCallCompatibility Decl=',GetObjName(Decl));
|
|
|
- {AllowWriteln-}
|
|
|
- {$ENDIF}
|
|
|
- end;
|
|
|
+ aType:=GetTypeInfoParamType(Param,ParamResolved,true);
|
|
|
if aType=nil then
|
|
|
- begin
|
|
|
- {$IFDEF VerbosePasResolver}
|
|
|
- writeln('TPasResolver.BI_TypeInfo_OnGetCallCompatibility ',GetResolverResultDbg(ParamResolved));
|
|
|
- {$ENDIF}
|
|
|
RaiseMsg(20170411100259,nTypeIdentifierExpected,sTypeIdentifierExpected,[],Param);
|
|
|
- end;
|
|
|
aType:=ResolveAliasType(aType);
|
|
|
if not HasTypeInfo(aType) then
|
|
|
RaiseMsg(20170413200118,nSymbolCannotBePublished,sSymbolCannotBePublished,[],Param);
|
|
@@ -19989,6 +20054,138 @@ begin
|
|
|
FBaseTypes[btPointer],FBaseTypes[btPointer],[rrfReadable]);
|
|
|
end;
|
|
|
|
|
|
+function TPasResolver.BI_GetTypeKind_OnGetCallCompatibility(
|
|
|
+ Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
|
|
|
+var
|
|
|
+ Params: TParamsExpr;
|
|
|
+ Param: TPasExpr;
|
|
|
+ aType: TPasType;
|
|
|
+ ParamResolved: TPasResolverResult;
|
|
|
+begin
|
|
|
+ Result:=cIncompatible;
|
|
|
+ if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
|
|
|
+ exit;
|
|
|
+ Params:=TParamsExpr(Expr);
|
|
|
+ Param:=Params.Params[0];
|
|
|
+ aType:=GetTypeInfoParamType(Param,ParamResolved,true);
|
|
|
+ if aType=nil then
|
|
|
+ RaiseMsg(20200826205441,nTypeIdentifierExpected,sTypeIdentifierExpected,[],Param);
|
|
|
+
|
|
|
+ Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TPasResolver.BI_GetTypeKind_OnGetCallResult(
|
|
|
+ Proc: TResElDataBuiltInProc; Params: TParamsExpr; out
|
|
|
+ ResolvedEl: TPasResolverResult);
|
|
|
+var
|
|
|
+ El: TPasElement;
|
|
|
+ EnumType: TPasEnumType;
|
|
|
+begin
|
|
|
+ El:=FindSystemIdentifier('system','ttypekind',Params);
|
|
|
+ if not (El is TPasEnumType) then
|
|
|
+ RaiseXExpectedButYFound(20200826211458,'enum type System.TTypeKind',GetElementTypeName(El),Params);
|
|
|
+ EnumType:=TPasEnumType(El);
|
|
|
+ SetResolverTypeExpr(ResolvedEl,btContext,EnumType,EnumType,[rrfReadable]);
|
|
|
+
|
|
|
+ if Proc=nil then ;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TPasResolver.BI_GetTypeKind_OnEval(Proc: TResElDataBuiltInProc;
|
|
|
+ Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue);
|
|
|
+var
|
|
|
+ aType: TPasType;
|
|
|
+ El: TPasElement;
|
|
|
+ TypeKindType: TPasEnumType;
|
|
|
+ C: TClass;
|
|
|
+ aClass: TPasClassType;
|
|
|
+ bt: TResolverBaseType;
|
|
|
+ Value: TPasEnumValue;
|
|
|
+ aName: String;
|
|
|
+ i: Integer;
|
|
|
+ ParamResolved: TPasResolverResult;
|
|
|
+begin
|
|
|
+ Evaluated:=nil;
|
|
|
+
|
|
|
+ aType:=GetTypeInfoParamType(Params.Params[0],ParamResolved,true);
|
|
|
+ C:=aType.ClassType;
|
|
|
+ aName:='tkUnknown';
|
|
|
+ if C=TPasEnumType then
|
|
|
+ aName:='tkEnumeration'
|
|
|
+ else if C=TPasSetType then
|
|
|
+ aName:='tkSet'
|
|
|
+ else if C=TPasRecordType then
|
|
|
+ aName:='tkRecord'
|
|
|
+ else if C=TPasClassType then
|
|
|
+ begin
|
|
|
+ aClass:=TPasClassType(aType);
|
|
|
+ case aClass.ObjKind of
|
|
|
+ okObject: aName:='tkObject';
|
|
|
+ okInterface:
|
|
|
+ case aClass.InterfaceType of
|
|
|
+ citCom: aName:='tkInterface';
|
|
|
+ else aName:='tkInterfaceRaw';
|
|
|
+ end;
|
|
|
+ okClassHelper, okRecordHelper, okTypeHelper: aName:='tkHelper';
|
|
|
+ else
|
|
|
+ aName:='tkClass';
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else if C=TPasClassOfType then
|
|
|
+ aName:='tkClassRef'
|
|
|
+ else if C.InheritsFrom(TPasProcedure) then
|
|
|
+ aName:='tkMethod'
|
|
|
+ else if C.InheritsFrom(TPasProcedureType) then
|
|
|
+ aName:='tkProcVar'
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ bt:=ParamResolved.BaseType;
|
|
|
+ case bt of
|
|
|
+ btChar: if BaseTypeChar=btAnsiChar then aName:='tkChar' else aName:='tkWChar';
|
|
|
+ {$ifdef FPC_HAS_CPSTRING}
|
|
|
+ btAnsiChar: aName:='tkChar';
|
|
|
+ {$endif}
|
|
|
+ btWideChar: aName:='tkWideChar';
|
|
|
+ btString: if BaseTypeString=btAnsiString then aName:='tkAString' else aName:='tkUString';
|
|
|
+ {$ifdef FPC_HAS_CPSTRING}
|
|
|
+ btAnsiString,
|
|
|
+ btShortString,
|
|
|
+ btRawByteString: aName:='tkAString';
|
|
|
+ {$endif}
|
|
|
+ btWideString: aName:='tkWString';
|
|
|
+ btUnicodeString: aName:='tkUString';
|
|
|
+ btPointer: aName:='tkPointer';
|
|
|
+ {$ifdef HasInt64}
|
|
|
+ btQWord,
|
|
|
+ btInt64,
|
|
|
+ btComp: aName:='tkInt64';
|
|
|
+ {$endif}
|
|
|
+ else
|
|
|
+ if bt in btAllBooleans then
|
|
|
+ aName:='tkBool'
|
|
|
+ else if bt in btAllInteger then
|
|
|
+ aName:='tkInteger'
|
|
|
+ else if bt in btAllFloats then
|
|
|
+ aName:='tkFloat';
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ El:=FindSystemIdentifier('system','ttypekind',Params);
|
|
|
+ TypeKindType:=El as TPasEnumType;
|
|
|
+
|
|
|
+ for i:=0 to TypeKindType.Values.Count-1 do
|
|
|
+ begin
|
|
|
+ Value:=TPasEnumValue(TypeKindType.Values[i]);
|
|
|
+ if SameText(aName,Value.Name) then
|
|
|
+ begin
|
|
|
+ Evaluated:=TResEvalEnum.CreateValue(i,Value);
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if Proc=nil then ;
|
|
|
+ if Flags=[] then ;
|
|
|
+end;
|
|
|
+
|
|
|
function TPasResolver.BI_Assert_OnGetCallCompatibility(
|
|
|
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
|
|
|
// check params of built-in procedure 'Assert'
|
|
@@ -21642,6 +21839,10 @@ begin
|
|
|
AddBuiltInProc('TypeInfo','function TypeInfo(type or var identifier): Pointer',
|
|
|
@BI_TypeInfo_OnGetCallCompatibility,@BI_TypeInfo_OnGetCallResult,
|
|
|
nil,nil,bfTypeInfo);
|
|
|
+ if bfGetTypeKind in TheBaseProcs then
|
|
|
+ AddBuiltInProc('GetTypeKind','function GetTypeKind(type or var identifier): System.TTypeKind',
|
|
|
+ @BI_GetTypeKind_OnGetCallCompatibility,@BI_GetTypeKind_OnGetCallResult,
|
|
|
+ @BI_GetTypeKind_OnEval,nil,bfGetTypeKind);
|
|
|
if bfAssert in TheBaseProcs then
|
|
|
AddBuiltInProc('Assert','procedure Assert(bool[,string])',
|
|
|
@BI_Assert_OnGetCallCompatibility,nil,nil,
|
|
@@ -23027,11 +23228,11 @@ begin
|
|
|
|
|
|
Value:=Params.Value;
|
|
|
if Value is TBinaryExpr then
|
|
|
- Value:=TBinaryExpr(Value).right;
|
|
|
+ Value:=TBinaryExpr(Value).right; // Note: parser guarantees that this is the rightmost
|
|
|
|
|
|
// check args
|
|
|
ParamCnt:=length(Params.Params);
|
|
|
- ArgResolved.BaseType:=btNone;;
|
|
|
+ ArgResolved.BaseType:=btNone;
|
|
|
i:=0;
|
|
|
while i<ParamCnt do
|
|
|
begin
|
|
@@ -24934,6 +25135,20 @@ begin
|
|
|
exit(true);
|
|
|
end;
|
|
|
|
|
|
+function TPasResolver.GetResolver(El: TPasElement): TPasResolver;
|
|
|
+var
|
|
|
+ Module: TPasModule;
|
|
|
+ Scope: TPasModuleScope;
|
|
|
+begin
|
|
|
+ Result:=nil;
|
|
|
+ if El=nil then exit;
|
|
|
+ Module:=El.GetModule;
|
|
|
+ if Module=nil then exit;
|
|
|
+ Scope:=Module.CustomData as TPasModuleScope;
|
|
|
+ if Scope=nil then exit;
|
|
|
+ Result:=Scope.Owner as TPasResolver;
|
|
|
+end;
|
|
|
+
|
|
|
function TPasResolver.ElHasModeSwitch(El: TPasElement; ms: TModeSwitch
|
|
|
): boolean;
|
|
|
begin
|
|
@@ -29229,6 +29444,16 @@ begin
|
|
|
Result:=Module.InterfaceSection;
|
|
|
end;
|
|
|
|
|
|
+function TPasResolver.GetParentSection(El: TPasElement): TPasSection;
|
|
|
+begin
|
|
|
+ while El<>nil do
|
|
|
+ begin
|
|
|
+ if El is TPasSection then exit(TPasSection(El));
|
|
|
+ El:=El.Parent;
|
|
|
+ end;
|
|
|
+ Result:=nil;
|
|
|
+end;
|
|
|
+
|
|
|
function TPasResolver.FindUsedUnitInSection(aMod: TPasModule;
|
|
|
Section: TPasSection): TPasUsesUnit;
|
|
|
var
|
|
@@ -29288,9 +29513,47 @@ end;
|
|
|
|
|
|
function TPasResolver.CheckClassIsClass(SrcType, DestType: TPasType): integer;
|
|
|
// check if Src is equal or descends from Dest
|
|
|
+// Generics: TBird<T> is both directions a TBird<word>
|
|
|
+// and TBird<TMap<T>> is both directions a TBird<TMap<word>>
|
|
|
+
|
|
|
+ function CheckSpecialized(SrcScope, DestScope: TPasGenericScope): boolean;
|
|
|
+ var
|
|
|
+ SrcParams, DestParams: TPasTypeArray;
|
|
|
+ i: Integer;
|
|
|
+ SrcParam, DestParam: TPasType;
|
|
|
+ SrcParamScope, DestParamScope: TPasGenericScope;
|
|
|
+ begin
|
|
|
+ if SrcScope.SpecializedFromItem.GenericEl<>DestScope.SpecializedFromItem.GenericEl then
|
|
|
+ exit(false);
|
|
|
+ // specialized from same generic -> check params
|
|
|
+ SrcParams:=SrcScope.SpecializedFromItem.Params;
|
|
|
+ DestParams:=DestScope.SpecializedFromItem.Params;
|
|
|
+ for i:=0 to length(SrcParams)-1 do
|
|
|
+ begin
|
|
|
+ SrcParam:=SrcParams[i];
|
|
|
+ DestParam:=DestParams[i];
|
|
|
+ if (SrcParam is TPasGenericTemplateType)
|
|
|
+ or (DestParam is TPasGenericTemplateType)
|
|
|
+ or (SrcParam=DestParam)
|
|
|
+ then
|
|
|
+ // ok
|
|
|
+ else if (SrcParam is TPasGenericType) and (DestParam is TPasGenericType) then
|
|
|
+ begin
|
|
|
+ // e.g. TList<Src<...>> and TList<Dest<...>>
|
|
|
+ SrcParamScope:=SrcParam.CustomData as TPasGenericScope;
|
|
|
+ DestParamScope:=DestParam.CustomData as TPasGenericScope;
|
|
|
+ if not CheckSpecialized(SrcParamScope,DestParamScope) then
|
|
|
+ exit(false);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ exit(false); // specialized with different params -> incompatible
|
|
|
+ end;
|
|
|
+ Result:=true;
|
|
|
+ end;
|
|
|
+
|
|
|
var
|
|
|
- ClassEl: TPasClassType;
|
|
|
- DestScope: TPasClassScope;
|
|
|
+ SrcClassEl: TPasClassType;
|
|
|
+ SrcScope, DestScope: TPasClassScope;
|
|
|
GenericType: TPasGenericType;
|
|
|
begin
|
|
|
{$IFDEF VerbosePasResolver}
|
|
@@ -29300,6 +29563,7 @@ begin
|
|
|
DestType:=ResolveAliasType(DestType);
|
|
|
if DestType.ClassType<>TPasClassType then
|
|
|
exit(cIncompatible);
|
|
|
+ DestScope:=DestType.CustomData as TPasClassScope;
|
|
|
|
|
|
Result:=cExact;
|
|
|
while SrcType<>nil do
|
|
@@ -29328,16 +29592,15 @@ begin
|
|
|
end
|
|
|
else if SrcType.ClassType=TPasClassType then
|
|
|
begin
|
|
|
- ClassEl:=TPasClassType(SrcType);
|
|
|
- if ClassEl.IsForward then
|
|
|
+ SrcClassEl:=TPasClassType(SrcType);
|
|
|
+ if SrcClassEl.IsForward then
|
|
|
// class forward -> skip
|
|
|
- SrcType:=(ClassEl.CustomData as TResolvedReference).Declaration as TPasType
|
|
|
+ SrcType:=(SrcClassEl.CustomData as TResolvedReference).Declaration as TPasType
|
|
|
else
|
|
|
begin
|
|
|
- if (ClassEl.GenericTemplateTypes<>nil) and (ClassEl.GenericTemplateTypes.Count>0) then
|
|
|
+ if (SrcClassEl.GenericTemplateTypes<>nil) and (SrcClassEl.GenericTemplateTypes.Count>0) then
|
|
|
begin
|
|
|
// SrcType is a generic
|
|
|
- DestScope:=DestType.CustomData as TPasClassScope;
|
|
|
if DestScope.SpecializedFromItem<>nil then
|
|
|
begin
|
|
|
// DestType is specialized
|
|
@@ -29349,8 +29612,14 @@ begin
|
|
|
exit; // DestType is a specialized SrcType
|
|
|
end;
|
|
|
end;
|
|
|
+ SrcScope:=SrcClassEl.CustomData as TPasClassScope;
|
|
|
+ if (SrcScope.SpecializedFromItem<>nil)
|
|
|
+ and (DestScope.SpecializedFromItem<>nil)
|
|
|
+ and CheckSpecialized(SrcScope,DestScope) then
|
|
|
+ exit;
|
|
|
+
|
|
|
// class ancestor -> increase distance
|
|
|
- SrcType:=(ClassEl.CustomData as TPasClassScope).DirectAncestor;
|
|
|
+ SrcType:=SrcScope.DirectAncestor;
|
|
|
inc(Result);
|
|
|
end;
|
|
|
end
|