Example #1
0
  public SubstMap unify(final Loc loc, final Type other, final TypeEnv env) {
    if (env.checkVisited(this, other)) return SubstMap.EMPTY;

    if (other instanceof TypeVar) return SubstMap.bindVar(loc, (TypeVar) other, this);

    // if our application expression can be evaluated, unify against that.
    if (isAbsApply()) return eval().unify(loc, other, env);

    final Type otherEval = other.deref().eval();

    if (otherEval instanceof TypeApp) {
      final TypeApp otherApp = (TypeApp) otherEval;
      final SubstMap baseSubst = base.unify(loc, otherApp.base, env);

      if (baseSubst != null) {
        final SubstMap argSubst =
            arg.subst(baseSubst).unify(loc, otherApp.arg.subst(baseSubst), env);

        if (argSubst != null) return baseSubst.compose(loc, argSubst);
      }
    } else if (kind.equals(otherEval.getKind())) {
      // other is not an application expression, but kinds match.
      // other type classes do opportunistic matching of type apps
      // implementations of unify. This approach is really ad-hoc,
      // needs to be rationalized.

      return otherEval.unify(loc, this, env);
    }

    return null;
  }
Example #2
0
  public Type eval() {
    if (reduced != null) return reduced;

    if (inEval) return this;

    final Type baseEval = base.deref().eval();
    final Type argEval = arg.deref().eval();

    if (!(baseEval instanceof TypeCons))
      // error has been raised
      return this;

    final TypeCons cons = (TypeCons) baseEval;

    final Type body = cons.getBody();
    if (body == null) return reduced(baseEval, argEval);

    // check base abs param kind against arg kind
    if (!checkKindAgreement(cons, argEval))
      // error has been raised
      return this;

    // evaluate by building param->arg subst map and
    // applying it to body term

    final SubstMap argMap = new SubstMap();

    final Collection<TypeParam> params = body.getParams().values();

    if (params.size() == 1) {
      final TypeParam param = params.iterator().next();
      assert param.getTypeScope() == body : "nope";

      argMap.put(param, argEval);
    } else {
      if (!(argEval instanceof TypeTuple)) assert false;

      final Iterator<Type> argList = ((TypeTuple) argEval).getMembers().iterator();

      for (final TypeParam param : params) {
        assert param.getTypeScope() == body : "nope";
        argMap.put(param, argList.next());
      }
    }

    final Type bodySubst = new TypeApplier(body, argMap).apply();

    // evaluate body with args substituted for params
    inEval = true;
    reduced = bodySubst.eval();
    inEval = false;

    if (Session.isDebug())
      Session.debug(
          body.getLoc(), "eval {0}({1}) => {2}", body.dump(), argMap.dump(), reduced.dump());

    return reduced;
  }