Created
May 26, 2017 17:12
-
-
Save Skrylar/5fcb92f9559e098a34d6229d310b3557 to your computer and use it in GitHub Desktop.
Horrendous failure trying to use template-based callbacks across module boundaries.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.; | |
^ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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