merged upstream master

This commit is contained in:
Zahary Karadjov 2013-01-27 23:41:45 +02:00
commit 81a3585872
127 changed files with 4440 additions and 1496 deletions

View file

@ -0,0 +1,8 @@
# module A
import mexportb
export mexportb.TMyObject, mexportb.xyz
export mexportb.q
proc `$`*(x: TMyObject): string = "my object"

View file

@ -0,0 +1,7 @@
# module B
type TMyObject* = object
const xyz* = 13
proc q*(x: int): int = 6
proc q*(x: string): string = "8"

View file

@ -0,0 +1,13 @@
import json, tables
proc run(json_params: TTable) =
let json_elems = json_params["files"].elems
# These fail compilation.
var files = map(json_elems, proc (x: PJsonNode): string = x.str)
#var files = json_elems.map do (x: PJsonNode) -> string: x.str
echo "Hey!"
when isMainModule:
let text = """{"files": ["a", "b", "c"]}"""
run(toTable((text.parseJson).fields))

View file

@ -0,0 +1,194 @@
import hashes, math
type
TSlotEnum = enum seEmpty, seFilled, seDeleted
TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
TOrderedKeyValuePair[A, B] = tuple[
slot: TSlotEnum, next: int, key: A, val: B]
TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]]
TOrderedTable*[A, B] = object ## table that remembers insertion order
data: TOrderedKeyValuePairSeq[A, B]
counter, first, last: int
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() {.dirty.} =
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() {.dirty.} =
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
template AddImpl() {.dirty.} =
if mustRehash(len(t.data), t.counter): Enlarge(t)
RawInsert(t, t.data, key, val)
inc(t.counter)
template PutImpl() {.dirty.} =
var index = RawGet(t, key)
if index >= 0:
t.data[index].val = val
else:
AddImpl()
proc len*[A, B](t: TOrderedTable[A, B]): int {.inline.} =
## returns the number of keys in `t`.
result = t.counter
template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
var h = t.first
while h >= 0:
var nxt = t.data[h].next
if t.data[h].slot == seFilled: yieldStmt
h = nxt
iterator pairs*[A, B](t: TOrderedTable[A, B]): tuple[key: A, val: B] =
## iterates over any (key, value) pair in the table `t` in insertion
## order.
forAllOrderedPairs:
yield (t.data[h].key, t.data[h].val)
iterator mpairs*[A, B](t: var TOrderedTable[A, B]): tuple[key: A, val: var B] =
## iterates over any (key, value) pair in the table `t` in insertion
## order. The values can be modified.
forAllOrderedPairs:
yield (t.data[h].key, t.data[h].val)
iterator keys*[A, B](t: TOrderedTable[A, B]): A =
## iterates over any key in the table `t` in insertion order.
forAllOrderedPairs:
yield t.data[h].key
iterator values*[A, B](t: TOrderedTable[A, B]): B =
## iterates over any value in the table `t` in insertion order.
forAllOrderedPairs:
yield t.data[h].val
iterator mvalues*[A, B](t: var TOrderedTable[A, B]): var B =
## iterates over any value in the table `t` in insertion order. The values
## can be modified.
forAllOrderedPairs:
yield t.data[h].val
proc RawGet[A, B](t: TOrderedTable[A, B], key: A): int =
rawGetImpl()
proc `[]`*[A, B](t: TOrderedTable[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 mget*[A, B](t: var TOrderedTable[A, B], key: A): var B =
## retrieves the value at ``t[key]``. The value can be modified.
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
var index = RawGet(t, key)
if index >= 0: result = t.data[index].val
else: raise newException(EInvalidKey, "key not found: " & $key)
proc hasKey*[A, B](t: TOrderedTable[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 TOrderedTable[A, B],
data: var TOrderedKeyValuePairSeq[A, B],
key: A, val: B) =
rawInsertImpl()
data[h].next = -1
if t.first < 0: t.first = h
if t.last >= 0: data[t.last].next = h
t.last = h
proc Enlarge[A, B](t: var TOrderedTable[A, B]) =
var n: TOrderedKeyValuePairSeq[A, B]
newSeq(n, len(t.data) * growthFactor)
var h = t.first
t.first = -1
t.last = -1
while h >= 0:
var nxt = t.data[h].next
if t.data[h].slot == seFilled:
RawInsert(t, n, t.data[h].key, t.data[h].val)
h = nxt
swap(t.data, n)
proc `[]=`*[A, B](t: var TOrderedTable[A, B], key: A, val: B) =
## puts a (key, value)-pair into `t`.
putImpl()
proc add*[A, B](t: var TOrderedTable[A, B], key: A, val: B) =
## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
AddImpl()
proc initOrderedTable*[A, B](initialSize=64): TOrderedTable[A, B] =
## creates a new ordered hash table that is empty. `initialSize` needs to be
## a power of two.
assert isPowerOfTwo(initialSize)
result.counter = 0
result.first = -1
result.last = -1
newSeq(result.data, initialSize)
proc toOrderedTable*[A, B](pairs: openarray[tuple[key: A,
val: B]]): TOrderedTable[A, B] =
## creates a new ordered hash table that contains the given `pairs`.
result = initOrderedTable[A, B](nextPowerOfTwo(pairs.len+10))
for key, val in items(pairs): result[key] = val
proc sort*[A, B](t: var TOrderedTable[A,B],
cmp: proc (x, y: tuple[key: A, val: B]): int {.closure.}) =
## sorts the ordered table so that the entry with the highest counter comes
## first. This is destructive (with the advantage of being efficient)!
## 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
#echo(t.data.len, " ", j, " - ", h)
#echo(repr(t.data[j-h]))
proc rawCmp(x, y: TOrderedKeyValuePair[A, B]): int =
if x.slot in {seEmpty, seDeleted} and y.slot in {seEmpty, seDeleted}:
return 0
elif x.slot in {seEmpty, seDeleted}:
return -1
elif y.slot in {seEmpty, seDeleted}:
return 1
else:
let item1 = (x.key, x.val)
let item2 = (y.key, y.val)
return cmp(item1, item2)
while rawCmp(t.data[j-h], t.data[j]) <= 0:
swap(t.data[j], t.data[j-h])
j = j-h
if j < h: break
if h == 1: break

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)

View file

@ -0,0 +1,17 @@
type
PMenu = ref object
PMenuItem = ref object
proc createMenuItem*(menu: PMenu, label: string,
action: proc (i: PMenuItem, p: pointer) {.cdecl.}) = nil
var s: PMenu
createMenuItem(s, "Go to definition...",
proc (i: PMenuItem, p: pointer) {.cdecl.} =
try:
echo(i.repr)
except EInvalidValue:
echo("blah")
)

10
tests/compile/texport.nim Normal file
View file

@ -0,0 +1,10 @@
discard """
output: "my object68"
"""
import mexporta
# B.TMyObject has been imported implicitly here:
var x: TMyObject
echo($x, q(0), q"0")

View file

@ -1,5 +1,6 @@
discard """
output: "1.0000000000000000e+00 10"
ccodecheck: "!@'ClEnv'"
"""
proc p[T](a, b: T): T

View file

@ -272,7 +272,7 @@ proc handleWebMessage(state: PState, line: string) =
message.add(limitCommitMsg(commit["message"].str))
# Send message to #nimrod.
state.ircClient[].privmsg(joinChans[0], message)
state.ircClient.privmsg(joinChans[0], message)
elif json.existsKey("redisinfo"):
assert json["redisinfo"].existsKey("port")
#let redisPort = json["redisinfo"]["port"].num
@ -336,10 +336,11 @@ proc hubConnect(state: PState) =
state.dispatcher.register(state.sock)
proc handleIrc(irc: var TAsyncIRC, event: TIRCEvent, state: PState) =
proc handleIrc(irc: PAsyncIRC, event: TIRCEvent, state: PState) =
case event.typ
of EvConnected: nil
of EvDisconnected:
while not state.ircClient[].isConnected:
while not state.ircClient.isConnected:
try:
state.ircClient.connect()
except:
@ -355,12 +356,12 @@ proc handleIrc(irc: var TAsyncIRC, event: TIRCEvent, state: PState) =
let msg = event.params[event.params.len-1]
let words = msg.split(' ')
template pm(msg: string): stmt =
state.ircClient[].privmsg(event.origin, msg)
state.ircClient.privmsg(event.origin, msg)
case words[0]
of "!ping": pm("pong")
of "!lag":
if state.ircClient[].getLag != -1.0:
var lag = state.ircClient[].getLag
if state.ircClient.getLag != -1.0:
var lag = state.ircClient.getLag
lag = lag * 1000.0
pm($int(lag) & "ms between me and the server.")
else:
@ -433,7 +434,7 @@ proc open(port: TPort = TPort(5123)): PState =
res.hubPort = port
res.hubConnect()
let hirc =
proc (a: var TAsyncIRC, ev: TIRCEvent) =
proc (a: PAsyncIRC, ev: TIRCEvent) =
handleIrc(a, ev, res)
# Connect to the irc server.
res.ircClient = AsyncIrc(ircServer, nick = botNickname, user = botNickname,

View file

@ -0,0 +1,21 @@
discard """
output: '''9
1
2
3
'''
"""
# Test the new overloading rules for iterators:
# test that iterator 'p' is preferred:
proc p(): seq[int] = @[1, 2, 3]
iterator p(): int = yield 9
for x in p(): echo x
# test that 'q' works in this position:
proc q(): seq[int] = @[1, 2, 3]
for x in q(): echo x

View file

@ -0,0 +1,14 @@
type
PButton = ref object
TButtonClicked = proc(button: PButton) {.nimcall.}
proc newButton*(onClick: TButtonClicked) =
nil
proc main() =
newButton(onClick = proc(b: PButton) =
var requestomat = 12
)
main()

View file

@ -0,0 +1,28 @@
type
TFoo = ref object of TObject
Data: int
TBar = ref object of TFoo
nil
TBar2 = ref object of TBar
d2: int
template super(self: TBar): TFoo = self
template super(self: TBar2): TBar = self
proc Foo(self: TFoo) =
echo "TFoo"
#proc Foo(self: TBar) =
# echo "TBar"
# Foo(super(self))
# works when this code is uncommented
proc Foo(self: TBar2) =
echo "TBar2"
Foo(super(self))
var b: TBar2
new(b)
Foo(b)

View file

@ -21,7 +21,7 @@ proc takeParseInt(x: proc (y: string): int {.noSideEffect.}): int =
result = x("123")
echo "Give a list of numbers (separated by spaces): "
var x = stdin.readline.split.each(parseInt).max
var x = stdin.readline.split.map(parseInt).max
echo x, " is the maximum!"
echo "another number: ", takeParseInt(parseInt)

View file

@ -0,0 +1,28 @@
type
TFoo = object
data: array[0..100, int]
TSecond = distinct TFoo
proc `[]` (self: var TFoo, x: int): var int =
return self.data[x]
proc `[]=` (self: var TFoo, x, y: int) =
# only `[]` returning a 'var T' seems to not work for now :-/
self.data[x] = y
proc second(self: var TFoo): var TSecond =
return TSecond(self)
proc `[]`(self: var TSecond, x: int): var int =
return TFoo(self).data[2*x]
var f: TFoo
for i in 0..f.data.high: f[i] = 2 * i
echo f.second[1]
#echo `second[]`(f,1)
# this is the only way I could use it, but not what I expected

View file

@ -1,7 +1,7 @@
# iterate over all files with a given filter:
import
os, times
"../../lib/pure/os.nim", ../../ lib / pure / times
proc main(filter: string) =
for filename in walkFiles(filter):