Problem
pslua honours only binary @inline always / @inline never on a binding. The abstraction-elimination story (lenses, variants, generics) wants a richer directive DSL bound to a fully-qualified name plus an optional accessor:
[export] qualified-ident accessor? mode
accessor ::= "" -- the value itself
| ".label" -- a field of a dictionary record
| "...label" -- a field after application: f(x).member
mode ::= default | never | always | arity=N (N > 0)
arity=N inlines only when applied to at least N arguments, so a tiny curried combinator inlines at saturated sites but stays a reference otherwise; the accessor forms target one dictionary method rather than the whole record; and a --directives file.txt supplies these globally, above the built-in heuristics. Without graduated directives pslua cannot start the inlining cascade that eliminates a user-defined abstraction: a fusion pragma like @inline export overArray arity=1 never gets off the ground.
Worth stating up front: #180 already auto-specializes the non-Effect/ST monads with no directives needed, so the marginal value here is lens/variant/generics elimination and user tuning, not monad collapse.
Approach
Extend the pragma parser in IR/Inliner.hs to accept arity=N and the .label / ...label accessor forms, and add a --directives <file> input layering the sources by specificity: a local module-header directive beats the project directives file, which beats export-transitive directives, which beat the built-in defaults. At the call site an arity=N directive gates inlining on the saturation count already computed for the uncurry pass; the accessor forms attach the policy to a projection out of a known dictionary rather than to the binding as a whole.
Prerequisites / Relations
Independent to land; sharper together with the Complexity/Capture lattice, since default mode falls back to those heuristics. Enables two follow-ups tracked separately: #241 (auto-inferred directives on synthetic specializations) and #242 (a shipped default-directive pack for the prelude/core forks).
Verification / Measurement
A curried combinator marked arity=2 inlines at a saturated two-argument site and stays a reference at a partial one. A focused test covers both. A directives file overrides an exported directive for the same name, and a local module-header directive beats the file (precedence tests). An end-to-end golden where a user abstraction marked arity=1 collapses through the existing beta / case-of-known-constructor cascade.
Problem
pslua honours only binary
@inline always/@inline neveron a binding. The abstraction-elimination story (lenses, variants, generics) wants a richer directive DSL bound to a fully-qualified name plus an optional accessor:arity=Ninlines only when applied to at least N arguments, so a tiny curried combinator inlines at saturated sites but stays a reference otherwise; the accessor forms target one dictionary method rather than the whole record; and a--directives file.txtsupplies these globally, above the built-in heuristics. Without graduated directives pslua cannot start the inlining cascade that eliminates a user-defined abstraction: a fusion pragma like@inline export overArray arity=1never gets off the ground.Worth stating up front: #180 already auto-specializes the non-Effect/ST monads with no directives needed, so the marginal value here is lens/variant/generics elimination and user tuning, not monad collapse.
Approach
Extend the pragma parser in
IR/Inliner.hsto acceptarity=Nand the.label/...labelaccessor forms, and add a--directives <file>input layering the sources by specificity: a local module-header directive beats the project directives file, which beatsexport-transitive directives, which beat the built-in defaults. At the call site anarity=Ndirective gates inlining on the saturation count already computed for the uncurry pass; the accessor forms attach the policy to a projection out of a known dictionary rather than to the binding as a whole.Prerequisites / Relations
Independent to land; sharper together with the Complexity/Capture lattice, since
defaultmode falls back to those heuristics. Enables two follow-ups tracked separately: #241 (auto-inferred directives on synthetic specializations) and #242 (a shipped default-directive pack for the prelude/core forks).Verification / Measurement
A curried combinator marked
arity=2inlines at a saturated two-argument site and stays a reference at a partial one. A focused test covers both. A directives file overrides an exported directive for the same name, and a local module-header directive beats the file (precedence tests). An end-to-end golden where a user abstraction markedarity=1collapses through the existing beta / case-of-known-constructor cascade.