---++ Introduction
Stratego uses terms to represent the abstract syntax of programs or documents. A term consists of a constructor
and a list of argument terms. Sometimes it is useful to record additional information about a term without adapting
its structure, i.e., creating a constructor with additional arguments. For this purpose terms can be annotated.
Support for TermAnnotations has been available from StrategoRelease07.
In Stratego a term always has a list of annotations. This is the empty list if a term doesn't have any annotations.
term annotation uses the syntax
t1 { a1 }
where term a1 is an annotation of term t1. If you want to add more
annotations to a term you can use the same syntax you would use for the content of a list:
t1 { a1, a2, a3 }
---++ Annotations in match and build
The annotations of a term can be retrieved in a pattern match and set in a build. For example
the following build will create a term =Plus(1, 2)= with the term =Int= as the only annotation.
!Plus(1, 2){Int}
Naturally the annotation syntax can also be used in a match:
?Plus(1, 2){Int}
Note however that this match only accepts =Plus(1, 2)= terms with just one annotation, which
should be the empty contstructor application =Int=. This match will thus not allow other
annotations.
---++ Annotations in RewriteRules
Because a RewriteRule is just sugar for a StrategyDefinition, the usage of annotations in rules
is just as you would expect. The following rule checks that the two subterms of the Plus have annotation Int
and then attaches the annotation Int to the whole term:
TypeCheck :
Plus(e1{Int}, e2{Int}) -> Plus(e1, e2){Int}
---++ Annotations in CongruenceOperators
Also congruences over annotations are supported. Thus, if =s1= and =s2= are strategies,
then =s1{s2}= is also a strategy, which applies s1 to the term and s2 to its annotations.
Notice that s2 is applied to the =annotations=. Therefor you have to use a list
congruence =[s3]= if you want to apply s3 to the only annotation of s3. If you want to
apply a strategy to all annotations, you can use a map.
Some examples:
Plus(1, 2){3} => Plus(1, 2){4}
Plus(1, 2){3, 4} => Plus(1, 2){4, 5}
Plus(1, 2){3, 4, 5} => Plus(1, 2){4, 5, 6}
---++ Frequent problems
---+++ Annotation is list
Remember that if you apply a =!Plus(1, 2){x}=, the term x will be the only annotation. This is also
the case if x is a list. Example:
SomeRule: xs -> Plus(5, 6){xs}
["a", "b", "c"] => Plus(5, 6){["a", "b", "c"]}
Notice that in this example the result is not =Plus(5, 6){"a", "b", "c"}=. The Plus term
will have just one annotation, which is the list =["a", "b", "c"]=. You can use ListMatching to solve
this problem:
SomeRule: [xs*] -> Plus(5, 6){xs*}
["a", "b", "c"] => Plus(5, 6){"a", "b", "c"}
You can also use ListMatching inside the annotation part of a match:
Incr: Int(x){as*} -> Int( x){as*}
Int(5){Int} => Int(6){Int}
---+++ Preserving annotations
Because annotations are not part of the structure there is a huge risk
of losing them. For example the following RewriteRule will already
drop the annotations of the Int term.
Incr: Int(x) -> Int( x)
You can create a strategy into an annotation preserving strategy
with =preserve-annos= in the annotations module of the StrategoStandardLibrary.
The GenericTermTraversal operators =all=, =some= and =one= and
CongruenceOperators preserve annotations. If the =Incr= rule is implemented
as congruence, the annotations will be preserved:
Incr = Int(inc)
Int(5){Int} => Int(6){Int}
-- Main.MartinBravenboer - 25 Jan 2003
----
CategoryGlossary