diff options
author | Martin Odersky <odersky@gmail.com> | 2013-07-25 22:16:07 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-07-25 22:22:42 +0200 |
commit | cf65e84a6da2a151286a36297c057b72545960c8 (patch) | |
tree | 55f3d8a30f5751602836d62d0b1a4ae6269b64bd /src/dotty/tools/dotc/typer/Typer.scala | |
parent | 0a86c0ae8668070f62df25c7a4ba12369f23b216 (diff) | |
download | dotty-cf65e84a6da2a151286a36297c057b72545960c8.tar.gz dotty-cf65e84a6da2a151286a36297c057b72545960c8.tar.bz2 dotty-cf65e84a6da2a151286a36297c057b72545960c8.zip |
More typer logic, in particular dealing with variants of applications
Diffstat (limited to 'src/dotty/tools/dotc/typer/Typer.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 137 |
1 files changed, 103 insertions, 34 deletions
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index f99c08ecb..6d6211daf 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -9,7 +9,7 @@ import Constants._ import StdNames._ import Scopes._ import Denotations._ -import Inferencing.Infer +import Inferencing._ import Contexts._ import Symbols._ import Types._ @@ -19,7 +19,7 @@ import NameOps._ import Flags._ import Decorators._ import ErrorReporting._ -import Applications.FunProtoType +import Applications.{FunProtoType, PolyProtoType} import EtaExpansion.etaExpand import util.Positions._ import util.SourcePosition @@ -31,6 +31,8 @@ trait TyperContextOps { ctx: Context => } object Typer { + import tpd._ + object BindingPrec { val definition = 4 val namedImport = 3 @@ -40,12 +42,19 @@ object Typer { def isImportPrec(prec: Int) = prec == namedImport || prec == wildImport } - implicit class TreeDecorator(tree: tpd.Tree) { + implicit class TreeDecorator(tree: Tree) { def exprType(implicit ctx: Context): Type = tree.tpe match { case tpe: TermRef if !tpe.symbol.isStable => tpe.info case tpe => tpe } } + + case class StateFul[T](value: T, state: TyperState) { + def commit()(implicit ctx: Context): T = { + state.commit() + value + } + } } class Typer extends Namer with Applications with Implicits { @@ -60,11 +69,15 @@ class Typer extends Namer with Applications with Implicits { private var importedFromRoot: Set[Symbol] = Set() def typedSelection(site: Type, name: Name, pos: Position)(implicit ctx: Context): Type = { - val ref = site.member(name) + val ref = + if (name == nme.CONSTRUCTOR) site.decl(name) + else site.member(name) if (ref.exists) NamedType(site, name).withDenot(ref) else { if (!site.isErroneous) - ctx.error(s"$name is not a member of ${site.show}", pos) + ctx.error( + if (name == nme.CONSTRUCTOR) s"${site.show} does not have a constructor" + else s"$name is not a member of ${site.show}", pos) ErrorType } } @@ -95,6 +108,21 @@ class Typer extends Namer with Applications with Implicits { tpe } + /** The qualifying class + * of a this or super with prefix `qual`. + * packageOk is equal false when qualifying class symbol + */ + def qualifyingClass(tree: untpd.Tree, qual: Name, packageOK: Boolean)(implicit ctx: Context): Symbol = + ctx.owner.enclosingClass.ownersIterator.find(o => qual.isEmpty || o.isClass && o.name == qual) match { + case Some(c) if packageOK || !(c is Package) => + c + case _ => + ctx.error( + if (qual.isEmpty) tree.show + " can be used only in a class, object, or template" + else qual.show + " is not an enclosing class", tree.pos) + NoSymbol + } + /** Attribute an identifier consisting of a simple name or an outer reference. * * @param tree The tree representing the identifier. @@ -258,7 +286,7 @@ class Typer extends Namer with Applications with Implicits { val rawType = try findRef(NoType, BindingPrec.nothingBound, NoContext) finally importedFromRoot = saved - + val ownType = if (rawType.exists) checkAccessible(rawType, superAccess = false, tree.pos) else { @@ -275,21 +303,61 @@ class Typer extends Namer with Applications with Implicits { tree.withType(ownType).derivedSelect(qual1, tree.name) } - def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { - val proto = new FunProtoType(tree.args, pt, this) - val fun1 = typedExpr(tree.fun, proto) - TreeInfo.methPart(fun1).tpe match { - case funRef: TermRef => - val app = - if (proto.argsAreTyped) new ApplyToTyped(tree, fun1, funRef, proto.typedArgs, pt) - else new ApplyToUntyped(tree, fun1, funRef, tree.args, pt) - app.result - case _ => - fun1.exprType match { - case ErrorType => - tree.withType(ErrorType) - } + def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = { + val cls = qualifyingClass(tree, tree.qual, packageOK = false) + tree.withType(cls.thisType) + } + + def typedSuper(tree: untpd.Super)(implicit ctx: Context): Tree = { + val mix = tree.mix + val qual1 = typed(tree.qual) + val cls = qual1.tpe.typeSymbol + + def findMixinSuper(site: Type): Type = site.parents filter (_.name == mix) match { + case p :: Nil => + p + case Nil => + errorType(s"$mix does not name a parent class of $cls", tree.pos) + case p :: q :: _ => + errorType(s"ambiguous parent class qualifier", tree.pos) } + val owntype = + if (!mix.isEmpty) findMixinSuper(cls.info) + else if (ctx.mode is Mode.InSuperInit) cls.info.firstParent + else cls.info.parents.reduceLeft((x: Type, y: Type) => AndType(x, y)) + + tree.withType(SuperType(cls.thisType, owntype)).derivedSuper(qual1, mix) + } + + def typedLiteral(tree: untpd.Literal)(implicit ctx: Context) = + tree.withType(if (tree.const.tag == UnitTag) defn.UnitType else ConstantType(tree.const)) + + def typedNew(tree: untpd.New)(implicit ctx: Context) = { + val tpt1 = typedType(tree.tpt) + val cls = checkClassTypeWithStablePrefix(tpt1.tpe, tpt1.pos) + checkInstantiatable(cls, tpt1.pos) + tree.withType(tpt1.tpe).derivedNew(tpt1) + } + + def typedPair(tree: untpd.Pair)(implicit ctx: Context) = { + val left1 = typed(tree.left) + val right1 = typed(tree.right) + tree.withType(defn.PairType.appliedTo(left1.tpe :: right1.tpe :: Nil)).derivedPair(left1, right1) + } + + def TypedTyped(tree: untpd.Typed)(implicit ctx: Context) = { + val tpt1 = typedType(tree.tpt) + val expr1 = typedExpr(tree.expr, tpt1.tpe) + tree.withType(tpt1.tpe).derivedTyped(tpt1, expr1) + } + + def NamedArg(tree: untpd.NamedArg, pt: Type)(implicit ctx: Context) = { + val arg1 = typed(tree.arg, pt) + tree.withType(arg1.tpe).derivedNamedArg(tree.name, arg1) + } + + def Assign(tree: untpd.Assign)(implicit ctx: Context) = { + ??? } def typedModifiers(mods: untpd.Modifiers)(implicit ctx: Context): Modifiers = { @@ -428,29 +496,24 @@ class Typer extends Namer with Applications with Implicits { def typedPattern(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = typed(tree, pt)(ctx addMode Mode.Pattern) - def tryEither[T](op: Context => T)(fallBack: => T)(implicit ctx: Context) = { + def tryEither[T](op: Context => T)(fallBack: StateFul[T] => T)(implicit ctx: Context) = { val nestedCtx = ctx.fresh.withNewTyperState val result = op(nestedCtx) if (nestedCtx.reporter.hasErrors) - fallBack + fallBack(StateFul(result, nestedCtx.typerState)) else { nestedCtx.typerState.commit() result } } - def tryInsertApply(tree: Tree, pt: Type)(fallBack: => Tree)(implicit ctx: Context): Tree = + def tryInsertApply(tree: Tree, pt: Type)(fallBack: StateFul[Tree] => Tree)(implicit ctx: Context): Tree = tryEither { implicit ctx => typedSelect(Trees.Select(untpd.TypedSplice(tree), nme.apply), pt) } { fallBack } - def tryInsertApplyIfFunProto(tree: Tree, pt: Type)(fallBack: => Tree)(implicit ctx: Context): Tree = pt match { - case pt: FunProtoType => tryInsertApply(tree, pt)(fallBack) - case _ => fallBack - } - /** * (-1) For expressions with annotated types, let AnnotationCheckers decide what to do * (0) Convert expressions with constant types to literals (unless in interactive/scaladoc mode) @@ -501,10 +564,13 @@ class Typer extends Namer with Applications with Implicits { case alt :: Nil => adapt(tree.withType(alt), pt) case Nil => - tryInsertApplyIfFunProto(tree, pt) { + def noMatches = errorTree(tree, s"""none of the ${err.overloadedAltsStr(altDenots)} |match $expectedStr""".stripMargin) + pt match { + case pt: FunProtoType => tryInsertApply(tree, pt)(_ => noMatches) + case _ => noMatches } case alts => errorTree(tree, @@ -521,7 +587,7 @@ class Typer extends Namer with Applications with Implicits { case Apply(_, _) => " more" case _ => "" } - errorTree(tree, s"$fn does not take$more parameters") + _ => errorTree(tree, s"$fn does not take$more parameters") } } @@ -559,10 +625,13 @@ class Typer extends Namer with Applications with Implicits { tree.tpe.widen match { case ref: TermRef => adaptOverloaded(ref) - case pt: PolyType => - val tracked = ctx.track(pt) - val tvars = ctx.newTypeVars(tracked) - adapt(tpd.TypeApply(tree, tvars map (tpd.TypeTree(_))), pt) + case poly: PolyType => + if (pt.isInstanceOf[PolyProtoType]) tree + else { + val tracked = ctx.track(poly) + val tvars = ctx.newTypeVars(tracked) + adapt(tpd.TypeApply(tree, tvars map (tpd.TypeTree(_))), pt) + } case tp => pt match { case pt: FunProtoType => adaptToArgs(tp, pt) |