Feel.Extensions (feel v0.1.0)

Copy Markdown View Source

The extensions that are on for an expression, resolved (D-81).

Feel.prepare/2 turns its :extensions option into this once, and every stage that has to decide something asks it: the parser which words are a function name, the analyzer which functions there are and which signatures they have, and a run which function to call. It is part of the prepared expression and of its executable, and a run cannot change it, as with the dialect (D-49).

new/1 checks what is given:

It raises ArgumentError otherwise: a wrong extension is a mistake of the caller, found when the expression is prepared and not when it runs.

The signatures of everything an extension adds carry extension: true. The analyzer reads it to mark a call that an extension may answer in its metadata (Feel.IR): the analyzer and the optimizer fold such a call with the extensions of the expression, and Feel.Analysis.Analyzer does not fold it as one of DMN 1.6, which it would take for an error (D-45).

iex> Feel.Extensions.none() == Feel.Extensions.new([])
true

Summary

Functions

Returns true when every extension in the set says it adds data only (Feel.Extension.data_only?/0); so does an empty set. For a resolved set this reads what new/1 recorded and runs no extension code, so a host may ask it where nothing of the extension may run (a caller that has not started its worker yet). For a list of names and modules, as new/1 takes it, the callbacks are called here, so ask where new/1 could be called; something that is no extension is not data only.

Finds a function that an extension adds, by its name. A function of DMN 1.6 is never found here: its overloads are overloads/2.

Returns true when an extension adds a function of this name.

The names of the functions that the extensions add, which the parser needs to read a name of several words as one.

Reads the text of a time or a date and time as an extension spells it (Feel.Extension.temporal_text/1): the first other spelling of text, in the order of the extensions, that parse reads. Returns the value and the text that was read, and :error if no extension has a spelling that parse reads.

The extensions, as modules, in the order they were given.

Resolves a list of extension names and modules. An already resolved set is returned as it is, so every function that takes the option can be given either.

No extension: DMN 1.6 and nothing else.

Returns true when no extension is on.

The overloads that the extensions add to the function of DMN 1.6 of this name, in the order of the extensions.

The :info for a text that was read as another spelling (D-81), with the code :temporal_spelling. Its span is the one of the operation that read it.

Returns true when the function reads a text that an extension that is on may spell another way (D-81): a call of it may give a value where DMN 1.6 gives null, so the analyzer marks the call (Feel.IR, meta.extension) and folds it with the extensions, and not as a call of DMN 1.6 (D-45). range is one: the endpoints of its text are such texts.

Types

t()

@type t() :: %Feel.Extensions{
  data_only: boolean(),
  functions: %{optional(Feel.Name.t()) => Feel.Builtin.Function.t()},
  modules: [module()],
  overloads: %{optional(Feel.Name.t()) => [Feel.Builtin.Function.t()]},
  temporal: [module()]
}

Functions

data_only?(extensions)

@spec data_only?(t() | [atom()]) :: boolean()

Returns true when every extension in the set says it adds data only (Feel.Extension.data_only?/0); so does an empty set. For a resolved set this reads what new/1 recorded and runs no extension code, so a host may ask it where nothing of the extension may run (a caller that has not started its worker yet). For a list of names and modules, as new/1 takes it, the callbacks are called here, so ask where new/1 could be called; something that is no extension is not data only.

function(extensions, name)

@spec function(t(), Feel.Name.t()) :: {:ok, Feel.Builtin.Function.t()} | :error

Finds a function that an extension adds, by its name. A function of DMN 1.6 is never found here: its overloads are overloads/2.

function?(extensions, name)

@spec function?(t(), Feel.Name.t()) :: boolean()

Returns true when an extension adds a function of this name.

function_names(extensions)

@spec function_names(t()) :: [Feel.Name.t()]

The names of the functions that the extensions add, which the parser needs to read a name of several words as one.

lenient_temporal(extensions, text, parse)

@spec lenient_temporal(t(), String.t(), Feel.Value.Temporal.Spellings.parser()) ::
  {:ok, Feel.Value.Temporal.t(), String.t()} | :error

Reads the text of a time or a date and time as an extension spells it (Feel.Extension.temporal_text/1): the first other spelling of text, in the order of the extensions, that parse reads. Returns the value and the text that was read, and :error if no extension has a spelling that parse reads.

The caller has tried parse on text, and says what it read with spelling_diagnostic/2.

modules(extensions)

@spec modules(t()) :: [module()]

The extensions, as modules, in the order they were given.

new(extensions)

@spec new(t() | [atom()]) :: t()

Resolves a list of extension names and modules. An already resolved set is returned as it is, so every function that takes the option can be given either.

none()

@spec none() :: t()

No extension: DMN 1.6 and nothing else.

none?(extensions)

@spec none?(t()) :: boolean()

Returns true when no extension is on.

overloads(extensions, name)

@spec overloads(t(), Feel.Name.t()) :: [Feel.Builtin.Function.t()]

The overloads that the extensions add to the function of DMN 1.6 of this name, in the order of the extensions.

spelling_diagnostic(text, candidate)

@spec spelling_diagnostic(String.t(), String.t()) :: Feel.Diagnostic.t()

The :info for a text that was read as another spelling (D-81), with the code :temporal_spelling. Its span is the one of the operation that read it.

spells?(extensions, name)

@spec spells?(t(), Feel.Name.t()) :: boolean()

Returns true when the function reads a text that an extension that is on may spell another way (D-81): a call of it may give a value where DMN 1.6 gives null, so the analyzer marks the call (Feel.IR, meta.extension) and folds it with the extensions, and not as a call of DMN 1.6 (D-45). range is one: the endpoints of its text are such texts.