Skip to content

Split Assign into local variable and field assignment#20

Draft
keyboardDrummer-bot wants to merge 2 commits intomainfrom
split-assign-field-assign
Draft

Split Assign into local variable and field assignment#20
keyboardDrummer-bot wants to merge 2 commits intomainfrom
split-assign-field-assign

Conversation

@keyboardDrummer-bot
Copy link
Copy Markdown
Collaborator

@keyboardDrummer-bot keyboardDrummer-bot commented Apr 22, 2026

Closes #19

Summary

Adds a new FieldAssign constructor to StmtExpr for field assignments, separating them from local variable assignments, and strengthens the Assign constructor to only accept Identifier targets:

| Assign (targets : List (AstNode Identifier)) (value : AstNode StmtExpr)
| FieldAssign (target : AstNode StmtExpr) (member : Identifier) (value : AstNode StmtExpr)

Previously, field assignments were represented as Assign [FieldSelect target member] value, requiring pattern matching on the target list to distinguish field writes from local variable assignments. The new FieldAssign constructor makes this distinction explicit in the type, and Assign targets are now List (AstNode Identifier) instead of List (AstNode StmtExpr), enforcing at the type level that assign targets are identifiers.

Grammar

  • Single-target assign: a := value
  • Multi-target assign: (a, b) := value (new multiAssign rule)
  • Field assign: obj#field := value (parsed via assign + fieldAccess, translated to FieldAssign)

Changes

Core type change (Laurel.lean):

  • Assign now takes List (AstNode Identifier) targets (was List (AstNode StmtExpr))
  • New FieldAssign takes a target: AstNode StmtExpr and member: Identifier

Grammar (LaurelGrammar.st):

  • Added multiAssign rule for (targets) := value syntax

Parser (ConcreteToAbstractTreeTranslator.lean):

  • assign extracts the identifier name from the target, or produces FieldAssign for field access targets
  • multiAssign parses comma-separated identifiers

Printer (AbstractToConcreteTreeTranslator.lean):

  • Single-target Assign prints as assign(identifier, value)
  • Multi-target Assign prints as multiAssign(targets, value)
  • FieldAssign prints as assign(fieldAccess(target, member), value)

All Laurel passes: Updated to work with AstNode Identifier targets. Passes that previously recursed into targets (MapStmtExpr, FilterPrelude, Resolution, CoreGroupingAndOrdering, TypeHierarchy, HeapParameterization) no longer need to since targets are just identifiers.

Python frontend (PythonToLaurel.lean):

  • Updated to construct AstNode Identifier targets for Assign
  • Field assignments produce FieldAssign

Testing

All existing tests pass (the only failure is the pre-existing StrataTest.DDM.Integration.Java.TestGen which requires a missing jar file).

Add a new FieldAssign constructor to StmtExpr that takes a target
expression, a member Identifier, and a value. The existing Assign
constructor now only accepts Identifier LHS targets.

Previously, field assignments were represented as
Assign [FieldSelect target member] value, requiring pattern matching
on the target list to distinguish field writes from local variable
assignments. The new FieldAssign constructor makes this distinction
explicit in the type.

Closes #19
@keyboardDrummer
Copy link
Copy Markdown
Owner

keyboardDrummer commented Apr 22, 2026

@keyboardDrummer-bot can the assign constructor be Assign (targets : List AstNode Identifier) (value : AstNode StmtExpr) ?

And once you have that, can we also enable this multi assign in the grammar?

…n grammar rule

- Assign constructor now takes (targets : List (AstNode Identifier)) instead of
  (targets : List (AstNode StmtExpr)), enforcing at the type level that assign
  targets are identifiers (not arbitrary expressions).

- Added multiAssign grammar rule: (a, b) := value for multi-target assignments.
  Single-target assign still uses: a := value.

- Updated all passes to work with the new target type:
  - Passes that recursed into targets (MapStmtExpr, FilterPrelude, Resolution,
    CoreGroupingAndOrdering, TypeHierarchy, HeapParameterization) no longer need
    to since targets are just identifiers.
  - LaurelToCoreTranslator, ConstrainedTypeElim, LiftImperativeExpressions,
    InferHoleTypes simplified by accessing .val directly as Identifier.
  - PythonToLaurel updated to construct AstNode Identifier targets.
@github-actions github-actions Bot added the Git conflicts PR has merge conflicts with the base branch label Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Git conflicts PR has merge conflicts with the base branch Laurel Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split assign into local variable and field assignment

2 participants