Conversation
sbrantq
force-pushed
the
structs
branch
5 times, most recently
from
July 31, 2026 01:55
573a322 to
31559fb
Compare
Type identity is the ordered sequence of slot representations, so slots may have different types; contrast array-representation, whose identity is (element type, length). Like array types, tuple types are synthesized on demand by get-representation rather than registered by a platform, so their names round-trip. The two representations stay separate: tuples get their own struct, their own constructor and their own clause in repr->prop, beside the array ones rather than merged with them.
Each function that special-cases arrays gains an independent tuple clause: repr-ulps, midpoint, random-generate, real->repr, repr->real and the JSON conversions in float.rkt, and the four Rival flattening walkers in core/arrays.rkt. Tuple clauses recurse per slot with that slot's own representation; array clauses are carried over verbatim. float.rkt is purely additive. In arrays.rkt three walkers change from if to cond so the two clauses can sit side by side, and three aggregate guards gain a tuple disjunct after the array one; the array bodies themselves are unchanged, so deleting arrays later means deleting one clause per walker. Because flattening already returns one representation per scalar leaf, and make-discretizations already builds one discretization per leaf, a mixed-precision tuple core gets per-slot ground truth with no change to the Rival shim.
Registers tuple as a real operator and adds tuple clauses alongside the array ones in the syntax checker, the type checker and check-spec!'s inference, in the same style and shape. Unlike array, tuple slot types need not agree, and ref over a tuple is typed by its literal index. A tuple type is compatible with any scalar ambient :precision, since its identity already records every slot's precision. An argument annotation may name a tuple type in :precision. Rather than teach the shared property validator a tuple mode, strip-tuple-precision validates and removes such a prop at the one call site that allows it, so core-level and expression-level :precision still reject tuple types.
A platform cannot enumerate one impl per sequence of slot types, and which sequences occur is chosen by the program. So the constructor and the per-slot accessors are synthesized the first time a shape is used, the same way get-representation already synthesizes the type, and registered into the active platform with costs taken from the platform's own per-representation move costs. fpcore->prog gets a tuple clause beside its existing neg, cast and ref clauses, so the general impl resolver is left alone. Generated shapes ride the existing platform-extensions list, ahead of the fpcore extensions, so they survive the platform re-activation that sandbox.rkt performs before every run; without that an already-lowered program would name a dead impl. Accessors are unary with the index baked into the impl, because the index determines the output type and so cannot be resolved by get-fpcore-impl on input types alone.
A tuple has as many slots as it was written with, so operator-info's single fixed signature cannot describe it. Three places pair a spec application's arguments with their types: egg-parsed->expr, rebuild-enode and add-enode. Asked about a tuple, they would see a two-element signature and drop every slot past the second. spec-itypes reports the argument types at the arity the term actually has. It is local to this file, and only tuple is special-cased: every other operator, array included, is still reported exactly as operator-info reports it, so array terms behave as before, truncation and all. all-reprs/types lists the tuple spec type beside the array one it already hardcodes, or extraction dies in split-untyped-eclasses, whose type->idx lookup has no failure thunk.
alt->fpcore picked the core's :precision with array-representation-base, which returns a tuple representation unchanged, so an improved tuple core came back with :precision (tuple binary64 binary64) and could not be read back in. It now goes through repr->prop, which descends to a scalar for every representation; on arrays the two agree exactly, including nested arrays. render-fpcore gains a tuple clause beside its array one, so a tuple-typed argument prints its full structural type, which is the only thing that identifies it.
Mirrors the array tests for type identity (per-slot and structural), distance, midpoint, sampling, real conversions, type checking, desugaring, and the platform-state round trip, including shapes of three slots.
Seven cores covering construction, the accessor, a tuple-typed argument, a three-slot tuple sharing one expensive subexpression, a multi-output rewrite target, and one mixed-precision pair whose type is (tuple binary32 binary64).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.