curry.icurry.analysis.partials module

Finds the partial application that the head of an apply denotes.

A chain apply (apply h x) y costs a rewrite step and a node per apply. When the head is known, the optimizer builds the call directly; see curry.interpreter.optimize.saturate_applies. A head is known when it is a partial application (IFPCall, or ICPCall of a constructor), or a call without arguments of a nullary function whose body is one such partial application, followed through nullary functions to a bounded depth. The Prelude’s instance methods that fall back to a class default have that shape:

_impl#/=#Prelude.Eq#Prelude.Int =

_def#/=#Prelude.Eq _inst#Prelude.Eq#Prelude.Int

and so do userError (a partial application of UserError) and showChar. A head that is itself an apply of a known head is known too (the body of g = k 1 with k = f), so the answer does not depend on the order in which the optimizer reaches the functions. A variable head, and a call with arguments, are not known.

A call of Prelude.$, the Prelude’s alias of apply, is an apply here (is_apply): the optimizer runs before alias inlining. A user alias of apply (app f x = f x) is not: the source wrote the indirection, and the pass keeps it.

curry.icurry.analysis.partials.is_apply(expr, modules)[source]

Tells whether expr is a saturated call of apply: an IFCall with two arguments of Prelude.apply, or of Prelude.$ while the loaded Prelude defines it as an alias of apply (resolve_alias). modules maps module names to Curry modules and packages, as Interpreter.modules does.

A user alias of apply (app f x = f x) is not an apply here, though inline_aliases turns a call of it into one afterwards: the source wrote the indirection, and a program may need it to hand a known function value to the apply of the runtime, which the optimizer would otherwise fold away (a let of a bare function value does not survive the front end).

curry.icurry.analysis.partials.lookup_constructor(symbolname, modules)[source]

Finds the IConstructor named by the full name symbolname among the loaded modules, as lookup_function finds a function. Returns None when the module is not loaded or has no such constructor.

curry.icurry.analysis.partials.lookup_symbol(symbolname, modules)[source]

The IFunction or IConstructor named by symbolname, or None.

curry.icurry.analysis.partials.nullary_body(ifun)[source]

The expression that the nullary function ifun returns, when its body is one return statement without declarations, or None. A function with parameters, a local variable, a free variable, or a case is never unfolded. Neither is a function without a Curry body (built-in, external, or loaded from its compiled form).

curry.icurry.analysis.partials.partial_head(expr, modules, depth=MAX_UNFOLDING_DEPTH)[source]

The partial application that the head expression expr denotes, as a fresh IFPCall or ICPCall, or None when the head is not known.

expr is known when it is a partial application; an IFCall without arguments of a nullary function that unfolds to one (unfolding); or an apply whose head is known and whose call is a partial application (saturate), through at most depth nullary functions and applies. modules maps module names to Curry modules and packages, as Interpreter.modules does. The partial must agree with the symbol table: the function or constructor is loaded, and its arity is the number of arguments plus the missing count, which is at least one. So a call built from the answer has the arity of its symbol.

curry.icurry.analysis.partials.saturate(iapply, modules, depth=MAX_UNFOLDING_DEPTH)[source]

The call that the apply node iapply builds when its head is known (partial_head), or None. When the partial misses one argument, the call is the saturated call (IFCall, or ICCall of a constructor); when it misses more, the call is the longer partial application. A saturated call that is itself an apply (ap = apply, then ap f x) is saturated again, to the bound depth. The head is a fresh copy, so the call shares nothing with the body of a nullary function; the argument is the one of iapply.

curry.icurry.analysis.partials.unfolding(ifun, modules, depth=MAX_UNFOLDING_DEPTH)[source]

The partial application that the nullary function ifun unfolds to, as a fresh expression, or None. The answer comes from the metadata when it is there (a module loaded from its compiled form), else from the body, which may itself be a call of another nullary function or an apply chain (see partial_head). A text in the metadata that does not read back as a partial application makes the function unknown; it does not stop the import.

curry.icurry.analysis.partials.unfolding_text(partial)[source]

The ICurry-JSON text of a partial application, for the metadata.