Directives¶
Directives are module-level declarations in .clausal files that control predicate properties, imports, and compilation behavior. They are prefixed with - and placed at the top of the file.
Module Declaration¶
Declares the module name and its public exports. The export list specifies which predicates are accessible to importers. If omitted, the module name is derived from the filename.
-private¶
Declares predicates that are internal to the module. Private predicates get proper PredicateMeta classes but are not exposed for import.
Import Directives¶
-import_from¶
Import specific predicates from another module:
With aliasing:
This imports Double from utils but makes it available locally as MyDouble.
-import_module¶
Import all exported predicates from a module:
Imported predicates are accessed via qualified names: utils.Double(X, Y).
See Import System for full details.
Predicate Property Directives¶
-dynamic¶
Marks a predicate as dynamic — its clauses can be modified at runtime via Assert/1, AssertFirst/1, and Retract/1. Without this directive, predicates are locked after module loading and assertion attempts raise an error.
-table¶
Enables SLG tabling (memoization) for a predicate. Tabled predicates automatically cache answers and handle left-recursive definitions that would otherwise loop. Required for well-founded semantics with negation.
See Tabling for details.
-discontiguous¶
Allows clauses for a predicate to be scattered throughout the file rather than grouped together. Without this, the compiler assumes all clauses for a predicate are contiguous and may warn or error.
-meta_predicate¶
Declares the meta-predicate calling convention. Used by the module system for correct import handling of higher-order predicates.
-shallow¶
Compiles a predicate in simple (non-trampoline) mode. This avoids the overhead of the trampoline protocol for predicates known to have bounded recursion depth. The default is trampoline mode for stack safety.
Specialization Directive¶
-specialize¶
Specializes a meta-interpreter with respect to an object program, producing a new predicate with interpretation overhead removed. The MI pattern is auto-detected from the clause structure.
Options:
# skip
-specialize(MI, Source, alias=Name, depth=5) # deep unfolding
-specialize(MI, Source, alias=Name, cpd=True) # conjunctive partial deduction
See Meta-Interpreter Specialization for full details.
EDCG Directives¶
Experimental
EDCG directives are parsed but end-to-end rewriting is not yet implemented.
Extended DCGs allow multiple named accumulators and passed arguments to be threaded through grammar rules automatically.
-edcg_acc¶
Declares a named accumulator with its joining operation. Arguments: name, value variable, input state, output state, and joiner goal.
-edcg_pass¶
Declares a passed argument — a value that threads through EDCG nonterminals without modification (read-only).
-edcg_pred¶
Declares how many visible arguments a predicate has and which accumulators/passed arguments it uses.
Directive Processing¶
Directives are processed during module loading:
- The term transformer parses
-directive(...)syntax into directive AST nodes - The compiler (v2 pipeline) processes directives before clause compilation via
_process_directives - Property directives set metadata flags on the predicate's
PredicateMetaclass - Import directives trigger module loading and predicate injection
Directives apply to the entire module — they cannot be scoped to individual clauses.
Test coverage
Tests are in tests/test_directives.py (21 tests).
- Dynamic: predicate metadata, runtime assert/retract, locking of non-dynamic predicates
- Discontiguous: scattered clause collection
- Table: tabling metadata, SLG resolution
- Parsing: directive syntax recognition, arity extraction
- Import-level locking: predicates locked after load, dynamic predicates remain mutable