feat(parser): make authored expression gates work and show themselves - #124
Merged
zhen8838 merged 8 commits intoAug 26, 2026
Merged
Conversation
Weak Python float scalars now adopt a typed floating-point peer's dtype, `@` builds a MatMul in runtime position, and a rejected call names the op it could not resolve. The generated grammar expands the operator set it actually accepts. HIR's per-shape CUDA MMA ops are removed: a backend-bound construct in the reference side pulls HIR toward the imperative.
`tile` and `range` each match their own argument count, so the generated grammar shows the accepted forms instead of an open repetition. A precheck keeps naming the specific reason, which a shape mismatch alone would reduce to a bare match failure.
zhen8838
commented
Aug 26, 2026
| lhs_ty = ctx.type_of(call.args[0]) | ||
| rhs_ty = ctx.type_of(call.args[1]) | ||
| if lhs_ty.dtype != rhs_ty.dtype: | ||
| number = next( |
Collaborator
Author
There was a problem hiding this comment.
Why does this solve what problems?
| return type(pattern).__name__ | ||
|
|
||
|
|
||
| def _runtime_expression_detail(node: object) -> str: |
| """ | ||
| roots = placed_fixture_roots() | ||
| assert len(roots) == 29 | ||
| assert len(roots) == 28 |
Collaborator
Author
There was a problem hiding this comment.
What's the meaning of this kind of test? remove it
| target=CudaTarget("nvidia.h200_sxm"), | ||
| topologies=(Topology("cta", 2),), | ||
| ) | ||
| class PlacedMatMul: |
Collaborator
Author
There was a problem hiding this comment.
The test writing method is wrong, and then merge it into the test call.
| ), | ||
| ), | ||
| ) | ||
| def test_unsupported_expression_names_its_shape(body: str, expected: str) -> None: |
Collaborator
Author
There was a problem hiding this comment.
Delete this file and merge the previous test files.
|
|
||
| def test_tensor_operands_do_not_promote() -> None: | ||
| with pytest.raises(VerifyError, match=r"bf16 vs f32.*never promoted"): | ||
| import_dsl( |
Collaborator
Author
There was a problem hiding this comment.
Wrong test writing method
…lved A call that resolves to no authored Op or Function now says so at the point of resolution instead of having its shape described from the outside, and a binary dtype mismatch states the two dtypes and the promotion rule instead of guessing what the author wrote. Matmul reuses the shared call result rules. The parser cases join the existing call and function suites.
…e node A choice used to synthesize a failure for every alternative that returned None, so a report listed one line per alternative tried and the reason had to be dug back out of the pile. Give matching a typed third outcome instead: a pattern that has established the node is its own refuses with a reason, and every other combinator returns that refusal unchanged. Refusals now name what is wrong with a call, a mesh, a launch, or a static dict, where those sites previously returned None and left the report with nothing to say.
A rule shared by several elements was rendered once per owner, so the four call rules and the two layout rules each took four rows saying the same sentence. Merge on the rule and list the elements it governs, the way the situation column already lists situations.
…h no alternative left A call pattern named a callee it could not resolve, so a valid `launch(...)` produced a refusal that a choice then discarded. Deciding whether the spelling was meant as an op call made one alternative reason about another's territory, and it still missed the namespaces it did not know. Being last in a choice is no better a claim, since that choice is itself an alternative elsewhere. Describe an unclaimed node in `parse_node`, where no alternative remains by construction, and let the call pattern stay silent about callees it does not own.
The four spellings were interpolated into a source string and run through the module-import harness, so none of them appeared as Python anywhere in the file and a failure could come from any step of that import. Write each one out, the way the rest of the file's negatives are written.
A Python float was parsed as a Constant with no type at all, then completed later: adopted from a Binary peer where one was floating, and otherwise defaulted to f32 on every argument of every call. Three construction sites had to remember to run that completion, the marker was an Expr state the IR says cannot exist, and a rule existed only to state the exception negation made. Parse a float as an ordinary f32 Constant. A dtype mismatch is now reported where every other mismatch is, and the message names the Cast the author writes instead of guessing which dtype was meant.
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.
Why
scalar never adopted its peer's dtype, so
x + 1.0on a bf16 tensor wasrejected although hir §1.3 requires the authoring surface to adapt it.
@was not a runtime operator at all, so
x @ bcould not be written. Thegenerated grammar rendered
binary-opas a placeholder, so the operator setthe parser really accepts was unreadable.
runtime_expression: nested pattern failed. A choicesynthesized a failure for every alternative that returned
None, so a reportlisted one line per alternative tried and the reason had to be dug back out
of the pile.
reference side pulls HIR toward the imperative, and TIR already owns that
surface.
What
_constantproduces a dtype-less weak Constant for Python floats; it takes atyped floating-point peer's dtype before type inference. Unary minus keeps it
weak. Python integers and tensor/tensor mismatches stay strict.
MatMulExpressionPatternbuildsMatMulfromast.MatMultin runtimeposition only; the placement sugar
2 @ mesh.tileis untouched.is its own refuses with a reason, every other combinator returns that refusal
unchanged, and a choice records only the alternatives that claimed the node.
launch, or a static dictwhere those sites previously returned
None.matmul-expression, and states each loop iterator's argument count.ir/hir/cuda/is deleted along with its lowering refusal, cost evaluator,tests, and the isolated
mma_tilefixture.Contract
matchreturnsAstMatch,None, or aMatchFailure. A patternMUST claim a node before refusing it with a reason; a pattern that has not
claimed it returns
None. The generated grammar and constraint table changewith the patterns.
Mmaleaves thesymmetric multi-input list. passes: the CUDA HIR MMA refusal section is
removed. code-organization: MMA is target-owned under
ir/tir/cuda/nn/only.T.mma, its atom, and CUDA codegen are unchanged.Risk
alternative owns produces a misleading report; the corpus check is that a
valid program yields no refusal at all, which currently holds.