Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
146 commits
Select commit Hold shift + click to select a range
f3bf3a5
Add Laurel grammar and transformation
keyboardDrummer Dec 9, 2025
4589663
refactoring
keyboardDrummer Dec 9, 2025
037a7d1
Fixes
keyboardDrummer Dec 9, 2025
1c9cfd1
Moved tests
keyboardDrummer Dec 9, 2025
3a3809c
Fix grammar test
keyboardDrummer Dec 9, 2025
927b0bb
Getting there
keyboardDrummer Dec 9, 2025
faa49df
TestExamples test passes
keyboardDrummer Dec 9, 2025
4481959
Refactoring
keyboardDrummer Dec 9, 2025
c600cf1
Fix
keyboardDrummer Dec 9, 2025
25df923
Revert AdvancedMaps changes
keyboardDrummer Dec 10, 2025
3c933e5
Add missing license headers
keyboardDrummer Dec 10, 2025
f182891
Revert RealBitVector
keyboardDrummer Dec 10, 2025
5bc8abd
Tweaks
keyboardDrummer Dec 10, 2025
fe2a831
Save state
keyboardDrummer Dec 10, 2025
2cd178c
Refactoring
keyboardDrummer Dec 10, 2025
12946cf
Refactoring
keyboardDrummer Dec 10, 2025
b12d781
Cleanup
keyboardDrummer Dec 10, 2025
75cc85f
Merge branch 'main' into laurelParsing
keyboardDrummer Dec 10, 2025
84235b4
Fix Laurel/TestGrammar
keyboardDrummer Dec 10, 2025
cffb991
Merge branch 'laurelParsing' of github.com:keyboardDrummer/Strata int…
keyboardDrummer Dec 10, 2025
b2ae3dc
Move Boogie examples
keyboardDrummer Dec 11, 2025
ea3438f
Rename
keyboardDrummer Dec 11, 2025
77aa05a
Merge remote-tracking branch 'origin' into laurelParsing
keyboardDrummer Dec 15, 2025
fbe4de5
Move back Boogie examples
keyboardDrummer Dec 15, 2025
e827d76
Remove white line
keyboardDrummer Dec 15, 2025
ff76419
Moved examples
keyboardDrummer Dec 15, 2025
ce236d8
Delete Examples.lean files since they're obsolete
keyboardDrummer Dec 15, 2025
79fbeb9
Remove duplication
keyboardDrummer Dec 15, 2025
b0832e6
Expand test
keyboardDrummer Dec 15, 2025
2de306c
Do not use type and fn feature from DDM
keyboardDrummer Dec 15, 2025
6e90ace
Fix parser
keyboardDrummer Dec 15, 2025
8ff685d
Update translate file
keyboardDrummer Dec 15, 2025
086f6f8
Added some expected errors
keyboardDrummer Dec 15, 2025
0ea1bbb
Fix test
keyboardDrummer Dec 15, 2025
c397cb5
Attempt at translating to Boogie
keyboardDrummer Dec 15, 2025
126885b
Add sequencing of impure expressions
keyboardDrummer Dec 15, 2025
b547baf
Move towards combining test and source file
keyboardDrummer Dec 15, 2025
83c28d6
Improve translator to Boogie
keyboardDrummer Dec 16, 2025
a496a14
Merge remote-tracking branch 'origin/main' into laurelParsing
keyboardDrummer Dec 16, 2025
4ac44c9
Merge branch 'main' into moveExamples
keyboardDrummer Dec 16, 2025
c2164e2
Merge branch 'laurelParsing' into laurelMoreStmtExpr
keyboardDrummer Dec 16, 2025
245f7ad
Fix after merge
keyboardDrummer Dec 16, 2025
4683301
Merge branch 'laurelParsing' into laurelMoreStmtExpr
keyboardDrummer Dec 16, 2025
69e05e4
Update test
keyboardDrummer Dec 16, 2025
95bb904
Fix
keyboardDrummer Dec 16, 2025
1d19b86
Fix oops
keyboardDrummer Dec 16, 2025
0ebc51d
Merge branch 'laurelParsing' into laurelMoreStmtExpr
keyboardDrummer Dec 16, 2025
c44fad1
Fix warning
keyboardDrummer Dec 16, 2025
d0bada5
Fixes
keyboardDrummer Dec 16, 2025
125bf17
Fix warning
keyboardDrummer Dec 16, 2025
fd1374f
Renames
keyboardDrummer Dec 16, 2025
cd77f34
T2_NestedImpureStatements.lean
keyboardDrummer Dec 16, 2025
de4e4a4
Restructure files
keyboardDrummer Dec 16, 2025
110fc87
Improvements
keyboardDrummer Dec 16, 2025
0104e5a
Updates
keyboardDrummer Dec 16, 2025
a7562b5
Updates to the grammar
keyboardDrummer Dec 16, 2025
d530725
Updates
keyboardDrummer Dec 16, 2025
d37c57a
Add panics
keyboardDrummer Dec 16, 2025
871b27e
Translate all operators
keyboardDrummer Dec 16, 2025
8ddbaa3
Merge branch 'main' into moveExamples
aqjune-aws Dec 16, 2025
5624f00
Progress with T3
keyboardDrummer Dec 17, 2025
02c5cdd
Merge remote-tracking branch 'origin/main' into moveExamples
keyboardDrummer Dec 17, 2025
9efa44a
Undo bad changes
keyboardDrummer Dec 17, 2025
853aa4d
Merge branch 'laurelParsing' into laurelMoreStmtExpr
keyboardDrummer Dec 17, 2025
088816c
Merge branch 'moveExamples' into laurelMoreStmtExpr
keyboardDrummer Dec 17, 2025
f0454dd
T3 passes now
keyboardDrummer Dec 17, 2025
b70f84d
Added failing assertion
keyboardDrummer Dec 17, 2025
6b0c417
Add breaking comment
keyboardDrummer Dec 18, 2025
67f4b31
Test update
keyboardDrummer Dec 18, 2025
333fc61
Test passes now
keyboardDrummer Dec 18, 2025
eae1536
Merge branch 'main' into laurelParsing
keyboardDrummer Dec 18, 2025
7e16741
Merge remote-tracking branch 'origin/main' into laurelParsing
keyboardDrummer Dec 18, 2025
f711bdc
Merge branch 'laurelParsing' of github.com:keyboardDrummer/Strata int…
keyboardDrummer Dec 18, 2025
fbb9a07
Merge branch 'laurelParsing' into laurelMoreStmtExpr
keyboardDrummer Dec 18, 2025
0d964e3
Add missing file
keyboardDrummer Dec 18, 2025
b3c66a3
Fix
keyboardDrummer Dec 18, 2025
f75ed44
Improve testing output and fix some issues
keyboardDrummer Dec 18, 2025
c6c8d5c
Use dbg_trace instead of IO
keyboardDrummer Dec 18, 2025
f878398
Cleanup
keyboardDrummer Dec 18, 2025
f80e775
Rename
keyboardDrummer Dec 18, 2025
b7f4f86
Fix TestGrammar file
keyboardDrummer Dec 18, 2025
78b8c88
Refactoring
keyboardDrummer Dec 18, 2025
f24afe5
Cleanup
keyboardDrummer Dec 18, 2025
3283f93
Improvements to output parameters
keyboardDrummer Dec 18, 2025
b423c9e
Cleanup
keyboardDrummer Dec 18, 2025
4cec349
Rename file
keyboardDrummer Dec 19, 2025
c32a3d5
Move file
keyboardDrummer Dec 19, 2025
44c4082
Merge remote-tracking branch 'origin/main' into laurelParsing
keyboardDrummer Dec 19, 2025
d803b56
Fixes
keyboardDrummer Dec 19, 2025
9856651
Fix TestGrammar
keyboardDrummer Dec 23, 2025
f6dfea9
Merge branch 'main' into laurelParsing
keyboardDrummer Dec 23, 2025
91ad85f
Merge branch 'laurelParsing' into laurelMoreStmtExpr
keyboardDrummer Dec 23, 2025
89d9008
Fixes
keyboardDrummer Dec 23, 2025
f8a9a67
Merge branch 'main' into laurelParsing
shigoel Dec 24, 2025
e05f137
Add tests for what is not supported
keyboardDrummer Dec 24, 2025
1dde070
Code review from previous PR
keyboardDrummer Dec 24, 2025
721c6c0
Merge remote-tracking branch 'fork/laurelParsing' into laurelMoreStmt…
keyboardDrummer Dec 24, 2025
79203e4
Merge commit '23050398e4a9782' into laurelMoreStmtExpr
keyboardDrummer Dec 24, 2025
d0ea8bf
Small refactoring
keyboardDrummer Dec 24, 2025
a40faed
Merge branch 'laurelMoreStmtExpr' into laurelFundamentalsNotSupported
keyboardDrummer Dec 24, 2025
7cf21e0
Improve error reporting when calling solver
keyboardDrummer Dec 24, 2025
bf0b2b9
Merge remote-tracking branch 'origin/main' into laurelMoreStmtExpr
keyboardDrummer Jan 5, 2026
53bab9c
Add missing import
keyboardDrummer Jan 5, 2026
b845049
Remove obsolete TestGrammar file
keyboardDrummer Jan 5, 2026
91058f8
Merge branch 'main' into laurelMoreStmtExpr
keyboardDrummer Jan 8, 2026
1c186a0
Fix errors
keyboardDrummer Jan 8, 2026
4bc6a2b
Remove hack
keyboardDrummer Jan 8, 2026
e805c57
Merge branch 'laurelMoreStmtExpr' into laurelFundamentalsNotSupported
keyboardDrummer Jan 8, 2026
2a4fdf7
Fix issues
keyboardDrummer Jan 8, 2026
583f7ea
More fixes
keyboardDrummer Jan 8, 2026
c37e396
Fixes
keyboardDrummer Jan 8, 2026
e8c8a13
Fixes to Strata/Languages/Laurel/LiftExpressionAssignments.lean
keyboardDrummer Jan 9, 2026
c711142
Refactoring
keyboardDrummer Jan 9, 2026
202633a
Refactoring
keyboardDrummer Jan 9, 2026
9451e45
Refactoring
keyboardDrummer Jan 9, 2026
2ff9f17
Refactoring
keyboardDrummer Jan 9, 2026
d4efe5b
Merge branch 'main' into laurelMoreStmtExpr
keyboardDrummer Jan 9, 2026
c90a7de
Add termination proofs for formatStmtExpr and translateExpr
Jan 9, 2026
f0aa528
Sequence the program using a reversed list for bookkeeping
keyboardDrummer Jan 12, 2026
f282147
Merge branch 'main' into laurelMoreStmtExpr
keyboardDrummer Jan 12, 2026
a84748a
Remove noise
keyboardDrummer Jan 12, 2026
5170e51
Merge branch 'laurelMoreStmtExpr' of github.com:keyboardDrummer/Strat…
keyboardDrummer Jan 12, 2026
e283b22
Merge branch 'laurelMoreStmtExpr' into laurelFundamentalsNotSupported
keyboardDrummer Jan 14, 2026
fe86098
Merge commit 'da9169e0597~1' into laurelFundamentalsNotSupported
keyboardDrummer Jan 14, 2026
ed227ef
Merge commit 'da9169e0597' into laurelFundamentalsNotSupported
keyboardDrummer Jan 14, 2026
b694fae
Merge remote-tracking branch 'origin/main' into laurelFundamentalsNot…
keyboardDrummer Jan 14, 2026
c5f9687
Merge branch 'forJVerify' into laurelFundamentalsNotSupported
keyboardDrummer Jan 14, 2026
3d358ca
Cleanup
keyboardDrummer Jan 14, 2026
086bf22
Draft work
keyboardDrummer Jan 14, 2026
e6142e3
Merge branch 'forJVerify' into mutableFields
keyboardDrummer Jan 15, 2026
61b305e
Some updates
keyboardDrummer Jan 15, 2026
0a777e0
Updates
keyboardDrummer Jan 15, 2026
4ab53da
Fix translator
keyboardDrummer Jan 15, 2026
25c36f5
Start
keyboardDrummer Jan 15, 2026
6c964ad
Progress
keyboardDrummer Jan 15, 2026
d539bec
Some changes
keyboardDrummer Jan 15, 2026
e4df61f
Updates
keyboardDrummer Jan 15, 2026
dd16f98
Updates
keyboardDrummer Jan 15, 2026
b6cd5c1
T1_MutableFields passes, although it's partially commented out
keyboardDrummer Jan 16, 2026
f4b1ab9
Merge remote-tracking branch 'origin/main' into mutableFields
keyboardDrummer Jan 16, 2026
ff3bb23
Merge remote-tracking branch 'fork/forJVerify' into mutableFields
keyboardDrummer Jan 16, 2026
3a16928
Merge remote-tracking branch 'fork/forJVerify' into mutableFields
keyboardDrummer Jan 16, 2026
d72523c
Add limited procedure calls test
keyboardDrummer Jan 16, 2026
2812fc0
Improved test
keyboardDrummer Jan 16, 2026
89aa89a
T5_ProcedureCallsBoogie.lean passes now
keyboardDrummer Jan 16, 2026
a9d5c60
Add comment
keyboardDrummer Jan 16, 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
1 change: 0 additions & 1 deletion Strata/DDM/Elab.lean
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,6 @@ def elabDialect
elabDialectRest fm dialects #[] inputContext loc dialect startPos stopPos

def parseStrataProgramFromDialect (dialects : LoadedDialects) (dialect : DialectName) (input : InputContext) : IO Strata.Program := do

let leanEnv ← Lean.mkEmptyEnvironment 0

let isTrue mem := inferInstanceAs (Decidable (dialect ∈ dialects.dialects))
Expand Down
23 changes: 12 additions & 11 deletions Strata/Languages/Boogie/Verifier.lean
Original file line number Diff line number Diff line change
Expand Up @@ -485,18 +485,19 @@ structure Diagnostic where
message : String
deriving Repr, BEq

def toDiagnostic (files: Map Strata.Uri Lean.FileMap) (vcr : Boogie.VCResult) : Option Diagnostic := do
def DiagnosticModel.toDiagnostic (files: Map Strata.Uri Lean.FileMap) (dm: DiagnosticModel): Diagnostic :=
let fileMap := (files.find? dm.fileRange.file).get!
let startPos := fileMap.toPosition dm.fileRange.range.start
let endPos := fileMap.toPosition dm.fileRange.range.stop
{
start := { line := startPos.line, column := startPos.column }
ending := { line := endPos.line, column := endPos.column }
message := dm.message
}

def Boogie.VCResult.toDiagnostic (files: Map Strata.Uri Lean.FileMap) (vcr : Boogie.VCResult) : Option Diagnostic := do
let modelOption := toDiagnosticModel vcr
modelOption.map (fun dm =>
let fileMap := (files.find? dm.fileRange.file).get!
let startPos := fileMap.toPosition dm.fileRange.range.start
let endPos := fileMap.toPosition dm.fileRange.range.stop
{
start := { line := startPos.line, column := startPos.column }
ending := { line := endPos.line, column := endPos.column }
message := dm.message
}
)
modelOption.map (fun dm => dm.toDiagnostic files)

end Strata

Expand Down
107 changes: 77 additions & 30 deletions Strata/Languages/Laurel/Grammar/ConcreteToAbstractTreeTranslator.lean
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Strata.Languages.Laurel.Laurel
import Strata.DL.Imperative.MetaData
import Strata.Languages.Boogie.Expressions

namespace Strata
namespace Laurel

open Std (ToFormat Format format)
Expand Down Expand Up @@ -79,10 +80,13 @@ instance : Inhabited Parameter where
def translateHighType (arg : Arg) : TransM HighType := do
match arg with
| .op op =>
match op.name with
| q`Laurel.intType => return .TInt
| q`Laurel.boolType => return .TBool
| _ => TransM.error s!"translateHighType expects intType or boolType, got {repr op.name}"
match op.name, op.args with
| q`Laurel.intType, _ => return .TInt
| q`Laurel.boolType, _ => return .TBool
| q`Laurel.compositeType, #[nameArg] =>
let name ← translateIdent nameArg
return .UserDefined name
| _, _ => TransM.error s!"translateHighType expects intType, boolType or compositeType, got {repr op.name}"
| _ => TransM.error s!"translateHighType expects operation"

def translateNat (arg : Arg) : TransM Nat := do
Expand Down Expand Up @@ -116,8 +120,6 @@ instance : Inhabited Procedure where
outputs := []
precondition := .LiteralBool true
decreases := none
determinism := Determinism.deterministic none
modifies := none
body := .Transparent (.LiteralBool true)
}

Expand Down Expand Up @@ -157,8 +159,8 @@ partial def translateStmtExpr (arg : Arg) : TransM StmtExpr := do
let varType ← match typeArg with
| .option _ (some (.op typeOp)) => match typeOp.name, typeOp.args with
| q`Laurel.optionalType, #[typeArg0] => translateHighType typeArg0
| _, _ => pure .TInt
| _ => pure .TInt
| _, _ => TransM.error s!"Variable {name} requires explicit type"
| _ => TransM.error s!"Variable {name} requires explicit type"
let value ← match assignArg with
| .option _ (some (.op assignOp)) => match assignOp.args with
| #[assignArg0] => translateStmtExpr assignArg0 >>= (pure ∘ some)
Expand All @@ -173,7 +175,8 @@ partial def translateStmtExpr (arg : Arg) : TransM StmtExpr := do
| q`Laurel.assign, #[arg0, arg1] =>
let target ← translateStmtExpr arg0
let value ← translateStmtExpr arg1
return .Assign target value
let md ← getArgMetaData (.op op)
return .Assign target value md
| q`Laurel.call, #[arg0, argsSeq] =>
let callee ← translateStmtExpr arg0
let calleeName := match callee with
Expand All @@ -195,6 +198,10 @@ partial def translateStmtExpr (arg : Arg) : TransM StmtExpr := do
| _, _ => pure none
| _ => pure none
return .IfThenElse cond thenBranch elseBranch
| q`Laurel.fieldAccess, #[objArg, fieldArg] =>
let obj ← translateStmtExpr objArg
let field ← translateIdent fieldArg
return .FieldSelect obj field
| _, #[arg0, arg1] => match getBinaryOp? op.name with
| some primOp =>
let lhs ← translateStmtExpr arg0
Expand Down Expand Up @@ -223,32 +230,73 @@ def parseProcedure (arg : Arg) : TransM Procedure := do
| TransM.error s!"parseProcedure expects operation"

match op.name, op.args with
| q`Laurel.procedure, #[arg0, arg1, returnParamsArg, arg3] =>
let name ← translateIdent arg0
let parameters ← translateParameters arg1
-- returnParamsArg is ReturnParameters category, need to unwrap returnParameters operation
let returnParameters ← match returnParamsArg with
| .option _ (some (.op returnOp)) => match returnOp.name, returnOp.args with
| q`Laurel.returnParameters, #[returnArg0] => translateParameters returnArg0
| _, _ => TransM.error s!"Expected returnParameters operation, got {repr returnOp.name}"
| .option _ none => pure []
| _ => TransM.error s!"Expected returnParameters operation, got {repr returnParamsArg}"
let body ← translateCommand arg3
| q`Laurel.procedure, #[nameArg, paramArg, returnTypeArg, returnParamsArg,
requiresArg, ensuresArg, bodyArg] =>
let name ← translateIdent nameArg
let parameters ← translateParameters paramArg
-- Either returnTypeArg or returnParamsArg may have a value, not both
-- If returnTypeArg is set, create a single "result" parameter
let returnParameters ← match returnTypeArg with
| .option _ (some (.op returnTypeOp)) => match returnTypeOp.name, returnTypeOp.args with
| q`Laurel.optionalReturnType, #[typeArg] =>
let retType ← translateHighType typeArg
pure [{ name := "result", type := retType : Parameter }]
| _, _ => TransM.error s!"Expected optionalReturnType operation, got {repr returnTypeOp.name}"
| .option _ none =>
-- No return type, check returnParamsArg instead
match returnParamsArg with
| .option _ (some (.op returnOp)) => match returnOp.name, returnOp.args with
| q`Laurel.returnParameters, #[returnArg0] => translateParameters returnArg0
| _, _ => TransM.error s!"Expected returnParameters operation, got {repr returnOp.name}"
| .option _ none => pure []
| _ => TransM.error s!"Expected returnParameters operation, got {repr returnParamsArg}"
| _ => TransM.error s!"Expected optionalReturnType operation, got {repr returnTypeArg}"
-- Parse precondition (requires clause)
let precondition ← match requiresArg with
| .option _ (some (.op requiresOp)) => match requiresOp.name, requiresOp.args with
| q`Laurel.optionalRequires, #[exprArg] => translateStmtExpr exprArg
| _, _ => TransM.error s!"Expected optionalRequires operation, got {repr requiresOp.name}"
| .option _ none => pure (.LiteralBool true)
| _ => TransM.error s!"Expected optionalRequires operation, got {repr requiresArg}"
-- Parse postcondition (ensures clause)
let postcondition ← match ensuresArg with
| .option _ (some (.op ensuresOp)) => match ensuresOp.name, ensuresOp.args with
| q`Laurel.optionalEnsures, #[exprArg] => translateStmtExpr exprArg >>= (pure ∘ some)
| _, _ => TransM.error s!"Expected optionalEnsures operation, got {repr ensuresOp.name}"
| .option _ none => pure none
| _ => TransM.error s!"Expected optionalEnsures operation, got {repr ensuresArg}"
let body ← translateCommand bodyArg
-- If there's a postcondition, use Opaque body; otherwise use Transparent
let procBody := match postcondition with
| some post => Body.Opaque post (some body) .nondeterministic none
| none => Body.Transparent body
return {
name := name
inputs := parameters
outputs := returnParameters
precondition := .LiteralBool true
precondition := precondition
decreases := none
determinism := Determinism.deterministic none
modifies := none
body := .Transparent body
body := procBody
}
| q`Laurel.procedure, args =>
TransM.error s!"parseProcedure expects 4 arguments, got {args.size}"
TransM.error s!"parseProcedure expects 7 arguments, got {args.size}"
| _, _ =>
TransM.error s!"parseProcedure expects procedure, got {repr op.name}"

def parseTopLevel (arg : Arg) : TransM (Option Procedure) := do
let .op op := arg
| TransM.error s!"parseTopLevel expects operation"

match op.name, op.args with
| q`Laurel.topLevelProcedure, #[procArg] =>
let proc ← parseProcedure procArg
return some proc
| q`Laurel.topLevelComposite, #[_compositeArg] =>
-- TODO: handle composite types
return none
| _, _ =>
TransM.error s!"parseTopLevel expects topLevelProcedure or topLevelComposite, got {repr op.name}"

/--
Translate concrete Laurel syntax into abstract Laurel syntax
-/
Expand All @@ -270,11 +318,10 @@ def parseProgram (prog : Strata.Program) : TransM Laurel.Program := do

let mut procedures : List Procedure := []
for op in commands do
if op.name == q`Laurel.procedure then
let proc ← parseProcedure (.op op)
procedures := procedures ++ [proc]
else
TransM.error s!"Unknown top-level declaration: {op.name}"
let result ← parseTopLevel (.op op)
match result with
| some proc => procedures := procedures ++ [proc]
| none => pure () -- composite types are skipped for now
return {
staticProcedures := procedures
staticFields := []
Expand Down
41 changes: 35 additions & 6 deletions Strata/Languages/Laurel/Grammar/LaurelGrammar.st
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dialect Laurel;
category LaurelType;
op intType : LaurelType => "int";
op boolType : LaurelType => "bool";
op compositeType (name: Ident): LaurelType => name;

category StmtExpr;
op literalBool (b: Bool): StmtExpr => b;
Expand All @@ -19,12 +20,17 @@ op optionalAssignment(value: StmtExpr): OptionalAssignment => ":=" value:0;
op varDecl (name: Ident, varType: Option OptionalType, assignment: Option OptionalAssignment): StmtExpr
=> @[prec(0)] "var " name varType assignment ";";

// Identifiers/Variables
op call(callee: StmtExpr, args: CommaSepBy StmtExpr): StmtExpr => callee "(" args ")";

// Field access
op fieldAccess (obj: StmtExpr, field: Ident): StmtExpr => @[prec(90)] obj "#" field;

// Identifiers/Variables - must come after fieldAccess so c.value parses as fieldAccess not identifier
op identifier (name: Ident): StmtExpr => name;
op parenthesis (inner: StmtExpr): StmtExpr => "(" inner ")";

// Assignment
op assign (target: StmtExpr, value: StmtExpr): StmtExpr => target ":=" value ";";
op assign (target: StmtExpr, value: StmtExpr): StmtExpr => @[prec(10)] target ":=" value ";";

// Binary operators
op add (lhs: StmtExpr, rhs: StmtExpr): StmtExpr => @[prec(60)] lhs "+" rhs;
Expand All @@ -35,8 +41,6 @@ op lt (lhs: StmtExpr, rhs: StmtExpr): StmtExpr => @[prec(40)] lhs "<" rhs;
op le (lhs: StmtExpr, rhs: StmtExpr): StmtExpr => @[prec(40)] lhs "<=" rhs;
op ge (lhs: StmtExpr, rhs: StmtExpr): StmtExpr => @[prec(40)] lhs ">=" rhs;

op call(callee: StmtExpr, args: CommaSepBy StmtExpr): StmtExpr => callee "(" args ")";

// If-else
category OptionalElse;
op optionalElse(stmts : StmtExpr) : OptionalElse => "else" stmts;
Expand All @@ -52,13 +56,38 @@ op block (stmts : Seq StmtExpr) : StmtExpr => @[prec(1000)] "{" stmts "}";
category Parameter;
op parameter (name: Ident, paramType: LaurelType): Parameter => name ":" paramType;

// Composite types
category Field;
op mutableField (name: Ident, fieldType: LaurelType): Field => "var " name ":" fieldType;
op immutableField (name: Ident, fieldType: LaurelType): Field => name ":" fieldType;

category Composite;
op composite (name: Ident, fields: Seq Field): Composite => "composite " name "{" fields "}";

// Procedures
category OptionalReturnType;
op optionalReturnType(returnType: LaurelType): OptionalReturnType => ":" returnType;

category OptionalRequires;
op optionalRequires(cond: StmtExpr): OptionalRequires => "requires" cond:0;

category OptionalEnsures;
op optionalEnsures(cond: StmtExpr): OptionalEnsures => "ensures" cond:0;

category ReturnParameters;
op returnParameters(parameters: CommaSepBy Parameter): ReturnParameters => "returns" "(" parameters ")";

category Procedure;
op procedure (name : Ident, parameters: CommaSepBy Parameter,
returnType: Option OptionalReturnType,
returnParameters: Option ReturnParameters,
requires: Option OptionalRequires,
ensures: Option OptionalEnsures,
body : StmtExpr) : Procedure =>
"procedure " name "(" parameters ")" returnParameters body:0;
"procedure " name "(" parameters ")" returnType returnParameters requires ensures body:0;

category TopLevel;
op topLevelComposite(composite: Composite): TopLevel => composite;
op topLevelProcedure(procedure: Procedure): TopLevel => procedure;

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