curry.icurry.analysis package
- class curry.icurry.analysis.CaseBody(body, params, locals, frees, scrutinee, branches)[source]
Bases:
objectA body that is one case on a parameter: the parameters it binds, the locals before the case, its free variables, the variable and the parameter index of the scrutinee, and the branches by the full name of their constructor.
sizeis the largest branch.
- class curry.icurry.analysis.ExpressionBody(body, params, locals, frees, result)[source]
Bases:
objectA body that returns an expression: the parameters it binds (variable to parameter index), the locals it binds, in order (variable and expression), its free variables, and the result.
sizecounts the nodes it builds,usesthe occurrences of each variable.
- class curry.icurry.analysis.Inliner(modules, budget, depth=MAX_DEPTH)[source]
Bases:
objectRewrites the body of one function at a time, in place: every saturated call of a known function is replaced by its body under the rules of this module, and every apply whose head is known is saturated (partials.saturate), to a fixpoint bounded by
depth.budgetis the largest expression body inlined, in nodes built; 0 turns both rules off.symbolscollects the symbol names that the copied bodies name, so the caller can join the imports of the module.- bind(sigma, vids, expr, uses, pending, depth, rewrite=False)[source]
Maps the variables
vidsof the body, which name one argument, toexprunder the sharing rule: a variable, a literal, or a static string as it is; an expression used once as it is; one used more through a fresh variable of the caller’s block, so that it is built once; one not used is dropped.usescounts the occurrences of all the variables together. A local that gets a variable is rewritten first (rewrite); an argument was rewritten already.
- expr(expr, pending, depth)[source]
Rewrites
exprfrom the inside out. The result of a rule is rewritten again, one level deeper, until no rule applies or the depth is reached. The walk over the arguments runs on the trampoline; the rewrite of a result (rules) runs a walk of its own, at mostdepthdeep.
- instantiate_case(shape, branch, args, pending, depth)[source]
The branch
branchof the single-case bodyshapeon the argumentsargs, whose scrutinee is a constructor of the branch.
- curry.icurry.analysis.alias_target(ifun)[source]
The full name of the function that
ifunis an alias of, or None. The answer comes from the metadata when it is there (a module loaded from its compiled form), else from the body.
- curry.icurry.analysis.alias_target_of_body(ifun)[source]
The full name of the function that
ifunis an alias of, read from its body, or None. A function without a Curry body (built-in, external, or loaded from its compiled form) is never an alias by this test.
- curry.icurry.analysis.body_shape(body, arity)[source]
The ExpressionBody or CaseBody of the IFuncBody
bodyof a function ofarityparameters, or None when the body has another shape: no block (a built-in, an external, or a function loaded from its compiled form), a recursive let, a case whose branches all have a case or an exempt, a variable the body does not bind, or a path the inliner does not follow.
- curry.icurry.analysis.find_static_strings(iobj)[source]
A static string is a sequence of ICCall nodes constructing a list of characters.
- curry.icurry.analysis.inline_body_text(body)[source]
The ICurry-JSON text of a function body, for the metadata.
- curry.icurry.analysis.inline_shape(ifun)[source]
The shape of the body that a call of
ifunis replaced by, or None. The shape is built once per function, over a copy of the body as it is when first asked for (before the pass rewrites the function), or over the body the metadata records (INLINE_KEY: a module loaded from its compiled form has no bodies). A text that does not read back makes the function unknown; it does not stop the import.
- curry.icurry.analysis.is_apply(expr, modules)[source]
Tells whether
expris a saturated call ofapply: an IFCall with two arguments of Prelude.apply, or of Prelude.$ while the loaded Prelude defines it as an alias of apply (resolve_alias).modulesmaps 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.is_recursive(ifun, modules)[source]
Whether
ifunlies on a cycle of the call graph of its module. A function whose module is not amongmodulescounts as recursive: the inliner leaves it alone.
- curry.icurry.analysis.lookup_constructor(symbolname, modules)[source]
Finds the IConstructor named by the full name
symbolnameamong 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.lookup_function(symbolname, modules)[source]
Finds the IFunction named by the full name
symbolnameamong the loaded modules.modulesmaps module names to Curry modules and packages, as Interpreter.modules does. Returns None when the module is not loaded or has no such function.
- curry.icurry.analysis.lookup_module(modulename, modules)[source]
Finds the IModule named
modulenameamong the loaded modules, as lookup_function finds a function, or None.
- curry.icurry.analysis.lookup_symbol(symbolname, modules)[source]
The IFunction or IConstructor named by
symbolname, or None.
- curry.icurry.analysis.node_count(expr)[source]
The nodes that
exprbuilds: a call, a partial application, a constructor, a choice, or a literal is one node plus its arguments; a variable is a reference and counts nothing.
- curry.icurry.analysis.nullary_body(ifun)[source]
The expression that the nullary function
ifunreturns, 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.partial_head(expr, modules, depth=MAX_UNFOLDING_DEPTH)[source]
The partial application that the head expression
exprdenotes, as a fresh IFPCall or ICPCall, or None when the head is not known.expris known when it is a partial application; an IFCall without arguments of a nullary function that unfolds to one (unfolding); or anapplywhose head is known and whose call is a partial application (saturate), through at mostdepthnullary functions and applies.modulesmaps 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.recordable(ifun, modules)[source]
Whether the body of
ifunis one that a module records for its importers: it has a shape, it is not recursive, and it is within the limit (RECORD_LIMIT for an expression body, CASE_LIMIT for the largest branch of a single-case body).
- curry.icurry.analysis.recorded_functions(imodule, modules)[source]
The full names of the functions of
imodulewhose bodies the module records under INLINE_KEY, as a frozenset: every public function that is recordable, and every private function that a recorded body names, in a saturated call or in a partial application, so that an importer can follow the chain (the lambda behind.sits in a partial application of the body of.). Computed once per module and cached on it.
- curry.icurry.analysis.recursive_functions(imodule)[source]
The full names of the functions of
imodulethat lie on a cycle of its call graph, as a frozenset: a function that calls itself, or two or more that call each other, through saturated calls (IFCall). A partial application is a value and makes no edge. Computed once per module, from the bodies as they are when first asked for, and cached on the module. A function without a body has no edges.
- curry.icurry.analysis.resolve_alias(symbolname, modules, nargs)[source]
Follows aliases from the function named
symbolname, called withnargsarguments, to the function that does the work. Returns the full name of that function:symbolnameitself when it is not an alias, when its module is not loaded, or when the call is not saturated. A chain stops before a target that is not loaded or that has another arity. A chain that closes on itself (aliases of each other) leaves the call alone.
- curry.icurry.analysis.saturate(iapply, modules, depth=MAX_UNFOLDING_DEPTH)[source]
The call that the
applynodeiapplybuilds 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 anapply(ap = apply, thenap f x) is saturated again, to the bounddepth. The head is a fresh copy, so the call shares nothing with the body of a nullary function; the argument is the one ofiapply.
- curry.icurry.analysis.set_monadic_metadata(ifun, modules)[source]
Determines whether an ICurry function is monadic.
The result is stored in the ‘all.monadic’ metadata and also in ‘all.flags’ by OR-ing with F_MONADIC. This apparent redundancy is needed because ‘all.monadic’ is actually a tristate: True or False indicates the monadic check has been performed, while its absense indicates the check needs to be performed.
To determine whether a function is monadic, its call graph is walked. If the function calls any monadic function, then it is determined to be monadic.
- curry.icurry.analysis.unfolding(ifun, modules, depth=MAX_UNFOLDING_DEPTH)[source]
The partial application that the nullary function
ifununfolds 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 anapplychain (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.unfolding_text(partial)[source]
The ICurry-JSON text of a partial application, for the metadata.
Submodules
- curry.icurry.analysis.aliases module
- curry.icurry.analysis.inlining module
- curry.icurry.analysis.monadic module
- curry.icurry.analysis.partials module
- curry.icurry.analysis.strings module
- curry.icurry.analysis.variables module