On Mon, 6 Sep 2004, Aaron Sherman wrote:
> > Sized low-level types are named most generally by appending the number
> > of bits to a generic low-level type name:
> >
> > [...] int1 int2 int4 int8 int16 int32 int64
> >
>
> Ok, so Parrot doesn't have those. Parrot has "int".

The above "generic low-level types" are specific instances of a more general
specification-based type system, with features grouped roughly as:

    * what range of values _must_ be storable, and what range of values
      _may_ be storable

    * what do you want to do if an attempt is made to store values outside
      the latter range

The possible specifications for "out of range" behaviour should include:

  bound   - force to nearest bound
  ignore  - don't store, keep the previous value
  throw   - "die" in perl-speak
  use(CONSTANT) - for example, use(undef)
  wrap    - apply a modulus

  fastest - do whichever of the above gives the best performance on the
            current platform

Presumably the default would be :out_of_range(wrap,lax), subject to
modification by pragmata of course.

The range should be specifyable as a numeric range, with an optional
parameter:

  strict  - use exactly the limits specified
  lax     - use the natural limits of the underlying implementation (unless
            some contrary pragma is in effect, for testing purposes)

Specification of signed and/or unsigned bitfields is problematic; usually
they're used because the author assumes they will only-just-fit-into a
specific implementation type, in which case the "lax" parameter would give
the same benefit for a more readable range specification.

Only in specific applications like CRC computation would an actual specific
binary modulus be appropriate.

Requirements of less expressive languages could be written in terms of
these; in perl6-ish terms, perhaps something like this:

  my int $int1  :range(         -1..0         ) :out_of_range(wrap);
  my int $int2  :range(         -2..1         ) :out_of_range(wrap);
  my int $int4  :range(        -16..15        ) :out_of_range(wrap);
  my int $int8  :range(       -128..127       ) :out_of_range(wrap);
  my int $int16 :range(     -32768..32767     ) :out_of_range(wrap);
  my int $int32 :range(-2147483648..2147483647) :out_of_range(wrap);
  my int $int64 :range(-9223372036854775808..9223372036854775807) :out_of_range(wrap);
  my int $int128 
:range(-170141183460469231731687303715884105728..170141183460469231731687303715884105727)
 :out_of_range(wrap);
  my int $byte  :range(          0..255       ) :out_of_range(wrap);
  my int $bool  :range(          0..1         ) :out_of_range(use(1));

In my opinion we should target this case: a language that lets you specify to
this level of detail, and automatically infers the most efficient low-level
type from the given specification.

To implement this, should we consider attaching a "store" (native) method to
each integer register, which could implement the required logic for each of
the above cases? Or would we need perhaps a vtable, with both "store" for
when we're interpreting, and "generate_jit_store" for when we're jitting?

-Martin


Reply via email to