MMD table creation looks now at parent and tries to install inherited
MMD functions. But that's error prone and bulky and I'm too dumb to do
it right.
Currently one test (t/pmc/pmc_43.pasm) is failing due to wrong inheritance.
TODO
1) adjust the PMC compiler not to emit MMD setup for inherited methods
2) allow multiple inheritance in PMCs, e.g.
pmclass PyInt extends PyObject extends Integer
(some hacks are already present in config/*/*.pl to do the same with
OrderedHash)
Takers wanted,
thanks
> Currently one test (t/pmc/pmc_43.pasm) is failing due to wrong inheritance.
Actually not because of inheritance. The implementation of
PerlUndef.logical_xor was bogus. I've fixed this and the test.
leo
I took a look into this. Apparently, in Perl5, the result of xor'ing
undef with anything is undef. I'm not suggesting that this is either
right or wrong (it actually was surprising to me), but if Parrot wanted
to provide this behavior, the seemingly obvious way for this to be coded
would be for PerlUndef to have the following:
void logical_xor (PMC* value, PMC* dest) {
MMD_DEFAULT: {
VTABLE_set_pmc(INTERP, dest, SELF);
}
Unfortunately, this does not work as inheritance seems to take
precedence over defaults. I think that this should be the other way
around: a subclass should be able to easily override all MMD operations
for a given method.
Finally, I took a look at Parrot_mmd_register_parents. This seems more
complicated than it needs to be, and that is because it is only looking
at the mmd table (the final results after overriding) instead of at the
specific overrides (the various _temp_mmd_init arrays).
An alternate approach would be for the make process to generate a
function that registers a given class into a given type slot, and code
to call each parent in order (top down) to override their slots as required.
A concrete example might help:
Parrot_PerlInt_mmd_init(interp, entry) {
const MMD_init _temp_mmd_init[] = {...};
Parrot_mmd_register(interp, entry, _temp_mmd_init, N_MMD_INIT);
}
followed later by the following calls:
Parrot_scalar_mdd_init(interp, entry);
Parrot_Integer_mmd_init(interp, entry);
Parrot_PerlInt_mmd_init(interp, entry);
- Sam Ruby
I'd leave that to language lawyers. Undef (like null in SQL) could be
interpreted to mean "I don't know", and a case could be made that "I
don't know" xor'ed with anything is "I don't know".
Furthmore, the concept of a logical xor seems to be a Perl innovation.
Languages like C and Python don't have such a concept.
Finally, Perl doesn't seem to be consistent. Anything xor undef always
seems to return the leftmost argument.
*shrug*
>>Unfortunately, this does not work as inheritance seems to take
>>precedence over defaults.
>
> Partly. Specific functions are set last.
The precedence seems to be specific functions, inheritance, and then
defaults.
>>... I think that this should be the other way
>>around: a subclass should be able to easily override all MMD operations
>>for a given method.
>
> The problem is that the passed in mmd init list has no indication, if a
> default function is installed or a inherited or a specific one.
The passed in mmd init list only has specific and defaults.
>>Finally, I took a look at Parrot_mmd_register_parents.
>
> Don't ;-)
Oops. ;-)
>>... This seems more
>>complicated than it needs to be,
>
> Well, yes. But I'm not even sure if it's worth the effort to improve it.
> The static MMD table doesn't handle dynamic inheritance. While you can
> install a function with mmdvtregister, this is just for a pair of types,
> which is rather useless for classes that inherit from one of the types.
> But which other functions for which types should be registered too?
>
> This is the reason for the proposal of going fully dynamic with MMD too.
OK, I'll leave this alone unless I have a specific problem that I need
to fix. Hopefully by then, all this will go away.
- Sam Ruby
> I took a look into this. Apparently, in Perl5, the result of xor'ing
> undef with anything is undef. I'm not suggesting that this is either
> right or wrong (it actually was surprising to me),
Yep. It doesn't really follow the definition of xor, nor does it match
the implementation of other types.
> Unfortunately, this does not work as inheritance seems to take
> precedence over defaults.
Partly. Specific functions are set last.
> ... I think that this should be the other way
> around: a subclass should be able to easily override all MMD operations
> for a given method.
The problem is that the passed in mmd init list has no indication, if a
default function is installed or a inherited or a specific one.
> Finally, I took a look at Parrot_mmd_register_parents.
Don't ;-)
> ... This seems more
> complicated than it needs to be,
Well, yes. But I'm not even sure if it's worth the effort to improve it.
The static MMD table doesn't handle dynamic inheritance. While you can
install a function with mmdvtregister, this is just for a pair of types,
which is rather useless for classes that inherit from one of the types.
But which other functions for which types should be registered too?
This is the reason for the proposal of going fully dynamic with MMD too.
> An alternate approach would be for the make process to generate a
> function that registers a given class into a given type slot, and code
> to call each parent in order (top down) to override their slots as required.
I don't think that this would help currently because the mmd_init table
already has (defaulted) and other static inheritance. Dunno.
> - Sam Ruby
leo
My bad. I misinterpreted an empty string as an undef. Here's the test
I ran:
my $a = undef;
$c = $a xor $a;
print "$c";
$c = $a xor 0;
print "$c";
$c = $a xor 1;
print "$c";
$c = 2 xor $a;
print "$c";
$c = 3 xor 4;
print "$c";
$c = 0 xor $a;
print "$c";
$c = 5 xor 0;
print "$c";
$c = 0 xor 6;
print "$c";
print "\n";
perl -v returns:
This is perl, v5.8.4 built for i386-linux-thread-multi
- Sam Ruby
> Sam Ruby <ru...@intertwingly.net> wrote:
>
>> I took a look into this. Apparently, in Perl5, the result of xor'ing
>> undef with anything is undef. I'm not suggesting that this is either
>> right or wrong (it actually was surprising to me),
>
> Yep. It doesn't really follow the definition of xor, nor does it match
> the implementation of other types.
Which Perl5 (xor, undef) would this be? It does not look like the
result is undef around here:
eirik@blackbox:~$ perl -le 'print defined($_)?"defined":"undef", ": «$_»"
for map {(undef xor $_), ($_ xor undef), (undef ^ $_), ($_ ^ undef)}
"string", "", -1, 0, 1 , 2'
defined: «1»
defined: «1»
defined: «string»
defined: «string»
defined: «»
defined: «»
defined: «»
defined: «»
defined: «1»
defined: «1»
defined: «4294967295»
defined: «4294967295»
defined: «»
defined: «»
defined: «0»
defined: «0»
defined: «1»
defined: «1»
defined: «1»
defined: «1»
defined: «1»
defined: «1»
defined: «2»
defined: «2»
eirik@blackbox:~$ perl -v
This is perl, v5.8.5 built for i686-linux
Copyright 1987-2004, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using `man perl' or `perldoc perl'. If you have access to the
Internet, point your browser at http://www.perl.com/, the Perl Home Page.
eirik@blackbox:~$
--
C++ is the only current language making COBOL look good.
-- Bertrand Meyer
> Which Perl5 (xor, undef) would this be? It does not look like the
> result is undef around here:
> eirik@blackbox:~$ perl -le 'print defined($_)?"defined":"undef", ": «$_»"
> for map {(undef xor $_), ($_ xor undef), (undef ^ $_), ($_ ^ undef)}
> "string", "", -1, 0, 1 , 2'
This "xor" is returning the bool values, which is quite different to
returning a value according to the xor of the booleans.
perl -le 'print defined($_)?"defined":"undef", ": «$_»"
for map {(undef xor $_), ($_ xor undef)}
"string", "", undef, -1, 0, 1 , 2'
dropping bitwise xor, and including "undef xor undef" reveals that Perl5
has a different opinion then Parrot (or Perl6?).
inline op xor(out INT, in INT, in INT) :base_core {
$1 = ($2 && ! $3) ? $2 : ($3 && ! $2) ? $3 : 0;
goto NEXT();
}
static void
mmd_fallback_lxor_pmc(Parrot_Interp interp, PMC *left, PMC *right, PMC *dest)
{
INTVAL left_truth, right_truth;
PMC *true;
left_truth = VTABLE_get_bool(interp, left);
right_truth = VTABLE_get_bool(interp, right);
if (left_truth && !right_truth)
true = left;
else if (!left_truth && right_truth)
true = right;
else {
VTABLE_set_integer_native(interp, dest, 0);
return;
}
VTABLE_set_pmc(interp, dest, true);
}
We need language lawyers ;)
leo
inline op xor(out INT, in INT, in INT) :base_core {
$1 = ($2 && ! $3) ? $2 : ($3 && ! $2) ? $3 : 0;
goto NEXT();
}
> We need language lawyers ;)
IANAL, but I am a mathematician. Because C<xor> necessarily always
depends on *both* its arguments, analogies with C<and> and C<or> are
inappropriate. C<xor> cannot short-circuit, and it is not sensible
to return as result either of the arguments. So the above macro
is misguided nonsense.
Perl5 C<xor> always returns a "standard" boolean value, i.e.
dualvar(0, '') or dualvar(1, '1'). Perl6/Parrot should do the same
thing.
Mike Guy
Try:
perl -le "print 'day' xor 'night'"
On the version of Perl I have installed, I get "day" as the result.
- Sam Ruby
print("day\n" xor "night\n");
--
Gordon Henriksen
IT Manager
ICLUBcentral Inc.
gor...@iclub.com
> inline op xor(out INT, in INT, in INT) :base_core {
> $1 = ($2 && ! $3) ? $2 : ($3 && ! $2) ? $3 : 0;
> goto NEXT();
> }
>> We need language lawyers ;)
> IANAL, but I am a mathematician. Because C<xor> necessarily always
> depends on *both* its arguments, analogies with C<and> and C<or> are
> inappropriate. C<xor> cannot short-circuit, and it is not sensible
> to return as result either of the arguments.
C<xor> can't of course be short-circuit and above code isn't. Both values
are evaluated WRT trueness, always.
> ... So the above macro is misguided nonsense.
Not quite. It gives one value if one is true or 0 (false). This is more
information then the perl5 implementation returns. The returned value (if
any) is still true but usable, if I just want one of both. Well that's
"logical xor" - not binary xor.
> Perl5 C<xor> always returns a "standard" boolean value, i.e.
> dualvar(0, '') or dualvar(1, '1'). Perl6/Parrot should do the same
> thing.
Maybe, IANAL.
> Mike Guy
leo
Agreed. At some point this probably belongs on perl6-languages (and
apologies if this posting to p6i is therefore inappropriate). But if
the following hold (Perl 5):
print (0 and "hello"); # outputs "0"
print ("" and "hello"); # outputs ""
print (0 or "hello"); # outputs "hello"
print ("" or "hello"); # outputs "hello"
print ("" or 0); # outputs "0"
print (0 or ""); # outputs ""
print (not("" or 0)); # outputs "1"
print (not("a" and "b")); # outputs ""
it seems like one should be able to do:
print (0 xor "hello"); # outputs "hello"
print ("" xor "hello"); # outputs "hello"
print ("hello" xor 0); # outputs "hello"
print ("hello" xor ""); # outputs "hello"
print ("world" xor "hello"); # outputs ""
print (0 xor ""); # outputs "1"
print ("" xor 0); # outputs "1"
Just as C<or> returns its first non-false argument, the interpretation
of C<xor> would be that it returns its single non-false argument, or 1 if
both (all?) arguments logically evaluate to false.
> > Perl5 C<xor> always returns a "standard" boolean value, i.e.
> > dualvar(0, '') or dualvar(1, '1'). Perl6/Parrot should do the same
> > thing.
Keep in mind that in Perl 6 the boolean forms of C<and>, C<or>, and C<xor>
(the ones that always return 0 or 1) are C<?&>, C<?|>, and C<?^>.
So perhaps C<xor> should be able to return more than just 0 or 1.
Pm
Gordon mentioned the precedence problem here. I've not replied to his
message because I couldn't be bothered to fix up the quoting and
attributions. s/le/wle/ gives the hint too.
Mike is quite right of course. And the code which handles this is one
of the more simple parts of perl5. Provided you're not too worried
about what's going on under the macros, I suppose.
if (SvTRUE(left) != SvTRUE(right))
RETSETYES;
else
RETSETNO;
--
Paul Johnson - pa...@pjcj.net
http://www.pjcj.net
Odd, since xoring two true values should give a false one.
Remember the precedence of xor. This is parsed:
perl -le "print('day') xor 'night'"
Luke
> Just as C<or> returns its first non-false argument, the interpretation
> of C<xor> would be that it returns its single non-false argument, or 1 if
> both (all?) arguments logically evaluate to false.
Yep, except *0* if both evaluate to either true or false.
> Pm
leo
Oh yeah, I got my truth values messed up there--I don't know what I was
typing. I stand corrected, although the return value in this case should
probably be "" in a string context (or, to follow Perl 5 somewhat, whatever
corresponds to the value of "false" for the type of the last argument).
Pm