/** * This method produces a new Abstraction which is the result of adding captured variables as new * arguments and bind it in current ns. It returns the name of the bound funciton. * * @param a * @param captured * @return a String object denoting the name given to this function * @throws SymbolException */ private String lift(Abstraction a, Set captured) throws SymbolException { Abstraction abs = a; if (!captured.isEmpty()) { /* recreate abstraction adding captured variables */ abs = new Abstraction(); /* bind captured variables */ Iterator it = captured.iterator(); while (it.hasNext()) { LocalBinding lb = (LocalBinding) it.next(); LocalBinding nlb = new LocalBinding(lb.getName()); abs.bind(nlb); } /* rebind old variables */ it = a.getBindings().values().iterator(); while (it.hasNext()) { LocalBinding lb = (LocalBinding) it.next(); LocalBinding nlb = new LocalBinding(lb.getName()); abs.bind(nlb); } /* restore body */ abs.setBody(a.getBody()); } /* * bind new abstraction in ns if a is an anonymous abstraction - no class * name - then it is renamed lambdaXXX and bound in namespace. Else, it is * given a new name and a reference to this new name is stored in substMap. */ String newname = "lambda" + counter++; ns.bind(newname, abs); abs.setClassName(ns.getName() + "." + newname); return newname; }
/** * This method produces an Expression from an arbitrary Abstraction object which is applied to a * list of Variables referencing captured bindings. * * @param a an Abstraction object to partially apply * @param captured * @return */ private Expression applyLifted(String s, Set captured) { if (captured.isEmpty()) return new Variable(s); Application app = new Application(); app.setFunction(new Variable(s)); /* bind captured variables */ Iterator it = captured.iterator(); while (it.hasNext()) { LocalBinding lb = (LocalBinding) it.next(); app.addArgument(new Variable(lb.getName())); } return app; }
/** * Returns an Abstraction object resulting from lifting the given expression with captured * variable set. if <code>f * x y</code> is an expression with <code>y</code> a captured variable, then it is transformed * into <code>lambdaXXX * = \ y -> f x y</code> which can later be used to replace the original expression with <code> * lambdaXXX y</code>. * * @param e * @param captured * @return a String object * @throws SymbolException */ private String lift(Expression e, Set captured) throws SymbolException { if (e instanceof Abstraction) return lift((Abstraction) e, captured); Abstraction abs = new Abstraction(); /* bind captured variables */ Iterator it = captured.iterator(); while (it.hasNext()) { LocalBinding lb = (LocalBinding) it.next(); LocalBinding nlb = new LocalBinding(lb.getName()); abs.bind(nlb); } /* restore body */ abs.setBody(e); String newname = "lambda" + counter++; ns.bind(newname, abs); return newname; }
/** @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(LocalBinding) */ public Object visit(LocalBinding a) { return a.getType(); }