protected void insertCompilationUnitMessages(boolean insertErrors, IList otherMessages) {
    org.rascalmpl.value.type.Type args = TF.tupleType(TF.stringType(), TF.sourceLocationType());

    IValueList result = new IValueList(values);

    if (otherMessages != null) {
      for (IValue message : otherMessages) {
        result.add(message);
      }
    }

    if (insertErrors) {
      int i;

      IProblem[] problems = compilUnit.getProblems();
      for (i = 0; i < problems.length; i++) {
        int offset = problems[i].getSourceStart();
        int length = problems[i].getSourceEnd() - offset + 1;
        int sl = problems[i].getSourceLineNumber();
        ISourceLocation pos = values.sourceLocation(loc, offset, length, sl, sl, 0, 0);
        org.rascalmpl.value.type.Type constr;
        if (problems[i].isError()) {
          constr =
              typeStore.lookupConstructor(
                  this.typeStore.lookupAbstractDataType("Message"), "error", args);
        } else {
          constr =
              typeStore.lookupConstructor(
                  this.typeStore.lookupAbstractDataType("Message"), "warning", args);
        }
        result.add(values.constructor(constr, values.string(problems[i].getMessage()), pos));
      }
    }
    setAnnotation("messages", result.asList());
  }
Example #2
0
  @Override
  public Type getKeywordArgumentTypes(Environment scope) {
    ArrayList<String> labels = new ArrayList<>();
    ArrayList<Type> types = new ArrayList<>();
    // TODO: I am not sure this is what we want. Double names will end up twice in the tuple type...

    for (AbstractFunction c : primaryCandidates) {
      Type args = c.getKeywordArgumentTypes(scope);

      if (args != null && args.hasFieldNames()) {
        for (String label : args.getFieldNames()) {
          labels.add(label);
          types.add(args.getFieldType(label));
        }
      }
    }

    for (AbstractFunction c : defaultCandidates) {
      Type args = c.getKeywordArgumentTypes(scope);

      if (args != null && args.hasFieldNames()) {
        for (String label : args.getFieldNames()) {
          labels.add(label);
          types.add(args.getFieldType(label));
        }
      }
    }

    return TF.tupleType(
        types.toArray(new Type[types.size()]), labels.toArray(new String[labels.size()]));
  }
  public static IList compose(IList rel1, IList rel2) {

    Type otherTupleType = rel2.getType().getFieldTypes();

    if (rel1.getElementType() == voidType) return rel1;
    if (otherTupleType == voidType) return rel2;

    if (rel1.getElementType().getArity() != 2 || otherTupleType.getArity() != 2)
      throw new IllegalOperationException("compose", rel1.getElementType(), otherTupleType);

    // Relaxed type constraint:
    if (!rel1.getElementType().getFieldType(1).comparable(otherTupleType.getFieldType(0)))
      throw new IllegalOperationException("compose", rel1.getElementType(), otherTupleType);

    Type[] newTupleFieldTypes =
        new Type[] {rel1.getElementType().getFieldType(0), otherTupleType.getFieldType(1)};
    Type tupleType = typeFactory.tupleType(newTupleFieldTypes);

    IListWriter w = new ListWriter(tupleType);

    for (IValue v1 : rel1) {
      ITuple tuple1 = (ITuple) v1;
      for (IValue t2 : rel2) {
        ITuple tuple2 = (ITuple) t2;

        if (tuple1.get(1).isEqual(tuple2.get(0))) {
          w.append(Tuple.newTuple(tuple1.get(0), tuple2.get(1)));
        }
      }
    }
    return w.done();
  }
Example #4
0
  private static Type lub(List<AbstractFunction> candidates) {
    Set<FunctionType> alternatives = new HashSet<FunctionType>();
    Iterator<AbstractFunction> iter = candidates.iterator();
    if (!iter.hasNext()) {
      return TF.voidType();
    }
    FunctionType first = iter.next().getFunctionType();
    Type returnType = first.getReturnType();
    alternatives.add(first);

    AbstractFunction l = null;
    while (iter.hasNext()) {
      l = iter.next();
      if (l.getFunctionType().getReturnType() == returnType) {
        alternatives.add(l.getFunctionType());
      } else {
        return TF.valueType();
      }
    }

    return RascalTypeFactory.getInstance().overloadedFunctionType(alternatives);
  }
Example #5
0
  private static String computeMessage(
      String name, List<AbstractFunction> candidates, Type[] argTypes) {
    StringBuilder b = new StringBuilder();

    b.append("The called signature: " + name);
    b.append('(');
    argumentTypes(TypeFactory.getInstance().tupleType(argTypes), b);
    b.append(')');
    if (candidates.size() == 1) {
      b.append(",\ndoes not match the declared signature:");
    } else {
      b.append(",\ndoes not match any of the declared (overloaded) signature patterns:\n");
    }
    for (AbstractFunction c : candidates) {
      b.append('\t');
      b.append(c.toString());
      b.append('\n');
    }

    return b.toString();
  }
  public ITree filterAmbiguity(ITree ambCluster, Object environment) {
    ISet alts = (ISet) ambCluster.get("alternatives");

    if (alts.size() == 0) {
      return null;
    }

    Environment env = (Environment) environment;

    Result<IValue> var = env.getFrameVariable("amb");

    if (var != null && var instanceof ICallableValue) {
      Type type = RascalTypeFactory.getInstance().nonTerminalType(ambCluster);
      ICallableValue func = (ICallableValue) var;
      try {
        Result<IValue> result = func.call(new Type[] {TF.setType(type)}, new IValue[] {alts}, null);

        if (result.getType().isBottom()) {
          return ambCluster;
        }
        ITree r = (ITree) result.getValue();
        if (TreeAdapter.isAmb(r)) {
          ISet returnedAlts = TreeAdapter.getAlternatives(r);
          if (returnedAlts.size() == 1) {
            return (ITree) returnedAlts.iterator().next();
          } else if (returnedAlts.size() == 0) {
            return null;
          } else {
            return r;
          }
        }

        return (ITree) result.getValue();
      } catch (ArgumentMismatch e) {
        return ambCluster;
      }
    }

    return ambCluster;
  }
  public ISourceLocation resolveSourceLocation(ISourceLocation loc) {
    String scheme = loc.getScheme();
    int pos;

    ICallableValue resolver = sourceResolvers.get(scheme);
    if (resolver == null) {
      for (char sep : new char[] {'+', ':'}) {
        pos = scheme.indexOf(sep);
        if (pos != -1) {
          scheme = scheme.substring(0, pos);
        }
      }

      resolver = sourceResolvers.get(scheme);
      if (resolver == null) {
        return loc;
      }
    }

    Type[] argTypes = new Type[] {TypeFactory.getInstance().sourceLocationType()};
    IValue[] argValues = new IValue[] {loc};

    return (ISourceLocation) resolver.call(argTypes, argValues, null).getValue();
  }
/**
 * This is the way of executing actions for Rascal syntax definitions. Each function that returns a
 * non-terminal type and is named one of the constructor names of one of the alternatives and has
 * the same argument types as the syntax production will be called when a certain production is
 * constructed, e.g:
 *
 * <p>Stat if(Exp e, Stat thenPart, Stat elsePart);
 *
 * <p>Also, on ambiguity clusters functions named 'amb' are called with a set[&T] argument for the
 * alternatives, e.g. Stat amb(set[Stat] alternatives);
 *
 * <p>Also, on entering a production the 'enter' function is called with a reifed type argument for
 * the production type that is entered: void enter(type[Stat.If] prod);
 *
 * <p>Also on exiting a production the 'exit' function is called, similarly: void exit(type[Stat.If]
 * prod);
 *
 * <p>Note that RascalFunctionActionExecutors use functions visible from the call site of the parse
 * function.
 */
public class RascalFunctionActionExecutor implements IActionExecutor<ITree> {
  private static final TypeFactory TF = TypeFactory.getInstance();
  private final IEvaluatorContext ctx;

  public RascalFunctionActionExecutor(IEvaluatorContext ctx) {
    this.ctx = ctx;
  }

  public void completed(Object environment, boolean filtered) {}

  public Object createRootEnvironment() {
    return ctx.getCurrentEnvt();
  }

  public Object enteringListNode(Object production, int index, Object environment) {
    return environment;
  }

  public Object enteringListProduction(Object production, Object env) {
    return env;
  }

  public Object enteringNode(Object production, int index, Object environment) {
    return environment;
  }

  public Object enteringProduction(Object production, Object env) {
    return env;
  }

  public void exitedListProduction(Object production, boolean filtered, Object environment) {}

  public void exitedProduction(Object production, boolean filtered, Object environment) {}

  public ITree filterAmbiguity(ITree ambCluster, Object environment) {
    ISet alts = (ISet) ambCluster.get("alternatives");

    if (alts.size() == 0) {
      return null;
    }

    Environment env = (Environment) environment;

    Result<IValue> var = env.getFrameVariable("amb");

    if (var != null && var instanceof ICallableValue) {
      Type type = RascalTypeFactory.getInstance().nonTerminalType(ambCluster);
      ICallableValue func = (ICallableValue) var;
      try {
        Result<IValue> result = func.call(new Type[] {TF.setType(type)}, new IValue[] {alts}, null);

        if (result.getType().isBottom()) {
          return ambCluster;
        }
        ITree r = (ITree) result.getValue();
        if (TreeAdapter.isAmb(r)) {
          ISet returnedAlts = TreeAdapter.getAlternatives(r);
          if (returnedAlts.size() == 1) {
            return (ITree) returnedAlts.iterator().next();
          } else if (returnedAlts.size() == 0) {
            return null;
          } else {
            return r;
          }
        }

        return (ITree) result.getValue();
      } catch (ArgumentMismatch e) {
        return ambCluster;
      }
    }

    return ambCluster;
  }

  @Override
  public ITree filterCycle(ITree cycle, Object environment) {
    return cycle;
  }

  @Override
  public ITree filterListAmbiguity(ITree ambCluster, Object environment) {
    return filterAmbiguity(ambCluster, environment);
  }

  @Override
  public ITree filterListCycle(ITree cycle, Object environment) {
    return cycle;
  }

  @Override
  public ITree filterListProduction(ITree tree, Object environment) {
    return tree;
  }

  @Override
  public ITree filterProduction(ITree tree, Object environment) {
    String cons = TreeAdapter.getConstructorName(tree);

    if (cons != null) {
      Environment env = (Environment) environment;
      Result<IValue> var = env.getFrameVariable(cons);

      if (var != null && var instanceof ICallableValue) {
        ICallableValue function = (ICallableValue) var;

        try {
          Result<IValue> result = null;
          if (TreeAdapter.isContextFree(tree)) {
            // For context free trees, try it without layout and literal arguments first.
            result = call(function, TreeAdapter.getASTArgs(tree));
          }

          if (result == null) {
            result = call(function, TreeAdapter.getArgs(tree));
          }

          if (result == null) {
            return tree;
          }

          if (result.getType().isBottom()) {
            return tree;
          }

          if (!(result.getType() instanceof NonTerminalType
              && SymbolAdapter.isEqual(
                  ((NonTerminalType) result.getType()).getSymbol(), TreeAdapter.getType(tree)))) {
            // do not call the function if it does not return the right type
            return tree;
          }

          return (ITree) result.getValue();
        } catch (Filtered f) {
          return null;
        }
      }
    }

    return tree;
  }

  private static Result<IValue> call(ICallableValue function, IList args) {
    try {
      int nrOfArgs = args.length();
      Type[] types = new Type[nrOfArgs];
      IValue[] actuals = new IValue[nrOfArgs];

      for (int i = nrOfArgs - 1; i >= 0; --i) {
        IValue arg = args.get(i);
        types[i] = RascalTypeFactory.getInstance().nonTerminalType((IConstructor) arg);
        actuals[i] = arg;
      }

      return function.call(types, actuals, null);
    } catch (MatchFailed e) {
      return null;
    } catch (Failure f) {
      return null;
    }
  }

  public boolean isImpure(Object rhs) {
    return true;
  }
}
 protected IValue constructTypeNode(String constructor, IValue... children) {
   org.rascalmpl.value.type.Type args = TF.tupleType(removeNulls(children));
   org.rascalmpl.value.type.Type constr =
       typeStore.lookupConstructor(DATATYPE_RASCAL_AST_TYPE_NODE_TYPE, constructor, args);
   return values.constructor(constr, removeNulls(children));
 }
public abstract class JavaToRascalConverter extends ASTVisitor {
  protected static final IValueFactory values = ValueFactoryFactory.getValueFactory();
  protected static final TypeFactory TF = TypeFactory.getInstance();

  protected final TypeStore typeStore;

  protected IValue ownValue;
  private static final String DATATYPE_RASCAL_AST_TYPE_NODE = "Type";
  private static final String DATATYPE_RASCAL_AST_MODIFIER_NODE = "Modifier";
  private static final String DATATYPE_RASCAL_AST_DECLARATION_NODE = "Declaration";
  private static final String DATATYPE_RASCAL_AST_EXPRESSION_NODE = "Expression";
  private static final String DATATYPE_RASCAL_AST_STATEMENT_NODE = "Statement";
  private static final String DATATYPE_RASCAL_MESSAGE = "Message";
  private static final String DATATYPE_RASCAL_MESSAGE_ERROR = "error";

  private final org.rascalmpl.value.type.Type DATATYPE_RASCAL_AST_DECLARATION_NODE_TYPE;
  private final org.rascalmpl.value.type.Type DATATYPE_RASCAL_AST_EXPRESSION_NODE_TYPE;
  private final org.rascalmpl.value.type.Type DATATYPE_RASCAL_AST_STATEMENT_NODE_TYPE;
  protected static org.rascalmpl.value.type.Type DATATYPE_RASCAL_AST_TYPE_NODE_TYPE;
  protected static org.rascalmpl.value.type.Type DATATYPE_RASCAL_AST_MODIFIER_NODE_TYPE;
  protected static org.rascalmpl.value.type.Type DATATYPE_RASCAL_MESSAGE_DATA_TYPE;
  protected static org.rascalmpl.value.type.Type DATATYPE_RASCAL_MESSAGE_ERROR_NODE_TYPE;

  protected CompilationUnit compilUnit;
  protected ISourceLocation loc;

  protected final BindingsResolver bindingsResolver;
  protected final boolean collectBindings;

  protected IListWriter messages;
  protected final Map<String, ISourceLocation> locationCache;

  JavaToRascalConverter(
      final TypeStore typeStore, Map<String, ISourceLocation> cache, boolean collectBindings) {
    super(true);
    this.typeStore = typeStore;
    this.bindingsResolver = new BindingsResolver(typeStore, cache, collectBindings);
    this.collectBindings = collectBindings;
    DATATYPE_RASCAL_AST_TYPE_NODE_TYPE =
        this.typeStore.lookupAbstractDataType(DATATYPE_RASCAL_AST_TYPE_NODE);
    DATATYPE_RASCAL_AST_MODIFIER_NODE_TYPE =
        this.typeStore.lookupAbstractDataType(DATATYPE_RASCAL_AST_MODIFIER_NODE);
    this.DATATYPE_RASCAL_AST_DECLARATION_NODE_TYPE =
        typeStore.lookupAbstractDataType(DATATYPE_RASCAL_AST_DECLARATION_NODE);
    this.DATATYPE_RASCAL_AST_EXPRESSION_NODE_TYPE =
        typeStore.lookupAbstractDataType(DATATYPE_RASCAL_AST_EXPRESSION_NODE);
    this.DATATYPE_RASCAL_AST_STATEMENT_NODE_TYPE =
        typeStore.lookupAbstractDataType(DATATYPE_RASCAL_AST_STATEMENT_NODE);
    JavaToRascalConverter.DATATYPE_RASCAL_MESSAGE_DATA_TYPE =
        typeStore.lookupAbstractDataType(DATATYPE_RASCAL_MESSAGE);
    JavaToRascalConverter.DATATYPE_RASCAL_MESSAGE_ERROR_NODE_TYPE =
        typeStore
            .lookupConstructor(DATATYPE_RASCAL_MESSAGE_DATA_TYPE, DATATYPE_RASCAL_MESSAGE_ERROR)
            .iterator()
            .next();
    this.locationCache = cache;

    messages = values.listWriter();
  }

  protected ISourceLocation resolveBinding(String packageComponent) {
    ISourceLocation packageBinding =
        new BindingsResolver(typeStore, locationCache, this.collectBindings) {
          public ISourceLocation resolveBinding(String packageC) {
            try {
              if (collectBindings) {
                if (locationCache.containsKey(packageC)) {
                  return locationCache.get(packageC);
                }
                return values.sourceLocation("java+package", null, packageC);
              }
              return values.sourceLocation("unknown", null, null);
            } catch (URISyntaxException e) {
              throw new RuntimeException("Should not happen", e);
            }
          }
        }.resolveBinding(packageComponent);
    locationCache.put(packageComponent, packageBinding);
    return packageBinding;
  }

  protected ISourceLocation resolveBinding(CompilationUnit node) {
    ISourceLocation compilationUnit =
        new BindingsResolver(typeStore, locationCache, true) {
          public ISourceLocation resolveBinding(CompilationUnit node) {
            return makeBinding("java+compilationUnit", null, loc.getPath());
          }
        }.resolveBinding(node);

    return compilationUnit;
  }

  protected ISourceLocation resolveBinding(IBinding binding) {
    ISourceLocation resolvedBinding = bindingsResolver.resolveBinding(binding);
    if (binding != null) locationCache.put(binding.getKey(), resolvedBinding);
    return resolvedBinding;
  }

  protected ISourceLocation resolveDeclaringClass(IBinding binding) {
    ISourceLocation resolvedBinding;
    if (binding instanceof ITypeBinding) {
      resolvedBinding =
          bindingsResolver.resolveBinding(((ITypeBinding) binding).getDeclaringClass());
    } else if (binding instanceof IMethodBinding) {
      resolvedBinding =
          bindingsResolver.resolveBinding(((IMethodBinding) binding).getDeclaringClass());
    } else if (binding instanceof IVariableBinding) {
      resolvedBinding =
          bindingsResolver.resolveBinding(((IVariableBinding) binding).getDeclaringClass());
    } else {
      binding = null;
      resolvedBinding = bindingsResolver.resolveBinding(binding);
    }
    return resolvedBinding;
  }

  protected ISourceLocation resolveBinding(ASTNode node) {
    if (node instanceof CompilationUnit) {
      return resolveBinding((CompilationUnit) node);
    }
    return bindingsResolver.resolveBinding(node);
  }

  protected ISourceLocation getSourceLocation(ASTNode node) {
    try {
      int nodeLength = compilUnit.getExtendedLength(node);

      if (nodeLength > 0) {
        int start = compilUnit.getExtendedStartPosition(node);
        int end = start + nodeLength - 1;

        if (end < start && ((node.getFlags() & 9) > 0)) {
          insert(
              messages,
              values.constructor(
                  DATATYPE_RASCAL_MESSAGE_ERROR_NODE_TYPE,
                  values.string("Recovered/Malformed node, guessing the length"),
                  values.sourceLocation(loc, 0, 0)));

          nodeLength = node.toString().length();
          end = start + nodeLength - 1;
        }

        return values.sourceLocation(
            loc,
            start,
            nodeLength,
            compilUnit.getLineNumber(start),
            compilUnit.getLineNumber(end),
            // TODO: only adding 1 at the end seems to work, need to test.
            compilUnit.getColumnNumber(start),
            compilUnit.getColumnNumber(end) + 1);
      }
    } catch (IllegalArgumentException e) {
      insert(
          messages,
          values.constructor(
              DATATYPE_RASCAL_MESSAGE_ERROR_NODE_TYPE,
              values.string("Most probably missing dependency"),
              values.sourceLocation(loc, 0, 0)));
    }
    return values.sourceLocation(loc, 0, 0, 0, 0, 0, 0);
  }

  protected IValue[] removeNulls(IValue... withNulls) {
    List<IValue> withOutNulls = new ArrayList<IValue>();
    for (IValue child : withNulls) {
      if (!(child == null)) {
        withOutNulls.add(child);
      }
    }
    return withOutNulls.toArray(new IValue[withOutNulls.size()]);
  }

  protected IValueList parseModifiers(int modifiers) {
    IValueList extendedModifierList = new IValueList(values);

    for (String constructor : java.lang.reflect.Modifier.toString(modifiers).split(" ")) {
      Set<org.rascalmpl.value.type.Type> exConstr =
          typeStore.lookupConstructor(DATATYPE_RASCAL_AST_MODIFIER_NODE_TYPE, constructor);
      for (org.rascalmpl.value.type.Type con : exConstr) {
        extendedModifierList.add(values.constructor(con));
      }
    }

    return extendedModifierList;
  }

  @SuppressWarnings({"rawtypes"})
  protected IValueList parseExtendedModifiers(List ext) {
    IValueList extendedModifierList = new IValueList(values);

    for (Iterator it = ext.iterator(); it.hasNext(); ) {
      ASTNode p = (ASTNode) it.next();
      IValue val = visitChild(p);
      if (p instanceof Annotation) {
        val = constructModifierNode("annotation", val);
      }
      extendedModifierList.add(val);
    }
    return extendedModifierList;
  }

  @SuppressWarnings("deprecation")
  protected IValueList parseExtendedModifiers(BodyDeclaration node) {
    if (node.getAST().apiLevel() == AST.JLS2) {
      return parseModifiers(node.getModifiers());
    } else {
      return parseExtendedModifiers(node.modifiers());
    }
  }

  protected IValue visitChild(ASTNode node) {
    node.accept(this);
    return this.getValue();
  }

  public IValue getValue() {
    return this.ownValue;
  }

  protected IConstructor constructModifierNode(String constructor, IValue... children) {
    org.rascalmpl.value.type.Type args = TF.tupleType(removeNulls(children));
    org.rascalmpl.value.type.Type constr =
        typeStore.lookupConstructor(DATATYPE_RASCAL_AST_MODIFIER_NODE_TYPE, constructor, args);
    return values.constructor(constr, removeNulls(children));
  }

  protected void setAnnotation(String annoName, IValue annoValue) {
    if (this.ownValue == null) {
      return;
    }
    if (annoValue != null && ownValue.getType().declaresAnnotation(this.typeStore, annoName)) {
      ownValue = ((IConstructor) ownValue).asAnnotatable().setAnnotation(annoName, annoValue);
    }
  }

  protected void setAnnotation(String annoName, IValueList annoList) {
    IList annos = (IList) annoList.asList();
    if (this.ownValue == null) {
      return;
    }
    if (annoList != null
        && this.ownValue.getType().declaresAnnotation(this.typeStore, annoName)
        && !annos.isEmpty()) {
      this.ownValue = ((IConstructor) this.ownValue).asAnnotatable().setAnnotation(annoName, annos);
    }
  }

  protected IValue constructDeclarationNode(String constructor, IValue... children) {
    org.rascalmpl.value.type.Type args = TF.tupleType(removeNulls(children));
    org.rascalmpl.value.type.Type constr =
        typeStore.lookupConstructor(DATATYPE_RASCAL_AST_DECLARATION_NODE_TYPE, constructor, args);
    return values.constructor(constr, removeNulls(children));
  }

  protected IValue constructExpressionNode(String constructor, IValue... children) {
    org.rascalmpl.value.type.Type args = TF.tupleType(removeNulls(children));
    org.rascalmpl.value.type.Type constr =
        typeStore.lookupConstructor(DATATYPE_RASCAL_AST_EXPRESSION_NODE_TYPE, constructor, args);
    return values.constructor(constr, removeNulls(children));
  }

  protected IValue constructStatementNode(String constructor, IValue... children) {
    org.rascalmpl.value.type.Type args = TF.tupleType(removeNulls(children));
    org.rascalmpl.value.type.Type constr =
        typeStore.lookupConstructor(DATATYPE_RASCAL_AST_STATEMENT_NODE_TYPE, constructor, args);
    return values.constructor(constr, removeNulls(children));
  }

  protected IValue constructTypeNode(String constructor, IValue... children) {
    org.rascalmpl.value.type.Type args = TF.tupleType(removeNulls(children));
    org.rascalmpl.value.type.Type constr =
        typeStore.lookupConstructor(DATATYPE_RASCAL_AST_TYPE_NODE_TYPE, constructor, args);
    return values.constructor(constr, removeNulls(children));
  }

  protected void insertCompilationUnitMessages(boolean insertErrors, IList otherMessages) {
    org.rascalmpl.value.type.Type args = TF.tupleType(TF.stringType(), TF.sourceLocationType());

    IValueList result = new IValueList(values);

    if (otherMessages != null) {
      for (IValue message : otherMessages) {
        result.add(message);
      }
    }

    if (insertErrors) {
      int i;

      IProblem[] problems = compilUnit.getProblems();
      for (i = 0; i < problems.length; i++) {
        int offset = problems[i].getSourceStart();
        int length = problems[i].getSourceEnd() - offset + 1;
        int sl = problems[i].getSourceLineNumber();
        ISourceLocation pos = values.sourceLocation(loc, offset, length, sl, sl, 0, 0);
        org.rascalmpl.value.type.Type constr;
        if (problems[i].isError()) {
          constr =
              typeStore.lookupConstructor(
                  this.typeStore.lookupAbstractDataType("Message"), "error", args);
        } else {
          constr =
              typeStore.lookupConstructor(
                  this.typeStore.lookupAbstractDataType("Message"), "warning", args);
        }
        result.add(values.constructor(constr, values.string(problems[i].getMessage()), pos));
      }
    }
    setAnnotation("messages", result.asList());
  }

  public void insert(IListWriter listW, IValue message) {
    if (message.getType().isConstructor()
        && message.getType().getAbstractDataType().getName().equals("Message")) {
      listW.insert(message);
    }
  }

  public void convert(CompilationUnit root, ASTNode node, ISourceLocation loc) {
    this.compilUnit = root;
    this.loc = loc;
    node.accept(this);
  }
}
Example #11
0
public class OverloadedFunction extends Result<IValue> implements IExternalValue, ICallableValue {
  private static final TypeFactory TF = TypeFactory.getInstance();

  private final List<AbstractFunction>
      primaryCandidates; // it should be a list to allow proper shadowing
  private final List<AbstractFunction>
      defaultCandidates; // it should be a list to allow proper shadowing
  private final String name;
  private final boolean isStatic;

  public OverloadedFunction(
      String name,
      Type type,
      List<AbstractFunction> candidates,
      List<AbstractFunction> defaults,
      IEvaluatorContext ctx) {
    super(type, null, ctx);

    if (candidates.size() + defaults.size() <= 0) {
      throw new ImplementationError("at least need one function");
    }
    this.name = name;

    this.primaryCandidates = new ArrayList<AbstractFunction>(candidates.size());
    this.defaultCandidates = new ArrayList<AbstractFunction>(candidates.size());

    addAll(primaryCandidates, candidates, true);
    addAll(defaultCandidates, defaults, false);

    isStatic = checkStatic(primaryCandidates) && checkStatic(defaultCandidates);
  }

  @Override
  public IConstructor encodeAsConstructor() {
    TypeReifier tr = new TypeReifier(getValueFactory());
    return tr.overloadedToProduction(this, ctx);
  }

  public List<AbstractFunction> getPrimaryCandidates() {
    return primaryCandidates;
  }

  public List<AbstractFunction> getDefaultCandidates() {
    return defaultCandidates;
  }

  @Override
  public Type getKeywordArgumentTypes(Environment scope) {
    ArrayList<String> labels = new ArrayList<>();
    ArrayList<Type> types = new ArrayList<>();
    // TODO: I am not sure this is what we want. Double names will end up twice in the tuple type...

    for (AbstractFunction c : primaryCandidates) {
      Type args = c.getKeywordArgumentTypes(scope);

      if (args != null && args.hasFieldNames()) {
        for (String label : args.getFieldNames()) {
          labels.add(label);
          types.add(args.getFieldType(label));
        }
      }
    }

    for (AbstractFunction c : defaultCandidates) {
      Type args = c.getKeywordArgumentTypes(scope);

      if (args != null && args.hasFieldNames()) {
        for (String label : args.getFieldNames()) {
          labels.add(label);
          types.add(args.getFieldType(label));
        }
      }
    }

    return TF.tupleType(
        types.toArray(new Type[types.size()]), labels.toArray(new String[labels.size()]));
  }

  public OverloadedFunction(AbstractFunction function) {
    super(function.getType(), null, function.getEval());

    this.name = function.getName();

    this.primaryCandidates = new ArrayList<AbstractFunction>(1);
    this.defaultCandidates = new ArrayList<AbstractFunction>(1);

    if (function.isDefault()) {
      defaultCandidates.add(function);
    } else {
      primaryCandidates.add(function);
    }

    this.isStatic = function.isStatic();
  }

  public OverloadedFunction(String name, List<AbstractFunction> funcs) {
    super(lub(funcs), null, funcs.iterator().next().getEval());

    this.name = name;

    this.primaryCandidates = new ArrayList<AbstractFunction>(1);
    this.defaultCandidates = new ArrayList<AbstractFunction>(1);

    addAll(primaryCandidates, funcs, true);
    addAll(defaultCandidates, funcs, false);

    this.isStatic = checkStatic(funcs);
  }

  private OverloadedFunction(
      String name,
      Type type,
      List<AbstractFunction> candidates,
      List<AbstractFunction> defaults,
      boolean isStatic,
      IEvaluatorContext ctx) {
    super(type, null, ctx);
    this.name = name;
    this.primaryCandidates = candidates;
    this.defaultCandidates = defaults;
    this.isStatic = isStatic;
  }

  @Override
  public OverloadedFunction cloneInto(Environment env) {
    List<AbstractFunction> newCandidates = new ArrayList<>();
    for (AbstractFunction f : primaryCandidates) {
      newCandidates.add((AbstractFunction) f.cloneInto(env));
    }

    List<AbstractFunction> newDefaultCandidates = new ArrayList<>();
    for (AbstractFunction f : defaultCandidates) {
      newDefaultCandidates.add((AbstractFunction) f.cloneInto(env));
    }
    OverloadedFunction of =
        new OverloadedFunction(name, getType(), newCandidates, newDefaultCandidates, isStatic, ctx);
    of.setPublic(isPublic());
    return of;
  }

  /**
   * This function groups occurrences of pattern dispatched functions as one "PatternFunction" that
   * has a hash table to look up based on outermost function symbol. A group is a bunch of functions
   * that have an ADT as a first parameter type and a call or tree pattern with a fixed name as the
   * first parameter pattern, or it is a singleton other case. The addAll function retains the order
   * of the functions from the candidates list, in order to preserve shadowing rules!
   */
  private void addAll(
      List<AbstractFunction> container, List<AbstractFunction> candidates, boolean nonDefault) {
    @SuppressWarnings("unchecked")
    Map<String, List<AbstractFunction>>[] constructors = new Map[10];
    @SuppressWarnings("unchecked")
    Map<IConstructor, List<AbstractFunction>>[] productions = new Map[10];
    List<AbstractFunction> other = new LinkedList<AbstractFunction>();

    for (AbstractFunction func : candidates) {
      if (nonDefault && func.isDefault()) {
        continue;
      }
      if (!nonDefault && !func.isDefault()) {
        continue;
      }

      String label = null;
      IConstructor prod = null;

      if (func.isPatternDispatched()) {
        // this one is already hashed, but we might find more to add to that map in the next round
        Map<String, List<AbstractFunction>> funcMap =
            ((AbstractPatternDispatchedFunction) func).getMap();
        int pos = func.getIndexedArgumentPosition();

        for (String key : funcMap.keySet()) {
          addFuncsToMap(pos, constructors, funcMap.get(key), key);
        }
      } else if (func.isConcretePatternDispatched()) {
        // this one is already hashed, but we might find more to add to that map in the next round
        Map<IConstructor, List<AbstractFunction>> funcMap =
            ((ConcretePatternDispatchedFunction) func).getMap();
        int pos = func.getIndexedArgumentPosition();

        for (IConstructor key : funcMap.keySet()) {
          addProdsToMap(pos, productions, funcMap.get(key), key);
        }
      } else {
        // a new function definition, that may be hashable
        int pos = func.getIndexedArgumentPosition();
        label = func.getIndexedLabel();
        prod = func.getIndexedProduction();

        if (label != null) {
          // we found another one to hash
          addFuncToMap(pos, constructors, func, label);
        } else if (prod != null) {
          addProdToMap(pos, productions, func, prod);
        } else {
          other.add(func);
        }
      }
    }

    for (int i = 0; i < constructors.length; i++) {
      if (constructors[i] != null && !constructors[i].isEmpty()) {
        container.add(
            new AbstractPatternDispatchedFunction(
                ctx.getEvaluator(), i, name, type, constructors[i]));
      }
    }

    for (int i = 0; i < productions.length; i++) {
      if (productions[i] != null && !productions[i].isEmpty()) {
        container.add(
            new ConcretePatternDispatchedFunction(
                ctx.getEvaluator(), i, name, type, productions[i]));
      }
    }

    container.addAll(other);
  }

  private void addFuncToMap(
      int pos, Map<String, List<AbstractFunction>>[] map, AbstractFunction func, String label) {
    if (map[pos] == null) {
      map[pos] = new HashMap<>();
    }

    List<AbstractFunction> l = map[pos].get(label);
    if (l == null) {
      l = new LinkedList<AbstractFunction>();
      map[pos].put(label, l);
    }
    l.add(func);
  }

  private void addProdToMap(
      int pos,
      Map<IConstructor, List<AbstractFunction>>[] map,
      AbstractFunction func,
      IConstructor label) {
    if (map[pos] == null) {
      map[pos] = new HashMap<>();
    }

    List<AbstractFunction> l = map[pos].get(label);
    if (l == null) {
      l = new LinkedList<AbstractFunction>();
      map[pos].put(label, l);
    }
    l.add(func);
  }

  private void addFuncsToMap(
      int pos,
      Map<String, List<AbstractFunction>>[] map,
      List<AbstractFunction> funcs,
      String label) {
    if (map[pos] == null) {
      map[pos] = new HashMap<>();
    }

    List<AbstractFunction> l = map[pos].get(label);
    if (l == null) {
      l = new LinkedList<AbstractFunction>();
      map[pos].put(label, l);
    }
    l.addAll(funcs);
  }

  private void addProdsToMap(
      int pos,
      Map<IConstructor, List<AbstractFunction>>[] map,
      List<AbstractFunction> funcs,
      IConstructor label) {
    if (map[pos] == null) {
      map[pos] = new HashMap<>();
    }

    List<AbstractFunction> l = map[pos].get(label);
    if (l == null) {
      l = new LinkedList<AbstractFunction>();
      map[pos].put(label, l);
    }
    l.addAll(funcs);
  }

  @Override
  public int getArity() {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean hasVarArgs() {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean hasKeywordArguments() {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean isStatic() {
    return isStatic;
  }

  private static boolean checkStatic(List<AbstractFunction> l) {
    for (ICallableValue f : l) {
      if (!f.isStatic()) {
        return false;
      }
    }
    return true;
  }

  @Override
  public IValue getValue() {
    return this;
  }

  private static Type lub(List<AbstractFunction> candidates) {
    Set<FunctionType> alternatives = new HashSet<FunctionType>();
    Iterator<AbstractFunction> iter = candidates.iterator();
    if (!iter.hasNext()) {
      return TF.voidType();
    }
    FunctionType first = iter.next().getFunctionType();
    Type returnType = first.getReturnType();
    alternatives.add(first);

    AbstractFunction l = null;
    while (iter.hasNext()) {
      l = iter.next();
      if (l.getFunctionType().getReturnType() == returnType) {
        alternatives.add(l.getFunctionType());
      } else {
        return TF.valueType();
      }
    }

    return RascalTypeFactory.getInstance().overloadedFunctionType(alternatives);
  }

  @Override
  public Result<IValue> call(
      IRascalMonitor monitor,
      Type[] argTypes,
      IValue[] argValues,
      Map<String, IValue> keyArgValues) {
    IRascalMonitor old = ctx.getEvaluator().setMonitor(monitor);
    try {
      return call(argTypes, argValues, keyArgValues);
    } finally {
      ctx.getEvaluator().setMonitor(old);
    }
  }

  @Override
  public Result<IValue> call(
      Type[] argTypes, IValue[] argValues, Map<String, IValue> keyArgValues) {
    Result<IValue> result =
        callWith(
            primaryCandidates, argTypes, argValues, keyArgValues, defaultCandidates.size() <= 0);

    if (result == null && defaultCandidates.size() > 0) {
      result = callWith(defaultCandidates, argTypes, argValues, keyArgValues, true);
    }

    if (result == null) {
      throw new MatchFailed();
    }

    return result;
  }

  private static Result<IValue> callWith(
      List<AbstractFunction> candidates,
      Type[] argTypes,
      IValue[] argValues,
      Map<String, IValue> keyArgValues,
      boolean mustSucceed) {
    AbstractFunction failed = null;
    Failure failure = null;

    for (AbstractFunction candidate : candidates) {
      if ((candidate.hasVarArgs() && argValues.length >= candidate.getArity() - 1)
          || candidate.getArity() == argValues.length
          || candidate.hasKeywordArguments()) {
        try {
          return candidate.call(argTypes, argValues, keyArgValues);
        } catch (MatchFailed m) {
          // could happen if pattern dispatched
        } catch (Failure e) {
          failed = candidate;
          failure = e;
          // could happen if function body throws fail
        }
      }
    }

    if (failed != null && mustSucceed) {
      throw new UnguardedFail(failed.ast, failure);
    }

    return null;
  }

  public OverloadedFunction join(OverloadedFunction other) {
    if (other == null) {
      return this;
    }
    List<AbstractFunction> joined =
        new ArrayList<AbstractFunction>(other.primaryCandidates.size() + primaryCandidates.size());
    List<AbstractFunction> defJoined =
        new ArrayList<AbstractFunction>(other.defaultCandidates.size() + defaultCandidates.size());

    joined.addAll(primaryCandidates);
    defJoined.addAll(defaultCandidates);

    for (AbstractFunction cand : other.primaryCandidates) {
      if (!joined.contains(cand)) {
        joined.add(cand);
      }
    }

    for (AbstractFunction cand : other.defaultCandidates) {
      if (!defJoined.contains(cand)) {
        defJoined.add(cand);
      }
    }

    return new OverloadedFunction(
        "(" + name + "+" + other.getName() + ")",
        lub(joined).lub(lub(defJoined)),
        joined,
        defJoined,
        ctx);
  }

  public OverloadedFunction add(AbstractFunction candidate) {
    List<AbstractFunction> joined = new ArrayList<AbstractFunction>(primaryCandidates.size() + 1);
    joined.addAll(primaryCandidates);
    List<AbstractFunction> defJoined =
        new ArrayList<AbstractFunction>(defaultCandidates.size() + 1);
    defJoined.addAll(defaultCandidates);

    if (candidate.isDefault() && !defJoined.contains(candidate)) {
      defJoined.add(candidate);
    } else if (!candidate.isDefault() && !joined.contains(candidate)) {
      joined.add(candidate);
    }

    return new OverloadedFunction(
        "(" + name + "+" + candidate.getName() + ")",
        lub(joined).lub(lub(defJoined)),
        joined,
        defJoined,
        ctx);
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof OverloadedFunction) {
      OverloadedFunction other = (OverloadedFunction) obj;
      return primaryCandidates.containsAll(other.primaryCandidates)
          && other.primaryCandidates.containsAll(primaryCandidates)
          && defaultCandidates.containsAll(other.defaultCandidates)
          && other.defaultCandidates.containsAll(defaultCandidates);
    }
    return false;
  }

  @Override
  public String toString() {
    StringBuilder b = new StringBuilder();
    for (AbstractFunction l : primaryCandidates) {
      b.append(l.toString());
      b.append(' ');
    }
    for (AbstractFunction l : defaultCandidates) {
      b.append(l.toString());
      b.append(' ');
    }

    return b.toString();
  }

  @Override
  public <T, E extends Throwable> T accept(IValueVisitor<T, E> v) throws E {
    return v.visitExternal(this);
  }

  @Override
  public boolean isEqual(IValue other) {
    if (other instanceof OverloadedFunction) {
      return primaryCandidates.equals(((OverloadedFunction) other).primaryCandidates);
    }
    return false;
  }

  @Override
  public <V extends IValue> Result<IBool> equals(Result<V> that) {
    return that.equalToOverloadedFunction(this);
  }

  @Override
  public Result<IBool> equalToOverloadedFunction(OverloadedFunction that) {
    return ResultFactory.bool(
        primaryCandidates.equals(that.primaryCandidates)
            && defaultCandidates.equals(that.defaultCandidates),
        ctx);
  }

  @Override
  public <U extends IValue, V extends IValue> Result<U> add(Result<V> that) {
    return that.addFunctionNonDeterministic(this);
  }

  @Override
  public OverloadedFunction addFunctionNonDeterministic(AbstractFunction that) {
    return this.add(that);
  }

  @Override
  public OverloadedFunction addFunctionNonDeterministic(OverloadedFunction that) {
    return this.join(that);
  }

  @Override
  public ComposedFunctionResult addFunctionNonDeterministic(ComposedFunctionResult that) {
    return new ComposedFunctionResult.NonDeterministic(that, this, ctx);
  }

  @Override
  public <U extends IValue, V extends IValue> Result<U> compose(Result<V> right) {
    return right.composeFunction(this);
  }

  @Override
  public ComposedFunctionResult composeFunction(AbstractFunction that) {
    return new ComposedFunctionResult(that, this, ctx);
  }

  @Override
  public ComposedFunctionResult composeFunction(OverloadedFunction that) {
    return new ComposedFunctionResult(that, this, ctx);
  }

  @Override
  public ComposedFunctionResult composeFunction(ComposedFunctionResult that) {
    return new ComposedFunctionResult(that, this, ctx);
  }

  public List<AbstractFunction> getFunctions() {
    List<AbstractFunction> result = new LinkedList<AbstractFunction>();
    for (AbstractFunction f : primaryCandidates) {
      result.add(f);
    }

    for (AbstractFunction f : defaultCandidates) {
      result.add(f);
    }

    return result;
  }

  public List<AbstractFunction> getTests() {
    List<AbstractFunction> result = new LinkedList<AbstractFunction>();
    for (AbstractFunction f : getFunctions()) {
      if (f.isTest()) {
        result.add(f);
      }
    }
    return result;
  }

  public String getName() {
    return name;
  }

  @Override
  public Evaluator getEval() {
    return (Evaluator) ctx;
  }

  @Override
  public boolean isAnnotatable() {
    return false;
  }

  @Override
  public IAnnotatable<? extends IValue> asAnnotatable() {
    throw new IllegalOperationException("Cannot be viewed as annotatable.", getType());
  }

  @Override
  public boolean mayHaveKeywordParameters() {
    return false;
  }

  @Override
  public IWithKeywordParameters<? extends IValue> asWithKeywordParameters() {
    throw new IllegalOperationException("Cannot be viewed as with keyword parameters", getType());
  }
}
public class RelationalFunctionsOnList {

  protected static final TypeFactory typeFactory = TypeFactory.getInstance();
  protected static final Type voidType = typeFactory.voidType();

  public static int arity(IList rel) {
    return rel.getElementType().getArity();
  }

  public static IList carrier(IList rel1) {
    Type newType = rel1.getType().carrier();
    IListWriter w = List.createListWriter(newType.getElementType());
    HashSet<IValue> cache = new HashSet<>();

    for (IValue v : rel1) {
      ITuple t = (ITuple) v;
      for (IValue e : t) {
        if (!cache.contains(e)) {
          cache.add(e);
          w.append(e);
        }
      }
    }

    return w.done();
  }

  public static IList domain(IList rel1) {
    Type lrelType = rel1.getType();
    IListWriter w = List.createListWriter(lrelType.getFieldType(0));
    HashSet<IValue> cache = new HashSet<>();

    for (IValue elem : rel1) {
      ITuple tuple = (ITuple) elem;
      IValue e = tuple.get(0);
      if (!cache.contains(e)) {
        cache.add(e);
        w.append(e);
      }
    }
    return w.done();
  }

  public static IList range(IList rel1) {
    Type lrelType = rel1.getType();
    int last = lrelType.getArity() - 1;
    IListWriter w = List.createListWriter(lrelType.getFieldType(last));
    HashSet<IValue> cache = new HashSet<>();

    for (IValue elem : rel1) {
      ITuple tuple = (ITuple) elem;
      IValue e = tuple.get(last);
      if (!cache.contains(e)) {
        cache.add(e);
        w.append(e);
      }
    }

    return w.done();
  }

  public static IList compose(IList rel1, IList rel2) {

    Type otherTupleType = rel2.getType().getFieldTypes();

    if (rel1.getElementType() == voidType) return rel1;
    if (otherTupleType == voidType) return rel2;

    if (rel1.getElementType().getArity() != 2 || otherTupleType.getArity() != 2)
      throw new IllegalOperationException("compose", rel1.getElementType(), otherTupleType);

    // Relaxed type constraint:
    if (!rel1.getElementType().getFieldType(1).comparable(otherTupleType.getFieldType(0)))
      throw new IllegalOperationException("compose", rel1.getElementType(), otherTupleType);

    Type[] newTupleFieldTypes =
        new Type[] {rel1.getElementType().getFieldType(0), otherTupleType.getFieldType(1)};
    Type tupleType = typeFactory.tupleType(newTupleFieldTypes);

    IListWriter w = new ListWriter(tupleType);

    for (IValue v1 : rel1) {
      ITuple tuple1 = (ITuple) v1;
      for (IValue t2 : rel2) {
        ITuple tuple2 = (ITuple) t2;

        if (tuple1.get(1).isEqual(tuple2.get(0))) {
          w.append(Tuple.newTuple(tuple1.get(0), tuple2.get(1)));
        }
      }
    }
    return w.done();
  }

  public static IList closure(IList rel1) {
    Type resultType = rel1.getType().closure(); // will throw exception if not binary and reflexive
    IList tmp = rel1;

    int prevCount = 0;

    ShareableValuesHashSet addedTuples = new ShareableValuesHashSet();
    while (prevCount != tmp.length()) {
      prevCount = tmp.length();
      IList tcomp = compose(tmp, tmp);
      IListWriter w = List.createListWriter(resultType.getElementType());
      for (IValue t1 : tcomp) {
        if (!tmp.contains(t1)) {
          if (!addedTuples.contains(t1)) {
            addedTuples.add(t1);
            w.append(t1);
          }
        }
      }
      tmp = tmp.concat(w.done());
      addedTuples.clear();
    }
    return tmp;
  }

  public static IList closureStar(IList rel1) {
    Type resultType = rel1.getType().closure();
    // an exception will have been thrown if the type is not acceptable

    IListWriter reflex = List.createListWriter(resultType.getElementType());

    for (IValue e : carrier(rel1)) {
      reflex.insert(Tuple.newTuple(new IValue[] {e, e}));
    }

    return closure(rel1).concat(reflex.done());
  }

  public static IList project(IList rel1, int... fields) {
    IListWriter w = ValueFactory.getInstance().listWriter();

    for (IValue v : rel1) {
      w.append(((ITuple) v).select(fields));
    }

    return w.done();
  }

  public static IList projectByFieldNames(IList rel1, String... fields) {
    int[] indexes = new int[fields.length];
    int i = 0;

    if (rel1.getType().getFieldTypes().hasFieldNames()) {
      for (String field : fields) {
        indexes[i++] = rel1.getType().getFieldTypes().getFieldIndex(field);
      }

      return project(rel1, indexes);
    }

    throw new IllegalOperationException("select with field names", rel1.getType());
  }
}