Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
241c598
Introduce pure property for procedures
keyboardDrummer Feb 23, 2026
079f5da
Rename
keyboardDrummer Feb 23, 2026
4a9dad2
Add additinal tests
keyboardDrummer Feb 23, 2026
6b2d31f
Parser stuck fix
keyboardDrummer Feb 23, 2026
fd5fdf1
Fixes
keyboardDrummer Feb 23, 2026
2defa7c
Fix test
keyboardDrummer Feb 23, 2026
49e0900
Merge remote-tracking branch 'origin/main' into remy/pureProcedures
keyboardDrummer Feb 24, 2026
2cd09af
Use function instead of pure procedure
keyboardDrummer Feb 24, 2026
ffa62ed
Fix docs
keyboardDrummer Feb 24, 2026
65082fa
Add more checks to LaurelToCoreTranslator.lean
keyboardDrummer Feb 25, 2026
82dd95c
Use a monad to make the code more readable
keyboardDrummer Feb 25, 2026
b1472a0
Update panic
keyboardDrummer Feb 25, 2026
40a28ad
Fix
keyboardDrummer Feb 25, 2026
2b39328
Merge branch 'main' into remy/pureProcedures
keyboardDrummer Feb 25, 2026
c9ed9fa
Add more test cases
keyboardDrummer Feb 25, 2026
64a5ad8
Test updated and extra diagnostics
keyboardDrummer Feb 25, 2026
f02d1dc
Fix warnings
keyboardDrummer Feb 25, 2026
4ad7c5e
Merge branch 'remy/pureProcedures' of github.com:strata-org/Strata in…
keyboardDrummer Feb 25, 2026
dbd4c1c
Merge remote-tracking branch 'origin/main' into remy/pureProcedures
keyboardDrummer Feb 25, 2026
21dcb9b
Hit cache
keyboardDrummer Feb 25, 2026
2c83631
Merge branch 'main' into remy/pureProcedures
keyboardDrummer Feb 25, 2026
eefc4cd
Merge branch 'main' into remy/pureProcedures
andrewmwells-amazon Feb 26, 2026
33c2b9f
Merge remote-tracking branch 'origin/main' into remy/pureProcedures
keyboardDrummer Feb 26, 2026
52ba56e
Updated comment
keyboardDrummer Feb 26, 2026
b2e5aa2
Introduce ids for identifiers
keyboardDrummer Feb 26, 2026
c8e091b
Some updates
keyboardDrummer Feb 26, 2026
b120036
Fixes
keyboardDrummer Feb 26, 2026
b739955
Updated ModifiesClauses
keyboardDrummer Feb 26, 2026
70ec1ab
Updated a few transformations assuming we have a semanticModel
keyboardDrummer Feb 26, 2026
5a7b39c
Changes
keyboardDrummer Feb 27, 2026
c35e08e
Merge branch 'remy/pureProcedures' into remy/LaurelResolution
keyboardDrummer Feb 27, 2026
d1046de
Updates
keyboardDrummer Feb 27, 2026
1af2bea
Fixes
keyboardDrummer Feb 27, 2026
f397ac3
Fixed build errors
keyboardDrummer Feb 27, 2026
3b63689
Fixes
keyboardDrummer Feb 27, 2026
0bb0f82
Fix
keyboardDrummer Feb 27, 2026
cf163b4
Fixes
keyboardDrummer Feb 27, 2026
3b2522d
Fixes
keyboardDrummer Feb 27, 2026
c18f69a
Bring back LaurelToCoreFromPureProcedures
keyboardDrummer Feb 27, 2026
63af1e1
Merge remote-tracking branch 'origin/main' into remy/LaurelResolution
keyboardDrummer Feb 27, 2026
7bc4988
Fixes
keyboardDrummer Feb 27, 2026
59fd2e3
Fixes
keyboardDrummer Feb 27, 2026
edc0257
Fix
keyboardDrummer Feb 27, 2026
b1a0789
Fixes
keyboardDrummer Feb 27, 2026
8406f2a
Updates
keyboardDrummer Feb 28, 2026
09d81f6
Fixes
keyboardDrummer Feb 28, 2026
484207a
Fixes
keyboardDrummer Feb 28, 2026
813d251
Fixes
keyboardDrummer Feb 28, 2026
9686c64
Fixes
keyboardDrummer Feb 28, 2026
da51850
Fix
keyboardDrummer Feb 28, 2026
be95aaf
Fix
keyboardDrummer Feb 28, 2026
ec38f8c
Fix
keyboardDrummer Feb 28, 2026
72a3b61
Update to Resolution
keyboardDrummer Feb 28, 2026
dee810c
Fixes
keyboardDrummer Feb 28, 2026
617eaf5
Fix
keyboardDrummer Feb 28, 2026
7e05e23
Fixes
keyboardDrummer Mar 1, 2026
cef64f0
Fix
keyboardDrummer Mar 1, 2026
b33222c
No more panics
keyboardDrummer Mar 1, 2026
caa55da
Reduce debug output
keyboardDrummer Mar 1, 2026
e526cce
Fix
keyboardDrummer Mar 1, 2026
c844a82
Fixes
keyboardDrummer Mar 1, 2026
e8c1b37
Merge commit 'd4c952877~1' into remy/LaurelResolution
keyboardDrummer Mar 1, 2026
b377e1a
Merge commit 'd4c952877' into remy/LaurelResolution
keyboardDrummer Mar 1, 2026
6ac4fa9
Merge remote-tracking branch 'origin/main' into remy/LaurelResolution
keyboardDrummer Mar 1, 2026
ac6113e
Replace calls to mkId with a coercion
keyboardDrummer Mar 2, 2026
6e1a108
Fixes
keyboardDrummer Mar 2, 2026
d55e027
Rename Identifier.name to Identifier.text
keyboardDrummer Mar 2, 2026
5df3e53
Fixes
keyboardDrummer Mar 2, 2026
c55ca5e
Fixes
keyboardDrummer Mar 2, 2026
b4025fa
Fix for PythonToLaurel
keyboardDrummer Mar 2, 2026
ad7ef4a
Python fixes
keyboardDrummer Mar 2, 2026
7e4448b
Fixed and cleanup
keyboardDrummer Mar 2, 2026
1253eb4
Cleanup
keyboardDrummer Mar 2, 2026
0ee314b
Cleanup
keyboardDrummer Mar 2, 2026
7c0e80c
Cleanup
keyboardDrummer Mar 2, 2026
dcc102b
Cleanup
keyboardDrummer Mar 2, 2026
02efb77
Cleanup
keyboardDrummer Mar 2, 2026
c53af02
Simplify
keyboardDrummer Mar 2, 2026
93a1c70
Cleanup
keyboardDrummer Mar 2, 2026
4e363d0
Fixes
keyboardDrummer Mar 2, 2026
1620ad5
Fixes
keyboardDrummer Mar 2, 2026
2f582ec
Remove dbg output
keyboardDrummer Mar 2, 2026
5979c60
Rename to avoid warning
keyboardDrummer Mar 2, 2026
170fbdf
Updates
keyboardDrummer Mar 2, 2026
c7faf1d
Add hack
keyboardDrummer Mar 2, 2026
4ff7855
Cleanup
keyboardDrummer Mar 2, 2026
5dcbc5f
Add comment and remove useless derive
keyboardDrummer Mar 4, 2026
7be6bd5
Remove DecidableEq for Identifier
keyboardDrummer Mar 4, 2026
8a1efb9
Merge remote-tracking branch 'origin/main' into remy/LaurelResolution
keyboardDrummer Mar 4, 2026
a3c3060
Remove dbg_trace
keyboardDrummer Mar 4, 2026
e261beb
Remove softPanic
keyboardDrummer Mar 4, 2026
24eddb7
Change handling of guillemets
keyboardDrummer Mar 5, 2026
3240692
Remove partials, rename boogie => core, added comment to workaround, …
keyboardDrummer Mar 5, 2026
f82b5b0
Cleanup
keyboardDrummer Mar 5, 2026
b18c5ab
Remove two partials
keyboardDrummer Mar 5, 2026
a4e0275
Merge remote-tracking branch 'origin/main' into remy/LaurelResolution
keyboardDrummer Mar 5, 2026
854bb0d
Merge branch 'main' into remy/LaurelResolution
joscoh Mar 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Strata/DDM/Elab/Core.lean
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ def translateQualifiedIdent (t : Tree) : MaybeQualifiedIdent :=
| q`Init.qualifiedIdentImplicit, 1 => Id.run do
let .ident _ name := args[0]
| return panic! "Expected ident"
let name := name.dropPrefix "«" |>.dropSuffix "»" |>.toString
match name.splitOn "." with
| [dialect, rest] => .qid { dialect, name := rest }
| _ => .name name
Expand Down Expand Up @@ -1448,7 +1447,7 @@ partial def catElaborator (c : SyntaxCat) : TypingContext → Syntax → ElabM T
fun tctx stx => do
let some loc := mkSourceRange? stx
| panic! "ident missing source location"
let info : IdentInfo := { inputCtx := tctx, loc := loc, val := stx.getId.toString }
let info : IdentInfo := { inputCtx := tctx, loc := loc, val := stx.getId.toString (escape := false) }
pure <| .node (.ofIdentInfo info) #[]
| q`Init.Num =>
fun tctx stx => do
Expand Down
5 changes: 0 additions & 5 deletions Strata/DDM/Format.lean
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,6 @@ Strips Lean's «» notation if present.
Follows SMT-LIB 2.6 specification for quoted symbols.
-/
private def formatIdent (s : String) : Format :=
-- Strip Lean's «» notation if present
let s := if s.startsWith "«" && s.endsWith "»" then
s.drop 1 |>.dropEnd 1 |>.toString
else
s
if needsPipeDelimiters s then
Format.text ("|" ++ escapePipeIdent s ++ "|")
else
Expand Down
3 changes: 2 additions & 1 deletion Strata/Languages/Core/Verifier.lean
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,8 @@ structure Diagnostic where
deriving Repr, BEq

def DiagnosticModel.toDiagnostic (files: Map Strata.Uri Lean.FileMap) (dm: DiagnosticModel): Diagnostic :=
let fileMap := (files.find? dm.fileRange.file).getD (panic s!"Could not find {repr dm.fileRange.file} in {repr files.keys} when converting model '{dm}' to a diagnostic")
let fileMap := (files.find? dm.fileRange.file).getD
(dbg_trace s!"Could not find {repr dm.fileRange.file} in {repr files.keys} when converting model '{dm}' to a diagnostic"; default)
let startPos := fileMap.toPosition dm.fileRange.range.start
let endPos := fileMap.toPosition dm.fileRange.range.stop
{
Expand Down
46 changes: 46 additions & 0 deletions Strata/Languages/Laurel/CoreDefinitionsForLaurel.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/-
Copyright Strata Contributors

SPDX-License-Identifier: Apache-2.0 OR MIT
-/

import Strata.DDM.Elab
import Strata.DDM.AST
import Strata.Languages.Laurel.Grammar.LaurelGrammar
import Strata.Languages.Laurel.Grammar.ConcreteToAbstractTreeTranslator

namespace Strata.Laurel

/--
Core map operations (`select`, `update`, `const`) expressed in Laurel syntax.
These are polymorphic map primitives used by the Laurel-to-Core translator.
Since Laurel doesn't have polymorphic types, `int` is used as a placeholder type
for all parameters — the actual types are inferred during Core translation.
-/
def coreDefinitionsForLaurelDDM :=
#strata
program Laurel;

// The types for these Map functions are incorrect.
// We'll fix them when Laurel supports polymorphism
function select(map: int, key: int) : int
external

function update(map: int, key: int, value: int) : int
external

function const(value: int) : int
external

#end

/--
The core map operation definitions as a `Laurel.Program`, parsed at compile time.
-/
def coreDefinitionsForLaurel : Program :=
let uri := Strata.Uri.file "Strata/Languages/Laurel/CoreDefinitionsForLaurel.lean"
match TransM.run uri (parseProgram coreDefinitionsForLaurelDDM) with
| .ok program => program
| .error e => panic! s!"CoreDefinitionsForLaurel parse error: {e}"

end Strata.Laurel
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ open Lean.Parser (InputContext)
open Imperative (MetaData)

structure TransState where
uri : Uri
uri : Option Uri
errors : Array String

abbrev TransM := StateT TransState (Except String)

def TransM.run (uri : Uri) (m : TransM α) : Except String α :=
def TransM.run (uri : Option Uri) (m : TransM α) : Except String α :=
match StateT.run m { uri := uri, errors := #[] } with
| .ok (v, _) => .ok v
| .error e => .error e
Expand All @@ -36,8 +36,10 @@ def SourceRange.toMetaData (uri : Uri) (sr : SourceRange) : Imperative.MetaData
let fileRangeElt := ⟨ Imperative.MetaDataElem.Field.label "fileRange", .fileRange ⟨ uri, sr.start, sr.stop ⟩ ⟩
#[fileRangeElt]

def getArgMetaData (arg : Arg) : TransM (Imperative.MetaData Core.Expression) :=
return SourceRange.toMetaData (← get).uri arg.ann
def getArgMetaData (arg : Arg) : TransM (Imperative.MetaData Core.Expression) := do
return match (← get).uri with
| some uri => SourceRange.toMetaData uri arg.ann
| none => default

def checkOp (op : Strata.Operation) (name : QualifiedIdent) (argc : Nat) :
TransM Unit := do
Expand All @@ -55,7 +57,7 @@ def checkOp (op : Strata.Operation) (name : QualifiedIdent) (argc : Nat) :
def translateIdent (arg : Arg) : TransM Identifier := do
let .ident _ id := arg
| TransM.error s!"translateIdent expects ident"
return id
return { text := id }

def translateBool (arg : Arg) : TransM Bool := do
match arg with
Expand All @@ -72,7 +74,7 @@ def translateBool (arg : Arg) : TransM Bool := do
| x => TransM.error s!"translateBool expects expression or operation, got {repr x}"

instance : Inhabited Parameter where
default := { name := "", type := ⟨.TVoid, #[]⟩ }
default := { name := "" , type := ⟨.TVoid, #[]⟩ }

def mkHighTypeMd (t : HighType) (md : MetaData Core.Expression) : HighTypeMd := ⟨t, md⟩
def mkStmtExprMd (e : StmtExpr) (md : MetaData Core.Expression) : StmtExprMd := ⟨e, md⟩
Expand All @@ -85,7 +87,12 @@ partial def translateHighType (arg : Arg) : TransM HighTypeMd := do
match op.name, op.args with
| q`Laurel.intType, _ => return mkHighTypeMd .TInt md
| q`Laurel.boolType, _ => return mkHighTypeMd .TBool md
| q`Laurel.float64Type, _ => return mkHighTypeMd .TFloat64 md
| q`Laurel.stringType, _ => return mkHighTypeMd .TString md
| q`Laurel.mapType, #[keyArg, valArg] =>
let keyType ← translateHighType keyArg
let valType ← translateHighType valArg
return mkHighTypeMd (.TMap keyType valType) md
| q`Laurel.compositeType, #[nameArg] =>
let name ← translateIdent nameArg
return mkHighTypeMd (.UserDefined name) md
Expand Down Expand Up @@ -257,12 +264,12 @@ partial def translateStmtExpr (arg : Arg) : TransM StmtExprMd := do
let name ← translateIdent nameArg
let ty ← translateHighType tyArg
let body ← translateStmtExpr bodyArg
return mkStmtExprMd (.Forall name ty body) md
return mkStmtExprMd (.Forall { name := name, type := ty } body) md
| q`Laurel.existsExpr, #[nameArg, tyArg, bodyArg] =>
let name ← translateIdent nameArg
let ty ← translateHighType tyArg
let body ← translateStmtExpr bodyArg
return mkStmtExprMd (.Exists name ty body) md
return mkStmtExprMd (.Exists { name := name, type := ty } body) md
| _, #[arg0] => match getUnaryOp? op.name with
| some primOp =>
let inner ← translateStmtExpr arg0
Expand Down Expand Up @@ -370,14 +377,22 @@ def parseProcedure (arg : Arg) : TransM Procedure := do
-- Parse modifies clauses (zero or more)
let modifies ← translateModifiesClauses modifiesArg
-- Parse optional body
let isExternal ← match bodyArg with
| .option _ (some (.op bodyOp)) => match bodyOp.name, bodyOp.args with
| q`Laurel.externalBody, #[] => pure true
| _, _ => pure false
| _ => pure false
let body ← match bodyArg with
| .option _ (some (.op bodyOp)) => match bodyOp.name, bodyOp.args with
| q`Laurel.optionalBody, #[exprArg] => translateCommand exprArg >>= (pure ∘ some)
| _, _ => TransM.error s!"Expected optionalBody operation, got {repr bodyOp.name}"
| q`Laurel.externalBody, #[] => pure none
| _, _ => TransM.error s!"Expected optionalBody or externalBody operation, got {repr bodyOp.name}"
| .option _ none => pure none
| _ => TransM.error s!"Expected optionalBody, got {repr bodyArg}"
-- Determine procedure body kind
let procBody := match postconditions, body with
let procBody :=
if isExternal then Body.External
else match postconditions, body with
| _ :: _, bodyOpt => Body.Opaque postconditions bodyOpt modifies
| [], some b => Body.Transparent b
| [], none => Body.Opaque [] none modifies
Expand Down Expand Up @@ -435,6 +450,51 @@ def parseComposite (arg : Arg) : TransM TypeDefinition := do
| _, _ =>
TransM.error s!"parseComposite expects composite, got {repr op.name}"

def parseDatatypeConstructorArg (arg : Arg) : TransM Parameter := do
let .op op := arg
| TransM.error s!"parseDatatypeConstructorArg expects operation"
match op.name, op.args with
| q`Laurel.datatypeConstructorArg, #[nameArg, typeArg] =>
let name ← translateIdent nameArg
let argType ← translateHighType typeArg
return { name := name, type := argType }
| _, _ =>
TransM.error s!"parseDatatypeConstructorArg expects datatypeConstructorArg, got {repr op.name}"

def parseDatatypeConstructor (arg : Arg) : TransM DatatypeConstructor := do
let .op op := arg
| TransM.error s!"parseDatatypeConstructor expects operation"
match op.name, op.args with
| q`Laurel.datatypeConstructor, #[nameArg, argsSeq] =>
let name ← translateIdent nameArg
let args ← match argsSeq with
| .seq _ .comma args => args.toList.mapM parseDatatypeConstructorArg
| _ => pure []
return { name := name, args := args }
| q`Laurel.datatypeConstructorNoArgs, #[nameArg] =>
let name ← translateIdent nameArg
return { name := name, args := [] }
| _, _ =>
TransM.error s!"parseDatatypeConstructor expects datatypeConstructor, got {repr op.name}"

def parseDatatype (arg : Arg) : TransM TypeDefinition := do
let .op op := arg
| TransM.error s!"parseDatatype expects operation"
match op.name, op.args with
| q`Laurel.datatype, #[nameArg, constructorsArg] =>
let name ← translateIdent nameArg
let constructors ← match constructorsArg with
| .op listOp => match listOp.name, listOp.args with
| q`Laurel.datatypeConstructorList, #[csArg] =>
match csArg with
| .seq _ .comma args => args.toList.mapM parseDatatypeConstructor
| singleArg => do let c ← parseDatatypeConstructor singleArg; pure [c]
| _, _ => TransM.error s!"Expected datatypeConstructorList, got {repr listOp.name}"
| _ => TransM.error s!"Expected datatypeConstructorList operation"
return .Datatype { name := name, typeArgs := [], constructors := constructors }
| _, _ =>
TransM.error s!"parseDatatype expects datatype, got {repr op.name}"

def parseTopLevel (arg : Arg) : TransM (Option Procedure × Option TypeDefinition) := do
let .op op := arg
| TransM.error s!"parseTopLevel expects operation"
Expand All @@ -446,8 +506,11 @@ def parseTopLevel (arg : Arg) : TransM (Option Procedure × Option TypeDefinitio
| q`Laurel.topLevelComposite, #[compositeArg] =>
let typeDef ← parseComposite compositeArg
return (none, some typeDef)
| q`Laurel.topLevelDatatype, #[datatypeArg] =>
let typeDef ← parseDatatype datatypeArg
return (none, some typeDef)
| _, _ =>
TransM.error s!"parseTopLevel expects topLevelProcedure or topLevelComposite, got {repr op.name}"
TransM.error s!"parseTopLevel expects topLevelProcedure, topLevelComposite, or topLevelDatatype, got {repr op.name}"

/--
Translate concrete Laurel syntax into abstract Laurel syntax
Expand Down
1 change: 1 addition & 0 deletions Strata/Languages/Laurel/Grammar/LaurelGrammar.lean
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
-- Laurel dialect definition, loaded from LaurelGrammar.st
-- NOTE: Changes to LaurelGrammar.st are not automatically tracked by the build system.
-- Update this file (e.g. this comment) to trigger a recompile after modifying LaurelGrammar.st.
-- Last grammar change: added externalBody op for external procedure/function bodies.
import Strata.DDM.Integration.Lean

namespace Strata.Laurel
Expand Down
18 changes: 18 additions & 0 deletions Strata/Languages/Laurel/Grammar/LaurelGrammar.st
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ dialect Laurel;
category LaurelType;
op intType : LaurelType => "int";
op boolType : LaurelType => "bool";
op float64Type : LaurelType => "float64";
op stringType : LaurelType => "string";
op mapType (keyType: LaurelType, valueType: LaurelType): LaurelType => "Map " keyType " " valueType;
op compositeType (name: Ident): LaurelType => name;

category StmtExpr;
Expand Down Expand Up @@ -106,6 +108,20 @@ op optionalExtends(parents: CommaSepBy Ident): OptionalExtends => "extends " par
category Composite;
op composite (name: Ident, extending: Option OptionalExtends, fields: Seq Field): Composite => "composite " name extending "{" fields "}";

// Datatype definitions
category DatatypeConstructorArg;
op datatypeConstructorArg (name: Ident, argType: LaurelType): DatatypeConstructorArg => name ":" argType;

category DatatypeConstructor;
op datatypeConstructor (name: Ident, args: CommaSepBy DatatypeConstructorArg): DatatypeConstructor => name "(" args ")";
op datatypeConstructorNoArgs (name: Ident): DatatypeConstructor => name;

category DatatypeConstructorList;
op datatypeConstructorList (constructors: CommaSepBy DatatypeConstructor): DatatypeConstructorList => constructors;

category Datatype;
op datatype (name: Ident, constructors: DatatypeConstructorList): Datatype => "datatype " name "{" constructors "}";

// Procedures
category OptionalReturnType;
op optionalReturnType(returnType: LaurelType): OptionalReturnType => ":" returnType;
Expand All @@ -124,6 +140,7 @@ op returnParameters(parameters: CommaSepBy Parameter): ReturnParameters => "retu

category OptionalBody;
op optionalBody(body: StmtExpr): OptionalBody => body:0;
op externalBody: OptionalBody => "external";

category Procedure;
op procedure (name : Ident, parameters: CommaSepBy Parameter,
Expand All @@ -147,5 +164,6 @@ op function (name : Ident, parameters: CommaSepBy Parameter,
category TopLevel;
op topLevelComposite(composite: Composite): TopLevel => composite;
op topLevelProcedure(procedure: Procedure): TopLevel => procedure;
op topLevelDatatype(datatype: Datatype): TopLevel => datatype;

op program (items: Seq TopLevel): Command => items;
Loading
Loading