Skip to content

[lang-model]: Integer-rep/Machine-type agnostic basic unary ops (e.g. Pred/Succ) (trivial, narrow, sem) #229

@archaephyrryx

Description

@archaephyrryx

Currently, there is no way to apply relatively simple Expr-based tweaks to a numeric value without knowing its underlying Machine-Type/Integer-rep (i.e. which of BaseType::{U8, U16, U32, U64} it conforms to). Though the direct need for these specific constructions may be obviated partially via value-model redesigns (e.g. #228), there is arguably a case to be made for type/rep-agnostic Successor and Predecessor primitives in the Expr-model, ideally as UnaryOp variants.

In particular, we can already see a couple of cases in opentype.rs where we either add or subtract a fundamentally invariant constant of 1, which can only be constructed within the Expr model with full knowledge of the inferred ValueType of an incoming operand:

It is worth noting that the vast majority of these cases are in the context of working with various forms of array-boundary conditions:

LastIndex(seq) := Pred(SeqLength(seq))

and the natural converse thereof,

NumRepeats(MaxIndex) := Succ(MaxIndex)

where seq is an instantiated incoming Expr that has kind Seq, and MaxIndex is an instantiated incoming Expr representing the maximum index we wish to capture in a RepeatCount-style format we are generating the iteration-count value for.

Similarly, we observe that the array of first partial differences of a pre-existing numeric array has the property

SeqLength(SeqDeltas(seq)) = Pred(SeqLength(seq))

and that, though slightly more niche, the length of the optional loca table in OpenType is Succ(NumGlyphs).

Given all these constructions, it seems fairly reasonable to introduce a Pred and Succ operator with the implicit type-signature Num a => a -> a (or, as in line with other proposed UnaryOp variants as in #228, an optionally-overloaded casting op (Num a, Num b) => a -> b). In this way, the actual type of an Expr that depends on the possibly-obfuscated ValueType of an incoming variable, or the abstract type-level semantics of a fixed operator like Expr::SeqLength or Format::Pos, can be left out, and errant Expr::U16(1) and similar can be avoided when the significance of the value 1 is arguably a workaround for the lack of a dedicated Succ or Pred primitive.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions