summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-10-07 14:13:14 +0000
committerMartin Odersky <odersky@gmail.com>2005-10-07 14:13:14 +0000
commitc64152bc3e64a713a1a0e452a26fb2b560411f68 (patch)
tree54dceecad7b7e3b0f8d278e907e079edad50af3f
parentecda78ddf1909313f8a7b8aafa40c57dd8c093b6 (diff)
downloadscala-c64152bc3e64a713a1a0e452a26fb2b560411f68.tar.gz
scala-c64152bc3e64a713a1a0e452a26fb2b560411f68.tar.bz2
scala-c64152bc3e64a713a1a0e452a26fb2b560411f68.zip
*** empty log message ***
-rwxr-xr-xsources/scala/tools/nsc/Global.scala12
-rw-r--r--sources/scala/tools/nsc/ast/Trees.scala4
-rwxr-xr-xsources/scala/tools/nsc/symtab/StdNames.scala2
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala2
-rwxr-xr-xsources/scala/tools/nsc/transform/LambdaLift.scala2
-rwxr-xr-xsources/scala/tools/nsc/transform/UnCurry.scala16
-rwxr-xr-xsources/scala/tools/nsc/typechecker/RefChecks.scala59
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala77
8 files changed, 129 insertions, 45 deletions
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala
index 3e7b8b7fde..6ec822c0cc 100755
--- a/sources/scala/tools/nsc/Global.scala
+++ b/sources/scala/tools/nsc/Global.scala
@@ -242,16 +242,8 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
object icodeChecker extends checkers.ICodeChecker();
- object typer extends analyzer.Typer(analyzer.NoContext.make(EmptyTree, Global.this.definitions.RootClass, new Scope())) {
- override def typed(tree: Tree, mode: int, pt: Type): Tree = {
- if (settings.debug.value) log("typing [[" + tree + "]]");
- val result = super.typed(tree, mode, pt);
- if (settings.debug.value) log(" ==> " + result + ":" + result.tpe);
- result
- }
- override def typed(tree: Tree): Tree = super.typed(tree);
- override def typed(tree: Tree, pt: Type): Tree = super.typed(tree, pt);
- }
+ object typer extends analyzer.Typer(
+ analyzer.NoContext.make(EmptyTree, Global.this.definitions.RootClass, new Scope()));
def phaseDescriptors: List[SubComponent] = List(
analyzer.namerFactory,
diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala
index 84e297afbf..808d876172 100644
--- a/sources/scala/tools/nsc/ast/Trees.scala
+++ b/sources/scala/tools/nsc/ast/Trees.scala
@@ -301,7 +301,7 @@ import symtab.Flags._;
/** Anonymous function, eliminated by analyzer */
case class Function(vparams: List[ValDef], body: Tree)
- extends TermTree;
+ extends TermTree with SymTree;
/** Assignment */
case class Assign(lhs: Tree, rhs: Tree)
@@ -1083,7 +1083,7 @@ import symtab.Flags._;
class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser {
override def traverse(tree: Tree): unit = {
- if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.owner == oldowner)
+ if ((tree.isDef || tree.isInstanceOf[Function]) && tree.symbol != NoSymbol && tree.symbol.owner == oldowner)
tree.symbol.owner = newowner;
super.traverse(tree)
}
diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala
index 4dbf4d8850..78d4da8403 100755
--- a/sources/scala/tools/nsc/symtab/StdNames.scala
+++ b/sources/scala/tools/nsc/symtab/StdNames.scala
@@ -140,7 +140,7 @@ import scala.tools.nsc.util.NameTransformer;
val WILDCARD_STAR = newTermName("_*");
val COMPOUND_NAME = newTermName("<ct>");
val ANON_CLASS_NAME = newTermName("$anon");
- val ANONFUN_CLASS_NAME = newTermName("$anonfun");
+ val ANON_FUN_NAME = newTermName("$anonfun");
val REFINE_CLASS_NAME = newTermName("<refinement>");
val EMPTY_PACKAGE_NAME = newTermName("<empty>");
val IMPORT = newTermName("<import>");
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
index 9e92ea6c8c..0bf2c14ec5 100755
--- a/sources/scala/tools/nsc/symtab/Symbols.scala
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -91,7 +91,7 @@ import Flags._;
final def newAnonymousClass(pos: int) =
newClass(pos, nme.ANON_CLASS_NAME.toTypeName);
final def newAnonymousFunctionClass(pos: int) =
- newClass(pos, nme.ANONFUN_CLASS_NAME.toTypeName);
+ newClass(pos, nme.ANON_FUN_NAME.toTypeName);
final def newRefinementClass(pos: int) =
newClass(pos, nme.REFINE_CLASS_NAME.toTypeName);
final def newErrorClass(name: Name) = {
diff --git a/sources/scala/tools/nsc/transform/LambdaLift.scala b/sources/scala/tools/nsc/transform/LambdaLift.scala
index ab03f02af2..2cedb71a90 100755
--- a/sources/scala/tools/nsc/transform/LambdaLift.scala
+++ b/sources/scala/tools/nsc/transform/LambdaLift.scala
@@ -197,7 +197,7 @@ abstract class LambdaLift extends InfoTransform {
private def proxy(sym: Symbol) = {
def searchIn(owner: Symbol): Symbol = {
- if (settings.debug.value) log("searching for " + sym + " in " + owner + " " + enclMethOrClass(owner));//debug
+ if (settings.debug.value) log("searching for " + sym + "(" + sym.owner + ") in " + owner + " " + enclMethOrClass(owner));//debug
proxies.get(enclMethOrClass(owner)) match {
case Some(ps) =>
ps filter (p => p.name == sym.name) match {
diff --git a/sources/scala/tools/nsc/transform/UnCurry.scala b/sources/scala/tools/nsc/transform/UnCurry.scala
index 05c9be4f54..47e3fe43c4 100755
--- a/sources/scala/tools/nsc/transform/UnCurry.scala
+++ b/sources/scala/tools/nsc/transform/UnCurry.scala
@@ -63,7 +63,13 @@ abstract class UnCurry extends InfoTransform {
private var inPattern = false;
- override def transform(tree: Tree): Tree = postTransform(mainTransform(tree));
+ override def transform(tree: Tree): Tree = try { //debug
+ postTransform(mainTransform(tree));
+ } catch {
+ case ex: Throwable =>
+ System.out.println("exception when traversing " + tree);
+ throw ex
+ }
/* Is tree a reference `x' to a call by name parameter that neeeds to be converted to
* x.apply()? Note that this is not the case if `x' is used as an argument to another
@@ -108,7 +114,12 @@ abstract class UnCurry extends InfoTransform {
List.map2(formals, args1) ((formal, arg) =>
if (formal.symbol != ByNameParamClass) arg
else if (isByNameRef(arg)) arg setType functionType(List(), arg.tpe)
- else typer.atOwner(currentOwner).typed(Function(List(), arg) setPos arg.pos))
+ else {
+ val fun = typer.atOwner(currentOwner).typed(
+ Function(List(), arg) setPos arg.pos).asInstanceOf[Function];
+ new ChangeOwnerTraverser(currentOwner, fun.symbol).traverse(arg);
+ refchecks.newTransformer(unit).transformFunction(fun)
+ })
}
}
@@ -122,6 +133,7 @@ abstract class UnCurry extends InfoTransform {
inPattern = false;
copy.CaseDef(tree, pat1, transform(guard), transform(body))
case _ =>
+ assert(!tree.isInstanceOf[Function]);
val tree1 = super.transform(tree);
if (isByNameRef(tree1))
typed(atPos(tree1.pos)(
diff --git a/sources/scala/tools/nsc/typechecker/RefChecks.scala b/sources/scala/tools/nsc/typechecker/RefChecks.scala
index 58e88f69da..638a7f4543 100755
--- a/sources/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/sources/scala/tools/nsc/typechecker/RefChecks.scala
@@ -44,7 +44,7 @@ abstract class RefChecks extends InfoTransform {
val phaseName: String = "refchecks";
override def phaseNewFlags: long = lateMETHOD;
- def newTransformer(unit: CompilationUnit): Transformer = new RefCheckTransformer(unit);
+ def newTransformer(unit: CompilationUnit): RefCheckTransformer = new RefCheckTransformer(unit);
override def changesBaseClasses = false;
def transformInfo(sym: Symbol, tp: Type): Type = {
@@ -81,6 +81,17 @@ abstract class RefChecks extends InfoTransform {
mvarRef))
}
+ val resetAttrs = new Traverser {
+ override def traverse(tree: Tree): unit = tree match {
+ case EmptyTree | TypeTree() =>
+ ;
+ case _ =>
+ if (tree.hasSymbol) tree.symbol = NoSymbol;
+ tree.tpe = null;
+ super.traverse(tree)
+ }
+ }
+
class RefCheckTransformer(unit: CompilationUnit) extends Transformer {
var localTyper: analyzer.Typer = typer;
@@ -474,6 +485,49 @@ abstract class RefChecks extends InfoTransform {
List(transform(tree))
}
+ def transformFunction(fun: Function): Tree = {
+ val anonClass = fun.symbol.owner.newAnonymousFunctionClass(fun.pos) setFlag (FINAL | SYNTHETIC);
+ val formals = fun.tpe.typeArgs.init;
+ val restpe = fun.tpe.typeArgs.last;
+ anonClass setInfo ClassInfoType(
+ List(ObjectClass.tpe, fun.tpe, ScalaObjectClass.tpe), new Scope(), anonClass);
+ val applyMethod = anonClass.newMethod(fun.pos, nme.apply)
+ setFlag FINAL setInfo MethodType(formals, restpe);
+ anonClass.info.decls enter applyMethod;
+ for (val vparam <- fun.vparams) vparam.symbol.owner = applyMethod;
+ new ChangeOwnerTraverser(fun.symbol, applyMethod).traverse(fun.body);
+ var members = List(
+ DefDef(FINAL, nme.apply, List(), List(fun.vparams), TypeTree(restpe), fun.body)
+ setSymbol applyMethod);
+ if (fun.tpe.symbol == PartialFunctionClass) {
+ val isDefinedAtMethod = anonClass.newMethod(fun.pos, nme.isDefinedAt)
+ setFlag FINAL setInfo MethodType(formals, BooleanClass.tpe);
+ anonClass.info.decls enter isDefinedAtMethod;
+ def idbody(idparam: Symbol) = fun.body match {
+ case Match(_, cases) =>
+ val substParam = new TreeSymSubstituter(List(fun.vparams.head.symbol), List(idparam));
+ def transformCase(cdef: CaseDef): CaseDef =
+ resetAttrs(CaseDef(cdef.pat.duplicate, cdef.guard.duplicate, Literal(true)));
+ if (cases exists treeInfo.isDefaultCase) Literal(true)
+ else
+ Match(
+ Ident(idparam),
+ (cases map transformCase) :::
+ List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))))
+ }
+ members = DefDef(isDefinedAtMethod, vparamss => idbody(vparamss.head.head)) :: members;
+ }
+ localTyper.typed {
+ atPos(fun.pos) {
+ Block(
+ List(ClassDef(anonClass, List(List()), List(List()), members)),
+ Typed(
+ New(TypeTree(anonClass.tpe), List(List())),
+ TypeTree(fun.tpe)))
+ }
+ }
+ }
+
override def transform(tree: Tree): Tree = try {
/* Convert a reference of a case factory to a new of the class it produces. */
@@ -524,6 +578,9 @@ abstract class RefChecks extends InfoTransform {
}
} traverse tree.tpe
+ case fun @ Function(_, _) =>
+ result = transform(transformFunction(fun));
+
case TypeApply(fn, args) =>
checkBounds(fn.tpe.typeParams, args map (.tpe));
if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor;
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index a1ce19b046..835e617b98 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -33,17 +33,6 @@ import collection.mutable.HashMap;
superDefs.clear;
}
- val resetAttrs = new Traverser {
- override def traverse(tree: Tree): unit = tree match {
- case EmptyTree | TypeTree() =>
- ;
- case _ =>
- if (tree.hasSymbol) tree.symbol = NoSymbol;
- tree.tpe = null;
- super.traverse(tree)
- }
- }
-
def newTyper(context: Context): Typer = new Typer(context);
class Typer(context0: Context) {
@@ -150,7 +139,8 @@ import collection.mutable.HashMap;
}
/** Check that type `tree' does not refer to entities defined in scope `scope'. */
- def locals[T <: Tree](scope: Scope, tree: T): T = check(NoSymbol, scope, tree);
+ def locals[T <: Tree](scope: Scope, pt: Type, tree: T): T =
+ if (isFullyDefined(pt)) tree setType pt else check(NoSymbol, scope, tree);
def check[T <: Tree](owner: Symbol, scope: Scope, tree: T): T = {
this.owner = owner;
@@ -638,20 +628,22 @@ import collection.mutable.HashMap;
List.mapConserve(vparams1)(typedValDef));
var tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt));
val rhs1 =
- if (ddef.name == nme.CONSTRUCTOR) {
- if (!meth.hasFlag(SYNTHETIC) &&
- !(meth.owner.isClass ||
- meth.owner.isModuleClass ||
- meth.owner.isAnonymousClass ||
- meth.owner.isRefinementClass))
- error(ddef.pos, "constructor definition not allowed here " + meth.owner);//debug
- context.enclClass.owner.setFlag(INCONSTRUCTOR);
- val result = typed(ddef.rhs, EXPRmode | INCONSTRmode, UnitClass.tpe);
- context.enclClass.owner.resetFlag(INCONSTRUCTOR);
- if (meth.isPrimaryConstructor && !phase.erasedTypes)
- computeParamAliases(meth.owner, vparamss1, result);
- result
- } else transformedOrTyped(ddef.rhs, tpt1.tpe);
+ checkNoEscaping.locals(
+ context.scope, tpt1.tpe,
+ if (ddef.name == nme.CONSTRUCTOR) {
+ if (!meth.hasFlag(SYNTHETIC) &&
+ !(meth.owner.isClass ||
+ meth.owner.isModuleClass ||
+ meth.owner.isAnonymousClass ||
+ meth.owner.isRefinementClass))
+ error(ddef.pos, "constructor definition not allowed here " + meth.owner);//debug
+ context.enclClass.owner.setFlag(INCONSTRUCTOR);
+ val result = typed(ddef.rhs, EXPRmode | INCONSTRmode, UnitClass.tpe);
+ context.enclClass.owner.resetFlag(INCONSTRUCTOR);
+ if (meth.isPrimaryConstructor && !phase.erasedTypes)
+ computeParamAliases(meth.owner, vparamss1, result);
+ result
+ } else transformedOrTyped(ddef.rhs, tpt1.tpe));
copy.DefDef(ddef, ddef.mods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
@@ -701,7 +693,7 @@ import collection.mutable.HashMap;
else {
if (block1.tpe.symbol.isAnonymousClass)
block1 setType intersectionType(block1.tpe.parents, block1.tpe.symbol.owner);
- checkNoEscaping.locals(context.scope, block1)
+ checkNoEscaping.locals(context.scope, pt, block1)
}
}
@@ -744,6 +736,7 @@ import collection.mutable.HashMap;
*
* def isDefinedAt(x: T): boolean = true
*/
+/*
def typedFunction(fun: Function, mode: int, pt: Type): Tree = {
val Triple(clazz, argpts, respt) =
if (isFunctionType(pt)
@@ -804,6 +797,32 @@ import collection.mutable.HashMap;
New(TypeTree(anonClass.tpe), List(List())),
TypeTree(funtpe)))))
}
+*/
+ def typedFunction(fun: Function, mode: int, pt: Type): Tree = {
+ val Triple(clazz, argpts, respt) =
+ if (isFunctionType(pt)
+ ||
+ pt.symbol == PartialFunctionClass &&
+ fun.vparams.length == 1 && fun.body.isInstanceOf[Match])
+ Triple(pt.symbol, pt.typeArgs.init, pt.typeArgs.last)
+ else
+ Triple(FunctionClass(fun.vparams.length), fun.vparams map (x => NoType), WildcardType);
+ val vparamSyms = List.map2(fun.vparams, argpts) { (vparam, argpt) =>
+ if (vparam.tpt.isEmpty)
+ vparam.tpt.tpe =
+ if (argpt == NoType) { error(vparam.pos, "missing parameter type"); ErrorType }
+ else argpt;
+ namer.enterSym(vparam);
+ vparam.symbol
+ }
+ val vparams = List.mapConserve(fun.vparams)(typedValDef);
+ val body = typed(fun.body, respt);
+ val formals = vparamSyms map (.tpe);
+ val restpe = body.tpe.deconst;
+ val funtpe = typeRef(clazz.tpe.prefix, clazz, formals ::: List(restpe));
+ copy.Function(fun, vparams, checkNoEscaping.locals(context.scope, restpe, body))
+ setType funtpe
+ }
def typedRefinement(stats: List[Tree]): List[Tree] = {
namer.enterSyms(stats);
@@ -1141,7 +1160,11 @@ import collection.mutable.HashMap;
else appliedType(ArrayClass.typeConstructor, List(elemtpt1.tpe)))
case fun @ Function(_, _) =>
+/*
newTyper(context.makeNewScope(tree, context.owner)).typedFunction(fun, mode, pt)
+*/
+ tree.symbol = context.owner.newValue(tree.pos, nme.ANON_FUN_NAME) setFlag SYNTHETIC;
+ newTyper(context.makeNewScope(tree, tree.symbol)).typedFunction(fun, mode, pt)
case Assign(lhs, rhs) =>
def isGetter(sym: Symbol) = sym.info match {