On 2020-01-30 17:20, Veesh Goldman wrote:
Hi Todd,
A couple of things.
One is that Int and int are totally unrelated concepts. Captial Int is a high level concept, which has a type constraint related to it, and belongs to raku's object system. Lowercase int is a special case, it's only for the interface with C, and it represents a low level piece of memory. It's not that one is bounded and the other has Larry magic sprinkled on it (even though it happens to have that), they're totally conceptually different.

Raku doesn't actually know what resides in the C space, because int doesn't really talk to raku, so in order to do something meaningful with that memory, you need to make sure it's dealt with in the right context. What I mean to say is that raku won't stop you from assigning negative numbers to an unsigned int, b/c it doesn't belong in the Object system. It just defines a way to send raku values down into C-world (which, despite the name, is not a pleasant place).

When you try to use a native variable like a raku variable, you have 2 choices. Either raku would blow up in your face and die (probably not what you want), or raku would wrap the variable in something it understands (autoboxing, as explained above). If you want to get a more specific wrapper, nothing is stopping you from implementing that yourself. In fact, someone posted earlier in this thread an implementation where you wrap your native uints in an object which would point to the specific type you want.

I believe the issue that you're having with the array is also because of autoboxing. Observe the following code:
use NativeCall
my $ary = CArray.new( 0xff );
say $ary[0];
#  -1
multi sub check-it (uint8 $i) { say 'uint8' }
multi sub check-it(Int $i) { say 'Int' }
check-it $ary[0]
# uint8
That proves that raku KNOWs that it's a uint8, just many operations will autobox it. Perhaps we need some more clarity about autoboxing rules.

What is further interesting, which was a point I think you were making, is if we add another multi:
multi sub check-it (int8 $i) { say 'int8' }
check-it $ary[0];
# Ambiguous call to 'check-it(Int)'; these signatures all match:
# :(uint8 $i)
# :(int8 $i)

So this may actually indicate that raku does not actually know it's a uint8, it just knows that it's supposed to be 8 bits long. This is what I've got, but I think the point here is that int represents memory, and Int is an object, and they're two totally distinct concepts so what applies to one is irrelevant to the other.

Hope this helps,
Veesh

Hi Veesh,

I adored the letter.  It was extremely well written and very
easy to follow.

Your explanation of bounding was the first time I actually
understood what was actually happening with bounding:
"liberate from C ..." and manipulate it in Raku-World.

I had previously been told I did not understand C Pointers,
which I though was rather odd as that is one of the few
things about C that I actually understand.  I had no idea
where they were coming from.

I wrote myself a little program to demonstrate
what I learned:

<intTest.pl6 >
#!/usr/bin/env perl6
use NativeCall;
constant BYTE     := uint8;
constant BYTES    := CArray[BYTE];
my BYTES  $u = CArray[BYTE].new( 0xFF, 0x7f );

say    "u[0] base 10 boxed to Int <", $u[0], ">";
say    "u[0] ^name after boxing   <", $u[0].^name, ">";
printf "u[0] OR  0x00 base 2      <%08s>\n", ($u[0] +& 0xFF).base(2);
say    "u[0] OR 0x00 base 10      <", ($u[0] +| 0x00).base(10), ">";
say    "u[0] OR 0x00 base 16      <", ($u[0] +| 0x00).base(16);
printf "(u[0] +3) +| 0x00)        <%08s>\n", (($u[0] +3) +| 0x00).base(2);
</intTest.pl6 >

$ intTest.pl6
u[0] base 10 boxed to Int <-1>
u[0] ^name after boxing   <Int>
u[0] OR 0x00 base 2       <11111111>
u[0] OR 0x00 base 10      <255>
u[0] OR 0x00 base 16      <FF>
u[0] OR  0x00 base 2 +3   <00000010>

Going over it

    $u[0] base 10 boxed to Int <-1>

shows that $u[0] got unbounded into Raku-World
for operation on it as an Int.  The "-1" is
because in the unbounding processed the cardinal
number inside $u[0]'s high bit as a sign bit, even
though $u[0] is an unsigned integer.

It would be nice if it unbounded to a UInt as
both are unsigned integers.  But Int also
works, you just have to be wary of the upper
bit in the uint being interpreted as a sign bit:
use "-1" in place of 0xFF, etc..

   $u[0] ^name after boxing   <Int>

Show that $u[0] was being operating on AFTER
it was unbounded and that the reason why ^name
gets a participation trophy is because it is
returning the name of the C-World liberated
variable, not the raw variable.

There is a trail back to the raw variable or
the variable could not be unbonded, but ^name is
not cleaver enough to follow the trail.  You
just have to be aware of ^name's limitation and
be glad it return a variable that is similar.
I can live with it.

   $u[0] OR 0x00 base 2       <11111111>
   $u[0] OR 0x00 base 10      <255>
   $u[0] OR 0x00 base 16      <FF>

Show the actual bit value of $u[0].  AND
that the actual value of $u[0] was not altered,
meaning it was not "stolen", as I originally though.
(WHAT??? ME WRONG??? NEVER!!! Well, maybe sometimes
too often.)

The bitwise OR forces "say" to give me the raw value.
It is not entirely clear if $u[0] was liberated
from C-World (unbounded), operated on, then
re-enslaved to C-World (rebounded), or just
had a machine code OR visited upon it, but it
works so ...

And it is not entirely clear why "say" thinks it
needs to unbound the variable to print it.

It is a bit annoying that I have to jump through
those hoops to see the actual bit patterns, but
I will certainly get use to it.

   $u[0] OR  0x00 base 2 +3   <00000010>

Is just me torturing the poor dear with a bit over
run off the left side.  Something that will
never happen if magic Larry powder was applied and,
if I were to speculate, the reason will Larry
created UInt and Int in the first place.

Thank you again for the marvelous letter!

:-)

-T

Reply via email to