summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattias <mattias@3ad0048d-3df7-0310-abae-a5850022a9f2>2019-06-14 20:45:01 +0000
committermattias <mattias@3ad0048d-3df7-0310-abae-a5850022a9f2>2019-06-14 20:45:01 +0000
commit9f8447981adaada15c46843c6dbe6077c8ed4d62 (patch)
tree82f3c1062958ebf5c821fcffe789749d21b3fc9c
parente4b2acc8e0912cd4f70fb0c67715a96f6840b68a (diff)
downloadfpc-9f8447981adaada15c46843c6dbe6077c8ed4d62.tar.gz
pastojs: setlength(arr) now always clone
git-svn-id: https://svn.freepascal.org/svn/fpc/trunk@42227 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--packages/pastojs/src/fppas2js.pp38
-rw-r--r--packages/pastojs/tests/tcmodules.pas8
-rw-r--r--utils/pas2js/dist/rtl.js33
3 files changed, 74 insertions, 5 deletions
diff --git a/packages/pastojs/src/fppas2js.pp b/packages/pastojs/src/fppas2js.pp
index be4f36ceed..0054967080 100644
--- a/packages/pastojs/src/fppas2js.pp
+++ b/packages/pastojs/src/fppas2js.pp
@@ -10783,8 +10783,8 @@ function TPasToJSConverter.ConvertBuiltIn_SetLength(El: TParamsExpr;
AContext: TConvertContext): TJSElement;
// convert "SetLength(a,Len)" to "a = rtl.arraySetLength(a,Len)"
var
- Param0: TPasExpr;
- ResolvedParam0: TPasResolverResult;
+ Param0, Range: TPasExpr;
+ ResolvedParam0, RangeResolved: TPasResolverResult;
ArrayType: TPasArrayType;
Call: TJSCallExpression;
ValInit: TJSElement;
@@ -10792,6 +10792,9 @@ var
ElType, TypeEl: TPasType;
i: Integer;
aResolver: TPas2JSResolver;
+ DimSize: TMaxPrecInt;
+ StaticDims: TObjectList;
+ Lit: TJSLiteral;
begin
Result:=nil;
Param0:=El.Params[0];
@@ -10813,6 +10816,7 @@ begin
// -> AnArray = rtl.setArrayLength(AnArray,defaultvalue,dim1,dim2,...)
AssignContext:=TAssignContext.Create(El,nil,AContext);
+ StaticDims:=nil;
try
aResolver.ComputeElement(Param0,AssignContext.LeftResolved,[rcNoImplicitProc]);
AssignContext.RightResolved:=ResolvedParam0;
@@ -10831,6 +10835,27 @@ begin
ArrayType:=ElType as TPasArrayType;
end;
ElType:=aResolver.ResolveAliasType(aResolver.GetArrayElType(ArrayType));
+ while (ElType.ClassType=TPasArrayType) and (length(TPasArrayType(ElType).Ranges)>0) do
+ begin
+ // array of static array, Note: setlength reallocs static arrays
+ ArrayType:=ElType as TPasArrayType;
+ for i:=0 to length(ArrayType.Ranges)-1 do
+ begin
+ Range:=ArrayType.Ranges[i];
+ // compute size of this dimension
+ DimSize:=aResolver.GetRangeLength(Range);
+ if DimSize=0 then
+ begin
+ aResolver.ComputeElement(Range,RangeResolved,[rcConstant]);
+ RaiseNotSupported(Range,AContext,20190614171520,GetResolverResultDbg(RangeResolved));
+ end;
+ Lit:=CreateLiteralNumber(El,DimSize);
+ if StaticDims=nil then
+ StaticDims:=TObjectList.Create(true);
+ StaticDims.Add(Lit);
+ end;
+ ElType:=aResolver.ResolveAliasType(aResolver.GetArrayElType(ArrayType));
+ end;
if ElType.ClassType=TPasRecordType then
ValInit:=CreateReferencePathExpr(ElType,AContext)
else
@@ -10839,12 +10864,19 @@ begin
// add params: dim1, dim2, ...
for i:=1 to length(El.Params)-1 do
Call.AddArg(ConvertExpression(El.Params[i],AContext));
+ if StaticDims<>nil then
+ begin
+ for i:=0 to StaticDims.Count-1 do
+ Call.AddArg(TJSElement(StaticDims[i]));
+ StaticDims.OwnsObjects:=false;
+ end;
// create left side: array =
Result:=CreateAssignStatement(Param0,AssignContext);
finally
AssignContext.RightSide.Free;
AssignContext.Free;
+ StaticDims.Free;
end;
end
else if ResolvedParam0.BaseType=btString then
@@ -15235,7 +15267,7 @@ begin
Call:=CreateCallExpression(PosEl);
Call.Expr:=CreateDotNameExpr(PosEl,Expr,
- TJSString(GetBIName(pbifnRecordClone)));
+ TJSString(GetBIName(pbifnRecordClone)));
Result:=Call;
if RecordExpr<>nil then
Call.AddArg(RecordExpr);
diff --git a/packages/pastojs/tests/tcmodules.pas b/packages/pastojs/tests/tcmodules.pas
index c4ed504232..fee705233e 100644
--- a/packages/pastojs/tests/tcmodules.pas
+++ b/packages/pastojs/tests/tcmodules.pas
@@ -9109,19 +9109,25 @@ begin
Add([
'type',
' TArrArrInt = array of array of longint;',
+ ' TArrStaInt = array of array[1..2] of longint;',
'var',
' a: TArrArrInt;',
+ ' b: TArrStaInt;',
'begin',
' SetLength(a,2);',
' SetLength(a,3,4);',
+ ' SetLength(b,5);',
'']);
ConvertProgram;
CheckSource('TestArray_SetLengthMultiDim',
LinesToStr([ // statements
- 'this.a = [];']),
+ 'this.a = [];',
+ 'this.b = [];',
+ '']),
LinesToStr([
'$mod.a = rtl.arraySetLength($mod.a, [], 2);',
'$mod.a = rtl.arraySetLength($mod.a, 0, 3, 4);',
+ '$mod.b = rtl.arraySetLength($mod.b, 0, 5, 2);',
'']));
end;
diff --git a/utils/pas2js/dist/rtl.js b/utils/pas2js/dist/rtl.js
index 7de352ced4..fc098fe670 100644
--- a/utils/pas2js/dist/rtl.js
+++ b/utils/pas2js/dist/rtl.js
@@ -798,6 +798,37 @@ var rtl = {
arraySetLength: function(arr,defaultvalue,newlength){
// multi dim: (arr,defaultvalue,dim1,dim2,...)
+ var p = arguments;
+ function setLength(src,argNo){
+ var newlen = p[argNo];
+ var a = [];
+ a.length = newlength;
+ if (argNo === p.length-1){
+ var oldlen = src?src.length:0;
+ if (rtl.isArray(defaultvalue)){
+ for (var i=0; i<newlen; i++) a[i]=(i<oldlen)?src[i]:[]; // array of dyn array
+ } else if (rtl.isObject(defaultvalue)) {
+ if (rtl.isTRecord(defaultvalue)){
+ for (var i=0; i<newlen; i++)
+ a[i]=(i<oldlen)?defaultvalue.$clone(src[i]):defaultvalue.$new(); // e.g. record
+ } else {
+ for (var i=0; i<newlen; i++) a[i]=(i<oldlen)?rtl.refSet(src[i]):{}; // e.g. set
+ }
+ } else {
+ for (var i=0; i<newlen; i++)
+ a[i]=(i<oldlen)?src[i]:defaultvalue;
+ }
+ } else {
+ // multi dim array
+ for (var i=0; i<newlen; i++) a[i]=setLength(src?src[i]:null,argNo+1);
+ }
+ return a;
+ }
+ return setLength(arr,2);
+ },
+
+ /*arrayChgLength: function(arr,defaultvalue,newlength){
+ // multi dim: (arr,defaultvalue,dim1,dim2,...)
if (arr == null) arr = [];
var p = arguments;
function setLength(a,argNo){
@@ -828,7 +859,7 @@ var rtl = {
return a;
}
return setLength(arr,2);
- },
+ },*/
arrayEq: function(a,b){
if (a===null) return b===null;