Package org.rascalmpl.interpreter.types

Source Code of org.rascalmpl.interpreter.types.NonTerminalType

/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:

*   * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
*   * Tijs van der Storm - Tijs.van.der.Storm@cwi.nl
*   * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.interpreter.types;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.type.Type;
import org.rascalmpl.interpreter.asserts.ImplementationError;
import org.rascalmpl.interpreter.utils.Symbols;
import org.rascalmpl.values.uptr.Factory;
import org.rascalmpl.values.uptr.ProductionAdapter;
import org.rascalmpl.values.uptr.SymbolAdapter;
import org.rascalmpl.values.uptr.TreeAdapter;

/**
* This is an "extension" of the PDB's type system with a special kind of type
* that implements the connection between Rascal's non-terminals and Rascal types.
*/
public class NonTerminalType extends RascalType {
  private IConstructor symbol;

  /*package*/ NonTerminalType(IConstructor cons) {
    if (cons.getType() == Factory.Symbol) {
      this.symbol = cons;
    }
    else if (cons.getType() == Factory.Production) {
      this.symbol = ProductionAdapter.getType(cons);
    }
    else if (cons.getConstructorType() == Factory.Tree_Appl) {
      this.symbol = TreeAdapter.getType(cons);
    }
    else if (cons.getConstructorType() == Factory.Tree_Amb) {
      IConstructor first = (IConstructor) TreeAdapter.getAlternatives(cons).iterator().next();
      this.symbol = TreeAdapter.getType(first);
    }
    else {
      throw new ImplementationError("Invalid concrete syntax type constructor:" + cons);
    }
  }
 
    /*package*/ NonTerminalType(org.rascalmpl.ast.Type type, boolean lex, String layout) {
    this(Symbols.typeToSymbol(type, lex, layout));
  }
 
  public IConstructor getSymbol() {
    return symbol;
  }
 
  public boolean isConcreteListType() {
    return SymbolAdapter.isAnyList(getSymbol());
  }
 
  public boolean isOptionalType() {
    return SymbolAdapter.isOpt(getSymbol());
  }
 
  @Override
  public Type getAbstractDataType() {
    return Factory.Tree;
  }
 
  @Override
  public boolean hasField(String fieldName) {
    // safe over-approximation
    return true;
  }
 
  @Override
  public String getName() {
    return Factory.Tree.getName();
  }
 
  @Override
  public Type getTypeParameters() {
    return Factory.Tree.getTypeParameters();
  }
 
  @Override
  public <T, E extends Throwable> T accept(IRascalTypeVisitor<T,E> visitor) throws E {
    return visitor.visitNonTerminal(this);
  }
 
  @Override
  protected boolean isSubtypeOfAbstractData(Type type) {
    return type.equivalent(Factory.Tree);
  }
 
  @Override
  protected boolean isSubtypeOfNode(Type type) {
    return true;
  }
 
  @Override
  protected Type lubWithNode(Type type) {
    return type;
  }
 
  @Override
  protected Type lubWithAbstractData(Type type) {
    return type.equivalent(Factory.Tree) ? type : TF.nodeType();
  }
 
  @Override
  protected Type lubWithConstructor(Type type) {
    return type.getAbstractDataType().equivalent(Factory.Tree) ? Factory.Tree : TF.nodeType();
  }
 
  @Override
  protected Type glbWithNode(Type type) {
    return this;
  }
 
  @Override
  protected Type glbWithAbstractData(Type type) {
    return type.equivalent(Factory.Tree) ? this : TF.voidType();
  }
 
  @Override
  protected Type glbWithConstructor(Type type) {
    return TF.voidType();
  }

 
  @Override
  protected boolean isSupertypeOf(Type type) {
    if (type instanceof NonTerminalType) {
      return ((NonTerminalType) type).isSubtypeOfNonTerminal(this);
    }
    if(type.isAbstractData() && getName() == type.getName()) {
      return type.getTypeParameters().isSubtypeOf(this.getTypeParameters());
    }
    return super.isSupertypeOf(type);
  }
 
  @Override
  protected boolean isSupertypeOf(RascalType type) {
    return type.isSubtypeOfNonTerminal(this);
  }
 
  @Override
  protected Type lub(RascalType type) {
    return type.lubWithNonTerminal(this);
  }
 
  @Override
  protected Type glb(RascalType type) {
    return type.glbWithNonTerminal(this);
  }
 
  @Override
  public boolean isSubtypeOfNonTerminal(RascalType other) {
    IConstructor otherSym = ((NonTerminalType)other).symbol;
    if (SymbolAdapter.isIterPlus(symbol) && SymbolAdapter.isIterStar(otherSym)) {
      return SymbolAdapter.isEqual(SymbolAdapter.getSymbol(symbol), SymbolAdapter.getSymbol(otherSym));
    }

    if (SymbolAdapter.isIterPlusSeps(symbol) && SymbolAdapter.isIterStarSeps(otherSym)) {
      return SymbolAdapter.isEqual(SymbolAdapter.getSymbol(symbol), SymbolAdapter.getSymbol(otherSym))
          && SymbolAdapter.isEqual(SymbolAdapter.getSeparators(symbol), SymbolAdapter.getSeparators(otherSym));
    }
   
    return SymbolAdapter.isEqual(otherSym, symbol);
  }
 
  @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 : Factory.Tree;
  }

  @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
  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;
  }
 
  @Override
  public int hashCode() {
    return symbol.hashCode();
  }
 
  @Override
  public String toString() {
    return SymbolAdapter.toString(symbol, false);
  }
}
TOP

Related Classes of org.rascalmpl.interpreter.types.NonTerminalType

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.