Skip to content

Laurel Language Enhancements#385

Open
fabiomadge wants to merge 314 commits intomainfrom
jverify-strata-backend
Open

Laurel Language Enhancements#385
fabiomadge wants to merge 314 commits intomainfrom
jverify-strata-backend

Conversation

@fabiomadge
Copy link
Contributor

@fabiomadge fabiomadge commented Feb 4, 2026

Summary

Expands the Laurel language with additional operators, data types, and verification constructs. Improves formatting across multiple dialects.

Key Changes

Laurel Grammar & Translator

  • New operators: -, *, /, %, /t, %t (truncating), ==>, !, unary -
  • Array support: Array<T> type, indexing, length
  • Sequence operations: Seq.From, Seq.Take, Seq.Drop, Seq.Contains
  • Constrained types with constraint injection into quantifiers
  • Quantifiers: forall, exists
  • Return statement works with postconditions
  • While loops with multiple invariants
  • Multiple requires clauses per procedure

Infrastructure

  • NewlineSepBy separator type for formatting preservation
  • Java codegen: list separator preservation, SourceRange overloads
  • Improved pretty printing for C_Simp, B3, Core

CLI Commands

  • laurelParse, laurelAnalyze, laurelToCore, laurelPrint

Bug Fixes

  • Fixed SMT encoding for multi-argument functions and Map type
  • Added substFvarLifting for proper de Bruijn index handling

Tests

  • Reorganized Laurel tests T01-T17
  • Added regression test for assignment lifting

match outputParams.head? with
| some _ => do
let coreExpr ← translateExpr ctMap tcMap env stmt
mkReturnStmts (some coreExpr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the scenario where we return "naturally" because we reach the end of a block? Since this is not a jump, should we not call something different than mkReturnStmt which does do a jump?

op assume (cond : StmtExpr) : StmtExpr => "assume " cond ";";
op return (value : StmtExpr) : StmtExpr => "return " value ";";
op block (stmts : Seq StmtExpr) : StmtExpr => @[prec(1000)] "{" stmts "}";
op block (stmts : NewlineSepBy StmtExpr) : StmtExpr => @[prec(1000)] "{" indent(2, "\n" stmts) "\n}";
Copy link
Contributor

@keyboardDrummer keyboardDrummer Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indent(2, is never used anywhere, right? I don't think we're ever printing Laurel through the DDM. Why did you add this?

return commands
let (some tree, true) ← runChecked <| elabCommand leanEnv
| return commands
-- Prevent infinite loop if parser makes no progress
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!!

| q`Init.SpacePrefixSepBy, 1 =>
let inner := mkCApp ``Array #[args[0]]
return if addAnn then mkCApp ``Ann #[inner, annType] else inner
| q`Init.NewlineSepBy, 1 =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you say more about this NewlineSepBy operator? What is it for?

github-merge-queue bot pushed a commit that referenced this pull request Feb 16, 2026
Contains a subset of the changes from
#385

### Changes
- Fix to Strata/DDM/Parser.lean so it can handle parsing comments `//`
in languages that have a division operator
- New operators: `-`, `*`, `/`, `%`, `/t`, `%t` (truncating), `==>`,
`!`, unary `-`
- Quantifiers: `forall`, `exists`
- While loops with multiple invariants

### Testing
- Added tests for the new features

---------

Co-authored-by: Andrew Wells <130512013+andrewmwells-amazon@users.noreply.github.com>
keyboardDrummer and others added 9 commits February 19, 2026 10:48
- Use CoreIdent.unres (not glob) for StaticCall translations, matching
  how DDM-parsed and translated functions are registered.
- Add isCoreFunction to isExpressionCall so corePrelude functions are
  translated as expressions, not procedure calls.
- Fix expression lifter: process block-expression internals with
  transformStmt instead of transformExprDiscarded.
- Update stale StrataMain call sites for verifyToVcResults and translate.
Merge resolution:
- Tier 1+2 (12 files): took main's versions for C_Simp tests, DDM/Format,
  C_Simp/Parse, Core/Grammar, Core test files
- Laurel.lean: added TCore constructor from main, kept deriving Repr
- SMTEncoder.lean: kept branch's multi-arg destructArrow + substFvarsLifting,
  added main's useArrayTheory threading and select/update guard
- LaurelToCoreTranslator.lean: kept branch for all 5 conflicts (ctMap,
  constrained types, Array/Seq, quantifier constraints), added from main:
  TCore type, FieldSelect safety check, Hole handling, decreases expression
  threading in While
- StrataMain.lean: kept branch's commands (laurelParse, laurelPrint,
  laurelToCore, prettyPrintCore), adopted main's CommandGroup structure,
  added pyAnalyzeLaurelCommand
- DDM/Format.lean: added SepFormat.newline case from branch
- PythonToLaurel.lean: updated Procedure constructors for branch's schema
  (preconditions list, no determinism field)
- ProgramTypeTests.lean: removed DivT/ModT from expected factory output
  (branch moved these to Laurel prelude)
- Fixed callback arg order in StrataMain commands
- Fixed Except monad context for constant identifier translation
- Restore intDivTFunc/intModTFunc to IntBoolFactory and Core Factory
  (lost during earlier merge of PR #428). These belong in the factory
  since the SMT encoder handles their semantics.
- Remove duplicate definitions from LaurelToCoreTranslator's corePrelude.
  The translator now references Core.intDivTOp/Core.intModTOp.
- Use empty precondition lists in PythonToLaurel instead of [true].
- Update test expectations for DivT/ModT in factory output.
Merge resolution:
- HeapParameterization.lean: kept branch's structure, added New case from
  main (allocate object via nextReference/increment)
- LaurelToCoreTranslator.lean: merged isPureExpr - added New case (false)
  and IfThenElse none handling from main
- T03_Variables.lean: kept both branch's regression test and main's
  nestedImpureStatementsAndOpaque test
- T1_MutableFields.lean: restored foo procedure dropped during conflict
  resolution, removed duplicate useBool, updated error annotations for
  PR #417 behavior (no longer generates modifies clause error, instead
  generates assertion failures from universal modifies postcondition)
Merged commits: f6ff88b, a6e5f93, 64fd6d6, 6f67113, 9dccebf,
a0716de, 1221d67, d1c7ddd, cb2411d

Conflict resolutions:
- IntBoolFactory.lean: took HEAD (has full function set + DivT/ModT).
  Added intSafeDivFunc/intSafeModFunc with preconditions (PR #444).
  Added Inhabited constraint to IntBoolFactory.
- SMTEncoder.lean: added main's SafeMod + DivT/ModT SMT encodings.
- LaurelToCoreTranslator.lean: took HEAD logic, wrapped init RHS
  values in `some` for PR #432's Cmd.init signature change.
- Laurel.lean: took main's version (PR #434 docstrings), then
  restored branch-specific changes: preconditions (list) in Procedure,
  postconditions (list) in Body.Opaque/Abstract, removed Determinism,
  added deriving Repr on WithMetadata and HighType, added Repr
  instance for Imperative.MetaData.
github-merge-queue bot pushed a commit that referenced this pull request Feb 26, 2026
Contains a subset of the changes from
#385, rebased on current main.

### DDM Infrastructure
- Add `NewlineSepBy` separator and `SyntaxDef.passthrough` variant
- Replace `fromIonName?`/`toIonName` with `fromCategoryName?` for
category-based lookup
- Add newline formatting case in `ArgF.mformatM`
- Update Java/Lean codegen for new constructs
- Comment parsing fix in `Parser.lean`

### Lambda/SMT Bug Fixes
- Add `liftBVars` with cutoff parameter for correct de Bruijn index
shifting
- Add `substFvarLifting`/`substFvarsLifting` for substitution under
binders (doc comment clarifies that `to`'s bvars must refer to binders
outside `e`)
- Fix multi-argument function SMT encoding (was hardcoded to unary)
- Add Map type to SMT Array encoding

### Testing
- `LExprWFTests.lean`: tests for `substFvarLifting`
- `SMTEncoderTests.lean`: updated for multi-arg encoding
- `Functions.lean`: multi-argument function test + quantifier-in-body
test

### Review feedback addressed
- The `≤` → `<` precedence change from the previous version has been
removed (it was incorrect)
- Doc comment added to `substFvarLifting` per review feedback

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.

Co-authored-by: Fabio Madge <fmadge@amazon.com>
github-merge-queue bot pushed a commit that referenced this pull request Feb 26, 2026
…ons (#481)

Part of the incremental split of #385. Can be merged independently of
#426.

### Changes

Converts Laurel's `Procedure` from a single precondition to a list of
preconditions, and `Body.Abstract` from a single postcondition to a
list. This enables multiple `requires`/`ensures` clauses per procedure,
which is needed by the upcoming constrained types and contract features.

**Laurel.lean:**
- `precondition : WithMetadata StmtExpr` → `preconditions : List
(WithMetadata StmtExpr)`
- `Body.Abstract postcondition` → `Body.Abstract (postconditions : List
...)`
- `Body.Opaque postcondition` → `Body.Opaque postconditions` (name only,
already a list)
- Reorder `Parameter` struct, add `Repr` instances

**Adapted callers:**
- `ConcreteToAbstractTreeTranslator` — parse `Option OptionalRequires`
into list
- `LaurelToCoreTranslator` — iterate over preconditions list, generate
indexed labels for multiple preconditions
- `HeapParameterization` — fold over preconditions/postconditions lists
- `LaurelFormat` — format preconditions/postconditions lists, relocate
`formatDeterminism`
- `PythonToLaurel`, `Specs/ToLaurel` — adapt to new field names

**LiftExpressionAssignments.lean:**
- Process block-in-expression non-last elements left-to-right via
`transformStmt` instead of right-to-left via `transformExprDiscarded`
- Remove now-unused `transformExprDiscarded`

### Testing

All existing Laurel, Python, and Core tests pass. No new tests needed —
this is a structural refactor with no new features.

By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.

---------

Co-authored-by: Andrew Wells <130512013+andrewmwells-amazon@users.noreply.github.com>
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.

6 participants