nim-drchaos/experiments/xtables_mutator.nim

78 lines
2.9 KiB
Nim

# WARNING: This mutator crashes for OrderedTable and it's too slow with Table.
# TODO: split into files and make it compile again.
# Use https://nim-lang.org/docs/importutils.html
# Could try to mutate KeyValuePairSeq directly and then use enlarge.
import random
include std/tables
proc firstPositionHidden*[A, B](t: OrderedTable[A, B]): int =
## Undocumented API for iteration.
if t.counter > 0:
result = t.first
while result >= 0 and not isFilled(t.data[result].hcode):
result = t.data[result].next
else:
result = -1
proc nextPositionHidden*[A, B](t: OrderedTable[A, B]; current: int): int =
## Undocumented API for iteration.
result = t.data[current].next
while result >= 0 and not isFilled(t.data[result].hcode):
result = t.data[result].next
proc nextPositionHidden*[A, B](t: Table[A, B]; current: int): int =
## Undocumented API for iteration.
result = current
while result >= 0 and not isFilled(t.data[result].hcode):
inc result
if result > t.data.high: result = -1
proc positionOfHidden*[A, B](t: OrderedTable[A, B]; index: int): int =
var index = index
result = firstPositionHidden(t)
while result >= 0 and index > 0:
result = t.nextPositionHidden(result)
dec index
proc positionOfHidden*[A, B](t: Table[A, B]; index: int): int =
var index = index
result = if t.counter > 0: 0 else: -1
while result >= 0 and index > 0:
result = t.nextPositionHidden(result)
dec index
proc keyAtHidden*[A, B](t: (Table[A, B]|OrderedTable[A, B]); current: int): lent A {.inline.} =
## Undocumented API for iteration.
result = t.data[current].key
proc keyAtHidden*[A, B](t: var (Table[A, B]|OrderedTable[A, B]); current: int): var A {.inline.} =
## Undocumented API for iteration.
result = t.data[current].key
proc newInput*[T](sizeIncreaseHint: int; r: var Rand): T = discard
proc runMutator*[T](x: var T; sizeIncreaseHint: int; enforceChanges: bool; r: var Rand) = discard
proc mutateTab*[A, B](value: var (Table[A, B]|OrderedTable[A, B]); previous: OrderedTable[A, B];
userMax, sizeIncreaseHint: int; r: var Rand): bool =
let previousSize = previous.byteSize
while value.len > 0 and r.rand(bool):
let pos = positionOfHidden(value, rand(r, value.len-1))
assert pos >= 0
value.del(value.keyAtHidden(pos))
var currentSize = value.byteSize
template remainingSize: untyped = sizeIncreaseHint-currentSize+previousSize
while value.len < userMax and remainingSize > 0 and r.rand(bool):
let key = newInput[A](remainingSize, r)
value[key] = newInput[B](remainingSize-key.byteSize, r)
currentSize = value.byteSize
if value != previous:
return true
elif value.len == 0:
let key = newInput[A](remainingSize, r)
value[key] = newInput[B](remainingSize-key.byteSize, r)
else:
let pos = positionOfHidden(value, rand(r, value.len-1))
assert pos >= 0
runMutator(value.keyAtHidden(pos), remainingSize, true, r)
result = value != previous