deleted web and dist
This commit is contained in:
parent
07d5a8085b
commit
972c510861
50 changed files with 4986 additions and 2289 deletions
21
tests/ecmas.html
Normal file
21
tests/ecmas.html
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!-- This has been written by hand. (c) 2008 Andreas Rumpf -->
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Nimrod ECMAScript Generator Test</title>
|
||||
<style type="text/css">
|
||||
span.DecNumber {color: blue}
|
||||
</style>
|
||||
<script src="rod_gen/ecmas.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<body onload="OnLoad()">
|
||||
<form name="form1" action="ecmas.html">
|
||||
<input type="text" name="input" size="3" />
|
||||
<input type="button" value="Calculate square" onclick="OnButtonClick()" />
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
16
tests/ecmas.nim
Normal file
16
tests/ecmas.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# This file tests the ECMAScript generator
|
||||
|
||||
import
|
||||
dom, strutils
|
||||
|
||||
# We need to declare the used elements here. This is annoying but
|
||||
# prevents any kind of typo:
|
||||
var
|
||||
inputElement {.importc: "document.form1.input", nodecl.}: ref TElement
|
||||
|
||||
proc OnButtonClick() {.exportc.} =
|
||||
var x: int = parseInt($inputElement.value)
|
||||
echo($(x * x))
|
||||
|
||||
proc OnLoad() {.exportc.} =
|
||||
echo("Welcome! Please take your time to fill in this formular!")
|
||||
172
tests/gcbench.nim
Normal file
172
tests/gcbench.nim
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
# This is adapted from a benchmark written by John Ellis and Pete Kovac
|
||||
# of Post Communications.
|
||||
# It was modified by Hans Boehm of Silicon Graphics.
|
||||
#
|
||||
# This is no substitute for real applications. No actual application
|
||||
# is likely to behave in exactly this way. However, this benchmark was
|
||||
# designed to be more representative of real applications than other
|
||||
# Java GC benchmarks of which we are aware.
|
||||
# It attempts to model those properties of allocation requests that
|
||||
# are important to current GC techniques.
|
||||
# It is designed to be used either to obtain a single overall performance
|
||||
# number, or to give a more detailed estimate of how collector
|
||||
# performance varies with object lifetimes. It prints the time
|
||||
# required to allocate and collect balanced binary trees of various
|
||||
# sizes. Smaller trees result in shorter object lifetimes. Each cycle
|
||||
# allocates roughly the same amount of memory.
|
||||
# Two data structures are kept around during the entire process, so
|
||||
# that the measured performance is representative of applications
|
||||
# that maintain some live in-memory data. One of these is a tree
|
||||
# containing many pointers. The other is a large array containing
|
||||
# double precision floating point numbers. Both should be of comparable
|
||||
# size.
|
||||
#
|
||||
# The results are only really meaningful together with a specification
|
||||
# of how much memory was used. It is possible to trade memory for
|
||||
# better time performance. This benchmark should be run in a 32 MB
|
||||
# heap, though we don't currently know how to enforce that uniformly.
|
||||
#
|
||||
# Unlike the original Ellis and Kovac benchmark, we do not attempt
|
||||
# measure pause times. This facility should eventually be added back
|
||||
# in. There are several reasons for omitting it for now. The original
|
||||
# implementation depended on assumptions about the thread scheduler
|
||||
# that don't hold uniformly. The results really measure both the
|
||||
# scheduler and GC. Pause time measurements tend to not fit well with
|
||||
# current benchmark suites. As far as we know, none of the current
|
||||
# commercial Java implementations seriously attempt to minimize GC pause
|
||||
# times.
|
||||
#
|
||||
# Known deficiencies:
|
||||
# - No way to check on memory use
|
||||
# - No cyclic data structures
|
||||
# - No attempt to measure variation with object size
|
||||
# - Results are sensitive to locking cost, but we dont
|
||||
# check for proper locking
|
||||
#
|
||||
|
||||
import
|
||||
strutils, times
|
||||
|
||||
type
|
||||
PNode = ref TNode
|
||||
TNode {.final.} = object
|
||||
left, right: PNode
|
||||
i, j: int
|
||||
|
||||
proc newNode(l, r: PNode): PNode =
|
||||
new(result)
|
||||
result.left = l
|
||||
result.right = r
|
||||
|
||||
const
|
||||
kStretchTreeDepth = 18 # about 16Mb
|
||||
kLongLivedTreeDepth = 16 # about 4Mb
|
||||
kArraySize = 500000 # about 4Mb
|
||||
kMinTreeDepth = 4
|
||||
kMaxTreeDepth = 16
|
||||
|
||||
# Nodes used by a tree of a given size
|
||||
proc TreeSize(i: int): int = return ((1 shl (i + 1)) - 1)
|
||||
|
||||
# Number of iterations to use for a given tree depth
|
||||
proc NumIters(i: int): int =
|
||||
return 2 * TreeSize(kStretchTreeDepth) div TreeSize(i)
|
||||
|
||||
# Build tree top down, assigning to older objects.
|
||||
proc Populate(iDepth: int, thisNode: PNode) =
|
||||
if iDepth <= 0:
|
||||
return
|
||||
else:
|
||||
new(thisNode.left)
|
||||
new(thisNode.right)
|
||||
Populate(iDepth-1, thisNode.left)
|
||||
Populate(iDepth-1, thisNode.right)
|
||||
|
||||
# Build tree bottom-up
|
||||
proc MakeTree(iDepth: int): PNode =
|
||||
if iDepth <= 0:
|
||||
new(result)
|
||||
else:
|
||||
return newNode(MakeTree(iDepth-1),
|
||||
MakeTree(iDepth-1))
|
||||
|
||||
proc PrintDiagnostics() =
|
||||
var
|
||||
FreeMemory = getFreeMem()
|
||||
TotalMemory = getTotalMem()
|
||||
|
||||
echo("Total memory available: " & $TotalMemory & " bytes")
|
||||
echo("Free memory: " & $FreeMemory & " bytes")
|
||||
|
||||
proc TimeConstruction(depth: int) =
|
||||
var
|
||||
root, tempTree: PNode
|
||||
t: int
|
||||
iNumIters: int
|
||||
|
||||
iNumIters = NumIters(depth)
|
||||
|
||||
echo("Creating " & $iNumIters & " trees of depth " & $depth)
|
||||
t = getStartMilsecs()
|
||||
for i in 0..iNumIters-1:
|
||||
new(tempTree)
|
||||
Populate(depth, tempTree)
|
||||
tempTree = nil
|
||||
echo("\tTop down construction took " &
|
||||
$(getStartMilsecs() - t) & "msecs")
|
||||
t = getStartMilsecs()
|
||||
for i in 0..iNumIters-1:
|
||||
tempTree = MakeTree(depth)
|
||||
tempTree = nil
|
||||
echo("\tBottom up construction took " &
|
||||
$(getStartMilsecs() - t) & "msecs")
|
||||
|
||||
type
|
||||
tMyArray = seq[float]
|
||||
|
||||
proc main() =
|
||||
var
|
||||
root, longLivedTree, tempTree: PNode
|
||||
t: int
|
||||
myarray: tMyArray
|
||||
|
||||
echo("Garbage Collector Test")
|
||||
echo(" Stretching memory with a binary tree of depth " &
|
||||
$kStretchTreeDepth)
|
||||
PrintDiagnostics()
|
||||
t = getStartMilsecs()
|
||||
|
||||
# Stretch the memory space quickly
|
||||
tempTree = MakeTree(kStretchTreeDepth)
|
||||
tempTree = nil
|
||||
|
||||
# Create a long lived object
|
||||
echo(" Creating a long-lived binary tree of depth " &
|
||||
$kLongLivedTreeDepth)
|
||||
new(longLivedTree)
|
||||
Populate(kLongLivedTreeDepth, longLivedTree)
|
||||
|
||||
# Create long-lived array, filling half of it
|
||||
echo(" Creating a long-lived array of " & $kArraySize & " doubles")
|
||||
myarray = []
|
||||
setlength(myarray, kArraySize)
|
||||
for i in 0..kArraySize div 2 -1:
|
||||
myarray[i] = 1.0 / toFloat(i)
|
||||
|
||||
PrintDiagnostics()
|
||||
|
||||
var d = kMinTreeDepth
|
||||
while d <= kMaxTreeDepth:
|
||||
TimeConstruction(d)
|
||||
inc(d, 2)
|
||||
|
||||
if longLivedTree == nil or myarray[1000] != 1.0/1000.0:
|
||||
echo("Failed")
|
||||
# fake reference to LongLivedTree
|
||||
# and array to keep them from being optimized away
|
||||
|
||||
var elapsed = getStartMilsecs() - t
|
||||
PrintDiagnostics()
|
||||
echo("Completed in " & $elapsed & "ms.")
|
||||
|
||||
main()
|
||||
34
tests/hallo.nim
Normal file
34
tests/hallo.nim
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Hallo world program
|
||||
|
||||
echo("Hi! What's your name?")
|
||||
var name = readLine(stdin)
|
||||
|
||||
if name == "Andreas":
|
||||
echo("What a nice name!")
|
||||
elif name == "":
|
||||
echo("Don't you have a name?")
|
||||
else:
|
||||
echo("Your name is not Andreas...")
|
||||
|
||||
for i in 0..name.len-1:
|
||||
if name[i] == 'm':
|
||||
echo("hey, there is an *m* in your name!")
|
||||
|
||||
echo("Please give your password: (12345)")
|
||||
var pw = readLine(stdin)
|
||||
|
||||
while pw != "12345":
|
||||
echo("Wrong password! Next try: ")
|
||||
pw = readLine(stdin)
|
||||
|
||||
echo("""Login complete!
|
||||
What do you want to do?
|
||||
delete-everything
|
||||
restart-computer
|
||||
go-for-a-walk""")
|
||||
|
||||
case readline(stdin)
|
||||
of "delete-everything", "restart-computer":
|
||||
echo("permission denied")
|
||||
of "go-for-a-walk": echo("please yourself")
|
||||
else: echo("unknown command")
|
||||
6
tests/rectest.nim
Normal file
6
tests/rectest.nim
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Test the error message
|
||||
|
||||
proc main() =
|
||||
main()
|
||||
|
||||
main()
|
||||
25
tests/tparscfg.nim
Normal file
25
tests/tparscfg.nim
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
import
|
||||
os, parsecfg, strutils
|
||||
|
||||
var
|
||||
p: TCfgParser
|
||||
|
||||
if open(p, paramStr(1)):
|
||||
while true:
|
||||
var e = next(p)
|
||||
case e.kind
|
||||
of cfgEof:
|
||||
echo("EOF!")
|
||||
break
|
||||
of cfgSectionStart: ## a ``[section]`` has been parsed
|
||||
echo("new section: " & e.section)
|
||||
of cfgKeyValuePair:
|
||||
echo("key-value-pair: " & e.key & ": " & e.value)
|
||||
of cfgOption:
|
||||
echo("command: " & e.key & ": " & e.value)
|
||||
of cfgError:
|
||||
echo(e.msg)
|
||||
close(p)
|
||||
else:
|
||||
echo("cannot open: " & paramStr(1))
|
||||
27
tests/tparsopt.nim
Normal file
27
tests/tparsopt.nim
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Test the new parseopt module
|
||||
|
||||
import
|
||||
parseopt
|
||||
|
||||
proc writeHelp() =
|
||||
writeln(stdout, "Usage: tparsopt [options] filename [options]")
|
||||
|
||||
proc writeVersion() =
|
||||
writeln(stdout, "Version: 1.0.0")
|
||||
|
||||
var
|
||||
filename = ""
|
||||
for kind, key, val in getopt():
|
||||
case kind
|
||||
of cmdArgument:
|
||||
filename = key
|
||||
of cmdLongOption, cmdShortOption:
|
||||
case key
|
||||
of "help", "h": writeHelp()
|
||||
of "version", "v": writeVersion()
|
||||
else:
|
||||
writeln(stdout, "Unknown command line option: ", key, ": ", val)
|
||||
of cmdEnd: assert(false) # cannot happen
|
||||
if filename == "":
|
||||
# no filename has been given, so we show the help:
|
||||
writeHelp()
|
||||
319
tests/tradix.nim
Normal file
319
tests/tradix.nim
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
# implements and tests an efficient radix tree
|
||||
|
||||
## another method to store an efficient array of pointers:
|
||||
## We use a radix tree with node compression.
|
||||
## There are two node kinds:
|
||||
|
||||
const bitsPerUnit = 8*sizeof(int)
|
||||
|
||||
type
|
||||
TRadixNodeKind = enum rnLinear, rnFull, rnLeafBits, rnLeafLinear
|
||||
PRadixNode = ptr TRadixNode
|
||||
TRadixNode {.pure.} = object
|
||||
kind: TRadixNodeKind
|
||||
TRadixNodeLinear = object of TRadixNode
|
||||
len: byte
|
||||
keys: array [0..31, byte]
|
||||
vals: array [0..31, PRadixNode]
|
||||
|
||||
TRadixNodeFull = object of TRadixNode
|
||||
b: array [0..255, PRadixNode]
|
||||
TRadixNodeLeafBits = object of TRadixNode
|
||||
b: array [0..7, int]
|
||||
TRadixNodeLeafLinear = object of TRadixNode
|
||||
len: byte
|
||||
keys: array [0..31, byte]
|
||||
|
||||
var
|
||||
root: PRadixNode
|
||||
|
||||
proc searchInner(r: PRadixNode, a: int): PRadixNode =
|
||||
case r.kind
|
||||
of rnLinear:
|
||||
var x = cast[ptr TRadixNodeLinear](r)
|
||||
for i in 0..x.len-1:
|
||||
if ze(x.keys[i]) == a: return x.vals[i]
|
||||
of rnFull:
|
||||
var x = cast[ptr TRadixNodeFull](r)
|
||||
return x.b[a]
|
||||
else: assert(false)
|
||||
|
||||
proc testBit(w, i: int): bool {.inline.} =
|
||||
result = (w and (1 shl (i %% BitsPerUnit))) != 0
|
||||
|
||||
proc setBit(w: var int, i: int) {.inline.} =
|
||||
w = w or (1 shl (i %% bitsPerUnit))
|
||||
|
||||
proc resetBit(w: var int, i: int) {.inline.} =
|
||||
w = w and not (1 shl (i %% bitsPerUnit))
|
||||
|
||||
proc testOrSetBit(w: var int, i: int): bool {.inline.} =
|
||||
var x = (1 shl (i %% bitsPerUnit))
|
||||
if (w and x) != 0: return true
|
||||
w = w or x
|
||||
|
||||
proc searchLeaf(r: PRadixNode, a: int): bool =
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
var x = cast[ptr TRadixNodeLeafBits](r)
|
||||
return testBit(x.b[a /% BitsPerUnit], a)
|
||||
of rnLeafLinear:
|
||||
var x = cast[ptr TRadixNodeLeafLinear](r)
|
||||
for i in 0..x.len-1:
|
||||
if ze(x.keys[i]) == a: return true
|
||||
else: assert(false)
|
||||
|
||||
proc exclLeaf(r: PRadixNode, a: int) =
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
var x = cast[ptr TRadixNodeLeafBits](r)
|
||||
resetBit(x.b[a /% BitsPerUnit], a)
|
||||
of rnLeafLinear:
|
||||
var x = cast[ptr TRadixNodeLeafLinear](r)
|
||||
var L = ze(x.len)
|
||||
for i in 0..L-1:
|
||||
if ze(x.keys[i]) == a:
|
||||
x.keys[i] = x.keys[L-1]
|
||||
dec(x.len)
|
||||
return
|
||||
else: assert(false)
|
||||
|
||||
proc in_Operator*(r: PRadixNode, a: TAddress): bool =
|
||||
if r == nil: return false
|
||||
var x = searchInner(r, a shr 24 and 0xff)
|
||||
if x == nil: return false
|
||||
x = searchInner(x, a shr 16 and 0xff)
|
||||
if x == nil: return false
|
||||
x = searchInner(x, a shr 8 and 0xff)
|
||||
if x == nil: return false
|
||||
return searchLeaf(x, a and 0xff)
|
||||
|
||||
proc excl*(r: PRadixNode, a: TAddress): bool =
|
||||
if r == nil: return false
|
||||
var x = searchInner(r, a shr 24 and 0xff)
|
||||
if x == nil: return false
|
||||
x = searchInner(x, a shr 16 and 0xff)
|
||||
if x == nil: return false
|
||||
x = searchInner(x, a shr 8 and 0xff)
|
||||
if x == nil: return false
|
||||
exclLeaf(x, a and 0xff)
|
||||
|
||||
proc addLeaf(r: var PRadixNode, a: int): bool =
|
||||
if r == nil:
|
||||
# a linear node:
|
||||
var x = cast[ptr TRadixNodeLinear](alloc(sizeof(TRadixNodeLinear)))
|
||||
x.kind = rnLeafLinear
|
||||
x.len = 1
|
||||
x.keys[0] = toU8(a)
|
||||
r = x
|
||||
return false # not already in set
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
var x = cast[ptr TRadixNodeLeafBits](r)
|
||||
return testOrSetBit(x.b[a /% BitsPerUnit], a)
|
||||
of rnLeafLinear:
|
||||
var x = cast[ptr TRadixNodeLeafLinear](r)
|
||||
var L = ze(x.len)
|
||||
for i in 0..L-1:
|
||||
if ze(x.keys[i]) == a: return true
|
||||
if L <= high(x.keys):
|
||||
x.keys[L] = toU8(a)
|
||||
inc(x.len)
|
||||
else:
|
||||
# transform into a full node:
|
||||
var y = cast[ptr TRadixNodeLeafBits](alloc0(sizeof(TRadixNodeLeafBits)))
|
||||
y.kind = rnLeafBits
|
||||
for i in 0..x.len-1:
|
||||
var u = ze(x.keys[i])
|
||||
setBit(y.b[u /% BitsPerUnit], u)
|
||||
setBit(y.b[a /% BitsPerUnit], a)
|
||||
dealloc(r)
|
||||
r = y
|
||||
else: assert(false)
|
||||
|
||||
proc addInner(r: var PRadixNode, a: int, d: int): bool =
|
||||
if d == 0:
|
||||
return addLeaf(r, a and 0xff)
|
||||
var k = a shr d and 0xff
|
||||
if r == nil:
|
||||
# a linear node:
|
||||
var x = cast[ptr TRadixNodeLinear](alloc(sizeof(TRadixNodeLinear)))
|
||||
x.kind = rnLinear
|
||||
x.len = 1
|
||||
x.keys[0] = toU8(k)
|
||||
r = x
|
||||
return addInner(x.vals[0], a, d-8)
|
||||
case r.kind
|
||||
of rnLinear:
|
||||
var x = cast[ptr TRadixNodeLinear](r)
|
||||
var L = ze(x.len)
|
||||
for i in 0..L-1:
|
||||
if ze(x.keys[i]) == k: # already exists
|
||||
return addInner(x.vals[i], a, d-8)
|
||||
if L <= high(x.keys):
|
||||
x.keys[L] = toU8(k)
|
||||
inc(x.len)
|
||||
return addInner(x.vals[L], a, d-8)
|
||||
else:
|
||||
# transform into a full node:
|
||||
var y = cast[ptr TRadixNodeFull](alloc0(sizeof(TRadixNodeFull)))
|
||||
y.kind = rnFull
|
||||
for i in 0..L-1: y.b[ze(x.keys[i])] = x.vals[i]
|
||||
dealloc(r)
|
||||
r = y
|
||||
return addInner(y.b[k], a, d-8)
|
||||
of rnFull:
|
||||
var x = cast[ptr TRadixNodeFull](r)
|
||||
return addInner(x.b[k], a, d-8)
|
||||
else: assert(false)
|
||||
|
||||
proc incl*(r: var PRadixNode, a: TAddress) {.inline.} =
|
||||
discard addInner(r, a, 24)
|
||||
|
||||
proc testOrIncl*(r: var PRadixNode, a: TAddress): bool {.inline.} =
|
||||
return addInner(r, a, 24)
|
||||
|
||||
iterator innerElements(r: PRadixNode): tuple[prefix: int, n: PRadixNode] =
|
||||
if r != nil:
|
||||
case r.kind
|
||||
of rnFull:
|
||||
var r = cast[ptr TRadixNodeFull](r)
|
||||
for i in 0..high(r.b):
|
||||
if r.b[i] != nil:
|
||||
yield (i, r.b[i])
|
||||
of rnLinear:
|
||||
var r = cast[ptr TRadixNodeLinear](r)
|
||||
for i in 0..ze(r.len)-1:
|
||||
yield (ze(r.keys[i]), r.vals[i])
|
||||
else: assert(false)
|
||||
|
||||
iterator leafElements(r: PRadixNode): int =
|
||||
if r != nil:
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
var r = cast[ptr TRadixNodeLeafBits](r)
|
||||
# iterate over any bit:
|
||||
for i in 0..high(r.b):
|
||||
if r.b[i] != 0: # test all bits for zero
|
||||
for j in 0..BitsPerUnit-1:
|
||||
if testBit(r.b[i], j):
|
||||
yield i*BitsPerUnit+j
|
||||
of rnLeafLinear:
|
||||
var r = cast[ptr TRadixNodeLeafLinear](r)
|
||||
for i in 0..ze(r.len)-1:
|
||||
yield ze(r.keys[i])
|
||||
else: assert(false)
|
||||
|
||||
iterator elements*(r: PRadixNode): TAddress {.inline.} =
|
||||
for p1, n1 in innerElements(r):
|
||||
for p2, n2 in innerElements(n1):
|
||||
for p3, n3 in innerElements(n2):
|
||||
for p4 in leafElements(n3):
|
||||
yield p1 shl 24 or p2 shl 16 or p3 shl 8 or p4
|
||||
|
||||
proc main() =
|
||||
const
|
||||
numbers = [128, 1, 2, 3, 4, 255, 17, -8, 45, 19_000]
|
||||
var
|
||||
r: PRadixNode = nil
|
||||
for x in items(numbers):
|
||||
echo testOrIncl(r, x)
|
||||
for x in elements(r): echo(x)
|
||||
|
||||
main()
|
||||
|
||||
|
||||
when false:
|
||||
proc traverse(r: PRadixNode, prefix: int, d: int) =
|
||||
if r == nil: return
|
||||
case r.kind
|
||||
of rnLeafBits:
|
||||
assert(d == 0)
|
||||
var x = cast[ptr TRadixNodeLeafBits](r)
|
||||
# iterate over any bit:
|
||||
for i in 0..high(x.b):
|
||||
if x.b[i] != 0: # test all bits for zero
|
||||
for j in 0..BitsPerUnit-1:
|
||||
if testBit(x.b[i], j):
|
||||
visit(prefix or i*BitsPerUnit+j)
|
||||
of rnLeafLinear:
|
||||
assert(d == 0)
|
||||
var x = cast[ptr TRadixNodeLeafLinear](r)
|
||||
for i in 0..ze(x.len)-1:
|
||||
visit(prefix or ze(x.keys[i]))
|
||||
of rnFull:
|
||||
var x = cast[ptr TRadixNodeFull](r)
|
||||
for i in 0..high(r.b):
|
||||
if r.b[i] != nil:
|
||||
traverse(r.b[i], prefix or (i shl d), d-8)
|
||||
of rnLinear:
|
||||
var x = cast[ptr TRadixNodeLinear](r)
|
||||
for i in 0..ze(x.len)-1:
|
||||
traverse(x.vals[i], prefix or (ze(x.keys[i]) shl d), d-8)
|
||||
|
||||
type
|
||||
TRadixIter {.final.} = object
|
||||
r: PRadixNode
|
||||
p: int
|
||||
x: int
|
||||
|
||||
proc init(i: var TRadixIter, r: PRadixNode) =
|
||||
i.r = r
|
||||
i.x = 0
|
||||
i.p = 0
|
||||
|
||||
proc nextr(i: var TRadixIter): PRadixNode =
|
||||
if i.r == nil: return nil
|
||||
case i.r.kind
|
||||
of rnFull:
|
||||
var r = cast[ptr TRadixNodeFull](i.r)
|
||||
while i.x <= high(r.b):
|
||||
if r.b[i.x] != nil:
|
||||
i.p = i.x
|
||||
return r.b[i.x]
|
||||
inc(i.x)
|
||||
of rnLinear:
|
||||
var r = cast[ptr TRadixNodeLinear](i.r)
|
||||
if i.x < ze(r.len):
|
||||
i.p = ze(r.keys[i.x])
|
||||
result = r.vals[i.x]
|
||||
inc(i.x)
|
||||
else: assert(false)
|
||||
|
||||
proc nexti(i: var TRadixIter): int =
|
||||
result = -1
|
||||
case i.r.kind
|
||||
of rnLeafBits:
|
||||
var r = cast[ptr TRadixNodeLeafBits](i.r)
|
||||
# iterate over any bit:
|
||||
for i in 0..high(r.b):
|
||||
if x.b[i] != 0: # test all bits for zero
|
||||
for j in 0..BitsPerUnit-1:
|
||||
if testBit(x.b[i], j):
|
||||
visit(prefix or i*BitsPerUnit+j)
|
||||
of rnLeafLinear:
|
||||
var r = cast[ptr TRadixNodeLeafLinear](i.r)
|
||||
if i.x < ze(r.len):
|
||||
result = ze(r.keys[i.x])
|
||||
inc(i.x)
|
||||
|
||||
iterator elements(r: PRadixNode): TAddress {.inline.} =
|
||||
var
|
||||
a, b, c, d: TRadixIter
|
||||
init(a, r)
|
||||
while true:
|
||||
var x = nextr(a)
|
||||
if x != nil:
|
||||
init(b, x)
|
||||
while true:
|
||||
var y = nextr(b)
|
||||
if y != nil:
|
||||
init(c, y)
|
||||
while true:
|
||||
var z = nextr(c)
|
||||
if z != nil:
|
||||
init(d, z)
|
||||
while true:
|
||||
var q = nexti(d)
|
||||
if q != -1:
|
||||
yield a.p shl 24 or b.p shl 16 or c.p shl 8 or q
|
||||
76
tests/tstrset.nim
Normal file
76
tests/tstrset.nim
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# test a simple yet highly efficient set of strings
|
||||
|
||||
type
|
||||
TRadixNodeKind = enum rnLinear, rnFull, rnLeaf
|
||||
PRadixNode = ptr TRadixNode
|
||||
TRadixNode = object
|
||||
kind: TRadixNodeKind
|
||||
TRadixNodeLinear = object of TRadixNode
|
||||
len: byte
|
||||
keys: array [0..31, char]
|
||||
vals: array [0..31, PRadixNode]
|
||||
TRadixNodeFull = object of TRadixNode
|
||||
b: array [char, PRadixNode]
|
||||
TRadixNodeLeaf = object of TRadixNode
|
||||
s: string
|
||||
PRadixNodeLinear = ref TRadixNodeLinear
|
||||
PRadixNodeFull = ref TRadixNodeFull
|
||||
PRadixNodeLeaf = ref TRadixNodeLeaf
|
||||
|
||||
proc search(r: PRadixNode, s: string): PRadixNode =
|
||||
var r = r
|
||||
var i = 0
|
||||
while r != nil:
|
||||
case r.kind
|
||||
of rnLinear:
|
||||
var x = PRadixNodeLinear(r)
|
||||
for j in 0..x.len-1:
|
||||
if x.keys[j] == s[i]:
|
||||
if s[i] == '\0': return r
|
||||
r = x.vals[j]
|
||||
inc(i)
|
||||
break
|
||||
break # character not found
|
||||
of rnFull:
|
||||
var x = PRadixNodeFull(r)
|
||||
var y = x.b[s[i]]
|
||||
if s[i] == '\0':
|
||||
return if y != nil: r else: nil
|
||||
r = y
|
||||
inc(i)
|
||||
of rnLeaf:
|
||||
var x = PRadixNodeLeaf(r)
|
||||
var j = 0
|
||||
while true:
|
||||
if x.s[j] != s[i]: return nil
|
||||
if s[i] == '\0': return r
|
||||
inc(j)
|
||||
inc(i)
|
||||
|
||||
proc in_Operator*(r: PRadixNode, s: string): bool =
|
||||
return search(r, s) != nil
|
||||
|
||||
proc testOrincl*(r: var PRadixNode, s: string): bool =
|
||||
nil
|
||||
|
||||
proc incl*(r: var PRadixNode, s: string) = discard testOrIncl(r, s)
|
||||
|
||||
proc excl*(r: var PRadixNode, s: string) =
|
||||
x = search(r, s)
|
||||
if x == nil: return
|
||||
case x.kind
|
||||
of rnLeaf: PRadixNodeLeaf(x).s = ""
|
||||
of rnFull: PRadixNodeFull(x).b['\0'] = nil
|
||||
of rnLinear:
|
||||
var x = PRadixNodeLinear(x)
|
||||
for i in 0..x.len-1:
|
||||
if x.keys[i] == '\0':
|
||||
swap(x.keys[i], x.keys[x.len-1])
|
||||
dec(x.len)
|
||||
break
|
||||
|
||||
var
|
||||
root: PRadixNode
|
||||
|
||||
|
||||
|
||||
12
tests/tstrtabs.nim
Normal file
12
tests/tstrtabs.nim
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import strtabs
|
||||
|
||||
var tab = newStringTable(["key1", "val1", "key2", "val2"],
|
||||
modeStyleInsensitive)
|
||||
for i in 0..80:
|
||||
tab["key_" & $i] = "value" & $i
|
||||
|
||||
for key, val in pairs(tab):
|
||||
writeln(stdout, key, ": ", val)
|
||||
writeln(stdout, "length of table ", $tab.len)
|
||||
|
||||
writeln(stdout, `%`("$key1 = $key2; ${PATH}", tab, {useEnvironment}))
|
||||
Loading…
Add table
Add a link
Reference in a new issue