Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

logical_not issue

7 views
Skip to first unread message

David Robins

unread,
Dec 3, 2002, 4:29:57 PM12/3/02
to perl6-i...@perl.org
Yes, me again....

Most of the time, in the PMC logical_not method, one can write:

void logical_not (PMC* dest) {
dest->vtable->set_integer_native(INTERP,dest,NOT_SELF);
}

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....]

Enlightenment appreciated as always.

Dave
Isa. 40:31

Dan Sugalski

unread,
Dec 3, 2002, 4:56:53 PM12/3/02
to David Robins, perl6-i...@perl.org
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)
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

David Robins

unread,
Dec 3, 2002, 5:47:17 PM12/3/02
to Dan Sugalski, perl6-i...@perl.org
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.

Dave
Isa. 40:31

Dan Sugalski

unread,
Dec 6, 2002, 5:01:21 PM12/6/02
to David Robins, perl6-i...@perl.org
At 5:47 PM -0500 12/3/02, David Robins wrote:
>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?

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.

Alex Gough

unread,
Dec 6, 2002, 7:27:03 PM12/6/02
to Dan Sugalski, perl6-i...@perl.org
#### [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.

Nicholas Clark

unread,
Dec 7, 2002, 12:43:34 PM12/7/02
to Dan Sugalski, David Robins, perl6-i...@perl.org
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?

Nicholas Clark
--
Befunge better than perl? http://www.perl.org/advocacy/spoofathon/

David Robins

unread,
Dec 9, 2002, 3:19:39 AM12/9/02
to Dan Sugalski, perl6-i...@perl.org
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.

[snip]

> >- 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.

Dave
Isa. 40:31

David Robins

unread,
Dec 9, 2002, 3:35:08 AM12/9/02
to Alex Gough, Dan Sugalski, perl6-i...@perl.org
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 :>.

Dave
Isa. 40:31

Steve Fink

unread,
Dec 9, 2002, 12:58:35 PM12/9/02
to David Robins, Dan Sugalski, perl6-i...@perl.org
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. 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.

Dan Sugalski

unread,
Dec 9, 2002, 1:34:42 PM12/9/02
to Alex Gough, perl6-i...@perl.org
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.

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.

David Robins

unread,
Dec 9, 2002, 6:58:08 PM12/9/02
to Dan Sugalski, Alex Gough, perl6-i...@perl.org
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 ;).

Dave
Isa. 40:31

Dan Sugalski

unread,
Dec 9, 2002, 8:22:25 PM12/9/02
to Steve Fink, David Robins, perl6-i...@perl.org
At 9:58 AM -0800 12/9/02, Steve Fink wrote:
>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 Sugalski

unread,
Dec 9, 2002, 8:32:44 PM12/9/02
to David Robins, Alex Gough, perl6-i...@perl.org
At 6:58 PM -0500 12/9/02, David Robins wrote:
>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).

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. :)

0 new messages