@Override public boolean isSubtypeOfNonTerminal(RascalType other) { if (other == this) { return true; } IConstructor otherSym = ((NonTerminalType) other).symbol; if ((SymbolAdapter.isIterPlus(symbol) && (SymbolAdapter.isIterStar(otherSym) || SymbolAdapter.isIterPlus(otherSym))) || (SymbolAdapter.isIterStar(symbol) && SymbolAdapter.isIterStar(otherSym))) { RascalType nt1 = (RascalType) RTF.nonTerminalType(SymbolAdapter.getSymbol(symbol)); RascalType nt2 = (RascalType) RTF.nonTerminalType(SymbolAdapter.getSymbol(otherSym)); return nt1.isSubtypeOfNonTerminal(nt2); } else if ((SymbolAdapter.isIterPlusSeps(symbol) && (SymbolAdapter.isIterStarSeps(otherSym) || SymbolAdapter.isIterPlusSeps(otherSym))) || (SymbolAdapter.isIterStarSeps(symbol) && SymbolAdapter.isIterStarSeps(otherSym))) { RascalType nt1 = (RascalType) RTF.nonTerminalType(SymbolAdapter.getSymbol(symbol)); RascalType nt2 = (RascalType) RTF.nonTerminalType(SymbolAdapter.getSymbol(otherSym)); if (nt1.isSubtypeOfNonTerminal(nt2)) { IList seps1 = SymbolAdapter.getSeparators(symbol); IList seps2 = SymbolAdapter.getSeparators(otherSym); // this works around broken regular prods in the RVM which have the wrong or missing layout // symbols: int sep1index = seps1.length() == 3 ? 1 : 0; int sep2index = seps2.length() == 3 ? 1 : 0; nt1 = (RascalType) RTF.nonTerminalType((IConstructor) seps1.get(sep1index)); nt2 = (RascalType) RTF.nonTerminalType((IConstructor) seps2.get(sep2index)); return nt1.isSubtypeOfNonTerminal(nt2); } return false; } else if (SymbolAdapter.isOpt(symbol) && SymbolAdapter.isOpt(otherSym)) { RascalType nt1 = (RascalType) RTF.nonTerminalType(SymbolAdapter.getSymbol(symbol)); RascalType nt2 = (RascalType) RTF.nonTerminalType(SymbolAdapter.getSymbol(otherSym)); return nt1.isSubtypeOfNonTerminal(nt2); } // else if (SymbolAdapter.isSequence(symbol) && SymbolAdapter.isSeq(otherSym)) { // TODO pairwise issubtype // } if (SymbolAdapter.isParameter(otherSym)) { RascalType bound = (RascalType) RTF.nonTerminalType((IConstructor) otherSym.get("bound")); return isSubtypeOf(bound); } // TODO co-variance for the other structured symbols (sequence, opt, list) return SymbolAdapter.isEqual(otherSym, symbol); }
@Override protected Type glbWithNonTerminal(RascalType other) { IConstructor otherSym = ((NonTerminalType) other).symbol; if (SymbolAdapter.isIterPlus(symbol) && SymbolAdapter.isIterStar(otherSym)) { return this; } else if (SymbolAdapter.isIterPlus(otherSym) && SymbolAdapter.isIterStar(symbol)) { return other; } else if (SymbolAdapter.isIterPlusSeps(symbol) && SymbolAdapter.isIterStarSeps(otherSym)) { return this; } else if (SymbolAdapter.isIterPlusSeps(otherSym) && SymbolAdapter.isIterStarSeps(symbol)) { return other; } return SymbolAdapter.isEqual(otherSym, symbol) ? other : TF.voidType(); }
@Override protected Type lubWithNonTerminal(RascalType other) { IConstructor otherSym = ((NonTerminalType) other).symbol; // * eats + if (SymbolAdapter.isIterPlus(symbol) && SymbolAdapter.isIterStar(otherSym)) { return other; } else if (SymbolAdapter.isIterPlus(otherSym) && SymbolAdapter.isIterStar(symbol)) { return this; } else if (SymbolAdapter.isIterPlusSeps(symbol) && SymbolAdapter.isIterStarSeps(otherSym)) { return other; } else if (SymbolAdapter.isIterPlusSeps(otherSym) && SymbolAdapter.isIterStarSeps(symbol)) { return this; } return SymbolAdapter.isEqual(otherSym, symbol) ? this : RascalValueFactory.Tree; }