where NOT_SELF is 0 if we're "true" and 1 if we're "false". Or just leave it out and let default blow up if we're not that kind of PMC.
I had a RubyInteger PMC in P0 and generated
not P0, P0
which is fine, except that it's still true using the above logical_not, since all Ruby integers (yes, Virginia, even 0) are true. (The fact that dest = src is sort of immaterial; the relevant detail is that the dest is a PMC that is never false).
Furthermore, this doesn't affect just RubyInteger, but any "not" with a type like it as the destination. Arguably, RubyInteger is broken and the rest of the world is fine using dest->set_integer_native(0), but I think it shows a problem with logical_not itself, and either
(a) a set_bool PMC method should be added (not the best fix, but at least then RubyInteger can morph itself into a false-able PMC), or
(b) logical_not's semantics should be changed to return an INTVAL (0 or 1), which of course brings up the question of what is left in the destination register - (1) clobber it, and set it to be a new boolean PMC, or (2) make not take just one param, and have it affect itself, like increment, or (3) require the destination register to be an Integer (Ix) (not presently allowed), or
(c) force people to create a "false-able" PMC as the destination (bad, because this introduces an "action at a distance" force; the destination of the result shouldn't affect the outcome of an operation)
Similar arguments can be made for the other logical ops, except that it's more evident that the Right Thing to put in the dest is the usual short- circuit result, i.e. one of lhs, rhs, or (null? whatever null is for PMCs?), via get_bool only and without the need for any logical_* PMC methods.
[Oh. Interesting. "not P0, P0" alone in a pasm file generates: logical_not() not implemented in class 'PerlArray' I see no PerlArray here....]
This is something that'll come up with perl 6 reasonably soon as well. The solution for us is to have truth and falsehood be an optional property on the variable, potentially separate from the variable's value. The mechanism for that's not in yet. (I'd forgotten. It's on the todo list now) -- Dan
--------------------------------------"it's like this"------------------- Dan Sugalski even samurai d...@sidhe.org have teddy bears and even teddy bears get drunk
On Tue, 3 Dec 2002, Dan Sugalski wrote: > At 4:29 PM -0500 12/3/02, David Robins wrote: > >Enlightenment appreciated as always.
> This is something that'll come up with perl 6 reasonably soon as > well. The solution for us is to have truth and falsehood be an > optional property on the variable, potentially separate from the > variable's value. The mechanism for that's not in yet. (I'd > forgotten. It's on the todo list now)
Was this discussed earlier (and if so, got a link?) or just sketched out and /* TODO */'d?
Adding an extra knob doesn't seem like all that good a solution (seems you'd run into weird issues, like a boolean PMC that was both true and false at the same time, or an undef value that was true); why not -
- create immutable "true" and "false" PMCs - have not P0, P1 set P0 to $1->get_bool ? true : false - and P0, P1, P2 set P0 to $1->get_bool ? $2->get_bool ? $2 : $1 : false - or P0, P1, P2 set P0 to $1->get_bool ? $1 : $2->get_bool ? $2 : false - xor P0, P1, P2 set P0 to whichever is set, false if both/neither
- plus optionally allow a not Ix, Px op which sets Ix to 1 or 0, etc.
>> At 4:29 PM -0500 12/3/02, David Robins wrote: >> >Enlightenment appreciated as always.
>> This is something that'll come up with perl 6 reasonably soon as >> well. The solution for us is to have truth and falsehood be an >> optional property on the variable, potentially separate from the >> variable's value. The mechanism for that's not in yet. (I'd >> forgotten. It's on the todo list now)
>Was this discussed earlier (and if so, got a link?) or just sketched out >and /* TODO */'d?
Just sketched out and TODO'd.
>Adding an extra knob doesn't seem like all that good a solution (seems >you'd run into weird issues, like a boolean PMC that was both true and >false at the same time, or an undef value that was true); why not -
True, but I'm looking at the boolean state of a variable as potentially part of a larger set of things. I freely admit a boolean PMC with a true value and a false property would be really bizarre. (So I'd suggest that you make it so that can't happen... :)
It is OK for an undef value to be true, though. That's not only allowable, it has to be allowed. For perl, at least, it's how Larry plans on getting around the "function returns undef, but it's a real undef value, not a false 'I didn't work' value" issues we have in perl 5 now.
>- create immutable "true" and "false" PMCs
That's fine.
>- have not P0, P1 set P0 to $1->get_bool ? true : false
Sure, that works. I can't think of a good reason to have PMCs be able to return something fancier than true or false when we ask them for their logical negation. (Can any language override logical negation to return something besides true/false?)
>- and P0, P1, P2 set P0 to $1->get_bool ? $2->get_bool ? $2 : $1 > : false >- or P0, P1, P2 set P0 to $1->get_bool ? $1 > : $2->get_bool ? $2 : false >- xor P0, P1, P2 set P0 to whichever is set, false if both/neither
Not for these, though. Logical and, or, and xor need to be delegated to the PMCs as they may be overridden, and binary logical operations may return something other than a plain true or false value. Otherwise perl's short-circuiting logical stuff behaves... oddly. And I know that can be overridden.
>- plus optionally allow a not Ix, Px op which sets Ix to 1 or 0, etc.
Maybe. Would any compiler actually use this, though? I don't often care about what opcodes we put in, but apparently today I do. -- Dan
--------------------------------------"it's like this"------------------- Dan Sugalski even samurai d...@sidhe.org have teddy bears and even teddy bears get drunk
#### [Fri, Dec 06, 2002 at 05:01:21PM -0500: Dan Sugalski]
> At 5:47 PM -0500 12/3/02, David Robins wrote: > >On Tue, 3 Dec 2002, Dan Sugalski wrote: > >- create immutable "true" and "false" PMCs
> That's fine.
> >- have not P0, P1 set P0 to $1->get_bool ? true : false
> Sure, that works. I can't think of a good reason to have PMCs be able > to return something fancier than true or false when we ask them for > their logical negation. (Can any language override logical negation > to return something besides true/false?)
Be careful not to stop people doing interesting, useful but entirely sick things. Current perl has problems rooted in the way it deals with overloading and tieing that mean some things can't be done without lots of rewriting.
I'd say that any operation who's result could be stored somewhere should (nay, must) be able to return a fully fledged PMC.
That is to say, in "if ( !exp1 ) { ... }", !exp1 merely has to be true or false, while $foo = !exp1 leaves !exp1 needing to be all manner of things.
Alex Gough -- It was at this time that some very pious Englishmen, known as the Early Fathers, sailed away to America in a ship called the Mayfly; this is generally referred to as the Pilgrims' Progress and was one of the chief causes of America.
On Fri, Dec 06, 2002 at 05:01:21PM -0500, Dan Sugalski wrote: > It is OK for an undef value to be true, though. That's not only > allowable, it has to be allowed. For perl, at least, it's how Larry > plans on getting around the "function returns undef, but it's a real > undef value, not a false 'I didn't work' value" issues we have in > perl 5 now.
Are you sure you want to spell that concept "true"?
Because then if &foo can legitimately return numbers, strings and undefs does it return
"pie" "pie" 2 2 undef: undef but true, 0 0 "" ""
so now
if (&foo(...)) { warn "Bang!"
}
warns on traditional true values, and undef?
So the caller then needs to launder the true property from undef before putting it somewhere else? That feels like a pain.
Or does it return
"pie" "pie" 2 2 undef: undef but true, 0 0 but true "" "" but true
which makes
if (&foo)) { warn "Bang!";
}
consistently noisy?
It seems to me that the distinction between intentional undef and failure undef needs to be made with some property other than "true". It feels like the distinction between doesn't exist and exists but undef in a hash, the value returned off the end of an array, or (maybe) the different between the empty list () and the list (undef)
undef but valid. Or maybe undef but invalid for the failure case? [so that by default things have no properties] It's like the argument about the meaning(s) of NULL in SQL, isn't it? "I just don't know", "known - this isn't applicable" and "this isn't valid"
This is more a perl6 language message, isn't it? If it can't quickly be quashed, should it migrate there?
On Fri, 6 Dec 2002, Dan Sugalski wrote: > At 5:47 PM -0500 12/3/02, David Robins wrote: .... > >Adding an extra knob doesn't seem like all that good a solution (seems > >you'd run into weird issues, like a boolean PMC that was both true and > >false at the same time, or an undef value that was true); why not -
> True, but I'm looking at the boolean state of a variable as > potentially part of a larger set of things. I freely admit a boolean > PMC with a true value and a false property would be really bizarre. > (So I'd suggest that you make it so that can't happen... :)
The existing get_bool should suffice for a boolean value, no?
I understand that in the perl language the user should be free to do anything, and the implementers make it Do The Right Thing, but in a backend interface there should be a few more constraints, because you know "can't happen" will.
> >- have not P0, P1 set P0 to $1->get_bool ? true : false
> Sure, that works. I can't think of a good reason to have PMCs be able > to return something fancier than true or false when we ask them for > their logical negation. (Can any language override logical negation > to return something besides true/false?)
> >- and P0, P1, P2 set P0 to $1->get_bool ? $2->get_bool ? $2 : $1 > > : false > >- or P0, P1, P2 set P0 to $1->get_bool ? $1 > > : $2->get_bool ? $2 : false > >- xor P0, P1, P2 set P0 to whichever is set, false if both/neither
> Not for these, though. Logical and, or, and xor need to be delegated > to the PMCs as they may be overridden, and binary logical operations > may return something other than a plain true or false value. > Otherwise perl's short-circuiting logical stuff behaves... oddly. And > I know that can be overridden.
Since and/or are _defined_ to short-circuit (in old core_ops.pod or core.ops), it should suffice to use get_bool, e.g. for and:
call $1->get_bool, if it returns false, return "false PMC" and end op; call $2->get_bool, return "false PMC" if false, or $2 itself if true.
change return "false PMC" to 0 and $2 to 1 for the Ix dest. version.
If it happens that either PMC represents, say, a call to a function, then the get_bool method can invoke it (side effect), as in '$x = foo() and bar()'.
> >- plus optionally allow a not Ix, Px op which sets Ix to 1 or 0, etc.
> Maybe. Would any compiler actually use this, though? I don't often > care about what opcodes we put in, but apparently today I do.
Well, the case that brought it up was trying to do "if" for Ruby. I started by using not P0/if P0, then I went with unless instead, but it still stuck out that the logical ops were rather broken because of the dest problem, i.e., that the dest can be any PMC type and the logical ops have no guarantee of what it is or what "set_integer" will do to its truth value (even a "set_bool" wouldn't properly fix this in all cases).
Perhaps the best fix would be to allow the logical ops to return a completely new PMC. It makes no sense to me for them to have to write to an existing PMC which could be (say) an array, hash, "integer that is always true" (Ruby), etc. i.e. pass in dest as a PMC**, if that works.
Of course this applies to other ops too, e.g. PerlInt's add should create a new perlint that is the sum of self and the rhs most of the time, except in some cases where it should create a float... ooh, that's gonna be interesting:
PerlInt + RubyInt => either, might as well favour the lhs PerlInt + PerlFloat => should return PerlFloat PerlInt + RubyFloat => ??? (should be a float, but how does perlint.add check the rhs is more precise?) RubyFloat + PerlInt => probably RubyFloat, which is OK ....
(Just using Ruby just as an example of an internally-unknown float/int set.)
Should ops like + be affected by argument order? (I was taught + is commutative....) I see PerlInt is doing all sorta of vtable-comparing, which is fine for the guys you know but doesn't fly for foreign floats.
It's a problem whether the dest is specified (as now) and just needs to be set, or is a PMC** and can be created - who picks the dest type and how?
If I may be so bold as to say it, maybe the PMC design shouldn't be closed just yet.
On Sat, 7 Dec 2002, Alex Gough wrote: > #### [Fri, Dec 06, 2002 at 05:01:21PM -0500: Dan Sugalski] .... > > >- have not P0, P1 set P0 to $1->get_bool ? true : false
> > Sure, that works. I can't think of a good reason to have PMCs be able > > to return something fancier than true or false when we ask them for > > their logical negation. (Can any language override logical negation > > to return something besides true/false?)
> Be careful not to stop people doing interesting, useful but entirely > sick things. Current perl has problems rooted in the way it deals > with overloading and tieing that mean some things can't be done > without lots of rewriting.
> I'd say that any operation who's result could be stored somewhere > should (nay, must) be able to return a fully fledged PMC.
But right now, they can't do that, because the 'PMC* dest' could be any type (I suppose every logical op handler could destroy dest and init whatever type it actually wants to return, but - even if that's legal - it's a little tacky). All that can be done is to call methods on the existing destination PMC, which is pretty restrictive sometimes, e.g. in the case of RubyInteger which is never false (no, not even 0).
> That is to say, in "if ( !exp1 ) { ... }", !exp1 merely has to be true > or false, while $foo = !exp1 leaves !exp1 needing to be all manner of > things.
But !exp doesn't need to translate to evaluating exp and then using the not op. You could parse it so that '!' is the postincrement operator if you like, and generate IMCC accordingly. Or that '!' does 'invoke("!")' on your PMC, which can do many weird and wonderful things.
By definition 'boolean not' should return a boolean value, and should work in a fairly predictable way on _any_ PMC, to aid interoperability between parrot targets; ditto for and/or/xor; and (as outlined in my previous message to the list) only get_bool needs to be implemented to provide for the whole set of logical ops.
I suppose it boils down to whether 'and' means 'semi-predictable white box logical and' or 'Yet Another Operator Name To Abuse', much the same way that sick and twisted people can override C++ operators to do evil things :>.
> If I may be so bold as to say it, maybe the PMC design shouldn't be closed > just yet.
I don't think it is. I may be wrong, but I think the only thing Dan was trying to close was the internal structure of PMCs, not the exact implementations. I think there are already a few reorganizations and rethinks queued up. We really can't freeze the hierarchy or implementations until we can implement perl6 with them, plus somebody needs to go through and try to implement another language. Maybe something like Ruby would work well... :-)
Right now, we can't even call non-vtable methods on PMCs.
>That is to say, in "if ( !exp1 ) { ... }", !exp1 merely has to be true >or false, while $foo = !exp1 leaves !exp1 needing to be all manner of >things.
D'oh! Now it's obvious.
I've been conflating the two, which is wrong.
The get_bool vtable method is specifically to retrieve the boolean state of a PMC. It returns 1 or 0, true or false, and we use it to check truthfulness.
We need a logical_not vtable entry that returns a full-fledged PMC that's the logical complement of the not-ted variable.
So "if (!$foo)" probably translates to "unless $foo, BAR" and under the hood does a get_bool on $foo. On the other hand, "$foo = !$bar" calls "not $foo, $bar" and $bar is in a position to decide what it isn't.
If a language really needs "if (!$bar)" to get a full-fledged not-ted $bar and then test it for truthfulness, it can emit "not $$temp, $bar; if $temp, FOO" or something very much like it. -- Dan
--------------------------------------"it's like this"------------------- Dan Sugalski even samurai d...@sidhe.org have teddy bears and even teddy bears get drunk
On Mon, 9 Dec 2002, Dan Sugalski wrote: > At 12:27 AM +0000 12/7/02, Alex Gough wrote: > >That is to say, in "if ( !exp1 ) { ... }", !exp1 merely has to be true > >or false, while $foo = !exp1 leaves !exp1 needing to be all manner of > >things.
> D'oh! Now it's obvious. > I've been conflating the two, which is wrong. > The get_bool vtable method is specifically to retrieve the boolean > state of a PMC. It returns 1 or 0, true or false, and we use it to > check truthfulness. > We need a logical_not vtable entry that returns a full-fledged PMC > that's the logical complement of the not-ted variable.
As in one that actually allows creation of one, or the same as already exists (which does not let one [easily] return a full PMC, just call vtable methods on the one passed in).
> So "if (!$foo)" probably translates to "unless $foo, BAR" and under > the hood does a get_bool on $foo. On the other hand, "$foo = !$bar" > calls "not $foo, $bar" and $bar is in a position to decide what it > isn't.
What about "if($a = !$foo)"? Or: "if(!!$foo)" or "if($a = !!$foo)"? Or if it's part of a bigger expression: "if(($a && !$b) || ($c && !$d))"? Or "if((!$some_set).union($other_set))"? I think using "unless" is more of an optimization than a "default" encoding for not, even if it isn't assigned anywhere permanent.
> If a language really needs "if (!$bar)" to get a full-fledged not-ted > $bar and then test it for truthfulness, it can emit "not $$temp, > $bar; if $temp, FOO" or something very much like it.
What type is $temp?
Or are logical_not et al. to be changed to be able to actually _return_ a PMC rather than just modify a given destination PMC?
I'm sorry to be asking a lot of pesky questions; it's not personal, just business ;).
>On Dec-09, David Robins wrote: >> If I may be so bold as to say it, maybe the PMC design shouldn't be closed >> just yet.
>I don't think it is. I may be wrong, but I think the only thing Dan >was trying to close was the internal structure of PMCs, not the exact >implementations.
Right. Up until recently I'd still waffled over whether the current PMC/vtable setup was the right way to go or not. While I'm still unsure, I've decided we're going to go this way, and so I've started (pending Leo's pending PMC rework) opening up the structure to the bytecode.
> I think there are already a few reorganizations and >rethinks queued up. We really can't freeze the hierarchy or >implementations until we can implement perl6 with them, plus somebody >needs to go through and try to implement another language. Maybe >something like Ruby would work well... :-)
>Right now, we can't even call non-vtable methods on PMCs.
That's on the list to get defined and implemented. :) -- Dan
--------------------------------------"it's like this"------------------- Dan Sugalski even samurai d...@sidhe.org have teddy bears and even teddy bears get drunk
>> At 12:27 AM +0000 12/7/02, Alex Gough wrote: >> >That is to say, in "if ( !exp1 ) { ... }", !exp1 merely has to be true >> >or false, while $foo = !exp1 leaves !exp1 needing to be all manner of >> >things.
>> D'oh! Now it's obvious. >> I've been conflating the two, which is wrong. >> The get_bool vtable method is specifically to retrieve the boolean >> state of a PMC. It returns 1 or 0, true or false, and we use it to >> check truthfulness. >> We need a logical_not vtable entry that returns a full-fledged PMC >> that's the logical complement of the not-ted variable.
>As in one that actually allows creation of one, or the same as already >exists (which does not let one [easily] return a full PMC, just call vtable >methods on the one passed in).
Right. It's up to the language implimentor (and PMC class implimentor) to decide what the right thing to return is.
> > So "if (!$foo)" probably translates to "unless $foo, BAR" and under >> the hood does a get_bool on $foo. On the other hand, "$foo = !$bar" >> calls "not $foo, $bar" and $bar is in a position to decide what it >> isn't.
>What about "if($a = !$foo)"? Or: "if(!!$foo)" or "if($a = !!$foo)"? Or if >it's part of a bigger expression: "if(($a && !$b) || ($c && !$d))"? Or >"if((!$some_set).union($other_set))"? I think using "unless" is more of an >optimization than a "default" encoding for not, even if it isn't assigned >anywhere permanent.
That's language-dependent. I can certainly see it going any one of a half-dozen ways, and it's up to whoever defines their language's behaviour to say how it should work. Parrot can go either way, since we really shouldn't care.
>> If a language really needs "if (!$bar)" to get a full-fledged not-ted >> $bar and then test it for truthfulness, it can emit "not $$temp, >> $bar; if $temp, FOO" or something very much like it.
>What type is $temp?
A temporary PMC of some sort. I bobbled the dollar signs there.
>Or are logical_not et al. to be changed to be able to actually _return_ >a PMC rather than just modify a given destination PMC?
>I'm sorry to be asking a lot of pesky questions; it's not personal, just >business ;).
Pesky questions are important, as they point out a place where someone didn't think clearly. In this case, that someone'd be me. :)
-- Dan
--------------------------------------"it's like this"------------------- Dan Sugalski even samurai d...@sidhe.org have teddy bears and even teddy bears get drunk