The type of e.name from the type of e (D-65).
select/3 is the static counterpart of Feel.Runtime.Path.select/2: it takes the union that is the
type of the source and the key, and gives the union that the selection can be and whether the run can
report an error for it. A test checks the two against each other on many values.
The union of the source is taken one alternative at a time, and the result is the union of what each gives:
| The alternative | The selection | An error |
|---|---|---|
context<..., key: T, ...> | T, whatever T is: a context type lists entries that are there (D-23) | never |
| an open context without the key | Any | Null (a context type allows more entries than it lists) | maybe |
| a closed context without the key | Null: it has the entries it lists and no others | always |
list<E> | list<S>, where S is the union of the selections from the alternatives of E, and Null for what has no such entry | never |
| a date, a time, ... | the type of the property, with the range of its values (Table 67): month is number in [1..12] | never, or always for a name the kind has not |
range<E> | E | Null for start and end, boolean for the flags | never |
Null | Null | always |
Any, a named type | Any | Null | maybe |
| anything else | Null | always |
A union with an alternative that errors and one that does not is a maybe; the analyzer warns only
about always. A component of the other kind of duration (duration("P1Y").days) is an error, as the
TCK flags it, though Table 67 says null; time offset and timezone of a value that has none are null
and no error.
A context type of the specification is open (Feel.Type.Conformance), and a declared type is one. The type of a
context literal, and of a constant, is closed ({:closed_context, entries}, D-65): it has the entries it lists
and no others, so the selection of an entry it does not list is Null for sure.
Normalization retains nested exclusions. A path reader requests a positive upper approximation of each union it inspects: the source, list elements, and context entries traversed for descendants. An excluded context is therefore not mistaken for a value with no properties. This approximation is local to reading; selecting an entry returns its declared union, including exclusions, unchanged.
The descendant
descend/2 is the type of e...name (D-65). The result is a list, and what is in it is known as far as the
source is: a closed context is walked as the run walks a value, so {a: {b: n}}...b is list<number | Null>
and {a: 1}...b is list<Null> (the list of nothing, Table 43). An open context may have entries that its type does not list,
nested as deep as it likes, so what is in the list is Any | Null. The contexts in a list are not looked into
(Feel.Runtime.Path), so a type that is a list is not either. A source that is Null or not a context is an error.
The value property of a date and a time is a number. That of a date and time is number | Null and a maybe:
it is null with an error for one with no zone, which the type does not tell (D-68).
iex> context = [{:context, %{"age" => [:number, :null]}}]
iex> Feel.Analysis.Paths.select(context, "age")
{:ok, [:number, :null], :never}
iex> {:ok, type, :never} = Feel.Analysis.Paths.select([:date], "month")
iex> Feel.Type.Union.format(type)
"number in [1..12]"
iex> Feel.Analysis.Paths.select([{:context, %{}}], "age")
{:ok, [:any, :null], :maybe}
iex> Feel.Analysis.Paths.select([{:closed_context, %{}}], "age")
{:ok, [:null], :always}
Summary
Functions
The type of the descendants of key in a value of type source, and whether it can be an error.
The type of the selection of key from a value of type source, and whether it can be an error.
Types
Functions
@spec descend(Feel.Type.Union.t(), Feel.Name.t()) :: {:ok, Feel.Type.Union.t(), errors()}
The type of the descendants of key in a value of type source, and whether it can be an error.
iex> Feel.Analysis.Paths.descend([{:closed_context, %{"a" => [:number]}}], "b")
{:ok, [{:list, [:null]}], :never}
iex> {:ok, type, :never} = Feel.Analysis.Paths.descend([{:closed_context, %{"a" => [{:closed_context, %{"b" => [:number]}}]}}], "b")
iex> Feel.Type.Union.format(type)
"list<number>"
iex> Feel.Analysis.Paths.descend([{:context, %{"b" => [:number]}}], "b")
{:ok, [{:list, [:any, :null]}], :never}
@spec select(Feel.Type.Union.t(), Feel.Name.t()) :: {:ok, Feel.Type.Union.t(), errors()}
The type of the selection of key from a value of type source, and whether it can be an error.