149 Denotation of Scalar Terms and Attribute Navigation
1. Scalar terms and function application
Function application covers literals, arithmetic, comparisons, type tests, boolean connectives, ordinary function calls, symbolic constants, finite value-set literals, and references to program variables. Boolean expressions are scalar terms until a rule lifts them into the formula layer.
ℒ(Γ, P, f(E₁, ..., Eₙ))
{
let γ₀ = currentDomain(Γ)
for each i
{
let γᵢ = ℒ(Γ, P, Eᵢ)
let (aᵢ,Cᵢ,Tᵢ) = unary(γᵢ)
}
let T = resulttype(f, T₁, ..., Tₙ)
return ⟨
{ _anon_ = f(C₁,...,Cₙ):T }
for
free(γ₀) ∪ free(γ₁) ∪ ... ∪ free(γₙ)
where
formula(γ₀) ∧ formula(γ₁) ∧ ... ∧ formula(γₙ)
⟩
}
For a literal or nullary program symbol, this reduces to:
ℒ(Γ, P, c) =
⟨{ _anon_ = c:type(c) } for free(currentDomain(Γ)) where formula(currentDomain(Γ))⟩
2. Attribute lookup and navigation
An attribute name is resolved by searching frames from top to bottom. Within a frame, scalar result navigation is tried before structural lookup.
The set attributes(T) includes the attributes of entity, value, variant, and enum types. Variant
and enum attributes therefore use the same navigation rule as ordinary entity and value attributes.
ℒ(Γ, P, a)
{
for each γ in Γ, searching top first
{
// Nominal navigation: unary frame whose result type defines attribute a.
if result(γ) = { x = C:Tₓ } and (a,T) ∈ attributes(Tₓ)
{
let V be fresh
return ⟨
{ a = V:T }
for
free(γ) ∪ { V:T from a }
where
formula(γ) ∧ C.a(V)
⟩
}
// Structural lookup: the frame result already contains attribute a.
if a = C:T ∈ result(γ)
{
return ⟨{ a = C:T } for free(γ) where formula(γ)⟩
}
}
raise error(attribute a not found)
}
This rule carries the frame's formula into the resulting path frame. Later composition rules do not
need a side condition saying that the left-hand frame was already used; it is already in
formula(γ).
For example, with source variable s:ShipmentsSystem, nominal navigation of supplier introduces
an uppercase logic variable S:
ℒ([], ∅, s.supplier)
=
⟨
{ supplier = S:Supplier }
for
{ S:Supplier from supplier }
where
s.supplier(S)
⟩