Pārlūkot izejas kodu

pastojs: faster concat append array:=array+

mattias 3 gadi atpakaļ
vecāks
revīzija
22926e4fc7

+ 55 - 1
packages/pastojs/src/fppas2js.pp

@@ -2226,6 +2226,7 @@ type
     Function ConvertAssignStatement(El: TPasImplAssign; AContext: TConvertContext): TJSElement; virtual;
     Function ConvertAssignStatement(El: TPasImplAssign; AContext: TConvertContext): TJSElement; virtual;
     Function ConvertDirectAssignArrayStatement(El: TPasImplAssign; AssignContext: TAssignContext): TJSElement; virtual;
     Function ConvertDirectAssignArrayStatement(El: TPasImplAssign; AssignContext: TAssignContext): TJSElement; virtual;
     Function ConvertDirectAssignArrayConcat(El: TPasImplAssign; Params: TParamsExpr; AssignContext: TAssignContext): TJSElement; virtual;
     Function ConvertDirectAssignArrayConcat(El: TPasImplAssign; Params: TParamsExpr; AssignContext: TAssignContext): TJSElement; virtual;
+    Function ConvertDirectAssignArrayAdd(El: TPasImplAssign; Bin: TBinaryExpr; AssignContext: TAssignContext): TJSElement; virtual;
     Function ConvertRaiseStatement(El: TPasImplRaise; AContext: TConvertContext ): TJSElement; virtual;
     Function ConvertRaiseStatement(El: TPasImplRaise; AContext: TConvertContext ): TJSElement; virtual;
     Function ConvertIfStatement(El: TPasImplIfElse; AContext: TConvertContext ): TJSElement; virtual;
     Function ConvertIfStatement(El: TPasImplIfElse; AContext: TConvertContext ): TJSElement; virtual;
     Function ConvertWhileStatement(El: TPasImplWhileDo; AContext: TConvertContext): TJSElement; virtual;
     Function ConvertWhileStatement(El: TPasImplWhileDo; AContext: TConvertContext): TJSElement; virtual;
@@ -23201,7 +23202,9 @@ begin
 
 
         end;
         end;
       end;
       end;
-    end;
+    end
+  else if (RightExpr.Kind=pekBinary) and (RightExpr.OpCode=eopAdd) then
+    Result:=ConvertDirectAssignArrayAdd(El,TBinaryExpr(RightExpr),AssignContext);
 end;
 end;
 
 
 function TPasToJSConverter.ConvertDirectAssignArrayConcat(El: TPasImplAssign;
 function TPasToJSConverter.ConvertDirectAssignArrayConcat(El: TPasImplAssign;
@@ -23272,6 +23275,57 @@ begin
     end;
     end;
 end;
 end;
 
 
+function TPasToJSConverter.ConvertDirectAssignArrayAdd(El: TPasImplAssign;
+  Bin: TBinaryExpr; AssignContext: TAssignContext): TJSElement;
+var
+  BinLeft, BinRight: TPasExpr;
+  Ref: TResolvedReference;
+  Decl: TPasElement;
+  ParentContext: TConvertContext;
+  SubParams: TParamsExpr;
+  Call: TJSCallExpression;
+  i: Integer;
+  JS: TJSElement;
+begin
+  Result:=nil;
+  BinLeft:=Bin.Left;
+  if not (BinLeft.CustomData is TResolvedReference) then
+    exit;
+  Ref:=TResolvedReference(BinLeft.CustomData);
+  Decl:=Ref.Declaration;
+  if not (El.Left.CustomData is TResolvedReference) then exit;
+  if (Decl<>TResolvedReference(El.Left.CustomData).Declaration) then
+    exit;
+  // A:=A+...
+  BinRight:=Bin.Right;
+  if BinRight.Kind=pekSet then
+    begin
+    // A:=A+[b,...]  ->  A=rtl.arrayPushN(A,b,...);
+    SubParams:=TParamsExpr(BinRight);
+    ParentContext:=AssignContext.Parent;
+    if length(SubParams.Params)=0 then
+      begin
+      // A:=Concat(A,[])  ->  A;
+      Result:=ConvertExpression(BinLeft,ParentContext);
+      exit;
+      end;
+    try
+      Call:=CreateArrayConcat(AssignContext.LeftResolved.LoTypeEl as TPasArrayType,
+                              El,ParentContext,true);
+      Call.AddArg(ConvertExpression(BinLeft,ParentContext));
+      for i:=0 to length(SubParams.Params)-1 do
+        begin
+        JS:=CreateArrayEl(SubParams.Params[i],ParentContext);
+        Call.AddArg(JS);
+        end;
+      Result:=Call;
+    finally
+      if Result=nil then
+        Call.Free;
+    end;
+    end;
+end;
+
 function TPasToJSConverter.ConvertIfStatement(El: TPasImplIfElse;
 function TPasToJSConverter.ConvertIfStatement(El: TPasImplIfElse;
   AContext: TConvertContext): TJSElement;
   AContext: TConvertContext): TJSElement;
 Var
 Var

+ 84 - 4
packages/pastojs/tests/tcmodules.pas

@@ -501,6 +501,7 @@ type
     Procedure TestArray_Concat_Append_Var;
     Procedure TestArray_Concat_Append_Var;
     Procedure TestArray_Copy;
     Procedure TestArray_Copy;
     Procedure TestArray_InsertDelete;
     Procedure TestArray_InsertDelete;
+    Procedure TestArray_Add_Append;
     Procedure TestArray_DynArrayConstObjFPC;
     Procedure TestArray_DynArrayConstObjFPC;
     Procedure TestArray_DynArrayConstDelphi;
     Procedure TestArray_DynArrayConstDelphi;
     Procedure TestArray_ArrayLitAsParam;
     Procedure TestArray_ArrayLitAsParam;
@@ -11639,6 +11640,85 @@ begin
     '']));
     '']));
 end;
 end;
 
 
+procedure TTestModule.TestArray_Add_Append;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch arrayoperators}',
+  'type',
+  '  integer = longint;',
+  '  TFlag = (big,small);',
+  '  TFlags = set of TFlag;',
+  '  TRec = record',
+  '    i: integer;',
+  '  end;',
+  '  TArrInt = array of integer;',
+  '  TArrRec = array of TRec;',
+  '  TArrFlag = array of TFlag;',
+  '  TArrSet = array of TFlags;',
+  '  TArrJSValue = array of jsvalue;',
+  'var',
+  '  ArrInt: tarrint;',
+  '  ArrRec: tarrrec;',
+  '  ArrFlag: tarrflag;',
+  '  ArrSet: tarrset;',
+  '  ArrJSValue: tarrjsvalue;',
+  '  r: TRec;',
+  '  f: TFlags;',
+  'begin',
+  '  // append',
+  '  arrint:=arrint+[2];',
+  '  arrint:=arrint+[3,4];',
+  '  arrrec:=arrrec+[r];',
+  '  arrrec:=arrrec+[r,r];',
+  '  arrset:=arrset+[f];',
+  '  arrset:=arrset+[f,f];',
+  '  arrjsvalue:=arrjsvalue+[11];',
+  '  arrjsvalue:=arrjsvalue+[12,13];',
+  '  arrflag:=arrflag+[small];',
+  '  arrflag:=arrflag+[small,big];',
+  '']);
+  ConvertProgram;
+  CheckSource('TestArray_Add_Append',
+    LinesToStr([ // statements
+    'this.TFlag = {',
+    '  "0": "big",',
+    '  big: 0,',
+    '  "1": "small",',
+    '  small: 1',
+    '};',
+    'rtl.recNewT(this, "TRec", function () {',
+    '  this.i = 0;',
+    '  this.$eq = function (b) {',
+    '    return this.i === b.i;',
+    '  };',
+    '  this.$assign = function (s) {',
+    '    this.i = s.i;',
+    '    return this;',
+    '  };',
+    '});',
+    'this.ArrInt = [];',
+    'this.ArrRec = [];',
+    'this.ArrFlag = [];',
+    'this.ArrSet = [];',
+    'this.ArrJSValue = [];',
+    'this.r = this.TRec.$new();',
+    'this.f = {};',
+    '']),
+    LinesToStr([ // $mod.$main
+    '$mod.ArrInt = rtl.arrayPushN($mod.ArrInt, 2);',
+    '$mod.ArrInt = rtl.arrayPushN($mod.ArrInt, 3, 4);',
+    '$mod.ArrRec = rtl.arrayPush($mod.TRec, $mod.ArrRec, $mod.TRec.$clone($mod.r));',
+    '$mod.ArrRec = rtl.arrayPush($mod.TRec, $mod.ArrRec, $mod.TRec.$clone($mod.r), $mod.TRec.$clone($mod.r));',
+    '$mod.ArrSet = rtl.arrayPush("refSet", $mod.ArrSet, rtl.refSet($mod.f));',
+    '$mod.ArrSet = rtl.arrayPush("refSet", $mod.ArrSet, rtl.refSet($mod.f), rtl.refSet($mod.f));',
+    '$mod.ArrJSValue = rtl.arrayPushN($mod.ArrJSValue, 11);',
+    '$mod.ArrJSValue = rtl.arrayPushN($mod.ArrJSValue, 12, 13);',
+    '$mod.ArrFlag = rtl.arrayPushN($mod.ArrFlag, $mod.TFlag.small);',
+    '$mod.ArrFlag = rtl.arrayPushN($mod.ArrFlag, $mod.TFlag.small, $mod.TFlag.big);',
+    '']));
+end;
+
 procedure TTestModule.TestArray_DynArrayConstObjFPC;
 procedure TTestModule.TestArray_DynArrayConstObjFPC;
 begin
 begin
   Parser.Options:=Parser.Options+[po_cassignments];
   Parser.Options:=Parser.Options+[po_cassignments];
@@ -11688,9 +11768,9 @@ begin
     '$mod.Ints = rtl.arrayConcatN([1], [2]);',
     '$mod.Ints = rtl.arrayConcatN([1], [2]);',
     '$mod.Ints = [2];',
     '$mod.Ints = [2];',
     '$mod.Ints = rtl.arrayConcatN([], $mod.Ints);',
     '$mod.Ints = rtl.arrayConcatN([], $mod.Ints);',
-    '$mod.Ints = rtl.arrayConcatN($mod.Ints, []);',
+    '$mod.Ints = $mod.Ints;',
     '$mod.Ints = rtl.arrayConcatN($mod.Ints, $mod.OneInt);',
     '$mod.Ints = rtl.arrayConcatN($mod.Ints, $mod.OneInt);',
-    '$mod.Ints = rtl.arrayConcatN($mod.Ints, [1, 1]);',
+    '$mod.Ints = rtl.arrayPushN($mod.Ints, 1, 1);',
     '$mod.Ints = rtl.arrayConcatN([$mod.i, $mod.i], $mod.Ints);',
     '$mod.Ints = rtl.arrayConcatN([$mod.i, $mod.i], $mod.Ints);',
     '$mod.Ints = rtl.arrayConcatN(rtl.arrayConcatN([1], [$mod.i]), [3]);',
     '$mod.Ints = rtl.arrayConcatN(rtl.arrayConcatN([1], [$mod.i]), [3]);',
     '']));
     '']));
@@ -11872,7 +11952,7 @@ begin
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
     '$mod.a = [[1]];',
     '$mod.a = [[1]];',
     '$mod.a = [$mod.i];',
     '$mod.a = [$mod.i];',
-    '$mod.a = rtl.arrayConcatN($mod.a, [$mod.i]);',
+    '$mod.a = rtl.arrayPushN($mod.a, $mod.i);',
     '$mod.a = rtl.arrayConcatN([$mod.i], $mod.a);',
     '$mod.a = rtl.arrayConcatN([$mod.i], $mod.a);',
     '$mod.a = [rtl.arrayConcatN([1], $mod.i)];',
     '$mod.a = [rtl.arrayConcatN([1], $mod.i)];',
     '$mod.a = [rtl.arrayConcatN([1], [2])];',
     '$mod.a = [rtl.arrayConcatN([1], [2])];',
@@ -11924,7 +12004,7 @@ begin
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
     '$mod.a = [[1, 1]];',
     '$mod.a = [[1, 1]];',
     '$mod.a = [$mod.i.slice(0)];',
     '$mod.a = [$mod.i.slice(0)];',
-    '$mod.a = rtl.arrayConcatN($mod.a, [$mod.i.slice(0)]);',
+    '$mod.a = rtl.arrayPushN($mod.a, $mod.i.slice(0));',
     '$mod.a = rtl.arrayConcatN([$mod.i.slice(0)], $mod.a);',
     '$mod.a = rtl.arrayConcatN([$mod.i.slice(0)], $mod.a);',
     '$mod.DoInt([[1, 1]]);',
     '$mod.DoInt([[1, 1]]);',
     '$mod.DoInt([[1, 2], [3, 4]]);',
     '$mod.DoInt([[1, 2], [3, 4]]);',