summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2012-04-26 17:08:05 +0200
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-04-26 17:28:48 +0200
commit17165269e22f8e4b60483d1277eb841131c3686d (patch)
tree39cb4c0f4825cbdebec33d26a2fa46db54f96724 /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parentefd1293df967a10211ca877130f97955be94dc30 (diff)
downloadscala-17165269e22f8e4b60483d1277eb841131c3686d.tar.gz
scala-17165269e22f8e4b60483d1277eb841131c3686d.tar.bz2
scala-17165269e22f8e4b60483d1277eb841131c3686d.zip
clean up typedMatchAnonFun
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala90
1 files changed, 51 insertions, 39 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e4c3dcfa55..6234c05258 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2249,43 +2249,35 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser
}
}
- def typedMatchAnonFun(tree: Tree, cases: List[CaseDef], mode: Int, pt0: Type, selOverride: Option[(List[ValDef], Tree)] = None) = {
- val pt = deskolemizeGADTSkolems(pt0)
- val targs = pt.normalize.typeArgs
- val arity = if (isFunctionType(pt)) targs.length - 1 else 1 // TODO pt should always be a (Partial)Function, right?
- val ptRes = if (targs.isEmpty) WildcardType else targs.last // may not be fully defined
+ // synthesize and type check a (Partial)Function implementation based on a match specified by `cases`
+ // Match(EmptyTree, cases) ==> new <Partial>Function { def apply<OrElse>(params) = `translateMatch('`(param1,...,paramN)` match { cases }')` }
+ // for fresh params, the selector of the match we'll translated simply gathers those in a tuple
+ class MatchFunTyper(tree: Tree, cases: List[CaseDef], mode: Int, pt0: Type) {
+ private val pt = deskolemizeGADTSkolems(pt0)
+ private val targs = pt.normalize.typeArgs
+ private val arity = if (isFunctionType(pt)) targs.length - 1 else 1 // TODO pt should always be a (Partial)Function, right?
+ private val ptRes = if (targs.isEmpty) WildcardType else targs.last // may not be fully defined
- val isPartial = pt.typeSymbol == PartialFunctionClass
- val anonClass = context.owner.newAnonymousFunctionClass(tree.pos)
- val funThis = This(anonClass)
- val serialVersionUIDAnnotation = AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List())
+ private val isPartial = pt.typeSymbol == PartialFunctionClass
+ private val anonClass = context.owner.newAnonymousFunctionClass(tree.pos)
+ private val funThis = This(anonClass)
- anonClass addAnnotation serialVersionUIDAnnotation
+ anonClass addAnnotation AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List())
def deriveFormals =
- selOverride match {
- case None if targs.isEmpty => Nil
- case None => targs.init // is there anything we can do if targs.isEmpty??
- case Some((vparams, _)) =>
- vparams map {p => if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe}
- }
+ if (targs.isEmpty) Nil
+ else targs.init
- def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) = {
- selOverride match {
- case None if targs.isEmpty => MissingParameterTypeAnonMatchError(tree, pt); (Nil, EmptyTree)
- case None =>
- val ps = methodSym newSyntheticValueParams formals // is there anything we can do if targs.isEmpty??
- val ids = ps map (p => Ident(p.name))
- val sel = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
- (ps, sel)
- case Some((vparams, sel)) =>
- val newParamSyms = (vparams, formals).zipped map {(p, tp) =>
- methodSym.newValueParameter(p.name, p.pos.focus, SYNTHETIC) setInfo tp
- }
+ def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) =
+ if (formals.isEmpty) { MissingParameterTypeAnonMatchError(tree, pt); Nil }
+ else methodSym newSyntheticValueParams formals
- (newParamSyms, sel.duplicate)
+ def mkSel(params: List[Symbol]) =
+ if (params.isEmpty) EmptyTree
+ else {
+ val ids = params map (p => Ident(p.name))
+ atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
}
- }
import CODE._
@@ -2298,7 +2290,8 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser
// rig the show so we can get started typing the method body -- later we'll correct the infos...
anonClass setInfo ClassInfoType(List(ObjectClass.tpe, pt, SerializableClass.tpe), newScope, anonClass)
val methodSym = anonClass.newMethod(nme.apply, tree.pos, if(isPartial) (FINAL | OVERRIDE) else FINAL)
- val (paramSyms, selector) = mkParams(methodSym)
+ val paramSyms = mkParams(methodSym)
+ val selector = mkSel(paramSyms)
if (selector eq EmptyTree) EmptyTree
else {
@@ -2329,9 +2322,10 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser
val methodSym = anonClass.newMethod(nme.applyOrElse, tree.pos, FINAL | OVERRIDE)
// create the parameter that corresponds to the function's parameter
- val List(argTp) = deriveFormals
- val A1 = methodSym newTypeParameter(newTypeName("A1")) setInfo TypeBounds.upper(argTp)
- val (List(x), selector) = mkParams(methodSym, List(A1.tpe))
+ val List(argTp) = deriveFormals
+ val A1 = methodSym newTypeParameter(newTypeName("A1")) setInfo TypeBounds.upper(argTp)
+ val paramSyms@List(x) = mkParams(methodSym, List(A1.tpe))
+ val selector = mkSel(paramSyms)
if (selector eq EmptyTree) EmptyTree
else {
@@ -2362,7 +2356,9 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser
def isDefinedAtMethod = {
val methodSym = anonClass.newMethod(nme.isDefinedAt, tree.pos, FINAL)
- val (paramSyms, selector) = mkParams(methodSym)
+ val paramSyms = mkParams(methodSym)
+ val selector = mkSel(paramSyms)
+
if (selector eq EmptyTree) EmptyTree
else {
val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it)
@@ -2382,8 +2378,23 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser
else List(applyOrElseMethodDef, isDefinedAtMethod)
} else List(applyMethod)
- if (members.head eq EmptyTree) setError(tree)
- else typed(Block(List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, tree.pos)), New(anonClass.tpe)), mode, pt)
+ def translated =
+ if (members.head eq EmptyTree) setError(tree)
+ else typed(Block(List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, tree.pos)), New(anonClass.tpe)), mode, pt)
+ }
+
+ // Function(params, Match(sel, cases)) ==> new <Partial>Function { def apply<OrElse>(params) = `translateMatch('sel match { cases }')` }
+ class MatchFunTyperBetaReduced(fun: Function, sel: Tree, cases: List[CaseDef], mode: Int, pt: Type) extends MatchFunTyper(fun, cases, mode, pt) {
+ override def deriveFormals =
+ fun.vparams map { p => if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe }
+
+ // the only difference from the super class is that we must preserve the names of the parameters
+ override def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) =
+ (fun.vparams, formals).zipped map { (p, tp) =>
+ methodSym.newValueParameter(p.name, p.pos.focus, SYNTHETIC) setInfo tp
+ }
+
+ override def mkSel(params: List[Symbol]) = sel.duplicate
}
/**
@@ -2443,7 +2454,8 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser
// go to outer context -- must discard the context that was created for the Function since we're discarding the function
// thus, its symbol, which serves as the current context.owner, is not the right owner
// you won't know you're using the wrong owner until lambda lift crashes (unless you know better than to use the wrong owner)
- newTyper(context.outer).typedMatchAnonFun(fun, cases, mode, pt, Some((fun.vparams, sel)))
+ val outerTyper = newTyper(context.outer)
+ (new outerTyper.MatchFunTyperBetaReduced(fun, sel, cases, mode, pt)).translated
case _ =>
val vparamSyms = fun.vparams map { vparam =>
enterSym(context, vparam)
@@ -3835,7 +3847,7 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser
if (selector ne EmptyTree) {
val (selector1, selectorTp, casesAdapted, ownType, doTranslation) = typedMatch(selector, cases, mode, pt)
typed(translatedMatch(selector1, selectorTp, casesAdapted, ownType, doTranslation), mode, pt)
- } else typedMatchAnonFun(tree, cases, mode, pt)
+ } else (new MatchFunTyper(tree, cases, mode, pt)).translated
} else if (selector == EmptyTree) {
if (opt.virtPatmat) debugwarn("virtpatmat should not encounter empty-selector matches "+ tree)
val arity = if (isFunctionType(pt)) pt.normalize.typeArgs.length - 1 else 1