0001: /*
0002: * xtc - The eXTensible Compiler
0003: * Copyright (C) 2005-2006 Princeton University
0004: *
0005: * This program is free software; you can redistribute it and/or
0006: * modify it under the terms of the GNU General Public License
0007: * version 2 as published by the Free Software Foundation.
0008: *
0009: * This program is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: * GNU General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU General Public License
0015: * along with this program; if not, write to the Free Software
0016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
0017: * USA.
0018: */
0019: package xtc.lang.c4;
0020:
0021: import xtc.tree.GNode;
0022:
0023: import java.util.ArrayList;
0024: import java.util.HashMap;
0025: import java.util.Iterator;
0026: import java.util.List;
0027:
0028: import xtc.xform.Query;
0029: import xtc.xform.Engine;
0030:
0031: import java.lang.reflect.InvocationTargetException;
0032: import java.lang.reflect.Method;
0033:
0034: /**
0035: * Transforms Aspect constructs to pure C code.
0036: *
0037: * @author Marco Yuen
0038: */
0039: public class AspectTransformer {
0040: /** The root of the AST to be transformed. */
0041: private GNode root = null;
0042:
0043: /** A list of names of the aspect nodes */
0044: private ArrayList aspectList = null;
0045:
0046: /** A XForm engine */
0047: private Engine engine = null;
0048:
0049: /** A bindings of names and mangled names */
0050: private HashMap bindings = null;
0051:
0052: /**
0053: * Global variable that indicates the name of the
0054: * aspect that's being transformed.
0055: */
0056: private String curAspectName = null;
0057:
0058: /** The counter for creating unique label statements. */
0059: private static int uniqueLabelCounter = 0;
0060:
0061: /**
0062: * Creates an AspectTransformer.
0063: *
0064: * @param r The root node
0065: */
0066: public AspectTransformer(GNode r) {
0067: this .root = r;
0068: this .engine = new Engine();
0069: bindings = new HashMap();
0070:
0071: // Create a list of node names that need to be transformed.
0072: this .aspectList = new ArrayList();
0073: this .aspectList.add("AspectDefinition");
0074: this .aspectList.add("AspectStructureDeclaration");
0075: this .aspectList.add("AspectFunctionDefinition");
0076: };
0077:
0078: /**
0079: * A dispatcher.
0080: * @param name The name of the method.
0081: * @param args Arguments for the method.
0082: * @param argValues Values of the arguments.
0083: */
0084: public Object process(String name, Class[] args, Object[] argValues) {
0085: try {
0086: Method m = getClass().getMethod(name, args);
0087: return m.invoke(this , argValues);
0088: } catch (SecurityException e) {
0089: e.printStackTrace();
0090: } catch (NoSuchMethodException e) {
0091: e.printStackTrace();
0092: } catch (IllegalArgumentException e) {
0093: e.printStackTrace();
0094: } catch (IllegalAccessException e) {
0095: e.printStackTrace();
0096: } catch (InvocationTargetException e) {
0097: e.printStackTrace();
0098: }
0099: return null;
0100: }
0101:
0102: /**
0103: * Based on the current GNode name, and dispatch the correct
0104: * method to perform a tranfomation on the GNode.
0105: */
0106: public void transform() {
0107: List result = null;
0108: Query query = null;
0109: for (Iterator i = aspectList.iterator(); i.hasNext();) {
0110: String aspectNodeName = (String) i.next();
0111: if (!aspectNodeName.equals("AspectStructureDeclaration"))
0112: query = new Query("//" + aspectNodeName);
0113: else
0114: query = new Query("//" + aspectNodeName
0115: + "/../../../../..");
0116: result = engine.run(query, root);
0117:
0118: // Invoke the method with name "process"+aspectNodeName.
0119: if (!result.isEmpty()) {
0120: process("process" + aspectNodeName,
0121: new Class[] { List.class },
0122: new Object[] { result });
0123: }
0124: }
0125: }
0126:
0127: // -------------------------------------------------------------------------
0128: // Utility Functions
0129: // -------------------------------------------------------------------------
0130:
0131: /**
0132: * Return the declarator of a node.
0133: *
0134: * @param n The node.
0135: */
0136: private String getSimpleDeclarator(GNode n) {
0137: if (null == n)
0138: return null;
0139: Query simpleDeclarator = new Query("//SimpleDeclarator");
0140: List result = engine.run(simpleDeclarator, n);
0141: if (result.size() <= 0)
0142: return null;
0143: else
0144: return ((GNode) result.get(0)).getString(0);
0145: }
0146:
0147: /**
0148: * Mangle the names in declarations.
0149: *
0150: * @param n The node to be mangled.
0151: * @param prefix The string that prepend to the name.
0152: */
0153: private void changeDeclarator(GNode n, String prefix) {
0154: boolean structUnion = false;
0155: Query simpleQuery = new Query("//SimpleDeclarator");
0156: Query structQuery = new Query(
0157: "/DeclarationSpecifiers/StructureTypeDefinition/../..");
0158: Query unionQuery = new Query(
0159: "/DeclarationSpecifiers/UnionTypeDefinition/../..");
0160:
0161: List result = engine.run(structQuery, n);
0162: if (result.size() > 0)
0163: structUnion = true;
0164: else {
0165: result = engine.run(unionQuery, n);
0166: if (result.size() > 0)
0167: structUnion = true;
0168: }
0169:
0170: if (structUnion) {
0171: GNode decl = (GNode) result.get(0);
0172: GNode structTypeDef = decl.getGeneric(1).getGeneric(0);
0173: String structTag = structTypeDef.getString(1);
0174: if (null != structTag) {
0175: structTypeDef.set(1, prefix + structTag);
0176: ((HashMap) bindings.get(curAspectName)).put("struct "
0177: + structTag, prefix + structTag);
0178: }
0179:
0180: GNode initDeclaratorList = decl.getGeneric(2);
0181: if (initDeclaratorList != null) {
0182: result = engine.run(simpleQuery, initDeclaratorList);
0183: GNode simpleDecl = (GNode) result.get(0);
0184: ((HashMap) bindings.get(curAspectName))
0185: .put(simpleDecl.getString(0), prefix
0186: + simpleDecl.getString(0));
0187: simpleDecl.set(0, prefix + simpleDecl.getString(0));
0188: }
0189: return;
0190: }
0191:
0192: result = engine.run(simpleQuery, n);
0193: GNode simpleDecl = (GNode) result.get(0);
0194: ((HashMap) bindings.get(curAspectName)).put(simpleDecl
0195: .getString(0), prefix + simpleDecl.getString(0));
0196: simpleDecl.set(0, prefix + simpleDecl.getString(0));
0197: }
0198:
0199: /**
0200: * Determine if a function has a void return type or not.
0201: *
0202: * @param declSpec The DeclarationSpecifier of FunctionDefinition.
0203: */
0204: private boolean isReturnVoid(GNode declSpec) {
0205: if (null != declSpec) {
0206: Query q = new Query("//VoidTypeSpecifier");
0207: List result = engine.run(q, declSpec);
0208: if (result.isEmpty())
0209: return false;
0210: else
0211: return true;
0212: }
0213: return false;
0214: }
0215:
0216: /**
0217: * This function manages the mangling of names for aspect introduction.
0218: *
0219: * @param n The node that contains a primary identifier.
0220: */
0221: private void replacePriID(GNode n) {
0222: HashMap symbols = (HashMap) bindings.get(curAspectName);
0223: ArrayList structSyms = (ArrayList) bindings.get("struct"
0224: + curAspectName);
0225: List results = null;
0226: Iterator reIt = null;
0227:
0228: Query priIDQuery = new Query("//PrimaryIdentifier");
0229: Query structTypeRef = new Query(
0230: "/DeclarationSpecifiers/StructureTypeReference/../..");
0231: Query typeDefName = new Query("//TypedefName");
0232: Query directCompSel = new Query("//DirectComponentSelection");
0233: Query indirectCompSel = new Query(
0234: "//IndirectComponentSelection");
0235:
0236: results = engine.run(structTypeRef, n);
0237: if (results.size() > 0) {
0238: GNode declaration = (GNode) results.get(0);
0239: GNode structDecl = declaration.getGeneric(1).getGeneric(0);
0240: GNode initDeclList = declaration.getGeneric(2);
0241: /*System.out.println("-------> " + structDecl.getName());*/
0242: if (symbols
0243: .containsKey("struct " + structDecl.getString(1))) {
0244: structDecl.set(1, symbols.get("struct "
0245: + structDecl.getString(1)));
0246: }
0247: // if key is in symbol table -> this struct has an advice in it.
0248: if (symbols.containsKey("field_struct_tag "
0249: + structDecl.getString(1))) {
0250: if (null == initDeclList) {
0251: System.err.println("initDeclList is null!?");
0252: System.exit(1);
0253: }
0254: String decltor = getSimpleDeclarator(initDeclList);
0255: Object val = symbols.get("field_struct_tag "
0256: + structDecl.getString(1));
0257: symbols.put("field_struct " + decltor, val);
0258: }
0259:
0260: //System.out.println("------- Symbol Table -------\n" + bindings + "\n------- Symbol Table -------");
0261: }
0262:
0263: results = engine.run(priIDQuery, n);
0264: for (reIt = results.iterator(); reIt.hasNext();) {
0265: GNode priID = (GNode) reIt.next();
0266: //System.out.println("priID: " + priID.getString(0));
0267: if (null != symbols
0268: && symbols.containsKey(priID.getString(0))) {
0269: //System.out.println("-------> Find a match in symbols table." + priID.getString(0));
0270: priID.set(0, symbols.get(priID.getString(0)));
0271: }
0272: }
0273:
0274: results = engine.run(typeDefName, n);
0275: for (reIt = results.iterator(); reIt.hasNext();) {
0276: GNode typedefName = (GNode) reIt.next();
0277: if (symbols.containsKey(typedefName.getString(0))) {
0278: typedefName.set(0, symbols
0279: .get(typedefName.getString(0)));
0280: }
0281: }
0282:
0283: results = engine.run(directCompSel, n);
0284: if (results.size() > 0) {
0285: GNode leftMost = (GNode) results.get(results.size() - 1);
0286: String structName = leftMost.getGeneric(0).getString(0);
0287: if (symbols.containsKey("field_struct " + structName)) {
0288: ArrayList fields = (ArrayList) symbols
0289: .get("field_struct " + structName);
0290: if (fields.contains(leftMost.getString(1))) {
0291: leftMost.set(0, makeDirectComponentSel(leftMost
0292: .getGeneric(0), curAspectName));
0293: }
0294: }
0295: }
0296:
0297: results = engine.run(indirectCompSel, n);
0298: if (results.size() > 0) {
0299: GNode leftMost = (GNode) results.get(results.size() - 1);
0300: String structName = leftMost.getGeneric(0).getString(0);
0301: if (symbols.containsKey("field_struct " + structName)) {
0302: ArrayList fields = (ArrayList) symbols
0303: .get("field_struct " + structName);
0304: if (fields.contains(leftMost.getString(1))) {
0305: leftMost.set(0, makeIndirectComponentSel(leftMost
0306: .getGeneric(0), curAspectName));
0307: }
0308: }
0309: }
0310: }
0311:
0312: // -------------------------------------------------------------------------
0313: // Nodes
0314: // -------------------------------------------------------------------------
0315:
0316: /**
0317: * Create a structure field access statement. (eg. sturctname.field)
0318: *
0319: * @param PriID The struct name.
0320: * @param fieldName The field name.
0321: */
0322: public GNode makeDirectComponentSel(GNode PriID, String fieldName) {
0323: return GNode.create("DirectComponentSelection", PriID,
0324: fieldName);
0325: }
0326:
0327: /**
0328: * Create a structure field access with a pointer. (eg. structname->field)
0329: *
0330: * @param PriID The struct name.
0331: * @param fieldName The field name.
0332: */
0333: public GNode makeIndirectComponentSel(GNode PriID, String fieldName) {
0334: return GNode.create("IndirectComponentSelection", PriID,
0335: fieldName);
0336: }
0337:
0338: /**
0339: * Create a assignment.
0340: *
0341: * @param id The left hand value.
0342: * @param val The right hand value.
0343: */
0344: public GNode makeAssignment(String id, GNode val) {
0345: return GNode.create("AssignmentExpression", GNode.create(
0346: "PrimaryIdentifier", id), "=", val);
0347: }
0348:
0349: /**
0350: * Create a goto statement.
0351: *
0352: * @param label The label to jump to.
0353: */
0354: public GNode makeGoto(String label) {
0355: return GNode.create("GotoStatement", label);
0356: }
0357:
0358: /**
0359: * Create a goto statement. However, instead of using a label
0360: * as the arugment, it uses a variable (eg. goto *var).
0361: * This is a GCC extension.
0362: *
0363: * @param label The name of the label variable.
0364: * @return A goto statement.
0365: */
0366: public GNode makeGotoWithAddress(String label) {
0367: return GNode.create("GotoStatement", GNode.create(
0368: "PrimaryIdentifier", label));
0369: }
0370:
0371: /**
0372: * Create a label.
0373: *
0374: * @param label The label name.
0375: * @param stmt Statements associate with that label.
0376: * @return A label in C.
0377: */
0378: public GNode makeLabel(String label, GNode stmt) {
0379: return GNode.create("LabeledStatement", GNode.create(
0380: "NamedLabel", label, null), stmt);
0381: }
0382:
0383: /**
0384: * Create a do-while loop.
0385: *
0386: * @param stmts The statemenst inside the do-while loop.
0387: * @param condition The invariant for the do-while loop.
0388: * @return A do-while loop construct.
0389: */
0390: public GNode makeDoStmt(GNode stmts, GNode condition) {
0391: if (null == stmts)
0392: stmts = GNode.create("CompoundStatement", null);
0393: return GNode.create("DoStatement", stmts, condition);
0394: }
0395:
0396: /**
0397: * Create a return statement.
0398: *
0399: * @param val The return value.
0400: * @return A return statement with the specified value.
0401: */
0402: public GNode makeReturn(GNode val) {
0403: return GNode.create("ReturnStatement", val);
0404: }
0405:
0406: /**
0407: * Create a structure declaration.
0408: *
0409: * @param type The Qualifier for the structure.
0410: * @param decl The name of the structure.
0411: * @return A sturct declaration with all the fields declared.
0412: */
0413: public GNode makeStructureDeclaration(GNode type, String decl) {
0414: GNode structDecl = GNode.create("StructureDeclaration");
0415: GNode specQualList = GNode.create("SpecifierQualifierList");
0416: GNode declarator = GNode.create("StructureDeclarationList");
0417: GNode attrDecl = GNode.create("AttributedDeclarator");
0418:
0419: attrDecl.add(null);
0420: attrDecl.add(GNode.create("SimpleDeclarator").add(decl));
0421: attrDecl.add(null);
0422: declarator.add(attrDecl);
0423:
0424: specQualList.add(type);
0425:
0426: structDecl.add(null);
0427: structDecl.add(specQualList);
0428: structDecl.add(declarator);
0429:
0430: return structDecl;
0431: }
0432:
0433: /**
0434: * Create a declaration.
0435: *
0436: * @param declSpecifier The type and qualifier for the declaration.
0437: * @param declarator The declarator for the declaration.
0438: * @return A declaration with the specificed type and name.
0439: */
0440: public GNode makeDeclaration(GNode declSpecifier, String declarator) {
0441: GNode initDeclList = GNode.create("InitializedDeclaratorList");
0442: GNode initDecl = GNode.create("InitializedDeclarator");
0443: GNode simpleDecl = GNode.create("SimpleDeclarator", declarator);
0444:
0445: // Create the InitializedDeclarator
0446: initDecl.add(null);
0447: initDecl.add(simpleDecl);
0448: initDecl.add(null);
0449: initDecl.add(null);
0450: initDecl.add(null);
0451:
0452: // Add it to InitializedDeclaratorList
0453: initDeclList.add(initDecl);
0454:
0455: GNode decl = GNode.create("Declaration");
0456: decl.add(null); // No __extension__
0457: decl.add(declSpecifier); // Type
0458: decl.add(initDeclList); // Declarator
0459:
0460: return decl;
0461: }
0462:
0463: /**
0464: * Create a declataion with initializer.
0465: *
0466: * @param declSpecifier The type.
0467: * @param initDeclarator The initialzier.
0468: * @return A declaration.
0469: */
0470: public GNode makeDeclaration(GNode declSpecifier,
0471: GNode initDeclarator) {
0472: GNode decl = GNode.create("Declaration");
0473: GNode initDeclList = GNode.create("InitializedDeclaratorList");
0474:
0475: initDeclList.add(initDeclarator);
0476:
0477: decl.add(null);
0478: decl.add(declSpecifier);
0479: decl.add(initDeclList);
0480: return decl;
0481: }
0482:
0483: /**
0484: * Create a structure definition.
0485: *
0486: * @param structTag The struct tag. Optional.
0487: * @param beforeAttrs The attributes. Optional.
0488: * @param declList The fields declaration.
0489: * @param afterAttrs The attributes. Optional.
0490: * @return A complete structure.
0491: */
0492: public GNode makeStructure(String structTag, GNode beforeAttrs,
0493: GNode declList, GNode afterAttrs) {
0494: GNode structure = GNode.create("StructureTypeDefinition");
0495: // Attributes
0496: if (null == beforeAttrs)
0497: structure.add(null);
0498: else
0499: structure.add(beforeAttrs);
0500:
0501: // Structure tag
0502: if (null == structTag)
0503: structure.add(null);
0504: else
0505: structure.add(structTag);
0506:
0507: // StructureDeclarationList
0508: GNode structDecl = null;
0509: structure.add(declList);
0510:
0511: // Attributes
0512: if (null == afterAttrs)
0513: structure.add(null);
0514: else
0515: structure.add(afterAttrs);
0516:
0517: return structure;
0518: }
0519:
0520: /**
0521: * Create a LabelAddressExpression.
0522: *
0523: * @param label The label.
0524: * @return A GNode LabelAddressExpression.
0525: */
0526: public GNode makeLabelAddressExpression(String label) {
0527: return GNode.create("LabelAddressExpression", label);
0528: }
0529:
0530: /**
0531: * Create a identifier with pointers.
0532: *
0533: * @param numPointer
0534: * @param declarator
0535: * @return A GNode for pointer.
0536: */
0537: public GNode makePointerDeclarator(int numPointer, String declarator) {
0538: GNode pointerDecl = GNode.create("PointerDeclarator");
0539: GNode pointer = (GNode) GNode.create("Pointer").add(
0540: GNode.create("TypeQualifierList")).add(null);
0541: GNode tmpPointer = pointer, newPointer = null;
0542:
0543: for (int i = 1; i < numPointer; ++i) {
0544: newPointer = (GNode) GNode.create("Pointer").add(
0545: GNode.create("TypeQualifierList")).add(null);
0546: tmpPointer.set(1, newPointer);
0547: tmpPointer = newPointer;
0548: }
0549:
0550: pointerDecl.add(pointer);
0551: pointerDecl.add(GNode.create("SimpleDeclarator")
0552: .add(declarator));
0553:
0554: return pointerDecl;
0555: }
0556:
0557: // -------------------------------------------------------------------------
0558: // Aspect Nodes Transformation
0559: // -------------------------------------------------------------------------
0560:
0561: /**
0562: * Transform a global advice to C code.
0563: *
0564: * @param nodes The list of AspectDefinition nodes.
0565: */
0566: public void processAspectDefinition(List nodes) {
0567: String prefix = null;
0568: int cnt = 0;
0569: ArrayList declList = null;
0570:
0571: for (int i = 0; i < root.size(); ++i) {
0572: GNode n = root.getGeneric(i);
0573: declList = new ArrayList();
0574: if (null != n && n.hasName("AspectDefinition")) {
0575: curAspectName = n.getString(1);
0576: // Create a binding table for this aspect.
0577: if (!bindings.containsKey(curAspectName)) {
0578: bindings.put(curAspectName, new HashMap());
0579: }
0580: prefix = "__aspect__" + curAspectName + "__";
0581: GNode declFuncDef = n.getGeneric(2);
0582: // Process the declarations and function definitions
0583: for (int j = 2; j < n.size(); ++j) {
0584: GNode decl = (GNode) n.get(j);
0585: changeDeclarator(decl, prefix);
0586: declList.add(decl);
0587: }
0588:
0589: root.remove(i);
0590: root.addAll(i, declList);
0591: ++cnt;
0592: }
0593: }
0594:
0595: if (cnt != nodes.size()) {
0596: System.err.println("cnt != nodes.size()");
0597: System.exit(1);
0598: }
0599: }
0600:
0601: /**
0602: * Transfrom struct or union introduction into C code.
0603: *
0604: * @param nodes The list of introduction nodes.
0605: */
0606: public void processAspectStructureDeclaration(List nodes) {
0607: //System.out.println("-------> Process AspectStructSpecifier");
0608: Query q = null;
0609: Query simpleDeclQuery = new Query("//SimpleDeclarator");
0610: List result = null;
0611: ArrayList fieldsVec = new ArrayList();
0612: for (Iterator i = nodes.iterator(); i.hasNext();) {
0613: GNode declaration = (GNode) i.next();
0614: //System.out.println("-------> " + declaration.getName());
0615: GNode structTypeDef = declaration.getGeneric(1).getGeneric(
0616: 0);
0617: String structTag = structTypeDef.getString(1);
0618: //System.out.println("-------> " + structTypeDef.getName());
0619: //System.out.println("\t\tStructure's Tag: " + structTag);
0620: GNode structDeclList = structTypeDef.getGeneric(2); // StructureDeclarationList
0621: GNode structDeclaration = null;
0622: GNode initDeclList = declaration.getGeneric(2);
0623:
0624: for (int j = 0; j < structDeclList.size(); ++j) {
0625: GNode structDecl = (GNode) structDeclList.get(j);
0626: if (null != structDecl) {
0627: //System.out.println("\t\t" + structDecl.getName());
0628: GNode declSpec = structDecl.getGeneric(1);
0629: //System.out.println("\t\t" + declSpec.getName());
0630: if (declSpec.hasName("AspectStructureDeclaration")) {
0631: curAspectName = declSpec.getString(1);
0632: if (!bindings.containsKey(curAspectName)) {
0633: bindings.put(curAspectName, new HashMap());
0634: }
0635: GNode A_StructDeclList = declSpec.getGeneric(2); // StructureDeclarationList
0636: //System.out.println("-------> " + A_StructDeclList.getName());
0637: result = engine.run(simpleDeclQuery,
0638: A_StructDeclList);
0639: for (Iterator simpleDecl = result.iterator(); simpleDecl
0640: .hasNext();) {
0641: GNode simDeclNode = (GNode) simpleDecl
0642: .next();
0643: fieldsVec.add(simDeclNode.getString(0));
0644: //((ArrayList)bindings.get(curAspectName)).add("field:" + simDeclNode.getString(0));
0645: }
0646: structDeclaration = makeStructureDeclaration(
0647: makeStructure(null, null,
0648: A_StructDeclList, null),
0649: declSpec.getString(1));
0650: structDeclList.set(j, structDeclaration);
0651: }
0652: }
0653: }
0654:
0655: ((HashMap) bindings.get(curAspectName)).put(
0656: "field_struct_tag " + structTag, fieldsVec);
0657: if (null != initDeclList) {
0658: for (Iterator it = initDeclList.iterator(); it
0659: .hasNext();) {
0660: GNode initDecl = (GNode) it.next();
0661: ((HashMap) bindings.get(curAspectName)).put(
0662: "field_struct "
0663: + getSimpleDeclarator(initDecl),
0664: fieldsVec);
0665: }
0666: }
0667: }
0668: }
0669:
0670: /**
0671: * Transform AspectFunctionDefinition to C code.
0672: *
0673: * @param nodes
0674: */
0675: public void processAspectFunctionDefinition(List nodes) {
0676: AspectFunctionAnalyzer funcAnalyzer = new AspectFunctionAnalyzer(
0677: (GNode) nodes.get(0));
0678: funcAnalyzer.analyze();
0679:
0680: boolean isAround = false, returnVoid = false, printReturn = false, hasAround = false, bodyBegin = false;
0681: ArrayList aroundList = new ArrayList();
0682: Query proceedCheck = new Query(
0683: "//FunctionCall/PrimaryIdentifier/\"proceed\"");
0684: Query simpleDecl = new Query("//SimpleDeclarator");
0685: List result = null;
0686: String functionName = "", nodeName = "";
0687: hasAround = funcAnalyzer.hasAround();
0688: //System.out.println("AspectFunctionDefinition ------->");
0689:
0690: /*
0691: * XXX: To make this more clean. I will probably need to change the grammar and use
0692: * the inside-out operator from XForm.
0693: * Search for AspectFunctionDefinition in the root level.
0694: * If found, do the transfromation. Then, replace AspectFunctionDefinition
0695: * with FunctionDefinition.
0696: */
0697: for (int nodeInx = 0; nodeInx < root.size(); ++nodeInx) {
0698: boolean gotReturn = false, gotProceed = false;
0699:
0700: GNode node = root.getGeneric(nodeInx);
0701: if (null == node
0702: || !node.hasName("AspectFunctionDefinition"))
0703: continue;
0704:
0705: GNode returnType = node.getGeneric(1);
0706: //System.out.println("Return Type:" + returnType.getName());
0707: returnVoid = isReturnVoid(returnType);
0708:
0709: GNode paramList = node.getGeneric(2).getGeneric(1);
0710: //System.out.println("Parameter List: " + paramList.getName());
0711:
0712: GNode aspectCompound = (GNode) node.get(4);
0713: //System.out.println("Compound: " + aspectCompound.getName());
0714:
0715: // The node that will eventually replace AspectCompoundStatement.
0716: GNode replacementNode = GNode.create("CompoundStatement");
0717:
0718: GNode beforeAReturnVal = null;
0719:
0720: // >>>> ----------------------- Declaring __returned__
0721: // Declare __returned__ if the return type is non-void.
0722: if (!(returnVoid)) {
0723: // System.out.println("-------> Non-void return type.");
0724: // proxyNode = GNode.create("CompoundStatement");
0725: replacementNode.add(makeDeclaration(returnType,
0726: "__returned__"));
0727: }
0728: // <<<< ----------------------- Declaring __returned__ END
0729:
0730: // >>>> ----------------------- Declaring void *gotoDest
0731: if (hasAround) {
0732: GNode initDecl = GNode.create("InitializedDeclarator");
0733: for (int i = 0; i < 5; ++i) {
0734: initDecl.add(null);
0735: }
0736: initDecl.set(1, makePointerDeclarator(1, "gotoDest"));
0737: replacementNode.add(makeDeclaration(GNode.create(
0738: "VoidTypeSpecifier", false), initDecl));
0739: }
0740: // <<<< ----------------------- Declaring void *gotoDest END
0741:
0742: // >>>> ----------------------- Transforming Before Advice
0743: if (funcAnalyzer.hasBefore()) {
0744: GNode aspectStmtList = funcAnalyzer.getBefore();
0745:
0746: // Convert AspectStatement in AspectStmtList to CompoundStatement's.
0747: for (Iterator aclIt = aspectStmtList.iterator(); aclIt
0748: .hasNext();) {
0749: GNode tmpCompound = GNode
0750: .create("CompoundStatement");
0751: GNode aspectStmt = (GNode) aclIt.next();
0752: curAspectName = aspectStmt.getString(1);
0753: //result = engine.run(proceedCheck, aspectStmt);
0754: if (funcAnalyzer.isAround(curAspectName)) {
0755: isAround = true;
0756: aroundList.add(curAspectName);
0757: }
0758:
0759: // System.out.println("-------> Processing (Before)" + aspectStmt.getString(1));
0760:
0761: // Skip the Keyword and aspect name, and copy all the declarations or
0762: // expressions over to tmpCompound.
0763:
0764: for (int i = 2; i < aspectStmt.size(); ++i) {
0765: GNode tmp = (GNode) aspectStmt.get(i);
0766: //System.out.println("-------> Adding " + tmp.getName());
0767:
0768: // Set a label. Perseve advice order.
0769: if (bodyBegin) {
0770: bodyBegin = false;
0771: tmpCompound.add(makeLabel("__body_begin",
0772: null));
0773: }
0774:
0775: // XXX I need to revamp this sometime in the future. Suggestions on improvements are VERY welcome :)
0776: result = engine
0777: .run(
0778: new Query(
0779: "//FunctionCall/PrimaryIdentifier/\"proceed\"/../../.."),
0780: tmp);
0781: //System.out.println("Result: " + result.size());
0782: //if(tmp.hasName("ExpressionStatement") && tmp.getGeneric(0).hasName("FunctionCall")
0783: // && tmp.getGeneric(0).getGeneric(0).getString(0).equals("proceed") && isAround) {
0784: if (isAround && result.size() > 0) {
0785: for (Iterator it = result.iterator(); it
0786: .hasNext();) {
0787: GNode expStmt = (GNode) it.next();
0788: //System.out.println("expStmt: " + expStmt.getName());
0789: //System.out.println("tmp: " + tmp.getName());
0790:
0791: gotProceed = true;
0792: if (tmp.hasName("ExpressionStatement")) {
0793: GNode expressionList = tmp
0794: .getGeneric(0)
0795: .getGeneric(1);
0796: List simResult = engine.run(
0797: simpleDecl, paramList);
0798: for (int paramInx = 0; paramInx < simResult
0799: .size(); ++paramInx) {
0800: GNode simpleDeclarator = (GNode) simResult
0801: .get(paramInx);
0802: tmpCompound
0803: .add(makeAssignment(
0804: simpleDeclarator
0805: .getString(0),
0806: expressionList
0807: .getGeneric(paramInx)));
0808: }
0809:
0810: tmpCompound
0811: .add(makeAssignment(
0812: "gotoDest",
0813: makeLabelAddressExpression("__"
0814: + curAspectName
0815: + "__return_point"
0816: + uniqueLabelCounter)));
0817:
0818: //Goto main body
0819: tmpCompound
0820: .add(makeGoto("__body_begin"));
0821:
0822: // Declare label
0823: tmpCompound.add(makeLabel("__"
0824: + curAspectName
0825: + "__return_point"
0826: + uniqueLabelCounter++,
0827: null));
0828: } else {
0829: List parResults = engine
0830: .run(
0831: new Query(
0832: "//FunctionCall/PrimaryIdentifier/\"proceed\"/../../../.."),
0833: tmp);
0834: //System.out.println("parResults size: " + parResults.size());
0835: for (Iterator pit = parResults
0836: .iterator(); pit.hasNext();) {
0837: ArrayList statements = new ArrayList();
0838: GNode parent = (GNode) pit
0839: .next();
0840: //System.out.println("parent: " + parent.getName());
0841: for (int j = 0; j < parent
0842: .size(); ++j) {
0843: GNode child = parent
0844: .getGeneric(j);
0845: //if(null != child && child.equals(expStmt)) {
0846: if (null != child
0847: && result
0848: .contains(child)) {
0849: GNode expressionList = child
0850: .getGeneric(0)
0851: .getGeneric(1);
0852: List simResult = engine
0853: .run(
0854: simpleDecl,
0855: paramList);
0856: for (int paramInx = 0; paramInx < simResult
0857: .size(); ++paramInx) {
0858: GNode simpleDeclarator = (GNode) simResult
0859: .get(paramInx);
0860: statements
0861: .add(makeAssignment(
0862: simpleDeclarator
0863: .getString(0),
0864: expressionList
0865: .getGeneric(paramInx)));
0866: }
0867:
0868: statements
0869: .add(makeAssignment(
0870: "gotoDest",
0871: makeLabelAddressExpression("__"
0872: + curAspectName
0873: + "__return_point"
0874: + uniqueLabelCounter)));
0875: statements
0876: .add(makeGoto("__body_begin"));
0877: statements
0878: .add(makeLabel(
0879: "__"
0880: + curAspectName
0881: + "__return_point"
0882: + uniqueLabelCounter++,
0883: null));
0884: parent.remove(j);
0885: parent.addAll(j,
0886: statements);
0887: }
0888: }
0889: }
0890:
0891: }
0892: }
0893: if (!tmp.hasName("ExpressionStatement"))
0894: tmpCompound.add(tmp);
0895: } else if (tmp.hasName("ReturnStatement")
0896: && isAround) {
0897: gotReturn = true;
0898: if (!gotProceed) {
0899: tmpCompound.add(makeGoto("__after_"
0900: + curAspectName
0901: + "__start_point"));
0902: tmpCompound.add(makeLabel("__"
0903: + curAspectName
0904: + "__return_point", null));
0905: }
0906: replacePriID(tmp);
0907: tmpCompound.add(tmp);
0908: } else {
0909: replacePriID(tmp);
0910: tmpCompound.add(tmp);
0911: }
0912: }
0913:
0914: // Make sure there is a return statement for around advice that instrument on non-void
0915: // return type function.
0916: if (isAround && !returnVoid && !gotReturn) {
0917: System.err
0918: .println("Missing return statement in before advice("
0919: + curAspectName
0920: + ") for non-void function.");
0921: System.exit(1);
0922: }
0923:
0924: // If the funciton has void return type, then jump to the end of the funciton.
0925: if (isAround && returnVoid) {
0926: if (!gotProceed) {
0927: tmpCompound.add(makeGoto("__after_"
0928: + curAspectName + "__start_point"));
0929: tmpCompound.add(makeLabel("__"
0930: + curAspectName + "__return_point",
0931: null));
0932: }
0933: tmpCompound.add(makeGoto("__return_point"));
0934: }
0935: if (isAround)
0936: bodyBegin = true;
0937: isAround = false;
0938: // No annotations.
0939: // tmpCompound.add(null);
0940: // Finally, add tmpCompound to replacementNode.
0941: replacementNode.add(tmpCompound);
0942: }
0943: }
0944: // <<<< ----------------------- Transforming Before Advice END
0945:
0946: // From here on now, proxyNode will either be an alias of replacementNode, or
0947: // a completely new node.
0948: GNode proxyNode = replacementNode;
0949:
0950: // body_begin label
0951: if (bodyBegin)
0952: proxyNode.add(makeLabel("__body_begin", null));
0953:
0954: // >>>> ----------------------- Transforming Body
0955: GNode returnVal = null;
0956: ArrayList body = funcAnalyzer.getBody();
0957: for (Iterator bodyIt = body.iterator(); bodyIt.hasNext();) {
0958: GNode tmp = (GNode) bodyIt.next();
0959:
0960: // Replace ReturnStatement (return __val__) with an Assignment __returned__ = __val__
0961: if (tmp.hasName("ReturnStatement")) {
0962: returnVal = tmp.getGeneric(0);
0963: // assignment
0964: if (!returnVoid)
0965: proxyNode.add(makeAssignment("__returned__",
0966: returnVal));
0967: else
0968: printReturn = true;
0969: // goto
0970: proxyNode.add(makeGoto("__aspects_done"));
0971: } else {
0972: proxyNode.add(tmp);
0973: }
0974: }
0975: // <<<< ----------------------- Transforming Body END
0976:
0977: // >>>> ----------------------- ASPECTS_AFTER_PROLOGE
0978: proxyNode.add(makeLabel("__aspects_done", makeDoStmt(null,
0979: GNode.create("IntegerConstant", "0"))));
0980: // <<<< ----------------------- ASPECTS_AFTER_PROLOGE END
0981:
0982: // >>>> ----------------------- Transforming After Advice
0983: if (funcAnalyzer.hasAfter()) {
0984: // System.out.println("-------> After advice(s) detected. Start processing ...");
0985: GNode aspectStmtList = funcAnalyzer.getAfter();
0986: for (Iterator aclIt = aspectStmtList.iterator(); aclIt
0987: .hasNext();) {
0988: GNode tmpCompound = GNode
0989: .create("CompoundStatement");
0990: GNode aspectStmt = (GNode) aclIt.next();
0991: curAspectName = aspectStmt.getString(1);
0992: if (aroundList.contains(curAspectName)) {
0993: aroundList.remove(curAspectName);
0994: isAround = true;
0995: }
0996:
0997: // Skip the Keyword and aspect name, and copy all the declarations or
0998: // expressions over to tmpCompound.
0999: if (isAround) {
1000: tmpCompound
1001: .add(makeLabel("__after_"
1002: + curAspectName
1003: + "__start_point", null));
1004: }
1005: for (int i = 2; i < aspectStmt.size(); ++i) {
1006: GNode tmp = (GNode) aspectStmt.get(i);
1007: result = engine.run(proceedCheck, tmp);
1008: if (result.size() > 0) {
1009: System.err
1010: .println("Calling proceed in after advice is not allowed.");
1011: System.exit(1);
1012: }
1013: // System.out.println("-------> Adding " + tmp.getName());
1014: replacePriID(tmp);
1015: if (tmp.hasName("ReturnStatement")) {
1016: GNode retVal = tmp.getGeneric(0);
1017: tmpCompound.add(makeAssignment(
1018: "__returned__", retVal));
1019: } else
1020: tmpCompound.add(tmp);
1021: }
1022: tmpCompound.add(makeGoto("__"
1023: + aspectStmt.getString(1) + "____out__"));
1024: //ASPECT_AFTER_END
1025: tmpCompound.add(makeLabel("__"
1026: + aspectStmt.getString(1) + "____out__",
1027: makeDoStmt(null, GNode.create(
1028: "IntegerConstant", "0"))));
1029:
1030: if (isAround) {
1031: //tmpCompound.add(makeGoto("__" + curAspectName + "__return_point"));
1032: tmpCompound
1033: .add(makeGotoWithAddress("gotoDest"));
1034: }
1035:
1036: isAround = false;
1037: // No annotations.
1038: // tmpCompound.add(null);
1039: // Finally, add tmpCompound to replacementNode.
1040: proxyNode.add(tmpCompound);
1041: }
1042: }
1043: // <<<< ----------------------- Transforming After Advice END
1044:
1045: // ASPECTS_AFTER_EPILOGUE
1046: proxyNode.add(makeLabel("__return_point", null));
1047: if (!returnVoid) {
1048: if (null != beforeAReturnVal)
1049: proxyNode.add(makeReturn(beforeAReturnVal));
1050: else
1051: proxyNode.add(makeReturn(GNode.create(
1052: "PrimaryIdentifier", "__returned__")));
1053: } else if (printReturn)
1054: proxyNode.add(makeReturn(null));
1055:
1056: if (!proxyNode.equals(replacementNode)) {
1057: //System.out.println("-------> Proxy node is different from replacement node.");
1058: // proxyNode.add(null);
1059: replacementNode.add(proxyNode);
1060: }
1061:
1062: // No annotations.
1063: // replacementNode.add(null);
1064: // Replacing AspectCompoundStatement with a CompoundStatement.
1065: node.set(4, replacementNode);
1066:
1067: // XXX
1068: // Replace node with a FunctionDefinition.
1069: GNode functionDef = GNode.create("FunctionDefinition");
1070: for (Iterator nodeIt = node.iterator(); nodeIt.hasNext();) {
1071: functionDef.add(nodeIt.next());
1072: }
1073:
1074: root.set(nodeInx, functionDef);
1075: // XXX
1076: }
1077:
1078: if (aroundList.size() != 0) {
1079: for (int i = 0; i < aroundList.size(); ++i)
1080: System.err.println("Missing after advice for: "
1081: + aroundList.get(i));
1082: System.exit(1);
1083: }
1084: }
1085: }
|