Library for First-Class Attribute Grammars.
The library is documented in the paper: Attribute Grammars Fly First-Class. How to do aspect oriented programming in Haskell
For more documentation see the AspectAG webpage: http://www.cs.uu.nl/wiki/bin/view/Center/AspectAG.
- type Att att val = LVPair att val
- data Fam l ho c p = Fam l ho c p
- type Chi ch atts = LVPair ch atts
- type Rule lf hof sc ip l ho ic sp l' ho' ic' sp' = Fam lf hof sc ip -> Fam l ho ic sp -> Fam l' ho' ic' sp'
- emptyRule :: Rule lf hof sc ip l ho ic sp l ho ic sp
- instdef :: HExtend (Att att val) ho ho' => att -> val -> Fam l ho ic sp -> Fam l ho' ic sp
- locdef :: HExtend (Att att val) l l' => att -> val -> Fam l ho ic sp -> Fam l' ho ic sp
- inhdef :: Defs att nts vals ic ic' => att -> nts -> vals -> Fam l ho ic sp -> Fam l ho ic' sp
- syndef :: HExtend (Att att val) sp sp' => att -> val -> Fam l ho ic sp -> Fam l ho ic sp'
- inhmod :: Mods att nts vals ic ic' => att -> nts -> vals -> Fam l ho ic sp -> Fam l ho ic' sp
- synmod :: HUpdateAtLabel att val sp sp' => att -> val -> Fam l ho ic sp -> Fam l ho ic sp'
- class At l m v | l -> v where
- at :: l -> m v
- lhs :: Proxy Lhs
- loc :: Proxy Loc
- def :: Reader (Fam l ho chi par) a -> Fam l ho chi par -> a
- instdefM :: HExtend (Att att a) ho ho' => att -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l ho' ic sp
- locdefM :: HExtend (Att att a) l l' => att -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l' ho ic sp
- inhdefM :: Defs att nts a ic ic' => att -> nts -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l ho ic' sp
- syndefM :: HExtend (Att att a) sp sp' => att -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l ho ic sp'
- inhmodM :: Mods att nts a ic ic' => att -> nts -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l ho ic' sp
- synmodM :: (HUpdateAtHNat n (Att att a) sp sp', HFind att ls n, RecordLabels sp ls) => att -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic (Record sp) l ho ic (Record sp')
- ext :: Rule lf hof sc ip l' ho' ic' sp' l'' ho'' ic'' sp'' -> Rule lf hof sc ip l ho ic sp l' ho' ic' sp' -> Rule lf hof sc ip l ho ic sp l'' ho'' ic'' sp''
- adapt :: Rule lf hof sc ip li hoi ici spi lo hoo ico spo -> (sc' -> sc) -> (ici' -> ici) -> (ico -> ico') -> Rule lf hof sc' ip li hoi ici' spi lo hoo ico' spo
- rename :: (RenRL s sc' sc, RenRL s ici' ici, RenLR s ico ico') => Rule lf hof sc ip li hoi ici spi lo hoo ico spo -> s -> Rule lf hof sc' ip li hoi ici' spi lo hoo ico' spo
- fixCst :: (RecordLabels r ls, HRLabelSet (HCons (LVPair l (Record HNil)) r), HExtend (LVPair l v) t2 l', HRearrange ls r1 r', HLabelSet ls, H2ProjectByLabels (HCons l HNil) t10 t11 r1) => (Fam t t1 l' t3 -> Fam t4 t5 (Record (HCons (LVPair l (Record HNil)) r)) t6 -> Fam t7 t8 (Record t10) t9) -> l -> v -> Fam t t1 t2 t3 -> Fam t4 t5 (Record r) t6 -> Fam t7 t8 (Record r') t9
- graft :: (RecordLabels r ls, RecordValues r1 vs, HRLabelSet t2, HRLabelSet t1, H2ProjectByLabels vs r t1 t2, HRLabelSet (HCons (LVPair l (Record HNil)) t2), HRLabelSet t21, HRLabelSet t11, H2ProjectByLabels vs t t11 t21, HasField l t6 ip1, RenLR r1 ico1 t4, RenRL r1 (Record t1) ici1, RenRL r1 (Record t11) sc1, HRLabelSet (HCons (LVPair l t5) t21), RenLR l' ico (Record t6), RenRL l' (Record (HCons (LVPair l (Record HNil)) t2)) ici, RenRL l' (Record (HCons (LVPair l t5) t21)) sc, HExtend (LVPair l l) l1 l', HLeftUnion t4 (Record t23) (Record r2), H2ProjectByLabels (HCons l HNil) t6 t13 t23, HRearrange ls r2 r', HLabelSet ls) => Rule lf hof sc ip li hoi ici spi li1 hoi1 ico t12 -> l1 -> l -> Rule lf hof sc1 ip1 li1 hoi1 ici1 (Record HNil) t22 t3 ico1 t5 -> r1 -> Fam lf hof (Record t) ip -> Fam li hoi (Record r) spi -> Fam t22 t3 (Record r') t12
- type Prd prd rule = LVPair prd rule
- (.+.) :: Com r r' r'' => r -> r' -> r''
- sem_Lit :: a -> Record HNil -> a
- knit :: (HLeftUnion ho fc fc', Kn fc' ic sc, Empties fc' ec) => Rule l ho sc ip (Record HNil) (Record HNil) ec (Record HNil) l ho ic sp -> fc -> ip -> sp
- class SemType t nt | t -> nt
- copy :: (Copy att nts vp ic ic', HasField att ip vp) => att -> nts -> Rule lf hof sc ip l ho ic sp l ho ic' sp
- use :: (Use att nts a sc, HExtend (Att att a) sp sp') => att -> nts -> (a -> a -> a) -> a -> Rule lf hof sc ip l ho ic sp l ho ic sp'
- chain :: (Chain att nts val sc l ho ic sp ic' sp', HasField att ip val) => att -> nts -> Rule lf hof sc ip l ho ic sp l ho ic' sp'
- inhAspect :: (AttAspect (FnInh att nts) defs defasp, DefAspect (FnCpy att nts) cpys cpyasp, Com cpyasp defasp inhasp) => att -> nts -> cpys -> defs -> inhasp
- synAspect :: (AttAspect (FnSyn att) defs defasp, DefAspect (FnUse att nts op unit) uses useasp, Com useasp defasp synasp) => att -> nts -> op -> unit -> uses -> defs -> synasp
- chnAspect :: (DefAspect (FnChn att nts) chns chnasp, AttAspect (FnInh att nts) inhdefs inhasp, Com chnasp inhasp asp, AttAspect (FnSyn att) syndefs synasp, Com asp synasp asp') => att -> nts -> chns -> inhdefs -> syndefs -> asp'
- attAspect :: AttAspect rdef defs rules => rdef -> defs -> rules
- defAspect :: DefAspect deff prds rules => deff -> prds -> rules
- class ListNT nt tHd tTl where
- module Data.HList
Rules
A Family Fam
contains a single attribution p
for the parent,
l
for local attributes, ho
for higer-order attributes and
a collection of attributions c
for the children.
Fam l ho c p |
(HasField lprd r (Rule lf hof sc ip l' ho' ic' sp' l'' ho'' ic'' sp''), HUpdateAtLabel lprd (Rule lf hof sc ip l ho ic sp l'' ho'' ic'' sp'') r r') => ComSingle HTrue (Prd lprd (Rule lf hof sc ip l ho ic sp l' ho' ic' sp')) r r' | |
HExtend (LVPair att val) sp sp' => Apply (FnSyn att) (Fam lf hof sc ip -> val) (Rule lf hof sc ip l ho ic sp l ho ic sp') | |
Defs att nts vals ic ic' => Apply (FnInh att nts) (Fam lf hof sc ip -> vals) (Rule lf hof sc ip l ho ic sp l ho ic' sp) |
type Rule lf hof sc ip l ho ic sp l' ho' ic' sp' = Fam lf hof sc ip -> Fam l ho ic sp -> Fam l' ho' ic' sp'Source
The type Rule
states that a rule takes as input the local attributes lf
,
the higher-order attributes hof
, the synthesized attributes
of the children sc
and the inherited attributes of the parent ip
and returns
a function from the output constructed thus far
(local attributes l
, higher-order attributes ho
, inherited attributes of the children
ic
and synthesized attributes of the parent sp
) to the extended output.
emptyRule :: Rule lf hof sc ip l ho ic sp l ho ic spSource
An emptyRule
does not introduce any new attribute.
instdef :: HExtend (Att att val) ho ho' => att -> val -> Fam l ho ic sp -> Fam l ho' ic spSource
The function instdef
adds the definition of a higher-order attribute.
It takes a label att
representing the name of the new attribute,
a value val
to be assigned to this attribute, and it builds a function which
updates the output constructed thus far.
locdef :: HExtend (Att att val) l l' => att -> val -> Fam l ho ic sp -> Fam l' ho ic spSource
The function locdef
adds the definition of a local attribute.
It takes a label att
representing the name of the new attribute,
a value val
to be assigned to this attribute, and it builds a function which
updates the output constructed thus far.
inhdef :: Defs att nts vals ic ic' => att -> nts -> vals -> Fam l ho ic sp -> Fam l ho ic' spSource
The function inhdef
introduces a new inherited attribute for
a collection of non-terminals.
It takes the following parameters:
att
: the attribute which is being defined,
nts
: the non-terminals with which this attribute is being associated, and
vals
: a record labelled with child names and containing values,
describing how to compute the attribute being defined at each
of the applicable child positions.
It builds a function which updates the output constructed thus far.
syndef :: HExtend (Att att val) sp sp' => att -> val -> Fam l ho ic sp -> Fam l ho ic sp'Source
The function syndef
adds the definition of a synthesized attribute.
It takes a label att
representing the name of the new attribute,
a value val
to be assigned to this attribute, and it builds a function which
updates the output constructed thus far.
inhmod :: Mods att nts vals ic ic' => att -> nts -> vals -> Fam l ho ic sp -> Fam l ho ic' spSource
The function inhmod
modifies an inherited attribute for
a collection of non-terminals.
It takes the following parameters:
att
: the attribute which is being defined,
nts
: the non-terminals with which this attribute is being associated, and
vals
: a record labelled with child names and containing values,
describing how to compute the attribute being defined at each
of the applicable child positions.
It builds a function which updates the output constructed thus far.||
synmod :: HUpdateAtLabel att val sp sp' => att -> val -> Fam l ho ic sp -> Fam l ho ic sp'Source
The function synmod
modifies the definition of a synthesized attribute.
It takes a label att
representing the name of the attribute,
a value val
to be assigned to this attribute, and it builds a function which
updates the output constructed thus far.
Monadic
class At l m v | l -> v whereSource
(HasField (Proxy (lch, nt)) chi v, MonadReader (Fam l ho chi par) m) => At (Proxy (lch, nt)) m v | |
MonadReader (Fam l ho chi par) m => At (Proxy Loc) m l | |
MonadReader (Fam l ho chi par) m => At (Proxy Lhs) m par |
instdefM :: HExtend (Att att a) ho ho' => att -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l ho' ic spSource
locdefM :: HExtend (Att att a) l l' => att -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l' ho ic spSource
inhdefM :: Defs att nts a ic ic' => att -> nts -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l ho ic' spSource
syndefM :: HExtend (Att att a) sp sp' => att -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l ho ic sp'Source
inhmodM :: Mods att nts a ic ic' => att -> nts -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic sp l ho ic' spSource
synmodM :: (HUpdateAtHNat n (Att att a) sp sp', HFind att ls n, RecordLabels sp ls) => att -> Reader (Fam lf hof sc ip) a -> Rule lf hof sc ip l ho ic (Record sp) l ho ic (Record sp')Source
Rules Composition
ext :: Rule lf hof sc ip l' ho' ic' sp' l'' ho'' ic'' sp'' -> Rule lf hof sc ip l ho ic sp l' ho' ic' sp' -> Rule lf hof sc ip l ho ic sp l'' ho'' ic'' sp''Source
Composition of two rules.
adapt :: Rule lf hof sc ip li hoi ici spi lo hoo ico spo -> (sc' -> sc) -> (ici' -> ici) -> (ico -> ico') -> Rule lf hof sc' ip li hoi ici' spi lo hoo ico' spoSource
Adaption of the childen of a rule.
rename :: (RenRL s sc' sc, RenRL s ici' ici, RenLR s ico ico') => Rule lf hof sc ip li hoi ici spi lo hoo ico spo -> s -> Rule lf hof sc' ip li hoi ici' spi lo hoo ico' spoSource
Children renaming.
fixCst :: (RecordLabels r ls, HRLabelSet (HCons (LVPair l (Record HNil)) r), HExtend (LVPair l v) t2 l', HRearrange ls r1 r', HLabelSet ls, H2ProjectByLabels (HCons l HNil) t10 t11 r1) => (Fam t t1 l' t3 -> Fam t4 t5 (Record (HCons (LVPair l (Record HNil)) r)) t6 -> Fam t7 t8 (Record t10) t9) -> l -> v -> Fam t t1 t2 t3 -> Fam t4 t5 (Record r) t6 -> Fam t7 t8 (Record r') t9Source
Fixing a constant as a child.
graft :: (RecordLabels r ls, RecordValues r1 vs, HRLabelSet t2, HRLabelSet t1, H2ProjectByLabels vs r t1 t2, HRLabelSet (HCons (LVPair l (Record HNil)) t2), HRLabelSet t21, HRLabelSet t11, H2ProjectByLabels vs t t11 t21, HasField l t6 ip1, RenLR r1 ico1 t4, RenRL r1 (Record t1) ici1, RenRL r1 (Record t11) sc1, HRLabelSet (HCons (LVPair l t5) t21), RenLR l' ico (Record t6), RenRL l' (Record (HCons (LVPair l (Record HNil)) t2)) ici, RenRL l' (Record (HCons (LVPair l t5) t21)) sc, HExtend (LVPair l l) l1 l', HLeftUnion t4 (Record t23) (Record r2), H2ProjectByLabels (HCons l HNil) t6 t13 t23, HRearrange ls r2 r', HLabelSet ls) => Rule lf hof sc ip li hoi ici spi li1 hoi1 ico t12 -> l1 -> l -> Rule lf hof sc1 ip1 li1 hoi1 ici1 (Record HNil) t22 t3 ico1 t5 -> r1 -> Fam lf hof (Record t) ip -> Fam li hoi (Record r) spi -> Fam t22 t3 (Record r') t12Source
Grafting one tree as a child of the other.
Aspects
type Prd prd rule = LVPair prd ruleSource
Field of an aspect. It associates a production prd
with a rule rule
.
Semantic Functions
knit :: (HLeftUnion ho fc fc', Kn fc' ic sc, Empties fc' ec) => Rule l ho sc ip (Record HNil) (Record HNil) ec (Record HNil) l ho ic sp -> fc -> ip -> spSource
The function knit
takes the combined rules for a node and the
semantic functions of the children, and builds a
function from the inherited attributes of the parent to its
synthesized attributes.
Common Patterns
copy :: (Copy att nts vp ic ic', HasField att ip vp) => att -> nts -> Rule lf hof sc ip l ho ic sp l ho ic' spSource
A copy rule copies an inherited attribute from the parent to all its children.
The function copy
takes the name of an attribute att
and
an heterogeneous list of non-terminals nts
for which the attribute has to be defined,
and generates a copy rule for this.
use :: (Use att nts a sc, HExtend (Att att a) sp sp') => att -> nts -> (a -> a -> a) -> a -> Rule lf hof sc ip l ho ic sp l ho ic sp'Source
A use rule declares a synthesized attribute that collects information
from some of the children.
The function use
takes the following arguments: the attribute to be defined,
the list of non-terminals for which the attribute is defined,
a monoidal operator which combines the attribute values,
and a unit value to be used in those cases where none of
the children has such an attribute.
chain :: (Chain att nts val sc l ho ic sp ic' sp', HasField att ip val) => att -> nts -> Rule lf hof sc ip l ho ic sp l ho ic' sp'Source
In the chain rule a value is threaded in a depth-first way through the tree, being updated every now and then. For this we have chained attributes (both inherited and synthesized). If a definition for a synthesized attribute of the parent with this name is missing we look for the right-most child with a synthesized attribute of this name. If we are missing a definition for one of the children, we look for the right-most of its left siblings which can provide such a value, and if we cannot find it there, we look at the inherited attributes of the father.
Defining Aspects
inhAspect :: (AttAspect (FnInh att nts) defs defasp, DefAspect (FnCpy att nts) cpys cpyasp, Com cpyasp defasp inhasp) => att -> nts -> cpys -> defs -> inhaspSource
The function inhAspect
defines an inherited attribute aspect.
It takes as arguments: the name of the attribute att
,
the list nts
of non-terminals where the attribute is defined,
the list cpys
of productions where the copy rule has to be applied,
and a record defs
containing the explicit definitions for some productions.
synAspect :: (AttAspect (FnSyn att) defs defasp, DefAspect (FnUse att nts op unit) uses useasp, Com useasp defasp synasp) => att -> nts -> op -> unit -> uses -> defs -> synaspSource
The function synAspect
defines a synthesized attribute aspect.
chnAspect :: (DefAspect (FnChn att nts) chns chnasp, AttAspect (FnInh att nts) inhdefs inhasp, Com chnasp inhasp asp, AttAspect (FnSyn att) syndefs synasp, Com asp synasp asp') => att -> nts -> chns -> inhdefs -> syndefs -> asp'Source
A chained attribute definition introduces both an inherited and a synthesized attribute. In this case the pattern to be applied is the chain rule.
Others
module Data.HList