153 Denotation of Absence, This, Splat, Let, and Constraints
12. Absence
The expression none is a curtailed no-result expression. It is not a value term and is not
translated by the scalar/function-application rule. It may appear only in source contexts that
explicitly permit absence, such as optional-result conditionals, presence tests, and optional
location clearing. It is never a member of any value domain.
ℒ(Γ, P, none) =
⟨∅ for ∅ where false⟩
Source comparisons with none are desugared before denotation: E = none means E.Σempty,
and E ≠ none means E.Σexists. After this rewrite, none is not passed to the scalar
comparison rule as an operand.
13. this and splat
ℒ(Γ, P, this)
{
if Γ = []
raise error
return currentFrame(Γ)
}
ℒ(Γ, P, *)
{
if Γ = []
raise error
let γ = currentFrame(Γ)
let (x,C,Tₓ) = unary(γ)
let A = { a | (a,Tₐ) ∈ attributes(Tₓ) }
return ⟨
{ _anon_ = A:Set<Attribute> }
for
free(γ)
where
formula(γ)
⟩
}
14. Let
ℒ(Γ, P, let a = E₁ in E₂)
{
let γ₁ = ℒ(Γ, P, E₁)
let (b,C,T) = unary(γ₁)
let γₐ = ⟨{ a = C:T } for free(γ₁) where formula(γ₁)⟩
let γ₂ = ℒ(push(Γ, γₐ), P, E₂)
return bind∃(γ₁, γ₂, P)
}
The binding is structural: the name points to the bound value's result term while keeping the bound formula and free variables attached to it.
15. Constraints
For a constraint expression C declared on type T, start with a frame for the constrained
value:
γ_this = ⟨{ this = this:T } for ∅ where true⟩
γ_C = ℒ([γ_this], ∅, C)
this is a source-level value supplied by the surrounding constraint, not a generated logic
variable. Fresh variables introduced while translating the constraint are added to free(γ_C).
if result(γ_C) = { a = B:Boolean }
constraint formula = ∀vars(free(γ_C)) ( formula(γ_C) → B )
else
reject the constraint
Design consequences
The frame calculus has the following consequences:
Fis the set of free variables of the frame, not a result. Its attribute labels are informational and do not replace the derivation given byRandΨ.- The current frame and current domain are distinct views of the same top frame. Rules that
need the current result value are based on the current frame rather than
domain. - Universal composition can be factored through
bind∀, which selects variables satisfying the precondition ofclose∀. - Filter, complement, fold, and cardinality rules show why protected variables are more than a control flag. A protected variable that remains free in the returned formula or term is retained in the returned frame's free variables.
- Tuple construction uses a stricter result merge than path-level meet and union. Duplicate result attributes and duplicate implicit result terms are rejected after attribute-set expansion, while deliberate aliases may expose the same variable under two explicit names.
- Path difference is written with source syntax
--, distinct from scalar and set difference. Scalar and set difference use the canonical set-minus character described in the lexical grammar, with keyboard backslash accepted as an input alias. - The right-hand frame in composition already contains the left-hand conditions that were available while the right-hand expression was translated.