COP 5021 Lecture -*- Outline -*- * Attributes This is terminology from the field of "attribute grammars" ** What are attributes? ------------------------------------------ ATTRIBUTES defn: an *attribute* is Two kinds of attributes: Synthesized: (passed up toward the root) AST's value computed from attributes of subtrees Inherited: (passed down) AST's value given to it from its parent in the AST ------------------------------------------ ... a property of an AST (typically computed) An attribute can have any type in XText ** Examples of Synthesized Attributes ------------------------------------------ SYNTHESIZED ATTRIBUTE EXAMPLE // file CFG.xtend // (in edu.ucf.cs.whilelang.utility) /** Returns the label of the initial * ElementaryBlock of a statement. */ def dispatch static int init(AssignS s) { s.label } /** Returns the label of the initial * ElementaryBlock of a statement. */ def dispatch static int init(SkipS s) { s.label } /** Returns the label of the initial * ElementaryBlock of a statement. */ def dispatch static int init(IfS s) { s.bexp.label } ------------------------------------------ Explain the notation: def, dispatch Note that AssignS, SkipS and IfS are AST types, so s is an AST Take a look at CFG.xtend for other code (in Xtend) A synthesized attribute is computed from below in the tree (towards the leaves) ** inherited attribute example Inherited attributes aren't supported very well in XText ------------------------------------------ INHERITED ATTRIBUTES No direct support (that I know of) in XText Can use static fields to hold mappings that are precomputed values of functions Compute them during "validation" in XText ------------------------------------------ ------------------------------------------ CODING INHERITED ATTRIBUTES IN XTEXT 1. Declare static maps somewhere class CFG { // file CFG.xtend /** What is the ElementaryBlock with the given label? */ public static val Map itsBlockMap = new HashMap() /** What is the set of flows within each statement? */ public static val FlowGraph cfgMap = new FlowGraph() /* ... */ } 2. Before other checks, populate the maps (a). Call the label validator first, then the CFG validator package edu.ucf.cs.whilelang.validation /* ... some imports... */ public class WhileLangValidator extends AbstractWhileLangValidator { @Check def checkStaticConstraints(Program p) { new WhileLangLabelsValidator().checkUniqueLabels(p) new WhileLangCFGValidator().constructCFG(p) } } (b). Write the CFG Validator to populate the maps package edu.ucf.cs.whilelang.validation import edu.ucf.cs.whilelang.utility.CFG /* ... */ /** * This class constructs a control flow graph (CFG) for the program. * See Section 2.1 of "Principles of Program Analysis" * by Nielsen, Nielsen, and Hankin (Springer-Verlag, 1999 and 2005). */ class WhileLangCFGValidator extends AbstractWhileLangValidator { /** What is the ElementaryBlock with the given label? */ val static Map itsBlockMap = CFG.itsBlockMap /** What is the set of flows within each statement? */ val static FlowGraph cfgMap = CFG.cfgMap /** Construct the CFG for the given program. * Assumes that the labels have already been added to the program. */ @Check def constructCFG(Program p) { resetMaps() // important because vars are static p.body.constructIBM p.body.constructFlows } /* ... */ } 3. Now the static maps are available to all ------------------------------------------ Xtend uses val to declare final variables and these are private by default Q: What happens if we don't reset the maps? Then the static vars continue their values from previous programs Look at the code in WhileLangCFGValidator to compute itsBlockMap and cfgMap... Show the tests for the CFGs ** other tools ------------------------------------------ OTHER TOOLS FOR ATTRIBUTES Tools to work with attributes exist JastAdd is an example tailored to compilers written in Java. These make dealing with inherited attributes easier One could also use LLVM or Visual Studio ------------------------------------------ We used JastAdd in this class in 2016