poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Generalizing the big/little attribute


From: Jose E. Marchesi
Subject: Re: Generalizing the big/little attribute
Date: Wed, 22 Jul 2020 11:27:02 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Hi Bruno!
Sorry for the delay in replying to this.

First of all, thank you very much for your suggestions.  There is a lot
to improve/complete in Poke's design!  Much appreciated :)

    Currently, big/little applies only integral struct fields:
    
    deftype test =
      struct
      {
        little uint32 a;                        // OK
        little uint8[3] b;                      // ERROR
        little struct { uint8 x; uint8 y; } c;  // ERROR
      };
    
    A simple generalization to make it apply to integral types, then
    
    deftype test =
      struct
      {
        little uint32 a;                        // OK
        little uint8[3] b;                      // would be OK
        little struct { uint8 x; uint8 y; } c;  // ERROR
      };

    However, another generalization would be more powerful:
    [...]

The big/little attribute, as you mention, is currently associated with
struct fields.  It is not associated with integral types.  Implementing
the "simple generalization" would involve adding a new attribute to
struct types, with the endianness to use.  This would be easy.

However, at this point I would generalize the endianness in a way it
becomes an attribute of certain types, not struct fields.  This way, you
could write [1]:

deftype MSBInt32 = big int<32>;
deftype MSBOff32 = offset<big int<32>,B>;
deftype MSBArray = big int<32>[10];
deftype Foo = little struct { MSBInt32 magic_in_big; ... };
deftype IntegralFoo = struct little uint<32> { ... };

Integral values can't be mapped themselves, so the endianness attribute
of an integral type becomes relevant when using an l-value map:

(poke) MSBInt32 @ 0#B = 666

This would require a few changes in the type system:

- Two integer types with different endianness are different types.
- Casting/coercing a ENDIAN1 u?int<N> type into ENDIAN2 u?int<M>
  involves changing the endianness from ENDIAN1 to ENDIAN2.

But overall I don't think it will require a lot of work.

    So, in any place where you can use a type name, you could also add a
    little/big attribute, and it has a recursive effect.

Using the approach of associating endianness to types, it would be
natural to support a new type specifier `{little,big} typename', that
constructs a proper (derived) type itself:

  deftype LSBInt32 = | little MSBInt32 |;
                     +--- type spec ---+
 
and

  (poke) | little MSBInt32 | @ 0#B
         +--- type spec ---+

Then we could use `{little,big} typename' anywhere a type specifier is
expected, like casts, function formal arguments, etc.

    Method invocations would not only have an implicit SELF argument, but
    maybe also an implicit ENDIANNESS_OVERRIDE argument?
    
If you mean that any mapping performed in an method (or in a function
called from a method) will inherit the endianness of the struct, I don't
think that is a good idea.  Using the schema proposed above the
referenced struct fields would be available in whatever endianness their
type mandates, which may be different to the endianness of the struct
(see the magic_in_big field above):

  big struct
  {
    [...]

    int i;

    method foo = int:
    {
      return i + uint<8> + 
    }
  };

WDYT?

[1] We may have to wrestle/massage the syntax to avoid ambiguities, but
    let's asume for now this syntax works :)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]