pastojs: setlength(arr) now always clone

git-svn-id: trunk@42227 -
This commit is contained in:
Mattias Gaertner 2019-06-14 20:45:01 +00:00
parent db1903f45d
commit f50b4c5fbb
3 changed files with 74 additions and 5 deletions

View File

@ -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);

View File

@ -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;

View File

@ -797,6 +797,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;
@ -828,7 +859,7 @@ var rtl = {
return a;
}
return setLength(arr,2);
},
},*/
arrayEq: function(a,b){
if (a===null) return b===null;