Feel.Analysis.Callees (feel v0.1.0)

Copy Markdown View Source

The functions a callee can be, read from the node of the callee (D-193).

A call of a function that is written in the expression, called at once or through the key of a context, is typed from its arguments (D-193): the analyzer finds the function by what is written (a function literal, a name that is bound to one, a call that gives one). The type of a function says no more than its arrows, and a part of a type holds the kinds whole (D-152), so where the function reaches the call through a path, an element of a list or an if, the type of the callee has lost which function it is. The node has not: the callee is the node of a context literal that is selected from, a list literal that is indexed, or a conditional, and what it can be is read from the structure of it. This is alternatives/2:

  • a function literal is a function that was written there ({:function, meta, ...} with the closure the analyzer gave it, which is where it finds the place the literal was written in);
  • a built-in function by its name;
  • a complete recursion link, whose single-signature FEEL value is constructed by Feel.Recursion. This evidence is separate from ordinary arrow types and can travel through aliases and containers;
  • an if is the alternatives of its two branches (a branch that cannot be taken, whose nodes have no value, is none);
  • list[index] of a list literal, one of its items;
  • context.key of a context literal, the entry;
  • a name whose value is one of these (a key of a context, a parameter that a call gives such an argument, the iterator of a for over a list of them), which has the alternatives in its metadata (callees);
  • a key or an item of a name that is bound to a context or a list: the binding keeps the structure of the value (D-193), and the shape of each entry and each item has the alternatives that its node said (callees), so that fs[1] and c.g read them from the name, and so does a chain of these four deep (c.d.g, fs[1].g).

Anything else (an ordinary name of the scope, a call without callee evidence, a filter by a condition) is not read, and the callee is typed by its type. So are more alternatives than the cap. In linked preparation, compact completeness evidence can instead retain the written result bound beyond discovery limits. It is kept separately from closure identities: syntax and retained shapes are read first, including for list iterators and forwarded container arguments. If the analyzer cannot specialize a discovered closure within its depth or source budget, the marked complete signature is still available through complete_alternatives/1, without further body analysis. Descendant selection also retains completeness when its source establishes that every contained function is complete; a partial host declaration alone does not establish this property.

Summary

Types

A function a callee can be: a literal closure, a built-in by name, or a value satisfying this type whose contained function values are complete single-signature FEEL closures. The latter property can also describe containers of peers; it is established from linked values and syntax, never from an ordinary arrow declaration.

Functions

The functions the node can be, if all of them are read from it, and at most cap of them; :error if some is not.

The functions the elements of a list can be, if all of them are read, and at most cap of them; :error if some is not (D-193). The list is a list literal, or a name or a key or an item of one that is bound to a list whose items are read. This is what an iterator of a for, some or every over it is.

Types

alternative()

@type alternative() ::
  {:closure, non_neg_integer()}
  | {:builtin, Feel.Name.t()}
  | {:complete, Feel.Type.Union.t()}

A function a callee can be: a literal closure, a built-in by name, or a value satisfying this type whose contained function values are complete single-signature FEEL closures. The latter property can also describe containers of peers; it is established from linked values and syntax, never from an ordinary arrow declaration.

Functions

alternatives(callee, cap)

@spec alternatives(Feel.IR.t(), pos_integer()) :: {:ok, [alternative(), ...]} | :error

The functions the node can be, if all of them are read from it, and at most cap of them; :error if some is not.

elements(list, cap)

@spec elements(Feel.IR.t(), pos_integer()) :: {:ok, [alternative(), ...]} | :error

The functions the elements of a list can be, if all of them are read, and at most cap of them; :error if some is not (D-193). The list is a list literal, or a name or a key or an item of one that is bound to a list whose items are read. This is what an iterator of a for, some or every over it is.