diff options
Diffstat (limited to 'sources/scalac/transformer/LambdaLiftPhase.java')
-rw-r--r-- | sources/scalac/transformer/LambdaLiftPhase.java | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/sources/scalac/transformer/LambdaLiftPhase.java b/sources/scalac/transformer/LambdaLiftPhase.java new file mode 100644 index 0000000000..31d9eea2a8 --- /dev/null +++ b/sources/scalac/transformer/LambdaLiftPhase.java @@ -0,0 +1,135 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +** ** +\* */ + +// $Id$ + +package scalac.transformer; + +import scalac.*; +import scalac.util.*; +import scalac.parser.*; +import scalac.symtab.*; +import scalac.checkers.*; + +public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers { + + private Global global; + int nextPhase; + + public void initialize(Global global, int id) { + super.initialize(global, id); + this.global = global; + this.nextPhase = id + 1; + } + + public String name () { + return "lambdalift"; + } + + public String description () { + return "lambda lifter"; + } + + public String taskDescription() { + return "lambda lifting"; + } + + public Phase createPhase(Global global) { + return new LambdaLift(global, this); + } + + public Type transformInfo(Symbol sym, Type tp) { + Type tp1 = transform(tp, sym.owner()); + if ((sym.flags & Modifiers.CAPTURED) != 0) return refType(tp1); + else return tp1; + } + + /** Add proxies as type arguments for propagated type parameters. + */ + Type transform(Type tp, Symbol owner) { + return transformTypeMap.setOwner(owner).apply(tp); + } + + private class TransformTypeMap extends Type.Map { + Symbol owner; + Type.Map setOwner(Symbol owner) { this.owner = owner; return this; } + + public Type apply(Type tp) { + switch (tp) { + case TypeRef(Type pre, Symbol sym, Type[] targs): + switch (pre) { + case ThisType(_): + if (sym.constructor().isUpdated(nextPhase)) { + System.out.println("updated: " + sym.constructor());//debug + Symbol[] tparams = + sym.constructor().infoAt(nextPhase).typeParams(); + int i = tparams.length; + while (i > 0 && (tparams[i-1].flags & SYNTHETIC) != 0) + i--; + if (i < tparams.length) { + Type[] targs1 = new Type[tparams.length]; + System.arraycopy(map(targs), 0, targs1, 0, targs.length); + while (i < tparams.length) { + targs1[i] = proxy(tparams[i], owner).type(); + } + return Type.TypeRef(pre, sym, targs1); + } + } + } + break; + } + return map(tp); + } + + /** All symbols are mapped to themselves. + */ + public Scope map(Scope s) { return s; } + public Symbol map(Symbol s) { return s; } + public Symbol[] map(Symbol[] ss) { return ss; } + } + + private TransformTypeMap transformTypeMap = new TransformTypeMap(); + + /** Return closest enclosing (type)parameter that has same name as `fv', + * or `fv' itself if this is the closest definition. + */ + Symbol proxy(Symbol fv, Symbol owner) { + if (global.debug) + global.log("proxy " + fv + " in " + LambdaLift.asFunction(owner)); + Symbol o = owner; + while (o.kind != NONE) { + Symbol fowner = LambdaLift.asFunction(o); + if (fv.owner() == fowner) return fv; + Type ft = (fowner.isUpdated(nextPhase)) ? fowner.typeAt(nextPhase) + : fowner.type(); + Symbol[] ownerparams = fv.isType() ? ft.typeParams() + : ft.firstParams(); + for (int i = 0; i < ownerparams.length; i++) { + if (ownerparams[i].name == fv.name) + return ownerparams[i]; + } + o = o.owner(); + } + throw new ApplicationError("proxy " + fv + " in " + owner); + } + + /** The type scala.Ref[tp] + */ + Type refType(Type tp) { + Symbol refClass = global.definitions.getClass(Names.scala_Ref); + assert refClass.kind == Kinds.CLASS; + return Type.TypeRef(global.definitions.SCALA_TYPE, refClass, new Type[]{tp}); + } + + public Checker[] postCheckers(Global global) { + return new Checker[] { + new CheckSymbols(global), + new CheckTypes(global), + new CheckOwners(global) + }; + } +} |