mirror of
https://gitlab.com/freepascal.org/fpc/pas2js.git
synced 2025-04-13 13:19:22 +02:00
fcl-pssrc, pastojs: fixed anonymous proc inside for-loop
This commit is contained in:
parent
b692d76fc5
commit
849d604c04
compiler/packages
@ -1467,7 +1467,6 @@ type
|
||||
procedure ResolveImplElement(El: TPasImplElement); virtual;
|
||||
procedure ResolveImplCaseOf(CaseOf: TPasImplCaseOf); virtual;
|
||||
procedure ResolveImplLabelMark(Mark: TPasImplLabelMark); virtual;
|
||||
procedure ResolveImplForLoop(Loop: TPasImplForLoop); virtual;
|
||||
procedure ResolveImplWithDo(El: TPasImplWithDo); virtual;
|
||||
procedure ResolveImplAsm(El: TPasImplAsmStatement); virtual;
|
||||
procedure ResolveImplAssign(El: TPasImplAssign); virtual;
|
||||
@ -1525,6 +1524,7 @@ type
|
||||
procedure FinishExceptOnExpr; virtual;
|
||||
procedure FinishExceptOnStatement; virtual;
|
||||
procedure FinishWithDo(El: TPasImplWithDo); virtual;
|
||||
procedure FinishForLoopHeader(Loop: TPasImplForLoop); virtual;
|
||||
procedure FinishDeclaration(El: TPasElement); virtual;
|
||||
procedure FinishVariable(El: TPasVariable); virtual;
|
||||
procedure FinishProperty(PropEl: TPasProperty); virtual;
|
||||
@ -6390,6 +6390,224 @@ begin
|
||||
PopWithScope(El);
|
||||
end;
|
||||
|
||||
procedure TPasResolver.FinishForLoopHeader(Loop: TPasImplForLoop);
|
||||
var
|
||||
VarResolved, StartResolved, EndResolved,
|
||||
OrigStartResolved: TPasResolverResult;
|
||||
EnumeratorFound, HasInValues: Boolean;
|
||||
InRange, VarRange: TResEvalValue;
|
||||
InRangeInt, VarRangeInt: TResEvalRangeInt;
|
||||
bt: TResolverBaseType;
|
||||
TypeEl, ElType: TPasType;
|
||||
C: TClass;
|
||||
begin
|
||||
CreateScope(Loop,TPasForLoopScope);
|
||||
|
||||
// loop var
|
||||
ResolveExpr(Loop.VariableName,rraReadAndAssign);
|
||||
ComputeElement(Loop.VariableName,VarResolved,[rcNoImplicitProc,rcSetReferenceFlags]);
|
||||
if not ResolvedElCanBeVarParam(VarResolved,Loop.VariableName) then
|
||||
RaiseVarExpected(20170216151955,Loop.VariableName,VarResolved.IdentEl);
|
||||
|
||||
// resolve start expression
|
||||
ResolveExpr(Loop.StartExpr,rraRead);
|
||||
ComputeElement(Loop.StartExpr,StartResolved,[rcSetReferenceFlags]);
|
||||
|
||||
case Loop.LoopType of
|
||||
ltNormal,ltDown:
|
||||
begin
|
||||
// start value
|
||||
if CheckAssignResCompatibility(VarResolved,StartResolved,Loop.StartExpr,true)=cIncompatible then
|
||||
RaiseIncompatibleTypeRes(20170216151958,nIncompatibleTypesGotExpected,
|
||||
[],StartResolved,VarResolved,Loop.StartExpr);
|
||||
CheckAssignExprRange(VarResolved,Loop.StartExpr);
|
||||
|
||||
// end value
|
||||
ResolveExpr(Loop.EndExpr,rraRead);
|
||||
ComputeElement(Loop.EndExpr,EndResolved,[rcSetReferenceFlags]);
|
||||
if CheckAssignResCompatibility(VarResolved,EndResolved,Loop.EndExpr,false)=cIncompatible then
|
||||
RaiseIncompatibleTypeRes(20170216152001,nIncompatibleTypesGotExpected,
|
||||
[],EndResolved,VarResolved,Loop.EndExpr);
|
||||
CheckAssignExprRange(VarResolved,Loop.EndExpr);
|
||||
end;
|
||||
ltIn:
|
||||
begin
|
||||
// check range
|
||||
EnumeratorFound:=CheckForIn(Loop,VarResolved,StartResolved);
|
||||
if (not EnumeratorFound)
|
||||
and not (StartResolved.IdentEl is TPasType)
|
||||
and (rrfReadable in StartResolved.Flags) then
|
||||
begin
|
||||
EnumeratorFound:=CheckForInClassOrRec(Loop,VarResolved,StartResolved);
|
||||
end;
|
||||
|
||||
if not EnumeratorFound then
|
||||
begin
|
||||
VarRange:=nil;
|
||||
InRange:=nil;
|
||||
try
|
||||
OrigStartResolved:=StartResolved;
|
||||
if StartResolved.IdentEl is TPasType then
|
||||
begin
|
||||
// e.g. for e in TEnum do
|
||||
TypeEl:=StartResolved.LoTypeEl;
|
||||
if TypeEl is TPasArrayType then
|
||||
begin
|
||||
if length(TPasArrayType(TypeEl).Ranges)=1 then
|
||||
InRange:=Eval(TPasArrayType(TypeEl).Ranges[0],[refConst]);
|
||||
end;
|
||||
if InRange=nil then
|
||||
InRange:=EvalTypeRange(TypeEl,[]);
|
||||
{$IFDEF VerbosePasResolver}
|
||||
{AllowWriteln}
|
||||
if InRange<>nil then
|
||||
writeln('TPasResolver.ResolveImplForLoop in type: InRange=',InRange.AsDebugString)
|
||||
else
|
||||
writeln('TPasResolver.ResolveImplForLoop in type: InRange=nil');
|
||||
{AllowWriteln-}
|
||||
{$ENDIF}
|
||||
end
|
||||
else if rrfReadable in StartResolved.Flags then
|
||||
begin
|
||||
// value (variable or expression)
|
||||
bt:=StartResolved.BaseType;
|
||||
if bt in [btSet,btArrayOrSet] then
|
||||
begin
|
||||
if (StartResolved.IdentEl=nil) and (StartResolved.ExprEl<>nil) then
|
||||
InRange:=Eval(StartResolved.ExprEl,[]);
|
||||
if InRange=nil then
|
||||
InRange:=EvalTypeRange(StartResolved.LoTypeEl,[]);
|
||||
end
|
||||
else if bt=btContext then
|
||||
begin
|
||||
TypeEl:=StartResolved.LoTypeEl;
|
||||
C:=TypeEl.ClassType;
|
||||
if C=TPasArrayType then
|
||||
begin
|
||||
ElType:=GetArrayElType(TPasArrayType(TypeEl));
|
||||
ComputeElement(ElType,StartResolved,[rcType]);
|
||||
StartResolved.Flags:=OrigStartResolved.Flags*[rrfReadable,rrfWritable];
|
||||
if CheckAssignResCompatibility(VarResolved,StartResolved,Loop.StartExpr,true)=cIncompatible then
|
||||
RaiseIncompatibleTypeRes(20171112210138,nIncompatibleTypesGotExpected,
|
||||
[],StartResolved,VarResolved,Loop.StartExpr);
|
||||
EnumeratorFound:=true;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
bt:=GetActualBaseType(bt);
|
||||
case bt of
|
||||
{$ifdef FPC_HAS_CPSTRING}
|
||||
btAnsiString:
|
||||
InRange:=TResEvalRangeInt.CreateValue(revskChar,nil,0,$ff);
|
||||
{$endif}
|
||||
btUnicodeString:
|
||||
InRange:=TResEvalRangeInt.CreateValue(revskChar,nil,0,$ffff);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if (not EnumeratorFound) and (InRange<>nil) then
|
||||
begin
|
||||
// for v in <constant> do
|
||||
// -> check if same type
|
||||
VarRange:=EvalTypeRange(VarResolved.LoTypeEl,[]);
|
||||
if VarRange=nil then
|
||||
RaiseXExpectedButYFound(20171109191528,'range',
|
||||
GetResolverResultDescription(VarResolved),Loop.VariableName);
|
||||
//writeln('TPasResolver.ResolveImplForLoop ForIn VarRange=',VarRange.AsDebugString);
|
||||
//writeln('TPasResolver.ResolveImplForLoop ForIn InRange=',InRange.AsDebugString,' ElType=',GetResolverResultDbg(StartResolved));
|
||||
case InRange.Kind of
|
||||
revkRangeInt,revkSetOfInt:
|
||||
begin
|
||||
InRangeInt:=TResEvalRangeInt(InRange);
|
||||
case VarRange.Kind of
|
||||
revkRangeInt:
|
||||
begin
|
||||
VarRangeInt:=TResEvalRangeInt(VarRange);
|
||||
HasInValues:=(InRange.Kind<>revkSetOfInt) or (length(TResEvalSet(InRange).Ranges)>0);
|
||||
case InRangeInt.ElKind of
|
||||
revskEnum:
|
||||
if (VarRangeInt.ElKind<>revskEnum)
|
||||
or not IsSameType(InRangeInt.ElType,VarRangeInt.ElType,prraAlias) then
|
||||
RaiseXExpectedButYFound(20171109200752,GetTypeDescription(InRangeInt.ElType),
|
||||
GetResolverResultDescription(VarResolved,true),loop.VariableName);
|
||||
revskInt:
|
||||
if VarRangeInt.ElKind<>revskInt then
|
||||
RaiseXExpectedButYFound(20171109200752,'integer',
|
||||
GetResolverResultDescription(VarResolved,true),loop.VariableName);
|
||||
revskChar:
|
||||
if VarRangeInt.ElKind<>revskChar then
|
||||
RaiseXExpectedButYFound(20171109200753,'char',
|
||||
GetResolverResultDescription(VarResolved,true),loop.VariableName);
|
||||
revskBool:
|
||||
if VarRangeInt.ElKind<>revskBool then
|
||||
RaiseXExpectedButYFound(20171109200754,'boolean',
|
||||
GetResolverResultDescription(VarResolved,true),loop.VariableName);
|
||||
else
|
||||
if HasInValues then
|
||||
RaiseNotYetImplemented(20171109200954,Loop.StartExpr);
|
||||
end;
|
||||
if HasInValues then
|
||||
begin
|
||||
if (VarRangeInt.RangeStart>InRangeInt.RangeStart) then
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveImplForLoop VarRange=',VarRangeInt.AsDebugString,' ',InRangeInt.AsDebugString);
|
||||
{$ENDIF}
|
||||
fExprEvaluator.EmitRangeCheckConst(20171109201428,
|
||||
InRangeInt.ElementAsString(InRangeInt.RangeStart),
|
||||
VarRangeInt.ElementAsString(VarRangeInt.RangeStart),
|
||||
VarRangeInt.ElementAsString(VarRangeInt.RangeEnd),Loop.VariableName,mtError);
|
||||
end;
|
||||
if (VarRangeInt.RangeEnd<InRangeInt.RangeEnd) then
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveImplForLoop VarRange=',VarRangeInt.AsDebugString,' ',InRangeInt.AsDebugString);
|
||||
{$ENDIF}
|
||||
fExprEvaluator.EmitRangeCheckConst(20171109201429,
|
||||
InRangeInt.ElementAsString(InRangeInt.RangeEnd),
|
||||
VarRangeInt.ElementAsString(VarRangeInt.RangeStart),
|
||||
VarRangeInt.ElementAsString(VarRangeInt.RangeEnd),Loop.VariableName,mtError);
|
||||
end;
|
||||
end;
|
||||
EnumeratorFound:=true;
|
||||
end;
|
||||
else
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveImplForLoop ForIn VarRange=',VarRange.AsDebugString);
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
else
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveImplForLoop ForIn InRange=',InRange.AsDebugString);
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
if not EnumeratorFound then
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
{AllowWriteln}
|
||||
writeln('TPasResolver.ResolveImplForLoop StartResolved=',GetResolverResultDbg(StartResolved));
|
||||
if VarRange<>nil then
|
||||
writeln('TPasResolver.ResolveImplForLoop VarRange=',VarRange.AsDebugString);
|
||||
{AllowWriteln-}
|
||||
{$ENDIF}
|
||||
RaiseMsg(20171108223818,nCannotFindEnumeratorForType,sCannotFindEnumeratorForType,
|
||||
[GetBaseDescription(OrigStartResolved)],Loop.StartExpr);
|
||||
end;
|
||||
finally
|
||||
ReleaseEvalValue(VarRange);
|
||||
ReleaseEvalValue(InRange);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
else
|
||||
RaiseNotYetImplemented(20171108221334,Loop);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPasResolver.FinishDeclaration(El: TPasElement);
|
||||
var
|
||||
C: TClass;
|
||||
@ -7788,7 +8006,8 @@ begin
|
||||
else if C=TPasImplLabelMark then
|
||||
ResolveImplLabelMark(TPasImplLabelMark(El))
|
||||
else if C=TPasImplForLoop then
|
||||
ResolveImplForLoop(TPasImplForLoop(El))
|
||||
// the header was already resolved
|
||||
ResolveImplElement(TPasImplForLoop(El).Body)
|
||||
else if C=TPasImplTry then
|
||||
begin
|
||||
ResolveImplBlock(TPasImplTry(El));
|
||||
@ -8131,225 +8350,6 @@ begin
|
||||
RaiseNotYetImplemented(20161014141636,Mark);
|
||||
end;
|
||||
|
||||
procedure TPasResolver.ResolveImplForLoop(Loop: TPasImplForLoop);
|
||||
var
|
||||
VarResolved, StartResolved, EndResolved,
|
||||
OrigStartResolved: TPasResolverResult;
|
||||
EnumeratorFound, HasInValues: Boolean;
|
||||
InRange, VarRange: TResEvalValue;
|
||||
InRangeInt, VarRangeInt: TResEvalRangeInt;
|
||||
bt: TResolverBaseType;
|
||||
TypeEl, ElType: TPasType;
|
||||
C: TClass;
|
||||
begin
|
||||
CreateScope(Loop,TPasForLoopScope);
|
||||
|
||||
// loop var
|
||||
ResolveExpr(Loop.VariableName,rraReadAndAssign);
|
||||
ComputeElement(Loop.VariableName,VarResolved,[rcNoImplicitProc,rcSetReferenceFlags]);
|
||||
if not ResolvedElCanBeVarParam(VarResolved,Loop.VariableName) then
|
||||
RaiseVarExpected(20170216151955,Loop.VariableName,VarResolved.IdentEl);
|
||||
|
||||
// resolve start expression
|
||||
ResolveExpr(Loop.StartExpr,rraRead);
|
||||
ComputeElement(Loop.StartExpr,StartResolved,[rcSetReferenceFlags]);
|
||||
|
||||
case Loop.LoopType of
|
||||
ltNormal,ltDown:
|
||||
begin
|
||||
// start value
|
||||
if CheckAssignResCompatibility(VarResolved,StartResolved,Loop.StartExpr,true)=cIncompatible then
|
||||
RaiseIncompatibleTypeRes(20170216151958,nIncompatibleTypesGotExpected,
|
||||
[],StartResolved,VarResolved,Loop.StartExpr);
|
||||
CheckAssignExprRange(VarResolved,Loop.StartExpr);
|
||||
|
||||
// end value
|
||||
ResolveExpr(Loop.EndExpr,rraRead);
|
||||
ComputeElement(Loop.EndExpr,EndResolved,[rcSetReferenceFlags]);
|
||||
if CheckAssignResCompatibility(VarResolved,EndResolved,Loop.EndExpr,false)=cIncompatible then
|
||||
RaiseIncompatibleTypeRes(20170216152001,nIncompatibleTypesGotExpected,
|
||||
[],EndResolved,VarResolved,Loop.EndExpr);
|
||||
CheckAssignExprRange(VarResolved,Loop.EndExpr);
|
||||
end;
|
||||
ltIn:
|
||||
begin
|
||||
// check range
|
||||
EnumeratorFound:=CheckForIn(Loop,VarResolved,StartResolved);
|
||||
if (not EnumeratorFound)
|
||||
and not (StartResolved.IdentEl is TPasType)
|
||||
and (rrfReadable in StartResolved.Flags) then
|
||||
begin
|
||||
EnumeratorFound:=CheckForInClassOrRec(Loop,VarResolved,StartResolved);
|
||||
end;
|
||||
|
||||
if not EnumeratorFound then
|
||||
begin
|
||||
VarRange:=nil;
|
||||
InRange:=nil;
|
||||
try
|
||||
OrigStartResolved:=StartResolved;
|
||||
if StartResolved.IdentEl is TPasType then
|
||||
begin
|
||||
// e.g. for e in TEnum do
|
||||
TypeEl:=StartResolved.LoTypeEl;
|
||||
if TypeEl is TPasArrayType then
|
||||
begin
|
||||
if length(TPasArrayType(TypeEl).Ranges)=1 then
|
||||
InRange:=Eval(TPasArrayType(TypeEl).Ranges[0],[refConst]);
|
||||
end;
|
||||
if InRange=nil then
|
||||
InRange:=EvalTypeRange(TypeEl,[]);
|
||||
{$IFDEF VerbosePasResolver}
|
||||
{AllowWriteln}
|
||||
if InRange<>nil then
|
||||
writeln('TPasResolver.ResolveImplForLoop in type: InRange=',InRange.AsDebugString)
|
||||
else
|
||||
writeln('TPasResolver.ResolveImplForLoop in type: InRange=nil');
|
||||
{AllowWriteln-}
|
||||
{$ENDIF}
|
||||
end
|
||||
else if rrfReadable in StartResolved.Flags then
|
||||
begin
|
||||
// value (variable or expression)
|
||||
bt:=StartResolved.BaseType;
|
||||
if bt in [btSet,btArrayOrSet] then
|
||||
begin
|
||||
if (StartResolved.IdentEl=nil) and (StartResolved.ExprEl<>nil) then
|
||||
InRange:=Eval(StartResolved.ExprEl,[]);
|
||||
if InRange=nil then
|
||||
InRange:=EvalTypeRange(StartResolved.LoTypeEl,[]);
|
||||
end
|
||||
else if bt=btContext then
|
||||
begin
|
||||
TypeEl:=StartResolved.LoTypeEl;
|
||||
C:=TypeEl.ClassType;
|
||||
if C=TPasArrayType then
|
||||
begin
|
||||
ElType:=GetArrayElType(TPasArrayType(TypeEl));
|
||||
ComputeElement(ElType,StartResolved,[rcType]);
|
||||
StartResolved.Flags:=OrigStartResolved.Flags*[rrfReadable,rrfWritable];
|
||||
if CheckAssignResCompatibility(VarResolved,StartResolved,Loop.StartExpr,true)=cIncompatible then
|
||||
RaiseIncompatibleTypeRes(20171112210138,nIncompatibleTypesGotExpected,
|
||||
[],StartResolved,VarResolved,Loop.StartExpr);
|
||||
EnumeratorFound:=true;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
bt:=GetActualBaseType(bt);
|
||||
case bt of
|
||||
{$ifdef FPC_HAS_CPSTRING}
|
||||
btAnsiString:
|
||||
InRange:=TResEvalRangeInt.CreateValue(revskChar,nil,0,$ff);
|
||||
{$endif}
|
||||
btUnicodeString:
|
||||
InRange:=TResEvalRangeInt.CreateValue(revskChar,nil,0,$ffff);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if (not EnumeratorFound) and (InRange<>nil) then
|
||||
begin
|
||||
// for v in <constant> do
|
||||
// -> check if same type
|
||||
VarRange:=EvalTypeRange(VarResolved.LoTypeEl,[]);
|
||||
if VarRange=nil then
|
||||
RaiseXExpectedButYFound(20171109191528,'range',
|
||||
GetResolverResultDescription(VarResolved),Loop.VariableName);
|
||||
//writeln('TPasResolver.ResolveImplForLoop ForIn VarRange=',VarRange.AsDebugString);
|
||||
//writeln('TPasResolver.ResolveImplForLoop ForIn InRange=',InRange.AsDebugString,' ElType=',GetResolverResultDbg(StartResolved));
|
||||
case InRange.Kind of
|
||||
revkRangeInt,revkSetOfInt:
|
||||
begin
|
||||
InRangeInt:=TResEvalRangeInt(InRange);
|
||||
case VarRange.Kind of
|
||||
revkRangeInt:
|
||||
begin
|
||||
VarRangeInt:=TResEvalRangeInt(VarRange);
|
||||
HasInValues:=(InRange.Kind<>revkSetOfInt) or (length(TResEvalSet(InRange).Ranges)>0);
|
||||
case InRangeInt.ElKind of
|
||||
revskEnum:
|
||||
if (VarRangeInt.ElKind<>revskEnum)
|
||||
or not IsSameType(InRangeInt.ElType,VarRangeInt.ElType,prraAlias) then
|
||||
RaiseXExpectedButYFound(20171109200752,GetTypeDescription(InRangeInt.ElType),
|
||||
GetResolverResultDescription(VarResolved,true),loop.VariableName);
|
||||
revskInt:
|
||||
if VarRangeInt.ElKind<>revskInt then
|
||||
RaiseXExpectedButYFound(20171109200752,'integer',
|
||||
GetResolverResultDescription(VarResolved,true),loop.VariableName);
|
||||
revskChar:
|
||||
if VarRangeInt.ElKind<>revskChar then
|
||||
RaiseXExpectedButYFound(20171109200753,'char',
|
||||
GetResolverResultDescription(VarResolved,true),loop.VariableName);
|
||||
revskBool:
|
||||
if VarRangeInt.ElKind<>revskBool then
|
||||
RaiseXExpectedButYFound(20171109200754,'boolean',
|
||||
GetResolverResultDescription(VarResolved,true),loop.VariableName);
|
||||
else
|
||||
if HasInValues then
|
||||
RaiseNotYetImplemented(20171109200954,Loop.StartExpr);
|
||||
end;
|
||||
if HasInValues then
|
||||
begin
|
||||
if (VarRangeInt.RangeStart>InRangeInt.RangeStart) then
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveImplForLoop VarRange=',VarRangeInt.AsDebugString,' ',InRangeInt.AsDebugString);
|
||||
{$ENDIF}
|
||||
fExprEvaluator.EmitRangeCheckConst(20171109201428,
|
||||
InRangeInt.ElementAsString(InRangeInt.RangeStart),
|
||||
VarRangeInt.ElementAsString(VarRangeInt.RangeStart),
|
||||
VarRangeInt.ElementAsString(VarRangeInt.RangeEnd),Loop.VariableName,mtError);
|
||||
end;
|
||||
if (VarRangeInt.RangeEnd<InRangeInt.RangeEnd) then
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveImplForLoop VarRange=',VarRangeInt.AsDebugString,' ',InRangeInt.AsDebugString);
|
||||
{$ENDIF}
|
||||
fExprEvaluator.EmitRangeCheckConst(20171109201429,
|
||||
InRangeInt.ElementAsString(InRangeInt.RangeEnd),
|
||||
VarRangeInt.ElementAsString(VarRangeInt.RangeStart),
|
||||
VarRangeInt.ElementAsString(VarRangeInt.RangeEnd),Loop.VariableName,mtError);
|
||||
end;
|
||||
end;
|
||||
EnumeratorFound:=true;
|
||||
end;
|
||||
else
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveImplForLoop ForIn VarRange=',VarRange.AsDebugString);
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
else
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.ResolveImplForLoop ForIn InRange=',InRange.AsDebugString);
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
if not EnumeratorFound then
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
{AllowWriteln}
|
||||
writeln('TPasResolver.ResolveImplForLoop StartResolved=',GetResolverResultDbg(StartResolved));
|
||||
if VarRange<>nil then
|
||||
writeln('TPasResolver.ResolveImplForLoop VarRange=',VarRange.AsDebugString);
|
||||
{AllowWriteln-}
|
||||
{$ENDIF}
|
||||
RaiseMsg(20171108223818,nCannotFindEnumeratorForType,sCannotFindEnumeratorForType,
|
||||
[GetBaseDescription(OrigStartResolved)],Loop.StartExpr);
|
||||
end;
|
||||
finally
|
||||
ReleaseEvalValue(VarRange);
|
||||
ReleaseEvalValue(InRange);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
else
|
||||
RaiseNotYetImplemented(20171108221334,Loop);
|
||||
end;
|
||||
ResolveImplElement(Loop.Body);
|
||||
end;
|
||||
|
||||
procedure TPasResolver.ResolveImplWithDo(El: TPasImplWithDo);
|
||||
// Note: the expressions were already resolved during parsing
|
||||
// and the scopes were already stored in a TPasWithScope.
|
||||
@ -16309,6 +16309,7 @@ begin
|
||||
stExceptOnExpr: FinishExceptOnExpr;
|
||||
stExceptOnStatement: FinishExceptOnStatement;
|
||||
stWithExpr: FinishWithDo(El as TPasImplWithDo);
|
||||
stForLoopHeader: FinishForLoopHeader(El as TPasImplForLoop);
|
||||
stDeclaration: FinishDeclaration(El);
|
||||
stAncestors: FinishAncestors(El as TPasClassType);
|
||||
stInitialFinalization: FinishInitialFinalization(El as TPasImplBlock);
|
||||
|
@ -174,7 +174,8 @@ type
|
||||
stWithExpr, // calls BeginScope after parsing every WITH-expression
|
||||
stExceptOnExpr,
|
||||
stExceptOnStatement,
|
||||
stDeclaration, // e.g. a TPasProperty, TPasVariable, TPasArgument
|
||||
stForLoopHeader,
|
||||
stDeclaration, // e.g. a TPasProperty, TPasVariable, TPasArgument, ...
|
||||
stAncestors, // the list of ancestors and interfaces of a class
|
||||
stInitialFinalization
|
||||
);
|
||||
@ -5735,6 +5736,7 @@ begin
|
||||
TPasImplForLoop(El).LoopType:=lt;
|
||||
if (CurToken<>tkDo) then
|
||||
ParseExcTokenError(TokenInfos[tkDo]);
|
||||
Engine.FinishScope(stForLoopHeader,El);
|
||||
CreateBlock(TPasImplForLoop(El));
|
||||
El:=nil;
|
||||
//WriteLn(i,'FOR "',VarName,'" := ',StartValue,' to ',EndValue,' Token=',CurTokenText);
|
||||
|
@ -469,6 +469,7 @@ type
|
||||
Procedure TestAnonymousProc_With;
|
||||
Procedure TestAnonymousProc_ExceptOn;
|
||||
Procedure TestAnonymousProc_Nested;
|
||||
Procedure TestAnonymousProc_ForLoop;
|
||||
|
||||
// record
|
||||
Procedure TestRecord;
|
||||
@ -7683,6 +7684,27 @@ begin
|
||||
ParseProgram;
|
||||
end;
|
||||
|
||||
procedure TTestResolver.TestAnonymousProc_ForLoop;
|
||||
begin
|
||||
StartProgram(false);
|
||||
Add([
|
||||
'type TProc = reference to procedure;',
|
||||
'procedure Foo(p: TProc);',
|
||||
'begin',
|
||||
'end;',
|
||||
'procedure DoIt;',
|
||||
'var i: word;',
|
||||
' a: word;',
|
||||
'begin',
|
||||
' for i:=1 to 10 do begin',
|
||||
' Foo(procedure begin a:=3; end);',
|
||||
' end;',
|
||||
'end;',
|
||||
'begin',
|
||||
' DoIt;']);
|
||||
ParseProgram;
|
||||
end;
|
||||
|
||||
procedure TTestResolver.TestRecord;
|
||||
begin
|
||||
StartProgram(false);
|
||||
|
@ -16723,7 +16723,7 @@ end;
|
||||
|
||||
function TPasToJSConverter.CreateRTTIMemberProperty(Prop: TPasProperty;
|
||||
AContext: TConvertContext): TJSElement;
|
||||
// create $r.addProperty("propname",flags,result,"getter","setter",{options})
|
||||
// create $r.addProperty("propname",flags,proptype,"getter","setter",{options})
|
||||
var
|
||||
Call: TJSCallExpression;
|
||||
OptionsEl: TJSObjectLiteral;
|
||||
|
@ -347,6 +347,7 @@ type
|
||||
Procedure TestAnonymousProc_Nested;
|
||||
Procedure TestAnonymousProc_NestedAssignResult;
|
||||
Procedure TestAnonymousProc_Class;
|
||||
Procedure TestAnonymousProc_ForLoop;
|
||||
|
||||
// enums, sets
|
||||
Procedure TestEnum_Name;
|
||||
@ -4789,6 +4790,44 @@ begin
|
||||
'']));
|
||||
end;
|
||||
|
||||
procedure TTestModule.TestAnonymousProc_ForLoop;
|
||||
begin
|
||||
StartProgram(false);
|
||||
Add([
|
||||
'type TProc = reference to procedure;',
|
||||
'procedure Foo(p: TProc);',
|
||||
'begin',
|
||||
'end;',
|
||||
'procedure DoIt;',
|
||||
'var i: word;',
|
||||
' a: word;',
|
||||
'begin',
|
||||
' for i:=1 to 10 do begin',
|
||||
' Foo(procedure begin a:=3; end);',
|
||||
' end;',
|
||||
'end;',
|
||||
'begin',
|
||||
' DoIt;']);
|
||||
ConvertProgram;
|
||||
CheckSource('TestAnonymousProc_ForLoop',
|
||||
LinesToStr([ // statements
|
||||
'this.Foo = function (p) {',
|
||||
'};',
|
||||
'this.DoIt = function () {',
|
||||
' var i = 0;',
|
||||
' var a = 0;',
|
||||
' for (i = 1; i <= 10; i++) {',
|
||||
' $mod.Foo(function () {',
|
||||
' a = 3;',
|
||||
' });',
|
||||
' };',
|
||||
'};',
|
||||
'']),
|
||||
LinesToStr([
|
||||
'$mod.DoIt();'
|
||||
]));
|
||||
end;
|
||||
|
||||
procedure TTestModule.TestEnum_Name;
|
||||
begin
|
||||
StartProgram(false);
|
||||
|
Loading…
Reference in New Issue
Block a user