Browse Source

pastojs: convert TBinaryExpr left lists without stack

git-svn-id: trunk@49031 -
(cherry picked from commit d62da7bc5d4af2303e031bf0118feb9549990bff)
Mattias Gaertner 4 years ago
parent
commit
16c118c881
1 changed files with 105 additions and 1 deletions
  1. 105 1
      packages/pastojs/src/fppas2js.pp

+ 105 - 1
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.