<<18-06-2012>>

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:59SchalaZealI can't seem to find an unsigned assignment operator.
02:14:26SchalaZealonly the arithmetic ones
03:08:12SchalaZealThing is... what would I do if something needed to be byte aligned and expected an 8-bit unsigned value of........say......213?
03:11:22Trixar_zaOo
03:11:35Trixar_zaChrono Trigger?
03:13:44SchalaZealehe...yes
03:14:44Trixar_zaAnyway, 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:51Trixar_zaNot sure what dom96 is doing though :P
03:19:07SchalaZealposted... anyway...
03:19:13SchalaZealthanks
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:35SchalaZealAre cstrings null terminated? I don't quite comprehend how they work.
09:43:54SchalaZealI'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:44SchalaZealI think I get the point... probably equivalent to C's char*
10:36:51SchalaZealgnight
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:10Araqping zahary
21:35:21zaharyyo
21:43:20AraqI got closures mostly working but there are ugly things ...
21:45:28zaharywhat kind of ugly things?
21:45:30Araqfor a start you can mark an outer proc with {.closure.} but the implementation has a *hard* time with that
21:45:52Araqas there is no environment to pass around
21:46:11Araqand 'nil' is already used for conversions from 'nimcall' to 'closure'
21:46:33AraqI think I'll simply disallow it for outer procs
21:47:27zaharywell, what is supposed to mean for outer proc anyway?
21:48:04Araqto have a hidden unused *env* parameter just like every other .closure proc
21:48:19Araqso that no implicit conversion is necessary
21:48:20zaharybut why would I want that?
21:48:28Araqdunno
21:48:38Araqcan't think of any use case either :D
21:48:51Araqbut I wanted to ask you before going that way :D
21:49:36Araqok, next problem:
21:49:52zahary:) I agree in disallowing it. this is in no way related to passing regular procs to closure params, right?
21:51:16Araqwell no, passing nimcall to closure works
21:52:00Araqnext problem: if I have a top level loop statement
21:52:15Araqand a 'variable' in the loop body, it's a global var
21:52:49Araqso the semantics are: "same location for each iteration"
21:53:05Araqbut if the loop is in a proc and the variable is captured in a closure
21:53:18Araqthe semantics are "new location for each iteration"
21:53:39Araqi.e. the closure allocation is done in the loop repeatedly
21:53:51Araqso we have a small inconsistency in the language here
21:54:18AraqI suppose it should be fixed by changing semantics of variables in top level loops
21:54:49zaharyI 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:21filwithi folks
21:58:19zaharyhi filwit. what's up?
21:58:47filwitnot to much. just finishing up some stuff on my game project
21:59:05filwit:)
21:59:10filwityou?
21:59:22Araqzahary: it should be easy to make these vars local and make the code generator put them in main()
21:59:40filwitbtw, you guys hear about Unity 3D game engine coming to Linux?
21:59:57filwitthat's pretty sweet news
22:01:28Araqhi filwit, yes we know
22:01:47AraqI think you alread told us? :P
22:02:21Araqbut if I have:
22:02:24filwitcouldn't have. just announced this morning :)
22:02:28zaharyfilwit, are you developing a 3d game in nimrod or was it you who created the nimgame project on github?
22:03:03filwitzahary, no not in Nimrod (C#). Not yet at least ;-V
22:03:04Araqwhile true:
22:03:14Araq var x
22:03:25Araq proc p = echo x # closure? o.O
22:03:59zaharyyes, closure by default for inner procs makes sense
22:04:08filwitAraq: will closures in Nim require something like a 'nonlocal' keyword?
22:05:01Araqfilwit: nimrod has sane scoping rules
22:05:02filwitI'm assuming not, so I guess a better question would be, can you make a "non closure" proc _inside_ another proc?
22:05:19filwitproc foo =
22:05:23Araqfilwit: the compiler does an analysis
22:05:25filwit static proc bar =
22:05:37filwit # NOT ACTUAL SOURCE
22:05:40Araqif the inner proc doesn't capture any vars, it's not a .closure proc
22:05:57filwityou freaking rock. did I ever tell you that?
22:06:06Araqnope :-)
22:06:36filwitwell that's great. very simple and obvious (now that I think about it)
22:06:41filwitI don't know why D doesn't do that
22:07:21Araqzahary: the problem is that it is no "inner proc"
22:07:47Araqit's just in the loop body of a top level loop statement
22:07:49zaharyah, we are talking about top level code again
22:07:54Araqyep
22:08:39zaharyI 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:37Araqyes and procs become inner procs too
22:16:36Araqhowever 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:55Araqallocating it in a loop is another
22:17:19Araqand it is mostly useful for rosetta code examples ...
22:17:48Araqthere are also more problems still, let me prepare a gist
22:21:20zaharywell, 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:00Araqyou did convince me, yes
22:22:00zaharyand as you said, the escape analysis should move most of the closures to the stack
22:22:23Araqwell stack vs heap is not my point really here
22:23:10filwitwill the performance of "closure objects" be comparable to normal types?
22:23:27filwitI've only really used closures in Javascript...
22:23:46zaharythere is a call though a function pointer (as in every other compiled language)
22:23:55AraqI'm working on it but first version is not really optimized
22:24:03Araqhttps://gist.github.com/2951106
22:24:42Araqso take a look
22:25:10filwitokay, 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:42zaharyok, so the problem is where are the captures stored?
22:25:42zaharythe ouch line is not much of a problem, because the closure name is just a reference to it's variable
22:26:21Araqfilwit: there is no cost that can't be optimized away in principle
22:26:37filwitcool
22:26:38Araqand it's not even particularly hard to do so *cough*
22:27:00filwitlol, I'll be trying to help out more soon I promis
22:27:29filwitpromise**
22:28:00Araqzahary: the problem is that it's an edge case
22:28:14Araqrequiring special logic in the transformation pass
22:28:37Araqand currently I just bail out with an internal error for it
22:28:55Araqin innerA() you have a closure param that captures 'y'
22:28:59zaharyyou're referring to the innerB call?
22:29:19Araqand this closure has an 'up' pointer to another closure containing the 'x'
22:29:32Araq(y in the loop, x is not)
22:29:53Araqso in innerA() we call innerB()
22:30:08Araqand we need to do innerB(closureParam.up)
22:30:26Araq*not* innerB(closureParam)
22:30:36zaharyyep
22:31:32zaharyyou outlined the solution. what needs special handling here?
22:32:27Araqit's a special case in the analysis and it makes me feel uneasy if I still overlooked something
22:33:23Araqand as I said, I wonder if this whole upvalue thingie isn't overkill
22:33:44Araqpython for instance gets closures wrong and nobody seems to care
22:34:10Araqyou put it into another inner 'def' there to get the desired semantics
22:34:37zaharywhat's wrong there? I disliked the "every assignment is to local var" that was in python 2.x
22:35:03Araqbut that's only caused by python having to 'var/let' keywords
22:35:26Araq*having no
22:36:26zaharynot strictly true as ruby, lua and javascript just assign to any existing outer variable
22:37:53AraqI'm still talking about "same location per iteration" vs. "1 *new* location per iteration"
22:38:18Araqpython does "same location per iteration"
22:38:34AraqLua does "1 new location" afaik
22:38:45Araqdunno about ruby and javascript
22:39:27zaharyah, 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:45zaharyand 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:28Araqthe difference is subtle enough to show up only in code examples like for i in 0..10: capture(i, f(i))
22:41:44zaharybut that's very common code
22:42:06zaharyit happens all the time when you install callbacks in event driver APIs
22:42:11Araqbut it needs to escape to make a difference
22:42:26AraqI never noticed C#'s broken behaviour
22:42:59Araqbut alright, you've won
22:43:18Araqand fortunately it's already implemented and works ;-)
22:43:36Araqbut now I need to implement the other kind of "upvalues" ... :-$
22:44:08Araqwhich are needed when crossing middle procs:
22:44:14Araqproc a() =
22:44:18Araq var x
22:44:23Araq proc b() =
22:44:28Araq proc c() =
22:44:37Araq capture x
22:45:28zaharywouldn't that be just env.up.up.x ?
22:47:02Araqwell currently b has no 'env' param ... :-)
22:47:45Araqand btw the compiler converts that to env.up2.x for nested blocks
22:48:30Araqthe env.up.up.x way doesn't work but I forgot why
22:48:53zaharybecause 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:03zaharyc() won't be created before that point in time?
22:49:36Araqwell yes that's the hard part, b() need to get an 'env'
22:50:31Araqbut b doesn't capture anything itself
22:50:52zaharyso 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:09zaharybut 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:41Araqcurrently the compiler disallows captures that jump over a middle proc
22:56:01AraqI'm not sure this is a bad solution
22:56:32Araqthe implemenation is hairy and who programs 3 levels of procs with implicit captures anyway
22:56:51Araqit's easy enough to pass it explicitly in this case
22:57:09zaharyI think you shouldn't worry much about it - we'll add such "aiming for completeness" features one by one eventually
22:57:22Araqgood :-)
22:58:13AraqI'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:46Araqwhich is only correct if the captured variable is 'byCopy' or a 'let' variable ...
23:01:43zaharyI think the escape analysis will yield positive results in a great deal of cases, but I can wait for it :)
23:03:30AraqI thought about that too
23:03:55Araqand if 'f' is never stored anywhere the closure can't escape, right?
23:04:18zaharywhat is f here? the closure param?
23:04:44Araqinvoking 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:01Araq'f' is the inner proc and thus the (f, env) tuple
23:06:48Araqhm yes, I think that's it
23:07:04zaharybeside 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:31Araqno need for a flag
23:07:45Araqthe escape analysis is trivial
23:07:58Araqif you do it approximatively
23:08:10zaharybut without a flag, you'll need to perform in repeatedly on each callsite
23:08:16Araqeach -- does not store 'f'
23:08:27AraqonClick -- yep, does store 'f' somewhere
23:08:35zaharyand it's enough to analyze each only once
23:09:04zaharyanalyze "each" - I mean the each proc
23:09:14Araqyeah Just got it
23:09:18Araqyou're right
23:09:27AraqskEscapes is the way to go
23:10:45Araqbut the trivial analysis is good enough
23:11:00Araqand should catch 95% of all cases
23:11:32Araqin fact the analysis for 'each' and 'onClick' is:
23:12:06Araq"does use 'f' in an expression not invoking it?"
23:12:25Araqwhere 'f' stands for higher order function parameter
23:13:05Araqyou can of course do a better analysis but it shouldn't be necessary
23:13:12zaharytrivial, but also recursive
23:13:24zaharyif f is passed over to another proc
23:15:46Araqyes :-)
23:20:42zaharyI'm about to go to bed btw, last chance for another topic :)
23:20:52AraqI'm also thinking about making 'map', 'foldl' and 'foldr' built-ins
23:21:01zaharyhmm, why?
23:21:32Araqbecause they are slow otherwise
23:21:44zaharyyou mean in evals?
23:21:58Araqyou need inlining of indirect function calls and escape analysis
23:22:10Araqfor the closures to get their overhead to 0
23:22:40Araqseems easier to have them built-in in a first version at least
23:22:57Araqon the other hand inlining of indirect function calls is easy ... hm
23:23:00zaharynew built-ins are too much work
23:23:24Araqlol?
23:23:25zaharywe are not hard-pressed to deliver the best performance yet
23:23:53Araqyou do introduce new built-ins all the time :P
23:23:53zaharyI think inlining with templates will be quite easy to do
23:24:29Araqthat's cheating ;-)
23:24:37Araqbut nice
23:25:04zaharye.g. my plan to unify stmt and nkLambda and then using compatible syntax for lambda and template version of map, fold, etc
23:25:22Araqyes I know
23:25:52AraqI hate the "implemented but still slow things"
23:26:24Araqit's not too bad to put closures on the heap
23:26:37Araqbut having a working but slow 'map' sucks IMO
23:26:44zaharywell, then instead of built-ins (with codegen and everything I imagine), implement this template thing
23:27:13Araqhm alright
23:27:54Araqwe need generic types for templates then ;-)
23:28:07AraqI wonder why you still disallowed these?
23:28:15zaharywhat's that? isn't that supported?
23:28:24zaharyyou mean template foo[T] ?
23:28:28Araqyep
23:28:35Araqcompiler says error
23:28:54filwitwhat's the difference between that and template foo(T:epxr)?
23:29:10AraqT is inferred then
23:29:24Araqand in fact it's quite different
23:29:28zaharyI see - you can do it now with
23:29:28zaharytype T1 = distinct expr
23:29:28zaharytype T2 = distinct expr
23:29:28zaharytemplate foo(x, y: T1, z: T2) (it's equivalent in every way)
23:29:40Araqreally?
23:30:00Araqtemplate foo[T](s: seq[T]) :P
23:30:10zaharywell, 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:18zaharytemplate foo(s: seq)
23:30:21filwiti c
23:32:10Araqalright that should do as well
23:32:21AraqI have to sleep now too
23:32:28Araqso good night
23:32:35zaharygood night
23:35:32filwitnight
23:35:45filwitwhat time zone you in zahary?
23:36:01filwitI'm on eastern US
23:52:58zaharyI'm in eastern Europe, probaby +6 from you
23:55:16filwitah, night then