diff options
author | Martin Odersky <odersky@gmail.com> | 2005-06-09 18:45:48 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-06-09 18:45:48 +0000 |
commit | 4ae459ef755dccc8230a884bf6f462c4dadc96b8 (patch) | |
tree | 3d27d19a37680d452c4b52b84e809174a86fba5f /sources | |
parent | d7499538cc0da7beb331a4550b7a6e85cd132876 (diff) | |
download | scala-4ae459ef755dccc8230a884bf6f462c4dadc96b8.tar.gz scala-4ae459ef755dccc8230a884bf6f462c4dadc96b8.tar.bz2 scala-4ae459ef755dccc8230a884bf6f462c4dadc96b8.zip |
Repository : /home/cvslamp/repositories/scala
Module : scala
Working dir: ~/scala/
In directory .:
Unknown META-INF
Unknown Test.symbl
Unknown VERSION-1.1.0-b1
Unknown collection
Unknown expr.exe.stackdump
Unknown importing
Unknown iq.symbl
Unknown java.io.Writer
Unknown make
Unknown rm
Unknown scalac.symtab.Symbol
Unknown testcast
Unknown x
Unknown xmake
Unknown y
Unknown z
In directory bin:
Unknown bin/dtd2scala.lnk
Unknown bin/scala-debug.lnk
Unknown bin/scala-info.lnk
Unknown bin/scala.lnkMa
Unknown bin/scalac-debug.lnk
Unknown bin/scalac.lnk
Unknown bin/scaladoc-debug.lnk
Unknown bin/scaladoc.lnk
Unknown bin/scalaint-debug.lnk
Unknown bin/scalaint.lnk
Unknown bin/scalap.lnk
Unknown bin/scalarun-debug.lnk
Unknown bin/scalarun.lnk
Unknown bin/scalatest.lnk
In directory config:
In directory config/list:
Modified config/list/nsc.lst
In directory doc:
Unknown doc/announcement.txt
In directory doc/papers:
Message: cvs update: cannot open directory /home/cvslamp/repositories/scala/scala/doc/papers: No such file or directory
Message: cvs update: skipping directory doc/papers
In directory doc/reference:
Unknown doc/reference/R1.tex
Unknown doc/reference/ScalaReference.tex.1
Unknown doc/reference/ScalaReference.tex.new
Unknown doc/reference/ScalaVersion.tex
Unknown doc/reference/lecture.tex
Unknown doc/reference/math.sty
Unknown doc/reference/modefs.sty
Unknown doc/reference/prooftree.sty
Unknown doc/reference/sbe-talk.tex
Unknown doc/reference/scaladefs.sty
Unknown doc/reference/scaladefs.tex
Unknown doc/reference/scaladoc.sty
Unknown doc/reference/tweaklist.sty
Unknown doc/reference/vquote.sty
Unknown doc/reference/x
In directory doc/reports:
Message: cvs update: cannot open directory /home/cvslamp/repositories/scala/scala/doc/reports: No such file or directory
Message: cvs update: skipping directory doc/reports
In directory doc/talks:
Message: cvs update: cannot open directory /home/cvslamp/repositories/scala/scala/doc/talks: No such file or directory
Message: cvs update: skipping directory doc/talks
In directory sources:
Unknown sources/new
Unknown sources/scala.zip
Unknown sources/scalac.own
Unknown sources/ziDeLBjS
In directory sources/examples:
Unknown sources/examples/BibTree.scala
Unknown sources/examples/BibTree1.scala
Unknown sources/examples/BinTree.scala
Unknown sources/examples/concurrent
Unknown sources/examples/epl
Unknown sources/examples/epl.zip
Unknown sources/examples/examples
Unknown sources/examples/fs
Unknown sources/examples/graphs.scala
Unknown sources/examples/implicit
Unknown sources/examples/interpreters.scala
Unknown sources/examples/parsers2a.scala
Unknown sources/examples/parsers3.scala
Unknown sources/examples/pubsub.scala
Unknown sources/examples/pubsub.scala.notyet
Unknown sources/examples/pubsub1.scala
Unknown sources/examples/shapes.scala
Unknown sources/examples/stacks.scala
Unknown sources/examples/teletrans.scala
Unknown sources/examples/teletrans1.scala
Unknown sources/examples/xpath.scala
Unknown sources/examples/xpath1.scala
In directory sources/examples/expressions:
Unknown sources/examples/expressions/abstract-data-1.scala
Unknown sources/examples/expressions/abstract-data-2.scala
Unknown sources/examples/expressions/abstract-data-mixin-1.scala
Unknown sources/examples/expressions/abstract-data-mixin-bad.scala
Unknown sources/examples/expressions/abstract-data-mixin-neg.scala
Unknown sources/examples/expressions/abstract-data-mixin.scala
Unknown sources/examples/expressions/abstract-data.scala
Unknown sources/examples/expressions/abstract-operation-1.scala
Unknown sources/examples/expressions/abstract-operation-2.scala
Unknown sources/examples/expressions/abstract-operation-mixin.scala
Unknown sources/examples/expressions/abstract-operation.scala
Unknown sources/examples/expressions/expressions-constr-abstypes.scala
Unknown sources/examples/expressions/expressions-oo.scala
Unknown sources/examples/expressions/expressions-visitors.scala
Unknown sources/examples/expressions/expressions-visitos.scala
Unknown sources/examples/expressions/generic-data.scala
Unknown sources/examples/expressions/generic-operation-factory.scala
Unknown sources/examples/expressions/generic-operation-simple.scala
Unknown sources/examples/expressions/generic-operation.scala
Unknown sources/examples/expressions/scala
Unknown sources/examples/expressions/test
Unknown sources/examples/expressions/x
In directory sources/scala:
Unknown sources/scala/$colon$colon.scala.disabled
Unknown sources/scala/.latest-compiler
Unknown sources/scala/Array.java.notyet
Unknown sources/scala/ArrayIterator.java.notyet
Modified sources/scala/CaseClass.scala
Modified sources/scala/List.scala
Unknown sources/scala/NoValue
Unknown sources/scala/ScalaObject.scala
Unknown sources/scala/bootclasses
Unknown sources/scala/cls
Unknown sources/scala/new
Unknown sources/scala/newclasses
Unknown sources/scala/nsc-build
Unknown sources/scala/nsc-build.bat
Unknown sources/scala/nscnew
Unknown sources/scala/nscnew.bat
Unknown sources/scala/nx
Unknown sources/scala/old
Unknown sources/scala/ox
Unknown sources/scala/predef
Unknown sources/scala/scala.Ordered![a!])scala.Ordered![scala.List![a!]]
Unknown sources/scala/test.scala
Unknown sources/scala/x
In directory sources/scala/runtime:
Unknown sources/scala/runtime/CaseOps.scala
In directory sources/scala/tools:
Unknown sources/scala/tools/nsc.zip
Unknown sources/scala/tools/nsc1
Unknown sources/scala/tools/nscnew
In directory sources/scala/tools/nsc:
Modified sources/scala/tools/nsc/Global.scala
Modified sources/scala/tools/nsc/Phase.scala
Added sources/scala/tools/nsc/SubComponent.scala
Unknown sources/scala/tools/nsc/typechecker.new
In directory sources/scala/tools/nsc/ast:
Modified sources/scala/tools/nsc/ast/TreeGen.scala
Modified sources/scala/tools/nsc/ast/Trees.scala
In directory sources/scala/tools/nsc/ast/parser:
Modified sources/scala/tools/nsc/ast/parser/Parsers.scala
Modified sources/scala/tools/nsc/ast/parser/Scanners.scala
Added sources/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
Modified sources/scala/tools/nsc/ast/parser/Tokens.scala
Modified sources/scala/tools/nsc/ast/parser/TreeBuilder.scala
In directory sources/scala/tools/nsc/matching:
Modified sources/scala/tools/nsc/matching/PatternUtil.scala
In directory sources/scala/tools/nsc/symtab:
Modified sources/scala/tools/nsc/symtab/Definitions.scala
Modified sources/scala/tools/nsc/symtab/Flags.scala
Modified sources/scala/tools/nsc/symtab/Names.scala
Modified sources/scala/tools/nsc/symtab/Scopes.scala
Modified sources/scala/tools/nsc/symtab/StdNames.scala
Modified sources/scala/tools/nsc/symtab/SymbolTable.scala
Modified sources/scala/tools/nsc/symtab/Symbols.scala
Modified sources/scala/tools/nsc/symtab/Types.scala
In directory sources/scala/tools/nsc/symtab/classfile:
Modified sources/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala
Modified sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala
Modified sources/scala/tools/nsc/symtab/classfile/Pickler.scala
In directory sources/scala/tools/nsc/transform:
Modified sources/scala/tools/nsc/transform/SampleTransform.scala
Modified sources/scala/tools/nsc/transform/Transform.scala
Removed sources/scala/tools/nsc/transform/TypesAsValues.scala
In directory sources/scala/tools/nsc/typechecker:
Modified sources/scala/tools/nsc/typechecker/Analyzer.scala
Modified sources/scala/tools/nsc/typechecker/Contexts.scala
Modified sources/scala/tools/nsc/typechecker/Infer.scala
Modified sources/scala/tools/nsc/typechecker/Namers.scala
Added sources/scala/tools/nsc/typechecker/RefChecks.scala
Modified sources/scala/tools/nsc/typechecker/TreeCheckers.scala
Modified sources/scala/tools/nsc/typechecker/Typers.scala
In directory sources/scala/xml:
In directory sources/scala/xml/parsing:
Modified sources/scala/xml/parsing/MarkupHandler.scala
Modified sources/scala/xml/parsing/MarkupParser.scala
In directory sources/scalac:
In directory sources/scalac/symtab:
In directory sources/scalac/symtab/classfile:
Unknown sources/scalac/symtab/classfile/PackageParser.java.1
In directory test:
Unknown test/absobs.scala
Unknown test/attr.scala
Unknown test/bug363.scala
Unknown test/mixin.scala
Unknown test/nsc
Unknown test/nsc.scala
Unknown test/nsc1.scala
Unknown test/nsc2.scala
Unknown test/sabin.scala
Unknown test/sabin2.scala
Unknown test/selftypes.scala
Unknown test/single.scala
Unknown test/testmatch.scala
In directory test/files:
Unknown test/files/bug320.scala
In directory test/files/neg:
Unknown test/files/neg/bug356.check
Unknown test/files/neg/bug356.scala
Unknown test/files/neg/bug363.check
Unknown test/files/neg/bug363.scala
Unknown test/files/neg/bug369.check
Unknown test/files/neg/bug369.scala
Unknown test/files/neg/bug370.check
Unknown test/files/neg/bug370.scala
Unknown test/files/neg/bug373.check
Unknown test/files/neg/bug373.scala
Unknown test/files/neg/bug375.check
Unknown test/files/neg/bug375.scala
Unknown test/files/neg/escapes.scala
Unknown test/files/neg/test
In directory test/files/pos:
Unknown test/files/pos/A.symbl
Unknown test/files/pos/B.symbl
Unknown test/files/pos/C.symbl
Unknown test/files/pos/D.symbl
Unknown test/files/pos/O.symbl
Unknown test/files/pos/S.symbl
Unknown test/files/pos/T.symbl
Unknown test/files/pos/arrays2.symbl
Unknown test/files/pos/bug348plus.scala
Unknown test/files/pos/lists.symbl
Unknown test/files/pos/main.symbl
Unknown test/files/pos/test.symbl
In directory test/new:
Message: cvs update: cannot open directory /home/cvslamp/repositories/scala/scala/test/new: No such file or directory
Message: cvs update: skipping directory test/new
In directory test/pos:
Unknown test/pos/valparams.scala
Unknown test/pos/vincent.scala
In directory website:
Message: cvs update: cannot open directory /home/cvslamp/repositories/scala/scala/website: No such file or directory
Message: cvs update: skipping directory website
--------------------- End ---------------------
-- last cmd: cvs -f update -d -P --
Diffstat (limited to 'sources')
33 files changed, 694 insertions, 416 deletions
diff --git a/sources/scala/Double.java b/sources/scala/Double.java index 9a62ab9dfa..be5d3de12a 100644 --- a/sources/scala/Double.java +++ b/sources/scala/Double.java @@ -10,6 +10,7 @@ package scala; +/** @meta class extends scala.AnyVal; */ public abstract class Double extends AnyVal implements java.io.Serializable { public final double value; diff --git a/sources/scala/List.scala b/sources/scala/List.scala index 7f7e1c2c7a..b4f80ddaf3 100644 --- a/sources/scala/List.scala +++ b/sources/scala/List.scala @@ -902,7 +902,7 @@ case object Nil extends List[All] { * @author Martin Odersky * @version 1.0, 15/07/2003 */ -[SerialVersionUID(0 - 8476791151983527571L)] +[SerialVersionUID(0L - 8476791151983527571L)] final case class ::[+b](hd: b, tl: List[b]) extends List[b] { def isEmpty: boolean = false; def head: b = hd; diff --git a/sources/scala/Predef.scala b/sources/scala/Predef.scala index 88f0e72015..d3214f9fd3 100644 --- a/sources/scala/Predef.scala +++ b/sources/scala/Predef.scala @@ -68,7 +68,6 @@ object Predef { for (val x <- xs.elements) { array(i) = x; i = i + 1; } array; } - def Array(xs: boolean*): Array[boolean] = { val array = new Array[boolean](xs.length); var i = 0; diff --git a/sources/scala/SerialVersionUID.scala b/sources/scala/SerialVersionUID.scala index dab477a7b0..3232a19db3 100644 --- a/sources/scala/SerialVersionUID.scala +++ b/sources/scala/SerialVersionUID.scala @@ -8,5 +8,5 @@ */ package scala; -case class SerialVersionUID(uid: long) extends Attribute {} +case class SerialVersionUID(uid: Long) extends Attribute {} diff --git a/sources/scala/runtime/ScalaRunTime.scala b/sources/scala/runtime/ScalaRunTime.scala index a9fc226ea3..b451c5e0f5 100644 --- a/sources/scala/runtime/ScalaRunTime.scala +++ b/sources/scala/runtime/ScalaRunTime.scala @@ -40,4 +40,41 @@ object ScalaRunTime { throw exception; } + def caseFields(x: CaseClass): List[Any] = { + val arity = x.caseArity; + def fields(from: Int): List[Any] = + if (from >= arity) List() + else x.caseElement(from) :: fields(from + 1); + fields(0) + } + + def _toString(x: CaseClass): String = { + caseFields(x).mkString(x.caseName + "(", ",", ")") + } + + def _hashCode(x: CaseClass): Int = { + var code = x.getClass().hashCode(); + val arity = x.caseArity; + var i = 0; + while (i < arity) { + code = code * 41 + x.caseElement(i).hashCode(); + i = i + 1 + } + code + } + + def _equals(x: CaseClass, y: Any): Boolean = y match { + case y1: CaseClass => + (x.getClass() eq y1.getClass()) && { + val arity = x.caseArity; + var i = 0; + while (i < arity && x.caseElement(i) == y1.caseElement(i)) + i = i + 1; + i == arity + } + case _ => + false + } + + def Seq[a](xs: a*): Seq[a] = null; // interpreted specially by new backend. } diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala index 317bc06ecd..f51dda9d2b 100755 --- a/sources/scala/tools/nsc/Global.scala +++ b/sources/scala/tools/nsc/Global.scala @@ -156,6 +156,13 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable } val refchecksPhase = new refchecks.Phase(picklePhase); +/* + object uncurry extends UnCurry { + val global: Global.this.type = Global.this; + } + val refchecksPhase = new uncurry.Phase(refchecksPhase); +*/ + //object transmatcher extends TransMatcher { // val global: Global.this.type = Global.this; //} diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala index 20d77d7c64..ab51837d21 100644 --- a/sources/scala/tools/nsc/ast/TreePrinters.scala +++ b/sources/scala/tools/nsc/ast/TreePrinters.scala @@ -225,12 +225,13 @@ abstract class TreePrinters { case Ident(name) => print(symName(tree, name)) - case Literal(obj) => - print(obj match { - case null => "null" - case s: String => "\"" + s + "\"" - case c: char => "\'" + c + "\'" - case _ => obj.toString() + case Literal(x) => + print(x.tag match { + case NullTag => "null" + case StringTag => "\"" + x.stringValue + "\"" + case CharTag => "\'" + x.charValue + "\'" + case LongTag => x.longValue.toString() + "L"; + case _ => x.value.toString() }) case TypeTree() => diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala index 7ee1a44d8a..2e3822272a 100644 --- a/sources/scala/tools/nsc/ast/Trees.scala +++ b/sources/scala/tools/nsc/ast/Trees.scala @@ -289,7 +289,7 @@ abstract class Trees: Global { * * after TM, cases will satisfy the following constraints: * - all guards are EmptyTree, - * - all patterns will be either Literal(x:Int) or Alternative(lit|...|lit) + * - all patterns will be either Literal(Constant(x:Int)) or Alternative(lit|...|lit) * - except for an "otherwise" branch, which has pattern Ident(nme.WILDCARD) */ case class Match(selector: Tree, cases: List[CaseDef]) extends TermTree; @@ -374,12 +374,13 @@ abstract class Trees: Global { } /** Literal */ - case class Literal(value: Any) - extends TermTree { - // todo: change hashcode generation to make this superfluous - override def hashCode(): int = if (value == null) 0 else value.hashCode() * 41 + 17; + case class Literal(value: Constant) + extends TermTree { + assert(value != null) } + def Literal(value: Any): Literal = Literal(Constant(value)); + /** General type term, introduced by RefCheck. */ case class TypeTree() extends TypTree { override def isEmpty = tpe == null || tpe == NoType; @@ -484,7 +485,7 @@ abstract class Trees: Global { def This(tree: Tree, qual: Name): This; def Select(tree: Tree, qualifier: Tree, selector: Name): Select; def Ident(tree: Tree, name: Name): Ident; - def Literal(tree: Tree, value: Any): Literal; + def Literal(tree: Tree, value: Constant): Literal; def TypeTree(tree: Tree): TypeTree; def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree; def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree; @@ -559,7 +560,7 @@ abstract class Trees: Global { new Select(qualifier, selector).copyAttrs(tree); def Ident(tree: Tree, name: Name) = new Ident(name).copyAttrs(tree); - def Literal(tree: Tree, value: Any) = + def Literal(tree: Tree, value: Constant) = new Literal(value).copyAttrs(tree); def TypeTree(tree: Tree) = new TypeTree().copyAttrs(tree); @@ -740,7 +741,7 @@ abstract class Trees: Global { if ((name0 == name)) => t case _ => copy.Ident(tree, name) } - def Literal(tree: Tree, value: Any) = tree match { + def Literal(tree: Tree, value: Constant) = tree match { case t @ Literal(value0) if (value0 == value) => t case _ => copy.Literal(tree, value) diff --git a/sources/scala/tools/nsc/ast/parser/Parsers.scala b/sources/scala/tools/nsc/ast/parser/Parsers.scala index 6802f83930..79bc2b024c 100755 --- a/sources/scala/tools/nsc/ast/parser/Parsers.scala +++ b/sources/scala/tools/nsc/ast/parser/Parsers.scala @@ -120,7 +120,7 @@ abstract class Parsers: SyntaxAnalyzer { } def errorTypeTree = TypeTree().setType(ErrorType).setPos(in.pos); - def errorTermTree = Literal(null).setPos(in.pos); + def errorTermTree = Literal(Constant(null)).setPos(in.pos); def errorPatternTree = Ident(nme.WILDCARD).setPos(in.pos); /////// TOKEN CLASSES ////////////////////////////////////////////////////// @@ -184,7 +184,7 @@ abstract class Parsers: SyntaxAnalyzer { params case Ident(_) | Typed(Ident(_), _) => List(convertToParam(t)); - case Literal(x) if x == () => //todo: check with Literal(()) + case Literal(c) if c.tag == UnitTag => //todo: check with Literal(Constant()) Nil case _ => syntaxError(t.pos, "malformed formal parameter list", false); @@ -395,23 +395,23 @@ abstract class Parsers: SyntaxAnalyzer { Literal( in.token match { case CHARLIT => - in.intVal.asInstanceOf[char] + Constant(in.intVal.asInstanceOf[char]) case INTLIT => - in.intVal(isNegated).asInstanceOf[int] + Constant(in.intVal(isNegated).asInstanceOf[int]) case LONGLIT => - in.intVal(isNegated) + Constant(in.intVal(isNegated)) case FLOATLIT => - in.floatVal(isNegated).asInstanceOf[float] + Constant(in.floatVal(isNegated).asInstanceOf[float]) case DOUBLELIT => - in.floatVal(isNegated) + Constant(in.floatVal(isNegated)) case STRINGLIT | SYMBOLLIT => - in.name.toString() + Constant(in.name.toString()) case TRUE => - true + Constant(true) case FALSE => - false + Constant(false) case NULL => - null + Constant(null) case _ => syntaxError("illegal literal", true); null diff --git a/sources/scala/tools/nsc/matching/CodeFactory.scala b/sources/scala/tools/nsc/matching/CodeFactory.scala index 0e81abdcaf..3fa733fbec 100644 --- a/sources/scala/tools/nsc/matching/CodeFactory.scala +++ b/sources/scala/tools/nsc/matching/CodeFactory.scala @@ -97,18 +97,18 @@ abstract class CodeFactory: TransMatcher { def Negate(tree: Tree) = tree match { - case Literal(value:Boolean)=> - Literal(!value) + case Literal(Constant(value:Boolean))=> + Literal(Constant(!value)) case _ => Apply(Select(tree, definitions.Boolean_not), List()); } /*protected*/ def And(left: Tree, right: Tree): Tree = left match { - case Literal(value:Boolean) => + case Literal(Constant(value:Boolean)) => if(value) right else left; case _ => right match { - case Literal(true) => + case Literal(Constant(true)) => left; case _ => Apply(Select(left, definitions.Boolean_and), List(right)); @@ -116,11 +116,11 @@ abstract class CodeFactory: TransMatcher { } /*protected*/ def Or(left: Tree, right: Tree): Tree = left match { - case Literal(value: Boolean)=> + case Literal(Constant(value: Boolean))=> if(value) left else right; case _ => right match { - case Literal(false) => + case Literal(Constant(false)) => left; case _ => Apply(Select(left, definitions.Boolean_or), List(right)); diff --git a/sources/scala/tools/nsc/matching/PatternMatcher.scala b/sources/scala/tools/nsc/matching/PatternMatcher.scala index d087131480..1e4dfabf3a 100644 --- a/sources/scala/tools/nsc/matching/PatternMatcher.scala +++ b/sources/scala/tools/nsc/matching/PatternMatcher.scala @@ -249,7 +249,7 @@ trait PatternMatchers: (TransMatcher with PatternNodes) with PatternNodeCreator else pVariablePat(tree.pos, tree); - case Literal(value) => + case Literal(Constant(value)) => pConstantPat(tree.pos, tree.tpe, value); case Sequence(ts) => diff --git a/sources/scala/tools/nsc/matching/TransMatcher.scala b/sources/scala/tools/nsc/matching/TransMatcher.scala index 2f74cb7315..f829aa18db 100644 --- a/sources/scala/tools/nsc/matching/TransMatcher.scala +++ b/sources/scala/tools/nsc/matching/TransMatcher.scala @@ -7,7 +7,7 @@ package scala.tools.nsc.matching; /** Translation of pattern matching */ -abstract class TransMatcher +abstract class TransMatcher extends transform.Transform with PatternNodes with CodeFactory with PatternMatchers @@ -22,12 +22,17 @@ with WordAutoms with LeftTracers with RightTracers { - val global: Global; - import global._; import definitions._; import posAssigner.atPos; + val phaseName = "transmatcher"; + + protected def newTransformer(unit: global.CompilationUnit): global.Transformer = { + cunit = unit; + new TransMatch + } + /** container. classes AlgebraicMatcher and SequenceMatcher get input and * store their results in here. resembles the 'Memento' design pattern, * could also be named 'Liaison' @@ -117,17 +122,6 @@ with RightTracers { generatedVars; } - class TransMatchPhase(prev: Phase) extends StdPhase(prev) { - def name = "transmatcher"; - val global: TransMatcher.this.global.type = TransMatcher.this.global; - def apply(unit: CompilationUnit): unit = { - TransMatcher.this.cunit = unit; - unit.body = newTransMatcher.transform(unit.body); - } - } - - def newTransMatcher = new TransMatch(); - class TransMatch extends Transformer { def isRegular(pat:Tree): Boolean = pat match { diff --git a/sources/scala/tools/nsc/symtab/Constants.scala b/sources/scala/tools/nsc/symtab/Constants.scala new file mode 100755 index 0000000000..28955f6449 --- /dev/null +++ b/sources/scala/tools/nsc/symtab/Constants.scala @@ -0,0 +1,178 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author Martin Odersky + */ +// $Id$ +package scala.tools.nsc.symtab; + +import classfile.PickleFormat._; + +abstract class Constants: SymbolTable { + + import definitions._; + + final val UnitTag = LITERALunit - LITERAL; + final val BooleanTag = LITERALboolean - LITERAL; + final val ByteTag = LITERALbyte - LITERAL; + final val ShortTag = LITERALshort - LITERAL; + final val CharTag = LITERALchar - LITERAL; + final val IntTag = LITERALint - LITERAL; + final val LongTag = LITERALlong - LITERAL; + final val FloatTag = LITERALfloat - LITERAL; + final val DoubleTag = LITERALdouble - LITERAL; + final val StringTag = LITERALstring - LITERAL; + final val NullTag = LITERALnull - LITERAL; + final val ZeroTag = LITERALzero - LITERAL; + + case class Constant(value: Any) { + val tag: int = + if (value.isInstanceOf[unit]) UnitTag + else if (value.isInstanceOf[boolean]) BooleanTag + else if (value.isInstanceOf[byte]) ByteTag + else if (value.isInstanceOf[short]) ShortTag + else if (value.isInstanceOf[char]) CharTag + else if (value.isInstanceOf[int]) IntTag + else if (value.isInstanceOf[long]) LongTag + else if (value.isInstanceOf[float]) FloatTag + else if (value.isInstanceOf[double]) DoubleTag + else if (value.isInstanceOf[String]) StringTag + else if (value == null) NullTag + else throw new Error("bad constant value: " + value); + + def tpe: Type = tag match { + case UnitTag => UnitClass.tpe + case BooleanTag => BooleanClass.tpe + case ByteTag => ByteClass.tpe + case ShortTag => ShortClass.tpe + case CharTag => CharClass.tpe + case IntTag => IntClass.tpe + case LongTag => LongClass.tpe + case FloatTag => FloatClass.tpe + case DoubleTag => DoubleClass.tpe + case StringTag => StringClass.tpe + case NullTag => AllRefClass.tpe + } + + def booleanValue: boolean = + if (tag == BooleanTag) value.asInstanceOf$erased[boolean] + else throw new Error("value " + value + " is not a boolean"); + + def byteValue: byte = tag match { + case ByteTag => value.asInstanceOf$erased[byte] + case ShortTag => value.asInstanceOf$erased[short].asInstanceOf[byte] + case CharTag => value.asInstanceOf$erased[char].asInstanceOf[byte] + case IntTag => value.asInstanceOf$erased[int].asInstanceOf[byte] + case LongTag => value.asInstanceOf$erased[long].asInstanceOf[byte] + case FloatTag => value.asInstanceOf$erased[float].asInstanceOf[byte] + case DoubleTag => value.asInstanceOf$erased[double].asInstanceOf[byte] + case _ => throw new Error("value " + value + " is not a byte") + } + + def shortValue: short = tag match { + case ByteTag => value.asInstanceOf$erased[byte].asInstanceOf[short] + case ShortTag => value.asInstanceOf$erased[short] + case CharTag => value.asInstanceOf$erased[char].asInstanceOf[short] + case IntTag => value.asInstanceOf$erased[int].asInstanceOf[short] + case LongTag => value.asInstanceOf$erased[long].asInstanceOf[short] + case FloatTag => value.asInstanceOf$erased[float].asInstanceOf[short] + case DoubleTag => value.asInstanceOf$erased[double].asInstanceOf[short] + case _ => throw new Error("value " + value + " is not a short") + } + + def charValue: char = tag match { + case ByteTag => value.asInstanceOf$erased[byte].asInstanceOf[char] + case ShortTag => value.asInstanceOf$erased[short].asInstanceOf[char] + case CharTag => value.asInstanceOf$erased[char] + case IntTag => value.asInstanceOf$erased[int].asInstanceOf[char] + case LongTag => value.asInstanceOf$erased[long].asInstanceOf[char] + case FloatTag => value.asInstanceOf$erased[float].asInstanceOf[char] + case DoubleTag => value.asInstanceOf$erased[double].asInstanceOf[char] + case _ => throw new Error("value " + value + " is not a char") + } + + def intValue: int = tag match { + case ByteTag => value.asInstanceOf$erased[byte].asInstanceOf[int] + case ShortTag => value.asInstanceOf$erased[short].asInstanceOf[int] + case CharTag => value.asInstanceOf$erased[char].asInstanceOf[int] + case IntTag => value.asInstanceOf$erased[int] + case LongTag => value.asInstanceOf$erased[long].asInstanceOf[int] + case FloatTag => value.asInstanceOf$erased[float].asInstanceOf[int] + case DoubleTag => value.asInstanceOf$erased[double].asInstanceOf[int] + case _ => throw new Error("value " + value + " is not an int") + } + + def longValue: long = tag match { + case ByteTag => value.asInstanceOf$erased[byte].asInstanceOf[long] + case ShortTag => value.asInstanceOf$erased[short].asInstanceOf[long] + case CharTag => value.asInstanceOf$erased[char].asInstanceOf[long] + case IntTag => value.asInstanceOf$erased[int].asInstanceOf[long] + case LongTag => value.asInstanceOf$erased[long] + case FloatTag => value.asInstanceOf$erased[float].asInstanceOf[long] + case DoubleTag => value.asInstanceOf$erased[double].asInstanceOf[long] + case _ => throw new Error("value " + value + " is not a long") + } + + def floatValue: float = tag match { + case ByteTag => value.asInstanceOf$erased[byte].asInstanceOf[float] + case ShortTag => value.asInstanceOf$erased[short].asInstanceOf[float] + case CharTag => value.asInstanceOf$erased[char].asInstanceOf[float] + case IntTag => value.asInstanceOf$erased[int].asInstanceOf[float] + case LongTag => value.asInstanceOf$erased[long].asInstanceOf[float] + case FloatTag => value.asInstanceOf$erased[float] + case DoubleTag => value.asInstanceOf$erased[double].asInstanceOf[float] + case _ => throw new Error("value " + value + " is not a float") + } + def doubleValue: double = { + System.out.println("doubleValue " + tag + " " + value); + tag match { + case ByteTag => System.out.println("Byte"); value.asInstanceOf$erased[byte].asInstanceOf[double] + case ShortTag => System.out.println("Short"); value.asInstanceOf$erased[short].asInstanceOf[double] + case CharTag => System.out.println("Char"); value.asInstanceOf$erased[char].asInstanceOf[double] + case IntTag => System.out.println("Int"); value.asInstanceOf$erased[int].asInstanceOf[double] + case LongTag => System.out.println("Long"); value.asInstanceOf$erased[long].asInstanceOf[double] + case FloatTag => System.out.println("Float"); value.asInstanceOf$erased[float].asInstanceOf[double] + case DoubleTag => System.out.println("Double"); value.asInstanceOf$erased[double].asInstanceOf[double] + case _ => System.out.println("error"); throw new Error("value " + value + " is not a double") + }} +/* + def doubleValue: double = + if (tag == ByteTag) value.asInstanceOf$erased[byte].asInstanceOf[double] + else if (tag == ShortTag) value.asInstanceOf$erased[short].asInstanceOf[double] + else if (tag == CharTag) value.asInstanceOf$erased[char].asInstanceOf[double] + else if (tag == IntTag) value.asInstanceOf$erased[int].asInstanceOf[double] + else if (tag == LongTag) value.asInstanceOf$erased[long].asInstanceOf[double] + else if (tag == FloatTag) value.asInstanceOf$erased[float].asInstanceOf[double] + else if (tag == DoubleTag) value.asInstanceOf$erased[double].asInstanceOf[double] + else throw new Error("value " + value + " is not a double"); +*/ + /** Convert constant value to conform to given type */ + def convertTo(pt: Type): Constant = { + val target = pt.symbol; + if (target == tpe.symbol) + this + else if (target == ByteClass && ByteTag <= tag && tag <= IntTag && + -128 <= intValue && intValue <= 127) + Constant(byteValue) + else if (target == ShortClass && ByteTag <= tag && tag <= IntTag && + -32768 <= intValue && intValue <= 32767) + Constant(shortValue) + else if (target == CharClass && ByteTag <= tag && tag <= IntTag && + 0 <= intValue && intValue <= 65635) + Constant(charValue) + else if (target == IntClass && ByteTag <= tag && tag <= IntTag) + Constant(intValue) + else if (target == LongClass && ByteTag <= tag && tag <= LongTag) + Constant(longValue) + else if (target == FloatClass && ByteTag <= tag && tag <= FloatTag) + Constant(floatValue) + else if (target == DoubleClass && ByteTag <= tag && tag <= DoubleTag) + Constant(doubleValue) + else null + } + + def stringValue: String = if (value == null) "<null>" else value.toString(); + + override def hashCode(): int = if (value == null) 0 else value.hashCode() * 41 + 17; + } +} + diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala index 8a1f401e2d..2dab0dcab1 100755 --- a/sources/scala/tools/nsc/symtab/Definitions.scala +++ b/sources/scala/tools/nsc/symtab/Definitions.scala @@ -72,7 +72,8 @@ abstract class Definitions: SymbolTable { var MatchErrorModule: Symbol = _; def MatchError_fail = getMember(MatchErrorModule, "fail"); def MatchError_report = getMember(MatchErrorModule, "report"); - var CaseOpsModule: Symbol = _; + var ScalaRunTimeModule: Symbol = _; + def SeqFactory = getMember(ScalaRunTimeModule, "Seq"); var RepeatedParamClass: Symbol = _; var ByNameParamClass: Symbol = _; @@ -271,7 +272,7 @@ abstract class Definitions: SymbolTable { PredefModule = getModule("scala.Predef"); ConsoleModule = getModule("scala.Console"); MatchErrorModule = getModule("scala.MatchError"); - CaseOpsModule = getModule("scala.runtime.CaseOps"); + ScalaRunTimeModule = getModule("scala.runtime.ScalaRunTime"); RepeatedParamClass = newCovariantPolyClass( ScalaPackageClass, nme.REPEATED_PARAM_CLASS_NAME, tparam => typeRef(SeqClass.typeConstructor.prefix, SeqClass, List(tparam.typeConstructor))); diff --git a/sources/scala/tools/nsc/symtab/SymbolTable.scala b/sources/scala/tools/nsc/symtab/SymbolTable.scala index 81de817b43..910886a9dd 100755 --- a/sources/scala/tools/nsc/symtab/SymbolTable.scala +++ b/sources/scala/tools/nsc/symtab/SymbolTable.scala @@ -12,6 +12,7 @@ abstract class SymbolTable extends Names with Types with Scopes with Definitions + with Constants with InfoTransformers with StdNames { def settings: Settings; diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala index f31e572a7c..1c7a3cf3a9 100755 --- a/sources/scala/tools/nsc/symtab/Symbols.scala +++ b/sources/scala/tools/nsc/symtab/Symbols.scala @@ -144,6 +144,15 @@ abstract class Symbols: SymbolTable { /** Is this symbol locally defined? I.e. not accessed from outside `this' instance */ final def isLocal: boolean = owner.isTerm; + /** Is this symbol a constant? */ + final def isConstant: boolean = + isStable && (tpe match { + case ConstantType(_) => true + case PolyType(_, ConstantType(_)) => true + case MethodType(_, ConstantType(_)) => true + case _ => false + }); + /** Is this class locally defined? * A class is local, if * - it is anonymous, or diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala index 7dd9f40b0b..8a16b3a2c1 100755 --- a/sources/scala/tools/nsc/symtab/Types.scala +++ b/sources/scala/tools/nsc/symtab/Types.scala @@ -15,7 +15,7 @@ import Flags._; case NoPrefix => case ThisType(_) => case SingleType(pre, sym) => - case ConstantType(base, value) => + case ConstantType(value) => case TypeRef(pre, sym, args) => case TypeBounds(lo, hi) => case RefinedType(parents, defs) => @@ -594,14 +594,12 @@ abstract class Types: SymbolTable { class PackageClassInfoType(decls: Scope, clazz: Symbol) extends ClassInfoType(List(), decls, clazz); /** A class representing a constant type */ - case class ConstantType(base: Type, value: Any) extends SingletonType { - assert(base.symbol != UnitClass); - override def symbol: Symbol = base.symbol; - override def singleDeref: Type = base; - override def deconst: Type = base; - override def toString(): String = base.toString() + "(" + value + ")"; - override def hashCode(): int = if (value == null) 0 - else base.hashCode() * 41 + value.hashCode(); + case class ConstantType(value: Constant) extends SingletonType { + assert(value.tpe.symbol != UnitClass); + override def symbol: Symbol = value.tpe.symbol; + override def singleDeref: Type = value.tpe; + override def deconst: Type = value.tpe; + override def toString(): String = value.tpe.toString() + "(" + value.stringValue + ")"; } /** A class for named types of the form <prefix>.<sym.name>[args] @@ -869,7 +867,7 @@ abstract class Types: SymbolTable { /** Map this function over given type */ def mapOver(tp: Type): Type = tp match { - case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) => + case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) | ConstantType(_) => tp case SingleType(pre, sym) => if (sym.isPackageClass) tp // short path @@ -883,10 +881,6 @@ abstract class Types: SymbolTable { val supertp1 = this(supertp); if ((thistp1 eq thistp) && (supertp1 eq supertp)) tp else SuperType(thistp1, supertp1) - case ConstantType(base, value) => - val base1 = this(base); - if (base1 eq base) tp - else ConstantType(base1, value) case TypeRef(pre, sym, args) => val pre1 = this(pre); val args1 = List.mapConserve(args)(this); @@ -1139,8 +1133,8 @@ abstract class Types: SymbolTable { pre2 =:= sym1.owner.thisType) => true */ - case Pair(ConstantType(base1, value1), ConstantType(base2, value2)) => - base1 =:= base2 && value1 == value2 + case Pair(ConstantType(value1), ConstantType(value2)) => + value1 == value2 case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) => sym1 == sym2 && pre1 =:= pre2 && isSameTypes(args1, args2) case Pair(RefinedType(parents1, ref1), RefinedType(parents2, ref2)) => @@ -1197,11 +1191,11 @@ abstract class Types: SymbolTable { case Pair(_, NoType) => false case Pair(_, NoPrefix) => tp1.symbol.isPackageClass - case Pair(ThisType(_), ThisType(_)) => tp1 =:= tp2 - case Pair(ThisType(_), SingleType(_, _)) => tp1 =:= tp2 - case Pair(SingleType(_, _), ThisType(_)) => tp1 =:= tp2 - case Pair(SingleType(_, _), SingleType(_, _)) => tp1 =:= tp2 - case Pair(ConstantType(_, _), ConstantType(_, _)) => tp1 =:= tp2 + case Pair(ThisType(_), ThisType(_)) => tp1 =:= tp2 + case Pair(ThisType(_), SingleType(_, _)) => tp1 =:= tp2 + case Pair(SingleType(_, _), ThisType(_)) => tp1 =:= tp2 + case Pair(SingleType(_, _), SingleType(_, _)) => tp1 =:= tp2 + case Pair(ConstantType(_), ConstantType(_)) => tp1 =:= tp2 case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) => //System.out.println("isSubType " + tp1 + " " + tp2);//DEBUG @@ -1253,11 +1247,11 @@ abstract class Types: SymbolTable { /* todo: replace following with case Pair(ThisType(_), _) | Pair(SingleType(_, _), _) - | Pair(ConstantType(_, _), _) => + | Pair(ConstantType(_), _) => once patern matching bug is fixed */ case Pair(ThisType(_), _) => tp1.singleDeref <:< tp2 case Pair(SingleType(_, _), _) => tp1.singleDeref <:< tp2 - case Pair(ConstantType(_, _), _) => tp1.singleDeref <:< tp2 + case Pair(ConstantType(_), _) => tp1.singleDeref <:< tp2 case Pair(TypeRef(pre1, sym1, args1), _) => sym1 == AllClass && tp2 <:< AnyClass.tpe diff --git a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 7f3a5e47ad..a1da6db8fa 100755 --- a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -149,7 +149,7 @@ abstract class ClassfileParser { def getSuperClass(index: int): Symbol = if (index == 0) definitions.AnyClass else getClassSymbol(index); - def getLiteral(index: int): Constant = { + def getConstant(index: int): Constant = { if (index <= 0 || len <= index) errorBadIndex(index); var value = values(index); if (value == null) { @@ -314,21 +314,10 @@ abstract class ClassfileParser { sym.setFlag(DEPRECATED); in.skip(attrLen) case nme.ConstantValueATTR => - def cast(c: Constant, tp: Type): Any = { - val s = symtype.symbol; - if (s == definitions.ByteClass) c.value.asInstanceOf$erased[int].asInstanceOf$erased[byte] - else if (s == definitions.ShortClass) c.value.asInstanceOf$erased[int].asInstanceOf$erased[short] - else if (s == definitions.CharClass) c.value.asInstanceOf$erased[int].asInstanceOf$erased[char] - else if (s == definitions.IntClass) c.value.asInstanceOf$erased[int] - else if (s == definitions.LongClass) c.value.asInstanceOf$erased[long] - else if (s == definitions.FloatClass) c.value.asInstanceOf$erased[float] - else if (s == definitions.DoubleClass) c.value.asInstanceOf$erased[double] - else if (s == definitions.UnitClass) () - else if (s == definitions.BooleanClass) c.value.asInstanceOf$erased[int] != 0 - else c.value - } - val c = pool.getLiteral(in.nextChar()); - sym.setInfo(ConstantType(symtype, cast(c, symtype))) + val c = pool.getConstant(in.nextChar()); + val c1 = c convertTo symtype; + assert(c1 != null, "cannot convert " + c + " to " + symtype); + sym.setInfo(ConstantType(c1)); case nme.InnerClassesATTR => parseInnerClasses() case nme.ScalaSignatureATTR => diff --git a/sources/scala/tools/nsc/symtab/classfile/Constant.scala b/sources/scala/tools/nsc/symtab/classfile/Constant.scala deleted file mode 100755 index d1fb4f1a3d..0000000000 --- a/sources/scala/tools/nsc/symtab/classfile/Constant.scala +++ /dev/null @@ -1,13 +0,0 @@ -/* NSC -- new scala compiler - * Copyright 2005 LAMP/EPFL - * @author Martin Odersky - */ -// $Id$ -package scala.tools.nsc.symtab.classfile; - -/* A wrapper for constant values */ -case class Constant(value: Any) { - // todo: change hashcode generation to make this superfluous - override def hashCode(): int = if (value == null) 0 else value.hashCode() * 41 + 17; -} - diff --git a/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala b/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala index 4b763baa10..9aec7dc802 100755 --- a/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala +++ b/sources/scala/tools/nsc/symtab/classfile/PickleFormat.scala @@ -73,6 +73,7 @@ object PickleFormat { final val METHODtpe = 20; final val POLYtpe = 21; final val IMPLICITMETHODtpe = 22; + final val LITERAL = 23; // base line for literals final val LITERALunit = 24; final val LITERALboolean = 25; final val LITERALbyte = 26; diff --git a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala index 5c1c7dbe53..c31d7ec2bf 100755 --- a/sources/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/sources/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -45,7 +45,7 @@ abstract class Pickler extends SubComponent { class Pickle(rootName: Name, rootOwner: Symbol) extends PickleBuffer(new Array[byte](4096), -1, 0) { private var entries = new Array[AnyRef](256); private var ep = 0; - private val index = new HashMap[Any, int]; + private val index = new HashMap[AnyRef, int]; /** Is root in symbol.owner*? */ private def isLocal(sym: Symbol): boolean = @@ -94,8 +94,8 @@ abstract class Pickler extends SubComponent { putSymbol(sym) case SingleType(pre, sym) => putType(pre); putSymbol(sym) - case ConstantType(base, value) => - putType(base); putConstant(value) + case ConstantType(value) => + putConstant(value) case TypeRef(pre, sym, args) => putType(pre); putSymbol(sym); putTypes(args) case TypeBounds(lo, hi) => @@ -114,20 +114,16 @@ abstract class Pickler extends SubComponent { } private def putTypes(tps: List[Type]): unit = tps foreach putType; - private def putConstant(value: Any) = if (putEntry(Constant(value))) { - value match { - case str: String => putEntry(newTermName(str)) - case _ => - } - } + private def putConstant(c: Constant) = + if (putEntry(c) && c.tag == StringTag) putEntry(newTermName(c.stringValue)); // Phase 2 methods: Write all entries to byte array ------------------------------ private val buf = new PickleBuffer(new Array[byte](4096), -1, 0); /** Write a reference to object, i.e., the object's number in the index. */ - private def writeRef(ref: Any): unit = writeNat(index(ref)); - private def writeRefs(refs: List[Any]): unit = refs foreach writeRef; + private def writeRef(ref: AnyRef): unit = writeNat(index(ref)); + private def writeRefs(refs: List[AnyRef]): unit = refs foreach writeRef; /** Write name, owner, flags, and info of a symbol */ private def writeSymInfo(sym: Symbol): unit = { @@ -177,8 +173,8 @@ abstract class Pickler extends SubComponent { writeRef(sym); THIStpe case SingleType(pre, sym) => writeRef(pre); writeRef(sym); SINGLEtpe - case ConstantType(base, value) => - writeRef(base); writeRef(Constant(value)); + case ConstantType(value) => + writeRef(value); CONSTANTtpe case TypeRef(pre, sym, args) => writeRef(pre); writeRef(sym); writeRefs(args); TYPEREFtpe @@ -194,28 +190,13 @@ abstract class Pickler extends SubComponent { else METHODtpe case PolyType(tparams, restpe) => writeRef(restpe); writeRefs(tparams); POLYtpe - case Constant(null) => - LITERALnull - case Constant(x: unit) => - LITERALunit - case Constant(x: boolean) => - writeLong(if (x) 1 else 0); LITERALboolean - case Constant(x: byte) => - writeLong(x); LITERALbyte - case Constant(x: char) => - writeLong(x); LITERALchar - case Constant(x: short) => - writeLong(x); LITERALshort - case Constant(x: int) => - writeLong(x); LITERALint - case Constant(x: long) => - writeLong(x); LITERALlong - case Constant(x: float) => - writeLong(Float.floatToIntBits(x)); LITERALfloat - case Constant(x: double) => - writeLong(Double.doubleToLongBits(x)); LITERALdouble - case Constant(x: String) => - writeRef(newTermName(x)); LITERALstring + case c @ Constant(_) => + if (c.tag == BooleanTag) writeLong(if (c.booleanValue) 1 else 0) + else if (ByteTag <= c.tag && c.tag <= LongTag) writeLong(c.longValue) + else if (c.tag == FloatTag) writeLong(Float.floatToIntBits(c.floatValue)) + else if (c.tag == DoubleTag) writeLong(Double.doubleToLongBits(c.doubleValue)); + else if (c.tag == StringTag) writeRef(newTermName(c.stringValue)); + LITERAL + c.tag case _ => throw new FatalError("bad entry: " + entry + " " + entry.getClass());//debug } diff --git a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala index 70d555bd2f..c6de552619 100755 --- a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala +++ b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala @@ -141,7 +141,7 @@ abstract class UnPickler { case SINGLEtpe => singleType(readTypeRef(), readSymbolRef()) case CONSTANTtpe => - ConstantType(readTypeRef(), readConstantRef().value) + ConstantType(readConstantRef()) case TYPEREFtpe => // create a type-ref as found, without checks or rebinds new TypeRef(readTypeRef(), readSymbolRef(), until(end, readTypeRef)) {} diff --git a/sources/scala/tools/nsc/transform/InfoTransform.scala b/sources/scala/tools/nsc/transform/InfoTransform.scala new file mode 100755 index 0000000000..8026019d88 --- /dev/null +++ b/sources/scala/tools/nsc/transform/InfoTransform.scala @@ -0,0 +1,25 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author + */ +// $Id$ +package scala.tools.nsc.transform; + +/** A base class for transforms. + * A transform contains a compiler phase which applies a tree transformer. + */ +abstract class InfoTransform extends Transform { + + import global.{Symbol, Type, InfoTransformer, infoTransformers}; + + def transformInfo(sym: Symbol, tpe: Type): Type; + + class Phase(prev: scala.tools.nsc.Phase) extends super.Phase(prev) { + val infoTransformer = new InfoTransformer { + val phase = Phase.this; + def transform(sym: Symbol, tpe: Type): Type = transformInfo(sym, tpe); + } + infoTransformers.insert(infoTransformer) + } +} + diff --git a/sources/scala/tools/nsc/transform/UnCurry.scala b/sources/scala/tools/nsc/transform/UnCurry.scala new file mode 100755 index 0000000000..f1bc9027f4 --- /dev/null +++ b/sources/scala/tools/nsc/transform/UnCurry.scala @@ -0,0 +1,131 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author + */ +// $Id$ +package scala.tools.nsc.transform; + +/*<export>*/ +/** - uncurry all symbol and tree types (@see UnCurryPhase) + * - for every curried parameter list: (ps_1) ... (ps_n) ==> (ps_1, ..., ps_n) + * - for every curried application: f(args_1)...(args_n) ==> f(args_1, ..., args_n) + * - for every type application: f[Ts] ==> f[Ts]() unless followed by parameters + * - for every use of a parameterless function: f ==> f() and q.f ==> q.f() + * - for every def-parameter: x: => T ==> x: () => T + * - for every use of a def-parameter: x ==> x.apply() + * - for every argument to a def parameter `x: => T': + * if argument is not a reference to a def parameter: + * convert argument `e' to (expansion of) `() => e' + * - for every repated parameter `x: T*' --> x: Seq[a]. + * - for every argument list that corresponds to a repeated parameter + * (a_1, ..., a_n) => (Seq(a_1, ..., a_n)) + * - for every argument list that is an escaped sequence + * (a_1:_*) => (a_1) + * - convert implicit method types to method types + * - todo: check-no-double-def in erasure + */ +/*</export>*/ +abstract class UnCurry extends InfoTransform { + import global._; // the global environment + import definitions._; // standard classes and methods + import typer.{typed}; // methods to type trees + import posAssigner.atPos; // for filling in tree positions + + protected val phaseName: String = "uncurry"; + protected def newTransformer(unit: CompilationUnit): Transformer = new UnCurryTransformer(unit); + + private val uncurry = new TypeMap { + def apply(tp: Type): Type = tp match { + case MethodType(formals, MethodType(formals1, restpe)) => + apply(MethodType(formals ::: formals1, restpe)) + case mt: ImplicitMethodType => + apply(MethodType(mt.paramTypes, mt.resultType)) + case PolyType(List(), restpe) => + apply(MethodType(List(), restpe)) + case PolyType(tparams, restpe) => + PolyType(tparams, apply(MethodType(List(), restpe))) + case TypeRef(pre, sym, List(arg)) if (sym == ByNameParamClass) => + apply(functionType(List(), arg)) + case TypeRef(pre, sym, args) if (sym == RepeatedParamClass) => + apply(TypeRef(pre, SeqClass, args)); + case _ => + mapOver(tp) + } + } + + /** - return symbol's transformed type, + * - if symbol is a def parameter with transformed type T, return () => T + */ + def transformInfo(sym: Symbol, tp: Type): Type = uncurry(tp); + + class UnCurryTransformer(unit: CompilationUnit) extends Transformer { + + private var inPattern = false; + + override def transform(tree: Tree): Tree = { + def transformArgs(args: List[Tree], formals: List[Type]) = { + if (formals.isEmpty) { + assert(args.isEmpty); List() + } else { + def mkSequence(args: List[Tree], pt: Type): Tree = typed { atPos(tree.pos) { + if (inPattern) Sequence(args) setType pt + else Apply(gen.mkRef(SeqFactory), args) + }} + val args1 = + formals.last match { + case TypeRef(pre, sym, List(pt)) if (sym == RepeatedParamClass) => + if (args.isEmpty) List(mkSequence(args, pt)) + else { + val suffix = args.last match { + case Typed(arg, Ident(name)) if name == nme.WILDCARD_STAR.toTypeName => + arg setType seqType(arg.tpe) + case _ => + mkSequence(args.drop(formals.length - 1), pt) + } + args.take(formals.length - 1) ::: List(suffix) + } + case _ => args + } + List.map2(formals, args1) ((formal, arg) => + if (formal.symbol == ByNameParamClass) + arg.tpe match { + case TypeRef(pre, sym, List(targ)) if (sym == ByNameParamClass) => + arg setType functionType(List(), targ) + case _ => + typed(Function(List(), arg) setPos arg.pos) + } + else arg) + } + } + val prevtpe = tree.tpe; + var result = tree match { + case Apply(fn, args) => + copy.Apply(tree, super.transform(fn), + super.transformTrees(transformArgs(args, fn.tpe.paramTypes))) + case CaseDef(pat, guard, body) => + inPattern = true; + val pat1 = super.transform(pat); + inPattern = false; + copy.CaseDef(tree, pat1, super.transform(guard), super.transform(body)) + case _ => + super.transform(tree) + } setType uncurry(tree.tpe); + result match { + case Apply(Apply(fn, args), args1) => + result = copy.Apply(result, fn, args ::: args1) + case Ident(name) => + if (name == nme.WILDCARD_STAR.toTypeName) + unit.error(tree.pos, " argument does not correspond to `*'-parameter"); + else if (prevtpe.symbol == ByNameParamClass) + result = typed(atPos(result.pos)(Select(result, nme.apply))) + case _ => + } + result.tpe match { + case MethodType(List(), restpe) => + if (!prevtpe.isInstanceOf[MethodType]) + result = typed(atPos(result.pos)(Apply(result, List()))) + } + result + } + } +} diff --git a/sources/scala/tools/nsc/typechecker/ConstantFolder.scala b/sources/scala/tools/nsc/typechecker/ConstantFolder.scala index 3a78775393..7883246424 100755 --- a/sources/scala/tools/nsc/typechecker/ConstantFolder.scala +++ b/sources/scala/tools/nsc/typechecker/ConstantFolder.scala @@ -11,187 +11,134 @@ abstract class ConstantFolder { import global._; import definitions._; - private val NoValue = new Object(); - /** If tree is a constant operation, replace with result. */ def apply(tree: Tree): Tree = fold(tree, tree match { case Apply(Select(Literal(x), op), List(Literal(y))) => foldBinop(op, x, y) case Select(Literal(x), op) => foldUnop(op, x) - case _ => NoValue + case _ => null }); /** If tree is a constant value that can be converted to type `pt', perform the conversion */ def apply(tree: Tree, pt: Type): Tree = fold(tree, tree.tpe match { - case ConstantType(base, value) => foldTyped(value, pt) - case _ => NoValue + case ConstantType(x) => x convertTo pt + case _ => null }); - private def fold(tree: Tree, value: Any): Tree = - if (value != NoValue && value != ()) tree setType ConstantType(literalType(value), value) - else tree; + private def fold(tree: Tree, x: Constant): Tree = + if (x != null && x.tag != UnitTag) tree setType ConstantType(x) else tree; - private def foldUnop(op: Name, value: Any): Any = Pair(op, value) match { - case Pair(nme.ZNOT, x: boolean) => !x + private def foldUnop(op: Name, x: Constant): Constant = Pair(op, x.tag) match { + case Pair(nme.ZNOT, BooleanTag) => Constant(!x.booleanValue) - case Pair(nme.NOT , x: int ) => ~x - case Pair(nme.NOT , x: long ) => ~x + case Pair(nme.NOT , IntTag ) => Constant(~x.intValue) + case Pair(nme.NOT , LongTag ) => Constant(~x.longValue) - case Pair(nme.ADD , x: int ) => +x - case Pair(nme.ADD , x: long ) => +x - case Pair(nme.ADD , x: float ) => +x - case Pair(nme.ADD , x: double ) => +x + case Pair(nme.ADD , IntTag ) => Constant(+x.intValue) + case Pair(nme.ADD , LongTag ) => Constant(+x.longValue) + case Pair(nme.ADD , FloatTag ) => Constant(+x.floatValue) + case Pair(nme.ADD , DoubleTag ) => Constant(+x.doubleValue) - case Pair(nme.SUB , x: int ) => -x - case Pair(nme.SUB , x: long ) => -x - case Pair(nme.SUB , x: float ) => -x - case Pair(nme.SUB , x: double ) => -x + case Pair(nme.SUB , IntTag ) => Constant(-x.intValue) + case Pair(nme.SUB , LongTag ) => Constant(-x.longValue) + case Pair(nme.SUB , FloatTag ) => Constant(-x.floatValue) + case Pair(nme.SUB , DoubleTag ) => Constant(-x.doubleValue) - case _ => NoValue + case _ => null } - private def foldBinop(op: Name, lvalue: Any, rvalue: Any): Any = Triple(op, lvalue, rvalue) match { - case Triple(nme.ZOR , x: boolean, y: boolean) => x | y - case Triple(nme.OR , x: boolean, y: boolean) => x | y - case Triple(nme.OR , x: int , y: int ) => x | y - case Triple(nme.OR , x: long , y: long ) => x | y - - case Triple(nme.XOR , x: boolean, y: boolean) => x ^ y - case Triple(nme.XOR , x: int , y: int ) => x ^ y - case Triple(nme.XOR , x: long , y: long ) => x ^ y - - case Triple(nme.ZAND, x: boolean, y: boolean) => x & y - case Triple(nme.AND , x: boolean, y: boolean) => x & y - case Triple(nme.AND , x: int , y: int ) => x & y - case Triple(nme.AND , x: long , y: long ) => x & y - - case Triple(nme.LSL , x: int , y: int ) => x << y - case Triple(nme.LSL , x: long , y: int ) => x << y - case Triple(nme.LSL , x: long , y: long ) => x << y - - case Triple(nme.LSR , x: int , y: int ) => x >>> y - case Triple(nme.LSR , x: long , y: int ) => x >>> y - case Triple(nme.LSR , x: long , y: long ) => x >>> y - - case Triple(nme.ASR , x: int , y: int ) => x >> y - case Triple(nme.ASR , x: long , y: int ) => x >> y - case Triple(nme.ASR , x: long , y: long ) => x >> y - - case Triple(nme.EQ , x: boolean, y: boolean) => x == y - case Triple(nme.EQ , x: int , y: int ) => x == y - case Triple(nme.EQ , x: long , y: long ) => x == y - case Triple(nme.EQ , x: float , y: float ) => x == y - case Triple(nme.EQ , x: double , y: double ) => x == y - - case Triple(nme.NE , x: boolean, y: boolean) => x != y - case Triple(nme.NE , x: int , y: int ) => x != y - case Triple(nme.NE , x: long , y: long ) => x != y - case Triple(nme.NE , x: float , y: float ) => x != y - case Triple(nme.NE , x: double , y: double ) => x != y - - case Triple(nme.LT , x: int , y: int ) => x < y - case Triple(nme.LT , x: long , y: long ) => x < y - case Triple(nme.LT , x: float , y: float ) => x < y - case Triple(nme.LT , x: double , y: double ) => x < y - - case Triple(nme.GT , x: int , y: int ) => x > y - case Triple(nme.GT , x: long , y: long ) => x > y - case Triple(nme.GT , x: float , y: float ) => x > y - case Triple(nme.GT , x: double , y: double ) => x > y - - case Triple(nme.LE , x: int , y: int ) => x <= y - case Triple(nme.LE , x: long , y: long ) => x <= y - case Triple(nme.LE , x: float , y: float ) => x <= y - case Triple(nme.LE , x: double , y: double ) => x <= y - - case Triple(nme.GE , x: int , y: int ) => x >= y - case Triple(nme.GE , x: long , y: long ) => x >= y - case Triple(nme.GE , x: float , y: float ) => x >= y - case Triple(nme.GE , x: double , y: double ) => x >= y - - case Triple(nme.ADD , x: int , y: int ) => x + y - case Triple(nme.ADD , x: long , y: long ) => x + y - case Triple(nme.ADD , x: float , y: float ) => x + y - case Triple(nme.ADD , x: double , y: double ) => x + y - case Triple(nme.ADD , x: String , y: String ) => x + y - - case Triple(nme.SUB , x: int , y: int ) => x - y - case Triple(nme.SUB , x: long , y: long ) => x - y - case Triple(nme.SUB , x: float , y: float ) => x - y - case Triple(nme.SUB , x: double , y: double ) => x - y - - case Triple(nme.MUL , x: int , y: int ) => x * y - case Triple(nme.MUL , x: long , y: long ) => x * y - case Triple(nme.MUL , x: float , y: float ) => x * y - case Triple(nme.MUL , x: double , y: double ) => x * y - - case Triple(nme.DIV , x: int , y: int ) => x / y - case Triple(nme.DIV , x: long , y: long ) => x / y - case Triple(nme.DIV , x: float , y: float ) => x / y - case Triple(nme.DIV , x: double , y: double ) => x / y - - case Triple(nme.MOD , x: int , y: int ) => x % y - case Triple(nme.MOD , x: long , y: long ) => x % y - case Triple(nme.MOD , x: float , y: float ) => x % y - case Triple(nme.MOD , x: double , y: double ) => x % y - - case _ => NoValue - } - - /** Widen constant value to conform to given type */ - private def foldTyped(value: Any, pt: Type): Any = { - val target = pt.symbol; - value match { - case x: byte => - if (target == ShortClass) x.asInstanceOf[short] - else if (target == CharClass) x.asInstanceOf[char] - else if (target == IntClass) x.asInstanceOf[int] - else if (target == LongClass) x.asInstanceOf[long] - else if (target == FloatClass) x.asInstanceOf[float] - else if (target == DoubleClass) x.asInstanceOf[double] - else NoValue - case x: short => - if (target == IntClass) x.asInstanceOf[int] - else if (target == LongClass) x.asInstanceOf[long] - else if (target == FloatClass) x.asInstanceOf[float] - else if (target == DoubleClass) x.asInstanceOf[double] - else NoValue - case x: char => - if (target == IntClass) x.asInstanceOf[int] - else if (target == LongClass) x.asInstanceOf[long] - else if (target == FloatClass) x.asInstanceOf[float] - else if (target == DoubleClass) x.asInstanceOf[double] - else NoValue - case x: int => - if (target == ByteClass && -128 <= x && x <= 127) x.asInstanceOf[byte] - else if (target == ShortClass && -32768 <= x && x <= 32767) x.asInstanceOf[short] - else if (target == CharClass && 0 <= x && x <= 65535) x.asInstanceOf[char] - else if (target == LongClass) x.asInstanceOf[long] - else if (target == FloatClass) x.asInstanceOf[float] - else if (target == DoubleClass) x.asInstanceOf[double] - else NoValue - case x: long => - if (target == FloatClass) x.asInstanceOf[float] - else if (target == DoubleClass) x.asInstanceOf[double] - else NoValue - case x: float => - if (target == DoubleClass) x.asInstanceOf[double] - else NoValue - case x => - NoValue + private def foldBinop(op: Name, x: Constant, y: Constant): Constant = { + val optag = if (x.tag > y.tag) x.tag else y.tag; + optag match { + case BooleanTag => + op match { + case nme.ZOR => Constant(x.booleanValue | y.booleanValue) + case nme.OR => Constant(x.booleanValue | y.booleanValue) + case nme.XOR => Constant(x.booleanValue ^ y.booleanValue) + case nme.ZAND => Constant(x.booleanValue & y.booleanValue) + case nme.AND => Constant(x.booleanValue & y.booleanValue) + case nme.EQ => Constant(x.booleanValue == y.booleanValue) + case nme.NE => Constant(x.booleanValue != y.booleanValue) + case _ => null + } + case ByteTag | ShortTag | LongTag | IntTag => + op match { + case nme.OR => Constant(x.intValue | y.intValue) + case nme.XOR => Constant(x.intValue ^ y.intValue) + case nme.AND => Constant(x.intValue & y.intValue) + case nme.LSL => Constant(x.intValue << y.intValue) + case nme.LSR => Constant(x.intValue >>> y.intValue) + case nme.ASR => Constant(x.intValue >> y.intValue) + case nme.EQ => Constant(x.intValue == y.intValue) + case nme.NE => Constant(x.intValue != y.intValue) + case nme.LT => Constant(x.intValue < y.intValue) + case nme.GT => Constant(x.intValue > y.intValue) + case nme.LE => Constant(x.intValue <= y.intValue) + case nme.GE => Constant(x.intValue >= y.intValue) + case nme.ADD => Constant(x.intValue + y.intValue) + case nme.SUB => Constant(x.intValue - y.intValue) + case nme.MUL => Constant(x.intValue * y.intValue) + case nme.DIV => Constant(x.intValue / y.intValue) + case nme.MOD => Constant(x.intValue % y.intValue) + case _ => null + } + case LongTag => + op match { + case nme.OR => Constant(x.longValue | y.longValue) + case nme.XOR => Constant(x.longValue ^ y.longValue) + case nme.AND => Constant(x.longValue & y.longValue) + case nme.LSL => Constant(x.longValue << y.longValue) + case nme.LSR => Constant(x.longValue >>> y.longValue) + case nme.ASR => Constant(x.longValue >> y.longValue) + case nme.EQ => Constant(x.longValue == y.longValue) + case nme.NE => Constant(x.longValue != y.longValue) + case nme.LT => Constant(x.longValue < y.longValue) + case nme.GT => Constant(x.longValue > y.longValue) + case nme.LE => Constant(x.longValue <= y.longValue) + case nme.GE => Constant(x.longValue >= y.longValue) + case nme.ADD => Constant(x.longValue + y.longValue) + case nme.SUB => Constant(x.longValue - y.longValue) + case nme.MUL => Constant(x.longValue * y.longValue) + case nme.DIV => Constant(x.longValue / y.longValue) + case nme.MOD => Constant(x.longValue % y.longValue) + case _ => null + } + case FloatTag => + op match { + case nme.EQ => Constant(x.floatValue == y.floatValue) + case nme.NE => Constant(x.floatValue != y.floatValue) + case nme.LT => Constant(x.floatValue < y.floatValue) + case nme.GT => Constant(x.floatValue > y.floatValue) + case nme.LE => Constant(x.floatValue <= y.floatValue) + case nme.GE => Constant(x.floatValue >= y.floatValue) + case nme.ADD => Constant(x.floatValue + y.floatValue) + case nme.SUB => Constant(x.floatValue - y.floatValue) + case nme.MUL => Constant(x.floatValue * y.floatValue) + case nme.DIV => Constant(x.floatValue / y.floatValue) + case nme.MOD => Constant(x.floatValue % y.floatValue) + case _ => null + } + case DoubleTag => + op match { + case nme.EQ => Constant(x.doubleValue == y.doubleValue) + case nme.NE => Constant(x.doubleValue != y.doubleValue) + case nme.LT => Constant(x.doubleValue < y.doubleValue) + case nme.GT => Constant(x.doubleValue > y.doubleValue) + case nme.LE => Constant(x.doubleValue <= y.doubleValue) + case nme.GE => Constant(x.doubleValue >= y.doubleValue) + case nme.ADD => Constant(x.doubleValue + y.doubleValue) + case nme.SUB => Constant(x.doubleValue - y.doubleValue) + case nme.MUL => Constant(x.doubleValue * y.doubleValue) + case nme.DIV => Constant(x.doubleValue / y.doubleValue) + case nme.MOD => Constant(x.doubleValue % y.doubleValue) + case _ => null + } + case StringTag => + op match { + case nme.ADD => Constant(x.stringValue + y.stringValue) + case _ => null + } + case _ => + null } } - - def literalType(value: Any): Type = - if (value.isInstanceOf[unit]) UnitClass.tpe - else if (value.isInstanceOf[boolean]) BooleanClass.tpe - else if (value.isInstanceOf[byte]) ByteClass.tpe - else if (value.isInstanceOf[short]) ShortClass.tpe - else if (value.isInstanceOf[char]) CharClass.tpe - else if (value.isInstanceOf[int]) IntClass.tpe - else if (value.isInstanceOf[long]) LongClass.tpe - else if (value.isInstanceOf[float]) FloatClass.tpe - else if (value.isInstanceOf[double]) DoubleClass.tpe - else if (value.isInstanceOf[String]) StringClass.tpe - else if (value == null) AllRefClass.tpe - else throw new FatalError("unexpected literal value: " + value); } diff --git a/sources/scala/tools/nsc/typechecker/RefChecks.scala b/sources/scala/tools/nsc/typechecker/RefChecks.scala index f7e5b3e32d..344e606b3e 100755 --- a/sources/scala/tools/nsc/typechecker/RefChecks.scala +++ b/sources/scala/tools/nsc/typechecker/RefChecks.scala @@ -31,7 +31,6 @@ import transform.Transform; * unless they are defined in the class or a baseclass * different from java.lang.Object * - Calls to case factory methods are replaced by new's. - * - Function nodes are eliminated. */ abstract class RefChecks extends Transform { @@ -280,7 +279,7 @@ abstract class RefChecks extends Transform { case NoType => ; case NoPrefix => ; case ThisType(_) => ; - case ConstantType(_, _) => ; + case ConstantType(_) => ; case SingleType(pre, sym) => validateVariance(pre, variance) case TypeRef(pre, sym, args) => @@ -389,12 +388,12 @@ abstract class RefChecks extends Transform { val caseFields = clazz.caseFieldAccessors map gen.mkRef; typed( DefDef(method, vparamss => - if (caseFields.isEmpty) Literal(null) + if (caseFields.isEmpty) Literal(Constant(null)) else { var i = caseFields.length; - var cases = List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(null))); + var cases = List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(Constant(null)))); for (val field <- caseFields.reverse) { - i = i - 1; cases = CaseDef(Literal(i), EmptyTree, field) :: cases + i = i - 1; cases = CaseDef(Literal(Constant(i)), EmptyTree, field) :: cases } Match(Ident(vparamss.head.head), cases) })) @@ -402,26 +401,26 @@ abstract class RefChecks extends Transform { def caseArityMethod: Tree = { val method = syntheticMethod(nme.caseArity, FINAL, PolyType(List(), IntClass.tpe)); - typed(DefDef(method, vparamss => Literal(clazz.caseFieldAccessors.length))) + typed(DefDef(method, vparamss => Literal(Constant(clazz.caseFieldAccessors.length)))) } def caseNameMethod: Tree = { val method = syntheticMethod(nme.caseName, FINAL, PolyType(List(), StringClass.tpe)); - typed(DefDef(method, vparamss => Literal(clazz.name.decode))) + typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode)))) } def moduleToStringMethod: Tree = { val method = syntheticMethod(nme.toString_, FINAL, MethodType(List(), StringClass.tpe)); - typed(DefDef(method, vparamss => Literal(clazz.name.decode))) + typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode)))) } def tagMethod: Tree = { val method = syntheticMethod(nme.tag, FINAL, MethodType(List(), IntClass.tpe)); - typed(DefDef(method, vparamss => Literal(clazz.tag))) + typed(DefDef(method, vparamss => Literal(Constant(clazz.tag)))) } def forwardingMethod(name: Name): Tree = { - val target = getMember(CaseOpsModule, "_" + name); + val target = getMember(ScalaRunTimeModule, "_" + name); val method = syntheticMethod( name, 0, MethodType(target.tpe.paramTypes.tail, target.tpe.resultType)); typed(DefDef(method, vparamss => @@ -487,7 +486,7 @@ abstract class RefChecks extends Transform { mvar setFlag (PRIVATE | LOCAL | SYNTHETIC); sym.owner.info.decls.enter(mvar); } - val vdef = typed(ValDef(mvar, if (sym.isLocal) Literal(null) else EmptyTree)); + val vdef = typed(ValDef(mvar, if (sym.isLocal) Literal(Constant(null)) else EmptyTree)); // def m: T = { if (m$ == null) m$ = new m$class; m$ } sym.setFlag(METHOD | STABLE); @@ -497,7 +496,7 @@ abstract class RefChecks extends Transform { Block( List( If( - Apply(Select(Ident(mvar), nme.EQ), List(Literal(null))), + Apply(Select(Ident(mvar), nme.EQ), List(Literal(Constant(null)))), Assign(Ident(mvar), New(TypeTree(moduleType), List(List()))), EmptyTree)), Ident(mvar)))); @@ -570,76 +569,6 @@ abstract class RefChecks extends Transform { case TypeApply(fn, args) => checkBounds(fn.tpe.typeParams, args map (.tpe)); - case Function(vparams, body) => - /* Transform a function node (x_1,...,x_n) => body of type FunctionN[T_1, .., T_N, R] to - * - * class $anon() extends Object() with FunctionN[T_1, .., T_N, R] with ScalaObject { - * def apply(x_1: T_1, ..., x_N: T_n): R = body - * } - * new $anon() - * - * transform a function node (x => body) of type PartialFunction[T, R] where - * body = x match { case P_i if G_i => E_i }_i=1..n - * to: - * - * class $anon() extends Object() with PartialFunction[T, R] with ScalaObject { - * def apply(x: T): R = body; - * def isDefinedAt(x: T): boolean = x match { - * case P_1 if G_1 => true - * ... - * case P_n if G_n => true - * case _ => false - * } - * } - * new $anon() - * - * However, if one of the patterns P_i if G_i is a default pattern, generate instead - * - * def isDefinedAt(x: T): boolean = true - */ - result = { - val anonClass = - currentOwner.newAnonymousFunctionClass(tree.pos) setFlag (FINAL | SYNTHETIC); - anonClass setInfo ClassInfoType( - List(ObjectClass.tpe, tree.tpe, ScalaObjectClass.tpe), new Scope(), anonClass); - val targs = tree.tpe.typeArgs; - val applyMethod = anonClass.newMethod(tree.pos, nme.apply) - setFlag FINAL setInfo MethodType(targs.init, targs.last); - anonClass.info.decls enter applyMethod; - for (val vparam <- vparams) - vparam.symbol.owner = applyMethod; - var members = List( - DefDef(FINAL, nme.apply, List(), List(vparams), TypeTree(targs.last), body) - setSymbol applyMethod); - if (tree.tpe.symbol == PartialFunctionClass) { - val isDefinedAtMethod = anonClass.newMethod(tree.pos, nme.isDefinedAt) - setFlag FINAL setInfo MethodType(targs.init, BooleanClass.tpe); - anonClass.info.decls enter isDefinedAtMethod; - def idbody(idparam: Symbol) = body match { - case Match(_, cases) => - val substParam = new TreeSymSubstituter(List(vparams.head.symbol), List(idparam)); - def transformCase(cdef: CaseDef): CaseDef = - CaseDef(substParam(cdef.pat), substParam(cdef.guard), Literal(true)); - def isDefaultCase(cdef: CaseDef) = cdef match { - case CaseDef(Ident(nme.WILDCARD), EmptyTree, _) => true - case CaseDef(Bind(_, Ident(nme.WILDCARD)), EmptyTree, _) => true - case _ => false - } - if (cases exists 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; - } - typed( - atPos(tree.pos)( - Block( - List(ClassDef(anonClass, List(List()), List(List()), members)), - New(TypeTree(anonClass.tpe), List(List()))))) - } - case New(tpt) => enterReference(tree.pos, tpt.tpe.symbol); diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala index 075eeb7e60..027956badc 100755 --- a/sources/scala/tools/nsc/typechecker/Typers.scala +++ b/sources/scala/tools/nsc/typechecker/Typers.scala @@ -198,9 +198,9 @@ abstract class Typers: Analyzer { else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !sym.isValue) // (2) errorTree(tree, sym.toString() + " is not a value"); else if (sym.isStable && pre.isStable && tree.tpe.symbol != ByNameParamClass && - (pt.isStable || (mode & QUALmode) != 0 || sym.isModule)) // (3) + (pt.isStable || (mode & QUALmode) != 0 && !sym.isConstant || sym.isModule)) { // (3) tree.setType(singleType(pre, sym)) - else tree + } else tree } /** Perform the following adaptations of expression, pattern or type `tree' wrt to @@ -234,7 +234,7 @@ abstract class Typers: Analyzer { */ // def adapt(tree: Tree, mode: int, pt: Type): Tree = { private def adapt(tree: Tree, mode: int, pt: Type): Tree = tree.tpe match { - case ct @ ConstantType(base, value) if ((mode & TYPEmode) == 0 && (ct <:< pt)) => // (0) + case ct @ ConstantType(value) if ((mode & TYPEmode) == 0 && (ct <:< pt)) => // (0) copy.Literal(tree, value) case OverloadedType(pre, alts) if ((mode & FUNmode) == 0) => // (1) inferExprAlternative(tree, pt); @@ -447,8 +447,7 @@ abstract class Typers: Analyzer { val getter = sym.owner.info.decls.lookup(name).suchThat(.hasFlag(ACCESSOR)); val result = atPos(vdef.pos)( DefDef(getter, vparamss => - if ((mods & DEFERRED) != 0) EmptyTree - else stabilize(gen.mkRef(sym), sym.owner.thisType, EXPRmode, sym.tpe))); + if ((mods & DEFERRED) != 0) EmptyTree else typed(gen.mkRef(sym), EXPRmode, sym.tpe))); checkNoEscaping.privates(result.symbol, result.tpt); result } @@ -570,30 +569,94 @@ abstract class Typers: Analyzer { copy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe } - def typedFunction(fun: Function, mode: int, pt: Type): Function = { + /* Transform a function node (x_1,...,x_n) => body of type FunctionN[T_1, .., T_N, R] to + * + * class $anon() extends Object() with FunctionN[T_1, .., T_N, R] with ScalaObject { + * def apply(x_1: T_1, ..., x_N: T_n): R = body + * } + * new $anon() + * + * transform a function node (x => body) of type PartialFunction[T, R] where + * body = x match { case P_i if G_i => E_i }_i=1..n + * to: + * + * class $anon() extends Object() with PartialFunction[T, R] with ScalaObject { + * def apply(x: T): R = body; + * def isDefinedAt(x: T): boolean = x match { + * case P_1 if G_1 => true + * ... + * case P_n if G_n => true + * case _ => false + * } + * } + * new $anon() + * + * However, if one of the patterns P_i if G_i is a default pattern, generate instead + * + * def isDefinedAt(x: T): boolean = true + */ + def typedFunction(fun: Function, mode: int, pt: Type): Tree = { val Triple(clazz, argpts, respt) = - if (isFunctionType(pt) - || + 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) => - vparam match { - case ValDef(_, _, tpt, _) => - if (tpt.isEmpty) - tpt.tpe = - if (argpt == NoType) { error(vparam.pos, "missing parameter type"); ErrorType } - else 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 vparams1 = List.mapConserve(fun.vparams)(typedValDef); - val body1 = typed(fun.body, respt); - copy.Function(fun, vparams1, body1) - setType typeRef(clazz.tpe.prefix, clazz, (vparamSyms map (.tpe)) ::: List(body1.tpe)) + val vparams = List.mapConserve(fun.vparams)(typedValDef); + val body = typed(fun.body, respt); + val formals = vparamSyms map (.tpe); + val funtpe = typeRef(clazz.tpe.prefix, clazz, formals ::: List(body.tpe)); + val anonClass = context.owner.newAnonymousFunctionClass(fun.pos) setFlag (FINAL | SYNTHETIC); + anonClass setInfo ClassInfoType( + List(ObjectClass.tpe, funtpe, ScalaObjectClass.tpe), new Scope(), anonClass); + val applyMethod = anonClass.newMethod(fun.pos, nme.apply) + setFlag FINAL setInfo MethodType(formals, body.tpe); + anonClass.info.decls enter applyMethod; + for (val vparam <- vparamSyms) vparam.owner = applyMethod; + var members = List( + DefDef(FINAL, nme.apply, List(), List(vparams), TypeTree(body.tpe), body) + setSymbol applyMethod); + if (pt.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) = body match { + case Match(_, cases) => + val substParam = new TreeSymSubstituter(List(vparams.head.symbol), List(idparam)); + def transformCase(cdef: CaseDef): CaseDef = + CaseDef(substParam(cdef.pat.duplicate), + substParam(cdef.guard.duplicate), + Literal(true)); + def isDefaultCase(cdef: CaseDef) = cdef match { + case CaseDef(Ident(nme.WILDCARD), EmptyTree, _) => true + case CaseDef(Bind(_, Ident(nme.WILDCARD)), EmptyTree, _) => true + case _ => false + } + if (cases exists 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; + } + typed( + atPos(fun.pos)( + Block( + List(ClassDef(anonClass, List(List()), List(List()), members)), + Typed( + New(TypeTree(anonClass.tpe), List(List())), + TypeTree(funtpe))))) } def typedRefinement(stats: List[Tree]): List[Tree] = { @@ -916,8 +979,7 @@ abstract class Typers: Analyzer { copy.Bind(tree, name, body1) setSymbol vble setType pt case fun @ Function(_, _) => - newTyper(context.makeNewScope(tree, context.owner)) - .typedFunction(fun, mode, pt) + newTyper(context.makeNewScope(tree, context.owner)).typedFunction(fun, mode, pt) case Assign(lhs, rhs) => def isGetter(sym: Symbol) = sym.info match { @@ -1074,9 +1136,9 @@ abstract class Typers: Analyzer { else typedIdent(name); + // todo: try with case Literal(Constant(())) case Literal(value) => - tree setType - (if (value == ()) UnitClass.tpe else ConstantType(constfold.literalType(value), value)) + tree setType (if (value.tag == UnitTag) UnitClass.tpe else ConstantType(value)) case SingletonTypeTree(ref) => val ref1 = checkStable(typed(ref, EXPRmode | QUALmode, AnyRefClass.tpe)); @@ -1119,7 +1181,10 @@ abstract class Typers: Analyzer { //System.out.println("typing " + tree);//debug } val tree1 = if (tree.tpe != null) tree else typed1(tree, mode, pt); - if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt) + //System.out.println("typed " + tree1 + ":" + tree1.tpe);//DEBUG + val result = if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt); + //System.out.println("adpated " + tree1 + ":" + tree1.tpe + " to " + pt);//DEBUG + result } catch { case ex: TypeError => reportTypeError(tree.pos, ex); diff --git a/sources/scala/tools/nsc/typechecker/Variances.scala b/sources/scala/tools/nsc/typechecker/Variances.scala index 7257a6c832..9425e3ce04 100755 --- a/sources/scala/tools/nsc/typechecker/Variances.scala +++ b/sources/scala/tools/nsc/typechecker/Variances.scala @@ -64,7 +64,7 @@ abstract class Variances { /** Compute variance of type parameter `tparam' in type `tp'. */ def varianceInType(tp: Type)(tparam: Symbol): int = tp match { - case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) | ConstantType(_, _) => + case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) | ConstantType(_) => VARIANCES case SingleType(pre, sym) => cut(varianceInType(pre)(tparam)) diff --git a/sources/scala/xml/dtd/ContentModel.scala b/sources/scala/xml/dtd/ContentModel.scala index 970f5eb05f..4875dad14b 100644 --- a/sources/scala/xml/dtd/ContentModel.scala +++ b/sources/scala/xml/dtd/ContentModel.scala @@ -194,7 +194,7 @@ Console.println("ns = "+ns); */ def toString(sb:StringBuffer): StringBuffer = { sb.append("(#PCDATA|"); - r.match { + r match { case Alt(Eps, rs@_*) => ContentModel.toString(Alt(rs:_*):RegExp, sb); } sb.append(")*"); diff --git a/sources/scala/xml/parsing/ExternalSources.scala b/sources/scala/xml/parsing/ExternalSources.scala index 7d42d6ec6a..edffbf5556 100644 --- a/sources/scala/xml/parsing/ExternalSources.scala +++ b/sources/scala/xml/parsing/ExternalSources.scala @@ -13,7 +13,7 @@ import scala.io.Source; import java.net._; import java.io._; -trait ExternalSources : (MarkupParser with MarkupHandler) { +trait ExternalSources : (ExternalSources with MarkupParser with MarkupHandler) { private def externalSourceFromURL(url:URL): Source = { diff --git a/sources/scala/xml/parsing/MarkupHandler.scala b/sources/scala/xml/parsing/MarkupHandler.scala index 21710759d7..d2f35cc728 100644 --- a/sources/scala/xml/parsing/MarkupHandler.scala +++ b/sources/scala/xml/parsing/MarkupHandler.scala @@ -34,7 +34,7 @@ abstract class MarkupHandler extends AnyRef with Logged { var ent: Map[String, EntityDecl] = new HashMap[String, EntityDecl](); def lookupElemDecl(Label: String): ElemDecl = { - def lookup(xs:List[Decl]): ElemDecl = xs.match { + def lookup(xs:List[Decl]): ElemDecl = xs match { case (z @ ElemDecl(Label, _)) :: zs => return z; case _::zs => lookup(zs); case _ => return null diff --git a/sources/scala/xml/parsing/MarkupParser.scala b/sources/scala/xml/parsing/MarkupParser.scala index 012d8cbdaa..5a5d68aa89 100644 --- a/sources/scala/xml/parsing/MarkupParser.scala +++ b/sources/scala/xml/parsing/MarkupParser.scala @@ -650,7 +650,7 @@ abstract class MarkupParser: (MarkupParser with MarkupHandler) extends AnyRef wi def element1(pscope: NamespaceBinding): NodeSeq = { val pos = this.pos; val Tuple3(qname, aMap, scope) = xTag(pscope); - val Tuple2(pre, local) = Utility.prefix(qname).match { + val Tuple2(pre, local) = Utility.prefix(qname) match { case Some(p) => Pair(p,qname.substring(p.length()+1, qname.length())); case _ => Pair(null,qname); } diff --git a/sources/scala/xml/parsing/ValidatingMarkupHandler.scala b/sources/scala/xml/parsing/ValidatingMarkupHandler.scala index c81b2b8f3e..4ae195511c 100644 --- a/sources/scala/xml/parsing/ValidatingMarkupHandler.scala +++ b/sources/scala/xml/parsing/ValidatingMarkupHandler.scala @@ -37,7 +37,7 @@ abstract class ValidatingMarkupHandler extends MarkupHandler with Logged { val trans = dm.dfa.delta(qCurrent); log("advanceDFA(dm): "+dm); log("advanceDFA(trans): "+trans); - trans.get(ContentModel.ElemName(label)).match { + trans.get(ContentModel.ElemName(label)) match { case Some(qNew) => qCurrent = qNew case _ => reportValidationError(pos, "DTD says, wrong element, expected one of "+trans.keys.toString); } @@ -51,7 +51,7 @@ abstract class ValidatingMarkupHandler extends MarkupHandler with Logged { reportValidationError(pos, "this element should be "+rootLabel); } else { log(" checking node"); - declCurrent.contentModel.match { + declCurrent.contentModel match { case ANY => case EMPTY => |