From 16c118c88158e64c614d8d407c5a365028dfdf0e Mon Sep 17 00:00:00 2001 From: Mattias Gaertner Date: Mon, 22 Mar 2021 17:35:51 +0000 Subject: [PATCH] pastojs: convert TBinaryExpr left lists without stack git-svn-id: trunk@49031 - (cherry picked from commit d62da7bc5d4af2303e031bf0118feb9549990bff) --- packages/pastojs/src/fppas2js.pp | 106 ++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/packages/pastojs/src/fppas2js.pp b/packages/pastojs/src/fppas2js.pp index 659c32d3c9..e48b8ecd4c 100644 --- a/packages/pastojs/src/fppas2js.pp +++ b/packages/pastojs/src/fppas2js.pp @@ -2261,6 +2261,7 @@ type Function ConvertBinaryExpression(El: TBinaryExpr; AContext: TConvertContext): TJSElement; virtual; Function ConvertBinaryExpressionRes(El: TBinaryExpr; AContext: TConvertContext; const LeftResolved, RightResolved: TPasResolverResult; var A,B: TJSElement): TJSElement; virtual; + function ConvertBinaryExpressionMultiAdd(El: TBinaryExpr; AContext: TConvertContext): TJSElement; virtual; Function ConvertSubIdentExpression(El: TBinaryExpr; AContext: TConvertContext): TJSElement; virtual; Function ConvertSubIdentExprCustom(El: TBinaryExpr; AContext: TConvertContext; const OnConvertRight: TConvertJSEvent = nil; Data: Pointer = nil): TJSElement; virtual; @@ -8787,6 +8788,11 @@ begin aResolver:=AContext.Resolver; case El.OpCode of + eopAdd: + begin + Result:=ConvertBinaryExpressionMultiAdd(El,aContext); + exit; + end; eopSubIdent: begin Result:=ConvertSubIdentExpression(El,AContext); @@ -8803,9 +8809,10 @@ begin OldAccess:=AContext.Access; AContext.Access:=caRead; Call:=nil; - A:=ConvertExpression(El.left,AContext); + A:=nil; B:=nil; try + A:=ConvertExpression(El.left,AContext); B:=ConvertExpression(El.right,AContext); if aResolver<>nil then @@ -9677,6 +9684,103 @@ begin end; end; +function TPasToJSConverter.ConvertBinaryExpressionMultiAdd(El: TBinaryExpr; + AContext: TConvertContext): TJSElement; +// handle multi add without stack +// Note: The parser generates a list of TBinaryExpr.Lefts +var + aResolver: TPas2JSResolver; + Left: TPasExpr; + SubBin: TBinaryExpr; + A, B: TJSElement; + LeftResolved, RightResolved, ResultResolved: TPasResolverResult; + Flags: TPasResolverComputeFlags; + R: TJSBinary; + OldAccess: TCtxAccess; +begin + Result:=nil; + aResolver:=AContext.Resolver; + Left:=El; + while Left.ClassType=TBinaryExpr do + begin + SubBin:=TBinaryExpr(Left); + if SubBin.OpCode<>eopAdd then break; + Left:=SubBin.left; + if Left.Parent<>SubBin then + begin + if aResolver<>nil then + RaiseNotSupported(SubBin,AContext,20210321220458) + else if Left.Parent=nil then + Left.Parent:=SubBin + else + RaiseNotSupported(SubBin,AContext,20210321221135); + end; + end; + if Left=El then + RaiseNotSupported(El,AContext,20210321221047); + OldAccess:=AContext.Access; + AContext.Access:=caRead; + A:=nil; + B:=nil; + try + A:=ConvertExpression(Left,AContext); + Flags:=[]; + if aResolver<>nil then + aResolver.ComputeElement(Left,LeftResolved,Flags); + repeat + SubBin:=TBinaryExpr(Left.Parent); + B:=ConvertExpression(SubBin.right,AContext); + if aResolver<>nil then + begin + aResolver.ComputeElement(El.right,RightResolved,Flags); + Result:=ConvertBinaryExpressionRes(SubBin,AContext,LeftResolved,RightResolved,A,B); + if (Result<>nil) then + begin + A:=nil; + B:=nil; + if SubBin=El then exit; + end; + aResolver.ComputeBinaryExprRes(SubBin,ResultResolved,Flags,LeftResolved,RightResolved); + end; + if Result=nil then + begin + // + + R:=TJSBinary(CreateElement(TJSAdditiveExpressionPlus,El)); + R.A:=A; A:=nil; + R.B:=B; B:=nil; + Result:=R; + + if (bsOverflowChecks in AContext.ScannerBoolSwitches) and (aResolver<>nil) then + case El.OpCode of + eopAdd,eopSubtract: + if (LeftResolved.BaseType in btAllJSOverflowAddSubType) + or (RightResolved.BaseType in btAllJSOverflowAddSubType) then + Result:=CreateOverflowCheckCall(Result,SubBin); + eopMultiply: + if (LeftResolved.BaseType in btAllJSOverflowMultType) + or (RightResolved.BaseType in btAllJSOverflowMultType) then + Result:=CreateOverflowCheckCall(Result,SubBin); + end; + + if SubBin=El then exit; + end; + // next + A:=Result; + Result:=nil; + if aResolver<>nil then + LeftResolved:=ResultResolved; + Left:=SubBin; + until false; + finally + AContext.Access:=OldAccess; + if Result=nil then + begin + A.Free; + B.Free; + end; + end; +end; + function TPasToJSConverter.ConvertSubIdentExpression(El: TBinaryExpr; AContext: TConvertContext): TJSElement; // connect El.left and El.right with a dot.