Version 2 (modified by cotto, 5 years ago)

--

<pmichaud> cotto_work: I do expect to try to generate smarter pir, yes.  However, the structure of Parrot doesn't allow for a lot smarter PIR.
<pmichaud> (I'm hoping parrot will change that... but I don't expect it to happen anytime in the near future.)
<cotto_work> ok.  How could Parrot enable smarter code generation?
<Tene> The fix isn't too bad, but I haven't done it yet.
<cotto_work> It sounds like that might fit in with Lorito.
<pmichaud> cotto_work: well, one of the big stumbling blocks at the moment is that lexicals can only be PMCs
<pmichaud> so anything that goes into a lexical ends up having to be boxed into a PMC
<pmichaud> an even bigger stumbling block is that Parrot doesn't have a good lvalue model or assignment semantics
<pmichaud> it tends to confuse "bind" with "assign"
<pmichaud> at least, it does that for most of the default PMC types
<pmichaud> there's also not a good reference model
<pmichaud> for keeping track of object references
<pmichaud> as a result, the code that nqp generates tends to have to be somewhat pessimistic, such as continually refetching lexical and global symbol tables because of the possibility of a symbol being rebound
<Coke> pmichaud,tene: > puts [list [catch barf var] $var]
<Coke> 1 {Could not find non-existent sub barf}
<Coke> whee.
<cotto_work> That explains some of the generated code then.
* cconstantine has quit (Quit: cconstantine)
<Coke> pmichaud: any issue with switching partcl-nqp to build with "nqp" instead of "parrot-nqp" for now?
<Coke> (then I don't have to ping you to cut a new 'release' =-)
<pmichaud> cotto_work: I do plan to have an option whereby code can say "assume this lexical/symbol isn't being rebound"
<pmichaud> but since parrot doesn't have a good assignment model, most folks end up doing rebinds
<pmichaud> partcl-nqp just went through this yesterday (until I fixed it this morning) whereby symbols were being re-bound to new PMCs instead of changing the value of an existing multiply-bound PMC
<cotto_work> What's the difference between assignment and binding?
<pmichaud> assignment changes the value of an existing PMC
<pmichaud> binding causes a symbol table entry to point to a PMC
<pmichaud> so, for example
<pmichaud> $P0 = box 1
<pmichaud> $P1 = $P0
<pmichaud> these are examples of binding
<pmichaud> if after the above, I do:    $P0 = box 3
<pmichaud> then $P1 ends up still being bound to the PMC containing 1
<pmichaud> and $P0 is bound to a new PMC containing 3
<pmichaud> okay so far?
<cotto_work> yes
<pmichaud> $P0 = box 1
<pmichaud> $P1 = $P0
<pmichaud> assign $P0, 3
<pmichaud> in this case,  $P0 and $P1 still point to the same PMC, and the value of that PMC has changed to 3
<pmichaud> still okay?
<cotto_work> yes
<pmichaud> that's the difference
<pmichaud> now then, let's look at something like
<pmichaud> $P0 = new ['ResizablePMCArray']
<pmichaud> $P0[0] = 1
<pmichaud> $P1 = $P0[0]
<pmichaud> in this case, $P1 and $P0[0] are pointing to the same PMC  (containing 1)
<pmichaud> but if we then do...
<pmichaud> $P0[0] = 3
<pmichaud> that's a binding, not an assignment
<pmichaud> such that $P1 refers to the old PMC (1), while $P0[0] refers to the new one (3)
<pmichaud> in other words, changing the value in the array has broken the bind
<moritz> pmichaud: this is becoming an FAQ... you should put that on a wiki page or so
<pmichaud> moritz: well, I have a few hours car ride today, perhaps I can type it up.
<pmichaud> but I also plan to do a NQP/compiler tutorial
<Coke> pmichaud: is t/sanity.t working for you?
<pmichaud> Coke: it was as of my last push
<cotto_work> Thanks.
<pmichaud> where it gets *really* nasty is with
<pmichaud>    $P0 = find_lex '$a'
<pmichaud>     'foo'()
<pmichaud> if the "foo" subroutine does   store_lex  '$a', $P99    to put a new value in lexical $a
<pmichaud> then when we get back from 'foo', $P0 no longer points to the PMC associated with $a
<dalek> nqp-rx: ae0666c | tene++ | t/nqp/44-try-catch.t:
<dalek> nqp-rx: Update test plan
<dalek> nqp-rx: review: http://github.com/perl6/nqp-rx/commit/ae0666cf489a209c1aa2bffb1a829ce689a3b146
<pmichaud> because store_lex does a bind
<pmichaud> and not an assign
<cotto_work> Then $P0 will have an out-of-date value
<pmichaud> exactly
<pmichaud> so, every time we need access to $a, we end up having to do a re-fetch
<pmichaud> because it's possible some other operation will have re-bound it to a different PMC
<dalek> rakudo: 2eb38b5 | moritz++ | perl6.pir:
<dalek> rakudo: alias Object and Mu, as suggested by jnthn++; wins us back quite a few tests
<dalek> rakudo: review: http://github.com/rakudo/rakudo/commit/2eb38b5bf07f1c4392a9d1d75f3fd1cf7d877105
<pmichaud> ideally there would be an opcode that makes it easier to do assignment
<pmichaud> there is an opcode called 'assign', but it tends to do weird things with the built-in PMCs
<pmichaud> for example
<pmichaud> $P0 = new ['ResizablePMCArray']
<pmichaud> store_lex '$a', $P0
<pmichaud> which sets $a to be a RPA
<pmichaud> now we want to do the equivalent of  $a = 3   -- i.e., change it to an Integer 3
<pmichaud> $P1 = find_lex '$a'
<pmichaud> assign $P1, 3      #   oooops!
<cotto_work> That changes the length to 3, doesn't it?
<pmichaud> what we want is $P1 to be an Integer 3
<pmichaud> right
<pmichaud> so the 'assign' opcode doesn't do what we want here
<pmichaud> late last year we added the 'copy' opcode to try to do this
<pmichaud> so we'd have
<pmichaud> $P1 = find_lex '$a'
<pmichaud> $P2 = box 3
<pmichaud> copy $P1, $P2    (replace $P1 with $P2)
* pjcj (~pjcj@80-218-204-119.dclient.hispeed.ch) has joined #parrot
* slavorg gives channel operator status to pjcj
<pmichaud> but it's horribly inefficient, because it involves making a clone of $P2 and then copying that structure into the PMC header for $P1
<pmichaud> but so far it's about the best we can do
<pmichaud> everything gets worse when we start talking about aggregate access
<pmichaud> because there's not a    copy $P0[0], $P2    opcode yet
<pmichaud> and this leads to allison's comment that it really should be the PMCs/vtables that determine behavior instead of opcodes
<pmichaud> (which is where the model completely breaks down)
<cotto_work> There's a lot conspiring to prevent good code generation from nqp.
<cotto_work> Thanks you for that explanation.
<pmichaud> sure thing!
<dukeleto> 'ello
<pmichaud> ultimately it's that Parrot (vtable and core types) doesn't have a good container/value/lvalue model
<pmichaud> or, at least, one that doesn't map well to the HLL's we're targing.
<pmichaud> *targeting