00:30:11 | * | Bosc0p joined #nimrod |
00:30:16 | * | Boscop quit (Disconnected by services) |
00:30:18 | * | Bosc0p is now known as Boscop |
00:30:20 | * | Boscop quit (Changing host) |
00:30:20 | * | Boscop joined #nimrod |
00:30:45 | * | XAMPP quit (Quit: DE:AD:BE:EF:C0:FE Out) |
00:45:11 | * | XAMPP joined #nimrod |
01:02:49 | * | XAMPP quit (Remote host closed the connection) |
01:05:40 | * | XAMPP joined #nimrod |
02:01:30 | * | SchalaZeal joined #nimrod |
02:01:59 | SchalaZeal | I can't seem to find an unsigned assignment operator. |
02:14:26 | SchalaZeal | only the arithmetic ones |
03:08:12 | SchalaZeal | Thing is... what would I do if something needed to be byte aligned and expected an 8-bit unsigned value of........say......213? |
03:11:22 | Trixar_za | Oo |
03:11:35 | Trixar_za | Chrono Trigger? |
03:13:44 | SchalaZeal | ehe...yes |
03:14:44 | Trixar_za | Anyway, Araq is probably sleeping (it's like 4am there), so you'd probably get a faster answer on the forums: http://forum.nimrod-code.org/ |
03:14:51 | Trixar_za | Not sure what dom96 is doing though :P |
03:19:07 | SchalaZeal | posted... anyway... |
03:19:13 | SchalaZeal | thanks |
03:19:28 | * | SchalaZeal quit (Quit: Konversation terminated!) |
05:52:20 | * | llm joined #nimrod |
05:56:53 | * | llm quit (Client Quit) |
07:40:03 | * | _ponce is now known as ponce |
08:48:04 | * | Araq_ joined #nimrod |
08:58:23 | * | CodeBlock quit (Changing host) |
08:58:23 | * | CodeBlock joined #nimrod |
09:00:24 | * | Araq_ quit (Quit: ChatZilla 0.9.88.2 [Firefox 13.0.1/20120614114901]) |
09:36:03 | * | SchalaZeal joined #nimrod |
09:37:35 | SchalaZeal | Are cstrings null terminated? I don't quite comprehend how they work. |
09:43:54 | SchalaZeal | I'm just looking to see if there's an alternative to an array of characters because I want to have a non-terminated string to be able to put in a byte array |
10:36:44 | SchalaZeal | I think I get the point... probably equivalent to C's char* |
10:36:51 | SchalaZeal | gnight |
10:40:17 | * | SchalaZeal quit (Quit: Konversation terminated!) |
13:01:22 | * | Araq_ joined #nimrod |
14:00:29 | * | Araq_ quit (Quit: ChatZilla 0.9.88.2 [Firefox 13.0.1/20120614114901]) |
20:25:10 | Araq | ping zahary |
21:35:21 | zahary | yo |
21:43:20 | Araq | I got closures mostly working but there are ugly things ... |
21:45:28 | zahary | what kind of ugly things? |
21:45:30 | Araq | for a start you can mark an outer proc with {.closure.} but the implementation has a *hard* time with that |
21:45:52 | Araq | as there is no environment to pass around |
21:46:11 | Araq | and 'nil' is already used for conversions from 'nimcall' to 'closure' |
21:46:33 | Araq | I think I'll simply disallow it for outer procs |
21:47:27 | zahary | well, what is supposed to mean for outer proc anyway? |
21:48:04 | Araq | to have a hidden unused *env* parameter just like every other .closure proc |
21:48:19 | Araq | so that no implicit conversion is necessary |
21:48:20 | zahary | but why would I want that? |
21:48:28 | Araq | dunno |
21:48:38 | Araq | can't think of any use case either :D |
21:48:51 | Araq | but I wanted to ask you before going that way :D |
21:49:36 | Araq | ok, next problem: |
21:49:52 | zahary | :) I agree in disallowing it. this is in no way related to passing regular procs to closure params, right? |
21:51:16 | Araq | well no, passing nimcall to closure works |
21:52:00 | Araq | next problem: if I have a top level loop statement |
21:52:15 | Araq | and a 'variable' in the loop body, it's a global var |
21:52:49 | Araq | so the semantics are: "same location for each iteration" |
21:53:05 | Araq | but if the loop is in a proc and the variable is captured in a closure |
21:53:18 | Araq | the semantics are "new location for each iteration" |
21:53:39 | Araq | i.e. the closure allocation is done in the loop repeatedly |
21:53:51 | Araq | so we have a small inconsistency in the language here |
21:54:18 | Araq | I suppose it should be fixed by changing semantics of variables in top level loops |
21:54:49 | zahary | I see. this issue is indeed a bit unexpected. I remember there were another problem with the top level for loop's variables? maybe we can somehow compile them as local variables in the initModule function? |
21:55:09 | * | filwit joined #nimrod |
21:55:21 | filwit | hi folks |
21:58:19 | zahary | hi filwit. what's up? |
21:58:47 | filwit | not to much. just finishing up some stuff on my game project |
21:59:05 | filwit | :) |
21:59:10 | filwit | you? |
21:59:22 | Araq | zahary: it should be easy to make these vars local and make the code generator put them in main() |
21:59:40 | filwit | btw, you guys hear about Unity 3D game engine coming to Linux? |
21:59:57 | filwit | that's pretty sweet news |
22:01:28 | Araq | hi filwit, yes we know |
22:01:47 | Araq | I think you alread told us? :P |
22:02:21 | Araq | but if I have: |
22:02:24 | filwit | couldn't have. just announced this morning :) |
22:02:28 | zahary | filwit, are you developing a 3d game in nimrod or was it you who created the nimgame project on github? |
22:03:03 | filwit | zahary, no not in Nimrod (C#). Not yet at least ;-V |
22:03:04 | Araq | while true: |
22:03:14 | Araq | var x |
22:03:25 | Araq | proc p = echo x # closure? o.O |
22:03:59 | zahary | yes, closure by default for inner procs makes sense |
22:04:08 | filwit | Araq: will closures in Nim require something like a 'nonlocal' keyword? |
22:05:01 | Araq | filwit: nimrod has sane scoping rules |
22:05:02 | filwit | I'm assuming not, so I guess a better question would be, can you make a "non closure" proc _inside_ another proc? |
22:05:19 | filwit | proc foo = |
22:05:23 | Araq | filwit: the compiler does an analysis |
22:05:25 | filwit | static proc bar = |
22:05:37 | filwit | # NOT ACTUAL SOURCE |
22:05:40 | Araq | if the inner proc doesn't capture any vars, it's not a .closure proc |
22:05:57 | filwit | you freaking rock. did I ever tell you that? |
22:06:06 | Araq | nope :-) |
22:06:36 | filwit | well that's great. very simple and obvious (now that I think about it) |
22:06:41 | filwit | I don't know why D doesn't do that |
22:07:21 | Araq | zahary: the problem is that it is no "inner proc" |
22:07:47 | Araq | it's just in the loop body of a top level loop statement |
22:07:49 | zahary | ah, we are talking about top level code again |
22:07:54 | Araq | yep |
22:08:39 | zahary | I guess it makes sense if all variables that appear in inner scopes (as inside this while loop) are actually compiled as local vars for the init proc |
22:13:37 | Araq | yes and procs become inner procs too |
22:16:36 | Araq | however I am beginning to dislike these semantics ... putting the proc's frame (or the captured parts thereof) on the heap is one thing |
22:16:55 | Araq | allocating it in a loop is another |
22:17:19 | Araq | and it is mostly useful for rosetta code examples ... |
22:17:48 | Araq | there are also more problems still, let me prepare a gist |
22:21:20 | zahary | well, I did convince you once that closure creation is something like syntax sugar for object creation - the user expects a new object object to be created every time the program passes through the line where the closure is written |
22:22:00 | Araq | you did convince me, yes |
22:22:00 | zahary | and as you said, the escape analysis should move most of the closures to the stack |
22:22:23 | Araq | well stack vs heap is not my point really here |
22:23:10 | filwit | will the performance of "closure objects" be comparable to normal types? |
22:23:27 | filwit | I've only really used closures in Javascript... |
22:23:46 | zahary | there is a call though a function pointer (as in every other compiled language) |
22:23:55 | Araq | I'm working on it but first version is not really optimized |
22:24:03 | Araq | https://gist.github.com/2951106 |
22:24:42 | Araq | so take a look |
22:25:10 | filwit | okay, just wanted to know if it *could* be as efficient, for if there'd be a major reason not to use them in hot-loops |
22:25:42 | zahary | ok, so the problem is where are the captures stored? |
22:25:42 | zahary | the ouch line is not much of a problem, because the closure name is just a reference to it's variable |
22:26:21 | Araq | filwit: there is no cost that can't be optimized away in principle |
22:26:37 | filwit | cool |
22:26:38 | Araq | and it's not even particularly hard to do so *cough* |
22:27:00 | filwit | lol, I'll be trying to help out more soon I promis |
22:27:29 | filwit | promise** |
22:28:00 | Araq | zahary: the problem is that it's an edge case |
22:28:14 | Araq | requiring special logic in the transformation pass |
22:28:37 | Araq | and currently I just bail out with an internal error for it |
22:28:55 | Araq | in innerA() you have a closure param that captures 'y' |
22:28:59 | zahary | you're referring to the innerB call? |
22:29:19 | Araq | and this closure has an 'up' pointer to another closure containing the 'x' |
22:29:32 | Araq | (y in the loop, x is not) |
22:29:53 | Araq | so in innerA() we call innerB() |
22:30:08 | Araq | and we need to do innerB(closureParam.up) |
22:30:26 | Araq | *not* innerB(closureParam) |
22:30:36 | zahary | yep |
22:31:32 | zahary | you outlined the solution. what needs special handling here? |
22:32:27 | Araq | it's a special case in the analysis and it makes me feel uneasy if I still overlooked something |
22:33:23 | Araq | and as I said, I wonder if this whole upvalue thingie isn't overkill |
22:33:44 | Araq | python for instance gets closures wrong and nobody seems to care |
22:34:10 | Araq | you put it into another inner 'def' there to get the desired semantics |
22:34:37 | zahary | what's wrong there? I disliked the "every assignment is to local var" that was in python 2.x |
22:35:03 | Araq | but that's only caused by python having to 'var/let' keywords |
22:35:26 | Araq | *having no |
22:36:26 | zahary | not strictly true as ruby, lua and javascript just assign to any existing outer variable |
22:37:53 | Araq | I'm still talking about "same location per iteration" vs. "1 *new* location per iteration" |
22:38:18 | Araq | python does "same location per iteration" |
22:38:34 | Araq | Lua does "1 new location" afaik |
22:38:45 | Araq | dunno about ruby and javascript |
22:39:27 | zahary | ah, plenty of languages that are broken here then, but surely I think we can do better (I see lua, coffeescript and C# 5 as evidence for the superiority of this approach) |
22:40:45 | zahary | and they are not entirely broken - dunno about python, but if you introduce a regular variable in the "broken" javascript, you still get the "1 per iteration" behavior |
22:41:28 | Araq | the difference is subtle enough to show up only in code examples like for i in 0..10: capture(i, f(i)) |
22:41:44 | zahary | but that's very common code |
22:42:06 | zahary | it happens all the time when you install callbacks in event driver APIs |
22:42:11 | Araq | but it needs to escape to make a difference |
22:42:26 | Araq | I never noticed C#'s broken behaviour |
22:42:59 | Araq | but alright, you've won |
22:43:18 | Araq | and fortunately it's already implemented and works ;-) |
22:43:36 | Araq | but now I need to implement the other kind of "upvalues" ... :-$ |
22:44:08 | Araq | which are needed when crossing middle procs: |
22:44:14 | Araq | proc a() = |
22:44:18 | Araq | var x |
22:44:23 | Araq | proc b() = |
22:44:28 | Araq | proc c() = |
22:44:37 | Araq | capture x |
22:45:28 | zahary | wouldn't that be just env.up.up.x ? |
22:47:02 | Araq | well currently b has no 'env' param ... :-) |
22:47:45 | Araq | and btw the compiler converts that to env.up2.x for nested blocks |
22:48:30 | Araq | the env.up.up.x way doesn't work but I forgot why |
22:48:53 | zahary | because it has no captures? I have to look at the code, but I worry this is not right - b() has to remember the env somehow, because it will give it to c() when b() is executed |
22:49:03 | zahary | c() won't be created before that point in time? |
22:49:36 | Araq | well yes that's the hard part, b() need to get an 'env' |
22:50:31 | Araq | but b doesn't capture anything itself |
22:50:52 | zahary | so the analysis is "transitive" if I can say that - if you have inner procs jumping over your scope, you have implicit capture too |
22:52:09 | * | silven quit (*.net *.split) |
22:52:09 | zahary | but yeah, thinking about it I see what you mean that this is likely to be a different kind of capture in the code |
22:55:41 | Araq | currently the compiler disallows captures that jump over a middle proc |
22:56:01 | Araq | I'm not sure this is a bad solution |
22:56:32 | Araq | the implemenation is hairy and who programs 3 levels of procs with implicit captures anyway |
22:56:51 | Araq | it's easy enough to pass it explicitly in this case |
22:57:09 | zahary | I think you shouldn't worry much about it - we'll add such "aiming for completeness" features one by one eventually |
22:57:22 | Araq | good :-) |
22:58:13 | Araq | I'd rather spend the time and identify a ref object with a closure if the closure only consists of a single ref object :-) |
22:58:46 | Araq | which is only correct if the captured variable is 'byCopy' or a 'let' variable ... |
23:01:43 | zahary | I think the escape analysis will yield positive results in a great deal of cases, but I can wait for it :) |
23:03:30 | Araq | I thought about that too |
23:03:55 | Araq | and if 'f' is never stored anywhere the closure can't escape, right? |
23:04:18 | zahary | what is f here? the closure param? |
23:04:44 | Araq | invoking f is fine, but when you do 'result = f' or even 'a[i] = f' you'd better allocated the environment on the heap |
23:05:01 | Araq | 'f' is the inner proc and thus the (f, env) tuple |
23:06:48 | Araq | hm yes, I think that's it |
23:07:04 | zahary | beside the analysis within the originating proc, I imagine that procs accepting closure params will have a skEscapes flag on a per-param basis - each(lambda) doesn't escape. onClick(lambda) does |
23:07:31 | Araq | no need for a flag |
23:07:45 | Araq | the escape analysis is trivial |
23:07:58 | Araq | if you do it approximatively |
23:08:10 | zahary | but without a flag, you'll need to perform in repeatedly on each callsite |
23:08:16 | Araq | each -- does not store 'f' |
23:08:27 | Araq | onClick -- yep, does store 'f' somewhere |
23:08:35 | zahary | and it's enough to analyze each only once |
23:09:04 | zahary | analyze "each" - I mean the each proc |
23:09:14 | Araq | yeah Just got it |
23:09:18 | Araq | you're right |
23:09:27 | Araq | skEscapes is the way to go |
23:10:45 | Araq | but the trivial analysis is good enough |
23:11:00 | Araq | and should catch 95% of all cases |
23:11:32 | Araq | in fact the analysis for 'each' and 'onClick' is: |
23:12:06 | Araq | "does use 'f' in an expression not invoking it?" |
23:12:25 | Araq | where 'f' stands for higher order function parameter |
23:13:05 | Araq | you can of course do a better analysis but it shouldn't be necessary |
23:13:12 | zahary | trivial, but also recursive |
23:13:24 | zahary | if f is passed over to another proc |
23:15:46 | Araq | yes :-) |
23:20:42 | zahary | I'm about to go to bed btw, last chance for another topic :) |
23:20:52 | Araq | I'm also thinking about making 'map', 'foldl' and 'foldr' built-ins |
23:21:01 | zahary | hmm, why? |
23:21:32 | Araq | because they are slow otherwise |
23:21:44 | zahary | you mean in evals? |
23:21:58 | Araq | you need inlining of indirect function calls and escape analysis |
23:22:10 | Araq | for the closures to get their overhead to 0 |
23:22:40 | Araq | seems easier to have them built-in in a first version at least |
23:22:57 | Araq | on the other hand inlining of indirect function calls is easy ... hm |
23:23:00 | zahary | new built-ins are too much work |
23:23:24 | Araq | lol? |
23:23:25 | zahary | we are not hard-pressed to deliver the best performance yet |
23:23:53 | Araq | you do introduce new built-ins all the time :P |
23:23:53 | zahary | I think inlining with templates will be quite easy to do |
23:24:29 | Araq | that's cheating ;-) |
23:24:37 | Araq | but nice |
23:25:04 | zahary | e.g. my plan to unify stmt and nkLambda and then using compatible syntax for lambda and template version of map, fold, etc |
23:25:22 | Araq | yes I know |
23:25:52 | Araq | I hate the "implemented but still slow things" |
23:26:24 | Araq | it's not too bad to put closures on the heap |
23:26:37 | Araq | but having a working but slow 'map' sucks IMO |
23:26:44 | zahary | well, then instead of built-ins (with codegen and everything I imagine), implement this template thing |
23:27:13 | Araq | hm alright |
23:27:54 | Araq | we need generic types for templates then ;-) |
23:28:07 | Araq | I wonder why you still disallowed these? |
23:28:15 | zahary | what's that? isn't that supported? |
23:28:24 | zahary | you mean template foo[T] ? |
23:28:28 | Araq | yep |
23:28:35 | Araq | compiler says error |
23:28:54 | filwit | what's the difference between that and template foo(T:epxr)? |
23:29:10 | Araq | T is inferred then |
23:29:24 | Araq | and in fact it's quite different |
23:29:28 | zahary | I see - you can do it now with |
23:29:28 | zahary | type T1 = distinct expr |
23:29:28 | zahary | type T2 = distinct expr |
23:29:28 | zahary | template foo(x, y: T1, z: T2) (it's equivalent in every way) |
23:29:40 | Araq | really? |
23:30:00 | Araq | template foo[T](s: seq[T]) :P |
23:30:10 | zahary | well, right now - yes. I remember your objections about expr and we can change that - but then something like auto will keep this functionality |
23:30:18 | zahary | template foo(s: seq) |
23:30:21 | filwit | i c |
23:32:10 | Araq | alright that should do as well |
23:32:21 | Araq | I have to sleep now too |
23:32:28 | Araq | so good night |
23:32:35 | zahary | good night |
23:35:32 | filwit | night |
23:35:45 | filwit | what time zone you in zahary? |
23:36:01 | filwit | I'm on eastern US |
23:52:58 | zahary | I'm in eastern Europe, probaby +6 from you |
23:55:16 | filwit | ah, night then |