001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2005-2006 Princeton University
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.lang.c4;
020:
021: import java.util.ArrayList;
022: import java.util.List;
023: import java.util.Iterator;
024:
025: import xtc.tree.GNode;
026: import xtc.xform.Query;
027: import xtc.xform.Engine;
028:
029: /**
030: * Performs analysis for the visistor.
031: * @author Marco Yuen
032: */
033: public class AspectFunctionAnalyzer {
034:
035: /** The XForm engine */
036: private Engine engine;
037:
038: /** Flag to determine whether there is a before advice. */
039: private boolean hasBefore = false;
040:
041: /** Flag to determine whether there is a after advice. */
042: private boolean hasAfter = false;
043:
044: /** Flag to determine whether there is a around advice. */
045: private boolean hasAround = false;
046:
047: /** The GNode to analyzed. */
048: private GNode functionNode = null;
049:
050: /** A list of before advice. */
051: private ArrayList beforeAdvice = null;
052:
053: /** The GNode of AspectStatementList (Before). */
054: private GNode beforeAdviceNode = null;
055:
056: /** A list of after advice. */
057: private ArrayList afterAdvice = null;
058:
059: /** The GNode of AspectStatementList (After).*/
060: private GNode afterAdviceNode = null;
061:
062: /** THe list of around advice. */
063: private ArrayList aroundAdvice = null;
064:
065: /** The Statement in the function body. */
066: private ArrayList functionBody = null;
067:
068: /**
069: * The constructor.
070: *
071: * @param n a reference to the function being analyzed.
072: */
073: public AspectFunctionAnalyzer(GNode n) {
074: engine = new Engine();
075: this .functionNode = n;
076: this .beforeAdvice = new ArrayList();
077: this .afterAdvice = new ArrayList();
078: this .aroundAdvice = new ArrayList();
079: this .functionBody = new ArrayList();
080: }
081:
082: /**
083: * Start the analysis on the aspect function.
084: *
085: */
086: public void analyze() {
087: List results;
088:
089: //System.out.println("Starting to Analyze ...");
090: if (null == functionNode)
091: throw new AssertionError("functionNode is NULL.");
092:
093: // Get the AspectStatementList's.
094: Query aspectStatmList = new Query("//AspectStatementList");
095: results = engine.run(aspectStatmList, functionNode);
096:
097: // Analyze before advice
098: beforeAdviceNode = (GNode) results.get(0);
099: if (beforeAdviceNode.size() > 0)
100: hasBefore = true;
101: for (Iterator beIt = beforeAdviceNode.iterator(); beIt
102: .hasNext();) {
103: GNode n = (GNode) beIt.next();
104: beforeAdvice.add(n.getString(1));
105: }
106:
107: //Analyze after advice
108: afterAdviceNode = (GNode) results.get(1);
109: if (afterAdviceNode.size() > 0)
110: hasAfter = true;
111: for (Iterator afIt = afterAdviceNode.iterator(); afIt.hasNext();) {
112: GNode n = (GNode) afIt.next();
113: afterAdvice.add(n.getString(1));
114:
115: // Recording around advice.
116: if (beforeAdvice.contains(n.getString(1))) {
117: hasAround = true;
118: aroundAdvice.add(n.getString(1));
119: }
120: }
121:
122: // Capturing the body.
123: GNode aspectCompound = (GNode) functionNode.get(4); // I may use XForm here.
124: for (Iterator bodyIt = aspectCompound.iterator(); bodyIt
125: .hasNext();) {
126: GNode n = (GNode) bodyIt.next();
127: if (null != n) {
128: if (n.hasName("AspectStatementList"))
129: continue;
130: functionBody.add(n);
131: }
132: }
133: }
134:
135: /**
136: * Determine if there is before advice
137: *
138: * @return True, there is before advice.
139: */
140: public boolean hasBefore() {
141:
142: return this .hasBefore;
143: }
144:
145: /**
146: * Get all of the before advice.
147: *
148: * @return A reference to all of the before advice of the current function.
149: */
150: public GNode getBefore() {
151:
152: return this .beforeAdviceNode;
153: }
154:
155: /**
156: * Extract the function body from a aspect function.
157: *
158: * @return A list of statements in the funciton body.
159: */
160: public ArrayList getBody() {
161:
162: return this .functionBody;
163: }
164:
165: /**
166: * Determine if there is after advice.
167: *
168: * @return Ture if there is at least one after advice. False, otherwise.
169: */
170: public boolean hasAfter() {
171:
172: return this .hasAfter;
173: }
174:
175: /**
176: * Extract all the after advice for transformation.
177: *
178: * @return The after AspectStatementList
179: */
180: public GNode getAfter() {
181:
182: return this .afterAdviceNode;
183: }
184:
185: /**
186: * Check if there is around advice in the current function
187: *
188: * @return True if there is an around advice detected.
189: */
190: public boolean hasAround() {
191:
192: return this .hasAround;
193: }
194:
195: /**
196: * Check if the specificed advice name is an around advice.
197: *
198: * @param name The aspect name.
199: * @return True, if the given aspect name is an around advice.
200: */
201: public boolean isAround(String name) {
202:
203: return aroundAdvice.contains(name);
204: }
205: }
|