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.Iterator;
0025:
0026: import xtc.util.Runtime;
0027: import xtc.util.Pair;
0028:
0029: import xtc.tree.Node;
0030: import xtc.tree.GNode;
0031:
0032: /**
0033: * Type to Java type mapper.
0034: *
0035: * @author Laune Harris
0036: * @version $Revision: 1.56 $
0037: */
0038: public class TypeMapper {
0039:
0040: class PatternMatchType {
0041:
0042: /** The type of the left hand side. */
0043: public Object left;
0044:
0045: /** The type of the right hand side. */
0046: public Object right;
0047:
0048: /**
0049: * Create a new pattern match type.
0050: *
0051: * @param left The type of the left hand side.
0052: * @param right The type of the right hand side.
0053: */
0054: public PatternMatchType(Object left, Object right) {
0055: this .left = left;
0056: this .right = right;
0057: }
0058:
0059: }
0060:
0061: /** The singleton object indicating an object. */
0062: public static final Object OBJECT = new Object();
0063:
0064: /** The singleton object indicating a pair of objects. */
0065: public static final Object PAIR_OF_OBJECT = new Object();
0066:
0067: /**
0068: * The tuple type of the tuple (name, string, string),
0069: * used in namespace translation.
0070: */
0071: public static final Node nameTupleT = GNode.create("Type", GNode
0072: .create("InstantiatedType", GNode.create(
0073: "TypeInstantiation", "Tuple", null), GNode.create(
0074: "TypeInstantiation", "T3", GNode.create(
0075: "TypeArguments", GNode.create("Type", GNode
0076: .create("QualifiedIdentifier",
0077: "Name"), null), GNode
0078: .create("Type", GNode.create(
0079: "QualifiedIdentifier",
0080: "String"), null), GNode
0081: .create("Type", GNode.create(
0082: "QualifiedIdentifier",
0083: "String"), null)))), null);
0084:
0085: /** The runtime. */
0086: protected final Runtime runtime;
0087:
0088: /** The prefix of the types that belong to the xxxTypes.java file*/
0089: protected final String prefix;
0090:
0091: /** The flag for replacing type with raw_type. */
0092: protected final boolean replaceType;
0093:
0094: /** The prefix without a dot at the end. */
0095: protected final String prefixNoDot;
0096:
0097: /** The tree factory. */
0098: protected final TreeFactory factory;
0099:
0100: /** A list of types that are nodes. */
0101: Pair<String> nodeTypes;
0102:
0103: /** The set of seen match conditions */
0104: protected HashMap<String, String> variableNames = new HashMap<String, String>();
0105:
0106: /** Being processing a function type. */
0107: protected boolean inFunctionType;
0108:
0109: /**
0110: * Create a new type mapper.
0111: *
0112: * @param runtime The runtime.
0113: * @param prefix The class name prefix.
0114: * @param replaceType The flag for replacing type with raw_type.
0115: */
0116: public TypeMapper(Runtime runtime, String prefix,
0117: boolean replaceType, Pair<String> nodeTypes) {
0118: factory = new TreeFactory();
0119: inFunctionType = false;
0120:
0121: this .runtime = runtime;
0122: this .prefixNoDot = prefix;
0123: this .prefix = prefix + ".";
0124: this .replaceType = replaceType;
0125: this .nodeTypes = nodeTypes;
0126: }
0127:
0128: /**
0129: * Make a pattern match type.
0130: *
0131: * @param left The type of the left hand side.
0132: * @param right The type of the right hand side.
0133: */
0134: public PatternMatchType makePatternMatchType(Object left,
0135: Object right) {
0136: if (null == left)
0137: throw new AssertionError("Null left type");
0138: if (null == right)
0139: throw new AssertionError("Null right type");
0140: return new PatternMatchType(left, right);
0141: }
0142:
0143: /**
0144: * Get annotated string from a type.
0145: *
0146: * @param o The type to get the annotated string from.
0147: * @return The annotated string.
0148: */
0149: public static String getAnnotatedString(Object o) {
0150: if (o instanceof TypicalTypes.type) {
0151: TypicalTypes.type t = (TypicalTypes.type) o;
0152: @SuppressWarnings("unchecked")
0153: TypicalTypes.raw_type<?> rt = (TypicalTypes.raw_type<?>) t.type;
0154: return getAnnotatedString(rt);
0155: } else if (o instanceof TypicalTypes.raw_type) {
0156: TypicalTypes.raw_type<?> rt = (TypicalTypes.raw_type<?>) o;
0157: if (rt.isStringName()) {
0158: return (String) rt.getTuple().get1();
0159: } else
0160: throw new AssertionError("unknown type " + rt);
0161: } else
0162: throw new AssertionError("unknown type " + o);
0163: }
0164:
0165: /**
0166: * Get annotated string from a type.
0167: *
0168: * @param o The type to get the annotated string from.
0169: * @return The annotated string.
0170: */
0171: public static Pair<String> getAnnotatedStringList(Object o) {
0172: if (o instanceof TypicalTypes.type) {
0173: TypicalTypes.type t = (TypicalTypes.type) o;
0174: @SuppressWarnings("unchecked")
0175: TypicalTypes.raw_type<?> rt = (TypicalTypes.raw_type<?>) t.type;
0176: return getAnnotatedStringList(rt);
0177: } else if (o instanceof TypicalTypes.raw_type) {
0178: TypicalTypes.raw_type<?> rt = (TypicalTypes.raw_type<?>) o;
0179: if (rt.isStringList()) {
0180: Pair<String> ob = rt.getTuple().get1();
0181: return ob;
0182: } else
0183: throw new AssertionError("unknown type " + rt);
0184: } else
0185: throw new AssertionError("unknown type " + o);
0186: }
0187:
0188: /**
0189: * Print a type as a Java generic type.
0190: *
0191: * @param o The type object.
0192: * @return The JavaTypeString.
0193: */
0194: public String toTypeString(Object o) {
0195: if (null == o)
0196: throw new AssertionError("Null type");
0197:
0198: if (OBJECT == o) {
0199: return "Object";
0200: }
0201:
0202: if (PAIR_OF_OBJECT == o) {
0203: return "Pair<?>";
0204: }
0205:
0206: if (o instanceof String)
0207: return getType((String) o);
0208:
0209: if (o instanceof TypicalTypes.type) {
0210: TypicalTypes.type t = (TypicalTypes.type) o;
0211: return toTypeString(t.type);
0212: } else if (o instanceof TypicalTypes.raw_type) {
0213: TypicalTypes.raw_type<?> rt = (TypicalTypes.raw_type<?>) o;
0214:
0215: if (rt.isBoolT())
0216: return "Boolean";
0217: if (rt.isIntT())
0218: return "BigInteger";
0219: if (rt.isFloat32T())
0220: return "Float";
0221: if (rt.isFloat64T())
0222: return "Double";
0223: if (rt.isStringT())
0224: return "String";
0225: if (rt.isAnyT())
0226: return "Object";
0227: if (rt.isWildcardT())
0228: return "Object";
0229:
0230: if (rt.isVariableT()) {
0231: String str = rt.getTuple().get1();
0232: if (inFunctionType && variableNames.containsKey(str)) {
0233: return variableNames.get(str);
0234: } else
0235: return "Object";
0236: }
0237:
0238: if (rt.isConstructorT())
0239: return getType((String) rt.getTuple().get1());
0240:
0241: if (rt.isVariantT()) {
0242: Pair<Object> params = rt.getTuple().get1();
0243: @SuppressWarnings("unchecked")
0244: TypicalTypes.raw_type<?> variant = unwrapRawType(params
0245: .head());
0246: return getType((String) variant.getTuple().get1());
0247: }
0248:
0249: if (rt.isPolyVariantT())
0250: return getType("Node");
0251:
0252: if (rt.isNodeTypeT())
0253: return getType("Node");
0254:
0255: if (rt.isFieldT()) {
0256: return getType(toTypeString(rt.getTuple().get3()));
0257: }
0258:
0259: if (rt.isConstructedT()) {
0260: // Work around
0261: Object ob = rt;
0262: @SuppressWarnings("unchecked")
0263: TypicalTypes.ConstructedT ct = (TypicalTypes.ConstructedT) ob;
0264: String str = (String) ct.getTuple().get2();
0265: if ("list".equals(str)) {
0266: return "Pair<" + getType(toTypeString(getBase(rt)))
0267: + ">";
0268: } else if ("var".equals(str)) {
0269: return getType(toTypeString(getBase(rt)));
0270: } else {
0271: return str;
0272: }
0273: }
0274:
0275: if (rt.isTypeName())
0276: return getType((String) rt.getTuple().get1());
0277:
0278: if (rt.isRecordT()) {
0279: Pair<Object> p = rt.getTuple().get1();
0280: Object head = p.head();
0281: @SuppressWarnings("unchecked")
0282: TypicalTypes.raw_type field = unwrapRawType(head);
0283: if (field.isFieldT()) {
0284: final String recName = (String) field.getTuple()
0285: .get1();
0286: return getType(recName);
0287: } else {
0288: return toTypeString(field);
0289: }
0290: }
0291:
0292: if (rt.isTupleT()) {
0293: List<String> members = getMembers(rt);
0294: String res = "Tuple.T" + members.size() + "<";
0295: for (int i = 0; i < members.size(); i++) {
0296: res += getType(members.get(i));
0297: if (i < members.size() - 1) {
0298: res += ",";
0299: }
0300: }
0301: res += ">";
0302: return res;
0303: }
0304:
0305: if (rt.isPairOfType()) {
0306: return toTypeString(rt.getTuple().get1());
0307: }
0308: if (rt.isFunctionT()) {
0309: inFunctionType = true;
0310: List<String> paramTypes = getParameterTypes(o);
0311: String ret = getReturnType(o);
0312:
0313: StringBuilder str = new StringBuilder("Function.F"
0314: + paramTypes.size() + "<" + ret);
0315: for (String s : paramTypes)
0316: str.append("," + s);
0317: str.append(">");
0318: inFunctionType = false;
0319: return str.toString();
0320: }
0321: } else if (o instanceof PatternMatchType) {
0322: PatternMatchType po = (PatternMatchType) o;
0323: return toTypeString(po.left);
0324: }
0325:
0326: throw new AssertionError("unknown type " + o);
0327: }
0328:
0329: /**
0330: * Get a java type node from a typical type
0331: *
0332: * @param o The typical type object
0333: * @param objectToWild To check if need to change Object to ?
0334: * @return The corresponding java type node
0335: */
0336: public Node toTypeNode(Object o, boolean objectToWild) {
0337: if (null == o)
0338: throw new AssertionError("Null type");
0339:
0340: // If this is already a type node, return it
0341: if (o instanceof Node)
0342: return (Node) o;
0343:
0344: // Object type
0345: if (OBJECT == o)
0346: return makeTypeNode("Object", objectToWild);
0347:
0348: // A type name
0349: if (o instanceof String)
0350: return makeTypeNode((String) o, objectToWild);
0351:
0352: // Pair of Object type
0353: if (PAIR_OF_OBJECT == o) {
0354: return GNode.create("Type", GNode.create(
0355: "InstantiatedType", GNode.create(
0356: "TypeInstantiation", "Pair", GNode.create(
0357: "TypeArguments", GNode.create(
0358: "Wildcard", null)))), null);
0359: }
0360:
0361: // A Typical type
0362: if (o instanceof TypicalTypes.type) {
0363: TypicalTypes.type t = (TypicalTypes.type) o;
0364: return toTypeNode(t.type, objectToWild);
0365: } // A raw_type
0366: else if (o instanceof TypicalTypes.raw_type) {
0367: TypicalTypes.raw_type<?> rt = (TypicalTypes.raw_type<?>) o;
0368:
0369: // Basic types
0370: if (rt.isBoolT())
0371: return makeTypeNode("Boolean", false);
0372: if (rt.isIntT())
0373: return makeTypeNode("BigInteger", false);
0374: if (rt.isFloat32T())
0375: return makeTypeNode("Float", false);
0376: if (rt.isFloat64T())
0377: return makeTypeNode("Double", false);
0378: if (rt.isStringT())
0379: return makeTypeNode("String", false);
0380: if (rt.isAnyT())
0381: return makeTypeNode("Object", objectToWild);
0382: if (rt.isWildcardT())
0383: return makeTypeNode("Object", objectToWild);
0384: //if (rt.isVariableT()) return makeTypeNode("Object", objectToWild);
0385:
0386: if (rt.isVariableT()) {
0387: String str = rt.getTuple().get1();
0388: if (inFunctionType && variableNames.containsKey(str)) {
0389: return GNode.create("Type", GNode.create(
0390: "QualifiedIdentifier", variableNames
0391: .get(str)), null);
0392: } else
0393: return makeTypeNode("Object", objectToWild);
0394: }
0395:
0396: // Constructor type
0397: if (rt.isConstructorT()) {
0398: return makeTypeNode((String) rt.getTuple().get1(),
0399: objectToWild);
0400: }
0401:
0402: // Variant type
0403: if (rt.isVariantT()) {
0404: Pair<Object> params = rt.getTuple().get1();
0405: @SuppressWarnings("unchecked")
0406: TypicalTypes.raw_type<?> variant = unwrapRawType(params
0407: .head());
0408: return makeTypeNode((String) variant.getTuple().get1(),
0409: objectToWild);
0410: }
0411:
0412: if (rt.isPolyVariantT())
0413: return makeTypeNode("Node", objectToWild);
0414:
0415: if (rt.isNodeTypeT())
0416: return makeTypeNode("Node", objectToWild);
0417: // Field type
0418: if (rt.isFieldT()) {
0419: return toTypeNode(rt.getTuple().get3(), objectToWild);
0420: }
0421:
0422: // Constructed type
0423: if (rt.isConstructedT()) {
0424: // Work around
0425: Object ob = rt;
0426: @SuppressWarnings("unchecked")
0427: TypicalTypes.ConstructedT ct = (TypicalTypes.ConstructedT) ob;
0428: String str = (String) ct.getTuple().get2();
0429: Node baseNode = toTypeNode(getBase(rt), objectToWild);
0430: if ("list".equals(str)) {
0431: return GNode.create("Type", GNode.create(
0432: "InstantiatedType", GNode.create(
0433: "TypeInstantiation", "Pair", GNode
0434: .create("TypeArguments",
0435: baseNode))), null);
0436: } else if ("var".equals(str)) {
0437: return baseNode;
0438: } else {
0439: return makeTypeNode(str, objectToWild);
0440: }
0441: }
0442:
0443: // Type name
0444: if (rt.isTypeName()) {
0445: return makeTypeNode((String) rt.getTuple().get1(),
0446: objectToWild);
0447: }
0448:
0449: // Record type
0450: if (rt.isRecordT()) {
0451: Pair<Object> p = rt.getTuple().get1();
0452: Object head = p.head();
0453: @SuppressWarnings("unchecked")
0454: TypicalTypes.raw_type field = unwrapRawType(head);
0455: if (field.isFieldT()) {
0456: final String recName = (String) field.getTuple()
0457: .get1();
0458: return makeTypeNode(recName, objectToWild);
0459: } else {
0460: return toTypeNode(field, objectToWild);
0461: }
0462: }
0463:
0464: // Tuple type
0465: if (rt.isTupleT()) {
0466:
0467: //Workaround to fix incompatible type bug on Mac OS
0468: Object o1 = rt;
0469: @SuppressWarnings("unchecked")
0470: TypicalTypes.TupleT tt = (TypicalTypes.TupleT) o1;
0471: //End workaround
0472:
0473: List<Object> members = new ArrayList<Object>();
0474: @SuppressWarnings("unchecked")
0475: Pair<?> tl = tt.getTuple().get1();
0476: for (Iterator<?> iter = tl.iterator(); iter.hasNext();) {
0477: members.add(iter.next());
0478: }
0479: // Make type arguments
0480: Node typeArgs = GNode.create("TypeArguments");
0481:
0482: for (Object ob : members)
0483: typeArgs.add(toTypeNode(ob, objectToWild));
0484:
0485: // Return the tuple type
0486: return GNode.create("Type", GNode.create(
0487: "InstantiatedType", GNode.create(
0488: "TypeInstantiation", "Tuple", null),
0489: GNode.create("TypeInstantiation", "T"
0490: + members.size(), typeArgs)), null);
0491: }
0492:
0493: if (rt.isPairOfType()) {
0494: return toTypeNode(rt.getTuple().get1(), objectToWild);
0495: }
0496:
0497: // Function type
0498: if (rt.isFunctionT()) {
0499: inFunctionType = true;
0500: List<Object> paramTypes = new ArrayList<Object>();
0501:
0502: Pair<?> params = cast(rt.getTuple().get1());
0503: for (Iterator<?> iter = params.iterator(); iter
0504: .hasNext();) {
0505: paramTypes.add(iter.next());
0506: }
0507:
0508: Node retTypeNode;
0509: Object retType = rt.getTuple().get2();
0510: if (retType instanceof TypicalTypes.type) {
0511: TypicalTypes.type retT = (TypicalTypes.type) retType;
0512: if (null == retT.type) {
0513: retTypeNode = makeTypeNode("Void", false);
0514: } else {
0515: retTypeNode = toTypeNode(retT, objectToWild);
0516: }
0517: } else {
0518: if (null == retType) {
0519: retTypeNode = makeTypeNode("Void", false);
0520: } else {
0521: retTypeNode = toTypeNode(retType, objectToWild);
0522: }
0523: }
0524:
0525: // Make type arguments
0526: Node typeArgs = GNode.create("TypeArguments");
0527: typeArgs.add(retTypeNode);
0528:
0529: for (Object ob : paramTypes)
0530: typeArgs.add(toTypeNode(ob, objectToWild));
0531: inFunctionType = false;
0532: // Return the function type
0533: return GNode.create("Type", GNode.create(
0534: "InstantiatedType", GNode.create(
0535: "TypeInstantiation", "Function", null),
0536: GNode.create("TypeInstantiation", "F"
0537: + paramTypes.size(), typeArgs)), null);
0538: }
0539: } else if (o instanceof PatternMatchType) {
0540: PatternMatchType po = (PatternMatchType) o;
0541: return toTypeNode(po.left, objectToWild);
0542: }
0543:
0544: throw new AssertionError("unknown type " + o);
0545: }
0546:
0547: /**
0548: * Get type variables from a typical type
0549: *
0550: * @param o The type to get type variables from
0551: * @return A list of type variables
0552: */
0553: public List<String> getTypeVariables(Object o) {
0554: List<String> res = new ArrayList<String>();
0555: if (null == o)
0556: return res;
0557:
0558: if (isTGType(o)) {
0559: // Get the type field
0560: TypicalTypes.raw_type<?> rt = unwrapRawType(o);
0561:
0562: if (null == rt)
0563: return res;
0564:
0565: if (rt.isVariableT()) {
0566: res.add((String) rt.getTuple().get1());
0567: return res;
0568: }
0569:
0570: // Check with each kind of field type
0571: if (rt.isConstructorT()) {
0572: return getTypeVariables(rt.getTuple().get3());
0573: }
0574:
0575: if (rt.isVariantT()) {
0576: Pair<Object> tl = rt.getTuple().get1();
0577: for (Iterator<?> iter = tl.iterator(); iter.hasNext();) {
0578: List<String> varList = getTypeVariables(iter.next());
0579: for (String mem : varList)
0580: if (-1 == res.indexOf(mem))
0581: res.add(mem);
0582: }
0583: return res;
0584: }
0585:
0586: if (rt.isFieldT()) {
0587: return getTypeVariables(rt.getTuple().get3());
0588: }
0589:
0590: if (rt.isConstructedT()) {
0591: // FIXME HERE - Support other constructed types
0592: return getTypeVariables(getBase(rt));
0593: }
0594:
0595: if (rt.isRecordT()) {
0596: Pair<Object> tl = rt.getTuple().get1();
0597: for (Iterator<?> iter = tl.iterator(); iter.hasNext();) {
0598: List<String> varList = getTypeVariables(iter.next());
0599: for (String mem : varList)
0600: if (-1 == res.indexOf(mem))
0601: res.add(mem);
0602: }
0603: return res;
0604: }
0605:
0606: if (rt.isTupleT()) {
0607: //Workaround to fix incompatible type bug on Mac OS
0608: Object o1 = rt;
0609: @SuppressWarnings("unchecked")
0610: TypicalTypes.TupleT tt = (TypicalTypes.TupleT) o1;
0611: //End workaround
0612:
0613: @SuppressWarnings("unchecked")
0614: Pair<?> tl = tt.getTuple().get1();
0615: for (Iterator<?> iter = tl.iterator(); iter.hasNext();) {
0616: List<String> varList = getTypeVariables(iter.next());
0617: for (String mem : varList)
0618: if (-1 == res.indexOf(mem))
0619: res.add(mem);
0620: }
0621: return res;
0622: }
0623:
0624: if (rt.isPairOfType()) {
0625: List<String> varList = getTypeVariables(rt.getTuple()
0626: .get1());
0627: res = varList;
0628: varList = getTypeVariables(rt.getTuple().get2());
0629: for (String mem : varList)
0630: if (-1 == res.indexOf(mem))
0631: res.add(mem);
0632: return res;
0633: }
0634:
0635: if (rt.isFunctionT()) {
0636: Pair<?> params = cast(rt.getTuple().get1());
0637: List<String> varList;
0638: for (Iterator<?> iter = params.iterator(); iter
0639: .hasNext();) {
0640: varList = getTypeVariables(iter.next());
0641: for (String mem : varList)
0642: if (-1 == res.indexOf(mem))
0643: res.add(mem);
0644: }
0645:
0646: TypicalTypes.type retType = (TypicalTypes.type) rt
0647: .getTuple().get2();
0648: varList = getTypeVariables(retType);
0649: for (String mem : varList)
0650: if (-1 == res.indexOf(mem))
0651: res.add(mem);
0652: return res;
0653: }
0654: return res;
0655:
0656: } else if (o instanceof PatternMatchType) {
0657: PatternMatchType po = (PatternMatchType) o;
0658: List<String> varList = getTypeVariables(po.left);
0659: res = varList;
0660: varList = getTypeVariables(po.right);
0661: for (String mem : varList)
0662: if (-1 == res.indexOf(mem))
0663: res.add(mem);
0664: return res;
0665:
0666: } else { // Not a typical type
0667: throw new AssertionError("unknown type " + o);
0668: }
0669: }
0670:
0671: /**
0672: * Preprocess type variables in function type
0673: *
0674: * @param o The function type to process
0675: * @param index The starting index
0676: * @return the number of type parameters
0677: */
0678: public int processTypeVariables(Object o, int index) {
0679: if (null == o)
0680: throw new AssertionError("Null type");
0681:
0682: if (isTGType(o)) {
0683: // Get the type field
0684: TypicalTypes.raw_type<?> rt = unwrapRawType(o);
0685: if (rt.isFunctionT()) {
0686: Pair<?> params = cast(rt.getTuple().get1());
0687: Object retType = rt.getTuple().get2();
0688:
0689: // Get type variables from return type
0690: List<String> retTypeVariables = getTypeVariables(retType);
0691:
0692: // Get all type variables from parameter types
0693: List<String> sl = new ArrayList<String>();
0694: for (Iterator<?> iter = params.iterator(); iter
0695: .hasNext();) {
0696: List<String> varList = getTypeVariables(iter.next());
0697: for (String mem : varList)
0698: if (-1 == sl.indexOf(mem))
0699: sl.add(mem);
0700: }
0701:
0702: // If a type variables is in return type, assign a new name and
0703: // put in the hash map, otherwise put "Object"
0704: int res = 0;
0705:
0706: for (String mem : sl) {
0707: if (-1 != retTypeVariables.indexOf(mem)) {
0708: variableNames.put(mem, "T" + index);
0709: index++;
0710: res++;
0711: } else {
0712: variableNames.put(mem, "Object");
0713: }
0714: }
0715:
0716: if ((null != retType) && isFunctionType(retType)) {
0717: res = res + processTypeVariables(retType, index);
0718: }
0719:
0720: return res;
0721:
0722: } else {
0723: throw new AssertionError(
0724: "function type expected, found " + o);
0725: }
0726: } else {
0727: throw new AssertionError("unknown type " + o);
0728: }
0729:
0730: }
0731:
0732: /**
0733: * Get the type of the left side of a pattern matching.
0734: *
0735: * @param o The pattern match type.
0736: * @return The left type.
0737: */
0738: public Object getPatternMatchLeftType(Object o) {
0739: if (null == o)
0740: throw new AssertionError("Null type");
0741:
0742: TypicalTypes.raw_type<?> pm = null;
0743: if (isTGType(o)) {
0744: pm = unwrapRawType(o);
0745: if (pm.isPairOfType())
0746: return pm.getTuple().get1();
0747: else {
0748: throw new AssertionError(
0749: "PairOfType is expected, found " + o);
0750: }
0751: } else if (o instanceof PatternMatchType) {
0752: PatternMatchType po = (PatternMatchType) o;
0753: return po.left;
0754: } else {
0755: throw new AssertionError("unknown type " + o);
0756: }
0757: }
0758:
0759: /**
0760: * Get the type of the left side of a pattern matching.
0761: *
0762: * @param o The pattern match type.
0763: * @return The left type.
0764: */
0765: public Object getPatternMatchRightType(Object o) {
0766: if (null == o)
0767: throw new AssertionError("Null type");
0768:
0769: TypicalTypes.raw_type<?> pm = null;
0770: if (isTGType(o)) {
0771: pm = unwrapRawType(o);
0772: if (pm.isPairOfType())
0773: return pm.getTuple().get2();
0774: else {
0775: throw new AssertionError(
0776: "PairOfType is expected, found " + o);
0777: }
0778: } else if (o instanceof PatternMatchType) {
0779: PatternMatchType po = (PatternMatchType) o;
0780: return po.left;
0781: } else {
0782: throw new AssertionError("unknown type " + o);
0783: }
0784: }
0785:
0786: /**
0787: * Unwrapp a raw_type.
0788: *
0789: * @param o The type object.
0790: * @return Unwrapped raw_type.
0791: */
0792: private TypicalTypes.raw_type<?> unwrapRawType(Object o) {
0793: if (null == o)
0794: throw new AssertionError("Null type");
0795:
0796: if (o instanceof TypicalTypes.raw_type)
0797: return (TypicalTypes.raw_type<?>) o;
0798:
0799: if (o instanceof TypicalTypes.type) {
0800: TypicalTypes.type t = (TypicalTypes.type) o;
0801: return t.type;
0802: }
0803:
0804: throw new IllegalArgumentException("can't unwrap non type");
0805: }
0806:
0807: /**
0808: * Test if a type is a list type.
0809: *
0810: * @param o The type to test.
0811: * @return <code> true </code> if this type is a list type,
0812: * <code> false </code> otherwise.
0813: */
0814: public boolean isList(Object o) {
0815: if (null == o)
0816: throw new AssertionError("Null type");
0817:
0818: // FIXME check the constructor.
0819: if (PAIR_OF_OBJECT == o)
0820: return true;
0821:
0822: TypicalTypes.raw_type<?> rt = null;
0823:
0824: if (isTGType(o)) {
0825: rt = unwrapRawType(o);
0826: } else {
0827: throw new AssertionError("unknown type " + o);
0828: }
0829: if (!rt.isConstructedT())
0830: return false;
0831: else {
0832: // Work around
0833: Object ob = rt;
0834: @SuppressWarnings("unchecked")
0835: TypicalTypes.ConstructedT ct = (TypicalTypes.ConstructedT) ob;
0836: String str = (String) ct.getTuple().get2();
0837: return "list".equals(str);
0838: }
0839: }
0840:
0841: /**
0842: * Test if a type is a variable type.
0843: *
0844: * @param o The type to test.
0845: * @return <code> true </code> if this type is a variable type,
0846: * <code> false </code> otherwise.
0847: */
0848: public boolean isVariable(Object o) {
0849: if (null == o)
0850: throw new AssertionError("Null type");
0851:
0852: // FIXME check the constructor.
0853: if (PAIR_OF_OBJECT == o)
0854: return true;
0855:
0856: TypicalTypes.raw_type<?> rt = null;
0857:
0858: if (isTGType(o)) {
0859: rt = unwrapRawType(o);
0860: } else {
0861: throw new AssertionError("unknown type " + o);
0862: }
0863: if (!rt.isConstructedT())
0864: return false;
0865: else {
0866: // Work around
0867: Object ob = rt;
0868: @SuppressWarnings("unchecked")
0869: TypicalTypes.ConstructedT ct = (TypicalTypes.ConstructedT) ob;
0870: String str = (String) ct.getTuple().get2();
0871: return "var".equals(str);
0872: }
0873: }
0874:
0875: /**
0876: * Check if this type contains an any type.
0877: *
0878: * @param o The type to test.
0879: * @return <code> true </code> if this type contains an any type,
0880: * <code> false </code> otherwise.
0881: */
0882: public boolean containsAny(Object o) {
0883: if (null == o)
0884: throw new AssertionError("Null type");
0885:
0886: List<String> members = getMembers(o);
0887:
0888: if (members.contains("AnyT"))
0889: return true;
0890:
0891: return false;
0892: }
0893:
0894: /**
0895: * Test if a type is a node.
0896: *
0897: * The type object.
0898: *
0899: * @return <code>true</code> if node <code>false</code> otherwise.
0900: */
0901: public boolean isNode(Object o) {
0902: return "Node".equals(toTypeString(o));
0903: }
0904:
0905: /**
0906: * Get the base of a contstructed type.
0907: *
0908: * @param o The type object.
0909: * @return The base type.
0910: */
0911: public Object getBase(Object o) {
0912: if (null == o)
0913: throw new AssertionError("Null type");
0914:
0915: if (PAIR_OF_OBJECT == o)
0916: return OBJECT;
0917:
0918: TypicalTypes.raw_type<?> rt = null;
0919:
0920: if (isTGType(o))
0921: rt = unwrapRawType(o);
0922: else
0923: throw new AssertionError("Not a type " + o);
0924:
0925: if (rt.isConstructedT()) {
0926: Pair<Object> p = cast(rt.getTuple().get1());
0927: return p.head();
0928: } else {
0929: throw new AssertionError("ConstructedT is expected, found "
0930: + o);
0931: }
0932: }
0933:
0934: /**
0935: * Test if this type object is a function type.
0936: *
0937: * @param o The type to test.
0938: * @return <code>true</code> if function type, false otherwise.
0939: */
0940: public boolean isFunctionType(Object o) {
0941: if (null == o)
0942: throw new AssertionError("Null type");
0943:
0944: if (isTGType(o)) {
0945: TypicalTypes.raw_type<?> rt = unwrapRawType(o);
0946: return (null != rt) && rt.isFunctionT();
0947: }
0948: return false;
0949: }
0950:
0951: /**
0952: * Test if this object is a generated type.
0953: *
0954: * @param o The type object to test.
0955: * @return <code> true</code> if o is a generated type, false otherwise.
0956: */
0957: private boolean isTGType(Object o) {
0958: return (o instanceof TypicalTypes.type || o instanceof TypicalTypes.raw_type);
0959: }
0960:
0961: /**
0962: * Get the the return type from a type.
0963: *
0964: * @param o The type object.
0965: * @return The Java Type of this return type.
0966: */
0967: public String getReturnType(Object o) {
0968: if (null == o)
0969: throw new AssertionError("Null type");
0970:
0971: TypicalTypes.raw_type<?> rt = null;
0972: if (isTGType(o))
0973: rt = unwrapRawType(o);
0974: else
0975: throw new AssertionError("Not a type " + o);
0976:
0977: if (rt.isFunctionT()) {
0978: inFunctionType = true;
0979: Object ob = rt.getTuple().get2();
0980:
0981: if (null == ob)
0982: return "Void";
0983:
0984: TypicalTypes.raw_type<?> retType = unwrapRawType(ob);
0985:
0986: if (null == retType)
0987: return "Void";
0988: String res = getType(toTypeString(retType));
0989: inFunctionType = false;
0990: return res;
0991: } else {
0992: return getType(toTypeString(rt));
0993: }
0994: }
0995:
0996: /**
0997: * Get the the return type node from a type.
0998: *
0999: * @param o The type object.
1000: * @return The Java type node of this return type.
1001: */
1002: public Node getReturnTypeNode(Object o) {
1003: if (null == o)
1004: throw new AssertionError("Null type");
1005:
1006: TypicalTypes.raw_type<?> rt = null;
1007: if (isTGType(o))
1008: rt = unwrapRawType(o);
1009: else
1010: throw new AssertionError("Not a type " + o);
1011:
1012: if (rt.isFunctionT()) {
1013: inFunctionType = true;
1014: Object ob = rt.getTuple().get2();
1015: if (null == ob)
1016: return makeTypeNode("Void", false);
1017:
1018: TypicalTypes.raw_type<?> retType = unwrapRawType(ob);
1019: if (null == retType)
1020: return makeTypeNode("Void", false);
1021: Node res = toTypeNode(retType, false);
1022: inFunctionType = false;
1023: return res;
1024: } else {
1025: return toTypeNode(rt, false);
1026: }
1027: }
1028:
1029: /**
1030: * Get the list of java types from a types parameter list.
1031: *
1032: * @param o The type object
1033: * @return The list of java types.
1034: */
1035: public List<String> getParameterTypes(Object o) {
1036: if (null == o)
1037: throw new AssertionError("Null type");
1038:
1039: List<String> pts = new ArrayList<String>();
1040:
1041: if (isTGType(o)) {
1042: inFunctionType = true;
1043: TypicalTypes.raw_type<?> pm = unwrapRawType(o);
1044:
1045: if (!pm.isFunctionT()) {
1046: throw new AssertionError(
1047: "FunctionT is expected, found " + o);
1048: }
1049:
1050: Pair<?> params = cast(pm.getTuple().get1());
1051: for (Iterator<?> iter = params.iterator(); iter.hasNext();) {
1052: Object x = iter.next();
1053: pts.add(getType(toTypeString(x)));
1054: }
1055: inFunctionType = false;
1056: return pts;
1057: }
1058: return null;
1059: }
1060:
1061: /**
1062: * Get the list of java type nodes from a types parameter list.
1063: *
1064: * @param o The type object
1065: * @return The list of java type nodes.
1066: */
1067: public List<Node> getParameterTypeNodes(Object o) {
1068: if (null == o)
1069: throw new AssertionError("Null type");
1070:
1071: List<Node> pts = new ArrayList<Node>();
1072:
1073: if (isTGType(o)) {
1074: inFunctionType = true;
1075:
1076: TypicalTypes.raw_type<?> pm = unwrapRawType(o);
1077:
1078: if (!pm.isFunctionT()) {
1079: throw new AssertionError(
1080: "FunctionT is expected, found " + o);
1081: }
1082:
1083: Pair<?> params = cast(pm.getTuple().get1());
1084: for (Iterator<?> iter = params.iterator(); iter.hasNext();) {
1085: pts.add(toTypeNode(iter.next(), false));
1086: }
1087: inFunctionType = false;
1088: return pts;
1089: }
1090: return null;
1091: }
1092:
1093: /**
1094: * Get the field types from a record.
1095: *
1096: * @param o The type object.
1097: * @return The list of field types.
1098: */
1099: public List<String> getFieldTypes(Object o) {
1100: if (null == o)
1101: throw new AssertionError("Null type");
1102:
1103: List<String> fieldTypes = new ArrayList<String>();
1104:
1105: TypicalTypes.raw_type<?> pm = null;
1106: if (!isTGType(o))
1107: throw new AssertionError("Not a type " + o);
1108:
1109: pm = unwrapRawType(o);
1110: if (!pm.isRecordT()) {
1111: throw new AssertionError("RecordT is expected, found " + o);
1112: }
1113:
1114: Pair<Object> mems = cast(pm.getTuple().get1());
1115:
1116: for (Iterator<Object> iter = mems.iterator(); iter.hasNext();) {
1117: // Cast to object first to avoid inconvertible types error with Java 5.
1118: TypicalTypes.FieldT ft = (TypicalTypes.FieldT) (Object) (unwrapRawType(iter
1119: .next()));
1120: fieldTypes.add(getType(toTypeString(ft.getTuple().get3())));
1121: }
1122:
1123: return fieldTypes;
1124: }
1125:
1126: /**
1127: * Get the field type nodes from a record.
1128: *
1129: * @param o The type object.
1130: * @return The list of field type nodes.
1131: */
1132: public List<Node> getFieldTypeNodes(Object o) {
1133: if (null == o)
1134: throw new AssertionError("Null type");
1135:
1136: List<Node> fieldTypes = new ArrayList<Node>();
1137:
1138: TypicalTypes.raw_type<?> pm = null;
1139: if (!isTGType(o))
1140: throw new AssertionError("Not a type " + o);
1141:
1142: pm = unwrapRawType(o);
1143: if (!pm.isRecordT()) {
1144: throw new AssertionError("RecordT is expected, found " + o);
1145: }
1146:
1147: Pair<Object> mems = cast(pm.getTuple().get1());
1148:
1149: for (Iterator<Object> iter = mems.iterator(); iter.hasNext();) {
1150: // Cast to object first to avoid inconvertible types error with Java 5.
1151: TypicalTypes.FieldT ft = (TypicalTypes.FieldT) (Object) (unwrapRawType(iter
1152: .next()));
1153: fieldTypes.add(toTypeNode(ft.getTuple().get3(), false));
1154: }
1155: return fieldTypes;
1156: }
1157:
1158: /**
1159: * Get the list of field names from a record.
1160: *
1161: * @param o The type object.
1162: * @return The list of field names.
1163: */
1164: public List<String> getFieldNames(Object o) {
1165: if (null == o)
1166: throw new AssertionError("Null type");
1167:
1168: List<String> fieldNames = new ArrayList<String>();
1169:
1170: TypicalTypes.raw_type<?> pm = null;
1171: if (!isTGType(o))
1172: throw new AssertionError("Not a type " + o);
1173:
1174: pm = unwrapRawType(o);
1175: if (!pm.isRecordT()) {
1176: throw new AssertionError("RecordT is expected, found " + o);
1177: }
1178:
1179: Pair<Object> mems = cast(pm.getTuple().get1());
1180:
1181: for (Iterator<Object> iter = mems.iterator(); iter.hasNext();) {
1182: Object j = unwrapRawType(iter.next());
1183: TypicalTypes.FieldT ft = (TypicalTypes.FieldT) j;
1184: String fn = ft.getTuple().get2();
1185: fieldNames.add(fn);
1186: }
1187: return fieldNames;
1188: }
1189:
1190: /**
1191: * Get the members from a constructor type.
1192: *
1193: * @param o The type object.
1194: * @return The list of members.
1195: */
1196: @SuppressWarnings("unchecked")
1197: public List<String> getMembers(Object o) {
1198: List<String> members = new ArrayList<String>();
1199:
1200: List<Object> memberObjects = getMemberObjects(o);
1201:
1202: for (Object object : memberObjects) {
1203: members.add(toTypeString(object));
1204: }
1205:
1206: return members;
1207: }
1208:
1209: /**
1210: * Get the members from a constructor type.
1211: *
1212: * @param o The type object.
1213: * @return The list of members.
1214: */
1215: @SuppressWarnings("unchecked")
1216: public List<Object> getMemberObjects(Object o) {
1217: if (null == o)
1218: throw new AssertionError("Null type");
1219: if (!isTGType(o))
1220: throw new AssertionError("Not a type " + o);
1221:
1222: List<Object> members = new ArrayList<Object>();
1223:
1224: TypicalTypes.raw_type rt = unwrapRawType(o);
1225:
1226: if (rt.isConstructorT()) {
1227: TypicalTypes.ConstructorT c = (TypicalTypes.ConstructorT) rt;
1228: if (null == c.getTuple().get3()) {
1229: return members;
1230: }
1231: TypicalTypes.raw_type type = unwrapRawType(c.getTuple()
1232: .get3());
1233:
1234: if (type.isTupleT()) {
1235: TypicalTypes.TupleT tt = (TypicalTypes.TupleT) type;
1236:
1237: @SuppressWarnings("unchecked")
1238: Pair<?> tl = tt.getTuple().get1();
1239: for (Iterator<?> iter = tl.iterator(); iter.hasNext();) {
1240: members.add(iter.next());
1241: }
1242: return members;
1243: } else {
1244: members.add(type);
1245: return members;
1246: }
1247: }
1248:
1249: if (null != rt && rt.isTupleT()) {
1250: @SuppressWarnings("unchecked")
1251: Pair<Object> tl = (Pair<Object>) rt.getTuple().get1();
1252: for (Iterator<Object> iter = tl.iterator(); iter.hasNext();) {
1253: members.add(toTypeString(iter.next()));
1254: }
1255: return members;
1256: }
1257: throw new AssertionError("unknown type " + o);
1258: }
1259:
1260: /**
1261: * Get the member nodes from a constructor type.
1262: *
1263: * @param o The type object.
1264: * @return The list of member nodes.
1265: */
1266: @SuppressWarnings("unchecked")
1267: public List<Node> getMemberNodes(Object o) {
1268: if (null == o)
1269: throw new AssertionError("Null type");
1270:
1271: List<Node> members = new ArrayList<Node>();
1272:
1273: if (o instanceof Node) {
1274: Node n = (Node) o;
1275: Node no = n.getGeneric(0).getGeneric(1).getGeneric(1);
1276: for (int i = 0; i < no.size(); i++) {
1277: members.add(no.getGeneric(i));
1278: }
1279: return members;
1280: }
1281:
1282: if (!isTGType(o))
1283: throw new AssertionError("Not a type " + o);
1284: TypicalTypes.raw_type rt = unwrapRawType(o);
1285:
1286: if (rt.isConstructorT()) {
1287: TypicalTypes.ConstructorT c = (TypicalTypes.ConstructorT) rt;
1288: if (null == c.getTuple().get3()) {
1289: return members;
1290: }
1291: TypicalTypes.raw_type type = unwrapRawType(c.getTuple()
1292: .get3());
1293:
1294: if (type.isTupleT()) {
1295: TypicalTypes.TupleT tt = (TypicalTypes.TupleT) type;
1296:
1297: @SuppressWarnings("unchecked")
1298: Pair<?> tl = tt.getTuple().get1();
1299: for (Iterator<?> iter = tl.iterator(); iter.hasNext();) {
1300: members.add(toTypeNode(iter.next(), false));
1301: }
1302: return members;
1303: } else {
1304: members.add(toTypeNode(type, false));
1305: return members;
1306: }
1307: }
1308:
1309: if (null != rt && rt.isTupleT()) {
1310: @SuppressWarnings("unchecked")
1311: Pair<Object> tl = (Pair<Object>) rt.getTuple().get1();
1312: for (Iterator<Object> iter = tl.iterator(); iter.hasNext();) {
1313: members.add(toTypeNode(iter.next(), false));
1314: }
1315: return members;
1316: }
1317: throw new AssertionError("unknown type " + o);
1318: }
1319:
1320: /** MagiCast (TM). Use at the peril of your eternal soul. */
1321: @SuppressWarnings("unchecked")
1322: private <T> Pair<T> cast(T o) {
1323: return (Pair<T>) o;
1324: }
1325:
1326: /**
1327: * Add the prefix to types that need it
1328: *
1329: * @param t The type.
1330: * @return The possibly prefixed type.
1331: */
1332: private String getType(String t) {
1333: String t1;
1334:
1335: t1 = "raw_type".equals(t) ? "raw_type<?>" : t;
1336: t1 = "Pair".equals(t1) ? "Pair<?>" : t1;
1337:
1338: if (replaceType && "type".equals(t1)) {
1339: t1 = "raw_type<?>";
1340: }
1341:
1342: // if ("node".equals(t1)) t1 = "Node" ;
1343: if (nodeTypes.contains(t1))
1344: t1 = "Node";
1345: else if ("name".equals(t1))
1346: t1 = "Name";
1347: else if ("scope_kind".equals(t1))
1348: t1 = "ScopeKind";
1349: else if ("scopeT".equals(t1))
1350: t1 = "Scope";
1351:
1352: if ("Named".equals(t1))
1353: return "ScopeKind.Named";
1354: else if ("Anonymous".equals(t1))
1355: return "ScopeKind.Anonymous";
1356: else if ("Temporary".equals(t1))
1357: return "ScopeKind.Temporary";
1358: else if ("SimpleName".equals(t1))
1359: return "Name.SimpleName";
1360: else if ("QualifiedName".equals(t1))
1361: return "Name.QualifiedName";
1362:
1363: else if ("Object".equals(t1) || "String".equals(t1)
1364: || "BigInteger".equals(t1) || "Float".equals(t1)
1365: || "Double".equals(t1) || "Node".equals(t1)
1366: || "GNode".equals(t1) || "Boolean".equals(t1)
1367: || t1.startsWith("Pair<") || t1.startsWith("Tuple.T")
1368: || t1.startsWith("Function.F") || t1.startsWith(prefix)
1369: || "Name".equals(t1) || "Scope".equals(t1)
1370: || "ScopeKind".equals(t1) || "Void".equals(t1))
1371: return t1;
1372: else
1373: return prefix + t1;
1374: }
1375:
1376: /**
1377: * Make a type node from a string
1378: *
1379: * @param str The name of the type
1380: * @param objectToWild To check if need to change Object to ?
1381: * @return The type node
1382: */
1383: private Node makeTypeNode(String str, boolean objectToWild) {
1384: String s;
1385:
1386: s = "raw_type".equals(str) ? "raw_type<?>" : str;
1387:
1388: if (replaceType && "type".equals(str)) {
1389: s = "raw_type<?>";
1390: }
1391:
1392: if (objectToWild && "Object".equals(str)) {
1393: return GNode.create("Wildcard", null);
1394: }
1395:
1396: //if ("node".equals(s)) s = "Node" ;
1397: if (nodeTypes.contains(s))
1398: s = "Node";
1399: else if ("name".equals(s))
1400: s = "Name";
1401: else if ("scope_kind".equals(s))
1402: s = "ScopeKind";
1403: else if ("scopeT".equals(s))
1404: s = "Scope";
1405:
1406: if ("Named".equals(s)) {
1407: return GNode.create("Type", GNode.create(
1408: "QualifiedIdentifier", "ScopeKind", "Named"), null);
1409: } else if ("Anonymous".equals(s)) {
1410: return GNode.create("Type", GNode.create(
1411: "QualifiedIdentifier", "ScopeKind", "Anonymous"),
1412: null);
1413: } else if ("Temporary".equals(s)) {
1414: return GNode.create("Type", GNode.create(
1415: "QualifiedIdentifier", "ScopeKind", "Temporary"),
1416: null);
1417: } else if ("SimpleName".equals(s)) {
1418: return GNode.create("Type", GNode.create(
1419: "QualifiedIdentifier", "Name", "SimpleName"), null);
1420: } else if ("QualifiedName".equals(s)) {
1421: return GNode.create("Type", GNode.create(
1422: "QualifiedIdentifier", "Name", "QualifiedName"),
1423: null);
1424: }
1425:
1426: else if ("Object".equals(s) || "String".equals(s)
1427: || "BigInteger".equals(s) || "Float".equals(s)
1428: || "Double".equals(s) || "Node".equals(s)
1429: || "GNode".equals(s) || "Boolean".equals(s)
1430: || "Name".equals(s) || "Scope".equals(s)
1431: || "ScopeKind".equals(s) || "Void".equals(s)) {
1432: return GNode.create("Type", GNode.create(
1433: "QualifiedIdentifier", s), null);
1434: } else
1435: return GNode.create("Type", GNode.create(
1436: "QualifiedIdentifier", prefixNoDot, s), null);
1437: }
1438:
1439: }
|