1% BEGIN LICENSE BLOCK
2% Version: CMPL 1.1
3%
4% The contents of this file are subject to the Cisco-style Mozilla Public
5% License Version 1.1 (the "License"); you may not use this file except
6% in compliance with the License.  You may obtain a copy of the License
7% at www.eclipse-clp.org/license.
8%
9% Software distributed under the License is distributed on an "AS IS"
10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11% the License for the specific language governing rights and limitations
12% under the License.
13%
14% The Original Code is  The ECLiPSe Constraint Logic Programming System.
15% The Initial Developer of the Original Code is  Cisco Systems, Inc.
16% Portions created by the Initial Developer are
17% Copyright (C) 1996 - 2006 Cisco Systems, Inc.  All Rights Reserved.
18%
19% Contributor(s):
20%
21% END LICENSE BLOCK
22
23% @(#)extmeta.tex	1.8 96/01/08
24%
25
26\chapter{Attributed Variables}
27%HEVEA\cutdef[1]{section}
28\label{attrvars}
29\label{metaterms}
30\index{attributed variables|(}\index{variable!attributed}
31
32\section{Introduction}
33The \defnotion{attributed variable} is a special \eclipse data type which
34represents a variable together with attached attributes.
35In the literature, attributed variables are sometimes referred to as
36``metaterms''.\index{metaterm|see{attributed variable}}
37The name \about{metaterm} originates from its application in meta-programming:
38for an object-level program, a metaterm looks like a variable, but for
39a meta-program the same variable is just a piece of data which, possibly
40together with additional meta-level information, forms the metaterm.
41
42The attributed variable is a powerful means to implement various extensions of
43the
44plain Prolog language.
45In particular, it allows the system's behaviour
46on unification to be customised.
47In most situations an attributed variable behaves like a normal
48variable, e.g.,
49it can be unified with other terms and
50\bipref{var/1}{../bips/kernel/typetest/var-1.html} succeeds on it.
51The differences in comparison to a plain variable are:
52\begin{itemize}
53\item an attributed variable has a number of associated \emph{attributes};
54\item the attributes are included in the module system;
55\item when an attributed variable occurs in the unification and in some
56built-in predicates, each attribute is processed by a user-defined
57\emph{handler}.
58\end{itemize}
59
60\section{Declaration}
61An attributed variable can have any number of attributes.
62The attributes are accessed by their name.
63Before an attribute can be created and used, it must be declared
64with the predicate
65\bipref{meta_attribute/2}{../bips/kernel/termmanip/meta_attribute-2.html}.
66The declaration has the format
67\begin{quote}
68\predspec{meta_attribute(\pattern{Name},~\pattern{HandlerList})}
69\end{quote}
70\about{Name} is an atom denoting the attribute name
71and usually it is the name of the module where this attribute
72is being created and used.
73\about{HandlerList} is a (possibly empty) list of handler specifications
74for this attribute (see Section \ref{metahandlers}).
75
76\vfill %<<<<<<<<<<<<<<<<
77
78\section{Syntax}
79
80{\samepage
81The most general attributed variable syntax is
82\begin{quote}
83\preddef{\pattern{Var}\{\pattern{Name_1}:\pattern{Attr_1},%
84~\pattern{Name_2}:\pattern{Attr_2},~\ldots,%
85~\pattern{Name_n}:\pattern{Attr_n}\}}
86\end{quote}
87where the syntax of \about{Var} is like that of a variable,
88\about{Name_i}
89are attribute names and
90\about{Attr_i}
91are the values of the corresponding attributes.
92}
93The expression \notation{Var\{Attr\}} is a shorthand for
94\notation{Var\{\pattern{Module}:Attr\}} where \about{Module} is the current
95module name.
96The former is called \defnotionni{unqualified} and the latter
97\defnotionni{qualified} attribute specification.
98\index{qualified attribute specification}
99\index{attribute!specification!qualified}
100\index{unqualified attribute specification}
101\index{attribute!specification!unqualified}
102As the attribute name is usually identical with the source module name,
103all occurrences of an attributed variable in the source module may use the
104unqualified
105specification.
106
107If there are several occurrences of the same attributed variable in a single
108term,
109only one occurrence is written with the attribute,
110the others just refer to the variable's name,
111e.g.,
112\begin{quote}
113\begin{verbatim}
114p(X, X{attr:Attr})
115\end{verbatim}
116\end{quote}
117or
118\begin{quote}
119\begin{verbatim}
120p(X{attr:Attr}, X)
121\end{verbatim}
122\end{quote}
123both describe the same term, which has two occurrences of a single attributed
124variable
125with attribute \notation{attr:Attr}.
126The following is a syntax error (even when the attributes are identical):
127\begin{quote}
128\begin{verbatim}
129p(X{attr:Attr}, X{attr:Attr})
130\end{verbatim}
131\end{quote}
132
133
134\section{Creating Attributed Variables}
135A new attribute can be added to a variable
136using the tool predicate
137\begin{quote}
138\predspec{add_attribute(\pattern{Var}, \pattern{Attr})}.%
139\indextt{add_attribute/2}
140\end{quote}
141An attribute whose name is not the current module name
142can be added using
143\bipref{add_attribute/3}{../bips/kernel/termmanip/add_attribute-3.html} which
144is its tool
145body predicate (exported in \notation{sepia_kernel}).
146If \about{Var} is a free variable, it will be bound to a new attributed variable
147whose attribute corresponding to the current module is
148\about{Attr} and all its other attributes are free variables.
149If \about{Var} is already an attributed variable and its attribute is
150uninstantiated,
151it will be bound to \about{Attr}, otherwise the effect of this predicate
152will be the same as unifying \about{Var} with another attributed variable
153whose attribute corresponding to the current module is
154\about{Attr}.
155
156\section{Decomposing Attributed Variables}
157The attributes of an attributed variable can be accessed using one-way
158unification in a matching clause, e.g.,
159\begin{quote}
160\begin{verbatim}
161    get_attribute(X{Name:Attribute}, A) :-
162        -?->
163        A = Attribute.
164\end{verbatim}
165\end{quote}
166This clause succeeds only when the first argument is an attributed variable,
167and it binds
168\about{X} to the whole attributed variable and \about{A} to the attribute
169whose name is the instantiation of \about{Name}.
170Note that a normal (unification) clause can \emph{not} be used to decompose
171an attributed variable (it would create a new attributed variable and unify this
172with the caller
173argument, but the unification is handled by an attributed variable handler, see
174Section \ref{metahandlers}).
175
176\section{Attribute Modification}
177Often an extension must modify the data stored in the
178attribute to reflect changes in the computation.
179The usual Prolog way to do this is by reserving
180one argument in the attribute structure for this next value.
181before accessing the most recent attribute value this chain
182of values has to be dereferenced until a value is found whose
183link is still free.
184A perfect compiler should be able to detect that the older
185attribute values are no longer accessed and it would compile
186these modifications using destructive assignment.
187Current compilers are unfortunately not able to perform
188this optimization (some systems can reduce these chains
189during garbage collection, but until this occurs,
190the list has to be dereferenced for each access and update).
191To avoid performance loss for both attribute updating and
192access, {\eclipse} provides a predicate for explicit
193attribute update:
194\predspec{setarg(\pattern{I}, \pattern{Term}, \pattern{NewArg})} will update the
195\about{I}'th
196argument of \about{Term} to be \about{NewArg}.
197Its previous value will be restored on backtracking.
198%Although the use of this predicate does not corrupt the
199%declarative reading of the program (it is merely
200%a shorthad for the above described modification
201%using value links), we still recommed to use it with care,
202%because sometimes it might yield unexpected results.
203
204Libraries which define user-programmable extensions
205like, e.g., \libspec{fd} usually define predicates that
206modify the attribute or a part of it, so that an explicit
207use of the \bipref{setarg/3}{../bips/kernel/termmanip/setarg-3.html} predicate
208is not necessary.
209
210\section{Attributed Variable Handlers}
211\label{metahandlers}
212An attributed variable is a variable with some additional information
213which is ignored by ordinary \emph{object level} system predicates.
214\emph{Meta level} operations on attributed variables are handled by
215extensions which know
216the contents of their attributes and can specify the outcome
217of each operation.
218This mechanism is implemented using \defnotionni{attributed variable handlers},
219\index{attributed variables!handlers}\index{handler}
220which are user-defined predicates invoked
221whenever an attributed variable occurs in one of the predefined
222operations.
223The handlers are specified in the attribute declaration
224\predspec{meta_attribute(\pattern{Name},~\pattern{HandlerList})}, the second
225argument
226is a list of handlers in the form
227\begin{quote}
228\begin{verbatim}
229[unify:UnifyHandler, test_unify:TUHandler, ...]
230\end{verbatim}
231\end{quote}
232Handlers for operations which are not specified or those that are
233\bipref{true/0}{../bips/kernel/control/true-0.html} are ignored and never
234invoked.
235If \about{Name} is an existing extension, the specified handlers
236replace the current ones.
237
238Whenever one of the specified operations detects an attributed variable,
239it will invoke all handlers that were declared for it
240and each of them receives either the whole attributed variable
241or its particular attribute as argument.
242The system does not check if the attribute that corresponds
243to a given handler is instantiated or not; this means
244that the handler must check itself if the attributed variable
245contains any attribute information or not.
246For instance, if an attributed variable \notation{X\{a:_, b:_, c:f(a)\}}
247is unified with the attributed variable \notation{Y\{a:_, b:_, c:f(b)\}},
248the handlers for the attributes \notation{a} and \notation{b} should
249treat this as binding of two plain variables
250because their attributes were not involved.
251Only the handler for \notation{c} has any work to do here.
252The library \libspec{suspend} can be used as a template
253for writing attributed variable handlers.
254
255The following operations invoke attributed variable handlers:
256
257\begin{description}
258%--------------------------
259\item [unify:]\handleridx{unify}
260  the usual unification.
261The handler procedure is
262\begin{quote}
263\predspec{%
264unify_handler(+\pattern{Term},~?\pattern{Attribute}~[,\pattern{SuspAttr}])}
265\end{quote}
266The first argument is the term that was unified with the attributed variable,
267it is either a non-variable or another attributed variable.
268The second argument is the contents of the attribute slot
269corresponding to the extension.  Note that, at this point in execution,
270the orginal attributed variable no longer exists, because it has already
271been bound to \about{Term}.
272The optional third argument is the suspend-attribute of the former
273variable; it may be needed to wake the variable's 'constrained' suspension
274list.
275
276The handler's job is to determine whether the binding is allowed with
277respect to the attribute.  This could for example involve checking whether
278the bound term is in a domain described by the attribute.
279For variable-variable bindings, typically the remaining attribute must
280be updated to reflect the intersection of the two individual attributes.
281In case of success, suspension lists inside the attributes may need to
282be scheduled for waking.
283
284If an attributed variable is unified with a standard variable, the variable is
285bound
286to the attributed variable and no handlers are invoked.
287If an attributed variable is unified with another attributed variable or a
288non-variable,
289the attributed variable is bound (like a standard variable) to the other term
290\emph{and} all handlers for the \notation{unify} operation are invoked.
291Note that several attributed variable bindings can occur simultaneously,
292e.g.\ during a head unification or
293during the unification of two compound terms.
294The handlers are only invoked at certain trigger points (usually before the
295next regular predicate call).  Woken goals will start executing once all
296unify-handlers are done.
297
298%--------------------------
299\item [test_unify:]\handleridx{test_unify}
300  a unifiability test which is not supposed
301to trigger constraints propagation. It is used
302by the \bipref{not_unify/2}{../bips/kernel/termcomp/not_unify-2.html}
303predicate.
304The handler procedure is
305\begin{quote}
306\predspec{test_unify_handler(+\pattern{Term}, ?\pattern{Attribute})}
307\end{quote}
308where the arguments are the same as for the unify handler.
309The handler's job is to determine whether \about{Attribute} allows
310unification with \about{Term} (not considering effects of woken goals).
311During the execution of the handler, the attributed variable may be bound
312to \about{Term}, however when all attribute handlers succeed,
313all bindings are undone again, and no waking occurs.
314
315\item [compare_instances:]\handleridx{compare_instances}
316  computation of instance, subsumption
317and variance relationship, as performed by the built-ins
318\bipref{compare_instances/3}{../bips/kernel/termcomp/compare_instances-3.html},
319\bipref{instance/2}{../bips/kernel/termcomp/instance-2.html} and
320\bipref{variant/2}{../bips/kernel/termcomp/variant-2.html}.
321The handler procedure is
322\begin{quote}
323\predspec{instance_handler(-\pattern{Res},~?\pattern{TermL},~?\pattern{TermR})}
324\end{quote}
325and its arguments are similar to the ones of the
326\bipref{compare_instances/3}{../bips/kernel/termcomp/compare_instances-3.html}
327predicate.
328The handler is invoked with one or both of \about{TermL} and \about{TermR} being
329attributed variables. The task of the handler is to examine the two terms,
330and compute their instance relationship with respect to the extension
331attribute in question.  The handler must
332bind \about{Res} to \notation{=} iff the terms are variants,
333\notation{<} iff \about{TermL} is a proper instance of TermR, or \notation{>}
334iff \about{TermR} is a proper instance of \about{TermL}) with respect to
335the attribute under consideration. If the terms are not unifiable with respect
336to this attribute, the handler must fail.
337
338Even though one of \about{TermL} and \about{TermR} is guaranteed to be
339an attributed variable, they might not have the particular attribute that
340the handler is concerned with.  The handler must therefore be written to
341correctly deal with all combinations of an attributed (but potentially
342uninstantiated attribute) variable with any other term.
343
344
345\item [copy_term:]\handleridx{copy_term}
346  the handler is invoked by either
347\bipref{copy_term/2}{../bips/kernel/termmanip/copy_term-2.html} or
348\bipref{copy_term_vars/3}{../bips/kernel/termmanip/copy_term_vars-3.html}.
349The handler procedure is
350\begin{quote}
351\predspec{copy_handler(?\pattern{AttrVar},~?\pattern{Copy})}
352\end{quote}
353\about{AttrVar} is the attributed variable encountered in the
354copied term, \about{Copy} is its corresponding variable in the copy.
355All extension handlers receive the same arguments.
356This means that if the attributed variable should be copied as
357an attributed variable, the handler must check if \about{Copy} is still
358a free variable or if it was already bound to an attributed variable by a
359previous handler.
360
361\item [suspensions:]\handleridx{suspensions}
362  this handler is invoked by the
363\bipref{suspensions/2}{../bips/kernel/suspensions/suspensions-2.html} predicate
364to collect all the suspension lists inside the attribute.
365The handler call pattern is
366\begin{quote}
367\predspec{suspensions_handler(?\pattern{AttrVar},~-\pattern{ListOfSuspLists},%
368~-\pattern{Tail})}
369\end{quote}
370\about{AttrVar} is an attributed variable. The handler should bind
371\about{ListOfSuspLists} to a list containing all the attribute's
372suspension lists and ending with \about{Tail}.
373
374
375\item [delayed_goals_number:]\handleridx{delayed_goals_number}
376  handler is invoked by the
377\bipref{delayed_goals_number/2}{../bips/kernel/suspensions/delayed_goals_number-2.html}
378predicate.
379The handler call pattern is
380\begin{quote}
381\predspec{delayed_goals_number_handler(?\pattern{AttrVar},%
382~-\pattern{Number})}
383\end{quote}
384\about{AttrVar} is the attributed variable encountered in the
385term, \about{Number} is the number of delayed
386goals occurring in this attribute.
387Its main purpose is for the first-fail selection predicates,
388i.e., it should return the number of constraints imposed on
389the variable.
390
391\item [get_bounds:]\handleridx{get_bounds}
392    This handler is used by the predicate
393    \bipref{get_var_bounds/3}{../bips/kernel/termmanip/get_var_bounds-3.html}
394    to retrieve information about the lower and upper bound of a numeric
395    variable.
396    The handler should therefore only be defined if the attribute contains
397    that kind of information. The handler call pattern is
398    \begin{quote}
399\predspec{%
400get_bounds_handler(?\pattern{AttrVar},~-\pattern{Lwb},~-\pattern{Upb})}
401    \end{quote}
402    The handler is only invoked if the variable has the corresponding
403    (non-empty) attribute.
404    The handler should bind \about{Lwb} and \about{Upb} to numbers
405    (any numeric type) reflecting the attribute's information about lower
406    and upper bound of the variable, respectively.
407    If different attributes return different bounds information,
408    \bipref{get_var_bounds/3}{../bips/kernel/termmanip/get_var_bounds-3.html}
409    will return the intersection of these bounds. This can be empty
410    (\about{Lwb} $>$ \about{Upb}).
411
412\item [set_bounds:]\handleridx{set_bounds}
413    This handler is used by the predicate
414    \bipref{set_var_bounds/3}{../bips/kernel/termmanip/set_var_bounds-3.html}
415    to distribute information about the lower and upper bound of a numeric
416    variable to all its existing attributes.
417    The handler should therefore only be defined if the attribute can
418    incorporate this kind of information. The handler call pattern is
419    \begin{quote}
420\predspec{%
421set_bounds_handler(?\pattern{AttrVar},~+\pattern{Lwb},~+\pattern{Upb})}
422    \end{quote}
423    The handler is only invoked if the variable has the corresponding
424    (non-empty) attribute.
425    \about{Lwb} and \about{Upb} are the numbers that were passed to
426    \bipref{set_var_bounds/3}{../bips/kernel/termmanip/set_var_bounds-3.html},
427    and the handler is expected to update its
428    own bounds representation accordingly.
429
430
431
432\item [print:]\handleridx{print}
433  attribute printing in
434\biprefni{write/1,2}{../bips/kernel/ioterm/write-1.html},%
435\indextt{write/1}\indextt{write/2}
436\biprefni{writeln/1,2}{../bips/kernel/ioterm/writeln-1.html},%
437\indextt{writeln/1}\indextt{writeln/2}
438\biprefni{printf/2,3}{../bips/kernel/ioterm/printf-2.html}%
439\indextt{printf/2}\indextt{printf/3}
440when the \notation{m} option is specified.
441The handler procedure is
442\begin{quote}
443\predspec{print_handler(?\pattern{AttrVar},~-\pattern{PrintAttr})}
444\end{quote}
445\about{AttrVar} is the attributed variable being printed, \about{PrintAttr}
446is the term which will be printed as a value for this attribute,
447prefixed by the attribute name.
448If no handler is specified for an attribute, or the print handler fails,
449the attribute will not be printed.
450
451\end{description}
452
453The following handlers are still supported for compatibility,
454but their use is not recommened:
455\begin{description}
456\item [pre_unify:]\handleridx{pre_unify}
457  this is another handler which can be invoked on
458normal unification, but it is called \emph{before} the unification
459itself occurs.
460The handler procedure is
461\begin{quote}
462\predspec{pre_unify_handler(?\pattern{AttrVar},~+\pattern{Term})}
463\end{quote}
464The first argument is the attributed variable to be unfied,
465the second argument is the term it is going to be unified with.
466This handler is provided only for compatibility with SICStus Prolog
467and its use is not recommended, because it is less efficient
468than the \notation{unify} handler and because its semantics is somewhat
469unclear, there may be cases where changes inside this handler
470may have unexpected effects.
471
472\item [delayed_goals:]\handleridx{delayed_goals}
473  this handler is superseded by the
474suspensions-handler, which should be preferred. If there is no suspensions-
475handler, this handler is invoked by the obsolete
476\bipref{delayed_goals/2}{../bips/kernel/suspensions/delayed_goals-2.html}
477predicate.
478The handler procedure is
479\begin{quote}
480\predspec{delayed_goals_handler(?\pattern{AttrVar},~?\pattern{GoalList},%
481~-\pattern{GoalCont})}
482\end{quote}
483\about{AttrVar} is the attributed variable encountered in the
484term, \about{GoalList} is an open-ended list of all delayed
485goals in this attribute and \about{GoalCont} is the
486tail of this list.
487
488\end{description}
489
490%--------------------------
491\subsection{Printing Attributed Variables}
492\indextt{output_mode}
493The different output predicates treat attributed variables differently.
494The \bipref{write/1}{../bips/kernel/ioterm/write-1.html} predicate prints
495the attributes using the print-handlers,
496while \bipref{writeq/1}{../bips/kernel/ioterm/writeq-1.html} prints the whole
497attribute, so that the attributed variable
498can be read back.
499The \bipref{printf/2}{../bips/kernel/ioterm/printf-2.html} predicate has two
500options to be combined with
501the \notation{w} format: \notation{M} forces the whole attributed variable to be
502printed
503together with all its attributes in the standard format, so that
504it can be read back in.
505With the \notation{m} option the attributed variable is printed using the
506handlers
507defined for the \notation{print} operation.
508If there is only one handled attribute, the attributed variable is printed as
509\begin{quote}
510X\{Attr\}
511\end{quote}
512where \about{Attr} is the value obtained from the handler.
513If there are several handled attributes, all attributes are qualified
514like in
515\begin{quote}
516X\{a:A, b:B, c:C\}.
517\end{quote}
518A simple print handler can just return the attribute literally, like
519\begin{quote}\begin{verbatim}
520print_attr(_{Attr}, PrintAttr) ?- PrintAttr=Attr.
521\end{verbatim}\end{quote}
522{\samepage
523An attributed variable \notation{X\{m:a\}} with \notation{print} handler
524\predspec{print_attr/2}
525for the m-attribute, can thus be printed in different ways, e.g.,
526\footnote{The attribute \notation{suspend} is always present and defined
527by system coroutining.}
528\begin{quote}
529\begin{verbatim}
530printf("%w", [X{m:a}])   or write(X{m:a}):   X
531printf("%vMw", [X{m:a}]) or writeq(X{m:a}):  _g246{suspend : _g242, m : a}
532printf("%mw", [X{m:a}]):                     X{a}
533printf("%Mw", [X{m:a}]):                     X{suspend : _g251, m : a}
534printf("%Vmw", [X{m:a}]):                    X_g252{a}
535\end{verbatim}
536\end{quote}
537}
538
539\index{macro!write}
540Write macros for attributed variables are not allowed because one extension
541alone
542should not decide whether the other attributes will be printed or not.
543
544\section{Built-Ins and Attributed Variables}
545\begin{description}
546\item[free(?\pattern{Term})]\indextt{free/1}
547This type-checking predicate succeeds iff its argument is an
548ordinary free variable, it fails if it is an attributed variable.
549
550\item[meta(?\pattern{Term})]\indextt{meta/1}
551This type-checking predicate succeeds iff its argument is an attributed
552variable.
553For other type testing predicates an attributed variable behaves like a
554variable.
555\end{description}
556
557\section{Examples of Using Attributed Variables}
558\subsection{Variables with Enumerated Domains}
559As an example, let us implement variables of enumerable types
560using attributes.
561We choose to represent these variable as attributed variables
562whose attribute is
563a \notation{enum/1} structure with a list holding the values the variable may
564take, e.g.,
565\begin{quote}
566\begin{verbatim}
567X{enum([a,b,c])}
568\end{verbatim}
569\end{quote}
570
571We have to specify now what should happen when such a variable is
572bound. This is done by writing a handler for the \notation{unify} operation.
573The predicate \predspec{unify_enum/2} defined below is this
574handler.
575Its first argument is the value that the attributed variable has been bound to,
576the second is the attribute that the bound attributed variable had
577(keep in mind that the system has already bound the attributed variable to the
578new value).  We distinguish two cases:
579\begin{itemize}
580\item
581First, the attributed variable has been
582bound to another attributed variable (1st clause of \predspec{unify_enum/2}).
583In this case, we form the intersection between the two lists
584of admissible values. If it is empty, we fail.
585If it contains exactly one value, we can instantiate the remaining
586attributed variable with this value.
587Otherwise, we bind it to a new attributed variable whose attribute represents
588the remaining admissible values.
589
590\item
591Second, when the attributed variable has been bound to a non-variable, the
592task that remains for the handler is merely to check if this binding
593was admissible (second clause of \predspec{unify_enum/2}).
594\end{itemize}
595
596\begin{quote}
597\begin{verbatim}
598[eclipse 2]: module(enum).
599warning: creating a new module in module(enum)
600[enum 3]: [user].
601:- meta_attribute(enum, [unify:unify_enum/2, print:print_enum/2]).
602:- import setarg/3 from sepia_kernel.
603
604% unify_enum(+Term, Attribute)
605unify_enum(_, Attr) :-
606    /*** ANY + VAR ***/
607    var(Attr).                 % Ignore if no attribute for this extension
608unify_enum(Term, Attr) :-
609    compound(Attr),
610    unify_term_enum(Term, Attr).
611
612unify_term_enum(Value, enum(ListY)) :-
613    nonvar(Value),             % The attributed variable was instantiated
614    /*** NONVAR + META ***/
615    memberchk(Value, ListY).
616unify_term_enum(Y{AttrY}, AttrX) :-
617    -?->
618    unify_enum_enum(Y, AttrX, AttrY).
619
620unify_enum_enum(_, AttrX, AttrY) :-
621    var(AttrY),                         % no attribute for this extension
622    /*** VAR + META ***/
623    AttrX = AttrY.                      % share the attribute
624unify_enum_enum(Y, enum(ListX), AttrY) :-
625    nonvar(AttrY),
626    /*** META + META ***/
627    AttrY = enum(ListY),
628     intersection(ListX, ListY, ListXY),
629     ( ListXY = [Val] ->
630            Y = Val
631     ;
632            ListXY \= [],
633            setarg(1, AttrY, ListXY)
634     ).
635
636print_enum(_{enum(List)}, Attr) :-
637    -?->
638    Attr = List.
639 user       compiled traceable 1188 bytes in 0.03 seconds
640
641yes.
642[enum 4]: A{enum([yellow, blue, white, green])}
643                = B{enum([orange, blue, red, yellow])}.
644
645A = B = A{[blue, yellow]}
646yes.
647[enum 5]: A{enum([yellow, blue, white, green])}
648                = B{enum([orange, blue, red, black])}.
649
650A = B = blue
651yes.
652[enum 6]: A{enum([yellow, blue, white, green])} = white.
653
654A = white
655yes.
656[enum 7]: A{enum([yellow, blue, white, green])} = red.
657
658no (more) solution.
659
660\end{verbatim}
661\end{quote}
662
663Some further remarks on this code:
664\index{matching}
665\index{pattern matching}
666\index{unification!pattern matching}
667The second clause of \predspec{unify_term_enum/2}
668is a \emph{matching clause}, as indicated
669by the \notation{-?->} guard.
670A matching clause is the only way to decompose an attributed variable.
671Note that this clause matches only calls that have an attributed variable
672with nonempty \notation{enum} attribute on the
673first argument position.
674
675\vfill %<<<<<<<<<<<<<<<<<<<<<<<<
676
677\section{Attribute Specification}
678The structures notation (see section~\ref{chapstruct})
679is used to define
680and access variable attributes and their arguments.
681This makes the code independent of the number of attributes
682and positions of their arguments.
683Wherever appropriate, the libraries described in this document
684describe their attributes in this way, e.g.,
685\begin{quote}
686\notation{suspend\{inst:I, constrained:C, bound:B\}}
687\end{quote}
688says that the structure name is \notation{suspend} and that
689it has (at least) three arguments with the corresponding names.%
690\index{attributed variables|)}
691
692%HEVEA\cutend
693
694
695