diff options
author | Martin Odersky <odersky@gmail.com> | 2005-10-07 14:13:14 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-10-07 14:13:14 +0000 |
commit | c64152bc3e64a713a1a0e452a26fb2b560411f68 (patch) | |
tree | 54dceecad7b7e3b0f8d278e907e079edad50af3f /sources/scala/tools/nsc/typechecker/RefChecks.scala | |
parent | ecda78ddf1909313f8a7b8aafa40c57dd8c093b6 (diff) | |
download | scala-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-x | sources/scala/tools/nsc/typechecker/RefChecks.scala | 59 |
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; |