Skip to content

Instantly share code, notes, and snippets.

@Skrylar
Created May 26, 2017 17:12
Show Gist options
  • Save Skrylar/5fcb92f9559e098a34d6229d310b3557 to your computer and use it in GitHub Desktop.
Save Skrylar/5fcb92f9559e098a34d6229d310b3557 to your computer and use it in GitHub Desktop.
Horrendous failure trying to use template-based callbacks across module boundaries.
Hint: used config file '/etc/nim.cfg' [Conf]
Hint: system [Processing]
Hint: rectui [Processing]
Hint: sklist [Processing]
Hint: skrectangle [Processing]
Hint: sksigslot [Processing]
Hint: unittest [Processing]
Hint: macros [Processing]
Hint: os [Processing]
Hint: strutils [Processing]
Hint: parseutils [Processing]
Hint: math [Processing]
Hint: algorithm [Processing]
Hint: times [Processing]
Hint: posix [Processing]
Hint: terminal [Processing]
Hint: termios [Processing]
lib/nim/pure/unittest.nim(137, 14) Hint: 'setup' is declared but not used [XDeclaredButNotUsed]
lib/nim/pure/unittest.nim(141, 14) Hint: 'teardown' is declared but not used [XDeclaredButNotUsed]
lib/nim/pure/unittest.nim(145, 9) Hint: 'testInSuiteImplFlag' is declared but not used [XDeclaredButNotUsed]
lib/nim/pure/unittest.nim(138, 11) Hint: 'testSetupIMPLFlag' is declared but not used [XDeclaredButNotUsed]
lib/nim/pure/unittest.nim(141, 14) Hint: 'teardown' is declared but not used [XDeclaredButNotUsed]
lib/nim/pure/unittest.nim(145, 9) Hint: 'testInSuiteImplFlag' is declared but not used [XDeclaredButNotUsed]
CC: rectui
Error: execution of an external compiler program 'gcc -c -w -I/usr/lib/nim -o /SNIP/nimcache/rectui.o /SNIP/nimcache/rectui.c' failed with exit code: 1
/SNIP/nimcache/rectui.c: In function ‘orphan_YBQ8wOyQT0s4z2tyzXyKiw’:
/SNIP/nimcache/rectui.c:1063:39: error: expected identifier before ‘=’ token
HEX3Atmp_suQ9a19awdNETbH7FgPdHskg. = (*self0).receivingnewparent.;
^
/SNIP/nimcache/rectui.c:1064:38: error: expected identifier before ‘.’ token
HEX3Atmp_suQ9a19awdNETbH7FgPdHskg..ClEnv = (*self0).receivingnewparent..ClEnv;
^
/SNIP/nimcache/rectui.c:1065:38: error: expected identifier before ‘.’ token
HEX3Atmp_suQ9a19awdNETbH7FgPdHskg..ClPrc = (*self0).receivingnewparent..ClPrc;
^
/SNIP/nimcache/rectui.c:1066:39: error: expected identifier before ‘=’ token
HEX3Atmp_suQ9a19awdNETbH7FgPdHskg. = (*self0).receivingnewparent.;
^
import sksigslot
type
ReceivingNewParentProc*[T] = proc (self, parent: UiRectoid[T]) {.closure.}
ChildReceivingNewParentProc*[T] = proc (self, child, parent: UiRectoid[T]) {.closure.}
UiRectoid*[T] = ref object
child_receiving_new_parent*: Slot[ChildReceivingNewParentProc[T]] ## A child is being added or removed to this rectoid.
receiving_new_parent*: Slot[ReceivingNewParentProc[T]] ## This rectoid is being added or removed to something.
proc `parent=`*(self, other: UiRectoid) =
## Logically, this makes sense as an alternative invocation of
## add_child.
if other != nil:
other.add_child(self)
proc add_child*(self, other: UiRectoid) =
other.receiving_new_parent.emit(other, self)
when isMainModule:
import unittest
suite "Basic tree operations":
var a, b, c: UiRectoid[int]
test "Parenting signals":
var p_hat, c_hat = false
var parent_proc = proc(self, child, parent: UiRectoid[int]) =
p_hat = parent != nil
var child_proc = proc(self, parent: UiRectoid[int]) =
c_hat = parent != nil
c.parent = nil
c.receiving_new_parent.connect(child_proc)
a.child_receiving_new_parent.connect(parent_proc)
c.parent = a
check(p_hat == true)
check(c_hat == true)
c.parent = nil
check(p_hat == false)
check(c_hat == false)
type
SlotFlag* = enum
Blocked ## A signal is blocked, and does not emit signals.
SlotFlags* = set[SlotFlag]
Slot*[T] = object
flags: SlotFlags
first: T ## First-most event to call.
rest: seq[T] ## Remaining events to call.
const
DefaultSignalCount* = 8 ## How large the 'rest' field should be when it must be initialized.
proc connect*[T](self: var Slot[T], victim: T) =
## Connects a handler to a given slot.
if self.first == nil:
self.first = victim
elif self.rest == nil:
newSeq(self.rest, 1)
self.rest[0] = victim
else:
self.rest.add(victim)
proc disconnect_all*[T](self: var Slot[T]) =
## Removes all connections from a slot.
setLen(self.rest, 0)
self.first = nil
iterator connections*[T](self: Slot[T]): T =
## Returns each active connection associated with this slot.
if self.first != nil:
yield self.first
if self.rest != nil:
for x in self.rest:
if x != nil: yield x
proc blocked*[T](self: Slot[T]): bool =
## Checks if a slot has been blocked.
return Blocked in self.flags
proc `blocked=`*[T](self: var Slot[T], value: bool) =
## Sets whether a slot has been blocked. Blocked slots do not emit
## signals.
if value:
incl(self.flags, Blocked)
else:
excl(self.flags, Blocked)
template emit*[T](self: Slot[T]) =
if Blocked notin self.flags:
for slot in self.connections: slot()
template emit*[T](self: Slot[T], x: untyped) =
if Blocked notin self.flags:
for slot in self.connections: slot(x)
template emit*[T](self: Slot[T], x, y: untyped) =
if Blocked notin self.flags:
for slot in self.connections: slot(x, y)
template emit*[T](self: Slot[T], x, y, z: untyped) =
if Blocked notin self.flags:
for slot in self.connections: slot(x, y, z)
when isMainModule:
import unittest
suite "Signals and Slots":
test "Connect and fire one event":
var thing_done = false
var do_thing = proc() =
thing_done = true
check(thing_done == false)
var test_slot = Slot[proc() {.closure.}]()
test_slot.connect(do_thing)
test_slot.emit
check(thing_done == true)
test "Connect and block one event":
var thing_done = false
var do_thing = proc() =
thing_done = true
check(thing_done == false)
var test_slot = Slot[proc() {.closure.}]()
test_slot.blocked = true
test_slot.connect(do_thing)
test_slot.emit
check(thing_done == false)
test_slot.blocked = false
test_slot.emit
check(thing_done == true)
test "Connect and fire two events":
var thing_done = false
var another_thing_done = false
var do_thing = proc() =
thing_done = true
var do_another_thing = proc() =
another_thing_done = true
check(thing_done == false)
check(another_thing_done == false)
var test_slot = Slot[proc() {.closure.}]()
test_slot.connect(do_thing)
test_slot.connect(do_another_thing)
test_slot.emit
check(thing_done == true)
check(another_thing_done == true)
test "Connect and disconnect two events":
var thing_done = false
var another_thing_done = false
var do_thing = proc() =
thing_done = true
var do_another_thing = proc() =
another_thing_done = true
check(thing_done == false)
check(another_thing_done == false)
var test_slot = Slot[proc() {.closure.}]()
test_slot.connect(do_thing)
test_slot.connect(do_another_thing)
test_slot.disconnect_all
test_slot.emit
check(thing_done == false)
check(another_thing_done == false)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment