0001: /*
0002: * xtc - The eXTensible Compiler
0003: * Copyright (C) 2007 New York 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.typical;
0020:
0021: import java.util.List;
0022: import java.util.ArrayList;
0023: import java.util.HashMap;
0024: import java.util.Set;
0025:
0026: import xtc.tree.Comment;
0027: import xtc.tree.GNode;
0028: import xtc.tree.Visitor;
0029: import xtc.tree.Node;
0030:
0031: import xtc.util.SymbolTable;
0032: import xtc.util.Runtime;
0033: import xtc.util.Pair;
0034:
0035: /**
0036: * Visitor to translate Typical ASTs into Java ASTs.
0037: *
0038: * @author Laune Harris, Anh Le
0039: * @version $Revision: 1.372 $
0040: */
0041: public class Transformer extends Visitor {
0042:
0043: /** A Typical attribute. */
0044: static class Attribute {
0045:
0046: /** The name. */
0047: public String name;
0048:
0049: /** The type (as a type expression node). */
0050: public Node type;
0051:
0052: /**
0053: * Create a new attribute.
0054: *
0055: * @param name The name.
0056: * @param type The type.
0057: */
0058:
0059: Attribute(String name, Node type) {
0060: this .name = name;
0061: this .type = type;
0062: }
0063:
0064: }
0065:
0066: // =========================================================================
0067:
0068: /** A Typical equality definition. */
0069: static class Equality {
0070:
0071: /** The constructor name */
0072: public String name;
0073:
0074: /** The positions of the arguments to consider for equality. */
0075: public List<Integer> positions;
0076:
0077: /**
0078: * Create a new equality definition.
0079: *
0080: * @param name The constructor name.
0081: * @param positions The relevant positions.
0082: */
0083: Equality(String name, List<Integer> positions) {
0084: this .name = name;
0085: this .positions = positions;
0086: }
0087:
0088: }
0089:
0090: // =========================================================================
0091:
0092: /** A primitive operation instance class. */
0093: static class PrimitiveInstance {
0094:
0095: /** The name of the operation. */
0096: public String name;
0097:
0098: /** The specific types of the instance. */
0099: public List<String> types;
0100:
0101: /** The name of the instance. */
0102: public String instanceName;
0103:
0104: /**
0105: * Create a new primitive instance.
0106: *
0107: * @param name The name of the primitive operation
0108: * @param types The types of the instance
0109: */
0110: PrimitiveInstance(String name, List<String> types,
0111: String instanceName) {
0112: this .name = name;
0113: this .types = types;
0114: this .instanceName = instanceName;
0115: }
0116:
0117: }
0118:
0119: // =========================================================================
0120:
0121: /** Representation of a matching clause. */
0122: static class Match {
0123:
0124: /** The argument type. */
0125: private Object type;
0126:
0127: /** The condition on the argument. */
0128: private Node condition;
0129:
0130: /**
0131: * Create a new match.
0132: *
0133: * @param type The argument type.
0134: * @param condition The condition.
0135: */
0136: public Match(Object type, Node condition) {
0137: this .type = type;
0138: this .condition = condition;
0139: }
0140:
0141: public int hashCode() {
0142: return 0;
0143:
0144: }
0145:
0146: public boolean equals(Object o) {
0147: if (this == o)
0148: return true;
0149: if (!(o instanceof Match))
0150: return false;
0151:
0152: Match other = (Match) o;
0153: return (type.equals(other.type) && condition
0154: .equals(other.condition));
0155: }
0156:
0157: }
0158:
0159: // =========================================================================
0160:
0161: /** The type annotation name. */
0162: protected static final String TYPE = "__type";
0163:
0164: /** The property indicating the top level of a pattern. */
0165: protected static final String TOP = "top";
0166:
0167: /** The property indicating the right hand side of a binding. */
0168: protected static final String RHS = "rhs";
0169:
0170: /** The property representing the match argument. */
0171: protected static final String MATCHARG = "match_arg";
0172:
0173: /** The property representing the block contains the bindings argument. */
0174: protected static final String BINDINGS = "bindings";
0175:
0176: /** The annotation name to remember it is currently in analyze function. */
0177: protected static final String INANALYZE = "inAnalyze";
0178:
0179: /** The annotation name to indicate it is needed to process scope. */
0180: protected static final String SCOPE = "process_scope";
0181:
0182: /** The annotation name to indicate it is needed to annotate the node. */
0183: protected static final String ANNOTATE = "annotate_node";
0184:
0185: /** The tree factory. */
0186: protected final TreeFactory factory;
0187:
0188: /** The symbol table for this typical file. */
0189: protected final SymbolTable table;
0190:
0191: /** The root of the incoming typical abstract syntax tree. */
0192: protected final Node typical;
0193:
0194: /** The name of the node type. */
0195: protected final String nodeTypeName;
0196:
0197: /** The name of the checker to be output. */
0198: protected final String output;
0199:
0200: /** The root of the generated java ast for the type checker. */
0201: protected GNode transformed;
0202:
0203: /** The root of the types file. */
0204: protected GNode typesAST;
0205:
0206: /** The root of the support file. */
0207: protected GNode supportAST;
0208:
0209: /** The class body of the generated typechecker. */
0210: protected Node cbody;
0211:
0212: /** The class body of the types file. */
0213: protected Node tbody;
0214:
0215: /** The class body of the support file. */
0216: protected Node sbody;
0217:
0218: /** The type enumerations. */
0219: protected Node tags;
0220:
0221: /** This Transformers runtime. */
0222: protected final Runtime runtime;
0223:
0224: /** The cached variables. */
0225: protected final HashMap<Integer, String> typicalVars = new HashMap<Integer, String>();
0226:
0227: /** The Type mapper. */
0228: protected TypeMapper mapper;
0229:
0230: /** Flag indicating that a scope definition has been seen. */
0231: protected boolean seenScope = false;
0232:
0233: /** The set of seen match conditions */
0234: protected HashMap<Match, String> matches = new HashMap<Match, String>();
0235:
0236: /** The set of seen match conditions */
0237: protected HashMap<Node, String> nodeMatches = new HashMap<Node, String>();
0238:
0239: /** Empty modifier node. */
0240: final protected Node mod = GNode.create("Modifiers");
0241:
0242: /** Final modifier node. */
0243: final protected Node fmod = toModifiers("final");
0244:
0245: /** Public modifier node. */
0246: final protected Node pmod = toModifiers("public");
0247:
0248: /** Nullliteral node. */
0249: final protected Node nullNode = GNode.create("NullLiteral");
0250:
0251: /** Node type. */
0252: final protected Node nodeType = GNode.create("Type", GNode.create(
0253: "QualifiedIdentifier", "Node"), null);
0254: /** GNode type. */
0255: final protected Node gnodeType = GNode.create("Type", GNode.create(
0256: "QualifiedIdentifier", "GNode"), null);
0257:
0258: /** The list of field that go into the. */
0259: final protected List<Node> staticFields = new ArrayList<Node>();
0260:
0261: /** The list of function definitions. */
0262: final protected List<Node> functionDefinitions = new ArrayList<Node>();
0263:
0264: /** Flag indicating that a namespace declaration has been seen. */
0265: protected boolean seenNameSpace = false;
0266:
0267: /** A list to store all node names in scope definition. */
0268: protected ArrayList<String> processScopeNodes = new ArrayList<String>();
0269:
0270: /** List of equal structure. */
0271: protected ArrayList<Equality> equalities = new ArrayList<Equality>();
0272:
0273: /** The package name. */
0274: protected String packageName;
0275:
0276: /** The package node. */
0277: protected Node packageNode;
0278:
0279: /** A list to store all defined attributes. */
0280: protected List<Attribute> attributeList = new ArrayList<Attribute>();
0281:
0282: /** A list to store all defined equal attributes. */
0283: protected List<Attribute> eqAttributeList = new ArrayList<Attribute>();
0284:
0285: /** A variable to remember is type is optimized. */
0286: protected boolean replaceType;
0287:
0288: /** A variable to check if List is used. */
0289: private boolean isListUsed;
0290:
0291: /** A variable to check if ArrayList is used. */
0292: private boolean isArrayListUsed;
0293:
0294: /** A variable to check if BigInteger is used. */
0295: private boolean isBigIntegerUsed;
0296:
0297: /** A variable to check if Pair is used. */
0298: private boolean isPairUsed;
0299:
0300: /** A variable to check if Node is used. */
0301: private boolean isNodeUsed;
0302:
0303: /** A variable to check if GNode is used. */
0304: private boolean isGNodeUsed;
0305:
0306: /** A variable to check if Primitives is used. */
0307: private boolean isPrimitivesUsed;
0308:
0309: /** A variable to check if Record is used. */
0310: private boolean isRecordUsed;
0311:
0312: /** A variable to check if Variant is used. */
0313: private boolean isVariantUsed;
0314:
0315: /** A variable to check if Tuple is used. */
0316: private boolean isTupleUsed;
0317:
0318: /** A variable to check if Reduction is used. */
0319: private boolean isReductionUsed;
0320:
0321: /** A variable to check if Name is used. */
0322: private boolean isNameUsed;
0323:
0324: /** A variable to check if Scope is used. */
0325: private boolean isScopeUsed;
0326:
0327: /** A variable to check if ScopeKind is used. */
0328: private boolean isScopeKindUsed;
0329:
0330: /** A variable to check if Analyzer is used. */
0331: private boolean isAnalyzerUsed;
0332:
0333: /**
0334: * A list to store all declarations of
0335: * instances of primitive list operations.
0336: */
0337: protected List<Node> primitiveDeclList = new ArrayList<Node>();
0338:
0339: /** A list to store all primitive instances. */
0340: protected List<PrimitiveInstance> primitiveInsList = new ArrayList<PrimitiveInstance>();
0341:
0342: /** A list of types that are nodes. */
0343: protected Pair<String> nodeTypes = null;
0344:
0345: /**
0346: * Initialise this transformer.
0347: *
0348: * @param ast the root of the typical ast
0349: * @param s the name of the checker to be generated
0350: * @param runt the runtime
0351: */
0352: public Transformer(GNode ast, SymbolTable st, String s, Runtime runt) {
0353: factory = new TreeFactory();
0354: typical = ast;
0355: output = s;
0356: table = st;
0357: runtime = runt;
0358:
0359: // Set replaceType
0360: if (runtime.test("optimizeType"))
0361: replaceType = true;
0362:
0363: // Get the name of the node type
0364: String tempName = (String) runtime.getValue("optionNodeType");
0365: if (null == tempName)
0366: nodeTypeName = "node";
0367: else
0368: nodeTypeName = tempName;
0369:
0370: /* Process the module declaration. */
0371: dispatch(typical.getGeneric(0));
0372: cbody = makeClassBody();
0373: cbody = GNode.ensureVariable((GNode) cbody);
0374:
0375: tbody = GNode.create("ClassBody");
0376: tbody = GNode.ensureVariable((GNode) tbody);
0377:
0378: sbody = GNode.create("ClassBody");
0379: sbody = GNode.ensureVariable((GNode) sbody);
0380: }
0381:
0382: /**
0383: * Process the module.
0384: *
0385: * @param n The module node.
0386: */
0387: public void visitModule(GNode n) {
0388: boolean hasAttributes = false;
0389:
0390: final int size = n.size();
0391: for (int i = 0; i < size; i++) {
0392: Node node = n.getGeneric(i);
0393: if (node.hasName("AttributeDefinition")
0394: || node.hasName("EqualAttributeDefinition")) {
0395: hasAttributes = true;
0396: new TypeCollector().dispatch(node);
0397: } else if (node.hasName("NameSpaceDefinition")
0398: || (node.hasName("TypeDefinition") && "raw_type"
0399: .equals(node.getString(1)))) {
0400: new TypeCollector().dispatch(node);
0401: }
0402: }
0403:
0404: if (hasAttributes && replaceType) {
0405: replaceType = false;
0406: }
0407:
0408: // Get the list of types that are nodes
0409: @SuppressWarnings("unchecked")
0410: Object ob = n.getProperty("__node_types");
0411: Pair<String> nodeTypes = TypeMapper.getAnnotatedStringList(ob);
0412:
0413: mapper = new TypeMapper(runtime, output + "Types", replaceType,
0414: nodeTypes);
0415:
0416: /* Process attribute, equality, and namespaced definitions first. */
0417: for (int j = 0; j < size; j++) {
0418: Node node = n.getGeneric(j);
0419: if (node.hasName("AttributeDefinition")
0420: || node.hasName("EqualAttributeDefinition")
0421: || node.hasName("EqualityDefinition")
0422: || node.hasName("NameSpaceDefinition")) {
0423: dispatch(node);
0424: }
0425: }
0426:
0427: for (int i = 0; i < size; i++) {
0428: Node node = n.getGeneric(i);
0429:
0430: /* Skip the node, attribute, equality and namespace declarations. */
0431: if ((node.hasName("TypeDefinition") && nodeTypes
0432: .contains(node.getString(1)))
0433: || node.hasName("AttributeDefinition")
0434: || node.hasName("EqualAttributeDefinition")
0435: || node.hasName("EqualityDefinition")
0436: || node.hasName("NameSpaceDefinition")) {
0437: continue;
0438: }
0439:
0440: dispatch(node);
0441:
0442: if (node.hasName("TypeDefinition")
0443: && "raw_type".equals(node.getString(1))) {
0444: dispatch(processRawTypeDefinition());
0445: }
0446: }
0447:
0448: /* Add code to process scopes. */
0449: processScopeSpace();
0450: cbody.addAll(functionDefinitions);
0451:
0452: sbody.addAll(primitiveDeclList);
0453: sbody.addAll(staticFields);
0454: tbody.add(factory.typesConstr(output + "Types"));
0455: sbody.add(factory.typesConstr(output + "Support"));
0456:
0457: // Make skeletons of generated files
0458: transformed = GNode.cast(makeSkeleton());
0459: typesAST = GNode.cast(makeTypesSkeleton());
0460: supportAST = GNode.cast(makeSupportSkeleton());
0461:
0462: }
0463:
0464: /**
0465: * Process a module declaration.
0466: *
0467: * @param n The ModuleDeclaration node.
0468: */
0469: public void visitModuleDeclaration(GNode n) {
0470: Node qid = GNode.create("QualifiedIdentifier");
0471:
0472: StringBuilder buf = new StringBuilder();
0473: for (int i = 0; i < n.size() - 1; i++) {
0474: qid.add(n.getString(i));
0475: buf.append(n.getString(i));
0476: if (i < n.size() - 2)
0477: buf.append('.');
0478: }
0479:
0480: packageName = buf.toString();
0481: packageNode = GNode.create("PackageDeclaration", null, qid);
0482: }
0483:
0484: /**
0485: * Process a value definition.
0486: *
0487: * @param n The value binding node.
0488: * @return The java code for the funciton
0489: */
0490: public Node visitValueDefinition(GNode n) {
0491:
0492: String name = n.getString(0);
0493: Node params = n.getGeneric(1);
0494: Node value = n.getGeneric(2);
0495:
0496: String nsname = SymbolTable.toNameSpace(name, "value");
0497: Object t = n.getProperty(TYPE);
0498:
0499: if (null == t)
0500: t = table.current().lookup(nsname);
0501:
0502: if (mapper.isFunctionType(t)) {
0503: // Get the number of type variables from the function type
0504: final int typeVarNumber = mapper.processTypeVariables(t, 0);
0505: // Check if this function is generic
0506: final boolean isGeneric = typeVarNumber > 0;
0507:
0508: Node returnTypeNode = mapper.getReturnTypeNode(t);
0509:
0510: List<Node> paramTypeNodes = mapper.getParameterTypeNodes(t);
0511:
0512: Node functionTypeNode = mapper.toTypeNode(t, false);
0513: //desugar function expressions
0514: if (value.hasName("FunctionExpression")) {
0515: String arg = table.freshJavaId("arg");
0516: value = GNode.create("MatchExpression", GNode.create(
0517: "LowerID", arg), value.get(0));
0518: value.setProperty("__arg_type", paramTypeNodes.get(0));
0519:
0520: n.set(1, GNode.create("Parameters", GNode.create(
0521: "Parameter", arg, null)));
0522: params = n.getGeneric(1);
0523: } else if (value.hasName("ReduceExpression")) {
0524: String arg = "lst";
0525: n.set(1, GNode.create("Parameters", GNode.create(
0526: "Parameter", arg, null)));
0527: params = n.getGeneric(1);
0528: }
0529:
0530: // Set property to remember value is in analyze function
0531: if ("analyze".equals(name))
0532: value.setProperty(INANALYZE, Boolean.TRUE);
0533:
0534: value.setProperty(TYPE, returnTypeNode);
0535:
0536: //populate the formal parameters for the "apply" method
0537: Node formalParameters = GNode.create("FormalParameters",
0538: params.size());
0539:
0540: for (int i = 0; i < params.size(); i++) {
0541: formalParameters.add(GNode.create("FormalParameter",
0542: fmod, paramTypeNodes.get(i), null, params
0543: .getGeneric(i).getString(0), null));
0544: }
0545:
0546: //enter the scope and process this bindings value
0547: if (!"getNameSpace".equals(name))
0548: enterScope(name);
0549:
0550: // Type parameters node
0551: Node typeParas = null;
0552: if (isGeneric) {
0553: typeParas = GNode.create("TypeParameters");
0554: for (int i = 0; i < typeVarNumber; i++) {
0555: typeParas.add(GNode.create("TypeParameter",
0556: "T" + i, null));
0557: }
0558: }
0559:
0560: Node classBody = GNode.create("ClassBody", GNode.create(
0561: "MethodDeclaration", pmod, typeParas,
0562: returnTypeNode, "apply", formalParameters, null,
0563: null, GNode.create("Block", factory
0564: .ret((Node) dispatch(value)))));
0565:
0566: if (!"getNameSpace".equals(name))
0567: exitScope(name);
0568:
0569: //create and add the fielddeclaration to the typechecker
0570: if ("getNameSpace".equals(name) || "getScope".equals(name)) {
0571: return makeVarDec2(name, functionTypeNode,
0572: toNewExpression2(functionTypeNode, null,
0573: classBody));
0574: } else {
0575: // If not a generic function, create a field declaration
0576: if (!isGeneric) {
0577: functionDefinitions
0578: .add(makeVarDec2(name, functionTypeNode,
0579: toNewExpression2(functionTypeNode,
0580: null, classBody)));
0581: } else { // create a class
0582: Node classNode = factory.classDecl3(name);
0583: classNode.set(5, classBody);
0584: functionDefinitions.add(classNode);
0585: functionDefinitions.add(factory
0586: .instanceDecl(GNode.create("Type",
0587: GNode.create("QualifiedIdentifier",
0588: name), null), name,
0589: GNode.create("QualifiedIdentifier",
0590: name)));
0591: }
0592: }
0593: } else {
0594: //no function needed, just field declaration
0595: functionDefinitions.add(makeVarDec2(name, mapper
0596: .toTypeNode(t, false), factory
0597: .cast((Node) dispatch(value))));
0598: }
0599:
0600: // Note: in general, we modify the AST in place and are done. For
0601: // getNameSpace() and getScope(), however, we need to do further
0602: // processing; so they are returned above.
0603:
0604: return null;
0605: }
0606:
0607: /**
0608: * Process a function expression
0609: *
0610: * @param n The function expression node
0611: * @return The translated node
0612: */
0613: public Node visitFunctionExpression(GNode n) {
0614: // Get the function type
0615: final Object t = n.getProperty(TYPE);
0616: final Node returnTypeNode = mapper.getReturnTypeNode(t);
0617:
0618: final List<Node> paramTypeNodes = mapper
0619: .getParameterTypeNodes(t);
0620:
0621: // Get the return type from the pattern match type
0622: final Object retType = mapper.getPatternMatchRightType(n
0623: .getGeneric(0).getProperty(TYPE));
0624:
0625: // Create a Typical match expression node
0626: Node value = GNode.create("MatchExpression", GNode.create(
0627: "LowerID", "var"), n.getGeneric(0));
0628: value.setProperty("__arg_type", paramTypeNodes.get(0));
0629: value.setProperty(TYPE, retType);
0630: return factory.functionExpression(returnTypeNode,
0631: paramTypeNodes.get(0), (Node) dispatch(value));
0632: }
0633:
0634: /**
0635: * Process a type definition.
0636: *
0637: * @param n The type definition node.
0638: */
0639: public void visitTypeDefinition(GNode n) {
0640: n.getGeneric(2).setProperty("name", n.getString(1));
0641: dispatch(n.getGeneric(2));
0642: }
0643:
0644: /**
0645: * Process a string literal.
0646: *
0647: * @param n The string literal node.
0648: * @return n.
0649: */
0650: public GNode visitStringLiteral(GNode n) {
0651: return n;
0652: }
0653:
0654: /**
0655: * Process an integer literal.
0656: *
0657: * @param n the integer literal node.
0658: * @return The BigInteger node.
0659: */
0660: public Node visitIntegerLiteral(GNode n) {
0661: return factory.createInteger(toLiteral("IntegerLiteral", n
0662: .getString(0)));
0663: }
0664:
0665: /**
0666: * Process a float literal.
0667: *
0668: * @param n the float literal node.
0669: * @return The 'new Double' node.
0670: */
0671: public Node visitFloatingLiteral(GNode n) {
0672: return factory.createFloat(toLiteral("FloatingPointLiteral", n
0673: .getString(0)));
0674: }
0675:
0676: /**
0677: * Process a bottom node.
0678: *
0679: * @param n The bottom node.
0680: * @return A null literal.
0681: */
0682: public Node visitBottom(GNode n) {
0683: return nullNode;
0684: }
0685:
0686: /**
0687: * Process a bottom pattern.
0688: *
0689: * @param n The bottom pattern node.
0690: * @return A null literal.
0691: */
0692: public Node visitBottomPattern(GNode n) {
0693: return factory.equalsBottom(toIdentifier((String) n
0694: .getProperty(MATCHARG)));
0695: }
0696:
0697: /**
0698: * Process a boolean literal.
0699: *
0700: * @param n the boolean literal node.
0701: */
0702: public Node visitBooleanLiteral(GNode n) {
0703: return ("true".equals(n.getString(0))) ? toIdentifier("Boolean.TRUE")
0704: : toIdentifier("Boolean.FALSE");
0705: }
0706:
0707: /**
0708: * Process a cons expression.
0709: *
0710: * @param n The cons expression node.
0711: * @return The java equivalent.
0712: */
0713: public Node visitConsExpression(GNode n) {
0714: if (n.hasProperty(INANALYZE)) {
0715: n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
0716: n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
0717: }
0718: return factory.consWrapper((Node) dispatch(n.getGeneric(0)),
0719: (Node) dispatch(n.getGeneric(1)));
0720: }
0721:
0722: /**
0723: * Transform a wildcard.
0724: *
0725: * @param n The wildcard node.
0726: * @return A wildcard primary identifier.
0727: */
0728: public Node visitWildCard(GNode n) {
0729: return toLiteral("BooleanLiteral", "true");
0730: }
0731:
0732: /**
0733: * Process a field expression.
0734: *
0735: * @param n The field expression node.
0736: * @return A java field access node (with null pointer checks inserted).
0737: */
0738: public Node visitFieldExpression(GNode n) {
0739: if (n.hasProperty(INANALYZE)) {
0740: n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
0741: }
0742: if ("TupleConstructor".equals(n.getGeneric(0).getName())) {
0743: String convertedName = Primitives.convertName(n
0744: .getString(1));
0745: if ("Limits".equals(n.getGeneric(0).getString(0))) {
0746: if (Primitives.hasIntegerType(convertedName)) {
0747: return factory
0748: .createInteger(toIdentifier("xtc.Limits."
0749: + convertedName));
0750: }
0751: return toIdentifier("xtc.Limits." + convertedName);
0752: }
0753: return toIdentifier("Primitives." + convertedName);
0754: }
0755:
0756: // Check replaceType and the field name
0757: if (replaceType && "type".equals(n.getString(1))) {
0758: return (Node) dispatch(n.getGeneric(0));
0759: }
0760:
0761: return factory.fieldExpression(
0762: (Node) dispatch(n.getGeneric(0)), n.getString(1));
0763: }
0764:
0765: /**
0766: * Process a tuple literal.
0767: *
0768: * @param n The tuple literal node.
0769: * @return The java equivalent.
0770: */
0771: public Node visitTupleLiteral(GNode n) {
0772: return makeTuple(n);
0773: }
0774:
0775: /**
0776: * Process a tuple pattern.
0777: *
0778: * @param n The tuple pattern node.
0779: * @return The java equivalent.
0780: */
0781: public Node visitTuplePattern(GNode n) {
0782: String matchArg = (String) n.getProperty(MATCHARG);
0783:
0784: Node condition = factory.jand(factory
0785: .notEqualsBottom(toIdentifier(matchArg)), factory
0786: .sizeEqual(toIdentifier(matchArg), toLiteral(
0787: "IntegerLiteral", Integer.toString(n.size()))));
0788:
0789: for (int i = 0; i < n.size(); i++) {
0790: Node node = n.getGeneric(i);
0791:
0792: if (node.hasName("WildCard"))
0793: continue;
0794:
0795: if (node.hasName("Variable")) {
0796: //make the binding
0797: node.setProperty(RHS, matchArg + ".get" + (i + 1)
0798: + "()");
0799: node.setProperty(BINDINGS, n.getProperty(BINDINGS));
0800: dispatch(node);
0801: continue;
0802: }
0803:
0804: if (isLiteral(node)) {
0805: condition = factory.jand(condition, factory.jequals2(
0806: (Node) dispatch(node), toIdentifier(matchArg
0807: + ".get" + (i + 1) + "()")));
0808: continue;
0809: }
0810:
0811: node.setProperty(BINDINGS, (n.getProperty(BINDINGS)));
0812: node.setProperty(MATCHARG, (String) n.getProperty(MATCHARG)
0813: + ".get" + (i + 1) + "()");
0814: condition = factory.jand(condition, (Node) dispatch(node));
0815: }
0816:
0817: if (n.hasProperty(TOP)) {
0818: String matchName = table.freshJavaId("match");
0819: condition = replaceMatchArg(condition, matchArg);
0820:
0821: Match ms = new Match(mapper.toTypeNode(n.getProperty(TYPE),
0822: false), condition);
0823:
0824: if (matches.containsKey(ms)) {
0825: matchName = matches.get(ms);
0826: } else {
0827: matches.put(ms, matchName);
0828: Node matchFunction = factory.matchFunction(matchName,
0829: mapper.toTypeNode(n.getProperty(TYPE), true),
0830: condition);
0831:
0832: matchFunction.getGeneric(4).getGeneric(0).set(3, "m");
0833: staticFields.add(matchFunction);
0834: }
0835:
0836: return factory.matchCall(toIdentifier(output + "Support"),
0837: matchName, toIdentifier((String) n
0838: .getProperty(MATCHARG)));
0839: } else {
0840: return condition;
0841: }
0842: }
0843:
0844: /**
0845: * Process a List literal.
0846: *
0847: * @param n The list literal node.
0848: * @return The java equivalent.
0849: */
0850: public Node visitListLiteral(GNode n) {
0851: return makeList(n);
0852: }
0853:
0854: /**
0855: * Make conditions identical with respect to argument name so we can generate
0856: * unique match functions;
0857: *
0858: * @param n The node to process.
0859: * @param id The name of the id to replace.
0860: * @return The processed node.
0861: */
0862: private Node replaceMatchArg(Node n, String id) {
0863:
0864: for (int i = 0; i < n.size(); i++) {
0865: Object o = n.get(i);
0866: if (o instanceof Node) {
0867: Node node = (Node) o;
0868:
0869: if (node.hasName("PrimaryIdentifier")
0870: && node.getString(0).equals(id)) {
0871: node.set(0, node.getString(0).replace(id, "m"));
0872: } else if (node.hasName("PrimaryIdentifier")
0873: && node.getString(0).startsWith(id + ".")) {
0874: node.set(0, node.getString(0).replace(id + ".",
0875: "m."));
0876: } else {
0877: replaceMatchArg(node, id);
0878: }
0879: } else if ((o instanceof String) && id.equals(o)) {
0880: n.set(i, id);
0881: }
0882: }
0883:
0884: return n;
0885: }
0886:
0887: /**
0888: * Process a List pattern.
0889: *
0890: * @param n The list pattern node.
0891: * @return The java equivalent.
0892: */
0893: public Node visitListPattern(GNode n) {
0894: checkTypeAnnotation(n);
0895:
0896: String matchArg = (String) n.getProperty(MATCHARG);
0897:
0898: Node condition = (0 == n.size()) ? factory
0899: .isEmptyCall(toIdentifier(matchArg)) : factory
0900: .sizeEqual(toIdentifier(matchArg), toLiteral(
0901: "IntegerLiteral", Integer.toString(n.size())));
0902:
0903: for (int i = 0; i < n.size(); i++) {
0904: Node node = n.getGeneric(i);
0905:
0906: if (node.hasName("WildCard"))
0907: continue;
0908:
0909: if (node.hasName("Variable")) {
0910: ((Node) n.getProperty(BINDINGS)).add(makeVarDec2(node
0911: .getString(0), mapper.toTypeNode(mapper
0912: .getBase(n.getProperty(TYPE)), false),
0913: factory.cast(toIdentifier(matchArg + ".get("
0914: + i + ")"))));
0915: continue;
0916: }
0917:
0918: if (isLiteral(node)) {
0919: condition = factory.jand(condition, factory.jequals2(
0920: (Node) dispatch(node), toIdentifier(matchArg
0921: + ".get(" + i + ")")));
0922: continue;
0923: }
0924:
0925: node.setProperty(BINDINGS, n.getProperty(BINDINGS));
0926: node.setProperty(MATCHARG, matchArg + ".get(" + i + ")");
0927: condition = factory.jand(condition, (Node) dispatch(node));
0928: }
0929:
0930: if (n.hasProperty(TOP)) {
0931: Node listTypeNode = mapper.toTypeNode(n.getProperty(TYPE),
0932: true);
0933:
0934: condition = replaceMatchArg(condition, matchArg);
0935:
0936: String matchName = table.freshJavaId("match");
0937: Match ms = null;
0938:
0939: ms = new Match(listTypeNode, condition);
0940:
0941: if (matches.containsKey(ms)) {
0942: matchName = matches.get(ms);
0943: } else {
0944: matches.put(ms, matchName);
0945: Node matchFunction = factory.matchFunction(matchName,
0946: listTypeNode, condition);
0947:
0948: matchFunction.getGeneric(4).getGeneric(0).set(3, "m");
0949: staticFields.add(matchFunction);
0950: }
0951:
0952: return factory.matchCall(toIdentifier(output + "Support"),
0953: matchName, toIdentifier((String) n
0954: .getProperty(MATCHARG)));
0955: } else {
0956: return condition;
0957: }
0958: }
0959:
0960: /**
0961: * Transform a predicate expression.
0962: *
0963: * @param n The predicate expression.
0964: * @return The java equivalent.
0965: */
0966: public Node visitPredicateExpression(GNode n) {
0967: if (n.hasProperty(INANALYZE)) {
0968: n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
0969: }
0970:
0971: Node arg = n.getGeneric(0).getGeneric(0);
0972:
0973: for (int i = 0; i < arg.size(); i++) {
0974: Node node = arg.getGeneric(i);
0975: node.setProperty(RHS, RHS);
0976: node.setProperty(BINDINGS, GNode.create("Block"));
0977: node.setProperty("enterScope", "scope" + i);
0978: }
0979:
0980: Node wild = GNode.create("WildCard");
0981: wild.setProperty("enterScope", "ihavenoscope");
0982:
0983: Node last = GNode.create("PatternMatch", GNode.create(
0984: "Patterns", wild), GNode.create("BooleanLiteral",
0985: "false"));
0986: Node first = GNode.create("PatternMatch", n.getGeneric(0)
0987: .getGeneric(0), GNode.create("BooleanLiteral", "true"));
0988:
0989: Node pmatching = GNode.create("PatternMatching", first, last);
0990:
0991: Object pt = mapper.makePatternMatchType(arg.getProperty(TYPE),
0992: n.getProperty(TYPE));
0993:
0994: first.setProperty(TYPE, pt);
0995: last.setProperty(TYPE, pt);
0996: pmatching.setProperty(TYPE, pt);
0997: first.setProperty("enterScope", "predicatescope");
0998: last.setProperty("enterScope", "predicatescope");
0999:
1000: Node match = GNode.create("MatchExpression", n.getGeneric(1),
1001: pmatching);
1002: match.setProperty("__arg_type", n.getProperty("__arg_type"));
1003:
1004: match.setProperty(TYPE, n.getProperty(TYPE));
1005:
1006: return factory.jequals2((Node) dispatch(match), toLiteral(
1007: "BooleanLiteral", "true"));
1008: }
1009:
1010: /**
1011: * Transform a guard expression.
1012: *
1013: * @param n
1014: */
1015: public Node visitGuardExpression(GNode n) {
1016: //we need to collect all the variables and test for nullity
1017: Set<String> variables = new FreeVariableCollector(n)
1018: .getIdentifiers();
1019:
1020: List<Node> statements = new ArrayList<Node>();
1021:
1022: Node typeNode = mapper.toTypeNode(n.getGeneric(0).getProperty(
1023: TYPE), false);
1024:
1025: String name = table.freshJavaId("result");
1026:
1027: for (String variable : variables) {
1028: statements.add(factory.ifStatement(factory
1029: .isNull(toIdentifier(variable)), factory
1030: .ret(toIdentifier("null"))));
1031:
1032: }
1033:
1034: statements.add(factory.fieldDecl2(typeNode, name,
1035: (Node) dispatch(n.getGeneric(0))));
1036: statements.add(factory.ifStatement(factory
1037: .isNull(toIdentifier(name)), factory.ret(factory
1038: .cast((Node) dispatch(n.getGeneric(1))))));
1039: statements.add(factory.ret(toIdentifier(name)));
1040:
1041: if (n.hasProperty(INANALYZE)) {
1042: n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
1043: }
1044:
1045: return factory.guardExpression(typeNode, statements);
1046: }
1047:
1048: /**
1049: * Transform a reduce expression.
1050: *
1051: * @param n The predicate expression.
1052: * @return The java equivalent.
1053: */
1054: public Node visitReduceExpression(GNode n) {
1055:
1056: Node arg = toIdentifier("lst");
1057: Node runtimeNode = toIdentifier("runtime");
1058:
1059: List<Node> initList = new ArrayList<Node>();
1060:
1061: Node options = n.getGeneric(0);
1062:
1063: for (int i = 0; i < options.size(); i++) {
1064: String opt = options.getString(i);
1065:
1066: if ("required".equals(opt)) {
1067: initList.add(factory.reduceReq());
1068: } else if ("optional".equals(opt)) {
1069: initList.add(factory.reduceOpt());
1070: } else if ("list".equals(opt)) {
1071: initList.add(factory.reduceList());
1072: } else if ("set".equals(opt)) {
1073: initList.add(factory.reduceSet());
1074: } else if ("dup".equals(opt)) {
1075: initList.add(factory.reduceDup());
1076: } else if ("nodup".equals(opt)) {
1077: initList.add(factory.reduceNodup());
1078: } else if ("singleton".equals(opt)) {
1079: initList.add(factory.reduceSing());
1080: }
1081: }
1082:
1083: //set the tag
1084: initList.add(factory.reduceTag(n.getGeneric(1)));
1085:
1086: Node patternMatching = n.getGeneric(2);
1087:
1088: for (int i = 0; i < patternMatching.size(); i++) {
1089: Node patternMatch = patternMatching.getGeneric(i);
1090:
1091: ArrayList<Node> addArgs = new ArrayList<Node>();
1092:
1093: ArrayList<Node> block = new ArrayList<Node>();
1094:
1095: addArgs.add((Node) dispatch(patternMatch.getGeneric(1)));
1096: Node lpatterns = patternMatch.getGeneric(0).getGeneric(0);
1097: for (int j = 0; j < lpatterns.size(); j++) {
1098: Node node = lpatterns.getGeneric(j);
1099:
1100: if (node.hasName("AsPattern")) {
1101: String binding = node.getString(1);
1102:
1103: node = node.getGeneric(0);
1104: node.setProperty("ancestor", true);
1105: node.setProperty("top", true);
1106: node
1107: .setProperty(MATCHARG, table
1108: .freshJavaId("arg"));
1109:
1110: block.add(factory.reduceGetMatch(binding,
1111: (Node) dispatch(node)));
1112: }
1113:
1114: node.setProperty("ancestor", true);
1115: node.setProperty("top", true);
1116: node.setProperty(MATCHARG, table.freshJavaId("arg"));
1117: addArgs.add((Node) dispatch(node));
1118: }
1119:
1120: block.add(factory.reduceAddPatterns(addArgs));
1121: initList.add(factory.block(block));
1122: }
1123:
1124: return factory.cast(factory.reduceExpression(arg, runtimeNode,
1125: initList));
1126: }
1127:
1128: /**
1129: * Process a function application.
1130: *
1131: * @param n The function application node.
1132: * @return The java equivalent of the function application node.
1133: */
1134: public Node visitFunctionApplication(GNode n) {
1135: // Get function arguments
1136: Node funcArgs = n.getGeneric(n.size() - 1);
1137:
1138: Node id = n.getGeneric(0);
1139:
1140: if ("ancestor".equals(id.getString(0))
1141: || "parent".equals(id.getString(0))) {
1142:
1143: Node arg = funcArgs.getGeneric(0);
1144: arg.setProperty("ancestor", true);
1145: arg.setProperty(MATCHARG, table.freshJavaId("arg"));
1146: arg = (Node) dispatch(arg);
1147:
1148: List<Node> nlist = new ArrayList<Node>(1);
1149: nlist.add(arg);
1150:
1151: return factory.apply(toIdentifier(id.getString(0)), nlist);
1152: }
1153: //special case
1154:
1155: // Annotate if this function application is in analyze function
1156: if (n.hasProperty(INANALYZE)) {
1157: for (int i = 0; i < funcArgs.size(); i++) {
1158: funcArgs.getGeneric(i).setProperty(INANALYZE,
1159: Boolean.TRUE);
1160: }
1161: }
1162:
1163: //process arguments
1164: Node args = GNode.create("Arguments");
1165:
1166: for (int i = 0; i < funcArgs.size(); i++) {
1167: args.add(dispatch(funcArgs.getGeneric(i)));
1168: }
1169:
1170: // Name of this function
1171: final String funcName;
1172: // Name is this function in Java's style
1173: final String newName;
1174:
1175: // Type of this function
1176: final Object funcType;
1177:
1178: // Parameter types of this function
1179: final List<String> paramTypes;
1180: final List<Node> paramTypeNodes;
1181:
1182: // Return type of this function
1183: final Node retTypeNode;
1184:
1185: // Process function application of the form Name.name ...
1186: if (3 == n.size()) {
1187: // All functions here are in Primitives
1188: // Module name
1189: String moduleName = n.getGeneric(0).getString(0);
1190:
1191: if ("Prelude".equals(moduleName)) {
1192: // Functions of this form: Prelude.name
1193: funcName = n.getGeneric(1).getString(0);
1194: } else {
1195: funcName = moduleName + "."
1196: + n.getGeneric(1).getString(0);
1197: }
1198:
1199: // Get type of this function
1200: funcType = table.current()
1201: .lookup("value(" + funcName + ")");
1202: // Get parameter type list
1203: paramTypes = mapper.getParameterTypes(funcType);
1204: paramTypeNodes = mapper.getParameterTypeNodes(funcType);
1205: // Get return type
1206: retTypeNode = mapper.getReturnTypeNode(funcType);
1207:
1208: // Java's style of the function name
1209: newName = Primitives.convertName(n.getGeneric(1).getString(
1210: 0));
1211:
1212: // Process get and put here
1213: if ("Map".equals(moduleName)) {
1214: List<Node> args1 = new ArrayList<Node>();
1215: if ("get".equals(newName)) {
1216: // This must be a complete function application
1217: args1.add(args.getGeneric(0));
1218: args1.add(toIdentifier("hashTable"));
1219: return factory.castInvocation(
1220: toIdentifier("Primitives.get"), "apply",
1221: args1);
1222: } else {
1223: if (2 == args.size()) {
1224: // complete application
1225: args1.add(args.getGeneric(0));
1226: args1.add(args.getGeneric(1));
1227: args1.add(toIdentifier("hashTable"));
1228: return factory.castInvocation(
1229: toIdentifier("Primitives.put"),
1230: "apply", args1);
1231: } else {
1232: // incomplete application
1233: String tempVar = table.freshJavaId("var");
1234: return factory.curryingPut(
1235: toIdentifier(tempVar), args
1236: .getGeneric(0));
1237: }
1238: }
1239:
1240: }
1241:
1242: //check if this is a complete or imcomplete function application
1243: if (args.size() == paramTypes.size()) {
1244: // This is a complete function application
1245: // Special case the pair ops
1246: // are generic
1247: final String newInstance;
1248: Node newIns = null;
1249:
1250: // Instances with one type parameter
1251: if ("head".equals(newName) || "tail".equals(newName)
1252: || "append".equals(newName)
1253: || "union".equals(newName)
1254: || "cons".equals(newName)
1255: || "nth".equals(newName)
1256: || "intersection".equals(newName)
1257: || "subtraction".equals(newName)) {
1258:
1259: final Object t = mapper.getBase(funcArgs
1260: .getGeneric(0).getProperty(TYPE));
1261: final String typeName = mapper.toTypeString(t);
1262: final Node typeNode = mapper.toTypeNode(t, false);
1263:
1264: List<String> instanceTypes = new ArrayList<String>();
1265: instanceTypes.add(typeName);
1266:
1267: String instanceName = getInstanceName(newName,
1268: instanceTypes);
1269:
1270: if (null == instanceName) {
1271: newInstance = table.freshJavaId(newName);
1272: primitiveInsList.add(new PrimitiveInstance(
1273: newName, instanceTypes, newInstance));
1274: } else {
1275: newInstance = instanceName;
1276: }
1277:
1278: // Create a new instances with one type parameter
1279:
1280: if (null == instanceName && "head".equals(newName)) {
1281: newIns = factory.newHead(typeNode, newInstance);
1282: } else if (null == instanceName
1283: && "tail".equals(newName)) {
1284: newIns = factory.newTail(typeNode, newInstance);
1285: } else if (null == instanceName
1286: && "append".equals(newName)) {
1287: newIns = factory.newAppend(typeNode,
1288: newInstance);
1289: } else if (null == instanceName
1290: && "union".equals(newName)) {
1291: newIns = factory
1292: .newUnion(typeNode, newInstance);
1293: } else if (null == instanceName
1294: && "cons".equals(newName)) {
1295: newIns = factory.newCons(typeNode, newInstance);
1296: } else if (null == instanceName
1297: && "nth".equals(newName)) {
1298: newIns = factory.newNth(typeNode, newInstance);
1299: } else if (null == instanceName
1300: && "intersection".equals(newName)) {
1301: newIns = factory.newIntersection(typeNode,
1302: newInstance);
1303: } else if (null == instanceName
1304: && "subtraction".equals(newName)) {
1305: newIns = factory.newSubtraction(typeNode,
1306: newInstance);
1307: }
1308:
1309: if (null == instanceName)
1310: primitiveDeclList.add(newIns);
1311:
1312: return factory.apply(toIdentifier(output
1313: + "Support." + newInstance),
1314: makeArgumentList(args));
1315: }
1316:
1317: if ("exists".equals(newName)) {
1318: final Object t = mapper.getBase(funcArgs
1319: .getGeneric(1).getProperty(TYPE));
1320: final String typeName = mapper.toTypeString(t);
1321: final Node typeNode = mapper.toTypeNode(t, false);
1322: List<String> instanceTypes = new ArrayList<String>();
1323: instanceTypes.add(typeName);
1324:
1325: String instanceName = getInstanceName(newName,
1326: instanceTypes);
1327:
1328: if (null == instanceName) {
1329: newInstance = table.freshJavaId(newName);
1330: primitiveInsList.add(new PrimitiveInstance(
1331: newName, instanceTypes, newInstance));
1332: newIns = factory.newExists(typeNode,
1333: newInstance);
1334: primitiveDeclList.add(newIns);
1335: } else {
1336: newInstance = instanceName;
1337: }
1338: return factory.apply(toIdentifier(output
1339: + "Support." + newInstance),
1340: makeArgumentList(args));
1341: }
1342:
1343: // Instances with two type parameters
1344: if ("map".equals(newName) || "iter".equals(newName)) {
1345: final Object t1 = funcArgs.getGeneric(0)
1346: .getProperty(TYPE);
1347: final String typeName1 = mapper.getReturnType(t1);
1348: final Node typeNode1 = mapper.getReturnTypeNode(t1);
1349: final Object t2 = mapper.getBase(funcArgs
1350: .getGeneric(1).getProperty(TYPE));
1351: final String typeName2 = mapper.toTypeString(t2);
1352: final Node typeNode2 = mapper.toTypeNode(t2, false);
1353: List<String> instanceTypes = new ArrayList<String>();
1354: instanceTypes.add(typeName1);
1355: instanceTypes.add(typeName2);
1356:
1357: String instanceName = getInstanceName(newName,
1358: instanceTypes);
1359: if (null == instanceName) {
1360: newInstance = table.freshJavaId(newName);
1361: primitiveInsList.add(new PrimitiveInstance(
1362: newName, instanceTypes, newInstance));
1363: } else {
1364: newInstance = instanceName;
1365: }
1366:
1367: if (null == instanceName && "map".equals(newName)) {
1368: newIns = factory.newMap(typeNode1, typeNode2,
1369: newInstance);
1370: } else if (null == instanceName
1371: && "iter".equals(newName)) {
1372: newIns = factory.newIter(typeNode1, typeNode2,
1373: newInstance);
1374: }
1375: if (null == instanceName)
1376: primitiveDeclList.add(newIns);
1377: return factory.apply(toIdentifier(output
1378: + "Support." + newInstance),
1379: makeArgumentList(args));
1380: }
1381:
1382: if ("foldl".equals(newName)) {
1383: final Object t1 = funcArgs.getGeneric(2)
1384: .getProperty(TYPE);
1385: final String typeName1 = mapper.toTypeString(t1);
1386: final Node typeNode1 = mapper.toTypeNode(t1, false);
1387: final Object t2 = mapper.getBase(funcArgs
1388: .getGeneric(1).getProperty(TYPE));
1389: final String typeName2 = mapper.toTypeString(t2);
1390: final Node typeNode2 = mapper.toTypeNode(t2, false);
1391: List<String> instanceTypes = new ArrayList<String>();
1392: instanceTypes.add(typeName1);
1393: instanceTypes.add(typeName2);
1394:
1395: String instanceName = getInstanceName(newName,
1396: instanceTypes);
1397: if (null == instanceName) {
1398: newInstance = table.freshJavaId(newName);
1399: primitiveInsList.add(new PrimitiveInstance(
1400: newName, instanceTypes, newInstance));
1401: newIns = factory.newFoldl(typeNode1, typeNode2,
1402: newInstance);
1403: primitiveDeclList.add(newIns);
1404: } else {
1405: newInstance = instanceName;
1406: }
1407: return factory.apply(toIdentifier(output
1408: + "Support." + newInstance),
1409: makeArgumentList(args));
1410: }
1411: // Other primitive functions
1412: return factory.applyPrimitive(newName,
1413: makeArgumentList(args));
1414: } else {
1415: // This is an incomplete function application, process currying
1416: return makeCurry("Primitives." + newName, args,
1417: paramTypeNodes, retTypeNode, funcType);
1418: }
1419:
1420: } else { // Process function application of this form: name ...
1421:
1422: funcName = n.getGeneric(0).getString(0);
1423: // Java's style of the function name
1424: newName = Primitives.convertName(n.getGeneric(0).getString(
1425: 0));
1426:
1427: List<Node> args1 = new ArrayList<Node>();
1428:
1429: // Process symbol table function applications, they must be complete.
1430: if ("lookup".equals(newName)
1431: || "lookupLocally".equals(newName)) {
1432: if (1 == funcArgs.size()) {
1433: // If it has only one child, that must be a node
1434: args1.add((Node) dispatch(funcArgs.getGeneric(0)));
1435: args1.add(toIdentifier("getNameSpace"));
1436: return factory.castInvocation(toIdentifier(newName
1437: + "2"), "apply", args1);
1438:
1439: } else if (2 == funcArgs.size()) {
1440: Node arg = (Node) dispatch(funcArgs.getGeneric(0));
1441:
1442: if ("ErrorClause".equals(funcArgs.getGeneric(1)
1443: .getName())) {
1444: // If the second child is a error clause.
1445: String tag = funcArgs.getGeneric(1).getGeneric(
1446: 0).getString(0);
1447: args1.add(arg);
1448: args1.add(toLiteral("StringLiteral", "\"" + tag
1449: + "\""));
1450: args1.add((Node) dispatch(funcArgs
1451: .getGeneric(1).getGeneric(1)));
1452: args1.add(toIdentifier("getNameSpace"));
1453: return factory.castInvocation(
1454: toIdentifier(newName + "4"), "apply",
1455: args1);
1456: } else {
1457: // The second child is a tag.
1458: args1.add(arg);
1459: args1.add(toIdentifier("getNameSpace"));
1460: return factory.castInvocation(
1461: toIdentifier(newName + "2"), "apply",
1462: args1);
1463: }
1464: } else {
1465: // The arguments include: node, tag and error clause in that order.
1466: String tag = funcArgs.getGeneric(2).getGeneric(0)
1467: .getString(0);
1468:
1469: args1.add((Node) dispatch(funcArgs.getGeneric(0)));
1470: args1.add(toLiteral("StringLiteral", "\"" + tag
1471: + "\""));
1472: args1.add((Node) dispatch(funcArgs.getGeneric(2)
1473: .getGeneric(1)));
1474: args1.add(toIdentifier("getNameSpace"));
1475: return factory.castInvocation(toIdentifier(newName
1476: + "4"), "apply", args1);
1477: }
1478: }
1479: // Process define.
1480: if ("define".equals(newName)) {
1481: if (2 == funcArgs.size()) {
1482: // It is has 2 children, they must be a node and a type.
1483: args1.add((Node) dispatch(funcArgs.getGeneric(0)));
1484: args1.add((Node) dispatch(funcArgs.getGeneric(1)));
1485: args1.add(toIdentifier("getNameSpace"));
1486:
1487: return factory
1488: .apply(toIdentifier("define3"), args1);
1489: } else {
1490: // It has 3 children: node, type and and error clause in that order.
1491: String tag = funcArgs.getGeneric(2).getGeneric(0)
1492: .getString(0);
1493:
1494: args1.add((Node) dispatch(funcArgs.getGeneric(0)));
1495: args1.add((Node) dispatch(funcArgs.getGeneric(1)));
1496: args1.add(toLiteral("StringLiteral", "\"" + tag
1497: + "\""));
1498: args1.add((Node) dispatch(funcArgs.getGeneric(2)
1499: .getGeneric(1)));
1500: args1.add(toIdentifier("getNameSpace"));
1501: return factory.invocation(toIdentifier("define5"),
1502: "apply", args1);
1503: }
1504: }
1505:
1506: //process redefine, isDefined, and isDefinedLocally
1507: if ("isDefined".equals(newName)
1508: || "isDefinedLocally".equals(newName)
1509: || "redefine".equals(newName)) {
1510: args.add(toIdentifier("getNameSpace"));
1511: return factory.apply(toIdentifier(newName),
1512: makeArgumentList(args));
1513: }
1514:
1515: // Get the type of this function
1516: funcType = table.current()
1517: .lookup("value(" + funcName + ")");
1518: // Get parameter type
1519: paramTypes = mapper.getParameterTypes(funcType);
1520: paramTypeNodes = mapper.getParameterTypeNodes(funcType);
1521: // Get return type
1522: retTypeNode = mapper.getReturnTypeNode(funcType);
1523:
1524: // check for complete and incomplete function applications
1525: if (args.size() == paramTypes.size()) {
1526: // Complete function application
1527: if (Primitives.isPrimitive(newName)) {
1528: return factory.applyPrimitive(newName,
1529: makeArgumentList(args));
1530: } else {
1531: return factory.apply(toIdentifier(newName),
1532: makeArgumentList(args));
1533: }
1534: } else {
1535: // incomplete function application
1536: if (Primitives.isPrimitive(newName)) {
1537: return makeCurry("Primitives." + newName, args,
1538: paramTypeNodes, retTypeNode, funcType);
1539: } else {
1540: return makeCurry(newName, args, paramTypeNodes,
1541: retTypeNode, funcType);
1542: }
1543: }
1544: }
1545: }
1546:
1547: /**
1548: * Make a java expresson to represent a tuple.
1549: *
1550: * @param n The typical tuple node.
1551: * @return The java representation.
1552: */
1553: private Node makeTuple(GNode n) {
1554: GNode args = GNode.create("Arguments");
1555: for (int i = 0; i < n.size(); i++) {
1556: args.add(dispatch(n.getGeneric(i)));
1557:
1558: if (n.hasProperty(INANALYZE)) {
1559: n.getGeneric(i).setProperty(INANALYZE, Boolean.TRUE);
1560: }
1561: }
1562: final List<Node> members = mapper.getMemberNodes(n
1563: .getProperty(TYPE));
1564: // Make type arguments
1565: Node typeArgs = GNode.create("TypeArguments");
1566: final Node typeNode;
1567: for (Node ob : members)
1568: typeArgs.add(ob);
1569:
1570: if (!members.isEmpty()) {
1571: typeNode = GNode.create("Type", GNode.create(
1572: "InstantiatedType", GNode.create(
1573: "TypeInstantiation", "Tuple", null), GNode
1574: .create("TypeInstantiation", "T"
1575: + members.size(), typeArgs)), null);
1576: } else {
1577: typeNode = GNode.create("Type", GNode.create(
1578: "QualifiedIdentifier", "Tuple", "T0"), null);
1579: }
1580: return toNewExpression2(typeNode, args, null);
1581: }
1582:
1583: /**
1584: * Create java code for a list literal.
1585: *
1586: * @param n The list expression or pattern node.
1587: * @return A Pair representing this list.
1588: */
1589: private Node makeList(GNode n) {
1590: List<Node> arguments = new ArrayList<Node>(n.size());
1591:
1592: //process each list element
1593: for (int i = 0; i < n.size(); i++) {
1594: arguments.add((GNode) dispatch(n.getGeneric(i)));
1595:
1596: if (n.hasProperty(INANALYZE)) {
1597: n.getGeneric(i).setProperty(INANALYZE, Boolean.TRUE);
1598: }
1599: }
1600:
1601: if (arguments.isEmpty()) {
1602: final String typeName = getType(mapper.getBase(n
1603: .getProperty(TYPE)));
1604: final Node typeNode = mapper.toTypeNode(mapper.getBase(n
1605: .getProperty(TYPE)), false);
1606: if ("Object".equals(typeName)) {
1607: return factory.invocation(toIdentifier("Pair"),
1608: "empty", arguments);
1609: } else {
1610: return factory.pairEmpty(typeNode);
1611: }
1612: }
1613:
1614: //cons up the list
1615: Node newPair = factory.newPair(mapper.toTypeNode(n
1616: .getProperty(TYPE), false), arguments.get(0));
1617:
1618: for (int i = 1; i < arguments.size(); i++) {
1619: newPair = factory.appendPair(newPair, toNewExpression2(
1620: mapper.toTypeNode(n.getProperty(TYPE), false),
1621: GNode.create("Arguments", arguments.get(i)), null));
1622: }
1623: return newPair;
1624: }
1625:
1626: /**
1627: * Process a cons pattern.
1628: *
1629: * @param n The cons pattern node.
1630: * @return The java equivalent.
1631: */
1632: public Node visitConsPattern(GNode n) {
1633: String name = table.freshJavaId("list");
1634: String rhs = (String) n.getProperty(RHS);
1635:
1636: String matchArg = (String) n.getProperty(MATCHARG);
1637:
1638: ((Node) n.getProperty(BINDINGS)).add(makeVarDec2(name, mapper
1639: .toTypeNode(n.getProperty(TYPE), false), factory
1640: .cast(factory.cast(toIdentifier(rhs)))));
1641:
1642: Node head = n.getGeneric(0);
1643: head.setProperty(MATCHARG, "Primitives.wrapHead(" + matchArg
1644: + ")");
1645: head.setProperty(RHS, "Primitives.wrapHead(" + name + ")");
1646: head.setProperty(BINDINGS, n.getProperty(BINDINGS));
1647:
1648: Node tail = n.getGeneric(1);
1649: tail.setProperty(MATCHARG, "Primitives.wrapTail(" + matchArg
1650: + ".tail()");
1651: tail.setProperty(RHS, "Primitives.wrapTail(" + name + ")");
1652: tail.setProperty(BINDINGS, n.getProperty(BINDINGS));
1653:
1654: if ((head.hasName("WildCard") || head.hasName("Variable"))
1655: && (tail.hasName("WildCard") || tail
1656: .hasName("Variable"))) {
1657: dispatch(head);
1658: dispatch(tail);
1659: return toLiteral("BooleanLiteral", "true");
1660: } else if (tail.hasName("WildCard") || tail.hasName("Variable")) {
1661: head = (Node) dispatch(head);
1662: dispatch(tail);
1663: return factory.jequals(head, factory
1664: .headWrapper(toIdentifier(matchArg)));
1665: } else if (head.hasName("WildCard") || head.hasName("Variable")) {
1666: tail = (Node) dispatch(tail);
1667: dispatch(head);
1668: return factory.jequals(tail, factory
1669: .tailWrapper(toIdentifier(matchArg)));
1670: }
1671:
1672: return factory.jand(factory.jequals((Node) dispatch(head),
1673: factory.headWrapper(toIdentifier(matchArg))), factory
1674: .jequals((Node) dispatch(tail), factory
1675: .tailWrapper(toIdentifier(matchArg))));
1676: }
1677:
1678: /**
1679: * Process a match expression type.
1680: *
1681: * @param n The match expression node.
1682: * @return The java equivalent.
1683: */
1684: public Node visitMatchExpression(GNode n) {
1685:
1686: Object argType = mapper.getPatternMatchLeftType(n.getGeneric(1)
1687: .getProperty(TYPE));
1688:
1689: String matchArg = table.freshJavaId("arg");
1690:
1691: n.getGeneric(1).setProperty(TOP, null);
1692: n.getGeneric(1).setProperty(MATCHARG, matchArg);
1693: n.getGeneric(1).setProperty(RHS, matchArg);
1694:
1695: List<Node> nodes = new ArrayList<Node>();
1696:
1697: final Node argTypeNode = mapper.toTypeNode(argType, false);
1698:
1699: if (nodeType.equals(argTypeNode)
1700: || gnodeType.equals(argTypeNode)) {
1701: nodes.add(makeVarDec2(matchArg, argTypeNode, factory
1702: .gnodeCast((Node) dispatch(n.getGeneric(0)))));
1703: if (n.hasProperty(INANALYZE)) {
1704: n.getGeneric(1).setProperty(ANNOTATE, Boolean.TRUE);
1705: } else {
1706: n.getGeneric(1).setProperty(SCOPE, Boolean.TRUE);
1707: }
1708: } else {
1709: nodes.add(makeVarDec2(matchArg, argTypeNode, factory
1710: .cast((Node) dispatch(n.getGeneric(0)))));
1711: }
1712:
1713: // Checking and return null
1714: nodes.add(factory.ifStatement4(toIdentifier(matchArg)));
1715:
1716: @SuppressWarnings("unchecked")
1717: List<Node> matches = (List<Node>) dispatch(n.getGeneric(1));
1718:
1719: nodes.addAll(matches);
1720: nodes.add(factory.ret(nullNode));
1721:
1722: Node match = factory.matchExpression(mapper.toTypeNode(n
1723: .getProperty(TYPE), false), nodes);
1724:
1725: return match;
1726: }
1727:
1728: /**
1729: * Check if this pattern match is on non-node type constructors.
1730: *
1731: * @param n the pattern match node.
1732: * @return <code> true </code> if type constructor match. <code> false</code>
1733: * otherwise.
1734: */
1735: private boolean isTypeConstructorMatch(Node n) {
1736: for (int i = 0; i < n.size(); i++) {
1737: if (n.getGeneric(i).getGeneric(0).getGeneric(0).hasName(
1738: "TypeConstructorPattern")
1739: && !mapper.isNode(n.getGeneric(i).getGeneric(0)
1740: .getGeneric(0).getProperty(TYPE))) {
1741: return true;
1742: }
1743: }
1744: return false;
1745: }
1746:
1747: /**
1748: * Process a pattern matching expression.
1749: *
1750: * @param n The pattern matching node.
1751: * @return A list with the unified types of the left and right sides
1752: * of the pattern matching.
1753: */
1754: public List<Node> visitPatternMatching(GNode n) {
1755:
1756: int size = n.size();
1757: ArrayList<Node> nodes = new ArrayList<Node>();
1758:
1759: boolean tcmatch = isTypeConstructorMatch(n);
1760:
1761: for (int i = 0; i < size; i++) {
1762: Node patterns = n.getGeneric(i).getGeneric(0);
1763:
1764: for (int j = 0; j < patterns.size(); j++) {
1765:
1766: String foo = (String) n.getGeneric(i).getProperty(
1767: "enterScope");
1768: if (null == foo)
1769: foo = (String) n.getGeneric(i).getProperty(
1770: "enterScope");
1771:
1772: enterScope(foo);
1773:
1774: Node pmatch2 = GNode.create("PatternMatch", GNode
1775: .create("Patterns", patterns.getGeneric(j)), n
1776: .getGeneric(i).getGeneric(1));
1777: pmatch2.setProperty(TOP, null);
1778: pmatch2.setProperty(MATCHARG, n.getProperty(MATCHARG));
1779: pmatch2.setProperty(RHS, n.getProperty(MATCHARG));
1780:
1781: if (n.hasProperty(ANNOTATE)) {
1782: pmatch2.setProperty(ANNOTATE, Boolean.TRUE);
1783: }
1784: if (n.hasProperty(SCOPE)) {
1785: pmatch2.setProperty(SCOPE, Boolean.TRUE);
1786: }
1787:
1788: if (tcmatch)
1789: pmatch2.setProperty("TCMatch", null);
1790:
1791: nodes.add((Node) dispatch(pmatch2));
1792:
1793: exitScope(foo);
1794: }
1795: }
1796:
1797: if (runtime.test("optimizeMatch")) {
1798:
1799: HashMap<String, ArrayList<Node>> bins = new HashMap<String, ArrayList<Node>>();
1800:
1801: bins.put("default", new ArrayList<Node>());
1802:
1803: for (int i = 0; i < nodes.size(); i++) {
1804: Node node = nodes.get(i);
1805: if (node.hasProperty("TName")) {
1806: String name = (String) node.getProperty("TName");
1807:
1808: if (bins.containsKey(name)) {
1809: bins.get(name).add(node);
1810: } else {
1811: ArrayList<Node> temp = new ArrayList<Node>();
1812: temp.add(node);
1813: bins.put(name, temp);
1814: }
1815: } else {
1816: bins.get("default").add(node);
1817: }
1818: }
1819:
1820: ArrayList<Node> nodes2 = new ArrayList<Node>();
1821: Node switchn = factory.switchStmnt(toIdentifier((String) n
1822: .getProperty(MATCHARG)));
1823:
1824: switchn = GNode.ensureVariable(GNode.cast(switchn));
1825:
1826: String defname = table.freshJavaId("default");
1827:
1828: for (String key : bins.keySet()) {
1829: if ("default".equals(key))
1830: continue;
1831: switchn.add(makeCase(GNode.create("PrimaryIdentifier",
1832: key), bins.get(key), defname));
1833: }
1834: switchn.add(GNode.create("DefaultClause", GNode.create(
1835: "BreakStatement", null)));
1836:
1837: nodes2.add(factory.switchWrap(toIdentifier((String) n
1838: .getProperty(MATCHARG)), switchn));
1839:
1840: if (bins.get("default").size() > 0) {
1841: nodes2.addAll(bins.get("default"));
1842: }
1843:
1844: if (tcmatch) {
1845: return nodes2;
1846: }
1847: }
1848:
1849: return nodes;
1850: }
1851:
1852: /**
1853: * Transform a typed pattern.
1854: *
1855: * @param n The typed pattern node.
1856: * @return The java code for the typed pattern.
1857: */
1858: public Node visitTypedPattern(GNode n) {
1859: return (Node) dispatch(n.getGeneric(0));
1860: }
1861:
1862: /**
1863: * Generate an as pattern.
1864: *
1865: * @param n The as pattern node.
1866: * @return The java as pattern node.
1867: */
1868: public Node visitAsPattern(GNode n) {
1869: Node pat = n.getGeneric(0);
1870: String rhs = (String) n.getProperty(RHS);
1871: String matchArg = (String) n.getProperty(MATCHARG);
1872:
1873: if (n.hasProperty(TOP))
1874: pat.setProperty(TOP, null);
1875:
1876: pat.setProperty(MATCHARG, n.getProperty(MATCHARG));
1877: pat.setProperty(RHS, rhs);
1878: pat.setProperty(BINDINGS, n.getProperty(BINDINGS));
1879: pat.setProperty(TYPE, pat.getProperty(TYPE));
1880:
1881: ((Node) n.getProperty(BINDINGS)).add(makeVarDec2(
1882: n.getString(1), mapper.toTypeNode(
1883: pat.getProperty(TYPE), false), factory
1884: .cast(toIdentifier(matchArg))));
1885:
1886: if (isLiteral(n))
1887: return factory.jequals((Node) dispatch(pat),
1888: toIdentifier(matchArg));
1889: return (Node) dispatch(pat);
1890: }
1891:
1892: /**
1893: * Generate a when pattern.
1894: *
1895: * @param n The when pattern node.
1896: * @return An if statement represeing the when expression.
1897: */
1898: public Node visitWhenPattern(GNode n) {
1899: Node pat = n.getGeneric(0);
1900:
1901: pat.setProperty(TOP, null);
1902: pat.setProperty(RHS, n.getProperty(RHS));
1903: pat.setProperty(BINDINGS, n.getProperty(BINDINGS));
1904: pat.setProperty(TYPE, n.getProperty(TYPE));
1905: pat.setProperty(MATCHARG, n.getProperty(MATCHARG));
1906:
1907: if (n.hasProperty(TOP))
1908: pat.setProperty(TOP, null);
1909:
1910: return factory.ifStatement((Node) dispatch(n.getGeneric(1)),
1911: (Node) dispatch(pat));
1912: }
1913:
1914: //additional conditions that need to be met after the basic pattern
1915: //is matched and bound.
1916: //For example, in the pattern Foo(a, a) -> e, both a's are wildcards.
1917: //however the expression is only executed if the a's are equal.
1918: //we therefor translate that pattern match as follows
1919: // if ( Constructor.make("Foo", wild1, wild2).equals(arg)) {
1920: // a = arg.get(1);
1921: // if (a.equals(arg.get(2))) { ***conditions***
1922: // return e;
1923: // }
1924: // }
1925: Node conditions = null;
1926:
1927: /**
1928: * Process a pattern match.
1929: *
1930: * @param n The pattern match node.
1931: * @return The if statement representing this pattern match.
1932: */
1933: public Node visitPatternMatch(GNode n) {
1934: Node savedConditions = conditions;
1935:
1936: String rhs = (String) n.getProperty(RHS);
1937: Node pattern = n.getGeneric(0);
1938:
1939: Node expr = n.getGeneric(1);
1940: String matchArg = (String) n.getProperty(MATCHARG);
1941:
1942: Node ifStmnt = toIfStatement(null, null);
1943:
1944: if (n.hasProperty(INANALYZE))
1945: expr.setProperty(INANALYZE, Boolean.TRUE);
1946:
1947: pattern.setProperty(TOP, null);
1948: pattern.setProperty(BINDINGS, ifStmnt.getGeneric(1));
1949: pattern.setProperty(MATCHARG, matchArg);
1950: pattern.setProperty(RHS, rhs);
1951:
1952: if ("WhenPattern".equals(pattern.getGeneric(0).getName())) {
1953: Node when = (GNode) dispatch(pattern);
1954:
1955: if (pattern.getGeneric(0).getGeneric(0).hasName("WildCard")
1956: || pattern.getGeneric(0).getGeneric(0).hasName(
1957: "Variable")) {
1958: ifStmnt.set(0, toLiteral("BooleanLiteral", "true"));
1959: } else {
1960: ifStmnt.set(0, GNode.create(when.getGeneric(1)
1961: .getGeneric(0)));
1962: }
1963:
1964: when.getGeneric(1).set(0,
1965: factory.ret((Node) dispatch(expr)));
1966: ifStmnt.getGeneric(1).add(when);
1967:
1968: if (n.hasProperty(ANNOTATE) || n.hasProperty(SCOPE)) {
1969: return augmentIfStatement(ifStmnt, matchArg, n);
1970: }
1971: return ifStmnt;
1972: }
1973:
1974: if (pattern.hasName("WildCard") || pattern.hasName("Variable")) {
1975: ifStmnt.set(0, toLiteral("BooleanLiteral", "true"));
1976: dispatch(pattern);
1977: } else {
1978: ifStmnt.set(0, dispatch(pattern));
1979: }
1980:
1981: Node res = (GNode) dispatch(expr);
1982: if (res.hasName("Block")) {
1983: ifStmnt.getGeneric(1).add(res);
1984: } else {
1985: if (conditions == null) {
1986: ifStmnt.getGeneric(1).add(
1987: factory
1988: .ret(factory
1989: .cast((Node) dispatch(expr))));
1990: } else {
1991: Node b = GNode.create("Block");
1992: Node newIf = toIfStatement(conditions, b);
1993: b.add(factory.ret(factory.cast((Node) dispatch(expr))));
1994: ifStmnt.getGeneric(1).add(newIf);
1995: }
1996: }
1997: conditions = savedConditions;
1998:
1999: if (n.hasProperty(ANNOTATE) || n.hasProperty(SCOPE)) {
2000: return augmentIfStatement(ifStmnt, matchArg, n);
2001: }
2002:
2003: if (n.hasProperty("TCMatch")) {
2004: if (n.getGeneric(0).getGeneric(0).hasName(
2005: "TypeConstructorPattern")) {
2006: ifStmnt.setProperty("TName", n.getGeneric(0)
2007: .getGeneric(0).getString(0));
2008: }
2009: if (n.getGeneric(0).getGeneric(0).hasName("AsPattern")
2010: && n.getGeneric(0).getGeneric(0).getGeneric(0)
2011: .hasName("TypeConstructorPattern")) {
2012: ifStmnt.setProperty("TName", n.getGeneric(0)
2013: .getGeneric(0).getGeneric(0).getString(0));
2014: }
2015: }
2016:
2017: return ifStmnt;
2018: }
2019:
2020: /**
2021: * Process a type constructor pattern.
2022: *
2023: * @param n The type constructor node.
2024: * @return The java equivalent.
2025: */
2026: public Node visitTypeConstructorPattern(GNode n) {
2027:
2028: final String typeName = n.getString(0);
2029: final Object type = n.getProperty(TYPE);
2030: final Node typeNode = mapper.toTypeNode(type, false);
2031:
2032: String matchArg = (String) n.getProperty(MATCHARG);
2033:
2034: Node matchArgNode = toIdentifier(matchArg);
2035: Node condition = null;
2036: Node inner = (Node) n.getProperty(BINDINGS);
2037:
2038: final int size = n.size();
2039:
2040: if (nodeType.equals(typeNode) || gnodeType.equals(typeNode)) {
2041: condition = factory.hasNameCall(toIdentifier(matchArg),
2042: toLiteral("StringLiteral", "\"" + typeName + "\""));
2043:
2044: if ((size == 1) || n.getGeneric(1).hasName("WildCard")) {
2045: //do nothing since the initial condition is sufficient
2046: } else {
2047: Node params = n.getGeneric(1);
2048: List<String> members = mapper.getMembers(type);
2049: List<Object> memberObjects = mapper
2050: .getMemberObjects(type);
2051: List<Node> memberNodes = mapper.getMemberNodes(type);
2052:
2053: boolean hasVar = false;
2054: for (Object o : memberObjects) {
2055: if (mapper.isVariable(o))
2056: hasVar = true;
2057: }
2058:
2059: //check the last item to see if it's a list variable
2060: //need to also check the last item to see if it's a node var
2061:
2062: if (members.get(members.size() - 1).startsWith("Pair")
2063: || hasVar) {
2064: condition = factory.jand(condition, factory
2065: .sizeGreaterEqual(matchArgNode,
2066: toLiteral("IntegerLiteral",
2067: Integer.toString((params
2068: .size() - 1)))));
2069: } else {
2070: condition = factory.jand(condition, factory
2071: .sizeEqual(matchArgNode, toLiteral(
2072: "IntegerLiteral", Integer
2073: .toString(params.size()))));
2074: }
2075:
2076: for (int i = 0; i < params.size(); i++) {
2077:
2078: String tname = members.get(i);
2079: Node tNode = memberNodes.get(i);
2080:
2081: Node node = params.getGeneric(i);
2082: if (node.hasName("Variable")) {
2083: if ("String".equals(tname)) {
2084: inner.add(factory.makeNodeBinding2(node
2085: .getString(0),
2086: toIdentifier(matchArg), toLiteral(
2087: "IntegerLiteral", Integer
2088: .toString(i))));
2089: } else if ("Node".equals(members.get(i))
2090: || "GNode".equals(members.get(i))) {
2091: inner.add(factory.makeNodeBinding(node
2092: .getString(0),
2093: toIdentifier(matchArg), toLiteral(
2094: "IntegerLiteral", Integer
2095: .toString(i))));
2096: } else if (tname.startsWith("Pair")) {
2097: inner
2098: .add(makeVarDec2(
2099: node.getString(0),
2100: tNode,
2101: factory
2102: .cast(toIdentifier("Primitives.getChildren("
2103: + matchArg
2104: + ", "
2105: + i
2106: + ", "
2107: + matchArg
2108: + ".size())"))));
2109: }
2110:
2111: continue;
2112: }
2113:
2114: if (node.hasName("WildCard"))
2115: continue;
2116:
2117: if (isLiteral(node)) {
2118: condition = factory.jand(condition, factory
2119: .jequals2((Node) dispatch(node),
2120: toIdentifier(matchArg
2121: + ".getString(" + i
2122: + ")")));
2123: continue;
2124: }
2125:
2126: node.setProperty(BINDINGS, inner);
2127:
2128: if ("String".equals(members.get(i))) {
2129: node.setProperty(MATCHARG, matchArg
2130: + ".getString(" + i + ")");
2131: } else if ("Node".equals(members.get(i))
2132: || "GNode".equals(members.get(i))) {
2133: node.setProperty(MATCHARG, matchArg
2134: + ".getGeneric(" + i + ")");
2135: } else if (members.get(i).startsWith("Pair")) {
2136:
2137: node.setProperty(MATCHARG,
2138: "Primitives.getChildren(" + matchArg
2139: + ", " + i + ", " + matchArg
2140: + ".size())");
2141: }
2142:
2143: condition = factory.jand(condition,
2144: (Node) dispatch(node));
2145: }
2146: }
2147: } else {
2148: condition = factory.isMethodCall(matchArgNode, "is"
2149: + typeName);
2150:
2151: if (n.size() == 1 || n.getGeneric(1).hasName("WildCard")) {
2152: //do nothing since the initial condition is sufficient
2153: } else {
2154: Node params = n.getGeneric(1);
2155:
2156: List<Node> memberNodes = mapper.getMemberNodes(type);
2157:
2158: for (int i = 0; i < params.size(); i++) {
2159: Node node = params.getGeneric(i);
2160:
2161: if (node.hasName("WildCard")) {
2162: continue;
2163: }
2164: if (node.hasName("Variable")) {
2165: inner.add(makeVarDec2(node.getString(0),
2166: memberNodes.get(i), factory
2167: .cast(toIdentifier(matchArg
2168: + ".getTuple().get"
2169: + (i + 1) + "()"))));
2170: continue;
2171: }
2172:
2173: if (isLiteral(node)) {
2174: condition = factory.jand(condition, factory
2175: .jequals2((Node) dispatch(node),
2176: toIdentifier(matchArg
2177: + ".getTuple().get"
2178: + (i + 1) + "()")));
2179: continue;
2180: }
2181:
2182: node.setProperty(MATCHARG, matchArg
2183: + ".getTuple().get" + (i + 1) + "()");
2184: condition = factory.jand(condition,
2185: (Node) dispatch(node));
2186: }
2187: }
2188: }
2189:
2190: if (n.hasProperty(TOP) || n.hasProperty("ancestor")) {
2191:
2192: condition = replaceMatchArg(condition, matchArg);
2193:
2194: if (n.hasProperty("ancestor")) {
2195: Node node = factory.ancestorExpression(factory
2196: .ret(condition));
2197:
2198: if (nodeMatches.containsKey(node)) {
2199: return factory.support(toIdentifier(output
2200: + "Support"), nodeMatches.get(node));
2201: } else {
2202: String arg = table.freshJavaId("nodeMatch");
2203: staticFields.add(factory
2204: .supportNodeMatch(arg, node));
2205: nodeMatches.put(node, arg);
2206: return factory.support(toIdentifier(output
2207: + "Support"), arg);
2208: }
2209: }
2210:
2211: String matchName = table.freshJavaId("match");
2212: Match ms = new Match(mapper.toTypeNode(n.getProperty(TYPE),
2213: false), condition);
2214: if (matches.containsKey(ms)) {
2215: matchName = matches.get(ms);
2216: } else {
2217: matches.put(ms, matchName);
2218: Node matchFunction = factory.matchFunction(matchName,
2219: mapper.toTypeNode(type, false), condition);
2220:
2221: matchFunction.getGeneric(4).getGeneric(0).set(3, "m");
2222: staticFields.add(matchFunction);
2223: }
2224:
2225: return factory.matchCall(toIdentifier(output + "Support"),
2226: matchName, toIdentifier((String) n
2227: .getProperty(MATCHARG)));
2228: } else {
2229: return condition;
2230: }
2231: }
2232:
2233: /**
2234: * Process pattern parameters.
2235: *
2236: * @param n The pattern parameters node.
2237: * @return A new tuple expression.
2238: */
2239: public Node visitPatternParameters(GNode n) {
2240: return makeTuple(n);
2241: }
2242:
2243: /**
2244: * Process a variant type definition.
2245: *
2246: * @param n The variant type node.
2247: */
2248: public void visitVariantDeclaration(GNode n) {
2249: String baseName = (String) n.getProperty("name");
2250: Node baseBody = GNode.create("ClassBody");
2251:
2252: Node enums = GNode.create("EnumConstants");
2253: Node tag = GNode.create("EnumDeclaration", GNode.create(
2254: "Modifiers", GNode.create("Modifier", "public"), GNode
2255: .create("Modifier", "static")), "Tag", null,
2256: enums, null);
2257:
2258: baseBody.add(tag);
2259: baseBody.add(factory.defaultConstr(baseName));
2260: baseBody.add(factory.getTagAbstract());
2261:
2262: for (int i = 0; i < n.size(); i++) {
2263: Node tc = n.getGeneric(i);
2264: addEnum(enums, tc.getString(0));
2265: Object tcType = tc.getProperty(TYPE);
2266:
2267: List<String> types = mapper.getMembers(tcType);
2268: List<Node> typeNodes = mapper.getMemberNodes(tcType);
2269:
2270: int size = types.size();
2271:
2272: Node fparams = GNode.create("FormalParameters");
2273: Node classBody = GNode.create("ClassBody");
2274:
2275: //create a constructor
2276: Node createArgs = GNode.create("Arguments");
2277: for (int j = 0; j < size; j++) {
2278: Node fptype = typeNodes.get(j);
2279: String fpname = "member" + (j + 1);
2280:
2281: createArgs.add(toIdentifier(fpname));
2282: fparams.add(GNode.create("FormalParameter", null,
2283: fptype, null, fpname, null));
2284: }
2285:
2286: Node constrblock1 = GNode.create("Block");
2287: Node constr1 = GNode.create("ConstructorDeclaration", pmod,
2288: null, tc.getString(0), fparams, null, constrblock1);
2289:
2290: // Make type arguments
2291: Node typeArgs = GNode.create("TypeArguments");
2292:
2293: final Node typeNode;
2294: for (Node ob : typeNodes)
2295: typeArgs.add(ob);
2296:
2297: if (!typeNodes.isEmpty()) {
2298: typeNode = GNode.create("Type", GNode.create(
2299: "InstantiatedType", GNode.create(
2300: "TypeInstantiation", "Tuple", null),
2301: GNode.create("TypeInstantiation", "T"
2302: + typeNodes.size(), typeArgs)), null);
2303: } else {
2304: typeNode = GNode.create("Type", GNode.create(
2305: "QualifiedIdentifier", "Tuple", "T0"), null);
2306: }
2307:
2308: constrblock1.add(factory.assign(toIdentifier("tuple"),
2309: factory.newExpr(typeNode,
2310: makeArgumentList(createArgs))));
2311:
2312: classBody.add(constr1);
2313: classBody.add(factory.getTag(tc.getString(0)));
2314:
2315: //add an isXXX method to the base class
2316: Node isBase = factory.isMethod();
2317: isBase.set(3, "is" + tc.getString(0));
2318: baseBody.add(isBase);
2319:
2320: //add an isXXX method to the variant type class
2321: Node isVariant = factory.isMethod();
2322: isVariant.set(3, "is" + tc.getString(0));
2323: isVariant.getGeneric(7).getGeneric(0).getGeneric(0).set(0,
2324: "true");
2325: classBody.add(isVariant);
2326:
2327: // Add getName() method
2328: classBody.add(factory.getNameMethod(GNode.create(
2329: "StringLiteral", "\"" + tc.getString(0) + "\"")));
2330: // ADD equals methods
2331: for (Equality e : equalities) {
2332: if (e.name.equals(tc.getString(0))) {
2333: classBody.add(createVariantEqualsMethod(tc
2334: .getString(0)));
2335: break;
2336: }
2337: }
2338:
2339: // Add toString()
2340: String toString = "\"" + tc.getString(0);
2341: if (size > 0) {
2342: toString += " of \" + tuple.toString()";
2343: } else {
2344: toString += "\"";
2345: }
2346:
2347: Node toStringNode = factory.toStringMethod();
2348: toStringNode.set(7, GNode.create("Block", factory
2349: .ret(toLiteral("StringLiteral", toString))));
2350:
2351: classBody.add(toStringNode);
2352:
2353: final Node baseNameNode = GNode.create("Type",
2354: GNode
2355: .create("InstantiatedType", GNode.create(
2356: "TypeInstantiation", baseName,
2357: GNode.create("TypeArguments",
2358: typeNode))), null);
2359:
2360: tbody.add(comment(makeExtendedClassDecl(tc.getString(0),
2361: baseNameNode, classBody),
2362: "Implementation of constructor '" + tc.getString(0)
2363: + "' in variant '" + baseName + "'."));
2364: }
2365:
2366: final String typeName = baseName + "<T extends Tuple>";
2367: final Node vNode = GNode.create("Type", GNode.create(
2368: "InstantiatedType", GNode.create("TypeInstantiation",
2369: "Variant", GNode.create("TypeArguments", GNode
2370: .create("Type", GNode.create(
2371: "QualifiedIdentifier", "T"),
2372: null)))), null);
2373:
2374: tbody.add(comment(makeExtendedClassDecl2(typeName, vNode,
2375: baseBody),
2376: "Superclass of all constructors in variant '"
2377: + baseName + "'."));
2378: }
2379:
2380: /**
2381: * Create an extends class declaration.
2382: *
2383: * @param n The name of the class.
2384: * @param b The base name node (the class that is extended).
2385: * @param classBody The class body.
2386: */
2387: private Node makeExtendedClassDecl(String n, Node b, Node classBody) {
2388: Node foo = factory.extendsDecl();
2389: foo.set(1, n);
2390: foo.getGeneric(3).set(0, b);
2391: foo.set(5, classBody);
2392: return foo;
2393: }
2394:
2395: /**
2396: * Create an abstract extends class declaration.
2397: *
2398: * @param n The name of the class.
2399: * @param b The base name node (the class that is extended).
2400: * @param classBody The class body.
2401: */
2402: private Node makeExtendedClassDecl2(String n, Node b, Node classBody) {
2403: Node foo = factory.extendsDecl2();
2404: foo.set(1, n);
2405: foo.getGeneric(3).set(0, b);
2406: foo.set(5, classBody);
2407: return foo;
2408: }
2409:
2410: /**
2411: * Create an implements class declaration.
2412: *
2413: * @param n The name of the class.
2414: * @param b The base name (the interface that is implemented).
2415: * @param classBody The class body.
2416: */
2417: private Node makeImplementedClassDecl(String n, String b,
2418: Node classBody) {
2419: Node foo = factory.implements Decl();
2420: foo.set(1, n);
2421: foo.getGeneric(4).set(0, toType(b));
2422: foo.set(5, classBody);
2423: return foo;
2424: }
2425:
2426: /**
2427: * Process a record type definition.
2428: *
2429: * @param n The type information.
2430: */
2431: public void visitRecordDeclaration(GNode n) {
2432: String name = (String) n.getProperty("name");
2433: Object t = n.getProperty(TYPE);
2434:
2435: List<Node> fieldTypeNodes = mapper.getFieldTypeNodes(t);
2436: List<String> fieldNames = mapper.getFieldNames(t);
2437: Node classBody = GNode.create("ClassBody");
2438: StringBuilder toString = new StringBuilder("\"{\"");
2439:
2440: //ADD equals method for type record
2441: Node equals = null;
2442: Node eqBlock = GNode.create("Block");
2443:
2444: if ("type".equals(name)) {
2445: equals = createTypeRecordEquals();
2446: } else {
2447: equals = factory.equalsMethod();
2448: equals.set(7, eqBlock);
2449: eqBlock.add(toIfStatement(factory.jnot(toInstanceOf(
2450: toIdentifier("o"), toType(name))), factory
2451: .ret(toLiteral("BooleanLiteral", "true"))));
2452: eqBlock.add(makeVarDec("r", name, factory
2453: .cast(toIdentifier("o"))));
2454: }
2455:
2456: Node constrblk = GNode.create("Block");
2457: Node constr = GNode.create("ConstructorDeclaration", pmod,
2458: null, name, GNode.create("FormalParameters"), null,
2459: constrblk);
2460:
2461: Node fps = constr.getGeneric(3);
2462:
2463: for (int i = 0; i < fieldNames.size(); i++) {
2464: String fname = fieldNames.get(i);
2465: Node ftype = fieldTypeNodes.get(i);
2466: toString.append(" + (null == " + fname + " ? \"?\" : "
2467: + fname + ".toString())");
2468:
2469: fps.add(GNode.create("FormalParameter", null, ftype, null,
2470: fname, null));
2471: constrblk.add(factory.assign(factory.this Expr(fname),
2472: toIdentifier(fname)));
2473:
2474: if (i < fieldNames.size() - 1)
2475: toString.append(" + \",\" ");
2476:
2477: classBody.add(factory.publicFieldDecl(ftype, fname));
2478:
2479: eqBlock.add(toIfStatement(factory.jnot(factory.jequals(
2480: toIdentifier(fname), factory.fieldExpression(
2481: toIdentifier("r"), fname))), factory
2482: .ret(toLiteral("BooleanLiteral", "false"))));
2483: }
2484: eqBlock.add(factory.ret(toLiteral("BooleanLiteral", "true")));
2485:
2486: toString.append(" + " + "\"}\"");
2487:
2488: //create the toString method for this record
2489: Node toStringNode = factory.toStringMethod();
2490: toStringNode.getGeneric(7).set(
2491: 0,
2492: factory.ret(toLiteral("StringLiteral", toString
2493: .toString())));
2494:
2495: classBody.add(constr);
2496: classBody.add(equals);
2497: classBody.add(toStringNode);
2498:
2499: tbody
2500: .add(comment(makeImplementedClassDecl(name, "Record",
2501: classBody), "Implementation of record '" + name
2502: + "'."));
2503: }
2504:
2505: /**
2506: * Create a new named tuple.
2507: *
2508: * @param n The tuple constructor node.
2509: * @return The java equivalent.
2510: */
2511: public Node visitTupleConstructor(GNode n) {
2512: Node args = GNode.create("Arguments");
2513:
2514: if (n.hasProperty(INANALYZE)) {
2515: for (int j = 1; j < n.size(); j++) {
2516: n.getGeneric(j).setProperty(INANALYZE, Boolean.TRUE);
2517: }
2518: }
2519:
2520: if (n.getProperty(TYPE) != null
2521: && gnodeType.equals(mapper.toTypeNode(n
2522: .getProperty(TYPE), false))
2523: || nodeType.equals(mapper.toTypeNode(n
2524: .getProperty(TYPE), false))) {
2525: List<Node> args2 = new ArrayList<Node>(n.size());
2526: args2.add(toLiteral("StringLiteral", "\"" + n.getString(0)
2527: + "\""));
2528:
2529: for (int i = 1; i < n.size(); i++) {
2530: args2.add((Node) dispatch(n.getGeneric(i)));
2531: }
2532:
2533: return factory.gnodeCreate(args2);
2534: }
2535:
2536: for (int i = 1; i < n.size(); i++) {
2537: args.add(dispatch(n.getGeneric(i)));
2538: }
2539:
2540: return toNewExpression2(mapper
2541: .toTypeNode(n.getString(0), false), args, null);
2542: }
2543:
2544: /**
2545: * Create an instanceof node.
2546: *
2547: * @param n1 The object node.
2548: * @param n2 The type node.
2549: * @return The instanceof expression
2550: */
2551: private Node toInstanceOf(Node n1, Node n2) {
2552: return GNode.create("InstanceOfExpression", n1, n2);
2553: }
2554:
2555: /**
2556: * Process a LowerID node.
2557: *
2558: * @return The primary identifier corresponding to this node.
2559: */
2560: public Node visitLowerID(GNode n) {
2561: final String newName = Primitives.convertName(n.getString(0));
2562: if (Primitives.isPrimitive(newName)) {
2563: if ("nonce".equals(newName)) {
2564: return factory.apply2(toIdentifier("Primitives."
2565: + newName));
2566: }
2567: return toIdentifier("Primitives." + newName);
2568: } else
2569: return toIdentifier(newName);
2570: }
2571:
2572: /**
2573: * Process a variable.
2574: *
2575: * @param n The variable node.
2576: */
2577: public void visitVariable(GNode n) {
2578: String name = n.getString(0);
2579: //make bindings for this variable if necessary
2580: Object type = n.getProperty(TYPE);
2581:
2582: final Node typeNode = mapper.toTypeNode(type, false);
2583:
2584: String rhs = (String) n.getProperty(RHS);
2585:
2586: if (table.current().isDefinedLocally(
2587: SymbolTable.toNameSpace(name, "value"))) {
2588:
2589: if (nodeType.equals(typeNode) || gnodeType.equals(typeNode)) {
2590: ((GNode) n.getProperty(BINDINGS))
2591: .add(makeVarDec2(name, typeNode, factory
2592: .gnodeCast(toIdentifier(rhs))));
2593: } else {
2594: ((GNode) n.getProperty(BINDINGS)).add(makeVarDec2(name,
2595: typeNode, factory.cast(toIdentifier(rhs))));
2596: }
2597: } else {
2598: Node cond = factory.jequals(toIdentifier(rhs),
2599: toIdentifier(name));
2600: if (conditions == null) {
2601: conditions = cond;
2602: } else {
2603: conditions = factory.jand(conditions, cond);
2604: }
2605: }
2606: }
2607:
2608: /**
2609: * Transform a record expression.
2610: *
2611: * @param n The record expression node.
2612: * @return A java equivalent.
2613: */
2614: public Node visitRecordExpression(GNode n) {
2615:
2616: boolean bottomWith = (null != n.getGeneric(0))
2617: && n.getGeneric(0).getGeneric(0).hasName("Bottom");
2618:
2619: if (n.hasProperty(INANALYZE)) {
2620: for (int j = 0; j < n.size(); j++) {
2621: n.getGeneric(j).setProperty(INANALYZE, Boolean.TRUE);
2622: }
2623: }
2624:
2625: // Check the first field assign, field name and replaceType variable
2626: if (replaceType && "type".equals(n.getGeneric(1).getString(0))) {
2627: return (Node) dispatch(n.getGeneric(1).getGeneric(1));
2628: }
2629:
2630: Object rt = n.getProperty(TYPE);
2631:
2632: List<String> fieldNames = mapper.getFieldNames(rt);
2633: Node firstNode = n.getGeneric(0);
2634:
2635: Node args = GNode.create("Arguments");
2636: for (String s : fieldNames) {
2637: boolean found = false;
2638: for (int i = 1; i < n.size(); i++) {
2639: if (s.equals(n.getGeneric(i).getString(0))) {
2640: found = true;
2641: args.add(dispatch(n.getGeneric(i).getNode(1)));
2642: }
2643: }
2644: if (!found
2645: && ("WithExpression".equals(firstNode.getName()))) {
2646: if (!bottomWith) {
2647: // expression with
2648: args.add(factory
2649: .fieldExpression((Node) dispatch(firstNode
2650: .getGeneric(0)), s));
2651: } else {
2652: args.add(GNode.create("NullLiteral"));
2653: }
2654: } else if (!found) {
2655: assert found : "cannot determine field value";
2656: }
2657: }
2658: return toNewExpression2(mapper.toTypeNode(rt, false), args,
2659: null);
2660: }
2661:
2662: /**
2663: * Transform a field assignment.
2664: *
2665: * @param n The field assignment node.
2666: * @return The java assignment expression.
2667: */
2668: public Node visitFieldAssign(GNode n) {
2669: if (n.hasProperty(INANALYZE)) {
2670: n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
2671: }
2672: return factory.assignField(toIdentifier(n.getString(0)),
2673: (Node) dispatch(n.getNode(1)));
2674: }
2675:
2676: /**
2677: * Collapse a let expression.
2678: * @param n The let expression node.
2679: */
2680: private void collapseLet(GNode n) {
2681: Node bindings = GNode.ensureVariable(n.getGeneric(0));
2682: Node value = n.getGeneric(1);
2683:
2684: if (value.hasName("LetExpression")) {
2685: Node vbindings = value.getGeneric(0);
2686: boolean collapse = true;
2687:
2688: for (int i = 0; i < n.size(); i++) {
2689: if (n.getGeneric(i).getGeneric(0).hasName("Variable")
2690: && containsBinding(vbindings, n.getGeneric(i)
2691: .getGeneric(0).getString(0))) {
2692: collapse = false;
2693: }
2694: }
2695:
2696: if (collapse) {
2697: for (int i = 0; i < vbindings.size(); i++) {
2698: bindings.add(vbindings.getGeneric(i));
2699: }
2700: n.set(0, bindings);
2701: n.set(1, value.getGeneric(1));
2702:
2703: String scopename = (String) value
2704: .getProperty("enterScope");
2705: if (table.current().hasNested(scopename)) {
2706: table.current().merge(scopename);
2707: }
2708:
2709: collapseLet(n);
2710: }
2711: }
2712: }
2713:
2714: /**
2715: * Test if a let binding node contains a named binding.
2716: *
2717: * @param n The let binding node.
2718: * @param binding The name of the binding.
2719: * @return <code>true</code> if the node contains the binding.
2720: */
2721: private boolean containsBinding(Node n, String binding) {
2722: for (int i = 0; i < n.size(); i++) {
2723: if (n.getGeneric(i).getGeneric(0).hasName("Variable")
2724: && binding.equals(n.getGeneric(i).getGeneric(0)
2725: .getString(0))) {
2726: return true;
2727: }
2728: }
2729: return false;
2730: }
2731:
2732: /**
2733: * Process a let expression.
2734: *
2735: * @param n The let expression node.
2736: * @return An anonymous Let instance
2737: */
2738: public Node visitLetExpression(GNode n) {
2739:
2740: if (runtime.test("optimizeLet")) {
2741: collapseLet(n);
2742: }
2743:
2744: if (n.hasProperty(INANALYZE)) {
2745: n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
2746: }
2747:
2748: final String scopename = (String) n.getProperty("enterScope");
2749:
2750: boolean didEnter = false;
2751: if (n.hasProperty("enterScope")) {
2752: if (!table.current().getName().equals(scopename)) {
2753: enterScope(scopename);
2754: didEnter = true;
2755: }
2756: }
2757:
2758: Node bindings = n.getGeneric(0);
2759: Node value = n.getGeneric(1);
2760: Object resultType = n.getProperty(TYPE);
2761: int size = bindings.size();
2762: Node block = null;
2763: Node res = (GNode) dispatch(value);
2764:
2765: if ("Block".equals(res.getName())) {
2766: block = GNode.create("Block", res);
2767: } else {
2768: block = GNode.create("Block", factory
2769: .ret(factory.cast(res)));
2770: }
2771:
2772: Node letclass = GNode.create("ClassBody");
2773: letclass = GNode.ensureVariable((GNode) letclass);
2774: GNode letbody = GNode.create("Block");
2775:
2776: for (int i = 0; i < size; i++) {
2777: Node binding = bindings.getGeneric(i);
2778: Node left = binding.getGeneric(0);
2779: Node right = binding.getGeneric(1);
2780:
2781: if (n.hasProperty(INANALYZE))
2782: right.setProperty(INANALYZE, Boolean.TRUE);
2783:
2784: String bname;
2785: Object btype;
2786:
2787: right = (Node) dispatch(right);
2788:
2789: if (left.hasName("Variable")) {
2790: bname = left.getString(0);
2791: btype = left.getProperty(TYPE);
2792: letclass.add(makeVarDec2(bname, mapper.toTypeNode(
2793: btype, false), null));
2794: letbody.add(factory.assign(toIdentifier(bname), factory
2795: .cast(right)));
2796:
2797: } else if ("TypedPattern".equals(left.getName())
2798: && "Variable".equals(left.getGeneric(0).getName())) {
2799: bname = left.getGeneric(0).getString(0);
2800: btype = left.getProperty(TYPE);
2801: letclass.add(makeVarDec2(bname, mapper.toTypeNode(
2802: btype, false), null));
2803: letbody.add(factory.assign(toIdentifier(bname), factory
2804: .cast(right)));
2805:
2806: } else {
2807: if (right.hasName("ConditionalExpression")) {
2808: letbody.add(factory.discard(right));
2809: } else {
2810: letbody.add(factory.expressionStmnt(right));
2811: }
2812: }
2813: }
2814:
2815: if (letbody.size() > 0) {
2816: letclass.add(letbody);
2817: }
2818:
2819: letclass
2820: .add(GNode.create("MethodDeclaration",
2821: toModifiers("public"), null, mapper.toTypeNode(
2822: resultType, false), "apply", GNode
2823: .create("FormalParameters"), null,
2824: null, block));
2825:
2826: Node let = factory.letExpression(mapper.toTypeNode(resultType,
2827: false));
2828: let.getGeneric(0).set(4, letclass);
2829:
2830: if (didEnter)
2831: exitScope(scopename);
2832:
2833: return let;
2834: }
2835:
2836: /**
2837: * Process a Patterns node.
2838: *
2839: * @return The patterns node corresponding to this node.
2840: */
2841: public Node visitPatterns(GNode n) {
2842: Node pat = n.getGeneric(0);
2843:
2844: if (n.hasProperty(TOP))
2845: pat.setProperty(TOP, null);
2846:
2847: if (isLiteral(pat)) {
2848: return factory.jequals((Node) dispatch(pat),
2849: toIdentifier((String) n.getProperty(MATCHARG)));
2850: } else {
2851: pat.setProperty(MATCHARG, n.getProperty(MATCHARG));
2852: pat.setProperty(BINDINGS, n.getProperty(BINDINGS));
2853: pat.setProperty(RHS, n.getProperty(RHS));
2854: return (GNode) dispatch(pat);
2855: }
2856: }
2857:
2858: /**
2859: * Test if a node is a literal.
2860: *
2861: * @param n The node to test.
2862: * @return True if literal false otherwise.
2863: */
2864: private boolean isLiteral(Node n) {
2865: if (null == n) {
2866: runtime.error("Calling isLiteral on null node", n);
2867: } else {
2868: String name = n.getName();
2869: return ("StringLiteral".equals(name)
2870: || "BooleanLiteral".equals(name)
2871: || "FloatingLiteral".equals(name) || "IntegerLiteral"
2872: .equals(name));
2873: }
2874: return false;
2875: }
2876:
2877: /**
2878: * Process an additive expression.
2879: *
2880: * @param n The additive expression node.
2881: * @return The java additive expression.
2882: */
2883: public Node visitAdditiveExpression(GNode n) {
2884: String op = n.getString(1);
2885: Node left = (Node) dispatch(n.getGeneric(0));
2886: Node right = (Node) dispatch(n.getGeneric(2));
2887: if (n.hasProperty(INANALYZE)) {
2888: left.setProperty(INANALYZE, Boolean.TRUE);
2889: right.setProperty(INANALYZE, Boolean.TRUE);
2890: }
2891:
2892: if ("+".equals(op))
2893: return factory.addInt(left, right);
2894: if ("-".equals(op))
2895: return factory.subtractInt(left, right);
2896: if ("+.".equals(op))
2897: return factory.addFloat64(left, right);
2898: return factory.subtractFloat64(left, right);
2899: }
2900:
2901: /**
2902: * Process a concatenation expression.
2903: *
2904: * @param n The concatenation expression node.
2905: * @return The java equivalent.
2906: */
2907: public Node visitConcatenationExpression(GNode n) {
2908: Node left = (Node) dispatch(n.getGeneric(0));
2909: Node right = (Node) dispatch(n.getGeneric(2));
2910: if (n.hasProperty(INANALYZE)) {
2911: left.setProperty(INANALYZE, Boolean.TRUE);
2912: right.setProperty(INANALYZE, Boolean.TRUE);
2913: }
2914:
2915: if ("^".equals(n.getString(1)))
2916: return factory.concatStrings(left, right);
2917: return factory.concatLists(left, right);
2918: }
2919:
2920: /**
2921: * Process a multiplicative expression.
2922: *
2923: * @param n The multiplicative expression node.
2924: * @return The java multiplicatiee expression.
2925: */
2926: public Node visitMultiplicativeExpression(GNode n) {
2927: String op = n.getString(1);
2928: Node left = (Node) dispatch(n.getGeneric(0));
2929: Node right = (Node) dispatch(n.getGeneric(2));
2930: if (n.hasProperty(INANALYZE)) {
2931: left.setProperty(INANALYZE, Boolean.TRUE);
2932: right.setProperty(INANALYZE, Boolean.TRUE);
2933: }
2934:
2935: if ("*".equals(op))
2936: return factory.multiplyInt(left, right);
2937: if ("/".equals(op))
2938: return factory.divideInt(left, right);
2939: if ("*.".equals(op))
2940: return factory.multiplyFloat64(left, right);
2941: return factory.divideFloat64(left, right);
2942: }
2943:
2944: /**
2945: * Process a relational expression.
2946: *
2947: * @param n The relational expression node.
2948: * @return The java relational expression
2949: */
2950: public Node visitRelationalExpression(GNode n) {
2951: Node left = (Node) dispatch(n.getGeneric(0));
2952: Node right = (Node) dispatch(n.getGeneric(2));
2953: if (n.hasProperty(INANALYZE)) {
2954: left.setProperty(INANALYZE, Boolean.TRUE);
2955: right.setProperty(INANALYZE, Boolean.TRUE);
2956: }
2957:
2958: String op = n.getString(1);
2959: String internal = null;
2960:
2961: if ("<".equals(op))
2962: internal = "lessInt";
2963: if ("<=".equals(op))
2964: internal = "lessEqualInt";
2965: if (">".equals(op))
2966: internal = "greaterInt";
2967: if (">=".equals(op))
2968: internal = "greaterEqualInt";
2969: if ("<.".equals(op))
2970: internal = "lessFloat64";
2971: if ("<=.".equals(op))
2972: internal = "lessEqualFloat64";
2973: if (">.".equals(op))
2974: internal = "greaterFloat64";
2975: if (">=.".equals(op))
2976: internal = "greaterEqualFloat64";
2977: assert null != internal : "undefined relational operator " + op;
2978:
2979: return factory.relationalExpr(toIdentifier("Primitives."
2980: + internal), left, right);
2981: }
2982:
2983: /**
2984: * Process a logical or expression.
2985: *
2986: * @param n The logical or expression node.
2987: * @return The java expression.
2988: */
2989: public Node visitLogicalOrExpression(GNode n) {
2990: if (n.hasProperty(INANALYZE)) {
2991: n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
2992: n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
2993: }
2994: return factory.or((Node) dispatch(n.getGeneric(0)),
2995: (Node) dispatch(n.getGeneric(1)));
2996: }
2997:
2998: /**
2999: * Process a logical and expression.
3000: *
3001: * @param n The logical and expression node.
3002: * @return The java expression.
3003: */
3004: public Node visitLogicalAndExpression(GNode n) {
3005: if (n.hasProperty(INANALYZE)) {
3006: n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3007: n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
3008: }
3009: return factory.and((Node) dispatch(n.getGeneric(0)),
3010: (Node) dispatch(n.getGeneric(1)));
3011: }
3012:
3013: /**
3014: * Process a logical negation expression.
3015: *
3016: * @param n The logical negation expression node.
3017: * @return n The java equivalent.
3018: */
3019: public Node visitLogicalNegationExpression(GNode n) {
3020: if (n.hasProperty(INANALYZE)) {
3021: n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3022: }
3023: return factory.not((Node) dispatch(n.getGeneric(0)));
3024: }
3025:
3026: /**
3027: * Process an equality expression.
3028: *
3029: * @param n The equality expression node.
3030: * @return The java equivalent.
3031: */
3032: public Node visitEqualityExpression(GNode n) {
3033: Node left = (Node) dispatch(n.getGeneric(0));
3034: Node right = (Node) dispatch(n.getGeneric(2));
3035: if (n.hasProperty(INANALYZE)) {
3036: left.setProperty(INANALYZE, Boolean.TRUE);
3037: right.setProperty(INANALYZE, Boolean.TRUE);
3038: }
3039: String op = n.getString(1);
3040:
3041: if ("=".equals(op)) {
3042: if ("Bottom".equals(n.getGeneric(0).getName())) {
3043: return factory.equalsBottom(right);
3044: } else if ("Bottom".equals(n.getGeneric(2).getName())) {
3045: return factory.equalsBottom(left);
3046: }
3047: } else {
3048: if ("Bottom".equals(n.getGeneric(0).getName())) {
3049: return factory.notEqualsBottom(right);
3050: } else if ("Bottom".equals(n.getGeneric(2).getName())) {
3051: return factory.notEqualsBottom(left);
3052: }
3053: }
3054:
3055: return ("=".equals(n.getString(1))) ? factory
3056: .equal(left, right) : factory.not(factory.equal(left,
3057: right));
3058: }
3059:
3060: /**
3061: * Process an attribute declaration.
3062: *
3063: * @param n the attribute declaration node to process.
3064: */
3065: public void visitAttributeDefinition(GNode n) {
3066: Node typeNode = n.getGeneric(1);
3067: if ("ConstraintType".equals(typeNode.getName())) {
3068: typeNode = GNode.create("UserDefinedType", "Node");
3069: }
3070: attributeList.add(new Attribute(n.getString(0), typeNode));
3071: }
3072:
3073: /**
3074: * Process an equal attribute definition.
3075: *
3076: * @param n the equal attribute definition node to process.
3077: */
3078: public void visitEqualAttributeDefinition(GNode n) {
3079: Node typeNode = n.getGeneric(1);
3080: if ("ConstraintType".equals(typeNode.getName())) {
3081: typeNode = GNode.create("UserDefinedType", "Node");
3082: }
3083: eqAttributeList.add(new Attribute(n.getString(0), typeNode));
3084: }
3085:
3086: /**
3087: * Process raw_type definition to create "type" record.
3088: *
3089: * @return The node of generated code for "type" record definition.
3090: */
3091: public Node processRawTypeDefinition() {
3092: //Create type
3093: Node typeInfo = GNode.create("RecordDeclaration", GNode.create(
3094: "FieldType", "type", GNode.create("UserDefinedType",
3095: "raw_type<?>")));
3096:
3097: typeInfo = GNode.ensureVariable((GNode) typeInfo);
3098:
3099: typeInfo
3100: .setProperty(TYPE, table.current().lookup("type(type)"));
3101:
3102: //Create equal attributes
3103: for (Attribute att : eqAttributeList) {
3104: typeInfo.add(GNode.create("FieldType", att.name, att.type));
3105: }
3106:
3107: //Create attributes
3108: for (Attribute att : attributeList) {
3109: typeInfo.add(GNode.create("FieldType", att.name, att.type));
3110: }
3111:
3112: return GNode.create("TypeDefinition", null, "type", typeInfo);
3113: }
3114:
3115: /**
3116: * Process an equality definition.
3117: *
3118: * @param n The equality definition node.
3119: */
3120: public void visitEqualityDefinition(GNode n) {
3121: // process equal structure
3122: for (int index = 1; index < n.size(); index++) {
3123: boolean seenLowerID = false;
3124: Node child = (GNode) n.get(index);
3125: ArrayList<Integer> list = new ArrayList<Integer>();
3126:
3127: for (int i = 1; i < child.size(); i++) {
3128: if (!("WildCard".equals(child.getGeneric(i).getName()))) {
3129: list.add(i);
3130: seenLowerID = true;
3131: }
3132: }
3133:
3134: if (!seenLowerID) {
3135: throw new AssertionError(
3136: "At least one identifier required");
3137: }
3138: equalities.add(new Equality((child.getGeneric(0))
3139: .getString(0), list));
3140: }
3141: }
3142:
3143: /**
3144: * Get node name from a pattern
3145: *
3146: * @param n The pattern node
3147: */
3148: protected String getNodeName(Node n) {
3149: return ("TypeConstructorPattern".equals(n.getName())) ? n
3150: .getString(0) : getNodeName(n.getGeneric(0));
3151: }
3152:
3153: /**
3154: * Process scope definition
3155: *
3156: * @param n The scope definition node
3157: */
3158: public void visitScopeDefinition(GNode n) {
3159: // Adding code to build the list of node names that need to process scope
3160: Node pat = n.getGeneric(0);
3161: for (int i = 0; i < pat.size(); i++) {
3162: Node patterns = pat.getGeneric(i).getGeneric(0);
3163: for (int j = 0; j < patterns.size(); j++) {
3164: processScopeNodes.add(getNodeName(patterns
3165: .getGeneric(j)));
3166: }
3167: }
3168:
3169: Node match = GNode.create("MatchExpression", GNode.create(
3170: "LowerID", "n"), n.getGeneric(0));
3171: match.setProperty("__arg_type", n.getProperty("__arg_type"));
3172: match.setProperty(TYPE, mapper.getPatternMatchRightType(n
3173: .getProperty(TYPE)));
3174:
3175: seenScope = true;
3176:
3177: Node pmatch = n.getGeneric(0);
3178: pmatch.setProperty(MATCHARG, "n");
3179:
3180: @SuppressWarnings("unchecked")
3181: List<Node> nodes = (List<Node>) dispatch(pmatch);
3182:
3183: nodes.add(factory.ret(GNode.create("NullLiteral")));
3184:
3185: // Create typical AST
3186: Node top = GNode.create("ValueDefinition", "getScope", GNode
3187: .create("Parameters", GNode.create("Parameter", "n",
3188: GNode.create("UserDefinedType", "node"))),
3189: GNode.create("BooleanLiteral", "true"));
3190:
3191: top
3192: .setProperty(TYPE, table.current().lookup(
3193: "value(getScope)"));
3194: top.setProperty("__isfunction", null);
3195:
3196: Node block = GNode.create("Block");
3197:
3198: for (Node node : nodes)
3199: block.add(node);
3200:
3201: Node scopefunc = (Node) dispatch(top);
3202:
3203: scopefunc.getGeneric(2).getGeneric(0).getGeneric(2).getGeneric(
3204: 4).getGeneric(0).set(7, block);
3205:
3206: functionDefinitions.add(scopefunc);
3207: return;
3208: }
3209:
3210: /**
3211: * Process namespace definition.
3212: *
3213: * @param n The name space definition node.
3214: */
3215: public void visitNameSpaceDefinition(GNode n) {
3216: seenNameSpace = true;
3217: Node pat = GNode.create("PatternMatching");
3218: pat.setProperty(TYPE, n.getProperty(TYPE));
3219: pat.setProperty(MATCHARG, "n");
3220:
3221: // Create the pattern matching node
3222: for (int i = 0; i < n.size(); i++) {
3223: Node child = n.getGeneric(i);
3224:
3225: for (int j = 0; j < child.getGeneric(2).size(); j++) {
3226: Node grand = child.getGeneric(2).getGeneric(j);
3227: Node pattern = GNode.create("PatternMatch");
3228:
3229: pattern.add(grand.getGeneric(0));
3230: // Create Typical tuple
3231: Node tup = GNode.create("TupleLiteral", grand
3232: .getGeneric(1), GNode.create("StringLiteral",
3233: "\"" + child.getString(0) + "\""), GNode
3234: .create("StringLiteral", "\""
3235: + child.getString(1) + "\""));
3236: tup.setProperty(TYPE, TypeMapper.nameTupleT);
3237: pattern.add(tup);
3238:
3239: pattern.setProperty("enterScope", grand
3240: .getProperty("enterScope"));
3241:
3242: Node thepatterns = pattern.getGeneric(0);
3243:
3244: for (int k = 0; k < thepatterns.size(); k++) {
3245: thepatterns.getGeneric(k).setProperty("enterScope",
3246: pattern.getProperty("enterScope"));
3247: }
3248: pat.add(pattern);
3249: }
3250: }
3251:
3252: pat.setProperty(MATCHARG, "n");
3253: Node match = GNode.create("MatchExpression", GNode.create(
3254: "LowerID", "n"), pat);
3255:
3256: // create the value definition node
3257: Node top = GNode.create("ValueDefinition", "getNameSpace",
3258: GNode.create("Parameters", GNode.create("Parameter",
3259: "n", GNode.create("UserDefinedType", "node"))),
3260: match);
3261: top.setProperty("__isfunction", null);
3262: match.setProperty("__arg_type", table.current().lookup(
3263: "type(node)"));
3264: match.setProperty(TYPE, TypeMapper.nameTupleT);
3265: top.setProperty("__arg_type", n.getProperty("__arg_type"));
3266:
3267: top.setProperty(TYPE, table.current().lookup(
3268: "value(getNameSpace)"));
3269: functionDefinitions.add((Node) dispatch(top));
3270: }
3271:
3272: /**
3273: * Transform an error clause into a function call to either or warning.
3274: *
3275: * @param n The expression node.
3276: * @return The function call java node.
3277: */
3278: public Node visitErrorClause(GNode n) {
3279: Node loc = (Node) dispatch(n.getGeneric(2));
3280: if (null == loc)
3281: loc = nullNode;
3282: return factory.errorClause(n.getGeneric(0).getString(0),
3283: (Node) dispatch(n.getGeneric(1)), loc);
3284: }
3285:
3286: /**
3287: * Transform an assert clause into a function call to assert.
3288: *
3289: * @param n The assert clause node.
3290: * @return The function call java node.
3291: */
3292: public Node visitAssertClause(GNode n) {
3293: if (n.hasProperty(INANALYZE)) {
3294: n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3295: if (null != n.getGeneric(1)) {
3296: n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
3297: }
3298: }
3299: Node exp = (Node) dispatch(n.getGeneric(0));
3300:
3301: return (null == n.getGeneric(1)) ? GNode.create(
3302: "PostfixExpression", toIdentifier("assertion"), GNode
3303: .create("Arguments", exp)) : GNode.create(
3304: "PostfixExpression", toIdentifier("assertion"), GNode
3305: .create("Arguments", exp, dispatch(n
3306: .getGeneric(1))));
3307: }
3308:
3309: /**
3310: * Transform an if expression into a java conditional expression.
3311: *
3312: * @param n The if expression node.
3313: * @return The java conditional expression.
3314: */
3315: public Node visitIfExpression(GNode n) {
3316: if (n.hasProperty(INANALYZE)) {
3317: n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3318: n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
3319: }
3320: return factory.ifExpression((Node) dispatch(n.getGeneric(0)),
3321: (Node) dispatch(n.getGeneric(1)));
3322: }
3323:
3324: /**
3325: * Transform an if expression into a java conditional expression.
3326: *
3327: * @param n The if expression node.
3328: * @return The java conditional expression.
3329: */
3330: public Node visitIfElseExpression(GNode n) {
3331: if (n.hasProperty(INANALYZE)) {
3332: n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3333: n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
3334: n.getGeneric(2).setProperty(INANALYZE, Boolean.TRUE);
3335: }
3336: return factory.ifElseExpression(
3337: (Node) dispatch(n.getGeneric(0)), (Node) dispatch(n
3338: .getGeneric(1)), (Node) dispatch(n
3339: .getGeneric(2)));
3340: }
3341:
3342: /**
3343: * Process require expression.
3344: *
3345: * @param n the require expression node
3346: * @return The java code for the require expression.
3347: */
3348: public Node visitRequireExpression(GNode n) {
3349:
3350: int nodeSize = n.size();
3351:
3352: // get the expression
3353: Node expr = n.getGeneric(nodeSize - 1);
3354:
3355: if (n.hasProperty(INANALYZE))
3356: expr.setProperty(INANALYZE, Boolean.TRUE);
3357:
3358: //dispatch this node to translate
3359: Node valExpr = (Node) dispatch(expr);
3360:
3361: final Node genericType;
3362: if (expr.hasProperty(TYPE)) {
3363: genericType = mapper.toTypeNode(expr.getProperty(TYPE),
3364: false);
3365: } else {
3366: genericType = GNode.create("Type", GNode.create(
3367: "QualifiedIdentifier", "Object"), null);
3368: }
3369:
3370: ArrayList<Node> list = new ArrayList<Node>();
3371:
3372: for (int id = 0; id < nodeSize - 1; id++) {
3373: Node no = n.getGeneric(id);
3374: list.add(no);
3375: }
3376:
3377: // Create require block
3378: List<Node> requireBlock = new ArrayList<Node>();
3379:
3380: /* A list of translated expressions */
3381: ArrayList<Node> listExpr = new ArrayList<Node>();
3382:
3383: // Add statement
3384: for (Node node : list) {
3385: Node boolNode = node.getGeneric(0);
3386: if (n.hasProperty(INANALYZE)) {
3387: boolNode.setProperty(INANALYZE, Boolean.TRUE);
3388: }
3389: Node boolExpr = (Node) dispatch(boolNode);
3390:
3391: final String newVar = table.freshJavaId("var");
3392:
3393: requireBlock.add(factory.boolVar(newVar, boolExpr));
3394:
3395: listExpr.add(toIdentifier(newVar));
3396:
3397: Node tagNode = node.getGeneric(1);
3398: String tag = tagNode.getString(0);
3399:
3400: Node msgNode = node.getGeneric(2);
3401: Node msgExpr = (Node) dispatch(msgNode);
3402:
3403: Node atNode = node.getGeneric(3);
3404: Node atExpr;
3405: if (null == atNode) {
3406: atExpr = nullNode;
3407: } else {
3408: atExpr = (Node) dispatch(atNode);
3409: }
3410:
3411: Node ifNode = factory.ifStatement3(toIdentifier(newVar),
3412: GNode.create("StringLiteral", "\"" + tag + "\""),
3413: msgExpr, atExpr);
3414: requireBlock.add(ifNode);
3415: }
3416:
3417: // check for returning null (bottom)
3418: if (1 == listExpr.size()) {
3419: Node checkNode = factory.ifStatement4(listExpr.get(0));
3420:
3421: requireBlock.add(checkNode);
3422: } else {
3423: Node logicalOr = GNode.create("LogicalOrExpression");
3424: logicalOr.add(factory.isNull(listExpr.get(0)));
3425: logicalOr.add(factory.isNull(listExpr.get(1)));
3426:
3427: for (int i = 2; i < listExpr.size(); i++) {
3428: logicalOr = GNode.create("LogicalOrExpression",
3429: logicalOr, factory.isNull(listExpr.get(i)));
3430: }
3431:
3432: Node checkNode = factory.ifStatement5(logicalOr);
3433: requireBlock.add(checkNode);
3434: }
3435:
3436: // Check to return expr
3437:
3438: if (1 == listExpr.size()) {
3439: Node checkNode;
3440: if (!"Block".equals(valExpr.getName())) {
3441: checkNode = factory.ifStatement(listExpr.get(0),
3442: factory.ret(valExpr));
3443: } else {
3444: checkNode = toIfStatement(listExpr.get(0), valExpr);
3445: }
3446: requireBlock.add(checkNode);
3447: } else {
3448: Node logicalAnd = GNode.create("LogicalAndExpression");
3449: logicalAnd.add(listExpr.get(0));
3450: logicalAnd.add(listExpr.get(1));
3451:
3452: for (int i = 2; i < listExpr.size(); i++) {
3453: logicalAnd = GNode.create("LogicalAndExpression",
3454: logicalAnd, listExpr.get(i));
3455: }
3456: Node checkNode;
3457: if (!"Block".equals(valExpr.getName())) {
3458: checkNode = factory.ifStatement(logicalAnd, factory
3459: .ret(valExpr));
3460: } else {
3461: checkNode = toIfStatement(logicalAnd, valExpr);
3462: }
3463: requireBlock.add(checkNode);
3464: }
3465:
3466: // return null at the end
3467: requireBlock.add(factory.ret(nullNode));
3468: return factory.requireExpression(genericType, requireBlock);
3469: }
3470:
3471: /** Store nodes that need to process scopes. */
3472: public void processScopeSpace() {
3473: Node block = GNode.create("Block");
3474:
3475: for (int i = 0; i < processScopeNodes.size(); i++) {
3476: Node add = factory.addScopeNode(toIdentifier("\""
3477: + processScopeNodes.get(i) + "\""));
3478: block.add(add);
3479:
3480: }
3481:
3482: Node getNodes = factory.getScopeNodesMethod();
3483: getNodes.set(7, block);
3484:
3485: cbody.add(getNodes);
3486:
3487: // if scope definition is not used
3488: if (!seenScope) {
3489: cbody.add(factory.getScopeClass());
3490: cbody.add(factory.getScopeObject());
3491:
3492: }
3493: if (!seenNameSpace) {
3494: throw new AssertionError("Name space must be defined");
3495: }
3496: }
3497:
3498: /**
3499: * Create equals method for the record "type".
3500: *
3501: * @return The equals method for the type record.
3502: */
3503: public Node createTypeRecordEquals() {
3504:
3505: Node block = GNode.create("Block");
3506:
3507: block.add(toIfStatement(factory.equality(toIdentifier("o"),
3508: nullNode), factory.ret(GNode.create("BooleanLiteral",
3509: "false"))));
3510:
3511: block.add(toIfStatement(GNode.create(
3512: "LogicalNegationExpression", GNode.create(
3513: "InstanceOfExpression", toIdentifier("o"),
3514: toType("type"))), factory.ret(toLiteral(
3515: "BooleanLiteral", "false"))));
3516:
3517: block.add(factory.recordFieldEqual());
3518:
3519: block.add(factory.recordEqualReturn());
3520:
3521: block.add(factory.compareTypes());
3522:
3523: // Add equal attribute comparisons.
3524: for (Attribute att : eqAttributeList) {
3525: block
3526: .add(factory
3527: .compareAttributes(toIdentifier(att.name)));
3528: }
3529: block.add(factory.ret(toIdentifier("res")));
3530:
3531: Node retNode = factory.equalsMethod();
3532: retNode.set(7, block);
3533: return retNode;
3534: }
3535:
3536: /**
3537: * Create equals method for a constructor that is in equality definition.
3538: *
3539: * @param variantName The name of the contructor.
3540: * @return The equals method for the variant.
3541: */
3542: public Node createVariantEqualsMethod(String variantName) {
3543: Equality constr = null;
3544: for (Equality e : equalities) {
3545: if (variantName.equals(e.name)) {
3546: constr = e;
3547: break;
3548: }
3549: }
3550:
3551: assert null != constr : "null value for constr";
3552:
3553: Node block = GNode.create("Block");
3554: block.add(factory.ifStatement1(toIdentifier("o")));
3555:
3556: Node secondIf = factory.ifStatement2(toIdentifier("o"));
3557: secondIf.getGeneric(0).getGeneric(0)
3558: .set(1, toType(variantName));
3559: block.add(secondIf);
3560: block.add(makeDec("other", variantName, GNode.create(
3561: "CastExpression", toType(variantName),
3562: toIdentifier("o"))));
3563: block.add(makeDec("res", "boolean", toLiteral("BooleanLiteral",
3564: "true")));
3565:
3566: for (Integer pos : constr.positions) {
3567: block.add(factory.compareMembers("getTuple().get" + pos
3568: + "()"));
3569: }
3570: block.add(factory.ret(toIdentifier("res")));
3571: Node foo = factory.equalsMethod();
3572: foo.set(7, block);
3573: return foo;
3574: }
3575:
3576: /**
3577: * Augment a translated IfStatement of a pattern match to process scope
3578: *
3579: * @param n The IfStatement node
3580: * @param matchArg The argument of the match expression
3581: * @param no The pattern match node
3582: * @return The augmented IfStatement
3583: */
3584: public Node augmentIfStatement(Node n, String matchArg, GNode no) {
3585: Node block = n.getGeneric(1);
3586: GNode pattern = no.getGeneric(0).getGeneric(0);
3587: List<Integer> indexList = getIndexList(pattern);
3588:
3589: int size = block.size();
3590: // Get the last return statement of the block
3591: Node retNode = block.getGeneric(size - 1);
3592:
3593: assert ("ReturnStatement" == retNode.getName()) : "The last statement of the if block is not a return statement";
3594:
3595: // Update matching_nodes.
3596: block.set(size - 1, factory
3597: .matchingNodesAdd(toIdentifier(matchArg)));
3598: // Check if this node needs to process scope
3599: block.add(factory.processScope(toIdentifier(matchArg)));
3600: // Check if enter a new scope
3601: block.add(factory.checkEnterScope(toIdentifier(matchArg)));
3602: // Check if needed to process scope of the offsprings
3603: String nodeName = table.freshJavaId("nodeName");
3604: String listName = table.freshJavaId("listName");
3605: if (null != indexList && indexList.size() > 1) {
3606: block.add(factory.spOffspringList(listName));
3607: block.add(factory.spRunNode(nodeName,
3608: toIdentifier(matchArg)));
3609: int index;
3610: for (int ind = 0; ind < indexList.size() - 1; ind++) {
3611: index = indexList.get(ind);
3612: block.add(factory.spGetGeneric(toIdentifier(nodeName),
3613: toLiteral("IntegerLiteral", "" + index)));
3614: block.add(factory.processScope(toIdentifier(nodeName)));
3615: block.add(factory
3616: .checkEnterScope(toIdentifier(nodeName)));
3617: block
3618: .add(factory.spOffspringListAdd(
3619: toIdentifier(listName),
3620: toIdentifier(nodeName)));
3621: }
3622: }
3623: // Store the return value
3624: String freshId = table.freshJavaId("retValue");
3625: block.add(factory.storeValue(freshId, retNode.getGeneric(0)));
3626: // Check to exit scope
3627: if (null != indexList && indexList.size() > 1) {
3628: block.add(factory.spForLoop(toIdentifier(listName)));
3629: }
3630: block.add(factory.checkExitScope(toIdentifier(matchArg)));
3631: // Update matching_nodes
3632: block.add(factory.matchingNodesRemove());
3633: // Annotate this node with the type
3634: if (no.hasProperty(ANNOTATE)) {
3635: block.add(factory.annotateType(toIdentifier(matchArg),
3636: toIdentifier(freshId)));
3637: }
3638: // return
3639: block.add(factory.castReturn(toIdentifier(freshId)));
3640: return n;
3641: }
3642:
3643: /**
3644: * Get a list of indice that corresspond to nodes needed to process scope
3645: *
3646: * @param node The pattern node
3647: * @return The list of indice
3648: */
3649: public static List<Integer> getIndexList(GNode node) {
3650: List<Integer> res;
3651: final String nodeName = node.getName();
3652: if ("WhenPattern".equals(nodeName)
3653: || "AsPattern".equals(nodeName)
3654: || "TypedPattern".equals(nodeName)) {
3655: return getIndexList(node.getGeneric(0));
3656:
3657: } else if ("TypeConstructorPattern".equals(nodeName)) {
3658: if (1 == node.size()
3659: || "WidlCard".equals(node.getGeneric(1).getName())) {
3660: return null;
3661: } else {
3662: Node paras = node.getGeneric(1);
3663: boolean hasBinding = false;
3664:
3665: for (int index = 0; index < paras.size(); index++) {
3666: res = getIndexList(paras.getGeneric(index));
3667: if (null != res && !res.isEmpty()) {
3668: if ("ConsPattern".equals(paras
3669: .getGeneric(index).getName())
3670: || "ListPattern".equals(paras
3671: .getGeneric(index).getName())) {
3672: int pos = res.remove(0);
3673: res.add(0, pos + index);
3674: return res;
3675: } else {
3676: res.add(0, index);
3677: return res;
3678: }
3679: } else if (null != res) {
3680: hasBinding = true;
3681: }
3682: }
3683: if (hasBinding) {
3684: res = new ArrayList<Integer>();
3685: res.add(0);
3686: return res;
3687: } else
3688: return null;
3689: }
3690: } else if ("ConsPattern".equals(nodeName)) {
3691: res = getIndexList(node.getGeneric(0));
3692: if (null == res) {
3693: res = getIndexList(node.getGeneric(1));
3694: if (null == res || res.isEmpty())
3695: return res;
3696: else {
3697: int pos = res.remove(0);
3698: res.add(0, pos + 1);
3699: return res;
3700: }
3701: } else if (res.isEmpty()) {
3702: return res;
3703: } else {
3704: res.add(0, 0);
3705: return res;
3706: }
3707:
3708: } else if ("ListPattern".equals(nodeName)) {
3709: boolean hasBinding = false;
3710: for (int index = 0; index < node.size(); index++) {
3711: res = getIndexList(node.getGeneric(index));
3712: if (null != res && !res.isEmpty()) {
3713: res.add(0, index);
3714: return res;
3715: } else if (null != res) {
3716: hasBinding = true;
3717: }
3718: }
3719: return hasBinding ? new ArrayList<Integer>() : null;
3720: } else if ("Variable".equals(nodeName)) {
3721: return new ArrayList<Integer>();
3722: } else if ("WildCard".equals(nodeName)
3723: || "BottomPattern".equals(nodeName)) {
3724: return null;
3725: }
3726: return null;
3727: }
3728:
3729: /**
3730: * Process currying in function applications
3731: *
3732: * @param funcName The name of the function
3733: * @param args The node that contains all arguments
3734: * @param paramTypes The list of parameter type nodes of the function
3735: * @param retType The return type node of the function
3736: * @param funcType The whole function type
3737: * @return A node that is a new function
3738: */
3739: public Node makeCurry(String funcName, Node args,
3740: List<Node> paramTypes, Node retType, Object funcType) {
3741:
3742: //create the function name and parameterise it with the return type
3743: //and the argument types
3744: final int paraSize = paramTypes.size() - args.size();
3745:
3746: Node typeArgs = GNode.create("TypeArguments");
3747: typeArgs.add(retType);
3748:
3749: for (int i = args.size(); i < paramTypes.size(); i++) {
3750: typeArgs.add(paramTypes.get(i));
3751: }
3752:
3753: Node functionTypeNode = GNode.create("Type",
3754: GNode.create("InstantiatedType", GNode.create(
3755: "TypeInstantiation", "Function", null), GNode
3756: .create("TypeInstantiation", "F" + paraSize,
3757: typeArgs)), null);
3758:
3759: // Populate the formal parameters for the "apply" method
3760: Node formalParameters = GNode.create("FormalParameters",
3761: paraSize);
3762: // Names of formal parameters
3763: List<String> formalParams = new ArrayList<String>();
3764:
3765: for (int i = args.size(); i < paramTypes.size(); i++) {
3766: String newPara = table.freshJavaId("para");
3767: formalParams.add(newPara);
3768: formalParameters.add(GNode.create("FormalParameter", fmod,
3769: paramTypes.get(i), null, newPara, null));
3770: }
3771:
3772: // Create block for apply method
3773: Node block = GNode.create("Block");
3774: // Names of temporary variables
3775: List<String> tempVars = new ArrayList<String>();
3776:
3777: for (int i = 0; i < args.size(); i++) {
3778: // Assign to a temporary variable
3779: String tempVar = table.freshJavaId("var");
3780: tempVars.add(tempVar);
3781: block.add(factory.fieldDecl2(paramTypes.get(i), tempVar,
3782: args.getGeneric(i)));
3783: }
3784:
3785: // Node of new arguments
3786: Node newArgs = GNode.create("Arguments");
3787:
3788: for (String s : tempVars)
3789: newArgs.add(toIdentifier(s));
3790: for (String s : formalParams)
3791: newArgs.add(toIdentifier(s));
3792:
3793: // Create return statement
3794: Node ret = factory.ret(factory.apply(toIdentifier(funcName),
3795: makeArgumentList(newArgs)));
3796: block.add(ret);
3797:
3798: // Create body of the class
3799: Node classBody = GNode.create("ClassBody", GNode.create(
3800: "MethodDeclaration", pmod, null, retType, "apply",
3801: formalParameters, null, null, block));
3802:
3803: return toNewExpression2(functionTypeNode, null, classBody);
3804: }
3805:
3806: /**
3807: * Get the index of a primitive instance in the list
3808: *
3809: * @param name The name of the instance
3810: * @param types The types of the instance
3811: * @return The index of the instance, -1 if not exists
3812: */
3813: public String getInstanceName(String name, List<String> types) {
3814: for (PrimitiveInstance ins : primitiveInsList) {
3815: if (!name.equals(ins.name)
3816: || types.size() != ins.types.size())
3817: continue;
3818: boolean check = true;
3819: for (int j = 0; j < types.size(); j++) {
3820: if (!types.get(j).equals(ins.types.get(j))) {
3821: check = false;
3822: break;
3823: }
3824: }
3825: if (check)
3826: return ins.instanceName;
3827: }
3828: return null;
3829: }
3830:
3831: /**
3832: * Make a variable declaration.
3833: *
3834: * @param s The variable name.
3835: * @param t The type.
3836: * @param d The declarator value.
3837: * @return The variable declaration node.
3838: */
3839: private Node makeVarDec(String s, String t, Node d) {
3840: Node decl = factory.fieldDecl(toType(t), d);
3841: //set the name
3842: decl.getGeneric(2).getGeneric(0).set(0, s);
3843: return decl;
3844: }
3845:
3846: /**
3847: * Make a variable declaration with type is a node.
3848: *
3849: * @param s The variable name.
3850: * @param t The type node.
3851: * @param d The declarator value.
3852: * @return The variable declaration node.
3853: */
3854: private Node makeVarDec2(String s, Node t, Node d) {
3855: Node decl = factory.fieldDecl(t, d);
3856: //set the name
3857: decl.getGeneric(2).getGeneric(0).set(0, s);
3858: return decl;
3859: }
3860:
3861: /**
3862: * Make a variable declaration.
3863: *
3864: * @param s The variable name.
3865: * @param t The type.
3866: * @param d The declarator value.
3867: * @return The variable declaration node.
3868: */
3869: @SuppressWarnings("unused")
3870: private Node makeStaticVarDec(String s, String t, Node d) {
3871: Node decl = factory.staticFieldDecl(toType(t), d);
3872: //set the name
3873: decl.getGeneric(2).getGeneric(0).set(0, s);
3874: return decl;
3875: }
3876:
3877: /**
3878: * Make a variable declaration.
3879: *
3880: * @param s The variable name.
3881: * @param t The type.
3882: * @param d The declarator value.
3883: * @return The variable declaration node.
3884: */
3885: private Node makeDec(String s, String t, Node d) {
3886: Node decl = factory.fieldDecl1(toType(t), d);
3887: //set the name
3888: decl.getGeneric(2).getGeneric(0).set(0, s);
3889: return decl;
3890: }
3891:
3892: /** Run this transformer. */
3893: public void run() {
3894: dispatch(typical);
3895: }
3896:
3897: /**
3898: * Return the ast of the generated program.
3899: *
3900: * @return The ast of the output type checker.
3901: */
3902: public GNode getCheckerAST() {
3903: return transformed;
3904: }
3905:
3906: /**
3907: * Return the ast of the generated types file.
3908: *
3909: * @return The ast of the output types file.
3910: */
3911: public GNode getTypesAST() {
3912: return typesAST;
3913: }
3914:
3915: /**
3916: * Return the ast of the generated support file.
3917: *
3918: * @return The ast of the output support file.
3919: */
3920: public GNode getSupportAST() {
3921: return supportAST;
3922: }
3923:
3924: /**
3925: * Check which libraries are used, set the corresponding flag variables.
3926: *
3927: * @param n The root of the generated code to check.
3928: */
3929: private void setFlagVariables(Node n) {
3930:
3931: FlagSetter set = new FlagSetter((GNode) n);
3932:
3933: isListUsed = set.isListUsed;
3934: isArrayListUsed = set.isArrayListUsed;
3935: isBigIntegerUsed = set.isBigIntegerUsed;
3936: isPairUsed = set.isPairUsed;
3937: isNodeUsed = set.isNodeUsed;
3938: isGNodeUsed = set.isGNodeUsed;
3939: isPrimitivesUsed = set.isPrimitivesUsed;
3940: isRecordUsed = set.isRecordUsed;
3941: isVariantUsed = set.isVariantUsed;
3942: isTupleUsed = set.isTupleUsed;
3943: isReductionUsed = set.isReductionUsed;
3944: isNameUsed = set.isNameUsed;
3945: isScopeUsed = set.isScopeUsed;
3946: isScopeKindUsed = set.isScopeKindUsed;
3947: isAnalyzerUsed = set.isAnalyzerUsed;
3948: }
3949:
3950: /**
3951: * Import libraries that are used.
3952: *
3953: * @param compUnit The CompilationUnit node.
3954: * @param n The node to check which libraries are used.
3955: * @param fileName The importing file, XXXAnalyzer, XXXTypes or XXXSuppport
3956: */
3957: private void addImports(Node compUnit, Node n, String fileName) {
3958:
3959: setFlagVariables(n);
3960: Node importNode;
3961:
3962: if (isBigIntegerUsed) {
3963: importNode = GNode.create("ImportDeclaration", null, GNode
3964: .create("QualifiedIdentifier", "java", "math",
3965: "BigInteger"), null);
3966: compUnit.add(importNode);
3967: }
3968:
3969: if (isListUsed) {
3970: importNode = GNode.create("ImportDeclaration", null, GNode
3971: .create("QualifiedIdentifier", "java", "util",
3972: "List"), null);
3973: compUnit.add(importNode);
3974: }
3975:
3976: if (isArrayListUsed) {
3977: importNode = GNode.create("ImportDeclaration", null, GNode
3978: .create("QualifiedIdentifier", "java", "util",
3979: "ArrayList"), null);
3980: compUnit.add(importNode);
3981: }
3982:
3983: if (isPairUsed) {
3984: importNode = GNode.create("ImportDeclaration", null, GNode
3985: .create("QualifiedIdentifier", "xtc", "util",
3986: "Pair"), null);
3987: compUnit.add(importNode);
3988: }
3989:
3990: if ("Analyzer".equals(fileName)) {
3991: importNode = GNode.create("ImportDeclaration", null, GNode
3992: .create("QualifiedIdentifier", "xtc", "util",
3993: "Runtime"), null);
3994: compUnit.add(importNode);
3995:
3996: importNode = GNode.create("ImportDeclaration", null, GNode
3997: .create("QualifiedIdentifier", "xtc", "util",
3998: "Function"), null);
3999: compUnit.add(importNode);
4000: }
4001:
4002: if (isNodeUsed) {
4003: importNode = GNode.create("ImportDeclaration", null, GNode
4004: .create("QualifiedIdentifier", "xtc", "tree",
4005: "Node"), null);
4006: compUnit.add(importNode);
4007: }
4008:
4009: if (isGNodeUsed) {
4010: importNode = GNode.create("ImportDeclaration", null, GNode
4011: .create("QualifiedIdentifier", "xtc", "tree",
4012: "GNode"), null);
4013: compUnit.add(importNode);
4014: }
4015:
4016: // Check and import xtc.typical.XXX
4017: if (!"xtc.typical".equals(packageName)) {
4018: if ("Analyzer".equals(fileName) || isAnalyzerUsed) {
4019: importNode = GNode.create("ImportDeclaration", null,
4020: GNode.create("QualifiedIdentifier", "xtc",
4021: "typical", "Analyzer"), (GNode) null);
4022: compUnit.add(importNode);
4023: }
4024:
4025: if (isPrimitivesUsed) {
4026: importNode = GNode.create("ImportDeclaration", null,
4027: GNode.create("QualifiedIdentifier", "xtc",
4028: "typical", "Primitives"), (GNode) null);
4029: compUnit.add(importNode);
4030: }
4031:
4032: if (isRecordUsed) {
4033: importNode = GNode.create("ImportDeclaration", null,
4034: GNode.create("QualifiedIdentifier", "xtc",
4035: "typical", "Record"), (GNode) null);
4036: compUnit.add(importNode);
4037: }
4038:
4039: if (isVariantUsed) {
4040: importNode = GNode.create("ImportDeclaration", null,
4041: GNode.create("QualifiedIdentifier", "xtc",
4042: "typical", "Variant"), (GNode) null);
4043: compUnit.add(importNode);
4044: }
4045:
4046: if (isTupleUsed) {
4047: importNode = GNode.create("ImportDeclaration", null,
4048: GNode.create("QualifiedIdentifier", "xtc",
4049: "typical", "Tuple"), (GNode) null);
4050: compUnit.add(importNode);
4051: }
4052:
4053: if (isReductionUsed) {
4054: importNode = GNode.create("ImportDeclaration", null,
4055: GNode.create("QualifiedIdentifier", "xtc",
4056: "typical", "Reduction"), (GNode) null);
4057: compUnit.add(importNode);
4058: }
4059:
4060: if (isNameUsed) {
4061: importNode = GNode.create("ImportDeclaration", null,
4062: GNode.create("QualifiedIdentifier", "xtc",
4063: "typical", "Name"), (GNode) null);
4064: compUnit.add(importNode);
4065: }
4066:
4067: if (isScopeUsed) {
4068: importNode = GNode.create("ImportDeclaration", null,
4069: GNode.create("QualifiedIdentifier", "xtc",
4070: "typical", "Scope"), (GNode) null);
4071: compUnit.add(importNode);
4072: }
4073:
4074: if (isScopeKindUsed) {
4075: importNode = GNode.create("ImportDeclaration", null,
4076: GNode.create("QualifiedIdentifier", "xtc",
4077: "typical", "ScopeKind"), (GNode) null);
4078: compUnit.add(importNode);
4079: }
4080: }
4081: }
4082:
4083: /**
4084: * Make the class body for the XXXAnalyzer
4085: *
4086: * @return The node of the class body
4087: */
4088: private Node makeClassBody() {
4089: // Make the constructor
4090: Node constructor;
4091: if ("Typical".equals(output)) {
4092: constructor = factory.makeConstructor(output + "Analyzer");
4093: Node fieldDecl = factory.nodeTypeDecl();
4094: // return the class body node
4095: return GNode.create("ClassBody", fieldDecl, constructor);
4096: } else {
4097: constructor = factory.makeConstructor2(output + "Analyzer");
4098: // return the class body node
4099: return GNode.create("ClassBody", constructor);
4100: }
4101: }
4102:
4103: /**
4104: * Create the typechecker skeleton.
4105: *
4106: * @return The root of the type checker ast.
4107: */
4108: private Node makeSkeleton() {
4109: Node classDec = GNode.create("ClassDeclaration",
4110: toModifiers("public"), output + "Analyzer", null, GNode
4111: .create("Extension", GNode.create("Type", GNode
4112: .create("QualifiedIdentifier",
4113: "Analyzer"), null)), null,
4114: cbody);
4115:
4116: Node compUnit = GNode.create("CompilationUnit", 8);
4117: compUnit.add(packageNode);
4118: addImports(compUnit, cbody, "Analyzer");
4119: compUnit.add(comment(classDec, "Type checker for " + output
4120: + "."));
4121: return compUnit;
4122: }
4123:
4124: /**
4125: * Create the skeleton for the xxxTypes.java file.
4126: *
4127: * @return The root of the XXXTypes.java ast.
4128: */
4129: private Node makeTypesSkeleton() {
4130: Node compUnit = GNode.create("CompilationUnit", 8);
4131: compUnit.add(packageNode);
4132: addImports(compUnit, tbody, "Types");
4133:
4134: Node classDecl = factory.classDecl2(output + "Types");
4135: classDecl.set(5, tbody);
4136:
4137: compUnit.add(comment(classDecl, "Types for " + output + "."));
4138: return compUnit;
4139: }
4140:
4141: /**
4142: * Create the skeleton for the xxxSupport.java file.
4143: *
4144: * @return The root of the XXXSupport.java ast.
4145: */
4146: private Node makeSupportSkeleton() {
4147: Node compUnit = GNode.create("CompilationUnit", 8);
4148: compUnit.add(packageNode);
4149: addImports(compUnit, sbody, "Support");
4150:
4151: Node classDecl = factory.classDecl2(output + "Support");
4152: classDecl.set(5, sbody);
4153:
4154: compUnit.add(comment(classDecl, "Helper functionality for "
4155: + output + "."));
4156: return compUnit;
4157: }
4158:
4159: /**
4160: * Add an enumeration constant.
4161: *
4162: * @param s The name of the enum.
4163: */
4164: private void addEnum(Node enums, String s) {
4165: enums.add(GNode.create("EnumConstant", null, s, null, null));
4166: }
4167:
4168: /**
4169: * Enter the scoped named.
4170: *
4171: * @param n The scope name.
4172: */
4173: private void enterScope(String n) {
4174: table.enter(n);
4175: }
4176:
4177: /**
4178: * Exit the scope named n.
4179: *
4180: * @param n The scope name.
4181: */
4182: private void exitScope(String n) {
4183: if (!(n.equals(table.current().getName()))) {
4184: throw new AssertionError("mismatched scope exit " + n);
4185: } else {
4186: table.exit();
4187: }
4188: }
4189:
4190: /**
4191: * Debug function to check for type annotations.
4192: *
4193: * @param n The node to check.
4194: */
4195: private void checkTypeAnnotation(GNode n) {
4196: if (!n.hasProperty(TYPE)) {
4197: throw new AssertionError("no type annotation for "
4198: + n.getName());
4199: } else if (n.getProperty(TYPE) == null) {
4200: throw new AssertionError(n.getName() + " has null type");
4201: }
4202: }
4203:
4204: /**
4205: * Utility function to print a nicely formatted ast for debugging.
4206: *
4207: * @param n The ast root.
4208: */
4209: @SuppressWarnings("unused")
4210: private final void printAST(Node n) {
4211: runtime.console().pln().format(n).pln().flush();
4212: }
4213:
4214: /** Print the symbol table. */
4215: @SuppressWarnings("unused")
4216: private final void printSymbolTable() {
4217: if (null != table) {
4218: Visitor visitor = runtime.console().visitor();
4219: try {
4220: table.root().dump(runtime.console());
4221: } finally {
4222: runtime.console().register(visitor);
4223: }
4224: runtime.console().flush();
4225: } else {
4226: throw new AssertionError("Symbol table not initialized");
4227: }
4228: }
4229:
4230: /**
4231: * Return the qualified name of a type object.
4232: *
4233: * @param o The type object.
4234: * @return The (possibly prefixed) type.
4235: */
4236: private String getType(Object o) {
4237: return mapper.toTypeString(o);
4238: }
4239:
4240: /**
4241: * Wrap the specified node in a documentation comment.
4242: *
4243: * @param node The node.
4244: * @param text The comment's text.
4245: * @return The commented node.
4246: */
4247: public static Node comment(Node node, String... text) {
4248: final List<String> l = new ArrayList<String>(text.length);
4249: for (String s : text)
4250: l.add(s);
4251: return new Comment(Comment.Kind.DOCUMENTATION, l, node);
4252: }
4253:
4254: /**
4255: * Convert the specified string to a modifier in a list of modifiers.
4256: *
4257: * @param mod The modifier
4258: * @return The corresponding node.
4259: */
4260: public static Node toModifiers(String mod) {
4261: return GNode.create("Modifiers", GNode.create("Modifier", mod));
4262: }
4263:
4264: /**
4265: * Convert the specified string to a literal node.
4266: *
4267: * @param name The node name.
4268: * @param literal The literal as a string.
4269: * @return The corresponding literal node.
4270: */
4271: public static Node toLiteral(String name, String literal) {
4272: return GNode.create(name, literal);
4273: }
4274:
4275: /**
4276: * Create an identifier node with the specified name.
4277: *
4278: * @param name The name.
4279: * @return The corresponding identifier node.
4280: */
4281: public static Node toIdentifier(String name) {
4282: if (null == name)
4283: throw new AssertionError("null name in toIdentifier");
4284: return GNode.create("PrimaryIdentifier", name);
4285: }
4286:
4287: /**
4288: * Create a conditional statement node.
4289: *
4290: * @param condition The condition node.
4291: * @param action The action statement or block.
4292: * @return The conditional node.
4293: */
4294: public Node toIfStatement(Node condition, Node action) {
4295:
4296: action = (null == action) ? GNode.create("Block") : action;
4297:
4298: Node block = (action.hasName("Block")) ? GNode
4299: .ensureVariable(GNode.cast(action)) : GNode
4300: .ensureVariable(GNode.create("Block", action));
4301:
4302: return GNode.create("ConditionalStatement", condition, block,
4303: null);
4304: }
4305:
4306: /**
4307: * Create a case statemnt
4308: *
4309: * @param clause
4310: * @param action
4311: */
4312: private Node makeCase(Node clause, List<Node> actions, String s) {
4313: Node c = factory.caseStmnt(clause, actions).getGeneric(1);
4314: return c;
4315: }
4316:
4317: /**
4318: * Create a type node.
4319: *
4320: * @param s The name of the type.
4321: * @return The type node.
4322: */
4323: private static Node toType(String s) {
4324: assert null != s : "null string";
4325: return GNode.create("Type", GNode.create("QualifiedIdentifier",
4326: s), null);
4327: }
4328:
4329: /**
4330: * Create new expression with type is a node.
4331: * If args is null empty arguments will be used.
4332: *
4333: * @param name The type node.
4334: * @param args The arguments.
4335: * @param body The option anonymous class body.
4336: */
4337: private Node toNewExpression2(Node name, Node args, Node body) {
4338: if (null == args)
4339: args = GNode.create("Arguments");
4340:
4341: List<Object> arglisto = new ArrayList<Object>(args.size());
4342: args.addAllTo(arglisto);
4343:
4344: Object o = arglisto; // Hack to enable cast from List<Object> to
4345: // List<Node>.
4346:
4347: @SuppressWarnings("unchecked")
4348: List<Node> arglistn = (List<Node>) o;
4349: Node newNode = factory.newExpr(name, arglistn);
4350: newNode.set(4, body);
4351: return newNode;
4352: }
4353:
4354: /**
4355: * Extract the list of arguments from an Arguments node.
4356: *
4357: * @param args The arguments node.
4358: * @return The list of arguments.
4359: */
4360: @SuppressWarnings("unchecked")
4361: private static List<Node> makeArgumentList(Node args) {
4362: if (null == args)
4363: args = GNode.create("Arguments");
4364: List<Object> arguments = new ArrayList<Object>(args.size());
4365: args.addAllTo(arguments);
4366:
4367: Object o = arguments; // Hack to enable cast from List<Object> to
4368: // List<Node>.
4369: return (List<Node>) (o);
4370: }
4371:
4372: }
|