Replace operator strings with UnaryOp and BinaryOp enums#79
Merged
StreamDemon merged 1 commit intoJul 2, 2026
Merged
Conversation
`ExprKind::Unary`/`Binary` stored their operator as an owned String,
which allocated per node and let any string masquerade as an operator.
Dedicated enums make illegal operators unrepresentable, shrink the
nodes, and give match exhaustiveness checking to every consumer.
`=` never reaches the AST (it builds `ExprKind::Assign`), so the parser
classifies infix tokens with a private `Infix { Assign, Op(BinaryOp) }`
wrapper instead of widening the public enum with a variant no AST node
can carry. `as_str()`/`Display` on both enums recover the source
spelling for diagnostics and the future pretty-printer (#67).
There was a problem hiding this comment.
No issues found across 2 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant Lexer as Token Stream
participant Parser as Parser (with Infix enum)
participant BinaryOp as BinaryOp
participant UnaryOp as UnaryOp
participant Expr as Expr AST Node
Note over Lexer,Expr: Parsing an expression (e.g., a |> b + c)
Parser->>Lexer: peek token
Lexer-->>Parser: PipeGt
Parser->>Parser: infix_binding_power()
alt TokenKind::PipeGt
Parser-->>Parser: returns (Infix::Op(BinaryOp::Pipe), 8, 9)
else TokenKind::Plus
Parser-->>Parser: returns (Infix::Op(BinaryOp::Add), 9, 10)
else TokenKind::Eq
Parser-->>Parser: returns (Infix::Assign, 2, 1)
else TokenKind::DotDot
Parser-->>Parser: returns (Infix::Op(BinaryOp::Range), 3, 4)
end
Note over Parser: Precedence climbing loop
Parser->>Parser: consume token
Parser->>Parser: check Infix variant
alt Infix::Assign
Parser->>Expr: build ExprKind::Assign { target, value }
else Infix::Op(op)
Parser->>Expr: build ExprKind::Binary { op: BinaryOp::Pipe, left, right }
Expr-->>Parser: expression node
end
Note over Parser: For prefix unary (e.g., *x)
Parser->>Lexer: peek token
Lexer-->>Parser: Star
Parser->>Parser: map token to UnaryOp::Deref
alt TokenKind::Amp
Parser->>UnaryOp: UnaryOp::Ref
else TokenKind::Bang
Parser->>UnaryOp: UnaryOp::Not
else TokenKind::Minus
Parser->>UnaryOp: UnaryOp::Neg
else TokenKind::Star
Parser->>UnaryOp: UnaryOp::Deref
end
Parser->>Expr: build ExprKind::Unary { op: UnaryOp::Deref, expr }
Note over Parser,Expr: Range non‑associativity check
alt last built binary op is Range/RangeInclusive and next token is dotdot/dotdoteq
Parser->>Parser: error – range cannot nest
end
Note over Expr: Test assertions (structural)
alt test: assert_eq!(*op, BinaryOp::Div)
Test->>Expr: check kind field
Expr-->>Test: BinaryOp::Div
else test: assert_eq!(*op, BinaryOp::Pipe)
Test->>Expr: check kind field
Expr-->>Test: BinaryOp::Pipe
else test: is_assign_target(*op == UnaryOp::Deref)
Test->>Expr: check Unary node
Expr-->>Test: UnaryOp::Deref
end
Requires human review: Refactoring core AST types and parser logic to replace operator strings with enums. This is a high-impact change that requires human review to ensure correctness.
Re-trigger cubic
12 tasks
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.
Summary
op: StringonExprKind::Unary/Binarywith dedicatedUnaryOpandBinaryOpenums — no per-node allocation, illegal operators unrepresentable, and exhaustive matching for every consumer.=never reaches the AST (it buildsExprKind::Assign), so the parser classifies infix tokens with a privateInfix { Assign, Op(BinaryOp) }wrapper instead of widening the public enum with a variant no AST node can carry.as_str()+Displayon both enums recover the source spelling for diagnostics and the future pretty-printer (Parser: pretty-printer + parse→print→parse round-trip validation #67).BinaryOp::Pipe,BinaryOp::Div, ...) instead of comparing strings.Fourth sub-PR of the enhancement wave (PR #71 roadmap: "
Binary/Unaryop: String→ dedicated operator enums"). No behavior change.Related Issue
None (PR #71 roadmap item).
Spec Sections Affected
None — implementation quality only. Operator set mirrors the §16 expression grammar and
docs/reference/operator-precedence.mdexactly (binding powers unchanged).Checklist
docs/pages — N/A, no behavior changeBuild Targets Tested
cargo fmt --all -- --check,cargo clippy --workspace --all-targets -- -D warnings,cargo test --workspaceall green locally.Test Plan
assert_eq!(*op, BinaryOp::Pipe)etc.).Summary by cubic
Replaced operator strings with
UnaryOpandBinaryOpenums to remove per-node allocations and make invalid operators unrepresentable. The parser now treats=as assignment (not a binary op), with no behavior changes.Refactors
ExprKind::UnaryandExprKind::Binarynow storeUnaryOp/BinaryOp.Infix { Assign, Op(BinaryOp) };=never reaches the AST.as_str()andDisplayon both enums for diagnostics; tests updated to assert enum variants.Migration
UnaryOp/BinaryOpmatches.op.as_str()orformat!("{}", op)when you need the operator’s source spelling.Written for commit bd95672. Summary will update on new commits.