00:00:57 | Jehan_ | On the other hand, my diagnosis of the deadlock seems to be wrong, the wait should release the lock. |
00:07:23 | Jehan_ | Hmm, the deadlock situation is really puzzling. |
00:07:48 | Jehan_ | Even if I explicitly release the lock and sleep forever, the other thread can't seem to acquire it. |
00:12:47 | * | flaviu quit (Remote host closed the connection) |
00:15:02 | Araq | well it works fine when I uncomment the GC_unref here |
00:15:07 | Araq | no deadlock |
00:16:13 | onionhammer | dom96_ it looks like you use them for both request and respnse |
00:16:38 | Jehan_ | Araq: Yeah, I'm using a different example, and the deadlock actually may be due to the GC_unref, too. |
00:16:49 | Jehan_ | I still get a crash with it being commented out, I think. |
00:16:51 | onionhammer | dom96_ look at :649 |
00:17:11 | Araq | Jehan_: well it's not safe to simply remove it either |
00:17:17 | Araq | I'm fixing the codegen |
00:17:42 | dom96_ | onionhammer: perhaps, but if the user adds their own they should only add them once. |
00:17:45 | onionhammer | dom96_ then on line 211 you assign a diff one |
00:17:56 | onionhammer | yeah i dont disagree.. |
00:18:03 | dom96_ | so we need another field |
00:18:18 | onionhammer | you just shouldnt modify the httpclient object with the request |
00:18:24 | onionhammer | you should return a new object |
00:18:33 | dom96_ | huh? |
00:18:56 | dom96_ | the request proc shouldn't have the extraHeaders param |
00:19:07 | onionhammer | you're muddling httprequests and httpresponses |
00:19:09 | onionhammer | blurring the lines |
00:19:58 | dom96_ | oh, I see what you mean |
00:20:08 | onionhammer | you shouldnt modify the httpclient when you do a request, you should just return a Response object |
00:20:20 | Jehan_ | Ah, works now. I had an echo of an int in a finalizer, which was a bad idea. |
00:20:22 | dom96_ | request() already returns a Response obj |
00:20:30 | onionhammer | i kno |
00:20:35 | onionhammer | but why modify the httpclient |
00:20:50 | Araq | onionhammer: for performance. |
00:20:56 | Jehan_ | Araq: I still think you can discard the release/acquire around the wakeupWorkerToProcessQueue call. |
00:21:07 | Jehan_ | wait() will do a release implicitly. |
00:21:13 | onionhammer | Araq how does that improve performance |
00:21:15 | Araq | how so? |
00:21:28 | Araq | onionhammer: keeps GC pressure lower |
00:21:38 | onionhammer | result.headers = newStringTable(modeCaseInsensitive) |
00:21:49 | onionhammer | actually that is modifying the Response |
00:21:53 | onionhammer | not the client |
00:22:07 | Araq | onionhammer: note that I don't know the code at all |
00:22:41 | Araq | Jehan_: how does that help with the first loop iteration? |
00:22:53 | Araq | wakeup is called before wait |
00:23:20 | * | rpag joined #nimrod |
00:23:24 | Jehan_ | Araq: Yes, but what's the point of it? The reacquire will likely happen before the other thread has a chance to acquire the lock. |
00:23:42 | Jehan_ | So it'll block until the wait() call anyway. |
00:23:55 | onionhammer | dom96_ the more i look at it, the more i think that the headers field just needs to be public... |
00:24:32 | Jehan_ | It's essentially a pair of expensive noops. Granted, should be a path that's rarely ever taken, but then it's just noise. |
00:24:43 | onionhammer | the client header table isnt used in the respnse anywhere i can see |
00:24:46 | Araq | Jehan_: I still don't get wait, lol |
00:24:58 | Araq | it's simply to weird with that explicit lock |
00:25:10 | Jehan_ | wait atomically unlocks the mutex and suspends execution until it receives the signal. |
00:25:25 | Jehan_ | Then it atomically reacquires the mutex and resumes execution. |
00:25:58 | Jehan_ | The atomic unlock is important to avoid race conditions. |
00:26:17 | * | flaviu joined #nimrod |
00:29:06 | Araq | nah, it's totally weird. signal(foo); await(foo) is the intuitive way to do it. |
00:29:27 | Araq | the locking is an implementation detail |
00:29:46 | Jehan_ | Not when operating on shared state (well, not always). |
00:30:30 | Araq | the spurious wakeups too btw are an implementation detail |
00:30:42 | Araq | but we discussed this before |
00:30:52 | Jehan_ | Yup, they are, and an annoying one. |
00:31:11 | Jehan_ | But they greatly simplify the implementation, so it's become part of the spec. |
00:32:39 | Araq | so again, the acquire before the wait is redundant, right? |
00:32:57 | dom96_ | onionhammer: Hrm, I think you're correct. I thought `result.headers` referred to AsyncHttpClient.headers now Response.headers. Silly me. |
00:34:19 | Jehan_ | The pair of release + acquire. |
00:34:30 | dom96_ | onionhammer: So yeah, PR please if you can. |
00:34:35 | Jehan_ | That surround the wakeup call. |
00:34:42 | Araq | which release? |
00:34:46 | Araq | what? why? |
00:34:59 | Araq | oh |
00:35:01 | Araq | now I get it |
00:35:03 | Araq | ok |
00:36:11 | * | saml_ joined #nimrod |
00:36:18 | * | Joe_knock left #nimrod ("Leaving") |
00:38:45 | Jehan_ | Oh, and here's a good explanation for why a mutex is needed: http://stackoverflow.com/questions/2763714/why-do-pthreads-condition-variable-functions-require-a-mutex/2764003#2764003 |
00:42:46 | onionhammer | dom96_ you're gonna hate me |
00:43:08 | onionhammer | dom96_ i stripped all the extra whitespace after line endings :P |
00:44:17 | Araq | that's nice. but I still think if 'diff' somehow manages to treat my file as plaintext with line endings and stuff, it should be able to also ignore trailing whitespace. |
00:44:44 | dom96_ | onionhammer: that's fine. Github can diff without showing those I think |
00:45:04 | dom96_ | Aporia needs a "don't add extra whitespace" feature |
00:45:26 | Araq | but yeah yeah yeah, let's instead pretend it's 1960 and blame the programmer for not caring about it. |
00:46:33 | onionhammer | k |
00:49:38 | Araq | http://www.dinduks.com/why-are-trailing-whitespaces-bad/ |
00:50:18 | * | darkf joined #nimrod |
00:55:01 | NimBot | Araq/Nimrod devel 06e9932 Araq [+0 ±2 -0]: fixes exhaustion bug and missing GC_ref code generation |
00:55:12 | Araq | Jehan_: please review |
00:56:14 | Jehan_ | Araq: Okay, give me a second. |
00:56:23 | Araq | nah, take your time |
00:56:33 | Araq | I have to sleep now anyway |
00:56:47 | Araq | also somebody should really test awaitAny |
00:57:47 | Jehan_ | It's still sometimes hanging for me. |
00:58:24 | Jehan_ | On this code: https://gist.github.com/rbehrends/95b8b91275e3c97709c1 |
00:58:28 | Jehan_ | Only hangs sometimes. |
01:00:04 | Jehan_ | Not really sure yet what's causing it, but the changes that I'm seeing seem to make sense. |
01:00:12 | Jehan_ | So there's not an obvious bug here. |
01:00:43 | * | BitPuffin quit (Ping timeout: 244 seconds) |
01:04:30 | Araq | # wakeup other potentially waiting threads: |
01:04:32 | Araq | if waited: signal(q.empty) |
01:04:38 | Araq | is that even correct now? |
01:04:59 | Jehan_ | You mean, necessary? |
01:05:10 | Araq | that too |
01:05:40 | Jehan_ | Well, most likely it's going to be discarded. |
01:07:26 | Jehan_ | So, at most it's going to be a waste of clock cycles. :) |
01:07:26 | * | shodan45 joined #nimrod |
01:08:13 | Araq | well I confirm |
01:08:20 | Araq | hangs quite often in fact |
01:08:54 | Araq | but I think you need QueueSize >= #WorkerThreads |
01:09:00 | Jehan_ | Looking at it in gdb right now. |
01:09:10 | Araq | and the QueueSize is 2 to stress test it |
01:10:12 | Jehan_ | Hmm, I wonder if it has to do with the fact that main() is also a spawned task. |
01:10:46 | Araq | well it also hangs when I do: setMaxPoolSize 2 |
01:10:55 | Araq | so that's not the problem |
01:11:57 | Jehan_ | It's hanging in finished, for what it's worth. |
01:12:09 | Jehan_ | With all the other worker threads waiting for an incoming task. |
01:12:23 | Jehan_ | Anyhow, I need sleep. Will have to look at it tomorrow. |
01:12:30 | Jehan_ | Night! |
01:12:36 | * | Jehan_ quit (Quit: Leaving) |
01:12:42 | Araq | ok, same here, good night |
01:34:22 | * | brson quit (Ping timeout: 256 seconds) |
01:35:32 | * | fowl quit (Quit: Leaving) |
01:36:25 | * | clone1018__ quit (Ping timeout: 255 seconds) |
01:39:04 | * | brson joined #nimrod |
01:40:03 | * | clone1018_ joined #nimrod |
01:44:06 | * | superfunc joined #nimrod |
01:58:34 | * | AMorpork is now known as AFKMorpork |
02:12:19 | * | mko quit (Ping timeout: 245 seconds) |
02:36:42 | * | brson quit (Ping timeout: 265 seconds) |
02:47:46 | * | q66[lap] quit (Read error: Connection reset by peer) |
02:50:10 | * | q66[lap] joined #nimrod |
03:16:29 | * | q66 quit (Quit: Leaving) |
03:21:28 | * | flaviu quit (Ping timeout: 256 seconds) |
03:31:36 | * | boydgreenfield joined #nimrod |
03:31:38 | boydgreenfield | Is it possible to have a function in nim take a conditional branch based on the type of an argument? E.g., coerce a string into a cstring to pass to a C library, but coerce a cint into a pointer to pass to the same C function? |
03:32:21 | boydgreenfield | (Specifically trying to get a general wrapper for the setsockopt in the zero-mq nimrod wrapper, which treats everything as a string despite zeromq requiring that some option values be passed as integers: https://github.com/nimrod-code/nim-zmq/blob/master/zmq.nim) |
03:32:43 | * | boydgreenfield quit (Client Quit) |
03:34:10 | * | brson joined #nimrod |
03:35:17 | * | brson quit (Client Quit) |
03:35:35 | * | brson joined #nimrod |
03:43:40 | * | boydgreenfield joined #nimrod |
03:52:38 | * | superfunc quit (Quit: Connection closed for inactivity) |
03:57:14 | * | BitPuffin joined #nimrod |
04:01:15 | onionhammer | boydgreenfield i'd look at http://nimrod-lang.org/manual.html#typedesc |
04:01:22 | * | BitPuffin quit (Ping timeout: 240 seconds) |
04:02:51 | boydgreenfield | onionhammer: Ya, I’m looking at that. But can one if/else or case on a typdesc? |
04:03:00 | boydgreenfield | onionhammer: I may just be getting the syntax wrong.. |
04:04:40 | onionhammer | http://nimrod-lang.org/manual.html#type-operator |
04:07:17 | onionhammer | i believe i've seen what ur trying to do somewhere but cant find an example.. |
04:08:13 | boydgreenfield | onionhammer: Ok thanks. I’m basically trying to do: `if T is string: call_c_function_that_requires_a_string; elif T is cint: call_c_function_that_takes_a_pointer; else fail` |
04:08:17 | onionhammer | within a macro it's definitely possible |
04:08:34 | onionhammer | right, you can use the "is" operato |
04:08:35 | onionhammer | r |
04:24:13 | * | boydgreenfield quit (Quit: boydgreenfield) |
04:40:57 | * | tillzy joined #nimrod |
05:04:11 | * | boydgreenfield joined #nimrod |
05:16:36 | * | saml_ quit (Quit: Leaving) |
05:19:48 | boydgreenfield | onionhammer: Got it. Will try that. |
05:22:00 | * | brson quit (Ping timeout: 265 seconds) |
05:27:00 | * | johnsoft quit (Ping timeout: 250 seconds) |
05:27:38 | * | tillzy quit (Quit: tillzy) |
05:27:39 | * | johnsoft joined #nimrod |
05:29:17 | * | boydgreenfield quit (Quit: boydgreenfield) |
05:46:29 | * | Fran__ quit (Ping timeout: 245 seconds) |
05:50:41 | * | nande quit (Remote host closed the connection) |
06:04:01 | * | bjz joined #nimrod |
06:37:00 | * | kemet joined #nimrod |
06:39:14 | * | Fr4n joined #nimrod |
06:46:46 | * | xtagon quit (Quit: Leaving) |
06:47:18 | * | q66[lap] quit (Read error: Connection reset by peer) |
06:49:15 | * | q66[lap] joined #nimrod |
07:06:49 | * | kemet quit (Ping timeout: 265 seconds) |
07:54:45 | * | Trustable joined #nimrod |
08:09:10 | Araq | boydgreenfield: use 'when' instead of 'if'. 'when T is string' |
08:25:01 | * | rpag quit (Ping timeout: 272 seconds) |
08:34:47 | gokr | Good morning! |
08:46:53 | * | rpag joined #nimrod |
08:57:32 | * | q66 joined #nimrod |
09:44:37 | * | khmm joined #nimrod |
09:47:50 | * | BlaXpirit joined #nimrod |
09:48:25 | * | BlaXpirit quit (Client Quit) |
09:57:06 | * | q66[lap] quit (Read error: Connection reset by peer) |
09:57:50 | * | q66[lap] joined #nimrod |
10:10:11 | * | bjz quit (Read error: Connection reset by peer) |
10:10:27 | * | bjz joined #nimrod |
10:40:39 | * | khmm quit (Ping timeout: 245 seconds) |
10:43:55 | * | khmm joined #nimrod |
10:48:09 | * | khmm quit (Ping timeout: 245 seconds) |
10:54:02 | * | khmm joined #nimrod |
11:04:52 | * | Fr4n left #nimrod ("Leaving") |
11:24:07 | * | khmm quit (Ping timeout: 244 seconds) |
11:29:37 | * | khmm joined #nimrod |
11:36:46 | * | BitPuffin joined #nimrod |
11:38:38 | gokr | Btw, drone.io seems... quite easy to get started with - and its free for public projects it seems. |
11:39:16 | gokr | Also, drone is open source, I am going to try it I think. |
11:44:54 | NimBot | Araq/Nimrod devel f31c623 Erik O'Leary [+0 ±1 -0]: Made 'headers' public |
11:44:54 | NimBot | Araq/Nimrod devel 96d1543 Dominik Picheta [+0 ±1 -0]: Merge pull request #1639 from onionhammer/devel... 2 more lines |
11:55:11 | * | khmm_ joined #nimrod |
12:24:17 | woodgiraffe | How do you initialize an array[uint8, int] - i.e. an array holding int-values with uint8-index-type? |
12:27:50 | * | AFKMorpork is now known as AMorpork |
12:29:13 | * | Jehan_ joined #nimrod |
12:31:07 | * | khmm_ quit (Ping timeout: 245 seconds) |
12:31:41 | * | khmm quit (Ping timeout: 255 seconds) |
12:33:45 | * | Jehan_ quit (Ping timeout: 250 seconds) |
12:37:24 | * | BlaXpirit joined #nimrod |
12:44:08 | * | Jehan_ joined #nimrod |
12:44:41 | * | dom96_ quit (Ping timeout: 272 seconds) |
12:58:15 | * | q66[lap] quit (Read error: Connection reset by peer) |
12:59:20 | Araq | woodgiraffe: const|let|var foo: array[uint8, int] = [1, 2, 3 ... ] |
12:59:34 | Araq | followed by 256 elements, so good luck with that |
12:59:48 | Araq | however, you can use a macro to construct it |
13:00:20 | * | q66[lap] joined #nimrod |
13:00:25 | Araq | plus it's 0 initialized for you so if 0 is the value you need you don't need any initializer |
13:02:43 | woodgiraffe | Araq: ahhhh I get it, thanks |
13:04:16 | * | q66[lap] quit (Read error: Connection reset by peer) |
13:05:06 | * | khmm joined #nimrod |
13:05:40 | * | khmm_ joined #nimrod |
13:05:43 | * | q66[lap] joined #nimrod |
13:06:51 | * | khmm_ quit (Read error: Connection reset by peer) |
13:07:07 | * | BitPuffin quit (Ping timeout: 250 seconds) |
13:08:00 | * | Jehan_ quit (Quit: Leaving) |
13:09:06 | * | Jehan_ joined #nimrod |
13:10:37 | * | JehanII joined #nimrod |
13:10:37 | * | Jehan_ quit (Read error: Connection reset by peer) |
13:15:29 | * | JehanII quit (Ping timeout: 260 seconds) |
13:25:20 | * | saml_ joined #nimrod |
13:37:41 | * | Etheco joined #nimrod |
13:42:03 | * | kemet joined #nimrod |
13:44:27 | gokr | I noticed eventually that `..`in a for loop is actually not a Slice creation, but an alias for countup. So... is there any reason we don't have items() for Slices? |
13:44:59 | gokr | (after trying to play with woodgiraffe's uint8 miseries) |
13:50:56 | Araq | I never needed it |
13:51:57 | gokr | it would feel a bit more symmetrical. Like "var r = 0..255" and then later "for i in r: blabla" |
13:52:31 | Araq | yeah but then who writes var r = 0..255 |
13:52:44 | gokr | (and Smalltalk treats Intervals like iterables) |
13:54:30 | gokr | Well, I am not really certain how Slices are used. Perhaps they aren't "Intervals" but they seem to be. |
13:58:08 | Araq | yeah but they only exist because there are no ternary operators that can look like x in a..b |
13:58:24 | Araq | so we need to construct a..b separately |
13:58:35 | Araq | to get this nicely looking syntax |
13:59:29 | Araq | if you need more interval ops I think we should create an intervals module |
13:59:40 | Araq | as system.nim is already bloated |
14:00:46 | gokr | In Smalltalk Interval is actually a subclass of the abstract SequencableCollection - so they behave just like they do. Yeah. |
14:16:33 | * | gokr_ quit (Ping timeout: 258 seconds) |
14:20:23 | * | saml_ quit (Ping timeout: 240 seconds) |
14:28:01 | woodgiraffe | So > let si:int = 8'u < isn't covered by implicit conversions, how do I convert this explicitly? |
14:29:28 | woodgiraffe | Stupid question, toInt |
14:31:54 | woodgiraffe | Excuse me, toInt is only declared for float-parameters. |
14:33:36 | woodgiraffe | I guess casting here is fine? |
14:37:26 | gokr | let si:int = int(8'u) |
14:37:58 | gokr | It seems to me that... unsigned ints are... a bit of paria in Nim land. |
14:39:35 | woodgiraffe | gork: thanks |
14:39:37 | woodgiraffe | is int() a proc? |
14:39:49 | gokr | No, its a type conversion. |
14:40:26 | woodgiraffe | I see, it's part of random examples in the manual but never mentioned as such |
14:40:44 | gokr | http://nimrod-lang.org/manual.html#type-conversions |
14:41:19 | woodgiraffe | I already opened a ticket proposing enhancing that section |
14:41:38 | woodgiraffe | What's the idea behind not letting implicit conversion take care of unsigned <-> signed? |
14:42:49 | woodgiraffe | I suspect you won't notice by seeing a variables usage if it's signed? |
14:43:06 | woodgiraffe | int() seems fine, not too verbose |
14:45:31 | * | dom96_ joined #nimrod |
14:48:28 | NimBot | Araq/Nimrod devel 13e3c0d Dominik Picheta [+0 ±3 -0]: Implement SO_REUSEADDR for asyncnet and asynchttpserver. |
15:01:39 | woodgiraffe | I seem to fail to add two unsigned ints: http://ix.io/f5t |
15:04:48 | dom96_ | import unsigned |
15:04:49 | * | BitPuffin joined #nimrod |
15:05:11 | woodgiraffe | dom96_: much obliged |
15:05:55 | dom96_ | :) |
15:07:44 | * | khmm quit (Ping timeout: 265 seconds) |
15:11:54 | * | darkf quit (Quit: Leaving) |
15:20:58 | * | khmm joined #nimrod |
15:23:12 | woodgiraffe | Might help mentioning that in the manual, it currently isn't. |
15:25:21 | woodgiraffe | How is the policy on contributing to documentation anyway? - Can I just write a barely comprehensible small paragraph and create a PR for it? - Should I just create an issue? - Should I just mention it here? |
15:33:46 | dom96_ | If you only mention it here it may be ignored. |
15:33:59 | dom96_ | So create an issue. |
15:34:10 | dom96_ | I think the plan is to get rid of this unsigned module anyway. |
15:35:41 | woodgiraffe | Will do |
15:39:16 | * | kemet quit (Ping timeout: 256 seconds) |
15:41:18 | * | Jehan_ joined #nimrod |
15:57:39 | * | gokr_ joined #nimrod |
16:01:22 | * | untitaker quit (Ping timeout: 256 seconds) |
16:03:07 | * | khmm quit (Ping timeout: 255 seconds) |
16:06:25 | * | untitaker joined #nimrod |
16:16:15 | * | mko joined #nimrod |
16:29:03 | * | q66[lap] quit (Read error: Connection reset by peer) |
16:30:06 | * | q66[lap] joined #nimrod |
16:41:12 | * | q66[lap] quit (Read error: Connection reset by peer) |
16:41:53 | * | q66[lap] joined #nimrod |
16:47:37 | * | dom96_ quit (Ping timeout: 246 seconds) |
16:53:42 | * | BlaXpirit-UA joined #nimrod |
16:54:02 | * | BlaXpirit quit (Ping timeout: 245 seconds) |
17:17:59 | * | Matthias247 joined #nimrod |
17:20:12 | * | kemet joined #nimrod |
17:21:29 | * | johnsoft quit (Ping timeout: 250 seconds) |
17:22:05 | * | kemet quit (Client Quit) |
17:22:11 | * | johnsoft joined #nimrod |
17:23:45 | * | gokr_ quit (Ping timeout: 260 seconds) |
17:26:49 | * | dom96_ joined #nimrod |
17:29:48 | onionhammer | hmm |
17:30:00 | onionhammer | filter(toSeq items(), (x: int) => x mod 2 == 1) |
17:30:12 | onionhammer | where items() has type int |
17:30:28 | onionhammer | im getting an error but expected one of: |
17:30:30 | onionhammer | system.==(x: int, y: int): booly |
17:30:39 | onionhammer | -y |
17:30:54 | onionhammer | do notation works |
17:31:32 | dom96_ | gist the whole error |
17:34:49 | onionhammer | dom96_ https://gist.github.com/onionhammer/ac6c3d8cf06afd9b6354 |
17:35:18 | dom96 | Araq: have you updated the c sources correctly? |
17:36:16 | dom96 | echo filter(toSeq items(), (x: int) => (x mod 2 == 1)) |
17:38:30 | onionhammer | so just putting parens arond the x mod 2 == 1 part huh |
17:39:41 | dom96 | does it work? |
17:39:49 | onionhammer | yeah |
17:40:01 | onionhammer | kinda hacky though |
17:40:06 | dom96 | do you know why? |
17:40:59 | onionhammer | im guessing the == 1 part is left out of the right-hand expression passed to => |
17:41:13 | dom96 | yeah |
17:41:26 | onionhammer | but it shouldnt be |
17:41:29 | onionhammer | ideally |
17:42:10 | onionhammer | => should be greedy, but it's just a macro right now i guess.. |
17:42:37 | dom96 | yes |
17:42:53 | dom96 | something to talk to Araq about |
17:43:13 | onionhammer | yeah |
17:43:18 | onionhammer | alrght, next component |
17:43:21 | onionhammer | chaining a map after a filter |
17:43:43 | onionhammer | say that instead of "echo"ing the result of that filter |
17:43:51 | onionhammer | I save it to a variable |
17:43:55 | onionhammer | values.map(x => $x) |
17:43:58 | onionhammer | this gives another error |
17:44:13 | onionhammer | Error: type mismatch: got (seq[int], proc (GenericParam): auto) |
17:46:28 | dom96 | you probably need to specify the types explicitly |
17:47:54 | onionhammer | like how |
17:48:22 | onionhammer | oh |
17:48:39 | onionhammer | values.map((x: int) => $x) |
17:48:41 | onionhammer | that works.. |
17:50:38 | onionhammer | https://gist.github.com/onionhammer/8c4dd13e2f4a92ad8102 |
17:51:05 | onionhammer | seems flimsy, not robust |
17:51:25 | onionhammer | one missing explicit type or parenthesis and it stops compiling |
17:51:48 | onionhammer | weird that map needs the explicit type but filter doesnt |
17:52:42 | dom96 | Yeah. I'm not sure what we can do to improve that. |
17:52:55 | dom96 | type inference can be improved I hope |
17:53:07 | dom96 | and parenthesis should perhaps just be mandatory |
17:53:49 | onionhammer | that would have far reaching consequences |
17:54:23 | onionhammer | imo it would be cool if nims compiler could back out during compilation if the assumed AST structure didnt work |
17:54:26 | onionhammer | and try things another way |
17:54:31 | onionhammer | idk if thats even remotely feasible |
17:55:22 | onionhammer | i.e. values(x => 4 == 5), the AST might say "oh, this is (x => 4) == 5, send it to the compiler, the compiler says "no, try again" |
17:56:32 | dom96 | problem is that an `==` could be defined for those types |
17:56:36 | dom96 | and then you get unwanted behaviour |
17:57:51 | onionhammer | could be |
17:57:54 | onionhammer | but probably isnt |
17:58:01 | onionhammer | typically the compiler would just give up |
17:58:06 | onionhammer | and throw an error |
17:58:25 | dom96 | typically isn't good enough :P |
18:00:33 | onionhammer | or maybe a way for macros to give hints to the AST |
18:02:34 | onionhammer | or space invocations looking for an expression get everything til the end of the paren block or comma or semicolon |
18:02:58 | onionhammer | space invocation meaning.. "myProc arg1" vs. "myProc(arg1)" |
18:05:13 | onionhammer | meh idk, just speculation w/o araq to weigh in |
18:05:17 | onionhammer | afk |
18:48:20 | Araq | when dom96 introduced => we knew its precedence is wrong |
18:48:38 | Araq | I have no idea why that now means I should change operator precedences again |
18:49:14 | Araq | => is simply a language showoff thing like everything in the "future" module |
18:49:55 | Araq | it's fine to use it but don't complain my spec doesn't give a shit about it |
18:50:15 | dom96 | I disagree, it is NOT a showoff. |
18:50:28 | dom96 | I have spent the last 4 years asking for a syntax IN THE LANGUAGE for this. |
18:50:36 | dom96 | You said "Implement it as a macro, it'll be fine" |
18:50:49 | dom96 | Then zahary implemented the do notation, and now you're saying you don't give a shit about this? |
18:54:09 | Araq | again |
18:54:16 | Araq | the do notation has a purpose |
18:55:01 | Araq | => is just envy we're not haskell |
18:57:29 | dom96 | what is its purpose? |
18:59:44 | Araq | it allows to pass multiple different blocks to a macro |
18:59:46 | Araq | it allows to pass multiple different blocks to a macro |
18:59:48 | Araq | it allows to pass multiple different blocks to a macro |
18:59:49 | Araq | it allows to pass multiple different blocks to a macro |
18:59:51 | Araq | it allows to pass multiple different blocks to a macro |
18:59:52 | Araq | it allows to pass multiple different blocks to a macro |
19:00:07 | * | Araq feels like a broken record |
19:04:10 | dom96 | so it has multiple purposes. |
19:04:48 | dom96 | IMO it fails at what should be its primary purpose |
19:05:33 | dom96 | and should be replaced with => |
19:06:10 | dom96 | Implying that => has no purpose is just wrong. |
19:20:03 | * | brson joined #nimrod |
19:31:20 | Araq | ok, fine |
19:31:30 | Araq | I think I have a solution that's acceptable |
19:32:08 | onionhammer | araq not trying to fault anyone |
19:32:14 | onionhammer | just think it's something worth supporting |
19:45:14 | * | johnsoft quit (Ping timeout: 245 seconds) |
19:45:22 | * | johnsoft joined #nimrod |
19:50:03 | * | johnsoft quit (Ping timeout: 258 seconds) |
19:51:10 | * | johnsoft joined #nimrod |
19:53:53 | * | milosn quit (Ping timeout: 258 seconds) |
19:54:55 | * | milosn joined #nimrod |
20:03:02 | * | dom96_ quit (Ping timeout: 255 seconds) |
20:08:16 | * | q66[lap] quit (Read error: Connection reset by peer) |
20:08:54 | NimBot | Varriount/NimLime master 4693df6 Erik O'Leary [+0 ±2 -0]: Updated support for 'case' indenting |
20:08:59 | * | q66[lap] joined #nimrod |
20:28:50 | * | johnsoft quit (Ping timeout: 256 seconds) |
20:29:31 | * | johnsoft joined #nimrod |
20:36:20 | * | gokr_ joined #nimrod |
20:38:30 | gokr_ | I am with Dominik regarding importance of a good lightweight syntax for closures. |
20:38:56 | * | q66[lap] quit (Read error: Connection reset by peer) |
20:39:38 | * | q66[lap] joined #nimrod |
20:39:51 | * | johnsoft quit (Ping timeout: 265 seconds) |
20:39:59 | Jehan_ | Why is it that the compiler can't infer the result type of a procedure if the type is "void"? |
20:40:15 | * | johnsoft joined #nimrod |
20:42:11 | * | flaviu joined #nimrod |
20:45:07 | gokr_ | silly question, why not a less naked lambda syntax? |
20:48:35 | Jehan_ | gokr_: Honestly, my problem right now is that with the existing lambda syntax(es) I keep running into compiler errors. |
20:50:16 | Jehan_ | Rather than fiddling with a new syntax, I'd prioritize fixing the existing ones. |
20:51:19 | gokr_ | Personally I feel the do syntax is less appealing (smalltalker in me) and the one in future - I also noticed it has precedence issues. |
20:52:18 | Jehan_ | gokr_: I don't necessarily disagree, but having it work in the first place should take precedence over prettying it up. |
20:52:39 | gokr_ | I just know a good fluid short lambda syntax is important to me, and I suspect i am not alone. |
20:53:12 | * | mat3 joined #nimrod |
20:53:18 | mat3 | hello |
20:54:12 | Jehan_ | gokr_: No, you're not alone. But I see it as a cart before horse issue. |
20:59:20 | Jehan_ | If the compiler blows up, all the pretty syntax in the world doesn't fix that. |
20:59:53 | * | brson quit (Ping timeout: 250 seconds) |
21:04:35 | * | hopla joined #nimrod |
21:05:08 | hopla | hello all, is there any example of config/nimrod.cfg to use msvc on windows? |
21:05:39 | hopla | I would like to test my simd crap on windows + msvc |
21:08:44 | * | dom96 quit (Excess Flood) |
21:10:45 | * | dom96 joined #nimrod |
21:11:12 | hopla | I was going to only set cl as a compiler and use vsvars32.bat. Is that the usual way to use nimrod with msvc? |
21:12:09 | Jehan_ | hopla: No idea, I don't use Windows at all, let alone msvc. |
21:15:31 | mat3 | Sorry, I have not used MSVC since Windows 3.1. Probably Araq or other Windows users here can answer your question. By the way: What 'SIMD' crap have you done ? |
21:16:44 | hopla | mat3: It is just porting sse and the rest to nim. I would like to add decent support also for cpuid (if not done yet) and other useful x86 stuff |
21:17:44 | NimBot | Varriount/NimLime master 1f9e606 Erik O'Leary [+0 ±1 -0]: Fixed indent support for proc/type |
21:18:21 | hopla | OK. |
21:18:25 | mat3 | reads nice |
21:18:53 | hopla | just works with amd64 and vcvarall amd64. However, nimbase.h does not seem to like compilation to 32 bits target on a 64 bits win7 |
21:20:18 | mat3 | ok, I interpret 'crap' here in terms of Intel's SSE ISA |
21:22:10 | Jehan_ | hopla: You will need --cpu:i386 for that. |
21:22:35 | hopla | Jehan_: thanks |
21:23:59 | * | Ven joined #nimrod |
21:24:13 | hopla | mat3: not SPU ISA or altivec for sure but still useful :-) |
21:24:43 | Jehan_ | gokr_: With respect to lambda syntax, I think the => is mostly fine, it's just annoying that you have to write "-> void" because the compiler can't infer a void result. |
21:26:16 | gokr_ | and parens needed sometimes, and sometimes not. |
21:26:39 | Jehan_ | gokr_: I don't honestly the problem with using them everywhere. |
21:28:19 | mat3 | can someone give me an example of the lambda syntax ? |
21:28:53 | * | flaviu quit (Remote host closed the connection) |
21:30:22 | onionhammer | mat3 values.filter(x => x == 5) would fail to compile |
21:30:33 | Jehan_ | mat3: (x: int) => x +1; x => x + 1; x -> void => echo(x) |
21:30:34 | onionhammer | whereas values.filter(x => (x == 5)) would succeed |
21:30:46 | * | hopla quit (Ping timeout: 246 seconds) |
21:34:14 | mat3 | hmm, probably a problem because of operator equivalence |
21:37:11 | Jehan_ | mat3: Yeah, == and => have equal precedence. |
21:38:36 | Jehan_ | As I said, it's not a big deal in my book. |
21:44:06 | gokr | The reason I feel strongly on the subject is that closures are *everywhere* in Smalltalk code, and without a clean nice syntax it would not have been the success it is. |
21:46:02 | gokr | The syntax Dominik made is "naked" as it doesn't have any delimiters around it. Smalltalk has [:x :y | x+y ] |
21:46:52 | Jehan_ | gokr: I fully agree that syntactically lightweight inline closures are important. |
21:46:54 | gokr | Since Nim generally has () for calls - a naked syntax is of course perhaps more fitting. |
21:47:36 | gokr | As libraries grow - more and more would use closures, especially since this style is getting more and more popular given the explosion of Javascript, Clojure and whatnot. |
21:47:39 | Jehan_ | For what it's worth, there IS already the do syntax. |
21:48:07 | gokr | And... the do syntax. I personally don't really get it. I need to read up on what's so neat with it. :) |
21:48:30 | Jehan_ | Well, mostly the -> part is annoying. The rest is nice, though. |
21:49:08 | gokr | Well... what does it buy? Is it just not having to have a parenthesis at the end? Araq said something about macros and multiple closures. |
21:49:10 | Jehan_ | indentation is Nim's equivalent to "begin … end" in Pascal and "[…]" in Smalltalk. |
21:49:28 | Jehan_ | First of all, do: allows you to start an indented block. |
21:49:31 | gokr | I know, I get it. But ... it still feels to me like a bit of a hack. |
21:49:38 | Jehan_ | Which gets interpreted as a closure. |
21:49:43 | gokr | Just like it did in Ruby. But again, Smalltalker in me talking. |
21:50:14 | gokr | And yes, the -> etc in do-syntax... I will mix that up 1000 times until I learn it. |
21:50:28 | ldlework | Are we talking about Rust? |
21:50:31 | Jehan_ | I think the -> part needs to be fixed. |
21:50:35 | Jehan_ | ldlework: No, Nim. |
21:50:39 | ldlework | Oh |
21:50:51 | Jehan_ | Mostly, it's just something that can be inferred, so should really be optional. |
21:51:19 | gokr | Jehan_: I think I understand why it was made like it is - we want a ":" at the end - and then... having a ":" before return type looks odd. So then "->" was stuffed in there. |
21:51:28 | gokr | But... the result is IMHO confusing vs procs. |
21:51:32 | Jehan_ | gokr: Yeah. |
21:51:50 | gokr | And even more confusing with lambdas now having "->" also in the type signature. |
21:52:17 | gokr | Now... what was the thing with macros and do? |
21:52:28 | Jehan_ | gokr: Yeah, the problem is really having three different types of lambda syntax. |
21:52:38 | Jehan_ | Rather than settling on one and making it really convenient. |
21:52:56 | Jehan_ | Macros can use the do syntax for stmt parameters, too. |
21:54:08 | gokr | Thing is... we can't nest the "do-syntax" reasonably, or? |
21:54:25 | mat3 | I want to remark that both the syntax and semantic of Nim(rod) stands in tradition to Algol which philosophy forced structure by syntactical differentiation. Because of this implementing lambda operators as suggested can lead to more complexity and as such unexpected errors |
21:54:49 | mat3 | (at least in langauges as Nim) |
21:54:50 | Jehan_ | gokr: What do you mean by nesting it? |
21:54:51 | gokr | Perhaps you can, its just... it doesn't fly with my brain. I always felt it looked really odd in Ruby too when Ruby came about. |
21:55:22 | gokr | Well, in Smalltalk I can easily nest blocks. They are just expressions. Everything is. |
21:56:27 | gokr | I will have to experiment with do-syntax to grok it I guess. It just feels so ... is it just me feeling that you lose sight of what is what? |
21:57:54 | Jehan_ | gokr: Well, but you don't just nest them. You pretty much always pass them as an argument to a method. |
21:58:13 | mat3 | gokr: except in Smalltalk everything is an (at runtime modifiable) object so this language require only a minimal set of syntactical rules |
21:59:12 | gokr | Sure, I am not saying Nim needs to be like Smalltalk - just pointing at my experience of how it works there. |
21:59:24 | gokr | And that particular part in Smalltalk is very nice. |
22:00:17 | gokr | For the record, I really like the indentation style of Nim too. But perhaps its hard to combine it with very clean lambdas. |
22:00:21 | Jehan_ | gokr: But the thing is, you don't really nest blocks directly. You have a method call inside a block that has a block as an argument. |
22:01:14 | gokr | Sure, well, there are some variants on that, but I mean more ... syntactically. |
22:01:57 | gokr | x foo: [:x | x bar: [ hey ]] |
22:02:40 | gokr | Or even: x foo: [:x | [ x + 1]] |
22:02:50 | Jehan_ | x.foo do(x): x.bar do: hey() |
22:03:16 | Jehan_ | x.foo do(x): x + 1 |
22:03:27 | gokr | What? |
22:03:27 | Jehan_ | Well, except for the -> annoyance that I omitted. |
22:03:32 | gokr | That last one looks wrong |
22:04:10 | gokr | The block sent in to foo is a block that will return a block when called. |
22:04:28 | Jehan_ | Oops, didn't look at it closely. |
22:04:59 | gokr | It's not the same as: x foo: [:x | x + 1] |
22:05:10 | Jehan_ | Yeah, I skimmed over it. |
22:05:26 | gokr | And.... Are you sure that first code you wrote is correct? |
22:05:59 | Jehan_ | gokr: What would be wrong with it? |
22:06:17 | * | gokr checking language manual... |
22:07:23 | gokr | Just curious about the "do: hey()" - is that not actually a second closure argument to foo? |
22:07:54 | mat3 | gokr: because my Smalltalk knowledge is quite non existent (beside theory, and studying the sources of Little Smalltalk) can you please describe what your code example compute ? |
22:07:55 | Jehan_ | For that, the indentation would have to line up. |
22:08:27 | gokr | Well, its just "silly code". |
22:09:46 | gokr | The first one "x foo: [:x | x bar: [ hey ]]" means "call method foo on object x, with one lambda argument". |
22:10:29 | gokr | That lambda argument takes one param, and after "|" is the code, where it calls "bar" on the argument with another lambda as argument: "[ hey ]" |
22:11:33 | Jehan_ | For what it's worth, I tried it and the compiler accepts it, though there's a bug in the generated C code. |
22:12:12 | gokr | Now, having naked lambdas, or having do-syntax - IMHO they may be harder to use "pervasively" in nested levels. |
22:12:21 | gokr | Simply because its harder to see where they end and start. |
22:12:43 | mat3 | I see |
22:12:44 | gokr | Naked ones don't really fly that well unless inside a call. |
22:13:19 | gokr | And the do-syntax... well, I feel that the lambda being passed "fell out" of the parenthesis that delimits the arguments of the call. |
22:13:32 | gokr | So nesting them etc, hurts my eyes. |
22:13:57 | gokr | As I said - I am just trying to give some input from someone used to nest closures a LOT (Smalltalk). |
22:14:12 | gokr | A Lisper would probably have similar thoughts. |
22:14:32 | Jehan_ | That's fine, Lisp hurts my eyes. :) |
22:14:38 | gokr | Well, it hurts mine too. |
22:14:47 | Jehan_ | That said, I'm fine with Smalltalk, too, and don't really see the issues. |
22:14:51 | gokr | Because Lisp has IMHO too few syntactical elements. |
22:15:29 | gokr | Another silly example then |
22:16:05 | * | Ven quit (Quit: My MacBook has gone to sleep. ZZZzzz…) |
22:16:20 | gokr | Hmmm. |
22:18:14 | gokr | Bah, I will experiment a bit myself - and gotta get to bed anyway :) |
22:18:17 | gokr | gnite |
22:18:52 | * | bjz quit (Ping timeout: 265 seconds) |
22:19:38 | mat3 | in a concatenative language that example would simply be something like: [hey] bar x foo |
22:20:59 | mat3 | however, I do not think this would be readable for someone with background in languages like C |
22:23:40 | Araq | Jehan_: any idea where the deadlock comes from? |
22:23:53 | Jehan_ | Araq: Haven't had an opportunity to look at it yet. |
22:24:12 | Araq | well I think what I wrote might be wrong: |
22:24:17 | Jehan_ | I'll give it a closer look in a minute. |
22:24:23 | Araq | # Note that if this fails somebody else already woke up the thread so it's |
22:24:24 | Araq | # perfectly fine to do nothing. |
22:29:10 | Jehan_ | For what it's worth, the dirty read of w.q.len may also be wrong, though unlikely to trigger this bug. |
22:29:38 | Araq | well |
22:29:52 | Araq | if I echo "failed" when the CAS fails |
22:30:01 | Araq | that indeed only shows up when it deadlocks |
22:30:43 | Araq | hrm nope |
22:30:55 | Araq | sometimes it fails and doesn't deadlock |
22:33:23 | onionhammer | Jehan_ gokr, can you chain the "do" syntax cleanly though? |
22:34:21 | Jehan_ | onionhammer: Don't see a problem, other than the limitations with multiple do: parts in a call. |
22:36:39 | Jehan_ | Araq: There's a gap after the w.q.len check where the cas will fail, but the slave will already be past cleanFlowVars. |
22:36:56 | Jehan_ | Mostly, however, the whole communication logic is full of race conditions. |
22:37:29 | Jehan_ | You do a dirty write of w.ready and then it's anybody's guess whether cas will succeed or fail. |
22:37:53 | Jehan_ | Honestly, this is precisely what mutexes and condition variables are for. |
22:38:05 | Jehan_ | And trying to avoid them is just going to give you more bugs. |
22:39:13 | onionhammer | Jehan_ i'd be curious to see how you would write this https://gist.github.com/onionhammer/8c4dd13e2f4a92ad8102 |
22:46:40 | Jehan_ | let values = ((toSeq items()) |
22:46:40 | Jehan_ | .filter do (x) -> bool: x mod 2 == 1) |
22:46:40 | Jehan_ | .map do(x) -> string: "Num " & $x |
22:50:16 | onionhammer | doesnt copile |
22:50:17 | onionhammer | compile* |
22:50:28 | onionhammer | oh sorry, it does nm |
22:50:34 | onionhammer | had the wrong iterator name |
22:51:13 | * | dom96_ joined #nimrod |
22:51:34 | onionhammer | the only issue w/ that is the weird open and close parent |
22:51:36 | onionhammer | paren* |
22:51:45 | * | Matthias247 quit (Read error: Connection reset by peer) |
22:52:49 | onionhammer | Jehan_ for each level of chaining you need another () wrapper |
22:52:57 | onionhammer | which would look ugly as hell |
22:53:03 | Jehan_ | onionhammer: Yes. |
22:53:15 | Jehan_ | Or a let tmp = ... |
22:53:19 | mat3 | Araq: In (de facto standard) C you can get the address of a label and branch to it thought the 'goto' statement. Is this usage implementable in Nim ? |
22:56:34 | Araq | mat3: not really, we don't even have goto. but we do have .computedGoto |
22:56:58 | Araq | Jehan_: no, the 'cas' is much easier to understand than a condition variable |
22:57:07 | * | BitPuffin quit (Ping timeout: 272 seconds) |
22:57:09 | Araq | and I'm aware of the dirty ready writing |
22:57:21 | Araq | didn't wrap "atomicWrite" yet |
22:59:20 | mat3 | Araq: ok, how can I get the address of a procedure ? |
22:59:33 | Araq | you simple use the proc's name without () |
23:01:14 | mat3 | proc test (): ... var pTest : pointer = test <- this way ? |
23:01:38 | Araq | var pTest = test # let the compiler infere the type |
23:02:05 | Araq | var pTest = pointer(test) # if you really want 'pointer' |
23:02:46 | mat3 | that is nice, this way I can define an array of procedure pointers |
23:03:14 | Araq | yes, but take a look at .computedGoto |
23:03:35 | Araq | that's been designed for interpreter loops |
23:03:50 | Araq | and yes it duplicates the dispatching |
23:04:08 | * | saml quit (Quit: Leaving) |
23:04:33 | Araq | so unless the C compiler folds it back into a single dispatch, it's as good as it can be |
23:08:29 | mat3 | I want to implement dynamic super instructions, a transformation of bytecode into a stream of calls either subroutine-threaded or direct threaded. This requires knowing at least the address of the primitive routines and a way to execute it |
23:10:18 | mat3 | the last requirement is easy implementable in Nim by an external assembler routine (which would be the only CPU related dependence) |
23:10:40 | Araq | ok, I see |
23:11:00 | Araq | how do you handle the problem of keeping interesting stuff in registers then? |
23:11:54 | * | brson joined #nimrod |
23:12:24 | mat3 | the call routine backup registers (AMD64 conform CPU's have 16 of them for example) |
23:13:45 | mat3 | (one can misuse SSE registers for that purpose) |
23:14:10 | mat3 | or better the FPU registers (via MMX) |
23:14:57 | Varriount | gokr: One thing about drone.io - it doesn't appear to have windows builders. |
23:15:09 | mat3 | otherwise the call routine can create a temporary call frame, there are plenty possibilities |
23:16:46 | onionhammer | Varriount any idea how to get the de-indent pattern in nimlime to deindent after 2 empty lines? |
23:17:15 | Varriount | onionhammer: Can the pattern search previous lines? |
23:18:10 | onionhammer | dunno. |
23:18:18 | onionhammer | hard to find any documentation on it |
23:18:29 | onionhammer | might have to be done in python |
23:18:37 | Varriount | onionhammer: Look at textmate - that's what this stuff is based one. |
23:18:39 | Varriount | *on |
23:18:46 | onionhammer | at least to experiment w/ it and see if its worth having |
23:18:47 | * | Jehan_ quit (Quit: Leaving) |
23:18:52 | onionhammer | right, i know |
23:19:10 | mat3 | let's see: SPARC features register windows (no problem here), PPC features 32 registers (also no problem), MIPS (no problem), ARM (well, possible), 6502 (no problem because of zero-page addressing), Z80 (ok, because of a second register set) |
23:19:29 | * | mat3 thinks this would work well |
23:20:13 | Varriount | onionhammer: A regex to find two lines with equal whitespace would be something like... "(\s*)\n$1" |
23:20:57 | Varriount | Or wait, it would be "(\s*)\n$1\n" |
23:21:29 | onionhammer | just ^(\s*\n){2,} is what i was thinking |
23:22:00 | onionhammer | but that wont search the previous line |
23:22:34 | Varriount | onionhammer: Dedenting via python is a good fallback. The comment continuation code can be modified to do that. |
23:26:01 | onionhammer | i'll take a look at your code there and see how much it would be to implement |
23:26:16 | onionhammer | i really wish there were a better way to reload plugins |
23:28:27 | onionhammer | Varriount actually the double comment python stuff might be broken :\ |
23:29:00 | onionhammer | it seems to only insert a single-comment (#) on the next line |
23:29:14 | Araq | Varriount: what's the status of the buildbot? |
23:31:10 | * | BlaXpirit-UA quit (Quit: Quit Konversation) |
23:34:16 | * | Demos joined #nimrod |
23:35:49 | Varriount | Araq: I have the main build config 99% done, the other build configs aren't done yet though. |
23:40:09 | Araq | ok nice. when/where can I see the test results? |
23:41:46 | * | Jesin quit (Quit: Leaving) |
23:41:49 | onionhammer | Varriount im getting Stage 1 failure - 1 on line 83, command == "insert_snippet" instead of "insert" which your check is looking fo |
23:41:51 | onionhammer | r |
23:44:22 | * | Jesin joined #nimrod |
23:47:25 | Varriount | Araq: Well, I can install the buildbot master tonight, if you want me to install it on the vps |
23:48:02 | Varriount | onionhammer: The stages are the checks the plugin uses to determine if it needs to insert a line |
23:48:05 | * | mat3 left #nimrod (#nimrod) |
23:48:26 | Varriount | onionhammer: It looks in the undo/redo buffer at what the user has just done. |
23:49:02 | onionhammer | hm |
23:49:07 | onionhammer | well i cant get it to work right now |
23:49:12 | onionhammer | can you? |
23:49:29 | Varriount | onionhammer: Which version of sublime text are you using? |
23:49:55 | Araq | Varriount: yeah, please do that |
23:50:09 | Varriount | onionhammer: By the way, just checking something: When editing a python file, and pressing enter after a line with a comment, does a new comment appear for you? |
23:50:39 | Varriount | onionhammer: At the moment, getting the new buildbot up is my priority. After that I'll be happy to fix and expand the plugin. |
23:57:35 | * | q66[lap] quit (Read error: Connection reset by peer) |
23:58:17 | * | q66[lap] joined #nimrod |