|
@@ -216,14 +216,24 @@ Works:
|
|
- pass as arg doit(procedure begin end)
|
|
- pass as arg doit(procedure begin end)
|
|
- modifiers assembler varargs cdecl
|
|
- modifiers assembler varargs cdecl
|
|
- typecast
|
|
- typecast
|
|
|
|
+ - with
|
|
|
|
+ - self
|
|
- built-in procedure Val(const s: string; var e: enumtype; out Code: integertype);
|
|
- built-in procedure Val(const s: string; var e: enumtype; out Code: integertype);
|
|
|
|
|
|
ToDo:
|
|
ToDo:
|
|
-- anonymous methods:
|
|
|
|
- - with
|
|
|
|
- - self
|
|
|
|
|
|
+- operator overload
|
|
|
|
+ - operator enumerator
|
|
|
|
+ - binaryexpr
|
|
|
|
+- advanced records:
|
|
|
|
+ - $modeswitch AdvancedRecords
|
|
|
|
+ - sub type
|
|
|
|
+ - const
|
|
|
|
+ - var
|
|
|
|
+ - function/procedure/class function/class procedure
|
|
|
|
+ - property, class property
|
|
|
|
+ - RTTI
|
|
|
|
+ - operator overloading
|
|
- Include/Exclude for set of int/char/bool
|
|
- Include/Exclude for set of int/char/bool
|
|
-- set of CharRange
|
|
|
|
- error if property method resolution is not used
|
|
- error if property method resolution is not used
|
|
- $H-hintpos$H+
|
|
- $H-hintpos$H+
|
|
- $pop, $push
|
|
- $pop, $push
|
|
@@ -235,13 +245,12 @@ ToDo:
|
|
- proc: check if forward and impl default values match
|
|
- proc: check if forward and impl default values match
|
|
- call array of proc without ()
|
|
- call array of proc without ()
|
|
- attributes
|
|
- attributes
|
|
-- object
|
|
|
|
- type helpers
|
|
- type helpers
|
|
- record/class helpers
|
|
- record/class helpers
|
|
|
|
+- array of const
|
|
- generics, nested param lists
|
|
- generics, nested param lists
|
|
|
|
+- object
|
|
- futures
|
|
- futures
|
|
-- operator overload
|
|
|
|
- - operator enumerator
|
|
|
|
- TPasFileType
|
|
- TPasFileType
|
|
- labels
|
|
- labels
|
|
- $zerobasedstrings on|off
|
|
- $zerobasedstrings on|off
|
|
@@ -529,6 +538,7 @@ type
|
|
bfWriteStr,
|
|
bfWriteStr,
|
|
bfVal,
|
|
bfVal,
|
|
bfConcatArray,
|
|
bfConcatArray,
|
|
|
|
+ bfConcatString,
|
|
bfCopyArray,
|
|
bfCopyArray,
|
|
bfInsertArray,
|
|
bfInsertArray,
|
|
bfDeleteArray,
|
|
bfDeleteArray,
|
|
@@ -563,6 +573,7 @@ const
|
|
'WriteStr',
|
|
'WriteStr',
|
|
'Val',
|
|
'Val',
|
|
'Concat',
|
|
'Concat',
|
|
|
|
+ 'Concat',
|
|
'Copy',
|
|
'Copy',
|
|
'Insert',
|
|
'Insert',
|
|
'Delete',
|
|
'Delete',
|
|
@@ -838,9 +849,16 @@ type
|
|
destructor Destroy; override;
|
|
destructor Destroy; override;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+ { TPasClassOrRecordScope }
|
|
|
|
+
|
|
|
|
+ TPasClassOrRecordScope = Class(TPasIdentifierScope)
|
|
|
|
+ public
|
|
|
|
+ DefaultProperty: TPasProperty;
|
|
|
|
+ end;
|
|
|
|
+
|
|
{ TPasRecordScope }
|
|
{ TPasRecordScope }
|
|
|
|
|
|
- TPasRecordScope = Class(TPasIdentifierScope)
|
|
|
|
|
|
+ TPasRecordScope = Class(TPasClassOrRecordScope)
|
|
end;
|
|
end;
|
|
|
|
|
|
TPasClassScopeFlag = (
|
|
TPasClassScopeFlag = (
|
|
@@ -863,12 +881,11 @@ type
|
|
|
|
|
|
{ TPasClassScope }
|
|
{ TPasClassScope }
|
|
|
|
|
|
- TPasClassScope = Class(TPasIdentifierScope)
|
|
|
|
|
|
+ TPasClassScope = Class(TPasClassOrRecordScope)
|
|
public
|
|
public
|
|
AncestorScope: TPasClassScope;
|
|
AncestorScope: TPasClassScope;
|
|
CanonicalClassOf: TPasClassOfType;
|
|
CanonicalClassOf: TPasClassOfType;
|
|
DirectAncestor: TPasType; // TPasClassType or TPasAliasType, see GetPasClassAncestor
|
|
DirectAncestor: TPasType; // TPasClassType or TPasAliasType, see GetPasClassAncestor
|
|
- DefaultProperty: TPasProperty;
|
|
|
|
Flags: TPasClassScopeFlags;
|
|
Flags: TPasClassScopeFlags;
|
|
AbstractProcs: TArrayOfPasProcedure;
|
|
AbstractProcs: TArrayOfPasProcedure;
|
|
Interfaces: TFPList; // list corresponds to TPasClassType(Element).Interfaces,
|
|
Interfaces: TFPList; // list corresponds to TPasClassType(Element).Interfaces,
|
|
@@ -894,7 +911,7 @@ type
|
|
DeclarationProc: TPasProcedure; // the corresponding forward declaration
|
|
DeclarationProc: TPasProcedure; // the corresponding forward declaration
|
|
ImplProc: TPasProcedure; // the corresponding proc with Body
|
|
ImplProc: TPasProcedure; // the corresponding proc with Body
|
|
OverriddenProc: TPasProcedure; // if IsOverride then this is the ancestor proc (virtual or override)
|
|
OverriddenProc: TPasProcedure; // if IsOverride then this is the ancestor proc (virtual or override)
|
|
- ClassScope: TPasClassScope;
|
|
|
|
|
|
+ ClassScope: TPasClassOrRecordScope;
|
|
SelfArg: TPasArgument;
|
|
SelfArg: TPasArgument;
|
|
Flags: TPasProcedureScopeFlags;
|
|
Flags: TPasProcedureScopeFlags;
|
|
BoolSwitches: TBoolSwitches; // if Body<>nil then body start, otherwise when FinishProc
|
|
BoolSwitches: TBoolSwitches; // if Body<>nil then body start, otherwise when FinishProc
|
|
@@ -1424,7 +1441,7 @@ type
|
|
procedure FinishWithDo(El: TPasImplWithDo); virtual;
|
|
procedure FinishWithDo(El: TPasImplWithDo); virtual;
|
|
procedure FinishDeclaration(El: TPasElement); virtual;
|
|
procedure FinishDeclaration(El: TPasElement); virtual;
|
|
procedure FinishVariable(El: TPasVariable); virtual;
|
|
procedure FinishVariable(El: TPasVariable); virtual;
|
|
- procedure FinishPropertyOfClass(PropEl: TPasProperty); virtual;
|
|
|
|
|
|
+ procedure FinishProperty(PropEl: TPasProperty); virtual;
|
|
procedure FinishArgument(El: TPasArgument); virtual;
|
|
procedure FinishArgument(El: TPasArgument); virtual;
|
|
procedure FinishAncestors(aClass: TPasClassType); virtual;
|
|
procedure FinishAncestors(aClass: TPasClassType); virtual;
|
|
procedure FinishMethodResolution(El: TPasMethodResolution); virtual;
|
|
procedure FinishMethodResolution(El: TPasMethodResolution); virtual;
|
|
@@ -1449,6 +1466,9 @@ type
|
|
procedure ComputeBinaryExprRes(Bin: TBinaryExpr;
|
|
procedure ComputeBinaryExprRes(Bin: TBinaryExpr;
|
|
out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
|
|
out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
|
|
var LeftResolved, RightResolved: TPasResolverResult); virtual;
|
|
var LeftResolved, RightResolved: TPasResolverResult); virtual;
|
|
|
|
+ function ComputeAddStringRes(
|
|
|
|
+ const LeftResolved, RightResolved: TPasResolverResult; ExprEl: TPasExpr;
|
|
|
|
+ out ResolvedEl: TPasResolverResult): boolean; virtual;
|
|
procedure ComputeArrayParams(Params: TParamsExpr;
|
|
procedure ComputeArrayParams(Params: TParamsExpr;
|
|
out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
|
|
out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
|
|
StartEl: TPasElement);
|
|
StartEl: TPasElement);
|
|
@@ -1602,6 +1622,12 @@ type
|
|
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
|
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
|
procedure BI_ConcatArray_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
|
|
procedure BI_ConcatArray_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
|
|
{%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
|
|
{%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
|
|
|
|
+ function BI_ConcatString_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
|
|
|
|
+ Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
|
|
|
+ procedure BI_ConcatString_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
|
|
|
|
+ {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
|
|
|
|
+ procedure BI_ConcatString_OnEval({%H-}Proc: TResElDataBuiltInProc;
|
|
|
|
+ Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue); virtual;
|
|
function BI_CopyArray_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
|
|
function BI_CopyArray_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
|
|
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
|
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
|
procedure BI_CopyArray_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
|
|
procedure BI_CopyArray_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
|
|
@@ -4298,7 +4324,7 @@ begin
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
// give a hint
|
|
// give a hint
|
|
- if Data^.Proc.Parent is TPasClassType then
|
|
|
|
|
|
+ if Data^.Proc.Parent is TPasMembersType then
|
|
LogMsg(20171118205344,mtHint,nFunctionHidesIdentifier_NonProc,sFunctionHidesIdentifier,
|
|
LogMsg(20171118205344,mtHint,nFunctionHidesIdentifier_NonProc,sFunctionHidesIdentifier,
|
|
[GetElementSourcePosStr(El)],Data^.Proc.ProcType);
|
|
[GetElementSourcePosStr(El)],Data^.Proc.ProcType);
|
|
end;
|
|
end;
|
|
@@ -4397,7 +4423,7 @@ begin
|
|
begin
|
|
begin
|
|
// Delphi/FPC do not give a message when hiding a non virtual method
|
|
// Delphi/FPC do not give a message when hiding a non virtual method
|
|
// -> emit Hint with other message id
|
|
// -> emit Hint with other message id
|
|
- if (Data^.Proc.Parent is TPasClassType) then
|
|
|
|
|
|
+ if (Data^.Proc.Parent is TPasMembersType) then
|
|
begin
|
|
begin
|
|
ProcScope:=Proc.CustomData as TPasProcedureScope;
|
|
ProcScope:=Proc.CustomData as TPasProcedureScope;
|
|
if (ProcScope.ImplProc<>nil) // not abstract, external
|
|
if (ProcScope.ImplProc<>nil) // not abstract, external
|
|
@@ -4920,7 +4946,7 @@ begin
|
|
else if (C=TPasAliasType) or (C=TPasTypeAliasType) then
|
|
else if (C=TPasAliasType) or (C=TPasTypeAliasType) then
|
|
begin
|
|
begin
|
|
aType:=ResolveAliasType(El);
|
|
aType:=ResolveAliasType(El);
|
|
- if (aType is TPasClassType) and (aType.CustomData=nil) then
|
|
|
|
|
|
+ if (aType is TPasMembersType) and (aType.CustomData=nil) then
|
|
exit;
|
|
exit;
|
|
EmitTypeHints(El,TPasAliasType(El).DestType);
|
|
EmitTypeHints(El,TPasAliasType(El).DestType);
|
|
end
|
|
end
|
|
@@ -5423,6 +5449,22 @@ begin
|
|
if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
|
|
if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
|
|
RaiseMsg(20170216151631,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'static'],Proc);
|
|
RaiseMsg(20170216151631,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'static'],Proc);
|
|
end
|
|
end
|
|
|
|
+ else if Proc.Parent is TPasRecordType then
|
|
|
|
+ begin
|
|
|
|
+ if Proc.IsReintroduced then
|
|
|
|
+ RaiseMsg(20181218195735,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'reintroduce'],Proc);
|
|
|
|
+ if Proc.IsVirtual then
|
|
|
|
+ RaiseMsg(20181218195431,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'virtual'],Proc);
|
|
|
|
+ if Proc.IsOverride then
|
|
|
|
+ RaiseMsg(20181218195437,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'override'],Proc);
|
|
|
|
+ if Proc.IsAbstract then
|
|
|
|
+ RaiseMsg(20181218195552,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'abstract'],Proc);
|
|
|
|
+ if Proc.IsForward then
|
|
|
|
+ RaiseMsg(20181218195514,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'forward'],Proc);
|
|
|
|
+ if Proc.IsStatic then
|
|
|
|
+ if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
|
|
|
|
+ RaiseMsg(20181218195519,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'static'],Proc);
|
|
|
|
+ end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
// intf proc, forward proc, proc body, method body, anonymous proc
|
|
// intf proc, forward proc, proc body, method body, anonymous proc
|
|
@@ -5466,7 +5508,7 @@ begin
|
|
if Proc.LibrarySymbolName<>nil then
|
|
if Proc.LibrarySymbolName<>nil then
|
|
ResolveExpr(Proc.LibrarySymbolName,rraRead);
|
|
ResolveExpr(Proc.LibrarySymbolName,rraRead);
|
|
|
|
|
|
- if Proc.Parent is TPasClassType then
|
|
|
|
|
|
+ if Proc.Parent is TPasMembersType then
|
|
begin
|
|
begin
|
|
FinishMethodDeclHeader(Proc);
|
|
FinishMethodDeclHeader(Proc);
|
|
exit;
|
|
exit;
|
|
@@ -5581,7 +5623,7 @@ procedure TPasResolver.FinishMethodDeclHeader(Proc: TPasProcedure);
|
|
|
|
|
|
var
|
|
var
|
|
Abort: boolean;
|
|
Abort: boolean;
|
|
- ClassScope: TPasClassScope;
|
|
|
|
|
|
+ ClassOrRecScope: TPasClassOrRecordScope;
|
|
FindData: TFindOverloadProcData;
|
|
FindData: TFindOverloadProcData;
|
|
OverloadProc: TPasProcedure;
|
|
OverloadProc: TPasProcedure;
|
|
ProcScope: TPasProcedureScope;
|
|
ProcScope: TPasProcedureScope;
|
|
@@ -5591,14 +5633,14 @@ begin
|
|
ProcScope:=TopScope as TPasProcedureScope;
|
|
ProcScope:=TopScope as TPasProcedureScope;
|
|
// ToDo: store the scanner flags *before* it has parsed the token after the proc
|
|
// ToDo: store the scanner flags *before* it has parsed the token after the proc
|
|
StoreScannerFlagsInProc(ProcScope);
|
|
StoreScannerFlagsInProc(ProcScope);
|
|
- ClassScope:=Scopes[ScopeCount-2] as TPasClassScope;
|
|
|
|
- ProcScope.ClassScope:=ClassScope;
|
|
|
|
|
|
+ ClassOrRecScope:=Scopes[ScopeCount-2] as TPasClassOrRecordScope;
|
|
|
|
+ ProcScope.ClassScope:=ClassOrRecScope;
|
|
FindData:=Default(TFindOverloadProcData);
|
|
FindData:=Default(TFindOverloadProcData);
|
|
FindData.Proc:=Proc;
|
|
FindData.Proc:=Proc;
|
|
FindData.Args:=Proc.ProcType.Args;
|
|
FindData.Args:=Proc.ProcType.Args;
|
|
FindData.Kind:=fopkMethod;
|
|
FindData.Kind:=fopkMethod;
|
|
Abort:=false;
|
|
Abort:=false;
|
|
- ClassScope.IterateElements(Proc.Name,ClassScope,@OnFindOverloadProc,@FindData,Abort);
|
|
|
|
|
|
+ ClassOrRecScope.IterateElements(Proc.Name,ClassOrRecScope,@OnFindOverloadProc,@FindData,Abort);
|
|
|
|
|
|
if FindData.Found=nil then
|
|
if FindData.Found=nil then
|
|
begin
|
|
begin
|
|
@@ -5643,24 +5685,25 @@ begin
|
|
if proFixCaseOfOverrides in Options then
|
|
if proFixCaseOfOverrides in Options then
|
|
Proc.Name:=OverloadProc.Name;
|
|
Proc.Name:=OverloadProc.Name;
|
|
// remove abstract
|
|
// remove abstract
|
|
- if OverloadProc.IsAbstract then
|
|
|
|
- for i:=length(ClassScope.AbstractProcs)-1 downto 0 do
|
|
|
|
- if ClassScope.AbstractProcs[i]=OverloadProc then
|
|
|
|
- Delete(ClassScope.AbstractProcs,i,1);
|
|
|
|
|
|
+ if OverloadProc.IsAbstract and (ClassOrRecScope is TPasClassScope) then
|
|
|
|
+ for i:=length(TPasClassScope(ClassOrRecScope).AbstractProcs)-1 downto 0 do
|
|
|
|
+ if TPasClassScope(ClassOrRecScope).AbstractProcs[i]=OverloadProc then
|
|
|
|
+ Delete(TPasClassScope(ClassOrRecScope).AbstractProcs,i,1);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
// add abstract
|
|
// add abstract
|
|
- if Proc.IsAbstract then
|
|
|
|
- Insert(Proc,ClassScope.AbstractProcs,length(ClassScope.AbstractProcs));
|
|
|
|
|
|
+ if Proc.IsAbstract and (ClassOrRecScope is TPasClassScope) then
|
|
|
|
+ Insert(Proc,TPasClassScope(ClassOrRecScope).AbstractProcs,
|
|
|
|
+ length(TPasClassScope(ClassOrRecScope).AbstractProcs));
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TPasResolver.FinishMethodImplHeader(ImplProc: TPasProcedure);
|
|
procedure TPasResolver.FinishMethodImplHeader(ImplProc: TPasProcedure);
|
|
var
|
|
var
|
|
ProcName: String;
|
|
ProcName: String;
|
|
- CurClassType: TPasClassType;
|
|
|
|
|
|
+ ClassRecType: TPasMembersType;
|
|
ImplProcScope, DeclProcScope: TPasProcedureScope;
|
|
ImplProcScope, DeclProcScope: TPasProcedureScope;
|
|
DeclProc: TPasProcedure;
|
|
DeclProc: TPasProcedure;
|
|
- CurClassScope: TPasClassScope;
|
|
|
|
|
|
+ CurClassRecScope: TPasClassOrRecordScope;
|
|
SelfArg: TPasArgument;
|
|
SelfArg: TPasArgument;
|
|
p: Integer;
|
|
p: Integer;
|
|
begin
|
|
begin
|
|
@@ -5685,14 +5728,14 @@ begin
|
|
if not IsValidIdent(ProcName) then
|
|
if not IsValidIdent(ProcName) then
|
|
RaiseNotYetImplemented(20160922163421,ImplProc.ProcType);
|
|
RaiseNotYetImplemented(20160922163421,ImplProc.ProcType);
|
|
|
|
|
|
- // search proc in class
|
|
|
|
|
|
+ // search proc in class/record
|
|
ImplProcScope:=ImplProc.CustomData as TPasProcedureScope;
|
|
ImplProcScope:=ImplProc.CustomData as TPasProcedureScope;
|
|
- CurClassScope:=ImplProcScope.ClassScope;
|
|
|
|
- if CurClassScope=nil then
|
|
|
|
|
|
+ CurClassRecScope:=ImplProcScope.ClassScope;
|
|
|
|
+ if CurClassRecScope=nil then
|
|
RaiseInternalError(20161013172346);
|
|
RaiseInternalError(20161013172346);
|
|
- CurClassType:=NoNil(CurClassScope.Element) as TPasClassType;
|
|
|
|
|
|
+ ClassRecType:=NoNil(CurClassRecScope.Element) as TPasMembersType;
|
|
|
|
|
|
- DeclProc:=FindProcOverload(ProcName,ImplProc,CurClassScope);
|
|
|
|
|
|
+ DeclProc:=FindProcOverload(ProcName,ImplProc,CurClassRecScope);
|
|
if DeclProc=nil then
|
|
if DeclProc=nil then
|
|
RaiseIdentifierNotFound(20170216151720,ImplProc.Name,ImplProc.ProcType);
|
|
RaiseIdentifierNotFound(20170216151720,ImplProc.Name,ImplProc.ProcType);
|
|
DeclProcScope:=DeclProc.CustomData as TPasProcedureScope;
|
|
DeclProcScope:=DeclProc.CustomData as TPasProcedureScope;
|
|
@@ -5721,14 +5764,14 @@ begin
|
|
or (DeclProc.ClassType=TPasClassProcedure)
|
|
or (DeclProc.ClassType=TPasClassProcedure)
|
|
or (DeclProc.ClassType=TPasClassFunction) then
|
|
or (DeclProc.ClassType=TPasClassFunction) then
|
|
begin
|
|
begin
|
|
- if not DeclProc.IsStatic then
|
|
|
|
|
|
+ if (not DeclProc.IsStatic) and (CurClassRecScope is TPasClassScope) then
|
|
begin
|
|
begin
|
|
// 'Self' in a class proc is the hidden classtype argument
|
|
// 'Self' in a class proc is the hidden classtype argument
|
|
SelfArg:=TPasArgument.Create('Self',DeclProc);
|
|
SelfArg:=TPasArgument.Create('Self',DeclProc);
|
|
ImplProcScope.SelfArg:=SelfArg;
|
|
ImplProcScope.SelfArg:=SelfArg;
|
|
{$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
|
|
{$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
|
|
SelfArg.Access:=argConst;
|
|
SelfArg.Access:=argConst;
|
|
- SelfArg.ArgType:=CurClassScope.CanonicalClassOf;
|
|
|
|
|
|
+ SelfArg.ArgType:=TPasClassScope(CurClassRecScope).CanonicalClassOf;
|
|
SelfArg.ArgType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
|
|
SelfArg.ArgType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
|
|
AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
|
|
AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
|
|
end;
|
|
end;
|
|
@@ -5740,8 +5783,8 @@ begin
|
|
ImplProcScope.SelfArg:=SelfArg;
|
|
ImplProcScope.SelfArg:=SelfArg;
|
|
{$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
|
|
{$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
|
|
SelfArg.Access:=argConst;
|
|
SelfArg.Access:=argConst;
|
|
- SelfArg.ArgType:=CurClassType;
|
|
|
|
- CurClassType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
|
|
|
|
|
|
+ SelfArg.ArgType:=ClassRecType;
|
|
|
|
+ ClassRecType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
|
|
AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
|
|
AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -5783,7 +5826,7 @@ begin
|
|
if (C=TPasVariable) or (C=TPasConst) then
|
|
if (C=TPasVariable) or (C=TPasConst) then
|
|
FinishVariable(TPasVariable(El))
|
|
FinishVariable(TPasVariable(El))
|
|
else if C=TPasProperty then
|
|
else if C=TPasProperty then
|
|
- FinishPropertyOfClass(TPasProperty(El))
|
|
|
|
|
|
+ FinishProperty(TPasProperty(El))
|
|
else if C=TPasArgument then
|
|
else if C=TPasArgument then
|
|
FinishArgument(TPasArgument(El))
|
|
FinishArgument(TPasArgument(El))
|
|
else if C=TPasMethodResolution then
|
|
else if C=TPasMethodResolution then
|
|
@@ -5812,6 +5855,9 @@ begin
|
|
ResolveExpr(El.Expr,rraRead);
|
|
ResolveExpr(El.Expr,rraRead);
|
|
if El.VarType<>nil then
|
|
if El.VarType<>nil then
|
|
begin
|
|
begin
|
|
|
|
+ if (El.Parent is TPasRecordType) and (El.VarType=El.Parent) then
|
|
|
|
+ RaiseMsg(20181218173631,nTypeXIsNotYetCompletelyDefined,
|
|
|
|
+ sTypeXIsNotYetCompletelyDefined,[El.VarType.Name],El);
|
|
if El.Expr<>nil then
|
|
if El.Expr<>nil then
|
|
CheckAssignCompatibility(El,El.Expr,true);
|
|
CheckAssignCompatibility(El,El.Expr,true);
|
|
end
|
|
end
|
|
@@ -5855,7 +5901,7 @@ begin
|
|
EmitTypeHints(El,El.VarType);
|
|
EmitTypeHints(El,El.VarType);
|
|
end;
|
|
end;
|
|
|
|
|
|
-procedure TPasResolver.FinishPropertyOfClass(PropEl: TPasProperty);
|
|
|
|
|
|
+procedure TPasResolver.FinishProperty(PropEl: TPasProperty);
|
|
var
|
|
var
|
|
PropType: TPasType;
|
|
PropType: TPasType;
|
|
ClassScope: TPasClassScope;
|
|
ClassScope: TPasClassScope;
|
|
@@ -6750,7 +6796,7 @@ begin
|
|
CreateReference(IntfProc,Expr,rraRead);
|
|
CreateReference(IntfProc,Expr,rraRead);
|
|
if IntfProc.ClassType<>El.ProcClass then
|
|
if IntfProc.ClassType<>El.ProcClass then
|
|
RaiseXExpectedButYFound(20180323144107,GetElementTypeName(El.ProcClass),GetElementTypeName(IntfProc),El.InterfaceProc);
|
|
RaiseXExpectedButYFound(20180323144107,GetElementTypeName(El.ProcClass),GetElementTypeName(IntfProc),El.InterfaceProc);
|
|
- // Note: do not create map here. CheckImplements in FinishPropertyOfClass must be called before.
|
|
|
|
|
|
+ // Note: do not create map here. CheckImplements in FinishProperty must be called before.
|
|
|
|
|
|
// El.ImplementationProc is resolved in FinishClassType
|
|
// El.ImplementationProc is resolved in FinishClassType
|
|
end;
|
|
end;
|
|
@@ -7863,7 +7909,7 @@ begin
|
|
// identifier is a proc and args brackets are missing
|
|
// identifier is a proc and args brackets are missing
|
|
if El.Parent.ClassType=TPasProperty then
|
|
if El.Parent.ClassType=TPasProperty then
|
|
// a property accessor does not need args -> ok
|
|
// a property accessor does not need args -> ok
|
|
- // Note: the detailed tests are in FinishPropertyOfClass
|
|
|
|
|
|
+ // Note: the detailed tests are in FinishProperty
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
// examples: funca or @proca or a.funca or @a.funca ...
|
|
// examples: funca or @proca or a.funca or @a.funca ...
|
|
@@ -7936,7 +7982,8 @@ procedure TPasResolver.ResolveInherited(El: TInheritedExpr;
|
|
Access: TResolvedRefAccess);
|
|
Access: TResolvedRefAccess);
|
|
var
|
|
var
|
|
ProcScope, DeclProcScope, SelfScope: TPasProcedureScope;
|
|
ProcScope, DeclProcScope, SelfScope: TPasProcedureScope;
|
|
- AncestorScope, ClassScope: TPasClassScope;
|
|
|
|
|
|
+ AncestorScope: TPasClassScope;
|
|
|
|
+ ClassRecScope: TPasClassOrRecordScope;
|
|
DeclProc, AncestorProc: TPasProcedure;
|
|
DeclProc, AncestorProc: TPasProcedure;
|
|
begin
|
|
begin
|
|
{$IFDEF VerbosePasResolver}
|
|
{$IFDEF VerbosePasResolver}
|
|
@@ -7955,13 +8002,24 @@ begin
|
|
SelfScope:=ProcScope.GetSelfScope;
|
|
SelfScope:=ProcScope.GetSelfScope;
|
|
if SelfScope=nil then
|
|
if SelfScope=nil then
|
|
RaiseMsg(20170216152141,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
|
|
RaiseMsg(20170216152141,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
|
|
- ClassScope:=SelfScope.ClassScope;
|
|
|
|
|
|
+ ClassRecScope:=SelfScope.ClassScope;
|
|
|
|
|
|
- AncestorScope:=ClassScope.AncestorScope;
|
|
|
|
- if AncestorScope=nil then
|
|
|
|
|
|
+ AncestorScope:=nil;
|
|
|
|
+ if ClassRecScope is TPasClassScope then
|
|
begin
|
|
begin
|
|
- // 'inherited;' without ancestor class is silently ignored
|
|
|
|
- exit;
|
|
|
|
|
|
+ // inherited in class method
|
|
|
|
+ AncestorScope:=TPasClassScope(ClassRecScope).AncestorScope;
|
|
|
|
+ if AncestorScope=nil then
|
|
|
|
+ begin
|
|
|
|
+ // 'inherited;' without ancestor class is silently ignored
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ // inherited in record method
|
|
|
|
+ RaiseMsg(20181218194022,nTheUseOfXisNotAllowedInARecord,sTheUseOfXisNotAllowedInARecord,
|
|
|
|
+ ['inherited'],El);
|
|
end;
|
|
end;
|
|
|
|
|
|
// search ancestor in element, i.e. 'inherited' expression
|
|
// search ancestor in element, i.e. 'inherited' expression
|
|
@@ -7986,7 +8044,8 @@ procedure TPasResolver.ResolveInheritedCall(El: TBinaryExpr;
|
|
// El.right is the identifier and parameters
|
|
// El.right is the identifier and parameters
|
|
var
|
|
var
|
|
ProcScope, SelfScope: TPasProcedureScope;
|
|
ProcScope, SelfScope: TPasProcedureScope;
|
|
- AncestorScope, ClassScope: TPasClassScope;
|
|
|
|
|
|
+ AncestorScope: TPasClassScope;
|
|
|
|
+ ClassRecScope: TPasClassOrRecordScope;
|
|
AncestorClass: TPasClassType;
|
|
AncestorClass: TPasClassType;
|
|
InhScope: TPasDotClassScope;
|
|
InhScope: TPasDotClassScope;
|
|
begin
|
|
begin
|
|
@@ -7998,11 +8057,22 @@ begin
|
|
SelfScope:=ProcScope.GetSelfScope;
|
|
SelfScope:=ProcScope.GetSelfScope;
|
|
if SelfScope=nil then
|
|
if SelfScope=nil then
|
|
RaiseMsg(20170216152148,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
|
|
RaiseMsg(20170216152148,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
|
|
- ClassScope:=SelfScope.ClassScope;
|
|
|
|
|
|
+ ClassRecScope:=SelfScope.ClassScope;
|
|
|
|
|
|
- AncestorScope:=ClassScope.AncestorScope;
|
|
|
|
- if AncestorScope=nil then
|
|
|
|
- RaiseMsg(20170216152151,nInheritedNeedsAncestor,sInheritedNeedsAncestor,[],El.left);
|
|
|
|
|
|
+ AncestorScope:=nil;
|
|
|
|
+ if ClassRecScope is TPasClassScope then
|
|
|
|
+ begin
|
|
|
|
+ // inherited in class method
|
|
|
|
+ AncestorScope:=TPasClassScope(ClassRecScope).AncestorScope;
|
|
|
|
+ if AncestorScope=nil then
|
|
|
|
+ RaiseMsg(20170216152151,nInheritedNeedsAncestor,sInheritedNeedsAncestor,[],El.left);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ // inherited in record method
|
|
|
|
+ RaiseMsg(20181218194436,nTheUseOfXisNotAllowedInARecord,sTheUseOfXisNotAllowedInARecord,
|
|
|
|
+ ['inherited'],El);
|
|
|
|
+ end;
|
|
|
|
|
|
// search call in ancestor
|
|
// search call in ancestor
|
|
AncestorClass:=TPasClassType(AncestorScope.Element);
|
|
AncestorClass:=TPasClassType(AncestorScope.Element);
|
|
@@ -9325,12 +9395,12 @@ procedure TPasResolver.AddProcedure(El: TPasProcedure);
|
|
var
|
|
var
|
|
ProcName, aClassName: String;
|
|
ProcName, aClassName: String;
|
|
p: SizeInt;
|
|
p: SizeInt;
|
|
- CurClassType: TPasClassType;
|
|
|
|
|
|
+ ClassOrRecType: TPasMembersType;
|
|
ProcScope: TPasProcedureScope;
|
|
ProcScope: TPasProcedureScope;
|
|
HasDot: Boolean;
|
|
HasDot: Boolean;
|
|
CurEl: TPasElement;
|
|
CurEl: TPasElement;
|
|
Identifier: TPasIdentifier;
|
|
Identifier: TPasIdentifier;
|
|
- CurClassScope: TPasClassScope;
|
|
|
|
|
|
+ ClassOrRecScope: TPasClassOrRecordScope;
|
|
C: TClass;
|
|
C: TClass;
|
|
begin
|
|
begin
|
|
{$IFDEF VerbosePasResolver}
|
|
{$IFDEF VerbosePasResolver}
|
|
@@ -9370,12 +9440,12 @@ begin
|
|
{$IFDEF VerbosePasResolver}
|
|
{$IFDEF VerbosePasResolver}
|
|
writeln('TPasResolver.AddProcedure searching class of "',ProcName,'" ...');
|
|
writeln('TPasResolver.AddProcedure searching class of "',ProcName,'" ...');
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
- CurClassType:=nil;
|
|
|
|
|
|
+ ClassOrRecType:=nil;
|
|
repeat
|
|
repeat
|
|
p:=Pos('.',ProcName);
|
|
p:=Pos('.',ProcName);
|
|
if p<1 then
|
|
if p<1 then
|
|
begin
|
|
begin
|
|
- if CurClassType=nil then
|
|
|
|
|
|
+ if ClassOrRecType=nil then
|
|
RaiseInternalError(20161013170829);
|
|
RaiseInternalError(20161013170829);
|
|
break;
|
|
break;
|
|
end;
|
|
end;
|
|
@@ -9387,10 +9457,10 @@ begin
|
|
if not IsValidIdent(aClassName) then
|
|
if not IsValidIdent(aClassName) then
|
|
RaiseNotYetImplemented(20161013170844,El);
|
|
RaiseNotYetImplemented(20161013170844,El);
|
|
|
|
|
|
- if CurClassType<>nil then
|
|
|
|
|
|
+ if ClassOrRecType<>nil then
|
|
begin
|
|
begin
|
|
- CurClassScope:=TPasClassScope(CurClassType.CustomData);
|
|
|
|
- Identifier:=CurClassScope.FindLocalIdentifier(aClassName);
|
|
|
|
|
|
+ ClassOrRecScope:=TPasClassOrRecordScope(ClassOrRecType.CustomData);
|
|
|
|
+ Identifier:=ClassOrRecScope.FindLocalIdentifier(aClassName);
|
|
if Identifier=nil then
|
|
if Identifier=nil then
|
|
RaiseIdentifierNotFound(20180430130635,aClassName,El);
|
|
RaiseIdentifierNotFound(20180430130635,aClassName,El);
|
|
CurEl:=Identifier.Element;
|
|
CurEl:=Identifier.Element;
|
|
@@ -9398,7 +9468,7 @@ begin
|
|
else
|
|
else
|
|
CurEl:=FindElementWithoutParams(aClassName,El,false);
|
|
CurEl:=FindElementWithoutParams(aClassName,El,false);
|
|
|
|
|
|
- if not (CurEl is TPasClassType) then
|
|
|
|
|
|
+ if not (CurEl is TPasMembersType) then
|
|
begin
|
|
begin
|
|
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
|
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
|
{$IFDEF VerbosePasResolver}
|
|
{$IFDEF VerbosePasResolver}
|
|
@@ -9407,26 +9477,29 @@ begin
|
|
RaiseXExpectedButYFound(20170216152557,
|
|
RaiseXExpectedButYFound(20170216152557,
|
|
'class',aClassname+':'+GetElementTypeName(CurEl),El);
|
|
'class',aClassname+':'+GetElementTypeName(CurEl),El);
|
|
end;
|
|
end;
|
|
- CurClassType:=TPasClassType(CurEl);
|
|
|
|
- if CurClassType.ObjKind<>okClass then
|
|
|
|
|
|
+ ClassOrRecType:=TPasMembersType(CurEl);
|
|
|
|
+ if ClassOrRecType is TPasClassType then
|
|
begin
|
|
begin
|
|
- aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
|
|
|
- RaiseXExpectedButYFound(20180321161722,
|
|
|
|
- 'class',aClassname+':'+GetElementTypeName(CurEl),El);
|
|
|
|
|
|
+ if TPasClassType(ClassOrRecType).ObjKind<>okClass then
|
|
|
|
+ begin
|
|
|
|
+ aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
|
|
|
+ RaiseXExpectedButYFound(20180321161722,
|
|
|
|
+ 'class',aClassname+':'+GetElementTypeName(CurEl),El);
|
|
|
|
+ end
|
|
end;
|
|
end;
|
|
- if CurClassType.GetModule<>El.GetModule then
|
|
|
|
|
|
+ if ClassOrRecType.GetModule<>El.GetModule then
|
|
begin
|
|
begin
|
|
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
|
aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName)-1);
|
|
RaiseMsg(20180211230432,nMethodClassXInOtherUnitY,sMethodClassXInOtherUnitY,
|
|
RaiseMsg(20180211230432,nMethodClassXInOtherUnitY,sMethodClassXInOtherUnitY,
|
|
- [aClassName,CurClassType.GetModule.Name],El);
|
|
|
|
|
|
+ [aClassName,ClassOrRecType.GetModule.Name],El);
|
|
end;
|
|
end;
|
|
until false;
|
|
until false;
|
|
|
|
|
|
if not IsValidIdent(ProcName) then
|
|
if not IsValidIdent(ProcName) then
|
|
RaiseNotYetImplemented(20161013170956,El);
|
|
RaiseNotYetImplemented(20161013170956,El);
|
|
|
|
|
|
- ProcScope.VisibilityContext:=CurClassType;
|
|
|
|
- ProcScope.ClassScope:=NoNil(CurClassType.CustomData) as TPasClassScope;
|
|
|
|
|
|
+ ProcScope.VisibilityContext:=ClassOrRecType;
|
|
|
|
+ ProcScope.ClassScope:=NoNil(ClassOrRecType.CustomData) as TPasClassOrRecordScope;
|
|
end;// HasDot=true
|
|
end;// HasDot=true
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -9714,90 +9787,9 @@ begin
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
eopAdd:
|
|
eopAdd:
|
|
- case LeftResolved.BaseType of
|
|
|
|
- btChar:
|
|
|
|
- begin
|
|
|
|
- case RightResolved.BaseType of
|
|
|
|
- btChar: SetBaseType(btString);
|
|
|
|
- {$ifdef FPC_HAS_CPSTRING}
|
|
|
|
- btAnsiChar:
|
|
|
|
- if BaseTypeChar=btAnsiChar then
|
|
|
|
- SetBaseType(btString)
|
|
|
|
- else
|
|
|
|
- SetBaseType(btUnicodeString);
|
|
|
|
- {$endif}
|
|
|
|
- btWideChar:
|
|
|
|
- if BaseTypeChar=btWideChar then
|
|
|
|
- SetBaseType(btString)
|
|
|
|
- else
|
|
|
|
- SetBaseType(btUnicodeString);
|
|
|
|
- else
|
|
|
|
- // use right type for result
|
|
|
|
- SetRightValueExpr([rrfReadable]);
|
|
|
|
- end;
|
|
|
|
- exit;
|
|
|
|
- end;
|
|
|
|
- {$ifdef FPC_HAS_CPSTRING}
|
|
|
|
- btAnsiChar:
|
|
|
|
- begin
|
|
|
|
- case RightResolved.BaseType of
|
|
|
|
- btChar:
|
|
|
|
- if BaseTypeChar=btAnsiChar then
|
|
|
|
- SetBaseType(btString)
|
|
|
|
- else
|
|
|
|
- SetBaseType(btUnicodeString);
|
|
|
|
- btAnsiChar:
|
|
|
|
- if BaseTypeChar=btAnsiChar then
|
|
|
|
- SetBaseType(btString)
|
|
|
|
- else
|
|
|
|
- SetBaseType(btAnsiString);
|
|
|
|
- btWideChar:
|
|
|
|
- if BaseTypeChar=btWideChar then
|
|
|
|
- SetBaseType(btString)
|
|
|
|
- else
|
|
|
|
- SetBaseType(btUnicodeString);
|
|
|
|
- else
|
|
|
|
- // use right type for result
|
|
|
|
- SetRightValueExpr([rrfReadable]);
|
|
|
|
- end;
|
|
|
|
- exit;
|
|
|
|
- end;
|
|
|
|
- {$endif}
|
|
|
|
- btWideChar:
|
|
|
|
- begin
|
|
|
|
- case RightResolved.BaseType of
|
|
|
|
- btChar,{$ifdef FPC_HAS_CPSTRING}btAnsiChar,{$endif}btWideChar:
|
|
|
|
- if BaseTypeChar=btWideChar then
|
|
|
|
- SetBaseType(btString)
|
|
|
|
- else
|
|
|
|
- SetBaseType(btUnicodeString);
|
|
|
|
- else
|
|
|
|
- // use right type for result
|
|
|
|
- SetRightValueExpr([rrfReadable]);
|
|
|
|
- end;
|
|
|
|
- exit;
|
|
|
|
- end;
|
|
|
|
- {$ifdef FPC_HAS_CPSTRING}
|
|
|
|
- btShortString:
|
|
|
|
- begin
|
|
|
|
- case RightResolved.BaseType of
|
|
|
|
- btChar,btAnsiChar,btShortString,btWideChar:
|
|
|
|
- // use left type for result
|
|
|
|
- SetLeftValueExpr([rrfReadable]);
|
|
|
|
- else
|
|
|
|
- // shortstring + string => string
|
|
|
|
- SetRightValueExpr([rrfReadable]);
|
|
|
|
- end;
|
|
|
|
- exit;
|
|
|
|
- end;
|
|
|
|
- {$endif}
|
|
|
|
- btString,{$ifdef FPC_HAS_CPSTRING}btAnsiString,{$endif}btUnicodeString:
|
|
|
|
- begin
|
|
|
|
- // string + x => string
|
|
|
|
- SetLeftValueExpr([rrfReadable]);
|
|
|
|
|
|
+ if RightResolved.BaseType in btAllStringAndChars then
|
|
|
|
+ if ComputeAddStringRes(LeftResolved,RightResolved,Bin,ResolvedEl) then
|
|
exit;
|
|
exit;
|
|
- end;
|
|
|
|
- end;
|
|
|
|
eopLessThan,
|
|
eopLessThan,
|
|
eopGreaterThan,
|
|
eopGreaterThan,
|
|
eopLessthanEqual,
|
|
eopLessthanEqual,
|
|
@@ -10286,6 +10278,117 @@ begin
|
|
if Flags=[] then ;
|
|
if Flags=[] then ;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function TPasResolver.ComputeAddStringRes(const LeftResolved,
|
|
|
|
+ RightResolved: TPasResolverResult; ExprEl: TPasExpr; out
|
|
|
|
+ ResolvedEl: TPasResolverResult): boolean;
|
|
|
|
+
|
|
|
|
+ procedure SetBaseType(BaseType: TResolverBaseType);
|
|
|
|
+ begin
|
|
|
|
+ SetResolverValueExpr(ResolvedEl,BaseType,FBaseTypes[BaseType],FBaseTypes[BaseType],
|
|
|
|
+ ExprEl,[rrfReadable]);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ procedure SetLeftValueExpr(Flags: TPasResolverResultFlags);
|
|
|
|
+ begin
|
|
|
|
+ SetResolverValueExpr(ResolvedEl,LeftResolved.BaseType,
|
|
|
|
+ LeftResolved.LoTypeEl,LeftResolved.HiTypeEl,ExprEl,Flags);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ procedure SetRightValueExpr(Flags: TPasResolverResultFlags);
|
|
|
|
+ begin
|
|
|
|
+ SetResolverValueExpr(ResolvedEl,RightResolved.BaseType,
|
|
|
|
+ RightResolved.LoTypeEl,RightResolved.HiTypeEl,ExprEl,Flags);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ Result:=true;
|
|
|
|
+ case LeftResolved.BaseType of
|
|
|
|
+ btChar:
|
|
|
|
+ begin
|
|
|
|
+ case RightResolved.BaseType of
|
|
|
|
+ btChar: SetBaseType(btString);
|
|
|
|
+ {$ifdef FPC_HAS_CPSTRING}
|
|
|
|
+ btAnsiChar:
|
|
|
|
+ if BaseTypeChar=btAnsiChar then
|
|
|
|
+ SetBaseType(btString)
|
|
|
|
+ else
|
|
|
|
+ SetBaseType(btUnicodeString);
|
|
|
|
+ {$endif}
|
|
|
|
+ btWideChar:
|
|
|
|
+ if BaseTypeChar=btWideChar then
|
|
|
|
+ SetBaseType(btString)
|
|
|
|
+ else
|
|
|
|
+ SetBaseType(btUnicodeString);
|
|
|
|
+ else
|
|
|
|
+ // use right type for result
|
|
|
|
+ SetRightValueExpr([rrfReadable]);
|
|
|
|
+ end;
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+ {$ifdef FPC_HAS_CPSTRING}
|
|
|
|
+ btAnsiChar:
|
|
|
|
+ begin
|
|
|
|
+ case RightResolved.BaseType of
|
|
|
|
+ btChar:
|
|
|
|
+ if BaseTypeChar=btAnsiChar then
|
|
|
|
+ SetBaseType(btString)
|
|
|
|
+ else
|
|
|
|
+ SetBaseType(btUnicodeString);
|
|
|
|
+ btAnsiChar:
|
|
|
|
+ if BaseTypeChar=btAnsiChar then
|
|
|
|
+ SetBaseType(btString)
|
|
|
|
+ else
|
|
|
|
+ SetBaseType(btAnsiString);
|
|
|
|
+ btWideChar:
|
|
|
|
+ if BaseTypeChar=btWideChar then
|
|
|
|
+ SetBaseType(btString)
|
|
|
|
+ else
|
|
|
|
+ SetBaseType(btUnicodeString);
|
|
|
|
+ else
|
|
|
|
+ // use right type for result
|
|
|
|
+ SetRightValueExpr([rrfReadable]);
|
|
|
|
+ end;
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+ {$endif}
|
|
|
|
+ btWideChar:
|
|
|
|
+ begin
|
|
|
|
+ case RightResolved.BaseType of
|
|
|
|
+ btChar,{$ifdef FPC_HAS_CPSTRING}btAnsiChar,{$endif}btWideChar:
|
|
|
|
+ if BaseTypeChar=btWideChar then
|
|
|
|
+ SetBaseType(btString)
|
|
|
|
+ else
|
|
|
|
+ SetBaseType(btUnicodeString);
|
|
|
|
+ else
|
|
|
|
+ // use right type for result
|
|
|
|
+ SetRightValueExpr([rrfReadable]);
|
|
|
|
+ end;
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+ {$ifdef FPC_HAS_CPSTRING}
|
|
|
|
+ btShortString:
|
|
|
|
+ begin
|
|
|
|
+ case RightResolved.BaseType of
|
|
|
|
+ btChar,btAnsiChar,btShortString,btWideChar:
|
|
|
|
+ // use left type for result
|
|
|
|
+ SetLeftValueExpr([rrfReadable]);
|
|
|
|
+ else
|
|
|
|
+ // shortstring + string => string
|
|
|
|
+ SetRightValueExpr([rrfReadable]);
|
|
|
|
+ end;
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+ {$endif}
|
|
|
|
+ btString,{$ifdef FPC_HAS_CPSTRING}btAnsiString,{$endif}btUnicodeString:
|
|
|
|
+ begin
|
|
|
|
+ // string + x => string
|
|
|
|
+ SetLeftValueExpr([rrfReadable]);
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ Result:=false;
|
|
|
|
+end;
|
|
|
|
+
|
|
procedure TPasResolver.ComputeArrayParams(Params: TParamsExpr; out
|
|
procedure TPasResolver.ComputeArrayParams(Params: TParamsExpr; out
|
|
ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
|
|
ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
|
|
StartEl: TPasElement);
|
|
StartEl: TPasElement);
|
|
@@ -11844,24 +11947,20 @@ begin
|
|
{$IFDEF VerbosePasResEval}
|
|
{$IFDEF VerbosePasResEval}
|
|
writeln('TPasResolver.OnExprEvalParams Calling BuiltInProc ',Decl.Name,' ',ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
|
|
writeln('TPasResolver.OnExprEvalParams Calling BuiltInProc ',Decl.Name,' ',ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
- case BuiltInProc.BuiltIn of
|
|
|
|
- bfLength: BI_Length_OnEval(BuiltInProc,Params,Flags,Result);
|
|
|
|
- bfAssigned: Result:=nil;
|
|
|
|
- bfChr: BI_Chr_OnEval(BuiltInProc,Params,Flags,Result);
|
|
|
|
- bfOrd: BI_Ord_OnEval(BuiltInProc,Params,Flags,Result);
|
|
|
|
- bfLow,bfHigh: BI_LowHigh_OnEval(BuiltInProc,Params,Flags,Result);
|
|
|
|
- bfPred,bfSucc: BI_PredSucc_OnEval(BuiltInProc,Params,Flags,Result);
|
|
|
|
- bfStrFunc: BI_StrFunc_OnEval(BuiltInProc,Params,Flags,Result);
|
|
|
|
- bfConcatArray: Result:=nil;
|
|
|
|
- bfCopyArray: Result:=nil;
|
|
|
|
- bfTypeInfo: Result:=nil;
|
|
|
|
- bfDefault: BI_Default_OnEval(BuiltInProc,Params,Flags,Result);
|
|
|
|
|
|
+ if BuiltInProc.Eval<>nil then
|
|
|
|
+ BuiltInProc.Eval(BuiltInProc,Params,Flags,Result)
|
|
else
|
|
else
|
|
- {$IFDEF VerbosePasResEval}
|
|
|
|
- writeln('TPasResolver.OnExprEvalParams Unhandled BuiltInProc ',Decl.Name,' ',ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
|
|
|
|
- {$ENDIF}
|
|
|
|
- RaiseNotYetImplemented(20170624192324,Params);
|
|
|
|
- end;
|
|
|
|
|
|
+ case BuiltInProc.BuiltIn of
|
|
|
|
+ bfAssigned: Result:=nil;
|
|
|
|
+ bfConcatArray: Result:=nil;
|
|
|
|
+ bfCopyArray: Result:=nil;
|
|
|
|
+ bfTypeInfo: Result:=nil;
|
|
|
|
+ else
|
|
|
|
+ {$IFDEF VerbosePasResEval}
|
|
|
|
+ writeln('TPasResolver.OnExprEvalParams Unhandled BuiltInProc ',Decl.Name,' ',ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ RaiseNotYetImplemented(20170624192324,Params);
|
|
|
|
+ end;
|
|
{$IFDEF VerbosePasResEval}
|
|
{$IFDEF VerbosePasResEval}
|
|
{AllowWriteln}
|
|
{AllowWriteln}
|
|
if Result<>nil then
|
|
if Result<>nil then
|
|
@@ -13501,6 +13600,95 @@ begin
|
|
ResolvedEl.BaseType:=btArrayLit;
|
|
ResolvedEl.BaseType:=btArrayLit;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function TPasResolver.BI_ConcatString_OnGetCallCompatibility(
|
|
|
|
+ Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
|
|
|
|
+var
|
|
|
|
+ Params: TParamsExpr;
|
|
|
|
+ i: Integer;
|
|
|
|
+ Param: TPasExpr;
|
|
|
|
+ ParamResolved: TPasResolverResult;
|
|
|
|
+begin
|
|
|
|
+ Result:=cIncompatible;
|
|
|
|
+ if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
|
|
|
|
+ exit;
|
|
|
|
+ Params:=TParamsExpr(Expr);
|
|
|
|
+
|
|
|
|
+ for i:=0 to length(Params.Params)-1 do
|
|
|
|
+ begin
|
|
|
|
+ // all params: char or string
|
|
|
|
+ Param:=Params.Params[i];
|
|
|
|
+ ComputeElement(Param,ParamResolved,[]);
|
|
|
|
+ if not (rrfReadable in ParamResolved.Flags)
|
|
|
|
+ or not (ParamResolved.BaseType in btAllStringAndChars) then
|
|
|
|
+ exit(CheckRaiseTypeArgNo(20181219230329,i+1,Param,ParamResolved,'string',RaiseOnError));
|
|
|
|
+ end;
|
|
|
|
+ Result:=cExact;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TPasResolver.BI_ConcatString_OnGetCallResult(
|
|
|
|
+ Proc: TResElDataBuiltInProc; Params: TParamsExpr; out
|
|
|
|
+ ResolvedEl: TPasResolverResult);
|
|
|
|
+var
|
|
|
|
+ i: Integer;
|
|
|
|
+ Param: TPasExpr;
|
|
|
|
+ ParamResolved, CombinedResolved: TPasResolverResult;
|
|
|
|
+begin
|
|
|
|
+ for i:=0 to length(Params.Params)-1 do
|
|
|
|
+ begin
|
|
|
|
+ // all params: char or string
|
|
|
|
+ Param:=Params.Params[i];
|
|
|
|
+ ComputeElement(Param,ParamResolved,[]);
|
|
|
|
+ if i=0 then
|
|
|
|
+ ResolvedEl:=ParamResolved
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ ComputeAddStringRes(ResolvedEl,ParamResolved,Params,CombinedResolved);
|
|
|
|
+ ResolvedEl:=CombinedResolved;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TPasResolver.BI_ConcatString_OnEval(Proc: TResElDataBuiltInProc;
|
|
|
|
+ Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue);
|
|
|
|
+var
|
|
|
|
+ i: Integer;
|
|
|
|
+ Param: TPasExpr;
|
|
|
|
+ Value, NewValue: TResEvalValue;
|
|
|
|
+ ok: Boolean;
|
|
|
|
+begin
|
|
|
|
+ Value:=nil;
|
|
|
|
+ Evaluated:=nil;
|
|
|
|
+ ok:=false;
|
|
|
|
+ try
|
|
|
|
+ for i:=0 to length(Params.Params)-1 do
|
|
|
|
+ begin
|
|
|
|
+ // all params: char or string
|
|
|
|
+ Param:=Params.Params[i];
|
|
|
|
+ Value:=Eval(Param,Flags);
|
|
|
|
+ if Value=nil then
|
|
|
|
+ exit;
|
|
|
|
+ if i=0 then
|
|
|
|
+ begin
|
|
|
|
+ Evaluated:=Value;
|
|
|
|
+ Value:=nil;
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ NewValue:=ExprEvaluator.EvalStringAddExpr(Param,Params.Params[i-1],Param,
|
|
|
|
+ Evaluated,Value);
|
|
|
|
+ ReleaseEvalValue(Evaluated);
|
|
|
|
+ Evaluated:=NewValue;
|
|
|
|
+ ReleaseEvalValue(Value);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ ok:=true;
|
|
|
|
+ finally
|
|
|
|
+ ReleaseEvalValue(Value);
|
|
|
|
+ if not ok then
|
|
|
|
+ ReleaseEvalValue(Evaluated);
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
function TPasResolver.BI_CopyArray_OnGetCallCompatibility(
|
|
function TPasResolver.BI_CopyArray_OnGetCallCompatibility(
|
|
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
|
|
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
|
|
var
|
|
var
|
|
@@ -14576,8 +14764,9 @@ var
|
|
OnlyTypeMembers, IsClassOf: Boolean;
|
|
OnlyTypeMembers, IsClassOf: Boolean;
|
|
TypeEl: TPasType;
|
|
TypeEl: TPasType;
|
|
C: TClass;
|
|
C: TClass;
|
|
- ClassScope: TPasClassScope;
|
|
|
|
|
|
+ ClassRecScope: TPasClassOrRecordScope;
|
|
i: Integer;
|
|
i: Integer;
|
|
|
|
+ AbstractProcs: TArrayOfPasProcedure;
|
|
begin
|
|
begin
|
|
StartScope:=FindData.StartScope;
|
|
StartScope:=FindData.StartScope;
|
|
OnlyTypeMembers:=false;
|
|
OnlyTypeMembers:=false;
|
|
@@ -14694,25 +14883,29 @@ begin
|
|
RaiseInternalError(20170131141936);
|
|
RaiseInternalError(20170131141936);
|
|
Ref.Context:=TResolvedRefCtxConstructor.Create;
|
|
Ref.Context:=TResolvedRefCtxConstructor.Create;
|
|
if StartScope is TPasDotClassScope then
|
|
if StartScope is TPasDotClassScope then
|
|
- ClassScope:=TPasDotClassScope(StartScope).ClassScope
|
|
|
|
|
|
+ ClassRecScope:=TPasDotClassScope(StartScope).ClassScope
|
|
else if (StartScope is TPasWithExprScope)
|
|
else if (StartScope is TPasWithExprScope)
|
|
- and (TPasWithExprScope(StartScope).Scope is TPasClassScope) then
|
|
|
|
- ClassScope:=TPasClassScope(TPasWithExprScope(StartScope).Scope)
|
|
|
|
|
|
+ and (TPasWithExprScope(StartScope).Scope is TPasClassOrRecordScope) then
|
|
|
|
+ ClassRecScope:=TPasClassOrRecordScope(TPasWithExprScope(StartScope).Scope)
|
|
else if (StartScope is TPasProcedureScope) then
|
|
else if (StartScope is TPasProcedureScope) then
|
|
- ClassScope:=TPasProcedureScope(StartScope).ClassScope
|
|
|
|
|
|
+ ClassRecScope:=TPasProcedureScope(StartScope).ClassScope
|
|
else
|
|
else
|
|
RaiseInternalError(20170131150855,GetObjName(StartScope));
|
|
RaiseInternalError(20170131150855,GetObjName(StartScope));
|
|
- TypeEl:=ClassScope.Element as TPasType;
|
|
|
|
|
|
+ TypeEl:=ClassRecScope.Element as TPasType;
|
|
TResolvedRefCtxConstructor(Ref.Context).Typ:=TypeEl;
|
|
TResolvedRefCtxConstructor(Ref.Context).Typ:=TypeEl;
|
|
- if (length(ClassScope.AbstractProcs)>0) then
|
|
|
|
|
|
+ if ClassRecScope is TPasClassScope then
|
|
begin
|
|
begin
|
|
- if IsClassOf then
|
|
|
|
- // aClass.Create: do not warn
|
|
|
|
- else
|
|
|
|
- for i:=0 to length(ClassScope.AbstractProcs)-1 do
|
|
|
|
- LogMsg(20171227110746,mtWarning,nConstructingClassXWithAbstractMethodY,
|
|
|
|
- sConstructingClassXWithAbstractMethodY,
|
|
|
|
- [TypeEl.Name,ClassScope.AbstractProcs[i].Name],FindData.ErrorPosEl);
|
|
|
|
|
|
+ AbstractProcs:=TPasClassScope(ClassRecScope).AbstractProcs;
|
|
|
|
+ if (length(AbstractProcs)>0) then
|
|
|
|
+ begin
|
|
|
|
+ if IsClassOf then
|
|
|
|
+ // aClass.Create: do not warn
|
|
|
|
+ else
|
|
|
|
+ for i:=0 to length(AbstractProcs)-1 do
|
|
|
|
+ LogMsg(20171227110746,mtWarning,nConstructingClassXWithAbstractMethodY,
|
|
|
|
+ sConstructingClassXWithAbstractMethodY,
|
|
|
|
+ [TypeEl.Name,AbstractProcs[i].Name],FindData.ErrorPosEl);
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF VerbosePasResolver}
|
|
{$IFDEF VerbosePasResolver}
|
|
@@ -15181,7 +15374,8 @@ begin
|
|
nil,@BI_Assigned_OnFinishParamsExpr,bfAssigned);
|
|
nil,@BI_Assigned_OnFinishParamsExpr,bfAssigned);
|
|
if bfChr in TheBaseProcs then
|
|
if bfChr in TheBaseProcs then
|
|
AddBuiltInProc('Chr','function Chr(const Integer): char',
|
|
AddBuiltInProc('Chr','function Chr(const Integer): char',
|
|
- @BI_Chr_OnGetCallCompatibility,@BI_Chr_OnGetCallResult,nil,nil,bfChr);
|
|
|
|
|
|
+ @BI_Chr_OnGetCallCompatibility,@BI_Chr_OnGetCallResult,
|
|
|
|
+ @BI_Chr_OnEval,nil,bfChr);
|
|
if bfOrd in TheBaseProcs then
|
|
if bfOrd in TheBaseProcs then
|
|
AddBuiltInProc('Ord','function Ord(const Enum or Char): integer',
|
|
AddBuiltInProc('Ord','function Ord(const Enum or Char): integer',
|
|
@BI_Ord_OnGetCallCompatibility,@BI_Ord_OnGetCallResult,
|
|
@BI_Ord_OnGetCallCompatibility,@BI_Ord_OnGetCallResult,
|
|
@@ -15222,6 +15416,10 @@ begin
|
|
AddBuiltInProc('Concat','function Concat(const Array1, Array2, ...): Array',
|
|
AddBuiltInProc('Concat','function Concat(const Array1, Array2, ...): Array',
|
|
@BI_ConcatArray_OnGetCallCompatibility,@BI_ConcatArray_OnGetCallResult,
|
|
@BI_ConcatArray_OnGetCallCompatibility,@BI_ConcatArray_OnGetCallResult,
|
|
nil,nil,bfConcatArray);
|
|
nil,nil,bfConcatArray);
|
|
|
|
+ if bfConcatString in TheBaseProcs then
|
|
|
|
+ AddBuiltInProc('Concat','function Concat(const String1, String2, ...): String',
|
|
|
|
+ @BI_ConcatString_OnGetCallCompatibility,@BI_ConcatString_OnGetCallResult,
|
|
|
|
+ @BI_ConcatString_OnEval,nil,bfConcatString);
|
|
if bfCopyArray in TheBaseProcs then
|
|
if bfCopyArray in TheBaseProcs then
|
|
AddBuiltInProc('Copy','function Copy(const Array; Start: integer = 0; Count: integer = all): Array',
|
|
AddBuiltInProc('Copy','function Copy(const Array; Start: integer = 0; Count: integer = all): Array',
|
|
@BI_CopyArray_OnGetCallCompatibility,@BI_CopyArray_OnGetCallResult,
|
|
@BI_CopyArray_OnGetCallCompatibility,@BI_CopyArray_OnGetCallResult,
|
|
@@ -20528,7 +20726,7 @@ var
|
|
begin
|
|
begin
|
|
Result:=false;
|
|
Result:=false;
|
|
if El=nil then exit;
|
|
if El=nil then exit;
|
|
- if El.Parent is TPasClassType then exit(true);
|
|
|
|
|
|
+ if El.Parent is TPasMembersType then exit(true);
|
|
if not (El.CustomData is TPasProcedureScope) then exit;
|
|
if not (El.CustomData is TPasProcedureScope) then exit;
|
|
ProcScope:=TPasProcedureScope(El.CustomData);
|
|
ProcScope:=TPasProcedureScope(El.CustomData);
|
|
Result:=IsMethod(ProcScope.DeclarationProc);
|
|
Result:=IsMethod(ProcScope.DeclarationProc);
|