Package com.odiago.flumebase.lang

Examples of com.odiago.flumebase.lang.TypeCheckException


    }

    // Get a handle to the symbol defining the function.
    Symbol fnSymbol = symTab.resolve(mFunctionName);
    if (null == fnSymbol) {
      throw new TypeCheckException("No such function: " + mFunctionName);
    }

    fnSymbol = fnSymbol.resolveAliases();

    if (!(fnSymbol instanceof FnSymbol)) {
      // This symbol isn't a function call?
      throw new TypeCheckException("Symbol " + mFunctionName + " is not a function");
    }

    mFnSymbol = (FnSymbol) fnSymbol; // memoize this for later.

    // Get a list of argument types from the function symbol. These may include
    // universal types we need to concretize.
    List<Type> abstractArgTypes = new ArrayList<Type>(mFnSymbol.getArgumentTypes());

    // Argument types for varargs, after the fixed args.
    List<Type> abstractVarArgTypes = mFnSymbol.getVarArgTypes();

    // Check that arity matches.
    int argsRemaining = mArgExprs.size();
    argsRemaining -= abstractArgTypes.size();
    if (argsRemaining < 0 || (argsRemaining > 0 && abstractVarArgTypes.size() == 0)) {
      // Too few actual args, or too many args (and this is not a varargs fn).
      throw new TypeCheckException("Function " + mFunctionName + " requires "
          + abstractArgTypes.size() + " arguments, but received " + mArgExprs.size());
    }

    if (argsRemaining > 0 && abstractVarArgTypes.size() > 0) {
      // varargs may need to come in pairs, etc. Check that we have a correct multiple
      // of the number of varargs available.
      int argRemainder = argsRemaining % abstractVarArgTypes.size();
      if (0 != argRemainder) {
        throw new TypeCheckException("Function " + mFunctionName + " requires varargs "
            + "in sets of " + abstractVarArgTypes.size() + ", but this call has "
            + argRemainder + " too few.");
      }
    }

    // For each actual vararg, add its type to the abstractArgTypes list.
    if (abstractVarArgTypes.size() > 0) {
      int numVarArgSets = (mArgExprs.size() - abstractArgTypes.size())
          / abstractVarArgTypes.size();
      for (int i = 0; i < numVarArgSets; i++) {
        abstractArgTypes.addAll(abstractVarArgTypes);
      }
    }

    assert mArgExprs.size() == abstractArgTypes.size();

    // Check that each expression type can promote to the argument type.
    for (int i = 0; i < mArgExprs.size(); i++) {
      Type exprType = mArgExprs.get(i).getType(symTab);
      mExprTypes.add(exprType);
      if (!exprType.promotesTo(abstractArgTypes.get(i))) {
        throw new TypeCheckException("Invalid argument to function " + mFunctionName
            + ": argument " + i + " has type " + exprType + "; requires type "
            + abstractArgTypes.get(i));
      }
    }

    mArgTypes = new Type[mArgExprs.size()];

    // Now identify all the UniversalType instances in here, and the
    // actual constraints on each of these.
    Map<UniversalType, List<Type>> unifications = new HashMap<UniversalType, List<Type>>();
    for (int i = 0; i < abstractArgTypes.size(); i++) {
      Type abstractType = abstractArgTypes.get(i);
      Type actualType = mExprTypes.get(i);
      UniversalConstraintExtractor constraintExtractor = new UniversalConstraintExtractor();
      if (constraintExtractor.extractConstraint(abstractType, actualType)) {
        // Found a UniversalType. Make sure it's mapped to a list of actual constraints.
        UniversalType univType = constraintExtractor.getUniversalType();
        List<Type> actualConstraints = unifications.get(univType);
        if (null == actualConstraints) {
          actualConstraints = new ArrayList<Type>();
          unifications.put(univType, actualConstraints);
        }

        // Add the actual constraint of the expression being applied as this argument.
        actualConstraints.add(constraintExtractor.getConstraintType());
      }
    }

    // Perform unifications on all the UniversalType expressions.
    Map<Type, Type> unificationOut = new HashMap<Type, Type>();
    for (Map.Entry<UniversalType, List<Type>> unification : unifications.entrySet()) {
      UniversalType univType = unification.getKey();
      List<Type> actualConstraints = unification.getValue();
      Type out = univType.getRuntimeType(actualConstraints);
      unificationOut.put(univType, out);
    }
   
    // Finally, generate a list of concrete argument types for coercion purposes.
    for (int i = 0; i < abstractArgTypes.size(); i++ ) {
      Type abstractType = abstractArgTypes.get(i);
      mArgTypes[i] = abstractType.replaceUniversal(unificationOut);
      assert mArgTypes[i] != null;
    }

    // Also set mReturnType; if this referenced a UniversalType, use the resolved
    // version. Otherwise, use the version from the function directly.
    Type fnRetType = mFnSymbol.getReturnType();
    try {
      mReturnType = fnRetType.replaceUniversal(unificationOut);
    } catch (TypeCheckException tce) {
      // We can only resolve against our arguments, not our caller's type.
      if (fnRetType instanceof ListType) {
        // If the unresolved typevar is an argument to a list type, we can
        // return this -- it's going to be an empty list, so we can return
        // LIST<NULL>
        // TODO(aaron): This allows to_list() to produce an empty list, but
        // putting this check here feels a bit like a hack to me.
        mReturnType = new ListType(Type.getNullable(Type.TypeName.NULL));
      } else {
        // This fails for being too abstract.
        throw new TypeCheckException("Output type of function " + mFunctionName
            + " is an unresolved UniversalType: " + fnRetType, tce);
      }
    }

    assert null != mReturnType;
View Full Code Here

TOP

Related Classes of com.odiago.flumebase.lang.TypeCheckException

Copyright © 2018 www.massapicom. 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.