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
- graft :: (HRLabelSet (HCons (LVPair lch t3) t22), HasField lch t6 p, HRLabelSet t22, HRLabelSet t12, H2ProjectByLabels ls t5 t12 t22, RecordLabels r ls, HRLabelSet t21, HRLabelSet t11, H2ProjectByLabels ls t4 t11 t21, HRLabelSet (HCons (LVPair lch (Record HNil)) t21), HLeftUnion (Record r) (Record t23) r'', H2ProjectByLabels (HCons lch HNil) t6 t13 t23) => Rule lf hof (Record (HCons (LVPair lch t3) t22)) t l ho (Record (HCons (LVPair lch (Record HNil)) t21)) t1 l1 ho1 (Record t6) t2 -> Rule lf hof (Record t12) p l1 ho1 (Record t11) (Record HNil) l2 ho2 (Record r) t3 -> lch -> Rule lf hof (Record t5) t l ho (Record t4) t1 l2 ho2 r'' t2
- 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
- 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 |
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.
graft :: (HRLabelSet (HCons (LVPair lch t3) t22), HasField lch t6 p, HRLabelSet t22, HRLabelSet t12, H2ProjectByLabels ls t5 t12 t22, RecordLabels r ls, HRLabelSet t21, HRLabelSet t11, H2ProjectByLabels ls t4 t11 t21, HRLabelSet (HCons (LVPair lch (Record HNil)) t21), HLeftUnion (Record r) (Record t23) r'', H2ProjectByLabels (HCons lch HNil) t6 t13 t23) => Rule lf hof (Record (HCons (LVPair lch t3) t22)) t l ho (Record (HCons (LVPair lch (Record HNil)) t21)) t1 l1 ho1 (Record t6) t2 -> Rule lf hof (Record t12) p l1 ho1 (Record t11) (Record HNil) l2 ho2 (Record r) t3 -> lch -> Rule lf hof (Record t5) t l ho (Record t4) t1 l2 ho2 r'' t2Source
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.
module Data.HList