/*package*/ public NonTerminalType(IConstructor cons) { // TODO refactor this into different factory methods in RascalTypeFactory if (cons.getConstructorType() == RascalValueFactory.Tree_Appl) { // Note that here we go from * to + lists if the list is not empty this.symbol = TreeAdapter.getType((ITree) cons); } else if (cons.getConstructorType() == RascalValueFactory.Tree_Amb) { ISet alts = TreeAdapter.getAlternatives((ITree) cons); if (!alts.isEmpty()) { ITree first = (ITree) alts.iterator().next(); this.symbol = TreeAdapter.getType(first); } else { this.symbol = IRascalValueFactory.getInstance().constructor(RascalValueFactory.Symbol_Empty); } } else if (cons.getConstructorType() == RascalValueFactory.Tree_Cycle) { this.symbol = TreeAdapter.getType((ITree) cons); } else if (cons.getType() == RascalValueFactory.Symbol) { this.symbol = cons; } else if (cons.getType() == RascalValueFactory.Production) { this.symbol = ProductionAdapter.getType(cons); } else { throw new ImplementationError("Invalid concrete syntax type constructor:" + cons); } }
@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 public boolean equals(Object obj) { if (obj == null) return false; if (obj.getClass() == getClass()) { NonTerminalType other = (NonTerminalType) obj; return symbol.equals(other.symbol); } return false; }
public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() == getClass()) { AnnotatedConstructorFacade other = (AnnotatedConstructorFacade) o; return content.equals(other.content) && annotations.equals(other.annotations); } return false; }
public IValue get(String label) { return content.get(label); }
public int arity() { return content.arity(); }
public Type getConstructorType() { return content.getConstructorType(); }
public Type getUninstantiatedConstructorType() { return content.getUninstantiatedConstructorType(); }
@Override public int hashCode() { return symbol.hashCode(); }
public IValue get(int i) throws IndexOutOfBoundsException { return content.get(i); }
public String getName() { return content.getName(); }
public Iterator<IValue> iterator() { return content.iterator(); }
public boolean has(String label) { return content.has(label); }
public boolean declaresAnnotation(TypeStore store, String label) { return content.declaresAnnotation(store, label); }
public Type getChildrenTypes() { return content.getChildrenTypes(); }
public INode replace(int first, int second, int end, IList repl) throws FactTypeUseException, IndexOutOfBoundsException { return content.replace(first, second, end, repl); }
public int getArity() { return symbol.arity(); }
public IConstructor set(int index, IValue newChild) throws FactTypeUseException { IConstructor newContent = content.set(index, newChild); return new AnnotatedConstructorFacade( newContent, annotations); // TODO: introduce wrap() here as well }
public boolean isEqual(IValue other) { return content.isEqual(other); }
public Iterable<IValue> getChildren() { return content.getChildren(); }
@Override public int hashCode() { return content.hashCode(); }
public IValue visitConstructor(IConstructor o) throws IOException { String name = o.getName(); if (name == null) System.err.println("hello"); if (name.equals("loc")) { append('\\'); } if (name.indexOf('-') != -1) { append('\\'); } append(name); boolean indent = checkIndent(o); append('('); tab(); indent(indent); Iterator<IValue> it = o.iterator(); int k = 0; while (it.hasNext()) { it.next().accept(this); if (it.hasNext()) { append(','); indent(indent); } k++; } if (o.mayHaveKeywordParameters()) { IWithKeywordParameters<? extends IConstructor> wkw = o.asWithKeywordParameters(); if (wkw.hasParameters()) { if (k > 0) { append(','); } Iterator<Entry<String, IValue>> iterator = wkw.getParameters().entrySet().iterator(); while (iterator.hasNext()) { Entry<String, IValue> e = iterator.next(); append(e.getKey()); append('='); e.getValue().accept(this); if (iterator.hasNext()) { append(','); } } } } append(')'); untab(); if (o.isAnnotatable() && o.asAnnotatable().hasAnnotations()) { append('['); tab(); indent(); int i = 0; Map<String, IValue> annotations = o.asAnnotatable().getAnnotations(); for (Entry<String, IValue> entry : annotations.entrySet()) { append("@" + entry.getKey() + "="); entry.getValue().accept(this); if (++i < annotations.size()) { append(","); indent(); } } untab(); indent(); append(']'); } try { stream.flush(); } catch (IOException e) { // flushing is just to make sure we get some intermediate output } return o; }
public Type getType() { return content.getType(); }