The unified statement-expression type for Laurel programs.
Constructors
Strata.Laurel.StmtExpr.Goto (target : String)
(destination : Strata.Laurel.GotoDestination) :
Strata.Laurel.StmtExpr
Jump to the start or past the end of an enclosing labelled block. Models
break and continue statements, and the reducible control flow of a
bytecode method.
Strata.Laurel.StmtExpr.Var (var : Strata.Laurel.Variable) :
Strata.Laurel.StmtExpr
A variable reference or declaration. When var is Variable.Local, this is a reference
that evaluates to the variable's value. When var is Variable.Declare, this is a
declaration without an initializer (used as a standalone statement in a block).
Strata.Laurel.StmtExpr.IncrDecr
(mode : Strata.Laurel.IncrDecrMode)
(op : Strata.Laurel.IncrDecrOp)
(target : Strata.Laurel.AstNode Strata.Laurel.Variable) :
Strata.Laurel.StmtExpr
Java-style increment/decrement operator. The target must be a Local or Field
Variable. As an expression, prefix form yields the new value (after the update)
and postfix form yields the old value (before the update). As a statement the
yielded value is discarded.
Eliminated by the EliminateIncrDecrAndCompoundAssign pass before lifting imperative expressions.
Strata.Laurel.StmtExpr.Call
(receiver? :
Option (Strata.Laurel.AstNode Strata.Laurel.StmtExpr))
(callee : Strata.Laurel.Identifier)
(arguments :
List (Strata.Laurel.AstNode Strata.Laurel.StmtExpr))
(typeArgs :
List (Strata.Laurel.AstNode Strata.Laurel.HighType)) :
Strata.Laurel.StmtExpr
Call a procedure by name with the given arguments.
receiver? is none for a static call and some target for an instance
call target#callee(args), whose callee is resolved in the target's
composite type. LiftInstanceProcedures rewrites every instance call into
a static one that passes the receiver as the first argument.
Primitive operators are calls too: x + y is a static call to the
built-in wrapper $add. See Operation.procName.
typeArgs carries the call's INFERRED type arguments, in the callee's
declaration order, for a generic callee — Resolution stamps them once it
has determined every one (and reports the call when it cannot); a generic
destructor carries its receiver's, in its datatype's order; an instance call
carries those inferred for the method's own type parameters. Empty for a
monomorphic callee, and empty on a freshly parsed tree: there is no surface
syntax for type arguments at a call, so this is a resolution output, not
something the user writes. Deliberately NOT defaulted: a defaulted field is
matched against its default in a PATTERN, so .Call none f args would
silently narrow to "no recorded instantiation" and any call carrying one
would fall through a non-exhaustive match with no compile error. Recorded rather than re-derived because a
downstream pass cannot recover it — computeExprType reports the callee's
DECLARED return type, without the call-site substitution, so the
instantiation of an external generic primitive (mapConst, setEmpty)
would otherwise be lost between resolution and Core translation. Mirrors
New's typeArgs in purpose.
Strata.Laurel.StmtExpr.New (ref : Strata.Laurel.Identifier)
(typeArgs :
List (Strata.Laurel.AstNode Strata.Laurel.HighType) :=
[]) :
Strata.Laurel.StmtExpr
Create new object (new). typeArgs carries explicit instantiation
arguments for a generic composite, e.g. new Box<int> → ref = Box,
typeArgs = [int]. Empty for a non-generic new C (the common case and the
pre-existing surface syntax), so the monomorphizer can read the concrete
instantiation directly off the allocation site rather than recovering it
from surrounding context.
Strata.Laurel.StmtExpr.Old
(value : Strata.Laurel.AstNode Strata.Laurel.StmtExpr)
(label? : Option Strata.Laurel.Identifier := none) :
Strata.Laurel.StmtExpr
Refer to the value of value at an earlier program point.
label? names which earlier state:
-
none — the procedure's native pre-state (Core's two-state old). This
is the only form on the regular path; surface old(e) produces it.
-
some h — a named earlier state h, so old reads that state rather
than the procedure entry state. h is bound either by a Snapshot h
earlier in the body or by a threaded Heap parameter.
Strata.Laurel.StmtExpr.OldGuarantee
(value : Strata.Laurel.AstNode Strata.Laurel.StmtExpr) :
Strata.Laurel.StmtExpr
Coroutine-only: refer to the value of value at the start of the
current coroutine step. Surface form: oldGuarantee(value).
Outside a coroutine body it is a resolution error. The lowering depends on
the path:
-
Body path — the start-of-step heap is the previous yield's
post-havoc snapshot (or procedure entry for the first yield), so it
lowers to a labeled Old value (some $old_heap) reading the
start-of-step Snapshot — the same lowering as an implicit old(...)
inside a guarantees clause.
-
Caller path — the start-of-step heap is resume's native entry
state (H2), so it lowers to a plain Old value (no label) that
push-old distributes onto the inout $heap.
The user uses this in body asserts and loop invariants where the
framework needs to relate the current heap to the previous yield's
resume point.
Strata.Laurel.StmtExpr.OldRelies
(value : Strata.Laurel.AstNode Strata.Laurel.StmtExpr) :
Strata.Laurel.StmtExpr
Coroutine-only: the old state of a two-state relies R(old, now)
— the heap at the coroutine's most recent suspension (H1). Surface
form: oldRelies(value). Unlike OldGuarantee (whose old heap is
resume's native entry state), H1 is tracked by the caller per
instance and threaded in as an explicit $h_rely_old : Heap
parameter, so on the caller path oldRelies(e) lowers to
Old e (some $h_rely_old) (no Core old, since relies become resume
preconditions). Seeded to the current heap on the first resume, so
R(H1, now) becomes R(H0, H0) there.
Strata.Laurel.StmtExpr.Hole (deterministic : Bool := true)
(type :
Option (Strata.Laurel.AstNode Strata.Laurel.HighType) :=
none) :
Strata.Laurel.StmtExpr
A hole represents an unknown expression.
This can be used to represent programs that are still under development, for example the program 3 +
The defining property of a hole is that interaction with it and other code should not produce any errors.
Besides representing partial user programs,
holes can also be used to handle under development parts of compilers that target Laurel.
-
deterministic: if true, the hole represents a deterministic unknown
(translated as an uninterpreted function); if false, a nondeterministic
unknown (translated as a havoced variable). Nondeterministic holes are
not allowed in functions.
-
type: this property is used internally by Laurel and can be left to its default value.
Internal usage: inferred by the hole type inference pass; none means not yet inferred.
Strata.Laurel.StmtExpr.Yield : Strata.Laurel.StmtExpr
Yield expression used inside coroutines.
Statement position: suspends the coroutine; the resumed value is dropped.
Expression position (z := yield): suspends; evaluates to the value the
next resume(co, v) sends in (type matches the coroutine's resumes
binding).
To yield a value outward, the user assigns it to the coroutine's
yields binding before the suspension: x := e; yield.