diff options
author | mattias <mattias@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2019-06-14 20:45:01 +0000 |
---|---|---|
committer | mattias <mattias@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2019-06-14 20:45:01 +0000 |
commit | 9f8447981adaada15c46843c6dbe6077c8ed4d62 (patch) | |
tree | 82f3c1062958ebf5c821fcffe789749d21b3fc9c | |
parent | e4b2acc8e0912cd4f70fb0c67715a96f6840b68a (diff) | |
download | fpc-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.pp | 38 | ||||
-rw-r--r-- | packages/pastojs/tests/tcmodules.pas | 8 | ||||
-rw-r--r-- | utils/pas2js/dist/rtl.js | 33 |
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; |