mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-02 21:49:02 +00:00
fixes #26000; Cannot add members to enum-indexed array of seqs at compile time
This commit is contained in:
@@ -851,14 +851,26 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
|
||||
c.freeTemp(tmp)
|
||||
c.freeTemp(dest)
|
||||
|
||||
proc genMutatingValue(c: PCtx; n: PNode): TRegister =
|
||||
## Loads the value of an in-place mutation target while keeping it attached to
|
||||
## its original storage. Compound lvalues must be resolved through their
|
||||
## address: a normal value load can return a detached copy (for example, when
|
||||
## indexing a broadcast default array).
|
||||
if needsAsgnPatch(n):
|
||||
let address = c.genx(n, {gfNodeAddr})
|
||||
result = c.getTemp(n.typ)
|
||||
c.gABC(n, opcLdDeref, result, address)
|
||||
c.freeTemp(address)
|
||||
else:
|
||||
result = c.genx(n)
|
||||
|
||||
proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
|
||||
var x = n[1]
|
||||
if x.kind in {nkAddr, nkHiddenAddr}: x = x[0]
|
||||
let
|
||||
dest = c.genx(x)
|
||||
dest = c.genMutatingValue(x)
|
||||
tmp = c.genx(n[2])
|
||||
c.gABC(n, opc, dest, tmp, 0)
|
||||
#c.genAsgnPatch(n[1], dest)
|
||||
c.freeTemp(tmp)
|
||||
c.freeTemp(dest)
|
||||
|
||||
@@ -1160,12 +1172,20 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMag
|
||||
c.freeTemp(right)
|
||||
c.freeTemp(d)
|
||||
|
||||
of mIncl, mExcl:
|
||||
of mIncl:
|
||||
unused(c, n, dest)
|
||||
var d = c.genMutatingValue(n[1])
|
||||
var tmp = c.genx(n[2])
|
||||
c.genSetType(n[1], d)
|
||||
c.gABC(n, opcIncl, d, tmp)
|
||||
c.freeTemp(d)
|
||||
c.freeTemp(tmp)
|
||||
of mExcl:
|
||||
unused(c, n, dest)
|
||||
var d = c.genx(n[1])
|
||||
var tmp = c.genx(n[2])
|
||||
c.genSetType(n[1], d)
|
||||
c.gABC(n, if m == mIncl: opcIncl else: opcExcl, d, tmp)
|
||||
c.gABC(n, opcExcl, d, tmp)
|
||||
c.freeTemp(d)
|
||||
c.freeTemp(tmp)
|
||||
of mCard: genCard(c, n, dest)
|
||||
|
||||
101
tests/vm/tbroadcastarraymutation.nim
Normal file
101
tests/vm/tbroadcastarraymutation.nim
Normal file
@@ -0,0 +1,101 @@
|
||||
type
|
||||
Container = object
|
||||
numbers: seq[int]
|
||||
text: string
|
||||
chars: set[char]
|
||||
|
||||
Variant = object
|
||||
case enabled: bool
|
||||
of false:
|
||||
numbers: seq[int]
|
||||
else:
|
||||
discard
|
||||
|
||||
Index = enum
|
||||
index0, index1, index2, index3, index4, index5, index6, index7,
|
||||
index8, index9, index10, index11, index12, index13, index14, index15,
|
||||
index16, index17, index18, index19, index20, index21, index22, index23,
|
||||
index24, index25, index26, index27, index28, index29, index30, index31,
|
||||
index32
|
||||
|
||||
Outer = object
|
||||
values: array[33, seq[int]]
|
||||
|
||||
proc directSeq(): array[33, seq[int]] =
|
||||
result[32].add 1
|
||||
|
||||
proc directStringChar(): array[33, string] =
|
||||
result[32].add 'a'
|
||||
|
||||
proc directStringString(): array[33, string] =
|
||||
result[32].add "ab"
|
||||
|
||||
proc directSet(): array[33, set[char]] =
|
||||
result[32].incl 'a'
|
||||
|
||||
proc fieldSeq(): array[33, Container] =
|
||||
result[32].numbers.add 1
|
||||
|
||||
proc fieldStringChar(): array[33, Container] =
|
||||
result[32].text.add 'a'
|
||||
|
||||
proc fieldStringString(): array[33, Container] =
|
||||
result[32].text.add "ab"
|
||||
|
||||
proc fieldSet(): array[33, Container] =
|
||||
result[32].chars.incl 'a'
|
||||
|
||||
proc nestedSeq(): array[33, array[33, seq[int]]] =
|
||||
result[32][32].add 1
|
||||
|
||||
proc checkedFieldSeq(): array[33, Variant] =
|
||||
result[32].numbers.add 1
|
||||
|
||||
proc enumIndexSeq(): array[Index, seq[int]] =
|
||||
result[index32].add 1
|
||||
|
||||
proc rangeIndexSeq(): array[10..42, seq[int]] =
|
||||
result[42].add 1
|
||||
|
||||
proc firstIndexSeq(): array[33, seq[int]] =
|
||||
result[0].add 1
|
||||
|
||||
proc middleIndexSeq(): array[33, seq[int]] =
|
||||
result[16].add 1
|
||||
|
||||
proc objectArraySeq(): Outer =
|
||||
result.values[32].add 1
|
||||
|
||||
proc singleEvaluation(): tuple[values: array[33, seq[int]], evaluations: int] =
|
||||
var evaluations = 0
|
||||
proc index(): int =
|
||||
inc evaluations
|
||||
32
|
||||
result.values[index()].add 1
|
||||
result.evaluations = evaluations
|
||||
|
||||
proc test =
|
||||
let direct = directSeq()
|
||||
doAssert direct[0].len == 0
|
||||
doAssert direct[31].len == 0
|
||||
doAssert direct[32] == @[1]
|
||||
doAssert directStringChar()[32] == "a"
|
||||
doAssert directStringString()[32] == "ab"
|
||||
doAssert 'a' in directSet()[32]
|
||||
doAssert fieldSeq()[32].numbers == @[1]
|
||||
doAssert fieldStringChar()[32].text == "a"
|
||||
doAssert fieldStringString()[32].text == "ab"
|
||||
doAssert 'a' in fieldSet()[32].chars
|
||||
doAssert nestedSeq()[32][32] == @[1]
|
||||
doAssert checkedFieldSeq()[32].numbers == @[1]
|
||||
doAssert enumIndexSeq()[index32] == @[1]
|
||||
doAssert rangeIndexSeq()[42] == @[1]
|
||||
doAssert firstIndexSeq()[0] == @[1]
|
||||
doAssert middleIndexSeq()[16] == @[1]
|
||||
doAssert objectArraySeq().values[32] == @[1]
|
||||
let evaluated = singleEvaluation()
|
||||
doAssert evaluated.values[32] == @[1]
|
||||
doAssert evaluated.evaluations == 1
|
||||
|
||||
static: test()
|
||||
test()
|
||||
Reference in New Issue
Block a user