mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 08:09:33 +02:00
pastojs: setlength(arr) now always clone
git-svn-id: trunk@42227 -
This commit is contained in:
parent
db1903f45d
commit
f50b4c5fbb
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
33
utils/pas2js/dist/rtl.js
vendored
33
utils/pas2js/dist/rtl.js
vendored
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user