Fixed copying of aggregates in JS.

This commit is contained in:
yglukhov 2015-06-11 15:55:46 +03:00
commit 6436d1920c
3 changed files with 45 additions and 24 deletions

View file

@ -817,7 +817,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
addf(p.body, "$1 = $2;$n", [a.rdLoc, b.rdLoc]) addf(p.body, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
else: else:
useMagic(p, "nimCopy") useMagic(p, "nimCopy")
addf(p.body, "$1 = nimCopy($2, $3);$n", addf(p.body, "$1 = nimCopy($1, $2, $3);$n",
[a.res, b.res, genTypeInfo(p, y.typ)]) [a.res, b.res, genTypeInfo(p, y.typ)])
of etyBaseIndex: of etyBaseIndex:
if a.typ != etyBaseIndex or b.typ != etyBaseIndex: if a.typ != etyBaseIndex or b.typ != etyBaseIndex:
@ -1206,7 +1206,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
s = a.res s = a.res
else: else:
useMagic(p, "nimCopy") useMagic(p, "nimCopy")
s = "nimCopy($1, $2)" % [a.res, genTypeInfo(p, n.typ)] s = "nimCopy(null, $1, $2)" % [a.res, genTypeInfo(p, n.typ)]
of etyBaseIndex: of etyBaseIndex:
if (a.typ != etyBaseIndex): internalError(n.info, "genVarInit") if (a.typ != etyBaseIndex): internalError(n.info, "genVarInit")
if {sfAddrTaken, sfGlobal} * v.flags != {}: if {sfAddrTaken, sfGlobal} * v.flags != {}:

View file

@ -517,62 +517,70 @@ proc isFatPointer(ti: PNimType): bool =
tyArray, tyArrayConstr, tyTuple, tyArray, tyArrayConstr, tyTuple,
tyOpenArray, tySet, tyVar, tyRef, tyPtr} tyOpenArray, tySet, tyVar, tyRef, tyPtr}
proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.} proc nimCopy(dest, src: pointer, ti: PNimType): pointer {.compilerproc.}
proc nimCopyAux(dest, src: pointer, n: ptr TNimNode) {.compilerproc.} = proc nimCopyAux(dest, src: pointer, n: ptr TNimNode) {.compilerproc.} =
case n.kind case n.kind
of nkNone: sysAssert(false, "nimCopyAux") of nkNone: sysAssert(false, "nimCopyAux")
of nkSlot: of nkSlot:
asm "`dest`[`n`.offset] = nimCopy(`src`[`n`.offset], `n`.typ);" asm """
var ddest = `dest`[`n`.offset];
if (ddest === undefined) ddest = null;
`dest`[`n`.offset] = nimCopy(ddest, `src`[`n`.offset], `n`.typ);
"""
of nkList: of nkList:
for i in 0..n.len-1: for i in 0..n.len-1:
nimCopyAux(dest, src, n.sons[i]) nimCopyAux(dest, src, n.sons[i])
of nkCase: of nkCase:
asm """ asm """
`dest`[`n`.offset] = nimCopy(`src`[`n`.offset], `n`.typ); var ddest = `dest`[`n`.offset];
if (ddest === undefined) ddest = null;
`dest`[`n`.offset] = nimCopy(ddest, `src`[`n`.offset], `n`.typ);
for (var i = 0; i < `n`.sons.length; ++i) { for (var i = 0; i < `n`.sons.length; ++i) {
nimCopyAux(`dest`, `src`, `n`.sons[i][1]); nimCopyAux(`dest`, `src`, `n`.sons[i][1]);
} }
""" """
proc nimCopy(x: pointer, ti: PNimType): pointer = proc nimCopy(dest, src: pointer, ti: PNimType): pointer =
case ti.kind case ti.kind
of tyPtr, tyRef, tyVar, tyNil: of tyPtr, tyRef, tyVar, tyNil:
if not isFatPointer(ti): if not isFatPointer(ti):
result = x result = src
else: else:
asm """ asm "`result` = [`src`[0], `src`[1]];"
`result` = [null, 0];
`result`[0] = `x`[0];
`result`[1] = `x`[1];
"""
of tySet: of tySet:
asm """ asm """
`result` = {}; `result` = {};
for (var key in `x`) { `result`[key] = `x`[key]; } for (var key in `src`) { `result`[key] = `src`[key]; }
""" """
of tyTuple, tyObject: of tyTuple, tyObject:
if ti.base != nil: result = nimCopy(x, ti.base) if ti.base != nil: result = nimCopy(dest, src, ti.base)
elif ti.kind == tyObject: elif ti.kind == tyObject:
asm "`result` = {m_type: `ti`};" asm "`result` = (`dest` === null) ? {m_type: `ti`} : `dest`;"
else: else:
asm "`result` = {};" asm "`result` = (`dest` === null) ? {} : `dest`;"
nimCopyAux(result, x, ti.node) nimCopyAux(result, src, ti.node)
of tySequence, tyArrayConstr, tyOpenArray, tyArray: of tySequence, tyArrayConstr, tyOpenArray, tyArray:
asm """ asm """
`result` = new Array(`x`.length); if (`dest` === null) {
for (var i = 0; i < `x`.length; ++i) { `dest` = new Array(`src`.length);
`result`[i] = nimCopy(`x`[i], `ti`.base); }
else {
`dest`.length = `src`.length;
}
`result` = `dest`;
for (var i = 0; i < `src`.length; ++i) {
`result`[i] = nimCopy(`result`[i], `src`[i], `ti`.base);
} }
""" """
of tyString: of tyString:
asm """ asm """
if (`x` !== null) { if (`src` !== null) {
`result` = `x`.slice(0); `result` = `src`.slice(0);
} }
""" """
else: else:
result = x result = src
proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} = proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} =
case ti.kind case ti.kind
@ -611,7 +619,7 @@ proc arrayConstr(len: int, value: pointer, typ: PNimType): pointer {.
# types are fake # types are fake
asm """ asm """
var result = new Array(`len`); var result = new Array(`len`);
for (var i = 0; i < `len`; ++i) result[i] = nimCopy(`value`, `typ`); for (var i = 0; i < `len`; ++i) result[i] = nimCopy(null, `value`, `typ`);
return result; return result;
""" """

13
tests/js/tcopying.nim Normal file
View file

@ -0,0 +1,13 @@
discard """
output: '''123
'''
"""
type MyArray = array[1, int]
proc changeArray(a: var MyArray) =
a = [123]
var a : MyArray
changeArray(a)
echo a[0]