/* * (non-Javadoc) * * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Module) */ public Object visit(Namespace a) { /* set current namespace */ ns = a; /* * visit definitions We set an infinite loop to cope with modifications * introduced by visiting sub expressions. When something is modified - * through lift - we restart the whole process. TODO : change this to defer * registering new bindings at end */ while (true) { try { Iterator it = a.getAllBindings().entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String functionName = (String) entry.getKey(); Expression def = (Expression) entry.getValue(); if (def instanceof Abstraction) ((Abstraction) def).setClassName(ns.getName() + "." + functionName); log.finest("Analyzing lifting for " + functionName); lift = false; entry.setValue((Expression) def.visit(this)); } break; } catch (ConcurrentModificationException cmex) { /* restart the process */ } } return a; }
/* * (non-Javadoc) * * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Alternative) */ public Object visit(Alternative a) { Iterator it = a.getChoices(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); Expression body = (Expression) entry.getValue(); entry.setValue(body.visit(this)); } return a; }
/** * 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; }
/* * Definitions in the let block are lifted to top-level and the corresponding * references in the body are replaced by new definitions. * * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Let) */ public Object visit(Let let) { HashMap subst = new HashMap(); /* substitution map */ Set lambdas = new HashSet(); /* newly created toplevels ? */ Iterator it = let.getBindings().entrySet().iterator(); /* first lift all definitions in this let */ while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String name = (String) entry.getKey(); Expression e = (Expression) entry.getValue(); /* reset lift flag */ lift = false; Expression ndef = (Expression) e.visit(this); ndef.setParent(let); /* lift new definition */ Set captured = new HashSet(); CaptureCollector cc = new CaptureCollector(captured); ndef.visit(cc); String vname; try { vname = lift(ndef, captured); lambdas.add(vname); /* * store new application spine in a map for later substitution */ subst.put(name, applyLifted(vname, captured)); } catch (SymbolException e1) { e1.printStackTrace(); } } /* second, replace old occurences in new definitions */ it = lambdas.iterator(); while (it.hasNext()) { String n = (String) it.next(); Expression e; try { e = (Expression) ns.resolve(n); ns.rebind(n, (Expression) e.visit(new Substitution(subst))); } catch (SymbolException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } /* thirs, replace occurences in body of let and return it */ return let.getBody().visit(new Substitution(subst)); }
/** @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; } }