The itemplate structure serves as a specification that determines how predicate definitions and calls to predicates are instrumented.
An itemplate is associated with a predicate whose definition or invocations are to be instrumented. This association is specified as an argument to instrument:instrument/2 or instrument:instrument/3 and is of the form: PredSpec = itemplate with [...].
PredSpec is of the form Module:Functor/Arity. If the module qualifier is omitted, then PredSpec is assumed to be a predicate defined within the calling module context in which instrument/2 was invoked. The definition context for a module can be wildcarded by specifying the module qualifier as the atom every_module or by setting the itemplate module_scope field to every_module.
This has two effects:
When determining whether a predicate is to be instrumented, a template is sought which matches the module qualified PredSpec, first using the named module (or current module if unqualified) and then using every_module as the module qualifier.
Within the template, predicate specifications supplied to its fields determine how predicate instrumentation and invocation proceeds. The template specifies the following instrumentation points:
clause_start
clause_end
clause_fail
clause_redo
block_start
block_end
block_fail
block_redo
subgoal_start
subgoal_end
subgoal_fail
subgoal_redo
call_start
call_end
call_fail
call_redo
fact
inbetween
The default value for the instrumentation predicates is that none are defined and so no instrumentation is performed. This is equivalent to setting the field values explicitly to free variables.
The instrumentation predicates must be defined with one of the following signatures:
It is anticipated that the callsite identifier be used for executing callsite specific code or storing data pertinent to the callsite in a non-logical store keyed by callsite identifier - set_callsite_data/2 and get_callsite_data/2 are provided for exactly this purpose.
The auxiliary variable passed as argument two to instrumentation predicates is provided for convenience for capturing 'delta' measurements between the start, end and fail instrumentation points. The variable is a logical variable and while the value passed to the end or fail predicate is guaranteed to be the value bound by the start predicate, backtracking past the start predicate results in the unbinding of the variable. If the captured delta should be retained beyond backtracking then it should be placed in the callsite's non-logical store using set_callsite_data/2.
The maximum arity of the fact and inbetween point predicates is one - only the callsite identifier is passed, there is no benefit in passing an auxiliary variable.
The result instrumentation predicate provides a mechanism for pretty-printing the annotated source code with the instrumentation results gathered during execution. By executing instrument:module_result/0 or instrument:file_result/1 the predicate specified for result instrumentation within the template is invoked as each of the instrumentation points are encountered for pretty-printing.
The result instrumentation predicate must be defined with one of the following signatures:
The meta_args field of the itemplate structure is applicable only to templates associated with predicates that are meta-predicates. When applicable, meta_args is a list of itemplate. Each element in the list is a template for the corresponding argument of the meta-predicate. The template defined instrumentation points are applied to the code found inside the meta-predicate at this argument position. For example:
findall/3 = itemplate with [..., meta_args:[_, ITemplateArg2, _]...]is an itemplate specification describing the instrumentation of the meta-predicate findall/3. Argument one and three undergo no instrumentation (denoted by free variables) and argument two is instrumented according to ITemplateArg2.
Within the meta-predicate argument itemplate fields may be specified as being inherit-ed. When such a field is specified as inherited it is set to the corresponding value of the template used in instrumenting the definition of the predicate in which the call to the meta-predicate resides.
The exclude field of the itemplate contains a list of predicate specifications. Any occurrence of such a predicate as a call or subgoal is excluded from application of the instrumentation specified by the enclosing template. The main use of exclusion is in preventing instrumentation application to recursive predicates or built-ins.
The code_weaver field of the itemplate specifies a predicate of arity six that is a compile-time callback allowing arbitrary user code to be woven into the code currently undergoing compilation. The weaving of user code is performed before the insertion of instrumentation predicates. The arguments of the predicate are as follows:
The remaining fields of the itemplate structure specify the options:
The value of asserted may be the atoms: on, off and post_compile or a free variable. When a free variable, the instrumentation predicates are compiled into the code like any other predicates. However, when set to one of the atomic values, the predicates are compiled such that they can be inserted and removed at runtime. This is done efficiently such that there is negligible overhead on execution.
The value on specifies that the predicates are initially inserted. The value off that they are removed and post_compile that they are not inserted until compilation of the whole file has completed. The post_compile option is provided so that instrumentation predicates inserted into predicate definitions that get executed at compile-time do not get executed.
During execution, the instrumentation predicates can be inserted and removed using instrument:instrument_control/2.
The possible values are an atom representing a module name, the atom every_module or a free variable indicating the current module. The value is used to determine the module definition context of unqualified instrumentation predicates or the predicate associated with the template for definition and call instrumentation:
The unqualified predicate is qualified with the named module.
The unqualified predicate is qualified with the calling module context in which instrument/2 was first invoked.
The unqualified predicate is qualified with the name of the current compilation module.
Templates persist in a global store between successive calls to instrument/2 and instrument/3. If it is undesirable for a template to be added to the global store (thus making it available for the instrumentation of other files and modules) an itemplate may be declared as being applicable to only the file currently being instrumented by setting this option to on.
The search order for an instrumentation template is first in the file local store and then in the global store.
Setting this to off will suppress goal expansion inlining) during compilation. This may be necessary when the processed code contains predicates that get executed at compile time.