Skip to content

WIP Struct - #1634

Draft
sbrantq wants to merge 8 commits into
mainfrom
structs
Draft

WIP Struct#1634
sbrantq wants to merge 8 commits into
mainfrom
structs

Conversation

@sbrantq

@sbrantq sbrantq commented Jul 27, 2026

Copy link
Copy Markdown

No description provided.

sbrantq added 8 commits July 29, 2026 17:56
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.

representation-base names the scalar that fixes an aggregate's ambient
rounding context: a tuple descends into its first slot, since a mixed
tuple has no single precision and prog->fpcore needs one.
Every array case in float.rkt gains a tuple case beside it that recurses
per slot with that slot's own representation: repr-ulps, midpoint,
random-generate, real->repr, repr->real, and the JSON conversions used to
serialize sampled points and results. The array cases are untouched.

The Rival flattening in core/arrays.rkt is generalized over both
aggregates, including the (ref (tuple e ...) i) beta rule. Because it
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. 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 directly, while a core-level :precision stays
scalar as it is for arrays.
A platform cannot enumerate one impl per sequence of slot types, and
enumerating array shapes is what upstream reverted in 67fa847 and
8c08e43. 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.

Generated shapes ride along in platform state 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. Both fpcore->prog and inline!
resolve them through the same index-aware helper.
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.

Add operator-itypes, which reports the argument types at the arity the
term actually has, and use it at those three sites. Only tuple is
special-cased; every other operator, array included, is still reported
exactly as operator-info reports it, so nothing about array terms
changes.

all-reprs/types must also list the tuple spec type, or extraction dies
in split-untyped-eclasses, whose type->idx lookup has no failure thunk.
alt->fpcore and render-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.

Both now use representation-base, which descends a tuple's first slot,
matching repr->prop; slots that differ are already annotated in the
body. A tuple-typed argument still prints its full structural type,
which is the only thing that identifies it. Array behaviour is
unchanged: representation-base and array-representation-base agree on
every array.
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.
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).
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 this pull request may close these issues.

1 participant