Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Tracked by #186
archaephyrryx opened this issue Nov 26, 2024 · 0 comments · Fixed by #230

Comments

@archaephyrryx
Copy link
Contributor

archaephyrryx commented Nov 26, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant