
meta_attribute(+Name, ++Handlers)

   Declares the variable attribute Name with the corresponding handlers

Arguments
   Name                Atom
   Handlers            List or nil.

Type
   Term Manipulation

Description

   This predicate is used to declare a variable attribute and/or the
   corresponding handlers.  The Name is usually the name of module where
   this attribute is being defined and used.  The unqualified use of
   attributed variables, i.e.  terms in the form Var{Attr} is allowed only in
   modules which have a defined attribute name, otherwise the qualified
   usage Var{Name:Attr} is required.

   The Handlers argument specifies a list of handler predicates for several
   built-in operations which require user-defined actions whenever an
   attributed variable is encountered.  The list contains elements in the
   form Operation:Pred, where Operation is the predefined name of the
   built-in operation and Pred is the handler predicate specification.  The
   handler definition module is assumed to be the module in which
   meta_attribute/2 is being called; another module can be specified by
   using the tool body predicate meta_attribute_body/3.  When true/0 is
   specified as the handler or when no handler for a particular operation
   is specified, this operation will ignore this extension.  If the
   extension Name already exists, the specified handlers are updated, the
   non-specified ones remain.

   The call meta_attribute(Name, []) can be used as a preliminary
   declaration of a particular attribute, e.g.  to compile a module part
   before the actual declaration is called, or when processing separate
   files that belong to a particular module.

   The meta_attribute/2 predicate is sensitive to the flag debug_compile.
   If it is on, the calls to the local handlers will be traceable (and
   slower), if it is off, it will be the opposite.  All specified handlers
   will be exported from their definition module.

   The predefined operations and the corresponding handler arguments are
   the following:

unify

    Operation :   unification

    Handler :   handler(+Term, ?Attribute)

    Description :   The handler for the usual unification.  Term is the
        term that was unified with the attributed variable, it is
        either a nonvariable or an attributed variable.  Attribute is
        directly the contents of the attribute slot corresponding to
        the extension, i.e.  it is not the whole attributed variable.
        When this handler is invoked, the attributed variable is already 
        bound to Term.  


        If an attributed variable is unified with a standard variable, the
        variable is bound to the attributed variable and no handlers are
        invoked.  If an attributed variable is unified with another
        attributed variable or a non-variable, the attributed variable is
        bound (like a standard variable) to the other term and all handlers
        for the unify operation are invoked.  Note that several attributed
        variable bindings can occur e.g. during a head unification and also
        during a single unification of compound terms.  The handlers are
        only invoked at certain trigger points (usually before the next
        predicate call).



test_unify

    Operation :   unification test

    Handler :   handler(+Term, ?Attribute)

    Description :   The handler for the unification which is not
        supposed to trigger constraints propagation.  It is used e.g.
        in the not_unify/2 predicate.  The handler arguments are
        equivalent to those of the unification handler, Term is the
        term that was unified with the attributed variable, Attribute
        is the attribute of this extension.  During the execution of
        the handler the attributed variable is bound to Term, however
        when all local handlers succeed, all bindings are undone.


compare_instances

    Operation :   instance and variant tests

    Handler :   handler(-Res, ?TermL, ?TermR)

    Description :   The handler for the variant/2, instance/2 and
	compare_instances/3 instance-testing predicates.  The handler
	arguments are similar to those of compare_instances/3. At least
	one of TermL or TermR will be an attributed variable whenever
	the handler is invoked.  The handler should bind Res to < if
	the attributes imply that TermL is a proper instance of TermR,
	> if TermR is a proper instance of TermL, and = if the two
	attributed variables are variants of each other (e.g. they have
	identical domains).  If the terms are incomparable, the handler
	should fail.  If the attribute being declared has no bearing on
	the instance-relationship, this handler should remain undefined.


copy_term

    Operation :   copying an attributed variable

    Handler :   handler(?AttrVar, ?Var)

    Description :   The handler for the copy_term/2 predicate.  AttrVar is
        the attributed variable encountered in the copied term, Var is
        its corresponding variable in the copy.  All extension handlers
        receive the same arguments.  This means that if the attributed
        variable should be copied as an attributed variable, the
        handler must check if Var is still a free variable or if it was
        already bound to an attributed variable by a previous handler.


delayed_goals_number

    Operation :   querying number of suspended goals of a variable

    Handler :   handler(?AttrVar, -GoalsNumber)

    Description :  The handler for the delayed_goals_number/2
	predicate.  AttrVar is the attributed variable encountered in
	the predicate.  The handler is supposed to return the number
	of all suspended goals in this attribute.


get_bounds

    Operation :   get information about numeric variable bounds

    Handler :   handler(?AttrVar, -Lwb, -Upb)

    Description :  The handler for the get_var_bounds/3 predicate. 
	The handler should only be defined if the attribute contains
	information about numeric bounds.  The handler is only invoked
	if the variable has the corresponding (non-empty) attribute. 
	The handler should bind Lwb and Upb to numbers (any numeric
	type) reflecting the attribute's information about lower and
	upper bound of the variable, respectively.  If different
	attributes return different bounds information,
	get_var_bounds/3 will return the intersection of the bounds, even
        if this is empty (Lwb > Upb).


set_bounds

    Operation :   impose new bounds on an attributed variable

    Handler :   handler(?AttrVar, +Lwb, +Upb)

    Description :  The handler for the set_var_bounds/3 predicate. 
	The handler should only be defined if the attribute can
	incorporate information about numeric variable bounds.  The
	handler is only invoked if the variable has the corresponding
	(non-empty) attribute.  Lwb and Upb are the numbers that were
	passed to set_var_bounds/3, and the handler is expected to
	update its own bounds representation accordingly.


suspensions

    Operation :   querying suspensions attached to a variable

    Handler :   handler(?AttrVar, -ListOfSuspLists, -Tail)

    Description :  The handler for the suspensions/2 predicate. 
	AttrVar is an attributed variable.  The handler should bind
	ListOfSuspLists to a list containing all the attribute's
	suspension lists and ending with Tail.


print

    Operation :   printing the attribute

    Handler :   handler(?AttrVar, -Attribute)

    Description : Printing the attribute in printf/2, 3 when the m option
        is specified.  AttrVar is the attributed variable being printed,
        Attribute is the term which will be printed as a value for this
        attribute, qualified by the attribute name.  If no handler is
        specified for an attribute, or the print handler fails, the
        attribute will not be printed.  If there is only one attribute with
        an associated print handler, the attribute value is not qualified
        with the attribute name.

The following handlers are still supported for compatibility,
but their use is not recommended:

delayed_goals

    Operation :   querying suspended goals of a variable (obsolete)

    Handler :   handler(?AttrVar, ?Goals, -GoalsTail)

    Description :   The handler for the delayed_goals/2 predicate.
        AttrVar is the attributed variable encountered in the predicate.
        The handler is supposed to create a difference list of all
        goals in the suspended lists for this attribute. This handler
	should not be used anymore, define a suspensions-handler instead.

pre_unify

    Operation :   pre-unification notification (compatibility only)

    Handler :   handler(?AttrVar, +Term)

    Description :  The handler is invoked before unification.  The
	first argument is the attributed variable to be unified, the
	second argument is the term it is going to be unified with. 
	This handler is provided only for compatibility with SICStus
	Prolog and its use is not recommended, because it is less
	efficient than the unify handler and because its
	semantics is somewhat unclear, there may be cases where
	changes inside this handler may have unexpected effects.





Modes and Determinism
   meta_attribute(+, ++) is det

Modules
   This predicate is sensitive to its module context (tool predicate, see @/2).

Exceptions
     4 --- The arguments are not ground.
     5 --- The first argument is not an atom or the second one is not a    list in the required format.
     6 --- The specified operation is not implemented or the handler    arity is wrong.

Examples
   
[eclipse 5]: write(X{a}).
undefined metaterm attribute in trans_meta_in(X, _g370, eclipse)
syntax error : in source transformation
| write(X{a}).
|             ^ here
[eclipse 6]: meta_attribute(eclipse, []).

yes.
[eclipse 7]: printf("%QPMw", X{a}).
X{suspend : _g386 , a}
X = X
yes.


See Also
   not_unify / 2, instance / 2, variant / 2, compare_instances / 3, copy_term / 2, delayed_goals_number / 2, delayed_goals / 2, set_var_bounds / 3, get_var_bounds / 3, printf / 2, printf / 3, suspensions / 2, add_attribute / 2
