/** @see jaskell.compiler.JaskellVisitor#visit(QualifiedVariable) */ public Object visit(QualifiedVariable a) { Module mod = null; Iterator it = a.getPath().iterator(); while (it.hasNext()) { String mname = (String) it.next(); if (mod != null) mod = (Module) mod.lookup(mname); else mod = (Module) Module.getToplevels().get(mname); } /* module found */ if (mod != null) { Expression def = mod.lookup(a.getName()); if (def == null) throw new CompilerException("Unknown variable " + a.getName()); Type t = def.getType(); if (t == null) t = (Type) def.visit(this); /* as it is the case for variable, we assume * that a defined symbol may be overloaded (only for primitive types) * so we return a type variable and defers choice of * symbol to a later stage */ a.setType(t); return t; } throw new CompilerException("Unable to find module needed for variable " + a.getName()); }
/** @see jaskell.compiler.JaskellVisitor#visit(ConstructorPattern) */ public Object visit(ConstructorPattern a) { String cname = a.getConstructor().getName(); /* retrieve parameter types of constructor */ ConstructorDefinition ctor = (ConstructorDefinition) a.getConstructor().lookup(cname); if (ctor == null) throw new TypeError("Undefined constructor pattern " + a); /* type of data constructed by constructor */ TypeInstantiator ti = new TypeInstantiator(ctor.getDataType()); Type rtype = ti.instance(); Map map = ti.getMap(); TypeSubstitution ts = new TypeSubstitution(map); Iterator ittypes = ctor.getParameters().iterator(); /* retrieve type of patterns */ Iterator it = a.getSubPatterns(); while (it.hasNext()) { try { Pattern p = (Pattern) it.next(); Type actual = TypeFactory.freshBinding(); Type formal = ts.substitute((Type) ittypes.next()); /* unify both types */ p.setType(tu.unify(formal, actual, typeVariablesMap)); } catch (NoSuchElementException nex) { throw new TypeError("Wrong number of arguments to pattern " + a); } } a.setType(rtype); return a.getType(); }
/** * Returns null or throws a TypeError if type cannot be inferred for any definition found. * Verifies that main symbol in Main module is typed as <code>IO ()</code>. * * @see jaskell.compiler.JaskellVisitor#visit(Module) */ public Object visit(Namespace a) { // visit definitions Iterator it = a.getAllBindings().entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String name = (String) entry.getKey(); Expression def = (Expression) entry.getValue(); Type type = (Type) def.visit(this); def.setType(type); log.finer("TypeChecker => END Visiting " + name); } log.finer("Substitution map = " + typeVariablesMap); return null; }
/** @see jaskell.compiler.JaskellVisitor#visit(Let) */ public Object visit(Let a) { Type ret = a.getType(); if (ret != null) return ret; // visit definitions Iterator it = a.getBindings().entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String name = (String) entry.getKey(); Expression def = (Expression) entry.getValue(); log.finer("Visiting " + name); def.setType((Type) def.visit(this)); } // visit body ret = (Type) a.getBody().visit(this); a.setType(ret); // return type of body return ret; }
/** @see jaskell.compiler.JaskellVisitor#visit(Alternative) */ public Object visit(Alternative a) { try { Type tex = (Type) a.getExpression().visit(this); log.finer("In alternative, type of expression " + a.getExpression() + " is " + tex); /* set type of bound variable */ LocalBinding lb = a.getBinding(); if (lb != null) lb.setType(tex); /* visit type of alternatives */ Iterator it = a.getChoices(); Type ptype = tex; Type btype = null; while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); /* checkt type of pattern */ Type pt = (Type) ((Pattern) entry.getKey()).visit(this); if (ptype == null) ptype = pt; else ptype = tu.unify(pt, ptype, typeVariablesMap); log.finer("In alternative, unifying pattern type " + pt + " to " + ptype); Expression expr = (Expression) entry.getValue(); /* check type of body */ Type bt = (Type) expr.visit(this); // /* apply substitution with type variables from pattern */ // TypeSubstitution ts = new TypeSubstitution(typeVariablesMap); // expr.visit(ts); if (btype == null) btype = bt; else btype = tu.unify(bt, btype, typeVariablesMap); log.finer("In alternative, unifying body type " + bt + " to " + btype); } /* visit default choice */ Type deft = (Type) a.getWildcard().visit(this); a.setType(btype); return btype; } catch (TypeError te) { if (te.getLineCol() == null) te.setLineCol(a.getTag("source")); throw te; } }
/** @see jaskell.compiler.JaskellVisitor#visit(Abstraction) */ public Object visit(Abstraction a) { try { Type t = a.getType(); if (t != null) return subst.substitute(t); log.finest("Visiting abstraction : " + a); Expression body = a.getBody(); /* duplicate bindings map to assign types to variables */ pushContext(a.getBindings()); /* create fresh type variables as type for each bound * variable */ Iterator it = namesMap.values().iterator(); LinkedList tl = new LinkedList(); while (it.hasNext()) { LocalBinding name = (LocalBinding) it.next(); Type vt = TypeFactory.freshBinding(); name.setType(vt); tl.add(vt); } Type tv = TypeFactory.freshBinding(); /* create type with all variables for function */ Type ft = Types.fun(tl, tv); log.finer("In abstraction, setting type to " + ft); a.setType(ft); /* analyze body */ Type bt = (Type) body.visit(this); /* unify return type of function with type of body */ Type ret = tu.unify(PrimitiveType.getReturnType(ft), bt, typeVariablesMap); TyvarSubstitution tys = new TyvarSubstitution(typeVariablesMap); tys.visit(a); log.finer("Done abstraction, setting type from " + ft + " to " + a.getType()); popContext(); return a.getType(); } catch (TypeError te) { if (te.getLineCol() == null) te.setLineCol(a.getTag("source")); throw te; } }
/** @see jaskell.compiler.JaskellVisitor#visit(Application) */ public Object visit(Application a) { try { /* get type of function */ Expression fun = a.getFunction(); /* get type deduced from arguments */ LinkedList l = new LinkedList(); Iterator it = a.getArgs().iterator(); while (it.hasNext()) { Expression e = (Expression) it.next(); l.add((Type) e.visit(this)); } Type vt = TypeFactory.freshBinding(); Type ft = Types.fun(l, vt); log.finer("TypeChecker => In application " + a + ", type is " + ft); /* apply substitution on both types */ ft = subst.substitute(ft); /* try to unify function type and constructed types */ Type t = (Type) fun.visit(this); log.finer("In application, function " + fun + " :: " + t); t = subst.substitute(t); log.finer("In application, trying to unify function type " + t + " with body " + ft); /* * TODO : problem with unification of constrained types */ TypeApplication uni = (TypeApplication) tu.unify(t, ft, typeVariablesMap); /* sets type of functional expression - this allows * polymorphic functions to receive several types * in the same code */ // fun.setType(uni); /* apply arguments type to compute return type */ log.finer("Done unify application :" + uni); it = PrimitiveType.functionIterator(uni); Iterator it2 = l.iterator(); TypeApplication ut = uni; while (it2.hasNext()) { /* type of argument */ Type at = (Type) it2.next(); ut = (TypeApplication) it.next(); /* try unification */ tu.unify(((TypeApplication) ut.getDomain()).getRange(), at, new HashMap(typeVariablesMap)); } ft = subst.substitute(ft); fun.setType(ft); log.finer("Setting type of functional element [" + fun + "] to :" + ft); a.setType(ut.getRange()); return ut.getRange(); } catch (TypeError te) { if (te.getLineCol() == null) te.setLineCol(a.getTag("source")); throw te; } }