Merge pull request #1075 from flaviut/inlinedocs

Add some documentations and code examples in system
This commit is contained in:
Andreas Rumpf
2014-04-09 22:56:18 +02:00
71 changed files with 2521 additions and 15 deletions

1
bin/empty.txt Normal file
View File

@@ -0,0 +1 @@
This file keeps several tools from deleting this subdirectory.

1
build/empty.txt Normal file
View File

@@ -0,0 +1 @@
This file keeps several tools from deleting this subdirectory.

View File

@@ -302,7 +302,7 @@ type
## value does not fit.
EOutOfRange* = object of ESynch ## is raised if a range check error
## occured.
## occurred.
EStackOverflow* = object of ESystem ## is raised if the hardware stack
## used for subroutine calls overflowed.
@@ -534,6 +534,10 @@ proc `div` *(x, y: int32): int32 {.magic: "DivI", noSideEffect.}
proc `div` *(x, y: int64): int64 {.magic: "DivI64", noSideEffect.}
## computes the integer division. This is roughly the same as
## ``floor(x/y)``.
## .. code-block:: Nimrod
## 1 div 2 == 0
## 2 div 2 == 1
## 3 div 2 == 1
proc `mod` *(x, y: int): int {.magic: "ModI", noSideEffect.}
proc `mod` *(x, y: int8): int8 {.magic: "ModI", noSideEffect.}
@@ -549,6 +553,10 @@ proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.}
proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.}
proc `shr` *(x, y: int64): int64 {.magic: "ShrI64", noSideEffect.}
## computes the `shift right` operation of `x` and `y`.
## .. code-block:: Nimrod
## 0b0001_0000'i8 shr 2 == 0b0100_0000'i8
## 0b1000_0000'i8 shr 2 == 0b0000_0000'i8
## 0b0000_0001'i8 shr 9 == 0b0000_0000'i8
proc `shl` *(x, y: int): int {.magic: "ShlI", noSideEffect.}
proc `shl` *(x, y: int8): int8 {.magic: "ShlI", noSideEffect.}
@@ -741,15 +749,49 @@ proc contains*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.}
## passes its arguments in reverse order.
proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
## Checks if `value` is withing the range of `s`; returns true iff
## `value >= s.a and value <= s.b`
##
## .. code-block:: Nimrod
## assert((1..3).contains(1) == true)
## assert((1..3).contains(2) == true)
## assert((1..3).contains(4) == false)
result = s.a <= value and value <= s.b
template `in` * (x, y: expr): expr {.immediate.} = contains(y, x)
## Suger for contains
##
## .. code-block:: Nimrod
## assert(1 in (1..3) == true)
## assert(5 in (1..3) == false)
template `notin` * (x, y: expr): expr {.immediate.} = not contains(y, x)
## Sugar for not containing
##
## .. code-block:: Nimrod
## assert(1 notin (1..3) == false)
## assert(5 notin (1..3) == true)
proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
## Checks if T is of the same type as S
##
## .. code-block:: Nimrod
## proc test[T](a: T): int =
## when (T is int):
## return a
## else:
## return 0
##
## assert(test[int](3) == 3)
## assert(test[string]("xyz") == 0)
template `isnot` *(x, y: expr): expr {.immediate.} = not (x is y)
## Negated version of `is`. Equivalent to `not(is(x,y))`
proc `of` *[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.}
## Checks if `x` has a type of `y`
##
## .. code-block:: Nimrod
## assert(EFloatingPoint is EBase)
## assert(EIO is ESystem)
## assert(EDivByZero is EBase)
proc cmp*[T](x, y: T): int {.procvar.} =
## Generic compare proc. Returns a value < 0 iff x < y, a value > 0 iff x > y
@@ -800,19 +842,48 @@ proc newStringOfCap*(cap: int): string {.
proc `&` * (x: string, y: char): string {.
magic: "ConStrStr", noSideEffect, merge.}
## Concatenates `x` with `y`
##
## .. code-block:: Nimrod
## assert("ab" & 'c' == "abc")
proc `&` * (x: char, y: char): string {.
magic: "ConStrStr", noSideEffect, merge.}
## Concatenates `x` and `y` into a string
##
## .. code-block:: Nimrod
## assert('a' & 'b' == "ab")
proc `&` * (x, y: string): string {.
magic: "ConStrStr", noSideEffect, merge.}
## Concatenates `x` and `y`
##
## .. code-block:: Nimrod
## assert("ab" & "cd" == "abcd")
proc `&` * (x: char, y: string): string {.
magic: "ConStrStr", noSideEffect, merge.}
## is the `concatenation operator`. It concatenates `x` and `y`.
## Concatenates `x` with `y`
##
## .. code-block:: Nimrod
## assert('a' & "bc" == "abc")
# implementation note: These must all have the same magic value "ConStrStr" so
# that the merge optimization works properly.
proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
## Appends `y` to `x` in place
##
## .. code-block:: Nimrod
## var tmp = ""
## tmp.add('a')
## tmp.add('b')
## assert(tmp == "ab")
proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
## Concatenates `x` and `y` in place
##
## .. code-block:: Nimrod
## var tmp = ""
## tmp.add("ab")
## tmp.add("cd")
## assert(tmp == "abcd")
type
TEndian* = enum ## is a type describing the endianness of a processor.
@@ -922,9 +993,9 @@ const
## failure.
var programResult* {.exportc: "nim_program_result".}: int
## modify this varialbe to specify the exit code of the program
## modify this variable to specify the exit code of the program
## under normal circumstances. When the program is terminated
## prematurelly using ``quit``, this value is ignored.
## prematurely using ``quit``, this value is ignored.
proc quit*(errorcode: int = QuitSuccess) {.
magic: "Exit", importc: "exit", header: "<stdlib.h>", noReturn.}
@@ -1281,42 +1352,42 @@ template `>%` *(x, y: expr): expr {.immediate.} = y <% x
## Returns true iff ``unsigned(x) > unsigned(y)``.
proc `$` *(x: int): string {.magic: "IntToStr", noSideEffect.}
## The stingify operator for an integer argument. Returns `x`
## The stringify operator for an integer argument. Returns `x`
## converted to a decimal string.
proc `$` *(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
## The stingify operator for an integer argument. Returns `x`
## The stringify operator for an integer argument. Returns `x`
## converted to a decimal string.
when not defined(NimrodVM):
when not defined(JS) and hostOS != "standalone":
proc `$` *(x: uint64): string {.noSideEffect.}
## The stingify operator for an unsigned integer argument. Returns `x`
## The stringify operator for an unsigned integer argument. Returns `x`
## converted to a decimal string.
proc `$` *(x: float): string {.magic: "FloatToStr", noSideEffect.}
## The stingify operator for a float argument. Returns `x`
## The stringify operator for a float argument. Returns `x`
## converted to a decimal string.
proc `$` *(x: bool): string {.magic: "BoolToStr", noSideEffect.}
## The stingify operator for a boolean argument. Returns `x`
## The stringify operator for a boolean argument. Returns `x`
## converted to the string "false" or "true".
proc `$` *(x: char): string {.magic: "CharToStr", noSideEffect.}
## The stingify operator for a character argument. Returns `x`
## The stringify operator for a character argument. Returns `x`
## converted to a string.
proc `$` *(x: cstring): string {.magic: "CStrToStr", noSideEffect.}
## The stingify operator for a CString argument. Returns `x`
## The stringify operator for a CString argument. Returns `x`
## converted to a string.
proc `$` *(x: string): string {.magic: "StrToStr", noSideEffect.}
## The stingify operator for a string argument. Returns `x`
## The stringify operator for a string argument. Returns `x`
## as it is. This operator is useful for generic code, so
## that ``$expr`` also works if ``expr`` is already a string.
proc `$` *[TEnum: enum](x: TEnum): string {.magic: "EnumToStr", noSideEffect.}
## The stingify operator for an enumeration argument. This works for
## The stringify operator for an enumeration argument. This works for
## any enumeration type thanks to compiler magic. If
## a ``$`` operator for a concrete enumeration is provided, this is
## used instead. (In other words: *Overwriting* is possible.)
@@ -1436,7 +1507,11 @@ proc max*(x, y: float): float {.magic: "MaxF64", noSideEffect.} =
{.pop.}
proc clamp*[T](x, a, b: T): T =
## limits the value ``x`` within the interval [a, b]
## limits the value ``x`` within the interval [a, b]
##
## .. code-block:: Nimrod
## assert((1.4).clamp(0.0, 1.0) == 1.0)
## assert((0.5).clamp(0.0, 1.0) == 0.5)
if x < a: return a
if x > b: return b
return x
@@ -1535,6 +1610,11 @@ proc `@`*[T](a: openArray[T]): seq[T] =
for i in 0..a.len-1: result[i] = a[i]
proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect.} =
## Concatenates two sequences.
## Requires copying of the sequences.
##
## .. code-block:: Nimrod
## assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6])
newSeq(result, x.len + y.len)
for i in 0..x.len-1:
result[i] = x[i]
@@ -1542,12 +1622,22 @@ proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect.} =
result[i+x.len] = y[i]
proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect.} =
## Appends element y to the end of the sequence.
## Requires copying of the sequence
##
## .. code-block:: Nimrod
## assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4])
newSeq(result, x.len + 1)
for i in 0..x.len-1:
result[i] = x[i]
result[x.len] = y
proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} =
## Prepends the element x to the beginning of the sequence.
## Requires copying of the sequence
##
## .. code-block:: Nimrod
## assert(1 & @[2, 3, 4] == @[1, 2, 3, 4])
newSeq(result, y.len + 1)
result[0] = x
for i in 0..y.len-1:

1
tests/misc/99bottles.nim Normal file
View File

@@ -0,0 +1 @@
# Test if the compiler detects invalid module names

2
tests/misc/minit.nim Normal file
View File

@@ -0,0 +1,2 @@
# Test the new initialization for modules
write(stdout, "Hello from module! ")

6
tests/misc/mvarious.nim Normal file
View File

@@ -0,0 +1,6 @@
# Test a submodule
#type
# TStringArr = array [0.. *] of string
proc exportme* = discard

36
tests/misc/t99bott.nim Normal file
View File

@@ -0,0 +1,36 @@
discard """
file: "t99bott.nim"
line: 26
errormsg: "cannot evaluate at compile time: bn"
disabled: false
"""
## 99 Bottles of Beer
## http://www.99-bottles-of-beer.net/
## Nimrod version
## Author: Philippe Lhoste <PhiLho(a)GMX.net> http://Phi.Lho.free.fr
# 2012-11-25
# Loosely based on my old Lua version... Updated to current official lyrics.
proc GetBottleNumber(n: int): string =
var bs: string
if n == 0:
bs = "No more bottles"
elif n == 1:
bs = "1 bottle"
else:
bs = $n & " bottles"
return bs & " of beer"
for bn in countdown(99, 1):
const cur = GetBottleNumber(bn)
echo(cur, " on the wall, ", cur, ".")
echo("Take one down and pass it around, ", GetBottleNumber(bn-1),
" on the wall.\n")
echo "No more bottles of beer on the wall, no more bottles of beer."
echo "Go to the store and buy some more, 99 bottles of beer on the wall."

21
tests/misc/tack.nim Normal file
View File

@@ -0,0 +1,21 @@
discard """
file: "tack.nim"
output: "125"
"""
# the Ackermann function
proc ack(x, y: int): int =
if x != 0:
if y != 0:
return ack(x-1, ack(x, y-1))
return ack(x-1, 1)
else:
return y + 1
# if x == 0: return y + 1
# elif y == 0: return ack(x-1, 1)
# else: return ack(x-1, ack(x, y-1))
# echo(ack(0, 0))
write(stdout, ack(3, 4)) #OUT 125

12
tests/misc/tatomic.nim Normal file
View File

@@ -0,0 +1,12 @@
discard """
file: "tatomic.nim"
line: 7
errormsg: "identifier expected, but found 'keyword atomic'"
"""
var
atomic: int
echo atomic

16
tests/misc/tbug511622.nim Normal file
View File

@@ -0,0 +1,16 @@
discard """
file: "tbug511622.nim"
output: "3"
"""
import StrUtils, Math
proc FibonacciA(n: int): int64 =
var fn = float64(n)
var p: float64 = (1.0 + sqrt(5.0)) / 2.0
var q: float64 = 1.0 / p
return int64((pow(p, fn) + pow(q, fn)) / sqrt(5.0))
echo FibonacciA(4) #OUT 3

14
tests/misc/tcmdline.nim Normal file
View File

@@ -0,0 +1,14 @@
# Test the command line
import
os, strutils
var
i: int
params = paramCount()
i = 0
writeln(stdout, "This exe: " & getAppFilename())
writeln(stdout, "Number of parameters: " & $params)
while i <= params:
writeln(stdout, paramStr(i))
i = i + 1

View File

@@ -0,0 +1,12 @@
proc p(a, b: int, c: proc ()) =
c()
p(1, 3):
echo 1
echo 3
p(1, 1, proc() =
echo 1
echo 2)

16
tests/misc/tdllvar.nim Normal file
View File

@@ -0,0 +1,16 @@
import os
proc getDllName: string =
result = "mylib.dll"
if ExistsFile(result): return
result = "mylib2.dll"
if ExistsFile(result): return
quit("could not load dynamic library")
proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().}
proc myImport2(s: int) {.cdecl, importc, dynlib: getDllName().}
myImport("test2")
myImport2(12)

20
tests/misc/temit.nim Normal file
View File

@@ -0,0 +1,20 @@
discard """
file: "temit.nim"
output: "509"
"""
# Test the new ``emit`` pragma:
{.emit: """
static int cvariable = 420;
""".}
proc embedsC() =
var nimrodVar = 89
{.emit: """printf("%d\n", cvariable + (int)`nimrodVar`);""".}
embedsC()

View File

@@ -0,0 +1,2 @@
echo()

3
tests/misc/tendian.nim Normal file
View File

@@ -0,0 +1,3 @@
# test the new endian magic
writeln(stdout, repr(system.cpuEndian))

View File

@@ -0,0 +1,33 @@
discard """
output: "pie"
"""
import tables, lists
type
TEventArgs = object of TObject
TEventEmitter = object of TObject
events*: TTable[string, TDoublyLinkedList[proc(e: TEventArgs) {.nimcall.}]]
proc emit*(emitter: TEventEmitter, event: string, args: TEventArgs) =
for func in nodes(emitter.events[event]):
func.value(args) #call function with args.
proc on*(emitter: var TEventEmitter, event: string,
func: proc(e: TEventArgs) {.nimcall.}) =
if not hasKey(emitter.events, event):
var list: TDoublyLinkedList[proc(e: TEventArgs) {.nimcall.}]
add(emitter.events, event, list) #if not, add it.
append(emitter.events.mget(event), func)
proc initEmitter(emitter: var TEventEmitter) =
emitter.events = initTable[string,
TDoublyLinkedList[proc(e: TEventArgs) {.nimcall.}]]()
var
ee: TEventEmitter
args: TEventArgs
initEmitter(ee)
ee.on("print", proc(e: TEventArgs) = echo("pie"))
ee.emit("print", args)

48
tests/misc/tevents.nim Normal file
View File

@@ -0,0 +1,48 @@
discard """
file: "tevents.nim"
output: '''HandlePrintEvent: Output -> Handled print event
HandlePrintEvent2: Output -> printing for ME
HandlePrintEvent2: Output -> printing for ME'''
"""
import events
type
TPrintEventArgs = object of TEventArgs
user*: string
proc handleprintevent*(e: TEventArgs) =
write(stdout, "HandlePrintEvent: Output -> Handled print event\n")
proc handleprintevent2*(e: TEventArgs) =
var args: TPrintEventArgs = TPrintEventArgs(e)
write(stdout, "HandlePrintEvent2: Output -> printing for " & args.user)
var ee = initEventEmitter()
var eventargs: TPrintEventArgs
eventargs.user = "ME\n"
##method one test
ee.on("print", handleprintevent)
ee.on("print", handleprintevent2)
ee.emit("print", eventargs)
##method two test
type
TSomeObject = object of TObject
PrintEvent: TEventHandler
var obj: TSomeObject
obj.PrintEvent = initEventHandler("print")
obj.PrintEvent.addHandler(handleprintevent2)
ee.emit(obj.PrintEvent, eventargs)
obj.PrintEvent.removeHandler(handleprintevent2)
ee.emit(obj.PrintEvent, eventargs)

11
tests/misc/tfib.nim Normal file
View File

@@ -0,0 +1,11 @@
iterator fibonacci(): int =
var a = 0
var b = 1
while true:
yield a
var c = b
b = a
a = a + c

41
tests/misc/tfilter.nim Normal file
View File

@@ -0,0 +1,41 @@
discard """
output: "02468101214161820\n15"
"""
proc filter[T](list: seq[T], f: proc (item: T): bool {.closure.}): seq[T] =
result = @[]
for i in items(list):
if f(i):
result.add(i)
let nums = @[0, 1, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
when true:
let nums2 = filter(nums,
(proc (item: int): bool =
result = (item mod 2) == 0)
)
proc outer =
# lets use a proper closure this time:
var modulo = 2
let nums2 = filter(nums,
(proc (item: int): bool = result = (item mod modulo) == 0)
)
for n in nums2: stdout.write(n)
stdout.write("\n")
outer()
import math
proc compose[T](f1, f2: proc (x: T): T {.closure.}): proc (x: T): T {.closure.} =
result = (proc (x: T): T =
result = f1(f2(x)))
proc add5(x: int): int = result = x + 5
var test = compose(add5, add5)
echo test(5)

View File

@@ -0,0 +1,32 @@
discard """
file: "tgenconstraints.nim"
line: 25
disabled: true
errormsg: "cannot instantiate T2"
"""
type
T1[T: int|string] = object
x: T
T2[T: Ordinal] = object
x: T
var x1: T1[int]
var x2: T1[string]
var x3: T2[int]
proc foo[T](x: T): T2[T] {.discardable.} =
var o: T1[T]
foo(10)
# XXX: allow type intersections in situation like this
proc bar(x: int|TNumber): T1[type(x)] {.discardable.} =
when type(x) is TNumber:
var o: T2[type(x)]
bar "test"
bar 100
bar 1.1

View File

@@ -0,0 +1,7 @@
#
import times, os
var start = epochTime()
os.sleep(1000)
echo epochTime() - start #OUT 1000

51
tests/misc/tgtk.nim Normal file
View File

@@ -0,0 +1,51 @@
import
gtk2, glib2, atk, gdk2, gdk2pixbuf, libglade2, pango,
pangoutils
proc hello(widget: PWidget, data: pointer) {.cdecl.} =
write(stdout, "Hello World\n")
proc delete_event(widget: PWidget, event: PEvent,
data: pointer): bool {.cdecl.} =
# If you return FALSE in the "delete_event" signal handler,
# GTK will emit the "destroy" signal. Returning TRUE means
# you don't want the window to be destroyed.
# This is useful for popping up 'are you sure you want to quit?'
# type dialogs.
write(stdout, "delete event occurred\n")
# Change TRUE to FALSE and the main window will be destroyed with
# a "delete_event".
return false
# Another callback
proc mydestroy(widget: PWidget, data: pointer) {.cdecl.} =
gtk2.main_quit()
proc mymain() =
# GtkWidget is the storage type for widgets
gtk2.nimrod_init()
var window = window_new(gtk2.WINDOW_TOPLEVEL)
discard g_signal_connect(window, "delete_event",
Gcallback(delete_event), nil)
discard g_signal_connect(window, "destroy", Gcallback(mydestroy), nil)
# Sets the border width of the window.
set_border_width(window, 10)
# Creates a new button with the label "Hello World".
var button = button_new("Hello World")
discard g_signal_connect(button, "clicked", Gcallback(hello), nil)
# This packs the button into the window (a gtk container).
add(window, button)
# The final step is to display this newly created widget.
show(button)
# and the window
show(window)
gtk2.main()
mymain()

85
tests/misc/thallo.nim Normal file
View File

@@ -0,0 +1,85 @@
# Hallo
import
os, strutils, macros
type
TMyEnum = enum
meA, meB, meC, meD
when isMainModule:
{.hint: "this is the main file".}
proc fac[T](x: T): T =
# test recursive generic procs
if x <= 1: return 1
else: return x.`*`(fac(x-1))
macro macrotest(n: expr): stmt {.immediate.} =
let n = callsite()
expectKind(n, nnkCall)
expectMinLen(n, 2)
result = newNimNode(nnkStmtList, n)
for i in 2..n.len-1:
result.add(newCall("write", n[1], n[i]))
result.add(newCall("writeln", n[1], newStrLitNode("")))
macro debug(n: expr): stmt {.immediate.} =
let n = callsite()
result = newNimNode(nnkStmtList, n)
for i in 1..n.len-1:
result.add(newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
result.add(newCall("writeln", newIdentNode("stdout"), n[i]))
macrotest(stdout, "finally", 4, 5, "variable", "argument lists")
macrotest(stdout)
#GC_disable()
echo("This was compiled by Nimrod version " & system.nimrodVersion)
writeln(stdout, "Hello", " World", "!")
echo(["a", "b", "c", "d"].len)
for x in items(["What's", "your", "name", "?", ]):
echo(x)
var `name` = readLine(stdin)
{.breakpoint.}
echo("Hi " & thallo.name & "!\n")
debug(name)
var testseq: seq[string] = @[
"a", "b", "c", "d", "e"
]
echo(repr(testseq))
var dummy = "hello"
echo(substr(dummy, 2, 3))
echo($meC)
# test tuples:
for x, y in items([(1, 2), (3, 4), (6, 1), (5, 2)]):
echo x
echo y
proc simpleConst(): int = return 34
# test constant evaluation:
const
constEval3 = simpleConst()
constEval = "abc".contains('b')
constEval2 = fac(7)
echo(constEval3)
echo(constEval)
echo(constEval2)
echo(1.`+`(2))
for i in 2..6:
for j in countdown(i+4, 2):
echo(fac(i * j))
when isMainModule:
{.hint: "this is the main file".}

71
tests/misc/theaproots.nim Normal file
View File

@@ -0,0 +1,71 @@
type
Bar = object
x: int
Foo = object
rheap: ref Bar
rmaybe: ref Bar
rstack: ref Bar
list: seq[ref Bar]
listarr: array[0..5, ref Bar]
nestedtup: Tup
inner: TInner
inref: ref TInner
TInner = object
inref: ref Bar
Tup = tuple
tupbar: ref Bar
inner: TInner
proc acc(x: var Foo): var ref Bar =
result = x.rheap
proc test(maybeFoo: var Foo,
maybeSeq: var seq[ref Bar],
bars: var openarray[ref Bar],
maybeTup: var Tup) =
var bb: ref Bar
maybeFoo.rmaybe = bb
maybeFoo.list[3] = bb
maybeFoo.listarr[3] = bb
acc(maybeFoo) = bb
var localFoo: Foo
localFoo.rstack = bb
localFoo.list[3] = bb
localFoo.listarr[3] = bb
acc(localFoo) = bb
var heapFoo: ref Foo
heapFoo.rheap = bb
heapFoo.list[3] = bb
heapFoo.listarr[3] = bb
acc(heapFoo[]) = bb
heapFoo.nestedtup.tupbar = bb
heapFoo.nestedtup.inner.inref = bb
heapFoo.inner.inref = bb
heapFoo.inref.inref = bb
var locseq: seq[ref Bar]
locseq[3] = bb
var locarr: array[0..4, ref Bar]
locarr[3] = bb
maybeSeq[3] = bb
bars[3] = bb
maybeTup[0] = bb
var
ff: ref Foo
tt: Tup
gseq: seq[ref Bar]
new(ff)
test(ff[], gseq, gseq, tt)

12
tests/misc/thintoff.nim Normal file
View File

@@ -0,0 +1,12 @@
discard """
file: "thintoff.nim"
output: "0"
"""
{.hint[XDeclaredButNotUsed]: off.}
var
x: int
echo x #OUT 0

12
tests/misc/tinc.nim Normal file
View File

@@ -0,0 +1,12 @@
discard """
file: "tinc.nim"
line: 8
errormsg: "for a \'var\' type a variable needs to be passed"
"""
var x = 0
inc(x+1)

12
tests/misc/tinit.nim Normal file
View File

@@ -0,0 +1,12 @@
discard """
file: "tinit.nim"
output: "Hello from module! Hello from main module!"
"""
# Test the new init section in modules
import minit
write(stdout, "Hello from main module!\n")
#OUT Hello from module! Hello from main module!

16
tests/misc/tinout.nim Normal file
View File

@@ -0,0 +1,16 @@
discard """
file: "tinout.nim"
line: 12
errormsg: "for a \'var\' type a variable needs to be passed"
"""
# Test in out checking for parameters
proc abc(x: var int) =
x = 0
proc b() =
abc(3) #ERROR
b()

45
tests/misc/tints.nim Normal file
View File

@@ -0,0 +1,45 @@
discard """
file: "tints.nim"
output: "Success"
"""
# Test the different integer operations
var testNumber = 0
template test(opr, a, b, c: expr): stmt {.immediate.} =
# test the expression at compile and runtime
block:
const constExpr = opr(a, b)
when constExpr != c:
{.error: "Test failed " & $constExpr & " " & $c.}
inc(testNumber)
#Echo("Test: " & $testNumber)
var aa = a
var bb = b
var varExpr = opr(aa, bb)
assert(varExpr == c)
test(`+`, 12'i8, -13'i16, -1'i16)
test(`shl`, 0b11, 0b100, 0b110000)
test(`shl`, 0b11'i32, 0b100'i64, 0b110000'i64)
test(`shl`, 0b11'i32, 0b100'i32, 0b110000'i32)
test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16)
test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16)
test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0x0fffffffffffffff'i64)
test(`shr`, 0xffff'i16, 0x4'i16, 0x0fff'i16)
test(`shr`, 0xff'i8, 0x4'i8, 0x0f'i8)
test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64)
test(`shr`, 0xffffffff'i32, 0x4'i32, 0x0fffffff'i32)
test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64)
test(`shl`, 0xffff'i16, 0x4'i16, 0xfff0'i16)
test(`shl`, 0xff'i8, 0x4'i8, 0xf0'i8)
test(`shl`, 0xffffffff'i64, 0x4'i64, 0xffffffff0'i64)
test(`shl`, 0xffffffff'i32, 0x4'i32, 0xfffffff0'i32)
Echo("Success") #OUT Success

View File

@@ -0,0 +1,14 @@
discard """
errormsg: "index out of bounds"
line: 11
"""
type TTestArr = array[0..1, int16]
var f: TTestArr
f[0] = 30
f[1] = 40
f[2] = 50
f[3] = 60
echo(repr(f))

View File

@@ -0,0 +1,27 @@
discard """
file: "tinvalidnewseq.nim"
line: 15
errormsg: "type mismatch: got (array[0..6, string], int literal(7))"
"""
import re, strutils
type
TURL = tuple[protocol, subdomain, domain, port: string, path: seq[string]]
proc parseURL(url: string): TURL =
#([a-zA-Z]+://)?(\w+?\.)?(\w+)(\.\w+)(:[0-9]+)?(/.+)?
var pattern: string = r"([a-zA-Z]+://)?(\w+?\.)?(\w+)(\.\w+)(:[0-9]+)?(/.+)?"
var m: array[0..6, string] #Array with the matches
newSeq(m, 7) #ERROR
discard regexprs.match(url, re(pattern), m)
result = (protocol: m[1], subdomain: m[2], domain: m[3] & m[4],
port: m[5], path: m[6].split('/'))
var r: TUrl
r = parseUrl(r"http://google.com/search?var=bleahdhsad")
echo(r.domain)

18
tests/misc/tlastmod.nim Normal file
View File

@@ -0,0 +1,18 @@
# test the new LastModificationTime() proc
import
os, times, strutils
proc main() =
var
a, b: TTime
a = getLastModificationTime(ParamStr(1))
b = getLastModificationTime(ParamStr(2))
writeln(stdout, $a)
writeln(stdout, $b)
if a < b:
Write(stdout, "$2 is newer than $1\n" % [ParamStr(1), ParamStr(2)])
else:
Write(stdout, "$1 is newer than $2\n" % [ParamStr(1), ParamStr(2)])
main()

28
tests/misc/tlibs.nim Normal file
View File

@@ -0,0 +1,28 @@
discard """
disabled: true
"""
# Test wether the bindings at least compile...
import
unicode, cgi, terminal, libcurl,
parsexml, parseopt, parsecfg,
osproc, complex,
sdl, smpeg, sdl_gfx, sdl_net, sdl_mixer, sdl_ttf,
sdl_image, sdl_mixer_nosmpeg,
cursorfont, xatom, xf86vmode, xkb, xrandr, xshm, xvlib, keysym, xcms, xi,
xkblib, xrender, xutil, x, xf86dga, xinerama, xlib, xresource, xv,
gtk2, glib2, pango, gdk2,
cairowin32, cairoxlib,
odbcsql,
gl, glut, glu, glx, glext, wingl,
lua, lualib, lauxlib, mysql, sqlite3, python, tcl,
db_postgres, db_mysql, db_sqlite, ropes, sockets, browsers, httpserver,
httpclient, parseutils, unidecode, xmldom, xmldomparser, xmltree, xmlparser,
htmlparser, re, graphics, colors, pegs, subexes, dialogs
when defined(linux):
import
zlib, zipfiles
writeln(stdout, "test compilation of binding modules")

11
tests/misc/tlocals.nim Normal file
View File

@@ -0,0 +1,11 @@
discard """
output: "(x: string here, a: 1)"
"""
proc simple[T](a: T) =
var
x = "string here"
echo locals()
simple(1)

87
tests/misc/tloops.nim Normal file
View File

@@ -0,0 +1,87 @@
# Test nested loops and some other things
proc andTest() =
var a = 0 == 5 and 6 == 6
proc incx(x: var int) = # is built-in proc
x = x + 1
proc decx(x: var int) =
x = x - 1
proc First(y: var int) =
var x: int
i_ncx(x)
if x == 10:
y = 0
else:
if x == 0:
incx(x)
else:
x=11
proc TestLoops() =
var i, j: int
while i >= 0:
if i mod 3 == 0:
break
i = i + 1
while j == 13:
j = 13
break
break
while True:
break
proc Foo(n: int): int =
var
a, old: int
b, c: bool
F_irst(a)
if a == 10:
a = 30
elif a == 11:
a = 22
elif a == 12:
a = 23
elif b:
old = 12
else:
a = 40
#
b = false or 2 == 0 and 3 == 9
a = 0 + 3 * 5 + 6 + 7 + +8 # 36
while b:
a = a + 3
a = a + 5
write(stdout, "Hello!")
# We should come till here :-)
discard Foo(345)
# test the new type symbol lookup feature:
type
MyType[T] = tuple[
x, y, z: T]
MyType2 = tuple[x, y: float]
proc main[T]() =
var myType: MyType[T]
var b: MyType[T]
b = (1, 2, 3)
myType = b
echo myType
var myType2: MyType2
var c: MyType2
c = (1.0, 2.0)
myType2 = c
echo myType2
main[int]()

View File

@@ -0,0 +1,57 @@
discard """
cmd: "nimrod cc --hints:on -d:release $# $#"
"""
# -*- nimrod -*-
import math
import os
import strutils
type TComplex = tuple[re, im: float]
proc `+` (a, b: TComplex): TComplex =
return (a.re + b.re, a.im + b.im)
proc `*` (a, b: TComplex): TComplex =
result.re = a.re * b.re - a.im * b.im
result.im = a.re * b.im + a.im * b.re
proc abs2 (a: TComplex): float =
return a.re * a.re + a.im * a.im
var size = parseInt (paramStr (1))
var bit = 128
var byteAcc = 0
stdout.writeln ("P4")
stdout.write ($size)
stdout.write (" ")
stdout.writeln ($size)
var fsize = float (size)
for y in 0 .. size-1:
var fy = 2.0 * float (y) / fsize - 1.0
for x in 0 .. size-1:
var z = (0.0, 0.0)
var c = (float (2*x) / fsize - 1.5, fy)
block iter:
for i in 0 .. 49:
z = z*z + c
if abs2 (z) >= 4.0:
break iter
byteAcc = byteAcc + bit
if bit > 1:
bit = bit div 2
else:
stdout.write (chr (byteAcc))
bit = 128
byteAcc = 0
if bit != 128:
stdout.write (chr (byteAcc))
bit = 128
byteAcc = 0

View File

@@ -0,0 +1,17 @@
discard """
msg: "test 1\ntest 2\ntest 3"
output: "TEST 1\nTEST 2\nTEST 3"
"""
import strutils
proc foo(s: static[string]): string =
static: echo s
const R = s.toUpper
return R
echo foo("test 1")
echo foo("test 2")
echo foo("test " & $3)

View File

@@ -0,0 +1,20 @@
discard """
disabled: true
"""
type
PFutureBase = ref object
callback: proc () {.closure.}
proc newConnection =
iterator newConnectionIter(): PFutureBase {.closure.} =
discard
var newConnectionIterVar = newConnectionIter
var first = newConnectionIterVar()
proc cb {.closure.} =
discard
first.callback = cb
newConnection()

49
tests/misc/tnew.nim Normal file
View File

@@ -0,0 +1,49 @@
# Test the implementation of the new operator
# and the code generation for gc walkers
# (and the garbage collector):
type
PNode = ref TNode
TNode = object
data: int
str: string
le, ri: PNode
TStressTest = ref array [0..45, array [1..45, TNode]]
proc finalizer(n: PNode) =
write(stdout, n.data)
write(stdout, " is now freed\n")
proc newNode(data: int, le, ri: PNode): PNode =
new(result, finalizer)
result.le = le
result.ri = ri
result.data = data
# now loop and build a tree
proc main() =
var
i = 0
p: TStressTest
while i < 1000:
var n: PNode
n = newNode(i, nil, newNode(i + 10000, nil, nil))
inc(i)
new(p)
write(stdout, "Simple tree node allocation worked!\n")
i = 0
while i < 1000:
var m = newNode(i + 20000, nil, nil)
var k = newNode(i + 30000, nil, nil)
m.le = m
m.ri = k
k.le = m
k.ri = k
inc(i)
write(stdout, "Simple cycle allocation worked!\n")
main()

11
tests/misc/tnewderef.nim Normal file
View File

@@ -0,0 +1,11 @@
discard """
output: 3
"""
var x: ref int
new(x)
x[] = 3
echo x[]

21
tests/misc/tnewlibs.nim Normal file
View File

@@ -0,0 +1,21 @@
discard """
disabled: true
"""
# Test wether the bindings at least compile...
import
tcl,
sdl, smpeg, sdl_gfx, sdl_net, sdl_mixer, sdl_ttf,
sdl_image, sdl_mixer_nosmpeg,
gtk2, glib2, pango, gdk2,
unicode, cgi, terminal, libcurl,
parsexml, parseopt, parsecfg,
osproc,
cairowin32, cairoxlib,
gl, glut, glu, glx, glext, wingl,
lua, lualib, lauxlib, mysql, sqlite3, db_mongo, md5, asyncio, mimetypes,
cookies, events, ftpclient, scgi, irc
writeln(stdout, "test compilation of binding modules")

6
tests/misc/tnewsets.nim Normal file
View File

@@ -0,0 +1,6 @@
# new test for sets:
const elem = ' '
var s: set[char] = {elem}
assert(elem in s and 'a' not_in s and 'c' not_in s )

12
tests/misc/tnewuns.nim Normal file
View File

@@ -0,0 +1,12 @@
# test the new unsigned operations:
import
strutils
var
x, y: int
x = 1
y = high(int)
writeln(stdout, $ ( x +% y ) )

14
tests/misc/tnoforward.nim Normal file
View File

@@ -0,0 +1,14 @@
discard """
disabled: true
"""
{. noforward: on .}
proc foo(x: int) =
bar x
proc bar(x: int) =
echo x
foo(10)

16
tests/misc/tnoinst.nim Normal file
View File

@@ -0,0 +1,16 @@
discard """
line: 12
errormsg: "instantiate 'notConcrete' explicitly"
"""
proc wrap[T]() =
proc notConcrete[T](x, y: int): int =
var dummy: T
result = x - y
var x: proc (x, y: T): int
x = notConcrete
wrap[int]()

9
tests/misc/tnolen.nim Normal file
View File

@@ -0,0 +1,9 @@
discard """
line: 8
errormsg: "type mismatch: got (int literal(3))"
"""
# please finally disallow Len(3)
echo len(3)

12
tests/misc/tnoop.nim Normal file
View File

@@ -0,0 +1,12 @@
discard """
file: "tnoop.nim"
line: 11
errormsg: "expression \'a()\' cannot be called"
"""
# Tests the new check in the semantic pass
var
a: int
a() #ERROR_MSG expression 'a()' cannot be called

22
tests/misc/tnot.nim Normal file
View File

@@ -0,0 +1,22 @@
discard """
file: "tnot.nim"
line: 14
errormsg: "type mismatch"
"""
# BUG: following compiles, but should not:
proc nodeOfDegree(x: Int): bool =
result = false
proc main =
for j in 0..2:
for i in 0..10:
if not nodeOfDegree(1) >= 0: #ERROR_MSG type mismatch
Echo "Yes"
else:
Echo "No"
main()

4
tests/misc/tparedef.nim Normal file
View File

@@ -0,0 +1,4 @@
# This test is now superfluous:
proc a(a: int) =
return

35
tests/misc/tpos.nim Normal file
View File

@@ -0,0 +1,35 @@
discard """
file: "tpos.nim"
output: "6"
"""
# test this particular function
proc mypos(sub, s: string, start: int = 0): int =
var
i, j, M, N: int
M = sub.len
N = s.len
i = start
j = 0
if i >= N:
result = -1
else:
while True:
if s[i] == sub[j]:
Inc(i)
Inc(j)
else:
i = i - j + 1
j = 0
if (j >= M) or (i >= N): break
if j >= M:
result = i - M
else:
result = -1
var sub = "hello"
var s = "world hello"
write(stdout, mypos(sub, s))
#OUT 6

30
tests/misc/tprep.nim Normal file
View File

@@ -0,0 +1,30 @@
# Test the features that used to belong to the preprocessor
import
times
#{.warning: "This is only a test warning!".}
const
case2 = true
case3 = true
when defined(case1):
{.hint: "Case 1".}
when case3:
{.hint: "Case 1.3".}
elif case2:
{.hint: "Case 2".}
when case3:
{.hint: "Case 2.3".}
elif case3:
{.hint: "Case 3".}
else:
{.hint: "unknown case".}
var
s: string
write(stdout, "compiled at " & system.compileDate &
" " & compileTime & "\n")
echo getDateStr()
echo getClockStr()

26
tests/misc/tquicksort.nim Normal file
View File

@@ -0,0 +1,26 @@
proc QuickSort(list: seq[int]): seq[int] =
if len(list) == 0:
return @[]
var pivot = list[0]
var left: seq[int] = @[]
var right: seq[int] = @[]
for i in low(list)..high(list):
if list[i] < pivot:
left.add(list[i])
elif list[i] > pivot:
right.add(list[i])
result = QuickSort(left) &
pivot &
QuickSort(right)
proc echoSeq(a: seq[int]) =
for i in low(a)..high(a):
echo(a[i])
var
list: seq[int]
list = QuickSort(@[89,23,15,23,56,123,356,12,7,1,6,2,9,4,3])
echoSeq(list)

319
tests/misc/tradix.nim Normal file
View 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, inheritable.} = object
kind: TRadixNodeKind
TRadixNodeLinear = object of TRadixNode
len: int8
keys: array [0..31, int8]
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: int8
keys: array [0..31, int8]
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..ze(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..ze(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 contains*(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'i8
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..ze(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'i8
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

12
tests/misc/trawstr.nim Normal file
View File

@@ -0,0 +1,12 @@
discard """
file: "trawstr.nim"
line: 10
errormsg: "closing \" expected"
"""
# Test the new raw strings:
const
xxx = r"This is a raw string!"
yyy = "This not\" #ERROR

12
tests/misc/treadln.nim Normal file
View File

@@ -0,0 +1,12 @@
# test the improved readline handling that does not care whether its
# Macintosh, Unix or Windows text format.
var
inp: TFile
line: string
if open(inp, "readme.txt"):
while not EndOfFile(inp):
line = readLine(inp)
echo("#" & line & "#")
close(inp)

14
tests/misc/treadx.nim Normal file
View File

@@ -0,0 +1,14 @@
when not defined(windows):
import posix
var inp = ""
var buf: array[0..10, char]
while true:
var r = read(0, addr(buf), sizeof(buf)-1)
add inp, $buf
if r != sizeof(buf)-1: break
echo inp
#dafkladskölklödsaf ölksdakölfölksfklwe4iojr389wr 89uweokf sdlkf jweklr jweflksdj fioewjfsdlfsd

71
tests/misc/tromans.nim Normal file
View File

@@ -0,0 +1,71 @@
discard """
file: "tromans.nim"
output: "success"
"""
import
strutils
## Convert an integer to a Roman numeral
# See http://en.wikipedia.org/wiki/Roman_numerals for reference
proc raiseInvalidValue(msg: string) {.noreturn.} =
# Yes, we really need a shorthand for this code...
var e: ref EInvalidValue
new(e)
e.msg = msg
raise e
# I should use a class, perhaps.
# --> No. Why introduce additional state into such a simple and nice
# interface? State is evil. :D
proc RomanToDecimal(romanVal: string): int =
result = 0
var prevVal = 0
for i in countdown(romanVal.len - 1, 0):
var val = 0
case romanVal[i]
of 'I', 'i': val = 1
of 'V', 'v': val = 5
of 'X', 'x': val = 10
of 'L', 'l': val = 50
of 'C', 'c': val = 100
of 'D', 'd': val = 500
of 'M', 'm': val = 1000
else: raiseInvalidValue("Incorrect character in roman numeral! (" &
$romanVal[i] & ")")
if val >= prevVal:
inc(result, val)
else:
dec(result, val)
prevVal = val
proc DecimalToRoman(decValParam: int): string =
# Apparently numbers cannot be above 4000
# Well, they can be (using overbar or parenthesis notation)
# but I see little interest (beside coding challenge) in coding them as
# we rarely use huge Roman numeral.
const romanComposites = [
("M", 1000), ("CM", 900),
("D", 500), ("CD", 400), ("C", 100),
("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9),
("V", 5), ("IV", 4), ("I", 1)]
if decValParam < 1 or decValParam > 3999:
raiseInvalidValue("number not representable")
result = ""
var decVal = decValParam
for key, val in items(romanComposites):
while decVal >= val:
dec(decVal, val)
result.add(key)
for i in 1..100:
if RomanToDecimal(DecimalToRoman(i)) != i: quit "BUG"
for i in items([1238, 1777, 3830, 2401, 379, 33, 940, 3973]):
if RomanToDecimal(DecimalToRoman(i)) != i: quit "BUG"
echo "success" #OUT success

View File

@@ -0,0 +1,24 @@
type
TListItemType* = enum
RedisNil, RedisString
TListItem* = object
case kind*: TListItemType
of RedisString:
str*: string
else: nil
TRedisList* = seq[TListItem]
# Caused by this.
proc seq*() =
discard
proc lrange*(key: string): TRedisList =
var foo: TListItem
foo.kind = RedisNil
result = @[foo]
when isMainModule:
var p = lrange("mylist")
for i in items(p):
echo(i.str)

313
tests/misc/tsimplesort.nim Normal file
View File

@@ -0,0 +1,313 @@
discard """
output: '''true'''
"""
import hashes, math
when defined(shallowADT):
{.pragma: myShallow, shallow.}
else:
{.pragma: myShallow.}
type
TSlotEnum = enum seEmpty, seFilled, seDeleted
TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
TTable* {.final, myShallow.}[A, B] = object
data: TKeyValuePairSeq[A, B]
counter: int
proc len*[A, B](t: TTable[A, B]): int =
## returns the number of keys in `t`.
result = t.counter
iterator pairs*[A, B](t: TTable[A, B]): tuple[key: A, val: B] =
## iterates over any (key, value) pair in the table `t`.
for h in 0..high(t.data):
if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val)
iterator keys*[A, B](t: TTable[A, B]): A =
## iterates over any key in the table `t`.
for h in 0..high(t.data):
if t.data[h].slot == seFilled: yield t.data[h].key
iterator values*[A, B](t: TTable[A, B]): B =
## iterates over any value in the table `t`.
for h in 0..high(t.data):
if t.data[h].slot == seFilled: yield t.data[h].val
const
growthFactor = 2
proc mustRehash(length, counter: int): bool {.inline.} =
assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4)
proc nextTry(h, maxHash: THash): THash {.inline.} =
result = ((5 * h) + 1) and maxHash
template rawGetImpl() =
var h: THash = hash(key) and high(t.data) # start with real hash value
while t.data[h].slot != seEmpty:
if t.data[h].key == key and t.data[h].slot == seFilled:
return h
h = nextTry(h, high(t.data))
result = -1
template rawInsertImpl() =
var h: THash = hash(key) and high(data)
while data[h].slot == seFilled:
h = nextTry(h, high(data))
data[h].key = key
data[h].val = val
data[h].slot = seFilled
proc RawGet[A, B](t: TTable[A, B], key: A): int =
rawGetImpl()
proc `[]`*[A, B](t: TTable[A, B], key: A): B =
## retrieves the value at ``t[key]``. If `key` is not in `t`,
## default empty value for the type `B` is returned
## and no exception is raised. One can check with ``hasKey`` whether the key
## exists.
var index = RawGet(t, key)
if index >= 0: result = t.data[index].val
proc hasKey*[A, B](t: TTable[A, B], key: A): bool =
## returns true iff `key` is in the table `t`.
result = rawGet(t, key) >= 0
proc RawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B],
key: A, val: B) =
rawInsertImpl()
proc Enlarge[A, B](t: var TTable[A, B]) =
var n: TKeyValuePairSeq[A, B]
newSeq(n, len(t.data) * growthFactor)
for i in countup(0, high(t.data)):
if t.data[i].slot == seFilled: RawInsert(t, n, t.data[i].key, t.data[i].val)
swap(t.data, n)
template PutImpl() =
var index = RawGet(t, key)
if index >= 0:
t.data[index].val = val
else:
if mustRehash(len(t.data), t.counter): Enlarge(t)
RawInsert(t, t.data, key, val)
inc(t.counter)
proc `[]=`*[A, B](t: var TTable[A, B], key: A, val: B) =
## puts a (key, value)-pair into `t`.
putImpl()
proc del*[A, B](t: var TTable[A, B], key: A) =
## deletes `key` from hash table `t`.
var index = RawGet(t, key)
if index >= 0:
t.data[index].slot = seDeleted
dec(t.counter)
proc initTable*[A, B](initialSize=64): TTable[A, B] =
## creates a new hash table that is empty. `initialSize` needs to be
## a power of two.
assert isPowerOfTwo(initialSize)
result.counter = 0
newSeq(result.data, initialSize)
proc toTable*[A, B](pairs: openarray[tuple[key: A,
val: B]]): TTable[A, B] =
## creates a new hash table that contains the given `pairs`.
result = initTable[A, B](nextPowerOfTwo(pairs.len+10))
for key, val in items(pairs): result[key] = val
template dollarImpl(): stmt =
if t.len == 0:
result = "{:}"
else:
result = "{"
for key, val in pairs(t):
if result.len > 1: result.add(", ")
result.add($key)
result.add(": ")
result.add($val)
result.add("}")
proc `$`*[A, B](t: TTable[A, B]): string =
## The `$` operator for hash tables.
dollarImpl()
# ------------------------------ count tables -------------------------------
type
TCountTable* {.final, myShallow.}[
A] = object ## table that counts the number of each key
data: seq[tuple[key: A, val: int]]
counter: int
proc len*[A](t: TCountTable[A]): int =
## returns the number of keys in `t`.
result = t.counter
iterator pairs*[A](t: TCountTable[A]): tuple[key: A, val: int] =
## iterates over any (key, value) pair in the table `t`.
for h in 0..high(t.data):
if t.data[h].val != 0: yield (t.data[h].key, t.data[h].val)
iterator keys*[A](t: TCountTable[A]): A =
## iterates over any key in the table `t`.
for h in 0..high(t.data):
if t.data[h].val != 0: yield t.data[h].key
iterator values*[A](t: TCountTable[A]): int =
## iterates over any value in the table `t`.
for h in 0..high(t.data):
if t.data[h].val != 0: yield t.data[h].val
proc RawGet[A](t: TCountTable[A], key: A): int =
var h: THash = hash(key) and high(t.data) # start with real hash value
while t.data[h].val != 0:
if t.data[h].key == key: return h
h = nextTry(h, high(t.data))
result = -1
proc `[]`*[A](t: TCountTable[A], key: A): int =
## retrieves the value at ``t[key]``. If `key` is not in `t`,
## 0 is returned. One can check with ``hasKey`` whether the key
## exists.
var index = RawGet(t, key)
if index >= 0: result = t.data[index].val
proc hasKey*[A](t: TCountTable[A], key: A): bool =
## returns true iff `key` is in the table `t`.
result = rawGet(t, key) >= 0
proc RawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]],
key: A, val: int) =
var h: THash = hash(key) and high(data)
while data[h].val != 0: h = nextTry(h, high(data))
data[h].key = key
data[h].val = val
proc Enlarge[A](t: var TCountTable[A]) =
var n: seq[tuple[key: A, val: int]]
newSeq(n, len(t.data) * growthFactor)
for i in countup(0, high(t.data)):
if t.data[i].val != 0: RawInsert(t, n, t.data[i].key, t.data[i].val)
swap(t.data, n)
proc `[]=`*[A](t: var TCountTable[A], key: A, val: int) =
## puts a (key, value)-pair into `t`. `val` has to be positive.
assert val > 0
PutImpl()
proc initCountTable*[A](initialSize=64): TCountTable[A] =
## creates a new count table that is empty. `initialSize` needs to be
## a power of two.
assert isPowerOfTwo(initialSize)
result.counter = 0
newSeq(result.data, initialSize)
proc toCountTable*[A](keys: openArray[A]): TCountTable[A] =
## creates a new count table with every key in `keys` having a count of 1.
result = initCountTable[A](nextPowerOfTwo(keys.len+10))
for key in items(keys): result[key] = 1
proc `$`*[A](t: TCountTable[A]): string =
## The `$` operator for count tables.
dollarImpl()
proc inc*[A](t: var TCountTable[A], key: A, val = 1) =
## increments `t[key]` by `val`.
var index = RawGet(t, key)
if index >= 0:
inc(t.data[index].val, val)
else:
if mustRehash(len(t.data), t.counter): Enlarge(t)
RawInsert(t, t.data, key, val)
inc(t.counter)
proc Smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
## returns the largest (key,val)-pair. Efficiency: O(n)
assert t.len > 0
var minIdx = 0
for h in 1..high(t.data):
if t.data[h].val > 0 and t.data[minIdx].val > t.data[h].val: minIdx = h
result.key = t.data[minIdx].key
result.val = t.data[minIdx].val
proc Largest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
## returns the (key,val)-pair with the largest `val`. Efficiency: O(n)
assert t.len > 0
var maxIdx = 0
for h in 1..high(t.data):
if t.data[maxIdx].val < t.data[h].val: maxIdx = h
result.key = t.data[maxIdx].key
result.val = t.data[maxIdx].val
proc sort*[A](t: var TCountTable[A]) =
## sorts the count table so that the entry with the highest counter comes
## first. This is destructive! You must not modify `t` afterwards!
## You can use the iterators `pairs`, `keys`, and `values` to iterate over
## `t` in the sorted order.
# we use shellsort here; fast enough and simple
var h = 1
while true:
h = 3 * h + 1
if h >= high(t.data): break
while true:
h = h div 3
for i in countup(h, high(t.data)):
var j = i
while t.data[j-h].val <= t.data[j].val:
var xyz = t.data[j]
t.data[j] = t.data[j-h]
t.data[j-h] = xyz
j = j-h
if j < h: break
if h == 1: break
const
data = {
"34": 123456, "12": 789,
"90": 343, "0": 34404,
"1": 344004, "2": 344774,
"3": 342244, "4": 3412344,
"5": 341232144, "6": 34214544,
"7": 3434544, "8": 344544,
"9": 34435644, "---00": 346677844,
"10": 34484, "11": 34474, "19": 34464,
"20": 34454, "30": 34141244, "40": 344114,
"50": 344490, "60": 344491, "70": 344492,
"80": 344497}
proc countTableTest1 =
var s = initTable[string, int](64)
for key, val in items(data): s[key] = val
var w: tuple[key: string, val: int] #type(otherCountTable.data[0])
var t = initCountTable[string]()
for k, v in items(data): t.inc(k)
for k in t.keys: assert t[k] == 1
t.inc("90", 3)
t.inc("12", 2)
t.inc("34", 1)
assert t.largest()[0] == "90"
t.sort()
var i = 0
for k, v in t.pairs:
case i
of 0: assert k == "90" and v == 4
of 1: assert k == "12" and v == 3
of 2: assert k == "34" and v == 2
else: break
inc i
countTableTest1()
echo true

12
tests/misc/tsimtych.nim Normal file
View File

@@ -0,0 +1,12 @@
discard """
file: "tsimtych.nim"
line: 10
errormsg: "type mismatch: got (bool) but expected \'string\'"
"""
# Test 2
# Simple type checking
var a: string
a = false #ERROR

10
tests/misc/tsizeof.nim Normal file
View File

@@ -0,0 +1,10 @@
# Test the sizeof proc
type
TMyRecord {.final.} = object
x, y: int
b: bool
r: float
s: string
write(stdout, sizeof(TMyRecord))

59
tests/misc/tslices.nim Normal file
View File

@@ -0,0 +1,59 @@
discard """
file: "tslices.nim"
output: '''456456
456456
456456
Zugr5nd
egerichtetd
verichtetd
'''
"""
# Test the new slices.
import strutils
var mystr = "Abgrund"
mystr[..1] = "Zu"
mystr[4..4] = "5"
type
TEnum = enum e1, e2, e3, e4, e5, e6
var myarr: array[TEnum, int] = [1, 2, 3, 4, 5, 6]
myarr[e1..e3] = myarr[e4..e6]
myarr[..e3] = myarr[e4..e6]
for x in items(myarr): stdout.write(x)
echo()
var myarr2: array[0..5, int] = [1, 2, 3, 4, 5, 6]
myarr2[0..2] = myarr2[3..5]
for x in items(myarr2): stdout.write(x)
echo()
var myseq = @[1, 2, 3, 4, 5, 6]
myseq[0..2] = myseq[-3.. -1]
for x in items(myseq): stdout.write(x)
echo()
echo mystr
mystr[4..4] = "u"
# test full replacement
mystr[.. -2] = "egerichtet"
echo mystr
mystr[0..2] = "ve"
echo mystr
var s = "abcdef"
s[1 .. -2] = "xyz"
assert s == "axyzf"

59
tests/misc/tsortdev.nim Normal file
View File

@@ -0,0 +1,59 @@
discard """
output: "done"
"""
import algorithm, strutils
proc cmpPlatforms(a, b: string): int =
if a == b: return 0
var dashes = a.split('-')
var dashes2 = b.split('-')
if dashes[0] == dashes2[0]:
if dashes[1] == dashes2[1]: return system.cmp(a,b)
case dashes[1]
of "x86":
return 1
of "x86_64":
if dashes2[1] == "x86": return -1
else: return 1
of "ppc64":
if dashes2[1] == "x86" or dashes2[1] == "x86_64": return -1
else: return 1
else:
return system.cmp(dashes[1], dashes2[1])
else:
case dashes[0]
of "linux":
return 1
of "windows":
if dashes2[0] == "linux": return -1
else: return 1
of "macosx":
if dashes2[0] == "linux" or dashes2[0] == "windows": return -1
else: return 1
else:
if dashes2[0] == "linux" or dashes2[0] == "windows" or
dashes2[0] == "macosx": return -1
else:
return system.cmp(a, b)
proc sorted[T](a: openArray[T]): bool =
result = true
for i in 0 .. < a.high:
if cmpPlatforms(a[i], a[i+1]) > 0:
echo "Out of order: ", a[i], " ", a[i+1]
result = false
proc main() =
var testData = @["netbsd-x86_64", "windows-x86", "linux-x86_64", "linux-x86",
"linux-ppc64", "macosx-x86-1058", "macosx-x86-1068"]
sort(testData, cmpPlatforms)
doAssert sorted(testData)
for i in 0..1_000:
main()
echo "done"

16
tests/misc/tstrace.nim Normal file
View File

@@ -0,0 +1,16 @@
# Test the new stacktraces (great for debugging!)
{.push stack_trace: on.}
proc recTest(i: int) =
# enter
if i < 10:
recTest(i+1)
else: # should printStackTrace()
var p: ptr int = nil
p[] = 12
# leave
{.pop.}
recTest(0)

23
tests/misc/tstrange.nim Normal file
View File

@@ -0,0 +1,23 @@
discard """
file: "tstrange.nim"
output: "hallo4"
"""
# test for extremely strange bug
proc ack(x: int, y: int): int =
if x != 0:
if y != 5:
return y
return x
return x+y
proc gen[T](a: T) =
write(stdout, a)
gen("hallo")
write(stdout, ack(5, 4))
#OUT hallo4

14
tests/misc/tstrdesc.nim Normal file
View File

@@ -0,0 +1,14 @@
var
x: array [0..2, int]
x = [0, 1, 2]
type
TStringDesc {.final.} = object
len, space: int # len and space without counting the terminating zero
data: array [0..0, char] # for the '\0' character
var
emptyString {.exportc: "emptyString".}: TStringDesc

26
tests/misc/tstrdist.nim Normal file
View File

@@ -0,0 +1,26 @@
# compute the edit distance between two strings
proc editDistance(a, b: string): int =
var
c: seq[int]
n = a.len
m = b.len
newSeq(c, (n+1)*(m+1))
for i in 0..n:
c[i*n] = i # [i,0]
for j in 0..m:
c[j] = j # [0,j]
for i in 1..n:
for j in 1..m:
var x = c[(i-1)*n + j]+1
var y = c[i*n + j-1]+1
var z: int
if a[i-1] == b[j-1]:
z = c[(i-1)*n + j-1]
else:
z = c[(i-1)*n + j-1]+1
c[(i-1)*n + (j-1)] = min(x,min(y,z))
return c[n*m]
write(stdout, editDistance("abc", "abd"))

64
tests/misc/tvarious.nim Normal file
View File

@@ -0,0 +1,64 @@
# Test various aspects
# bug #572
var a=12345678901'u64
var x = (x: 42, y: (a: 8, z: 10))
echo x.y
import
mvarious
type
PA = ref TA
PB = ref TB
TB = object
a: PA
TA = object
b: TB
x: int
proc getPA(): PA =
var
b: bool
b = not false
return nil
# bug #501
proc f(): int = 54
var
global: int
var
s: string
i: int
r: TA
r.b.a.x = 0
global = global + 1
exportme()
write(stdout, "Hallo wie heißt du? ")
write(stdout, getPA().x)
s = readLine(stdin)
i = 0
while i < s.len:
if s[i] == 'c': write(stdout, "'c' in deinem Namen gefunden\n")
i = i + 1
write(stdout, "Du heißt " & s)
# bug #544
when false:
# yay, fails again
type Bar [T; I:range] = array[I, T]
proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] =
when len(a) != 3:
# Error: constant expression expected
{.fatal:"Dimensions have to be 3".}
#...
block:
var a, b: Bar[int, 0..2]
discard foo(a, b)

41
tests/misc/tvarious1.nim Normal file
View File

@@ -0,0 +1,41 @@
discard """
file: "tlenopenarray.nim"
output: '''1
0
Whopie
12'''
"""
echo len([1_000_000]) #OUT 1
type
TArray = array[0..3, int]
TVector = distinct array[0..3, int]
proc `[]`(v: TVector; idx: int): int = TArray(v)[idx]
var v: TVector
echo v[2]
# bug #569
import queues
type
TWidget = object
names: TQueue[string]
var w = TWidget(names: initQueue[string]())
add(w.names, "Whopie")
for n in w.names: echo(n)
# bug #681
type TSomeRange = object
hour: range[0..23]
var value: string
var val12 = TSomeRange(hour: 12)
value = $(if val12.hour > 12: val12.hour - 12 else: val12.hour)
echo value

142
tests/misc/tvarnums.nim Normal file
View File

@@ -0,0 +1,142 @@
discard """
file: "tvarnums.nim"
output: "Success!"
"""
# Test variable length binary integers
import
strutils
type
TBuffer = array [0..10, int8]
proc toVarNum(x: int32, b: var TBuffer) =
# encoding: first bit indicates end of number (0 if at end)
# second bit of the first byte denotes the sign (1 --> negative)
var a = x
if x != low(x):
# low(int) is a special case,
# because abs() does not work here!
# we leave x as it is and use the check >% instead of >
# for low(int) this is needed and positive numbers are not affected
# anyway
a = abs(x)
# first 6 bits:
b[0] = toU8(ord(a >% 63'i32) shl 7 or (ord(x < 0'i32) shl 6) or (int(a) and 63))
a = a shr 6'i32 # skip first 6 bits
var i = 1
while a != 0'i32:
b[i] = toU8(ord(a >% 127'i32) shl 7 or (int(a) and 127))
inc(i)
a = a shr 7'i32
proc toVarNum64(x: int64, b: var TBuffer) =
# encoding: first bit indicates end of number (0 if at end)
# second bit of the first byte denotes the sign (1 --> negative)
var a = x
if x != low(x):
# low(int) is a special case,
# because abs() does not work here!
# we leave x as it is and use the check >% instead of >
# for low(int) this is needed and positive numbers are not affected
# anyway
a = abs(x)
# first 6 bits:
b[0] = toU8(ord(a >% 63'i64) shl 7 or (ord(x < 0'i64) shl 6) or int(a and 63))
a = a shr 6 # skip first 6 bits
var i = 1
while a != 0'i64:
b[i] = toU8(ord(a >% 127'i64) shl 7 or int(a and 127))
inc(i)
a = a shr 7
proc toNum64(b: TBuffer): int64 =
# treat first byte different:
result = ze64(b[0]) and 63
var
i = 0
Shift = 6'i64
while (ze(b[i]) and 128) != 0:
inc(i)
result = result or ((ze64(b[i]) and 127) shl Shift)
inc(Shift, 7)
if (ze(b[0]) and 64) != 0: # sign bit set?
result = not result +% 1
# this is the same as ``- result``
# but gives no overflow error for low(int)
proc toNum(b: TBuffer): int32 =
# treat first byte different:
result = ze(b[0]) and 63
var
i = 0
Shift = 6'i32
while (ze(b[i]) and 128) != 0:
inc(i)
result = result or ((int32(ze(b[i])) and 127'i32) shl Shift)
Shift = shift + 7'i32
if (ze(b[0]) and (1 shl 6)) != 0: # sign bit set?
result = (not result) +% 1'i32
# this is the same as ``- result``
# but gives no overflow error for low(int)
proc toBinary(x: int64): string =
result = newString(64)
for i in 0..63:
result[63-i] = chr((int(x shr i) and 1) + ord('0'))
proc t64(i: int64) =
var
b: TBuffer
toVarNum64(i, b)
var x = toNum64(b)
if x != i:
writeln(stdout, $i)
writeln(stdout, toBinary(i))
writeln(stdout, toBinary(x))
proc t32(i: int32) =
var
b: TBuffer
toVarNum(i, b)
var x = toNum(b)
if x != i:
writeln(stdout, toBinary(i))
writeln(stdout, toBinary(x))
proc tm(i: int32) =
var
b: TBuffer
toVarNum64(i, b)
var x = toNum(b)
if x != i:
writeln(stdout, toBinary(i))
writeln(stdout, toBinary(x))
t32(0)
t32(1)
t32(-1)
t32(-100_000)
t32(100_000)
t32(low(int32))
t32(high(int32))
t64(low(int64))
t64(high(int64))
t64(0)
t64(-1)
t64(1)
t64(1000_000)
t64(-1000_000)
tm(0)
tm(1)
tm(-1)
tm(-100_000)
tm(100_000)
tm(low(int32))
tm(high(int32))
writeln(stdout, "Success!") #OUT Success!