There are many math ops that work on Float PMCs but not Integer PMCs.
e.g.:
% cat foo.pir
.sub main
P1 = new .Float
P1 = 123
P1 = exp P1
print P1
print "\n"
.end
% ./parrot foo.pir
Method 'exp' not found
current instr.: 'main' pc 12 (foo.pir:6)
The assignment of 123 autoconverts the float to an integer, which
doesn't support the 'exp' method that's defined in the Float pmc.
(Change the 123 to 123. and it works fine.)
Given the morphing that typically happens, I'd expect to be able to
do numeric (as opposed to integer) ops on integer pmcs and have it
autoconvert to float.
exp is one of *many* math ops this needs to be done. Check out the
Methods POD section of src/pmc/float.pmc for the list.
> P1 = new .Float
> P1 = 123
> The assignment of 123 autoconverts the float to an integer, which
> doesn't support the 'exp' method that's defined in the Float pmc.
> (Change the 123 to 123. and it works fine.)
>
> Given the morphing that typically happens, I'd expect to be able to
> do numeric (as opposed to integer) ops on integer pmcs and have it
> autoconvert to float.
I'm not sure which parts of the fine documentation I've failed to read or
digest, and whether I'm about to criticise something fundamental that
someone(s) have worked on for a long time, but from reading this message
alone this whole behaviour just feels plain wrong. Sort of "principle of
most surprise" It doesn't seem very intuitive that the virtual machine's
basic types (or at least the ones that have names suggesting that they are
basic) are built to jump sideways at the least provocation.
I can see value in a type .Number, which changes internal representation and
vtable as and when necessary, but I'd still expect it to report "Number"
when asked what type it is, because the internal representation would be a
mere implementation detail. But I'd expect a type .Float to behave much like
a C float and coerce values fed to it, rather than metamorphose to their
type.
Was this built in morphing the cause of the problems Leo was describing in
trying to make a user defined class that is derived from Int?
Nicholas Clark
Just to add a "me too" of sorts -- I didn't really notice it when
most everything was using "Perl*" PMCs, but now that we've separated
things out into base types the behavior seems very odd, unexpected,
and somewhat undesirable.
The following is also bit unexpected (but at least it's consistent):
.sub main :main
$P1 = new .Integer
assign $P1, 2
#...and other ops on $P1...
$P0 = new .Float
assign $P0, $P1
$S0 = typeof $P0
print $S0 # outputs "Integer" (!)
print "\n"
.end
In short, the only way to get an integer value into a .Float PMC
seems to be to pass it through an N register:
$P1 = new .Integer
# ...
$P0 = new .Float
$N1 = $P1
assign $P0, $N1 # $P0 now remains a .Float
Here I agree with Nicholas -- there may be some invisible
design decisions behind this, but it just feels very wrong.
Pm
> Just to add a "me too" of sorts -- I didn't really notice it when
> most everything was using "Perl*" PMCs, but now that we've separated
> things out into base types the behavior seems very odd, unexpected,
> and somewhat undesirable.
This isn't related to Perl* PMCs vs. other PMCs at all.
$ cat p.pir
.sub main
P1 = new .PerlNum
P1 = 123
P1 = exp P1
print P1
print "\n"
.end
$ ./parrot -t2 p.pir
# find_method class 'LexInfo' method 'declare_lex_preg': NCI
# find_method class 'PerlInt' method 'exp': no
# find_method class 'Integer' method 'exp': no
# find_method class 'Integer' method 'exp': no
Method 'exp' not found
current instr.: 'main' pc 12 (p.pir:5)
leo
>
> I can see value in a type .Number, which changes internal
> representation and
> vtable as and when necessary, but I'd still expect it to report
> "Number"
> when asked what type it is
[ ... ]
> Was this built in morphing the cause of the problems Leo was
> describing in
> trying to make a user defined class that is derived from Int?
Exactly. A method, being it vtable, NCI (aka METHOD PMC* exp()), or MMD
dispatches on the type number(s) of the PMC(s). Whenever the type
number changes, strange things start happening. This gets worse, when
inheritance is involved too.
Changing the type name e.g. 'Integer' -> 'BigInt' is just the visible
effect of it, but of course as undesirable as broken method dispatch.
Before proposing any solution, we still have to clarify, what our
(scalar) PMCs really are. But I see light at the end of the tunnel.
> Nicholas Clark
leo
$P1 = new .Float
$P1 = 1.2
$N1 = cosh $P1
op/trans.t tests some of these math ops, but only against N registers. There are tests for the
complex PMC, but not Float.
Add tests for all math opcodes for Float & Integer.
> [coke - Tue Apr 11 07:05:31 2006]:
>
> There are many math ops that work on Float PMCs but not Integer PMCs.
>
> e.g.:
> % cat foo.pir
> .sub main
>
> P1 = new .Float
> P1 = 123
> P1 = exp P1
> print P1
> print "\n"
> .end
> % ./parrot foo.pir
> Method 'exp' not found
> current instr.: 'main' pc 12 (foo.pir:6)
>
> The assignment of 123 autoconverts the float to an integer, which
> doesn't support the 'exp' method that's defined in the Float pmc.
> (Change the 123 to 123. and it works fine.)
>
> Given the morphing that typically happens, I'd expect to be able to
> do numeric (as opposed to integer) ops on integer pmcs and have it
> autoconvert to float.
>