The error returned when an expression cannot be prepared or its run is cut short.
A semantic error in a running expression is not an Feel.Error: in the default
lenient mode it makes a result null and is reported as a Feel.Diagnostic.
A Feel.Error is returned for:
:syntax- the source could not be parsed, or, in S-FEEL, is not in its grammar (the code is:outside_s_feel, D-49).:analysis- the source parsed, but calls or types could not be resolved, or it has a construct that is not written yet (the code is:not_implemented). A name that the scope does not have is an error only withunknown_names: :error; by default it is a warning (D-37). This happens atFeel.prepare/2, never later.:strict- a run in:strictmode hit its first error and halted. The result of such a run isnullby definition.:limit- a resource limit ofFeel.Limitswas exceeded: the size of the source or of a value, the nesting, the depth of calls, the number of diagnostics (D-154), the facts that the conditions compose about one subject (:too_many_facts), or the statements of code that the BEAM backend would make of the expression (:too_large_to_compile, D-154); the last two are found when the expression is prepared. The library usesFeel.Workerfor default deadlines and process containment.:input- invalid sandbox options/backend, an argument error inside a worker, or a value that was bound to a name breaks the declaration of the scope: the name is declaredT!(notnull, D-48) and has no value, ornull. The run does not start, in either mode, since an expression that was typed on the declaration could not be relied on. It is the caller's mistake and not the expression's.:worker- a sandbox worker crashed or was killed before completing its result.:backend- a backend could not turn a prepared expression into something that runs: the code the BEAM backend generated did not compile or load (D-38). It is not a mistake in the expression, andFeel.prepare/2returns it.
The functions that end in ! raise this exception instead of returning it.
Summary
Functions
Builds an error from the diagnostics that caused it.
Types
@type kind() :: :syntax | :analysis | :strict | :limit | :input | :backend | :worker
@type t() :: %Feel.Error{ __exception__: term(), code: atom(), diagnostics: [Feel.Diagnostic.t()], kind: kind(), message: String.t(), span: Feel.Diagnostic.span() | nil }
Functions
@spec from_diagnostics(kind(), [Feel.Diagnostic.t(), ...]) :: t()
Builds an error from the diagnostics that caused it.
The error takes its :code, :message, and :span from the first diagnostic,
and keeps all of them in :diagnostics.
iex> diagnostic = Feel.Diagnostic.new(:unknown_name, ~s(unknown name "x"), span: {0, 1})
iex> error = Feel.Error.from_diagnostics(:analysis, [diagnostic])
iex> {error.kind, error.code, Exception.message(error)}
{:analysis, :unknown_name, ~s(unknown name "x")}