Property lookup
LookupKey
LookupKey is either LocalName(name) or Computed(value).
LookupKey.Value
LookupKey.Value returns:
- For LocalName(name), a StringConstant equivalent to name or defer if
String
is unresolved. - For Computed(value), value.
LookupKey.Type
LookupKey.Type returns:
- For LocalName(name), the
String
type or defer. - For Computed(value), the static type of value or defer.
LookupKey.Double
LookupKey.Double returns:
- For LocalName(name), undefined.
- For Computed(value), value is NumberConstant(v) ? force convert v to a
Number
: undefined.
PropertyLookup()
PropertyLookup(base, openNsSet, qual, key as LookupKey, followedByCall as Boolean
, forceFixture as Boolean
) takes the following steps in order, where forceFixture allows forcing access to a fixture property on dynamic types (used by the <?fixed={}?>
expression):
- If base is invalidation
- Return invalidation
- Let localName = key is LocalName(name) ? name : undefined
- Let doubleKey = key.Double
- If base is a TypeConstant(type)
- base = type
- Else if base is a FixtureReferenceValue and base.Property is a type
- base = base.Property
- If base is a class
- If localName is undefined or (qual is specified and qual is not a namespace nor a NamespaceConstant)
- Return StaticDynamicReferenceValue(base, qual, k.Value)
- For each descending class in base hierarchy
- Defer if class is unresolved.
- Let r = GetQNameInNsSetOrAnyPublicNs(class static properties, openNsSet, qual, localName)
- If r != undefined
- Mark r as used.
- Let r = r.ResolveAlias()
- Defer if r property's static type is unresolved.
- Return r.Wrap()
- Return undefined
- If localName is undefined or (qual is specified and qual is not a namespace nor a NamespaceConstant)
- If base is an interface
- Return undefined
- If base is a value
- Let baseType = static type of base or defer
- If baseType is invalid
- Return invalid
- baseType = baseType.ResolveAlias()
- If (followedByCall == false and forceFixture == false) and baseType defines an instance method
shock_proxy::get
(possibly a multi method)- Let foundRegularProperty = false
- For each
shock_proxy::get(k:K):V
method- If qual != undefined
- If K ==
*
or K == (Object
or defer) or K == (QName
or defer) or K ?union contains (QName
or defer)- Return KeyValuePairReferenceValue(base, proxy method, qual as a
Namespace
object, key.Value coerced to (String
or defer))
- Return KeyValuePairReferenceValue(base, proxy method, qual as a
- Continue loop
- If K ==
- If key.Value is a (
String
or defer) value and (K == (QName
or defer) or (K ?union does not containString
and K union containsQName
))- Return KeyValuePairReferenceValue(base, proxy method, undefined, key.Value)
- If K ==
*
or K == (Object
or defer) or K == (String
or defer) or K == (QName
or defer) or (K ?union containsString
or K union containsQName
)- foundRegularProperty = true
- If (static type of key.Value or defer) fails on implicit coercion to K
- Continue loop
- Return KeyValuePairReferenceValue(base, proxy method, undefined, key.Value implicitly coerced to K)
- If qual != undefined
- If (static type of key.Value or defer) != (
String
or defer) or foundRegularProperty- Throw a verify error
- Let hasKnownNs = qual == undefined or (qual is a namespace or NamespaceConstant)
- If localName == undefined
- If doubleKey != undefined and baseType is a tuple
- Let i = doubleKey coercion to integer
- If i < 0 or i >= baseType.ElementTypes.Length
- Throw a verify error
- Return TupleReferenceValue(base, i)
- Return DynamicReferenceValue(base, qual, key.Value, followedByCall, forceFixture)
- If doubleKey != undefined and baseType is a tuple
- If baseType ==
*
- Return DynamicReferenceValue(base, qual, key.Value, followedByCall, forceFixture)
- If baseType is a class
- For each descending class in baseType hierarchy
- Defer if class is unresolved
- Let prop = GetQNameInNsSetOrAnyPublicNs(class prototype properties, openNsSet, qual, localName)
- If prop != undefined
- Mark prop as used
- prop = prop.ResolveAlias()
- Call prop.Defer() (if about to defer, implementation may report the cause as unresolved expression in a location)
- If prop is a namespace or NamespaceConstant
- Return NamespaceConstant(prop) if prop is a namespace, or otherwise prop as is
- Return InstanceReferenceValue(base, prop)
- For implemented interfaces of baseType
- Lookup method (step required for optional methods)
- For each descending class in baseType hierarchy
- Else if baseType is an interface
- For each descending itrfc in baseType hierarchy
- Defer if itrfc is unresolved
- Let prop = GetQNameInNsSetOrAnyPublicNs(itrfc prototype properties, openNsSet, qual, localName)
- If prop != undefined
- Mark prop as used
- prop = prop.ResolveAlias()
- Call prop.Defer() (if about to defer, implementation may report the cause as unresolved expression in a location)
- Return InstanceReferenceValue(base, prop)
- Lookup for the
Object
instance definitions
- For each descending itrfc in baseType hierarchy
- Return undefined.
- If base is a
package
- If localName is undefined or (qual is specified and qual is not a namespace nor a NamespaceConstant)
- Throw a verify error
- Let r = undefined
- Let prop = GetQNameInNsSetOrAnyPublicNs(base properties, openNsSet, qual, localName)
- If prop != undefined
- Mark r as used.
- prop = prop.ResolveAlias()
- Call prop.Defer() (if about to defer, implementation may report the cause as unresolved expression in a location)
- r = prop.Wrap()
- Return r
- If localName is undefined or (qual is specified and qual is not a namespace nor a NamespaceConstant)
- If base is a type parameter with an
eventOf=, match="type"
constraint- If localName is undefined or (qual is specified)
- Return undefined.
- If localName = name
- Return EventNameType(type parameter).Wrap()
- If localName = type
- Return EventTypeType(previously introduced EventNameType).Wrap().
- Return undefined.
- If localName is undefined or (qual is specified)
- Return undefined.
Note: entity.Wrap() wraps entities into values. For instance, wrapping a variable into a property reference, where it belongs to a package, will produce a PackageReferenceValue.
Note: entity.Defer() defers if an entity is unresolved or if a direct compound is unresolved.
InScopeLookup()
InScopeLookup(scope, qual, key as LookupKey, followedByCall as Boolean
, forceFixture as Boolean
) takes the following steps in order:
Note: Content lacking.