diff options
author | buraq <buraq@epfl.ch> | 2005-05-27 17:57:30 +0000 |
---|---|---|
committer | buraq <buraq@epfl.ch> | 2005-05-27 17:57:30 +0000 |
commit | 958dd64c52fd7e1555b6d179474cfe1c6d025014 (patch) | |
tree | c6e0452882e218fe01acc9f31c6dd066f4cf11bc /sources | |
parent | c20c973f9fda2ed1833122132e84d83636df1a53 (diff) | |
download | scala-958dd64c52fd7e1555b6d179474cfe1c6d025014.tar.gz scala-958dd64c52fd7e1555b6d179474cfe1c6d025014.tar.bz2 scala-958dd64c52fd7e1555b6d179474cfe1c6d025014.zip |
hello
Diffstat (limited to 'sources')
-rw-r--r-- | sources/scala/tools/nsc/matching/CodeFactory.scala | 307 | ||||
-rw-r--r-- | sources/scala/tools/nsc/matching/PatternMatcher.scala | 379 | ||||
-rw-r--r-- | sources/scala/tools/nsc/matching/PatternNode.scala | 276 | ||||
-rw-r--r-- | sources/scala/tools/nsc/matching/PatternNodeCreator.scala | 18 | ||||
-rw-r--r-- | sources/scala/tools/nsc/matching/PatternUtil.scala | 19 | ||||
-rw-r--r-- | sources/scala/tools/nsc/matching/TransMatcher.scala | 6 | ||||
-rwxr-xr-x | sources/scala/tools/nsc/symtab/Definitions.scala | 15 |
7 files changed, 633 insertions, 387 deletions
diff --git a/sources/scala/tools/nsc/matching/CodeFactory.scala b/sources/scala/tools/nsc/matching/CodeFactory.scala index 99226d2bbd..fa2d2dfe95 100644 --- a/sources/scala/tools/nsc/matching/CodeFactory.scala +++ b/sources/scala/tools/nsc/matching/CodeFactory.scala @@ -3,6 +3,7 @@ */ package scala.tools.nsc.matching ; +import scala.tools.util.Position; abstract class CodeFactory extends PatternUtil { @@ -31,244 +32,164 @@ abstract class CodeFactory extends PatternUtil { return result ; } - /** returns `List[ Tuple2[ scala.Int, <elemType> ] ]' - def SeqTraceType( elemType: Type ): Type = { - definitions.LIST_TYPE(pairType(definitions.int_TYPE(), elemType)); - } - */ + /** returns code `<seqObj>.elements' */ + def newIterator( seqObj:Tree ): Tree = + Apply(Select(seqObj, newTermName("elements")), List()); - /** returns `Iterator[ elemType ]' - def _seqIterType( elemType: Type ): Type = { - definitions.ITERATOR_TYPE(elemType); - } - */ - - /** returns `<seqObj.elements>' */ - def newIterator( seqObj:Tree , elemType:Type ): Tree = { - typed( - Apply(Select(seqObj, Name("elements")), Nil) - ) - //gen.mkApply__(gen.Select(seqObj, definitions.ITERABLE_ELEMENTS())); - } - /** returns code `<seqObj>.elements' - * the parameter needs to have type attribute `Sequence[<elemType>]' - */ - def newIterator( seqObj:Tree ): Tree = { - newIterator( seqObj, getElemType_Sequence( seqObj.tpe )); - } + /** `it.next()' */ + def _next(iter: Tree) = + Apply(Select(iter, definitions.Iterator_next), List()); - /** returns A for T <: Sequence[ A ] - */ - def getElemType_Sequence( tpe: Type): Type = { - //System.err.println("getElemType_Sequence("+tpe.widen+")"); - val tpe1 = tpe.widen.baseType( definitions.IteratorClass ); - if( tpe1 == NoType ) - throw new ApplicationError("arg "+tpe+" not subtype of Seq[ A ]"); + /** `it.hasNext()' */ + def _hasNext(iter: Tree) = + Apply(Select(iter, definitions.Iterator_hasNext), List()); - return tpe1.typeArgs()( 0 ); - } - /** returns A for T <: Iterator[ A ] - */ - def getElemType_Iterator( tpe: Type ): Type = { - //System.err.println("getElemType_Iterator("+tpe+")"); + /** `!it.hasCur()' */ + def _not_hasNext( iter:Tree ) = + Apply(Select(_hasNext(iter), definitions.Boolean_not), List()); - val tpe1 = tpe.widen.baseType( definitions.IteratorClass ); - tpe1 match { - case Type.TypeRef(_,_,args) => - return args( 0 ); - case _ => - throw new ApplicationError("arg "+tpe+" not subtype of Iterator[ A ]"); - } + /** `trace.isEmpty' */ + def isEmpty( iter: Tree ): Tree = + Apply(Select(iter, definitions.List_isEmpty), List()); - } - /** `it.next()' - */ - def _next( iter: Tree ): Tree = { - gen.mkApply__(gen.Select(iter, definitions.ITERATOR_NEXT())); + def SeqTrace_headElem( arg: Tree ) = { // REMOVE SeqTrace + val t = Apply(Select(arg, definitions.List_head), List()); + Apply(Select(t, definitions.tupleField(2,2)),List()) } - /** `it.hasNext()' - */ - def _hasNext( iter: Tree ): Tree = { - gen.mkApply__(gen.Select(iter, definitions.ITERATOR_HASNEXT())); - } - - /** `!it.hasCur()' - */ - def _not_hasNext( iter:Tree ): Tree = { - gen.mkApply__(gen.Select(_hasNext(iter), definitions.BOOLEAN_NOT())); + def SeqTrace_headState( arg: Tree ) = { // REMOVE SeqTrace + val t = Apply(Select(arg, definitions.List_head), List()); + Apply(Select(t, definitions.tupleField(2,1)),List()) } - /** `trace.isEmpty' - */ - def isEmpty( iter: Tree ): Tree = { - gen.mkApply__(gen.Select(iter, definitions.LIST_ISEMPTY())); - } + def SeqTrace_tail( arg: Tree ): Tree = // REMOVE SeqTrace + Apply(Select(arg, definitions.List_tail), List()); - def SeqTrace_headElem( arg: Tree ): Tree = { // REMOVE SeqTrace - val t = gen.mkApply__(gen.Select(arg, definitions.LIST_HEAD())); - gen.mkApply__(gen.Select(t, definitions.TUPLE_FIELD(2, 2))); - } + /** `arg.head' */ + def SeqList_head( arg: Tree ) = + Apply(Select(arg, definitions.List_head), List()); - def SeqTrace_headState( arg: Tree ): Tree = { // REMOVE SeqTrace - val t = gen.mkApply__(gen.Select(arg, definitions.LIST_HEAD())); - gen.mkApply__(gen.Select(t, definitions.TUPLE_FIELD(2, 1))); + def Negate(tree: Tree) = tree match { + case Literal(value:Boolean)=> + Literal(!value) + case _ => + Apply(Select(tree, definitions.Boolean_not), List()); } - def SeqTrace_tail( arg: Tree ): Tree = { // REMOVE SeqTrace - gen.mkApply__(gen.Select(arg, definitions.LIST_TAIL())); - } - - /** `<seqlist>.head()' - */ - def SeqList_head( arg: Tree ): Tree = { - gen.mkApply__(gen.Select(arg, definitions.LIST_HEAD())); - } - - def Negate(tree: Tree): Tree = { - tree match { - case Literal(BOOLEAN(value))=> - gen.mkBooleanLit(tree.pos, !value); - case _ => - gen.mkApply__(gen.Select(tree, definitions.BOOLEAN_NOT())); - } - } - - /*protected*/ def And(left: Tree, right: Tree): Tree = { - left match { - case Literal(BOOLEAN(value)) => - return if(value) right else left; - case _ => - } - right match { - case Literal(BOOLEAN(value)) => - if (value) return left; - case _ => - } - gen.mkApply_V(gen.Select(left, definitions.BOOLEAN_AND()), Predef.Array[Tree](right)); + /*protected*/ def And(left: Tree, right: Tree): Tree = left match { + case Literal(value:Boolean) => + if(value) right else left; + case _ => + right match { + case Literal(true) => + left; + case _ => + Apply(Select(left, definitions.Boolean_and), List(right)); + } } - /*protected*/ def Or(left: Tree, right: Tree): Tree = { - left match { - case Literal(BOOLEAN(value))=> - return if(value) left else right; - case _ => - } - right match { - case Literal(BOOLEAN(value)) => - if (!value) return left; + /*protected*/ def Or(left: Tree, right: Tree): Tree = left match { + case Literal(value: Boolean)=> + if(value) left else right; case _ => - } - gen.mkApply_V(gen.Select(left, definitions.BOOLEAN_OR()), Predef.Array[Tree](right)); + right match { + case Literal(false) => + left; + case _ => + Apply(Select(left, definitions.Boolean_or), List(right)); + } } // used by Equals - private def getCoerceToInt(left: Type): Symbol = { - val sym = left.lookupNonPrivate(Names.coerce); + private def getCoerceToInt(left: Type): Symbol = { + val sym = left.nonPrivateMember( nme.coerce ); //assert sym != Symbol.NONE : Debug.show(left); - val syms = sym.alternativeSymbols(); - var i = 0; while( i < syms.length) { - syms(i).info() match { - case Type.MethodType(vparams, restpe) => - if (vparams.length == 0 && restpe.isSameAs(definitions.INT_TYPE())) - return syms(i); - case _ => + + sym.alternatives.find { + x => x.info match { + case MethodType(vparams, restpe) => + vparams.length == 0 && isSameType(restpe,definitions.IntClass.info) } - i = i + 1; - } - //assert false : Debug.show(left); - throw new ApplicationError(left); + }.get } // used by Equals private def getEqEq(left: Type, right: Type): Symbol = { - val sym = left.lookupNonPrivate(Names.EQEQ); + val sym = left.nonPrivateMember( nme.EQEQ ); + //assert sym != Symbol.NONE // : Debug.show(left) + "::" + Debug.show(left.members()); + var fun: Symbol = null; - var ftype:Type = definitions.ANY_TYPE(); - val syms = sym.alternativeSymbols(); - var i = 0; while(i < syms.length) { - val vparams = syms(i).valueParams(); - if (vparams.length == 1) { - val vptype = vparams(0).info(); - if (right.isSubType(vptype) && vptype.isSubType(ftype)) { - fun = syms(i); - ftype = vptype; + var ftype:Type = definitions.AnyClass.info; + + sym.alternatives.foreach { + x => + val vparams = x.info.paramTypes; + if (vparams.length == 1) { + val vptype = vparams(0); + if (isSubType(right, vptype) && isSubType(vptype, ftype)) { + fun = x; + ftype = vptype; + } } - } - i = i + 1 } //assert fun != null : Debug.show(sym.info()); fun; } - /*protected*/ def Equals(left1:Tree , right1:Tree ): Tree = { + def Equals(left1:Tree , right1:Tree ): Tree = { var left = left1; var right = right1; - val ltype = left.getType().widen; - var rtype = right.getType().widen; - if (ltype.isSameAs(rtype) - && (ltype.isSameAs(definitions.CHAR_TYPE()) - || ltype.isSameAs(definitions.BYTE_TYPE()) - || ltype.isSameAs(definitions.SHORT_TYPE()))) + val ltype = left.tpe.widen; + var rtype = right.tpe.widen; + if (isSameType(ltype, rtype) + && (isSameType(ltype, definitions.CharClass.info) + || isSameType(ltype,definitions.ByteClass.info) + || isSameType(ltype,definitions.ShortClass.info))) { - right = gen.mkApply__(gen.Select(right, getCoerceToInt(rtype))); - rtype = definitions.INT_TYPE(); + right = Apply(Select(right, getCoerceToInt(rtype)), List()); + rtype = definitions.IntClass.info; } val eqsym = getEqEq(ltype, rtype); - gen.mkApply_V(gen.Select(left, eqsym), Predef.Array[Tree](right)); - } - - /*protected*/ def ThrowMatchError(pos: Int, tpe: Type ): Tree = { - gen.mkApplyTV( - gen.mkGlobalRef(pos, definitions.MATCHERROR_FAIL()), - Predef.Array[Tree](gen.mkType(pos, tpe)), - Predef.Array[Tree]( - gen.mkStringLit(pos, unit.toString()), - gen.mkIntLit(pos, Position.line(pos)) - )); - } - - def ThrowMatchError(pos:int , tpe:Type , tree:Tree ): Tree = { - gen.mkApplyTV( - gen.mkGlobalRef(pos, definitions.MATCHERROR_REPORT()), - Predef.Array[Tree](gen.mkType(pos, tpe)), - Predef.Array[Tree]( - gen.mkStringLit(pos, unit.toString()), - gen.mkIntLit(pos, Position.line(pos)), - tree - )); - } - - def Error(pos: Int, tpe: Type): Tree = { - gen.mkApplyTV( - gen.mkGlobalRef(pos, definitions.MATCHERROR_FAIL()), - Predef.Array[Tree](gen.mkType(pos, tpe)), - Predef.Array[Tree]( - gen.mkStringLit(pos, unit.toString()), - gen.mkIntLit(pos, Position.line(pos)) - )); - } - - - def pairType(left: Type, right: Type): Type = { - definitions.TUPLE_TYPE(Predef.Array[Type] ( left, right ) ); - } - - def newPair(left: Tree, right: Tree): Tree = { - gen.New( - gen.mkApplyTV( - gen.mkPrimaryConstructorGlobalRef( pos, definitions.TUPLE_CLASS(2)), - Predef.Array[Type] ( left.getType(), right.getType() ), - Predef.Array[Tree] ( left, right ))); - } + Apply(Select(left, eqsym), List(right)); + } + + def ThrowMatchError(pos: Int, tpe: Type ) = + Apply( + gen.mkRef(definitions.MatchError_fail), + List( + Literal(unit.toString()), + Literal(Position.line(pos)) + ) + ); + + def ThrowMatchError(pos:int , tpe:Type , tree:Tree ) = + Apply( + gen.mkRef(definitions.MatchError_report), + List( + Literal(unit.toString()), + Literal(Position.line(pos)), + tree + ) + ); + + def Error(pos: Int, tpe: Type) = + ThrowMatchError(pos: Int, tpe: Type ); + + def newPair(left: Tree, right: Tree) = + New( + Apply( + gen.mkRef(definitions.TupleClass(2)), + List(left,right) + ) + ); } diff --git a/sources/scala/tools/nsc/matching/PatternMatcher.scala b/sources/scala/tools/nsc/matching/PatternMatcher.scala index c9d422e1a2..6215fde0ef 100644 --- a/sources/scala/tools/nsc/matching/PatternMatcher.scala +++ b/sources/scala/tools/nsc/matching/PatternMatcher.scala @@ -6,10 +6,14 @@ package scala.tools.nsc.matching ; -abstract class PatternMatch extends PatternUtil { +import scala.tools.util.Position; + +abstract class PatternMatcher extends PatternUtil with PatternNodes with PatternNodeCreator with CodeFactory { import global._; + import symtab.Flags; + protected var optimize = true; protected var delegateSequenceMatching = false; protected var doBinding = true; @@ -32,28 +36,41 @@ abstract class PatternMatch extends PatternUtil { /** methods to generate scala code */ - protected var cf: CodeFactory = _; + protected val cf: this.type = this; /** methods to create pattern nodes */ - protected var mk: PatternNodeCreator = _; + protected val mk: this.type = this; + def defs = definitions; /** init method, also needed in subclass AlgebraicMatcher */ def initialize(selector: Tree, owner: Symbol, resultType: Type, doBinding: Boolean): Unit = { - this.mk = new PatternNodeCreator(unit, owner); - this.cf = new CodeFactory(unit, selector.pos); - this.root = mk.ConstrPat(selector.pos, selector.getType().widen()); + + /* + this.mk = new PatternNodeCreator { + val global = PatternMatcher.this.global; + val unit = PatternMatcher.this.unit; + val owner = PatternMatcher.this.owner; + } + */ + /* + this.cf = new CodeFactory { + val global = PatternMatcher.this.global; + val unit = PatternMatcher.this.unit; + val owner = PatternMatcher.this.owner; + } + */ + this.root = mk.ConstrPat(selector.pos, selector.tpe.widen); this.root.and = mk.Header(selector.pos, - selector.getType().widen(), - gen.Ident(selector.pos, root.symbol())); - this.resultVar = owner.newVariable(selector.pos, - Modifiers.MUTABLE, - Names.result); - this.resultVar.setType(resultType); + selector.tpe.widen, + Ident(root.symbol)); + this.resultVar = owner.newVariable(Flags.MUTABLE, + "result"); + this.resultVar.setInfo(resultType); this.owner = owner; this.selector = selector; - this.optimize = this.optimize & (unit.global.target == Global.TARGET_JVM); + this.optimize = this.optimize & (settings.target == "jvm"); this.doBinding = doBinding; } @@ -65,6 +82,9 @@ abstract class PatternMatch extends PatternUtil { def print(patNode: PatternNode, indent: String, sb: StringBuffer): StringBuffer = { + def cont = if (patNode.or != null) print(patNode.or, indent, sb); else sb; + + def newIndent(s: String) = { val removeBar: Boolean = (null == patNode.or); val sb = new StringBuffer(); @@ -91,55 +111,50 @@ abstract class PatternMatch extends PatternUtil { print(patNode.or, indent + "|", sb); if (next != null) print(next, indent, sb); - + else + sb case ConstrPat(casted) => - val s = "-- " + patNode.getTpe().symbol().name + + val s = "-- " + patNode.getTpe().symbol.name + "(" + patNode.getTpe() + ", " + casted + ") -> "; val nindent = newIndent(s); sb.append(nindent + s).append('\n'); print(patNode.and, nindent, sb); - if (patNode.or != null) - print(patNode.or, indent, sb); + cont; case SequencePat( casted, plen ) => - val s = "-- " + patNode.getTpe().symbol().name + "(" + + val s = "-- " + patNode.getTpe().symbol.name + "(" + patNode.getTpe() + ", " + casted + ", " + plen + ") -> "; val nindent = newIndent(s); sb.append(indent + s).append('\n'); print(patNode.and, nindent, sb); - if (patNode.or != null) - print(patNode.or, indent, sb); + cont; case DefaultPat() => sb.append(indent + "-- _ -> ").append('\n'); print(patNode.and, indent.substring(0, indent.length() - 1) + " ", sb); - if (patNode.or != null) - print(patNode.or, indent, sb); + cont; case ConstantPat(value) => val s = "-- CONST(" + value + ") -> "; val nindent = newIndent(s); sb.append(indent + s).append('\n'); print(patNode.and, nindent, sb); - if (patNode.or != null) - print(patNode.or, indent, sb); + cont; case VariablePat(tree) => val s = "-- STABLEID(" + tree + ": " + patNode.getTpe() + ") -> "; val nindent = newIndent(s); sb.append(indent + s).append('\n'); print(patNode.and, nindent, sb); - if (patNode.or != null) - print(patNode.or, indent, sb); + cont; case AltPat(header) => sb.append(indent + "-- ALTERNATIVES:").append('\n'); print(header, indent + " * ", sb); print(patNode.and, indent + " * -> ", sb); - if (patNode.or != null) - print(patNode.or, indent, sb); + cont; case _b:Body => if ((_b.guard.length == 0) && (_b.body.length == 0)) @@ -161,9 +176,9 @@ abstract class PatternMatch extends PatternUtil { protected def enter(caseDef: Tree): Unit = { caseDef match { case CaseDef(pat, guard, body) => - val env = new CaseEnv(owner, unit); + val env = new CaseEnv; // PatternNode matched = match(pat, root); - val target = enter1(pat, -1, root, root.symbol(), env); + val target = enter1(pat, -1, root, root.symbol, env); // if (target.and != null) // unit.error(pat.pos, "duplicate case"); if (null == target.and) @@ -176,7 +191,7 @@ abstract class PatternMatch extends PatternUtil { } protected def updateBody(tree: Body, bound: Array[ValDef], guard: Tree , body: Tree): Unit = { - if (tree.guard(tree.guard.length - 1) == Tree.Empty) { + if (tree.guard(tree.guard.length - 1) == EmptyTree) { //unit.error(body.pos, "unreachable code"); } else { val bd = new Array[Array[ValDef]](tree.bound.length + 1); @@ -194,7 +209,7 @@ abstract class PatternMatch extends PatternUtil { } } - protected def patternArgs(tree: Tree):Array[Tree] = { + protected def patternArgs(tree: Tree):List[Tree] = { tree match { case Bind(_, pat) => patternArgs(pat); @@ -207,13 +222,10 @@ abstract class PatternMatch extends PatternUtil { args; } else args - case Sequence(ts) => - if (!delegateSequenceMatching) - ts; - else - Tree.EMPTY_ARRAY; + case Sequence(ts) if (!delegateSequenceMatching) => + ts; case _ => - Tree.EMPTY_ARRAY; + List(); } } @@ -229,37 +241,37 @@ abstract class PatternMatch extends PatternUtil { * (( tree.args.length == 1 ) && tree.args(0).isInstanceOf[Sequence]) * but fails */ - protected def isSeqApply( tree: Tree.Apply ): Boolean = + protected def isSeqApply( tree: Apply ): Boolean = (( tree.args.length == 1 ) && tree.args(0).isInstanceOf[Sequence]) - && (tree.getType().symbol().flags & Modifiers.CASE) == 0; + && (tree.tpe.symbol.flags & Flags.CASE) == 0; protected def patternNode(tree:Tree , header:Header , env: CaseEnv ): PatternNode = { //Console.println("patternNode("+tree+","+header+")"); - //Console.println("tree.getType()"+tree.getType()); + //Console.println("tree.tpe"+tree.tpe); tree match { - case Bind(name, Typed(Ident(Names.PATTERN_WILDCARD), tpe)) => // x@_:Type - if (header.getTpe().isSubType(tpe.getType())) { - val node = mk.DefaultPat(tree.pos, tpe.getType()); - env.newBoundVar( tree.symbol(), tree.getType(), header.selector ); + case Bind(name, Typed(Ident( nme.WILDCARD ), tpe)) => // x@_:Type + if (isSubType(header.getTpe(),tpe.tpe)) { + val node = mk.DefaultPat(tree.pos, tpe.tpe); + env.newBoundVar( tree.symbol, tree.tpe, header.selector ); node; } else { - val node = mk.ConstrPat(tree.pos, tpe.getType()); - env.newBoundVar( tree.symbol(), tree.getType(), gen.Ident(tree.pos, node.casted)); + val node = mk.ConstrPat(tree.pos, tpe.tpe); + env.newBoundVar( tree.symbol, tree.tpe, Ident( node.casted )); node; } - case Bind(name, Ident(Names.PATTERN_WILDCARD)) => // x @ _ + case Bind(name, Ident(nme.WILDCARD)) => // x @ _ val node = mk.DefaultPat(tree.pos, header.getTpe()); - if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) - env.newBoundVar( tree.symbol(), tree.getType(), header.selector); + if ((env != null) && (tree.symbol != defs.PatternWildcard)) + env.newBoundVar( tree.symbol, tree.tpe, header.selector); node; case Bind(name, pat) => val node = patternNode(pat, header, env); - if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) { - val casted = node.symbol(); - val theValue = if (casted == Symbol.NONE) header.selector else gen.Ident(tree.pos, casted); - env.newBoundVar(tree.symbol(), tree.getType(), theValue); + if ((env != null) && (tree.symbol != defs.PatternWildcard)) { + val casted = node.symbol; + val theValue = if (casted == NoSymbol) header.selector else Ident( casted); + env.newBoundVar(tree.symbol, tree.tpe, theValue); } node; @@ -268,90 +280,92 @@ abstract class PatternMatch extends PatternUtil { if (!delegateSequenceMatching) { args(0) match { case Sequence(ts)=> - mk.SequencePat(tree.pos, tree.getType(), ts.length); + mk.SequencePat(tree.pos, tree.tpe, ts.length); } } else { - val res = mk.ConstrPat(tree.pos, tree.getType()); + val res = mk.ConstrPat(tree.pos, tree.tpe); res.and = mk.Header(tree.pos, header.getTpe(), header.selector); - res.and.and = mk.SeqContainerPat(tree.pos, tree.getType(), args(0)); + res.and.and = mk.SeqContainerPat(tree.pos, tree.tpe, args(0)); res; } - } else if ((fn.symbol() != null) && - fn.symbol().isStable() && - !(fn.symbol().isModule() && - ((fn.symbol().flags & Modifiers.CASE) != 0))) { + } else if ((fn.symbol != null) && + fn.symbol.isStable && + !(fn.symbol.isModule && + ((fn.symbol.flags & Flags.CASE) != 0))) { mk.VariablePat(tree.pos, tree); } else { /* Console.println("apply but not seqApply"); - Console.println("tree.getType()="+tree.getType()); - Console.println("tree.symbol()="+tree.symbol()); + Console.println("tree.tpe="+tree.tpe); + Console.println("tree.symbol="+tree.symbol); */ - mk.ConstrPat(tree.pos, tree.getType()); + mk.ConstrPat(tree.pos, tree.tpe); } case t @ Typed(ident, tpe) => // variable pattern - val doTest = header.getTpe().isSubType(tpe.getType()); + val doTest = isSubType(header.getTpe(),tpe.tpe); val node = { if(doTest) - mk.DefaultPat(tree.pos, tpe.getType()) + mk.DefaultPat(tree.pos, tpe.tpe) else - mk.ConstrPat(tree.pos, tpe.getType()); + mk.ConstrPat(tree.pos, tpe.tpe); } - if ((null != env) && (ident.symbol() != defs.PATTERN_WILDCARD)) + if ((null != env) && (ident.symbol != defs.PatternWildcard)) node match { case ConstrPat(casted) => - env.newBoundVar(t.expr.symbol(), - tpe.getType(), - gen.Ident(tree.pos, casted)); + env.newBoundVar(t.expr.symbol, + tpe.tpe, + Ident( casted )); case _ => - env.newBoundVar(t.expr.symbol(), - tpe.getType(), - {if(doTest) header.selector else gen.Ident(tree.pos, node.asInstanceOf[ConstrPat].casted)}); + env.newBoundVar(t.expr.symbol, + tpe.tpe, + {if(doTest) header.selector else Ident(node.asInstanceOf[ConstrPat].casted)}); } node; case Ident(name) => // pattern without args or variable - if (tree.symbol() == defs.PATTERN_WILDCARD) + if (tree.symbol == defs.PatternWildcard) mk.DefaultPat(tree.pos, header.getTpe()); - else if (tree.symbol().isPrimaryConstructor()) { - throw new ApplicationError("this may not happen"); // Burak - } else if (name.isVariable()) {// Burak - throw new ApplicationError("this may not happen"); // Burak + else if (tree.symbol.isPrimaryConstructor) { + error("error may not happen"); // Burak + null + } else if (treeInfo.isVariableName(name)) {// Burak + error("this may not happen"); // Burak + null } else mk.VariablePat(tree.pos, tree); case Select(_, name) => // variable - if (tree.symbol().isPrimaryConstructor()) - mk.ConstrPat(tree.pos, tree.getType()); + if (tree.symbol.isPrimaryConstructor) + mk.ConstrPat(tree.pos, tree.tpe); else mk.VariablePat(tree.pos, tree); case Literal(value) => - mk.ConstantPat(tree.pos, tree.getType(), value); + mk.ConstantPat(tree.pos, tree.tpe, value); case Sequence(ts) => if ( !delegateSequenceMatching ) { - //throw new ApplicationError("cannot happen:"+tree); - mk.SequencePat(tree.pos, tree.getType(), ts.length); + mk.SequencePat(tree.pos, tree.tpe, ts.length); } else { - mk.SeqContainerPat(tree.pos, tree.getType(), tree); + mk.SeqContainerPat(tree.pos, tree.tpe, tree); } case Alternative(ts) => if(ts.length < 2) - throw new ApplicationError("ill-formed Alternative"); + error("ill-formed Alternative"); val subroot = mk.ConstrPat(header.pos, header.getTpe()); - subroot.and = mk.Header(header.pos, header.getTpe(), header.selector.duplicate()); - val subenv = new CaseEnv(owner, unit); + subroot.and = mk.Header(header.pos, header.getTpe(), header.selector.duplicate); + val subenv = new CaseEnv; var i = 0; while(i < ts.length) { - val target = enter1(ts(i), -1, subroot, subroot.symbol(), subenv); + val target = enter1(ts(i), -1, subroot, subroot.symbol, subenv); target.and = mk.Body(tree.pos); i = i + 1 } mk.AltPat(tree.pos, subroot.and.asInstanceOf[Header]); case _ => - throw new ApplicationError("unit = " + unit + "; tree = "+tree); + error("unit = " + unit + "; tree = "+tree); + null } } @@ -368,25 +382,24 @@ abstract class PatternMatch extends PatternUtil { private def newHeader(pos: Int, casted: Symbol, index: Int): Header = { //Console.println("newHeader(pos,"+casted+","+index+")"); - //Console.println(" casted.getType()"+casted.getType()); - val ident = gen.Ident(pos, casted); + //Console.println(" casted.tpe"+casted.tpe); + val ident = Ident(casted); if (casted.pos == Position.FIRSTPOS) { //Console.println("FIRSTPOS"); - val t = gen.mkApply_V( - gen.Select( ident, defs.FUNCTION_APPLY( 1 )), - Predef.Array[Tree]( gen.mkIntLit( pos, index ) )); - val seqType = t.getType(); + val t = Apply(Select( ident, defs.functionApply( 1 )), + List( Literal( index ) )); + val seqType = t.tpe; mk.Header( pos, seqType, t ); } else { //Console.println("NOT FIRSTPOS"); - val ts = casted.getType().symbol().asInstanceOf[ClassSymbol] + val ts = casted.tpe.symbol.asInstanceOf[ClassSymbol] .caseFieldAccessor(index); //Console.println("ts="+ts); - val accType = casted.getType().memberType(ts); + val accType = casted.tpe.memberType(ts); val accTree = gen.Select( ident, ts); accType match { // scala case accessor - case Type.MethodType(_, _) => + case MethodType(_, _) => mk.Header(pos, accType.resultType(), gen.mkApply__(accTree)); // jaco case accessor case _ => @@ -405,7 +418,7 @@ abstract class PatternMatch extends PatternUtil { var curHeader = target.and.asInstanceOf[Header]; // advance one step in intermediate representation if (curHeader == null) { // check if we have to add a new header //assert index >= 0 : casted; - if (index < 0) throw new ApplicationError("error entering:" + casted); + if (index < 0) { error("error entering:" + casted); return null } target.and = {curHeader = newHeader(pat.pos, casted, index); curHeader}; curHeader.or = patternNode(pat, curHeader, env); enter(patArgs, curHeader.or, casted, env); @@ -423,8 +436,7 @@ abstract class PatternMatch extends PatternUtil { // substitute... !!! patNode match { case ConstrPat(ocasted) => - env.substitute(ocasted, gen.Ident(patNode.pos, - next.asInstanceOf[ConstrPat].casted)); + env.substitute(ocasted, Ident(next.asInstanceOf[ConstrPat].casted)); case _ => } return enter(patArgs, next, casted, env); @@ -447,14 +459,14 @@ abstract class PatternMatch extends PatternUtil { } else next = next.or; } - throw new ApplicationError("must not happen"); - null // never reached + error("must not happen"); + null } } /** calls enter for an array of patterns, see enter */ - protected def enter(pats:Array[Tree], target1: PatternNode , casted1: Symbol , env: CaseEnv): PatternNode = { + protected def enter(pats:List[Tree], target1: PatternNode , casted1: Symbol , env: CaseEnv): PatternNode = { var target = target1; var casted = casted1; target match { @@ -474,23 +486,23 @@ abstract class PatternMatch extends PatternUtil { protected def nCaseComponents(tree: Tree): int = { tree match { case Apply(fn, _) => - val tpe = tree.getType().symbol().primaryConstructor().getType(); - //Console.println("~~~ " + tree.type() + ", " + tree.type().symbol().primaryConstructor()); + val tpe = tree.tpe.symbol.primaryConstructor.tpe; + //Console.println("~~~ " + tree.type() + ", " + tree.type().symbol.primaryConstructor()); tpe match { // I'm not sure if this is a good idea, but obviously, currently all case classes // without constructor arguments have type NoType - case Type.NoType => - throw new ApplicationError("this cannot happen"); + case NoType => + error("this cannot happen"); 0 - case Type.MethodType(args, _) => + case MethodType(args, _) => args.length; - case Type.PolyType(tvars, Type.MethodType(args, _)) => + case PolyType(tvars, Type.MethodType(args, _)) => args.length; - case Type.PolyType(tvars, _) => + case PolyType(tvars, _) => 0; case _ => - throw new ApplicationError("not yet implemented;" + - "pattern matching for " + tree + ": " + tpe); + error("not yet implemented;" + + "pattern matching for " + tree + ": " + tpe); } } return 0; @@ -521,9 +533,9 @@ abstract class PatternMatch extends PatternUtil { while (({node = node.or; node}) != null) { node match { case VariablePat(tree) => - Console.println(((tree.symbol().flags & Modifiers.CASE) != 0)); + Console.println(((tree.symbol.flags & Flags.CASE) != 0)); case ConstrPat(_) => - Console.println(node.getTpe().toString() + " / " + ((node.getTpe().symbol().flags & Modifiers.CASE) != 0)); + Console.println(node.getTpe().toString() + " / " + ((node.getTpe().symbol.flags & Flags.CASE) != 0)); var inner = node.and; def funct(inner: PatternNode): Boolean = { //outer: while (true) { @@ -538,7 +550,7 @@ abstract class PatternMatch extends PatternUtil { case b:Body => if ((b.guard.length > 1) || - (b.guard(0) != Tree.Empty)) + (b.guard(0) != EmptyTree)) throw Break(false); throw Break2() // break outer @@ -568,7 +580,7 @@ abstract class PatternMatch extends PatternUtil { } protected def isSimpleIntSwitch(): Boolean = { - if (selector.getType().widen().isSameAs(defs.int_TYPE())) { + if (isSameType(selector.tpe.widen, defs.IntClass.info)) { var patNode = root.and; while (patNode != null) { var node = patNode; @@ -581,7 +593,7 @@ abstract class PatternMatch extends PatternUtil { node.and match { case _b:Body => if ((_b.guard.length > 1) || - (_b.guard(0) != Tree.Empty) || + (_b.guard(0) != EmptyTree) || (_b.bound(0).length > 0)) return false; case _ => @@ -649,7 +661,7 @@ abstract class PatternMatch extends PatternUtil { def intSwitchToTree(): Tree = { //print(); val ncases = numCases(root.and); - val matchError = cf.ThrowMatchError(selector.pos, resultVar.getType()); + val matchError = cf.ThrowMatchError(selector.pos, resultVar.tpe); // without a case, we return a match error if there is no default case if (ncases == 0) return defaultBody(root.and, matchError); @@ -657,10 +669,9 @@ abstract class PatternMatch extends PatternUtil { else if (ncases == 1) { root.and.or match { case ConstantPat(value) => - return gen.If(cf.Equals(selector, - gen.Literal(root.and.or.pos, value)), - bodyToTree(root.and.or.and), - defaultBody(root.and, matchError)); + return If(cf.Equals(selector, Literal(value)), + bodyToTree(root.and.or.and), + defaultBody(root.and, matchError)); case _ => return generalSwitchToTree(); } @@ -671,7 +682,7 @@ abstract class PatternMatch extends PatternUtil { case _h:Header => val next = _h.next; var mappings: TagBodyPair = null; - var defaultBody = matchError; + var defaultBody: Tree = matchError; var patNode = root.and; while (patNode != null) { var node = patNode.or; @@ -679,11 +690,11 @@ abstract class PatternMatch extends PatternUtil { node match { case DefaultPat() => if (defaultBody != null) - throw new ApplicationError(); + error("not your day today"); defaultBody = bodyToTree(node.and); node = node.or; - case ConstantPat(AConstant.INT(value))=> + case ConstantPat( value: Int )=> mappings = insert( value, bodyToTree(node.and), @@ -691,13 +702,13 @@ abstract class PatternMatch extends PatternUtil { node = node.or; case _ => - throw new error("intSwitchToTree/Header " + node.toString()); + error("intSwitchToTree/Header " + node.toString()); } } patNode = patNode.nextH(); } if (mappings == null) { - return gen.Switch(selector, new Array[int](0), new Array[Tree](0), defaultBody, resultVar.getType()); + return Switch(selector, List(0), List(0), defaultBody, resultVar.tpe); } else { var n = mappings.length(); val tags = new Array[Int](n); @@ -709,7 +720,7 @@ abstract class PatternMatch extends PatternUtil { n = n + 1; mappings = mappings.next; } - return gen.Switch(selector, tags, bodies, defaultBody, resultVar.getType()); + return Switch(selector, tags, bodies, defaultBody, resultVar.tpe); } case _ => error("intSwitchToTree / not a header") @@ -727,19 +738,19 @@ abstract class PatternMatch extends PatternUtil { def generalSwitchToTree(): Tree = { val ts = Predef.Array[Tree] ( - gen.ValDef(root.symbol(), selector), - gen.ValDef(resultVar, gen.mkDefaultValue(selector.pos, resultVar.getType()))); - val res = gen.If( - selector.pos, - toTree(root.and), - gen.Ident(selector.pos, resultVar), - cf.ThrowMatchError(selector.pos, resultVar.getType(), gen.Ident(selector.pos, root.symbol()))); - return gen.mkBlock(selector.pos, ts, res); + ValDef(root.symbol, selector), + ValDef(resultVar, gen.mkDefaultValue(selector.pos, resultVar.tpe))); + val res = If(toTree(root.and), + Ident(resultVar), + cf.ThrowMatchError(selector.pos, + resultVar.tpe, + Ident(root.symbol))); + return Block(ts, res); } /*protected*/ def toTree(node1: PatternNode): Tree = { var node = node1; - var res = gen.mkBooleanLit(node.pos, false); + var res = Literal(false); while (node != null) node match { case _h:Header => @@ -760,35 +771,34 @@ abstract class PatternMatch extends PatternUtil { if ((bound.length == 0) && (guard.length == 0) && (body.length == 0)) { - return gen.mkBooleanLit(node.pos, true); // cf.Or(res, gen.mkBooleanLit(node.pos, true)); + return Literal(true); } else if (!doBinding) bound = Predef.Array[Array[ValDef]]( Predef.Array[ValDef]() ); var i = guard.length - 1; while(i >= 0) { val ts = bound(i).asInstanceOf[Array[Tree]]; - var res0 = gen.mkBlock(gen.Assign(gen.Ident(body(i).pos, resultVar), - body(i)), - gen.mkBooleanLit(body(i).pos, true)); - if (guard(i) != Tree.Empty) + var res0 = Block(Assign(Ident(resultVar), body(i)), + Literal(true)); + if (guard(i) != EmptyTree) res0 = cf.And(guard(i), res0); - res = cf.Or(gen.mkBlock(body(i).pos, ts, res0), res); + res = cf.Or(Block(ts, res0), res); i = i - 1 } return res; case _ => - throw new ApplicationError(); + error("I am tired"); } return res; } protected def optimize(selType:Type, alternatives1: PatternNode ): boolean = { var alternatives = alternatives1; - if (!optimize || !selType.isSubType(defs.SCALAOBJECT_TYPE())) + if (!optimize || !isSubType(selType, defs.ScalaObjectClass.info)) return false; var cases = 0; while (alternatives != null) { alternatives match { case ConstrPat(_) => - if (alternatives.getTpe().symbol().isCaseClass()) + if (alternatives.getTpe().symbol.isCaseClass()) cases = cases +1; else return false; @@ -840,7 +850,7 @@ abstract class PatternMatch extends PatternUtil { while (node != null) node match { case ConstrPat(casted) => - cases = insertNode(node.getTpe().symbol().tag(), node, cases); + cases = insertNode(node.getTpe().symbol.tag(), node, cases); node = node.or; case DefaultPat() => @@ -848,7 +858,7 @@ abstract class PatternMatch extends PatternUtil { node = node.or; case _ => - throw new ApplicationError(); + error("errare humanum est"); } var n = cases.length(); val tags = new Array[int](n); @@ -860,55 +870,66 @@ abstract class PatternMatch extends PatternUtil { n = n + 1; cases = cases.next; } - return gen.Switch(gen.mkApply__(gen.Select(selector.duplicate(), defs.SCALAOBJECT_TAG())), - tags, - bodies, - { if (defaultCase == null) gen.mkBooleanLit(selector.pos, false) else toTree(defaultCase.and) }, + return + Switch( + Apply( + Select(selector.duplicate, defs.ScalaObjectClass_tag), + List()), + tags, + bodies, + { if (defaultCase == null) Literal(false) else toTree(defaultCase.and) }, defs.boolean_TYPE()); } protected def toTree(node:PatternNode , selector:Tree ): Tree = { //System.err.println("pm.toTree("+node+","+selector+")"); if (node == null) - return gen.mkBooleanLit(selector.pos, false); + return Literal(false); else node match { case DefaultPat() => return toTree(node.and); case ConstrPat(casted) => - return gen.If(gen.mkIsInstanceOf(selector.duplicate(), node.getTpe()), - gen.mkBlock(gen.ValDef(casted, - gen.mkAsInstanceOf(selector.pos, selector.duplicate(), node.getTpe(), true)), - toTree(node.and)), - toTree(node.or, selector.duplicate())); + return If(gen.mkIsInstanceOf(selector.duplicate, node.getTpe()), + Block(ValDef(casted, + gen.mkAsInstanceOf(selector.pos, selector.duplicate, node.getTpe(), true)), + toTree(node.and)), + toTree(node.or, selector.duplicate)); case SequencePat(casted, len) => return cf.Or( cf.And( - cf.And(gen.mkIsInstanceOf(selector.duplicate(), node.getTpe()), - cf.Equals(gen.mkApply__(gen.Select(gen.mkAsInstanceOf(selector.pos, selector.duplicate(), node.getTpe(), true), - defs.SEQ_LENGTH())), - gen.mkIntLit(selector.pos, len))), - gen.mkBlock(gen.ValDef(casted, - gen.mkAsInstanceOf(selector.pos, selector.duplicate(), node.getTpe(), true)), - toTree(node.and))), - toTree(node.or, selector.duplicate())); + cf.And(gen.mkIsInstanceOf(selector.duplicate, node.getTpe()), + cf.Equals( + Apply( + Select( + gen.mkAsInstanceOf(selector.pos, + selector.duplicate, + node.getTpe(), + true), + defs.Seq_length) + List()), + Literal(len))), + Block(ValDef(casted, + gen.mkAsInstanceOf(selector.pos, selector.duplicate, node.getTpe(), true)), + toTree(node.and))), + toTree(node.or, selector.duplicate)); case ConstantPat(value) => - return gen.If(cf.Equals(selector.duplicate(), - gen.Literal(selector.pos, value)), - toTree(node.and), - toTree(node.or, selector.duplicate())); + return If(cf.Equals(selector.duplicate, + Literal(value)), + toTree(node.and), + toTree(node.or, selector.duplicate)); case VariablePat(tree) => - return gen.If(cf.Equals(selector.duplicate(), tree), - toTree(node.and), - toTree(node.or, selector.duplicate())); + return If(cf.Equals(selector.duplicate, tree), + toTree(node.and), + toTree(node.or, selector.duplicate)); case AltPat(header) => - return gen.If(toTree(header), - toTree(node.and), - toTree(node.or, selector.duplicate())); + return If(toTree(header), + toTree(node.and), + toTree(node.or, selector.duplicate)); case _ => - throw new ApplicationError(); + error("can't plant this tree"); } } } diff --git a/sources/scala/tools/nsc/matching/PatternNode.scala b/sources/scala/tools/nsc/matching/PatternNode.scala new file mode 100644 index 0000000000..97aa7821ee --- /dev/null +++ b/sources/scala/tools/nsc/matching/PatternNode.scala @@ -0,0 +1,276 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +** ** +** $Id$ +\* */ + +package scala.tools.nsc.matching ; + +import scala.tools.util.Position; + +abstract class PatternNodes { + + val global: Global; + + import global._; + + /** Intermediate data structure for algebraic + pattern matcher + */ + class PatternNode { + var pos = Position.FIRSTPOS; + var tpe: Type = _; + var or: PatternNode = _; + var and: PatternNode = _; + + def getTpe(): Type = { + tpe; + } + def setType(tpe: Type): Unit = { + this.tpe = tpe; + } + + def dup(): PatternNode = { + var res: PatternNode = _; + this match { + case h:Header => + res = new Header(h.selector, h.next); + + case b:Body=> + res = new Body(b.bound, b.guard, b.body); + + case DefaultPat() => + res = DefaultPat(); + + case ConstrPat(casted) => + res = ConstrPat(casted); + + case SequencePat(casted, len) => + res = SequencePat(casted, len); + + case SeqContainerPat(casted, seqpat) => + res = SeqContainerPat(casted, seqpat); + + case ConstantPat(value) => + res = ConstantPat(value); + + case VariablePat(tree) => + res = VariablePat(tree); + + case AltPat(subheader) => + res = AltPat(subheader); + + case _ => + error("") + } + res.pos = pos; + res.tpe = tpe; + res.or = or; + res.and = and; + res; + } + + def symbol: Symbol = { + this match { + case ConstrPat(casted) => + return casted; + case SequencePat(casted, _) => + return casted; + case SeqContainerPat(casted, _) => + return casted; + case _ => + return NoSymbol; //.NONE; + } + } + + def nextH(): PatternNode = { + this match { + case _h:Header => + return _h.next; + case _ => + return null; + } + } + + def isDefaultPat(): boolean = { + this match { + case DefaultPat() => + return true; + case _ => + return false; + } + } + + /** returns true if + * p and q are equal (constructor | sequence) type tests, or + * "q matches" => "p matches" + */ + def isSameAs(q: PatternNode): boolean = { + this match { + case ConstrPat(_) => + q match { + case ConstrPat(_) => + isSameType(q.getTpe(), this.getTpe()); + case _ => + false + } + case SequencePat(_, plen) => + q match { + case SequencePat(_, qlen) => + return (plen == qlen) && isSameType(q.getTpe(), this.getTpe()); + case _ => + false + } + case _ => + subsumes(q); + } + } + + /** returns true if "q matches" => "p matches" + */ + def subsumes(q:PatternNode): Boolean = { + this match { + case DefaultPat() => + q match { + case DefaultPat() => + true; + case _ => + false; + } + case ConstrPat(_) => + q match { + case ConstrPat(_) => + isSubType(q.getTpe(), this.getTpe()); + case _ => + false; + } + case SequencePat(_, plen) => + q match { + case SequencePat(_, qlen) => + (plen == qlen) && isSubType(q.getTpe(), this.getTpe()); + case _ => + false; + } + case ConstantPat(pval) => + q match { + case ConstantPat(qval) => + pval.equals(qval); + case _ => + false; + } + case VariablePat(tree) => + q match { + case VariablePat(other) => + (tree.symbol != null) && + (tree.symbol != NoSymbol) && + (!tree.symbol.isError) && + (tree.symbol == other.symbol); + case _ => + false; + } + case _ => + false; + } + } + + override def toString(): String = { + this match { + case _h:Header => + return "Header(" + _h.selector + ")"; + case _b:Body => + return "Body"; + case DefaultPat() => + return "DefaultPat"; + case ConstrPat(casted) => + return "ConstrPat(" + casted + ")"; + case SequencePat(casted, len) => + return "SequencePat(" + casted + ", " + len + "...)"; + case SeqContainerPat(casted, seqpat) => + return "SeqContainerPat(" + casted + ", " + seqpat + ")"; + case ConstantPat(value) => + return "ConstantPat(" + value + ")"; + case VariablePat(tree) => + return "VariablePat"; + case _ => + return "<unknown pat>"; + } + } + } + + class Header(sel1: Tree, next1: Header ) extends PatternNode { + var selector: Tree = sel1; + var next: Header = next1; + } + + class Body(bound1: Array[Array[ValDef]] , guard1:Array[Tree] , body1:Array[Tree] ) extends PatternNode { + var bound = bound1; + var guard = guard1; + var body = body1; + } + + case class DefaultPat()extends PatternNode; + case class ConstrPat(casted:Symbol ) extends PatternNode; + case class ConstantPat(value: Any /*AConstant*/ ) extends PatternNode; + case class VariablePat(tree: Tree ) extends PatternNode; + case class AltPat(subheader: Header ) extends PatternNode; + case class SequencePat( casted: Symbol, len:int) extends PatternNode; // only used in PatternMatcher + case class SeqContainerPat(casted: Symbol , seqpat: Tree ) extends PatternNode; // in AlgebraicMatcher + + /** the environment for a body of a case + * @param owner the owner of the variables created here + */ + class CaseEnv { +// (val owner:Symbol, unit:CompilationUnit) + private var boundVars:scala.Array[ValDef] = new Array[ValDef](4); + private var numVars = 0; + + /** substitutes a symbol on the right hand side of a ValDef + */ + def substitute(oldSym: Symbol, newInit: Tree): Unit = { + var i = 0; while( i < numVars) { + if( boundVars(i).rhs.symbol == oldSym ) { + boundVars(i) = ValDef(boundVars(i).symbol, newInit); + return; + } + i = i + 1; + } + } + + def newBoundVar(sym:Symbol, tpe: Type, init:Tree ): Unit = { + // sym.setOwner( owner ); // FIXME should be corrected earlier + // @maybe is corrected now? bq + if (numVars == boundVars.length) { + val newVars = new Array[ValDef](numVars * 2); + System.arraycopy(boundVars, 0, newVars, 0, numVars); + this.boundVars = newVars; + } + sym.setInfo(tpe); + this.boundVars(numVars) = ValDef(sym, init.duplicate); + numVars = numVars + 1; + } + + def getBoundVars(): Array[ValDef] = { + val newVars = new Array[ValDef](numVars); + System.arraycopy(boundVars, 0, newVars, 0, numVars); + return newVars; + } + + override def equals(obj: Any): Boolean = { + if (!(obj.isInstanceOf[CaseEnv])) + return false; + val env = obj.asInstanceOf[CaseEnv]; + if (env.numVars != numVars) + return false; + var i = 0; while(i < numVars) { + if ((boundVars(i).name != env.boundVars(i).name) || + !isSameType(boundVars(i).tpe, env.boundVars(i).tpe) || + (boundVars(i).rhs != env.boundVars(i).rhs)) + return false; + i = i + 1; + } + return true; + } + + } // class CaseEnv +} diff --git a/sources/scala/tools/nsc/matching/PatternNodeCreator.scala b/sources/scala/tools/nsc/matching/PatternNodeCreator.scala index 42c76c2863..60eab3d92e 100644 --- a/sources/scala/tools/nsc/matching/PatternNodeCreator.scala +++ b/sources/scala/tools/nsc/matching/PatternNodeCreator.scala @@ -1,12 +1,16 @@ package scala.tools.nsc.matching; +import scala.tools.util.Position; /** PatternNode factory. * we inherit the globals from PatternTool. */ -abstract class PatternNodeCreator(val owner:Symbol) extends PatternUtil { +abstract class PatternNodeCreator extends PatternUtil with PatternNodes { + import global._; + + var owner:Symbol = _; /** the owner of the variable symbols that might be created */ //Symbol owner; @@ -14,7 +18,7 @@ abstract class PatternNodeCreator(val owner:Symbol) extends PatternUtil { val sym = newVar(Position.FIRSTPOS, tpe); val node = new SequencePat(sym, len); node.pos = pos; - node.setType(tpe); + node.tpe = tpe; node; } @@ -40,7 +44,7 @@ abstract class PatternNodeCreator(val owner:Symbol) extends PatternUtil { node; } - def ConstantPat(pos: int, tpe: Type, value:AConstant ) = { + def ConstantPat(pos: int, tpe: Type, value: Any /*AConstant*/ ) = { val node = new ConstantPat( value ); node.pos = pos; node.setType(tpe); @@ -50,7 +54,7 @@ abstract class PatternNodeCreator(val owner:Symbol) extends PatternUtil { def VariablePat(pos: int, tree:Tree) = { val node = new VariablePat( tree ); node.pos = pos; - node.setType(tree.getType()); + node.setType(tree.tpe); node; } @@ -83,15 +87,15 @@ abstract class PatternNodeCreator(val owner:Symbol) extends PatternUtil { } def newVar(pos: int, name: Name, tpe: Type): Symbol= { - val sym = owner.newVariable(pos, 0, name); - sym.setType(tpe); + val sym = owner.newVariable(0, name); + sym.setInfo(tpe); //System.out.println("PatternNodeCreator::newVar creates symbol "+sym); //System.out.println("owner: "+sym.owner()); sym; } def newVar(pos: int, tpe: Type): Symbol = { - newVar(pos, fresh.newName("temp"), tpe); + newVar(pos, unit.fresh.newName("temp"), tpe); } } diff --git a/sources/scala/tools/nsc/matching/PatternUtil.scala b/sources/scala/tools/nsc/matching/PatternUtil.scala index 7da24e445b..1607c44856 100644 --- a/sources/scala/tools/nsc/matching/PatternUtil.scala +++ b/sources/scala/tools/nsc/matching/PatternUtil.scala @@ -9,15 +9,20 @@ package scala.tools.nsc.matching; -/** utility function +import scala.tools.util.Position; + +/** utility functions */ abstract class PatternUtil { val global: Global; - val unit: CompilationUnit; + import global._; + var pos: Position; + var unit: CompilationUnit = _; + import global.definitions; def containsBinding(pat: Tree): Boolean = { @@ -29,23 +34,23 @@ abstract class PatternUtil { } def isVariableName(name: Name): Boolean = - ( name.isVariable() ) && ( name != Name.fromString("_") ) ; + ( treeInfo.isVariableName(name) ) && ( name != nme.USCOREkw ) ; def isVariableSymbol(sym: Symbol): Boolean = - ( sym != null )&&( !sym.isPrimaryConstructor() ); + ( sym != null )&&( !sym.isPrimaryConstructor ); def traverse(tree: Tree): Unit = { tree match { case x @ Ident(name) => - if(x.symbol() != definitions.PATTERN_WILDCARD) - throw new ApplicationError("shouldn't happen?!"); + if(x.symbol != definitions.PatternWildcard) + error("shouldn't happen?!"); case Bind(name, subtree) => var sym: Symbol = _; if (isVariableName(name) - && isVariableSymbol( {sym = tree.symbol(); tree.symbol()} )) + && isVariableSymbol( {sym = tree.symbol; tree.symbol} )) handleVariableSymbol(sym); traverse( subtree ); diff --git a/sources/scala/tools/nsc/matching/TransMatcher.scala b/sources/scala/tools/nsc/matching/TransMatcher.scala index 862e356cd3..7cb1a3ccd3 100644 --- a/sources/scala/tools/nsc/matching/TransMatcher.scala +++ b/sources/scala/tools/nsc/matching/TransMatcher.scala @@ -15,11 +15,15 @@ abstract class TransMatcher { import definitions._; import posAssigner.atPos; + private var unit: CompilationUnit; + class TransMatchPhase(prev: Phase) extends StdPhase(prev) { def name = "transmatcher"; val global: TransMatcher.this.global.type = TransMatcher.this.global; - def apply(unit: CompilationUnit): unit = + def apply(unit: CompilationUnit): unit = { + TransMatcher.this.unit = unit; unit.body = newTransMatcher.transform(unit.body); + } } def newTransMatcher = new TransMatch(); diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala index 75a3cc4ddd..c3b325addb 100755 --- a/sources/scala/tools/nsc/symtab/Definitions.scala +++ b/sources/scala/tools/nsc/symtab/Definitions.scala @@ -37,6 +37,9 @@ abstract class Definitions: SymbolTable { // the scala value classes var UnitClass: Symbol = _; var BooleanClass: Symbol = _; + def Boolean_not = IterableClass.info.decl(nme.ZNOT); + def Boolean_and = IterableClass.info.decl(nme.ZAND); + def Boolean_or = IterableClass.info.decl(nme.ZOR); var ByteClass: Symbol = _; var ShortClass: Symbol = _; var CharClass: Symbol = _; @@ -47,6 +50,7 @@ abstract class Definitions: SymbolTable { // the scala reference classes var ScalaObjectClass: Symbol = _; + def ScalaObjectClass_tag = ScalaObjectClass.info.decl( nme.tag ); var AttributeClass: Symbol = _; var RefClass: Symbol = _; var PartialFunctionClass: Symbol = _; @@ -55,12 +59,18 @@ abstract class Definitions: SymbolTable { def Iterable_hasNext = IterableClass.info.decl("hasNext"); var IteratorClass: Symbol = _; var SeqClass: Symbol = _; + def Seq_length = SeqClass.info.decl("length"); var ListClass: Symbol = _; + def List_isEmpty = ListClass.info.decl("isEmpty"); + def List_head = ListClass.info.decl("head"); + def List_tail = ListClass.info.decl("tail"); var ArrayClass: Symbol = _; var TypeClass: Symbol = _; var PredefModule: Symbol = _; var ConsoleModule: Symbol = _; var MatchErrorModule: Symbol = _; + def MatchError_fail = MatchErrorModule.info.decl("fail"); + def MatchError_report = MatchErrorModule.info.decl("report"); var RepeatedParamClass: Symbol = _; var ByNameParamClass: Symbol = _; @@ -75,12 +85,17 @@ abstract class Definitions: SymbolTable { typeRef(sym.typeConstructor.prefix, sym, elems) } else NoType; + def tupleField(n:int, j:int) = + TupleClass(n).info.decl("_"+j.toString()); + def functionType(formals: List[Type], restpe: Type) = if (formals.length <= MaxFunctionArity) { val sym = FunctionClass(formals.length); typeRef(sym.typeConstructor.prefix, sym, formals ::: List(restpe)) } else NoType; + def functionApply(n:int) = FunctionClass(n).info.decl("apply"); + def isTupleType(tp: Type): boolean = tp match { case TypeRef(_, sym, elems) => elems.length <= MaxTupleArity && sym == TupleClass(elems.length); |