summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc/typechecker/RefChecks.scala
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 /sources/scala/tools/nsc/typechecker/RefChecks.scala
parentecda78ddf1909313f8a7b8aafa40c57dd8c093b6 (diff)
downloadscala-c64152bc3e64a713a1a0e452a26fb2b560411f68.tar.gz
scala-c64152bc3e64a713a1a0e452a26fb2b560411f68.tar.bz2
scala-c64152bc3e64a713a1a0e452a26fb2b560411f68.zip
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc/typechecker/RefChecks.scala')
-rwxr-xr-xsources/scala/tools/nsc/typechecker/RefChecks.scala59
1 files changed, 58 insertions, 1 deletions
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;