Skip to content

feat(autodiff): add the generated tensor constant operator and reader - #130

Open
AlekseiChirkovVention wants to merge 3 commits into
mainfrom
feat/generated-constant-operator
Open

feat(autodiff): add the generated tensor constant operator and reader#130
AlekseiChirkovVention wants to merge 3 commits into
mainfrom
feat/generated-constant-operator

Conversation

@AlekseiChirkovVention

Copy link
Copy Markdown
Collaborator

Introduce the single public representation of a generated tensor-valued constant operand, so
that a later expansion can multiply against a tensor of ones that actually exists in the graph.

Goal

Add FillOperator — a concrete zero-operand TensorOperator whose op_params is exactly
{fill, dtype, shape} — together with the FillDescriptor record and the shared
fill_descriptor reader, so every backend materializes a constant from one validated schema
instead of hand-parsing operator parameters.

A concrete operator type, rather than a parameter on an existing operator, is what lets
handler dispatch reject a backend that does not understand the construct before any handler
runs. Existing operators keep their operand contracts unchanged: no handler anywhere sees a
new operand count, a new parameter key, or a new shape convention.

Acceptance criteria

  • FillOperator is concrete, declares route_name "fill", and adds no field beyond the
    base operator.
  • fill_descriptor returns the declared fill, dtype, and shape from a node and from its
    OperationContext, as the same record.
  • A well-formed fill node's output_typespec equals its descriptor's dtype and shape.
  • A missing key, an extra key, a non-real or boolean fill, a non-integer or negative
    dimension, an absent or non-string dtype, a node carrying an operand, and a node whose
    operator is not a fill each raise a categorized error naming the node id.
  • No bare KeyError, IndexError, TypeError, ValueError, or AssertionError escapes the
    reader for those inputs.
  • The three names are reachable from tinychain.autodiff, present in __all__, and absent
    from the top-level tinychain package.
  • "fill" is absent from the tracing capture allowlist and the error-category tuple is
    unchanged.

Test evidence

Level: unit. Tests first: the failing set landed in ce1a5e2, before any
implementation existed; 7a869c7 made it pass.

py/tests/test_autodiff_fill_contract.py — 17 test functions, 59 parametrized cases, all
passing. Coverage per criterion: the operator shape by three tests asserting route_name and
the declared field set; the reader by two tests comparing the node and context results; the
typespec agreement by one; the categorized-rejection table by two 15-case parametrizations
plus three targeted tests; the builtin-leak guarantee by a third 15-case parametrization; the
export surface by one test asserting __all__ membership, identity against the module, and
absence from the top-level package; and the two nothing-changed criteria by one test each.

Neighbouring autodiff suites: 182 passed. Broad non-integration suite: 973 passed, 9 failed,
1 skipped — all 9 failures pre-existing and unrelated to this branch (7 require the unbuilt
local backend, 2 are symbolic-style guards naming a file this branch does not touch).

Stack position

Stack position 1 of 8 — based on main.

This is the base of a stacked series; the seven branches that follow build on it in order, so
they cannot reach main before this one does.

Review notes

Known follow-ups, already recorded and deliberately not fixed here:

  • The reader raises a bare TypeError for a hand-built OperationContext whose op_params
    is not iterable or whose operand list is not sized. Unreachable through the framework's own
    construction path, which always supplies a mapping proxy and a tuple. The guard is deferred
    because the same one must serve the expansion emitters that will share this module.
  • The typespec-agreement criterion is currently asserted against the test's own helper. The
    real guarantee is the truthful-shape audit that lands with the expansion passes, where
    production code emits the typespec.

Pin the concrete zero-operand constant operator, its descriptor schema, the
shared reader and every categorized rejection it must produce, and the
package-level export. The reader is the single parser every backend uses to
materialize a generated constant, so a malformed descriptor must fail with a
categorized error naming the offending node rather than leaking a builtin
exception into consumer code.
The parametrized cases for a null and a non-sequence shape crashed while
building the node under test, before the reader was ever called, because the
helper derived a default typespec from the malformed parameters. Pass an
explicit typespec, matching the two sibling malformed-descriptor tests. No
assertion changes.
A backend without a native reduction needs generated constant tensors to
exist as graph nodes before an expansion can multiply against them. Add a
concrete zero-operand operator carrying a fill value, dtype, and shape, plus
one validated reader so every backend materializes a constant from the same
schema instead of hand-parsing operator parameters.

A concrete operator type, rather than a parameter on an existing operator, is
what lets handler dispatch reject a backend that does not understand the
construct before any handler runs. Existing operators keep their operand
contracts unchanged.

Every rejection is a categorized error naming the offending node: a parameter
key outside the schema, an operand on a constant node, or a wrong operator
type are structural defects, while an absent shape or dtype keeps its own
more specific category. Booleans are refused in both numeric positions.
@AlekseiChirkovVention
AlekseiChirkovVention marked this pull request as ready for review August 28, 2026 06:18
@AlekseiChirkovVention AlekseiChirkovVention self-assigned this Aug 28, 2026
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.

3 participants