On Tue, May 22, 2007 at 01:41:32PM -0700, Allison Randal wrote: > Oh, could someone capture that IRC discussion we just had and paste it > on the list?
Here it is (long, 247 lines). Pm 19:45 <pmichaud> I know I should already know this, but is there a way to make a named function that is global to all namespaces? Does putting something in the root namespace do that for me? 19:45 <pmichaud> and what sort of naming convention should we use to avoid naming collisions there? 19:46 <pmichaud> (in particular, I'm looking at a PIR version of the assign_keyed operation from my email 19:46 <particle> why not stick it in a library? 19:46 <particle> you don't want to load the lib in each namespace? 19:46 <pmichaud> right 19:47 <particle> well, you could use exporter 19:47 <allison> by "global to all namespaces", do you mean you store it in one namespace, but can look it up in any namespace? if so, there isn't any such option (it would be a massive pollution) 19:47 <particle> can you stick it in a constant? 19:47 <allison> but, you can store it in the top level namespace, and look it up with get_root_global 19:47 <particle> .const pmc myassign = ... 19:48 <pmichaud> I don't necessarily want to look it up in every subroutine generated by PAST-pm 19:48 <pmichaud> I mean, I can, but... 19:48 <particle> macros are global 19:48 <pmichaud> I'd like for PAST-pm to be able to simply generate 'assign_keyed'($P0, key, $P1) and have it work 19:48 <allison> what are you looking to pass into the subroutine? 19:49 <particle> pmichaud: you could create a dynamic opcode lib 19:49 <pmichaud> allison: did you happen to read my post to parrot-porters about assignment? That's what I'm looking at 19:49 <allison> or, what are $P0 and $P1 in those examples 19:49 <particle> it'd be c, but i think that's your ultimate goal anyway 19:49 <pmichaud> particle: yes, that would probably work 19:49 <allison> I skimmed them this morning, but can look again 19:49 <pmichaud> allison: ideally I'd like to be able to have it as an opcode 19:49 <particle> assign_keyed aggregate, key, value 19:49 <pmichaud> given an aggregate $P0, a key, and a value to be assigned $P1 19:49 <pmichaud> assign_keyed $P0[key], $P1 19:49 <pmichaud> key could be an int, string, or PMC 19:50 <particle> pmichaud: current pir won't allow that syntax iirc 19:50 <allison> is that an advantage over aggregate[key] = value? 19:50 <particle> yes, = is set 19:50 <pmichaud> yes, because aggregate[key] = value does a bind, not an assign 19:50 <pmichaud> $P0 = aggregate[key] 19:50 <pmichaud> aggregate[key] = $P1 19:50 <particle> aggregate[key] := value 19:51 <allison> so "assign aggregate[key], value"? 19:51 <particle> unfortunately, := is what we have already as = 19:51 <pmichaud> there is no "assign aggregate[key], value" 19:51 <pmichaud> and yes, I'd like that sort of assign, but with a huge caveat 19:51 <allison> but that's what you're looking for? 19:51 <pmichaud> yes, but I also want it to create aggregate[key] if it doesn't exist, and to morph aggregate[key] to value's type if it does 19:52 <particle> dwim_assign_keyed 19:52 <particle> is it the op's job to create a nonexistent key, or the aggregate's job? 19:53 <allison> seems like something that may vary per-pmc, so you'd want it to be handled by vtable entries 19:53 <pmichaud> it should be a vtable on the aggregate, same as set aggregate[key], value does now 19:53 <particle> who's in charge of auto-vivifying? 19:53 <allison> but I'll look over your proposal 19:53 <particle> yeah, i agree it should be the pmc 19:53 <pmichaud> in the meantime, I was looking for a way to implement it even if it's not an opcode 19:54 <pmichaud> thus, something "global-ish" :-) 19:54 <allison> do you need both set_pmc_keyed and assign_pmc_keyed? 19:54 <pmichaud> probably, yes 19:54 <particle> yep 19:54 <pmichaud> one is binding, one is assignment 19:54 <particle> however... parrot *can* punt on this one 19:55 <pmichaud> it can? 19:55 <particle> iiuc you can implement the semantics of assignment with binding only or vice-versa 19:55 <pmichaud> particle: If you can show me how to do that for the example I gave in the message, I'm all ears :_) 19:55 <pmichaud> er, eyes 19:55 <particle> however you need a container type 19:55 <pmichaud> right, we don't have a scalar container type 19:55 <allison> the container type is PMC 19:56 <particle> ok, a value type :) 19:56 <allison> which is Integer, String, etc 19:57 <pmichaud> if we had a scalar container type, it could work, yes. But then an aggregate would need to be an array of scalar containers 19:58 <allison> what's the advantage of morphing the PMC to an Undef first and then morphing it to a new type? 19:58 <pmichaud> it works :-) 19:58 <allison> you lose the value anyway, so why not just store a new PMC? 19:58 <pmichaud> because of binding 19:58 <pmichaud> I may have other lexicals bound to the old PMC 19:58 <pmichaud> my $b := @a[2] 19:58 <pmichaud> if @a[2] goes to a new PMC, then $b still points to the old one 19:58 <allison> you may have the aggregate member aliased to another name 19:59 <particle> yep 19:59 <pmichaud> so, we have to make sure that the existing PMC at @a[2] changes to the new value, as opposed to simply giving @a[2] a new PMC 20:00 <allison> so, it used to be that all PMCs could morph to another type, but we dropped that feature 20:00 <particle> pm: we can create a Scalar, ResizableScalarArray, and ScalarHash if you wish 20:00 <allison> because it was only needed by perl 20:00 <pmichaud> I don't think it's ever been that all PMCs could morph to another type, at least not as long as I've been with Parrot 20:00 <allison> well, the basic types 20:00 <pmichaud> I know that several of the basic types (Int, Scalar, Fl... ) yeah 20:00 <pmichaud> but I couldn't, say, morph an array into an Integer 20:00 <particle> tcl has "shimmering" which is morphing 20:00 <allison> (they were called PerlInt, PerlString, etc in those days) 20:01 <pmichaud> well, Int, String, and Float still morph 20:01 <pmichaud> sorry, Integer, String, and Float still morph 20:01 <allison> what you're really looking to is an alias to a structural slot 20:02 <pmichaud> I'm not sure that's what I'm looking for :-) 20:03 <pmichaud> unless we have some way of keeping track of structural slots 20:04 <allison> does Perl 6 specify that if you take an alias to an array within an array, and assign an integer to the same position in the array, that the alias will still point to the integer? 20:04 <pmichaud> I don't think Perl 6 specifies 20:04 <allison> I can't see anywhere that's useful 20:04 <pmichaud> however, it's not just here that's an issue 20:05 <pmichaud> sub foo($x is rw) { ... } foo(@a[2]); 20:05 <pmichaud> the caller would need to know to construct an lvalue reference to @a[2] 20:06 <pmichaud> yes, we can do this, but it seems nicer if we just supported the standard assign semantics that most dynamic languages use directly in parrot 20:06 <pmichaud> I have to leave now to pick up kids from school... be back in 30 or so 20:07 <allison> I'll be on a plane then, but will look over your message 20:08 <allison> I question the idea that this is "standard assign semantics that most dynamic languages use" (or if it is, I haven't fully understood your message yet) 20:11 <particle> assign here means bind 20:12 <particle> our vtable function names are unfortunate (set and assign) 20:12 <allison> seems that the core of the behavior is in this code: 20:12 <allison> assign $P6, $P4 # $P6 needs to morph 20:12 <allison> # to whatever type $P4 is 20:13 <particle> yes, then there's all the if key doesn't exist, etc 20:13 <particle> but that's the core 20:14 <allison> well, you can't take an alias to a key that doesn't exist 20:14 <allison> aliases are to values. no value means no alias 20:15 <particle> what about autovivification? 20:15 <particle> i suppose that would have to happen at a higher level 20:16 <particle> as in, opcodes would have to be emitted to check whether or not the index exists in the aggregate, and create it if not--then perform the bind 20:16 <allison> if taking an alias kicks off autovivification, then the key would always exist any time it was aliased 20:17 <Coke> (shimmering) note that we're not actually shimmering, we're morphing. it's just that it's *close* to shimmering. =-) 20:17 <particle> right, i think it's the aggregate's job to determine whether or not a keyed lookup will work or not 20:17 <particle> coke: i was pretty sure you were morphing 20:17 <allison> yeah, that's the aggregate's implementation of get_pmc_keyed 20:17 <particle> thanks for the confirmation 20:18 <particle> so assign_keyed would have to call get_pmc_keyed, then 20:18 <particle> or, both ops would need to be emitted 20:18 <Coke> shimmering seems to involve having multiple slots to keep this information, and being able to switch back and forth if the value hasn't been mucked with without having to recalc. 20:19 <chromatic> Perl 5 does that. 20:19 <particle> coke: that's a caching strategy then, like perl SVs 20:20 <particle> allison: nicholas is right about pmc design size wrt cache size 20:20 <particle> s/design/ 20:20 <allison> so the Tcl data types have slots for all standard values? 20:20 <particle> gah, shouldn't have had that beer 20:20 <allison> particle: it was designed as a cache, yes, but it's being used as the core data of the PMC 20:21 <Coke> allison: I've been avoiding looking at the tcl source, mostly. =-) 20:21 <particle> i mean, the size of the pmc was designed to fit in processor caches 20:21 <allison> particle: which is a problem for role composition, and for intelligent inheritance across the low-level to high-level boundary 20:21 <allison> particle: that too 20:22 <particle> that's why the UnionVal is funny... that's the different types of things that would fit in that space 20:22 <allison> aye 20:23 <pmichaud> back 20:23 <particle> certain gc implementations (currently in core) rely on constant-size pmcs 20:23 <pmichaud> standard assign semantics: in most languages that I've dealt with, if I say $a = $b, then I expect $a to be a duplicate of $b, including its type 20:23 <allison> the PMCs will stay constant sized 20:23 <allison> that's one aspect of Leo's proposal that I've rejected 20:24 <allison> pmichaud: but generally I'd also expect $a to be a copy of $b 20:24 <pmichaud> by "duplicate" I was meaning "copy" 20:25 <allison> not an alias to $b, and not retaining any connection to the former value of $a 20:25 <allison> so, if a attached a property to $a, and then called $a = $b, I would expect it to lose the property 20:25 <pmichaud> really? I don't think so 20:25 <pmichaud> my $a is context(rw); 20:25 <pmichaud> $a = $b 20:26 <pmichaud> (okay, that's a trait. hrm.) 20:26 <allison> ah, drat, this is back to the very old argument of how many levels of container we need 20:27 <pmichaud> yes, and I spent several weeks last fall struggling with it to end up with what we have now 20:27 <pmichaud> I'm only bringing it up now in response to Nicholas Clark's question about "how much morphing do we need in Parrot", and the current answer, at least for PAST-pm, is "well, quite a lot, actually" 20:27 <allison> we've tried to keep it as simple as possible, with the PMC container and a core struct 20:27 <pmichaud> I just do the morph through a sequence of morph/assign 20:28 <allison> how much of the behavior could be implemented in the assign vtable function for the Perl 6 PMC types? 20:29 <pmichaud> is this assuming I have an assign_keyed op? 20:29 <pmichaud> oh, wait, assuming I don't 20:29 <pmichaud> hmmm 20:29 <allison> yeah, assuming you don't have it 20:29 <particle> we'd need many more perl 6 pmc types 20:29 <pmichaud> if all of the Perl 6 PMC types knew how to morph to any other Perl6 PMC type, then I think it would work 20:30 <particle> yeah, totally own type system, starting with Perl6Undef 20:30 <pmichaud> there's still the issue of dealing with non-existent keys, however 20:30 <allison> the Perl 6 types could be simple inherits from core types, with morphing added 20:30 <pmichaud> that's where the advantage of assign_keyed comes in, in that it creates the key at the time of assignment 20:30 <allison> isn't that a question of autovivification on the aggregate types for Perl 6? 20:30 <particle> pmichaud: the pmc will handle the _keyed lookup semantics 20:31 <pmichaud> particle: looking up a key shouldn't always autovivify it 20:31 <particle> right, it depends on the pmc type 20:31 <pmichaud> $a = $b[2] should not autovivify $b[2] 20:31 <particle> oh, i see. hrmm. 20:31 <allison> that's a get_pmc_keyed 20:31 <particle> ah, yes. we have different vtable functions for that 20:32 <pmichaud> right, but I don't have an equivalent of assign_pmc_keyed that autovivifies 20:32 <particle> so it'll be more than one opcode to do that 20:32 <allison> so, set_pmc_keyed clearly always autovivifies 20:33 <pmichaud> yes and now 20:33 <pmichaud> er, yes and no 20:33 <pmichaud> it does create the key, yes, but it could still point to NULL 20:33 <allison> well, it always sets a value 20:33 <allison> (not even autovivify) 20:33 <particle> in perl 5, auto-vivify means an undef value is associated with the key 20:33 <pmichaud> and set_pmc_keyed breaks any binding to an existing PMC. Sometimes we want that, yes, but sometimes we don't 20:34 <allison> so, perl 6 types, when they autovivify a key must also give it an .Perl6Undef value? 20:34 <allison> you can't take an alias to a NULL 20:34 <pmichaud> exactly 20:34 <pmichaud> and yes, we'd autovivify to an undef 20:35 <Coke> ... this sounds like a very similar conversation to the tcl way of doing things vs. the core parrot way of doing things from years ago. 20:35 <particle> allison: autoviv will give Perl6Undef value... if key exists, it must morph value to Perl6Undef 20:35 <pmichaud> that's what would happen for, say, my $b := @a[2] 20:35 <particle> ...during assign_keyed 20:35 <pmichaud> during assign_keyed, if key doesn't exist then we clone value and bind the key to that value 20:36 <allison> so, what code path could you follow to end up with an alias to a keyed element that is still NULL? 20:36 <pmichaud> if key does exist, then we give that key the new value 20:36 <pmichaud> allison: in PIR or in Perl 6? 20:36 <particle> ah, clone value. right 20:36 <pmichaud> (or, instead of clone value we do COW semantics, but it's much the same) 20:36 <allison> pmichaud: Perl 6 20:36 <pmichaud> allison: in Perl 6 I don't think we get there, no. 20:37 <pmichaud> allison: in Perl 6 I don't think we end up with a case of assigning to a keyed element that is NULL 20:37 <allison> so, if there is a NULL, it's always safe to set_pmc_keyed, because there can't be an alias to it 20:37 <pmichaud> right 20:37 <pmichaud> that's what PAST-pm is doing now 20:37 <pmichaud> if a key is NULL, then we clone the value and use set_pmc_keyed 20:37 <pmichaud> if a key is not NULL, then we get a reference to it and do morph/assign 20:38 <allison> okay, we're all on the same page, that's goo 20:38 <allison> good 20:38 <allison> (my flight 20:38 <pmichaud> note that this occurs not only for arrays, but can also occur for lexicals and package variables 20:38 <allison> is about to board) 20:38 <pmichaud> okay, allison, thanks 20:40 <allison> I'm still not quite getting the need for assign_pmc_keyed, unless it's just to condense the code? If so, then it's a simple complexity balance: whether it's better to have the complexity in one place than another. 20:40 <Coke> allison: fly safe. 20:40 <allison> thanks, ttyl 20:40 <Coke> it's better to have the complexity hidden from the HLL authors. 20:40 <Coke> chromatic: ping 20:40 <particle> it's better to get parrot out the door 20:40 <allison> agreed, if it is a form of complexity that is always standard across all HLLs 20:41 <pmichaud> it's to condense the code 20:41 <pmichaud> we'd be replacing a sequence of 10 or more PIR instructions with one 20:41 <pmichaud> and since assignment is a _very_ common operation, it seems better to do that 20:41 <allison> I'll email 20:41 -!- allison [EMAIL PROTECTED] has quit [Quit: ChatZilla 0.9.78.1 [Firefox 2.0.0.3/2007030919]] 20:42 <pmichaud> at any rate, I've already decided that at some point I'm going to revise PAST-pm so that it's using the same code for keyed assignment and global variables, instead of separate store_global instructions as it does now