Ejemplo n.º 1
0
  /*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 <U extends IValue> Result<U> fieldAccess(String name, TypeStore store) {
    IConstructor tree = getValue();

    if (TreeAdapter.isAppl(tree)) {
      int found = -1;
      IConstructor foundType = null;
      IConstructor prod = TreeAdapter.getProduction(tree);

      if (!ProductionAdapter.isRegular(prod)) {
        IList syms = ProductionAdapter.getSymbols(prod);

        // TODO: find deeper into optionals, checking the actual arguments for presence/absence of
        // optional trees.
        for (int i = 0; i < syms.length(); i++) {
          IConstructor sym = (IConstructor) syms.get(i);

          while (SymbolAdapter.isConditional(sym)) {
            sym = SymbolAdapter.getSymbol(sym);
          }
          if (SymbolAdapter.isLabel(sym)) {
            if (SymbolAdapter.getLabel(sym).equals(name)) {
              found = i;
              foundType = SymbolAdapter.delabel(sym);
            }
          }
        }

        if (found != -1) {
          Type nont = RascalTypeFactory.getInstance().nonTerminalType(foundType);
          IValue child = TreeAdapter.getArgs(tree).get(found);
          return makeResult(nont, child, ctx);
        }
      }
    }

    if (tree.getConstructorType().hasField(name)) {
      return makeResult(tree.getConstructorType().getFieldType(name), tree.get(name), ctx);
    }

    throw RuntimeExceptionFactory.noSuchField(name, ctx.getCurrentAST(), ctx.getStackTrace());
  }
  @Override
  public <U extends IValue, V extends IValue> Result<U> fieldUpdate(
      String name, Result<V> repl, TypeStore store) {
    IConstructor tree = getValue();

    if (TreeAdapter.isAppl(tree)) {
      int found = -1;
      IConstructor foundType = null;
      IConstructor prod = TreeAdapter.getProduction(tree);
      IList syms = ProductionAdapter.getSymbols(prod);

      // TODO: find deeper into optionals, alternatives and sequences checking the actual arguments
      // for presence/absence of optional trees.
      for (int i = 0; i < syms.length(); i++) {
        IConstructor sym = (IConstructor) syms.get(i);
        if (SymbolAdapter.isLabel(sym)) {
          if (SymbolAdapter.getLabel(sym).equals(name)) {
            found = i;
            foundType = SymbolAdapter.delabel(sym);
            break;
          }
        }
      }

      if (found != -1) {
        Type nont = RascalTypeFactory.getInstance().nonTerminalType(foundType);
        if (repl.getType().isSubtypeOf(nont)) {
          IList args = TreeAdapter.getArgs(tree).put(found, repl.getValue());
          return makeResult(getType(), tree.set("args", args), ctx);
        }
        throw new UnexpectedType(nont, repl.getType(), ctx.getCurrentAST());
      }

      if (Factory.Tree_Appl.hasField(name)) {
        Type fieldType = Factory.Tree_Appl.getFieldType(name);
        if (repl.getType().isSubtypeOf(fieldType)) {
          throw new UnsupportedOperation(
              "changing " + name + " in concrete tree", ctx.getCurrentAST());
        }
        throw new UnexpectedType(fieldType, repl.getType(), ctx.getCurrentAST());
      }

      throw RuntimeExceptionFactory.noSuchField(name, ctx.getCurrentAST(), ctx.getStackTrace());
    }
    throw new UnsupportedOperation("field update", ctx.getCurrentAST());
  }
  @Override
  public Result<IBool> has(Name name) {
    if (TreeAdapter.isAppl(getValue())) {
      IConstructor prod = TreeAdapter.getProduction(getValue());
      IList syms = ProductionAdapter.getSymbols(prod);
      String tmp = Names.name(name);

      // TODO: find deeper into optionals, checking the actual arguments for presence/absence of
      // optional trees.
      for (IValue sym : syms) {
        if (SymbolAdapter.isLabel((IConstructor) sym)) {
          if (SymbolAdapter.getLabel((IConstructor) sym).equals(tmp)) {
            return ResultFactory.bool(true, ctx);
          }
        }
      }
    }
    return ResultFactory.bool(false, ctx);
  }