151 Denotation of Path Operations and Alternatives
7. Path meet, union, and difference
The path-level logical connectives are direct calls to the horizontal frame operations:
ℒ(Γ, P, E₁ ⊓ E₂)
{
return ℒ(Γ, P, E₁) ⊓ ℒ(Γ, P, E₂)
}
ℒ(Γ, P, E₁ ⊔ E₂)
{
return ℒ(Γ, P, E₁) ⊔ ℒ(Γ, P, E₂)
}
ℒ(Γ, P, E₁ -- E₂)
{
return ℒ(Γ, P, E₁) -- ℒ(Γ, P, E₂)
}
The difference rule is unrestricted logical negation. Union-compatible results are not
required. Source-level path difference is written --. Scalar and set difference use the
canonical set-minus character described in the lexical grammar, with keyboard backslash accepted
as an input alias.
For example, s.(supplier.city ⊔ part.city) is a genuine query-level union. Both operands have
result attribute city = C:String, so alignment unifies the result city term and combines the two
formulas with ∨.
8. Alternative operator
The operator | is the expression-level alternative operator. It combines branches with
exactly one result term by logical disjunction. The branch result names do not need to align:
matching names are preserved, while differing names produce an anonymous result. Each branch
contributes possible values for one shared result, which is useful for expressions such as
variant-derived definitions:
sphere.(4/3*pi*radius^3) | cube.(side^3) | cone.(pi*radius^2*height/3)
Each operand must denote exactly one result. The operand result types must have a common result type. The alternative expression introduces one fresh output variable and each branch states that this output variable equals the value produced by that branch.
branchAlt(γ, C, O, γ_receiver, P)
{
let Ψ = formula(γ) ∧ O = C
let F = free(γ)
let Q = vars(F)
if γ_receiver ≠ noFrame
Q = Q \ vars(free(γ_receiver))
Q = Q \ P
Q = Q ∩ FV(Ψ)
let K = decls(F, Q)
return ∃(K) Ψ
}
ℒ(Γ, P, E₁ | E₂)
{
let γ₁ = ℒ(Γ, P, E₁)
let γ₂ = ℒ(Γ, P, E₂)
let (a₁,C₁,T₁) = unary(γ₁)
let (a₂,C₂,T₂) = unary(γ₂)
require T₁ and T₂ have common type T
let a = if a₁ = a₂ then a₁ else _anon_
let O:T be fresh
let γ_receiver = if Γ = [] then noFrame else currentFrame(Γ)
let Ψ =
branchAlt(γ₁, C₁, O, γ_receiver, P)
∨ branchAlt(γ₂, C₂, O, γ_receiver, P)
let F =
{ O:T from a }
∪ { d ∈ free(γ₁) ∪ free(γ₂) | var(d) ∈ FV(Ψ) }
return ⟨
{ a = O:T }
for
F
where
Ψ
⟩
}
This rule explains why a derived attribute over variant attributes naturally renders as a
disjunction. For a Shape.volume definition, the sphere, cube, and cone branch formulas are
inclusive alternatives for the same output volume variable. The | operator exposes one shared
result whose possible values are constrained by the disjunction of the branch formulas; if the branch
result names differ, that shared result is anonymous.
The raw alternative denotation is independent of schema cardinality constraints. A later
schema-aware formula simplifier may use cardinality facts for display. For example, if a branch
contains two structural equalities for the same single-valued record fields, the simplifier may infer
the corresponding field-term equalities and remove redundant witnesses. That is a simplification of
the rendered formula, not a side condition of the | denotation rule.
Declaration-level either is intentionally outside these path-expression rules. It is not a
composite expression and does not introduce a disjunction into the denotation of a path expression.