diff options
author | Matthias Zenger <mzenger@gmail.com> | 2004-03-08 10:51:36 +0000 |
---|---|---|
committer | Matthias Zenger <mzenger@gmail.com> | 2004-03-08 10:51:36 +0000 |
commit | ce039b7db18521e8fadf244099ed90ad1020ec5e (patch) | |
tree | fced47f3961d311587daeddcf6914e017be9fd2b /sources/scalac/transformer/matching | |
parent | 8ba6023e7aa181b4e7e3206caf29c0550315f5b4 (diff) | |
download | scala-ce039b7db18521e8fadf244099ed90ad1020ec5e.tar.gz scala-ce039b7db18521e8fadf244099ed90ad1020ec5e.tar.bz2 scala-ce039b7db18521e8fadf244099ed90ad1020ec5e.zip |
Improved error messages for failed pattern matc...
Improved error messages for failed pattern matching expressions.
Diffstat (limited to 'sources/scalac/transformer/matching')
-rw-r--r-- | sources/scalac/transformer/matching/CodeFactory.java | 11 | ||||
-rw-r--r-- | sources/scalac/transformer/matching/PatternMatcher.java | 986 |
2 files changed, 470 insertions, 527 deletions
diff --git a/sources/scalac/transformer/matching/CodeFactory.java b/sources/scalac/transformer/matching/CodeFactory.java index 8bb592327e..f860200a27 100644 --- a/sources/scalac/transformer/matching/CodeFactory.java +++ b/sources/scalac/transformer/matching/CodeFactory.java @@ -195,6 +195,17 @@ class CodeFactory extends PatternTool { }); } + protected Tree ThrowMatchError(int pos, Type type, Tree tree) { + return gen.mkApplyTV( + gen.mkGlobalRef(pos, defs.MATCHERROR_REPORT()), + new Tree[]{gen.mkType(pos, type)}, + new Tree[]{ + gen.mkStringLit(pos, unit.toString()), + gen.mkIntLit(pos, Position.line(pos)), + tree + }); + } + protected Tree Error(int pos, Type type) { return gen.mkApplyTV( gen.mkGlobalRef(pos, defs.MATCHERROR_FAIL()), diff --git a/sources/scalac/transformer/matching/PatternMatcher.java b/sources/scalac/transformer/matching/PatternMatcher.java index 935a3ac93e..085e0d8d17 100644 --- a/sources/scalac/transformer/matching/PatternMatcher.java +++ b/sources/scalac/transformer/matching/PatternMatcher.java @@ -20,7 +20,7 @@ import Tree.*; public class PatternMatcher extends PatternTool { - protected boolean optimize = true; + protected boolean optimize = true; protected boolean delegateSequenceMatching = false; protected boolean doBinding = true; @@ -56,7 +56,7 @@ public class PatternMatcher extends PatternTool { initialize(selector, owner, resultType, true); } - /** constructor, used in subclass ALgebraicMatcher + /** constructor, used in subclass AlgebraicMatcher */ protected PatternMatcher(Unit unit) { super(unit); @@ -93,87 +93,87 @@ public class PatternMatcher extends PatternTool { System.out.println(indent + "NULL"); else switch (patNode) { - case Header(Tree selector, Header next): - System.out.println(indent + "HEADER(" + patNode.type + - ", " + selector + ")"); - print(patNode.or, indent + "|"); - if (next != null) - print(next, indent); - break; - case ConstrPat(Symbol casted): - String s = "-- " + patNode.type.symbol().name + - "(" + patNode.type + ", " + casted + ") -> "; - String ind = indent; - indent = (patNode.or != null) ? - indent : - indent.substring(0, indent.length() - 1) + " "; - for (int i = 0; i < s.length(); i++) - indent += " "; - System.out.println(ind + s); - print(patNode.and, indent); - if (patNode.or != null) - print(patNode.or, ind); - break; - case SequencePat( Symbol casted, int plen ): - String s = "-- " + patNode.type.symbol().name + "(" + patNode.type + - ", " + casted + ", " + plen + ") -> "; - String ind = indent; - indent = (patNode.or != null) ? - indent : - indent.substring(0, indent.length() - 1) + " "; - for (int i = 0; i < s.length(); i++) - indent += " "; - System.out.println(ind + s); - print(patNode.and, indent); - if (patNode.or != null) - print(patNode.or, ind); - break; - case DefaultPat(): - System.out.println(indent + "-- _ -> "); - print(patNode.and, indent.substring(0, indent.length() - 1) + - " "); - if (patNode.or != null) - print(patNode.or, indent); - break; - case ConstantPat(AConstant value): - String s = "-- CONST(" + value + ") -> "; - String ind = indent; - indent = (patNode.or != null) ? - indent : - indent.substring(0, indent.length() - 1) + " "; - for (int i = 0; i < s.length(); i++) - indent += " "; - System.out.println(ind + s); - print(patNode.and, indent); - if (patNode.or != null) - print(patNode.or, ind); - break; - case VariablePat(Tree tree): - String s = "-- STABLEID(" + tree + ": " + patNode.type + ") -> "; - String ind = indent; - indent = (patNode.or != null) ? - indent : - indent.substring(0, indent.length() - 1) + " "; - for (int i = 0; i < s.length(); i++) - indent += " "; - System.out.println(ind + s); - print(patNode.and, indent); - if (patNode.or != null) - print(patNode.or, ind); - break; - case AltPat(Header header): - System.out.println(indent + "-- ALTERNATIVES:"); - print(header, indent + " * "); - print(patNode.and, indent + " * -> "); - if (patNode.or != null) - print(patNode.or, indent); - break; - case Body(_, Tree[] guards, Tree[] stats): - if ((guards.length == 0) && (stats.length == 0)) - System.out.println(indent + "true"); - else - System.out.println(indent + "BODY(" + stats.length + ")"); - break; + case Header(Tree selector, Header next): + System.out.println(indent + "HEADER(" + patNode.type + + ", " + selector + ")"); + print(patNode.or, indent + "|"); + if (next != null) + print(next, indent); + break; + case ConstrPat(Symbol casted): + String s = "-- " + patNode.type.symbol().name + + "(" + patNode.type + ", " + casted + ") -> "; + String ind = indent; + indent = (patNode.or != null) ? + indent : + indent.substring(0, indent.length() - 1) + " "; + for (int i = 0; i < s.length(); i++) + indent += " "; + System.out.println(ind + s); + print(patNode.and, indent); + if (patNode.or != null) + print(patNode.or, ind); + break; + case SequencePat( Symbol casted, int plen ): + String s = "-- " + patNode.type.symbol().name + "(" + patNode.type + + ", " + casted + ", " + plen + ") -> "; + String ind = indent; + indent = (patNode.or != null) ? + indent : + indent.substring(0, indent.length() - 1) + " "; + for (int i = 0; i < s.length(); i++) + indent += " "; + System.out.println(ind + s); + print(patNode.and, indent); + if (patNode.or != null) + print(patNode.or, ind); + break; + case DefaultPat(): + System.out.println(indent + "-- _ -> "); + print(patNode.and, indent.substring(0, indent.length() - 1) + + " "); + if (patNode.or != null) + print(patNode.or, indent); + break; + case ConstantPat(AConstant value): + String s = "-- CONST(" + value + ") -> "; + String ind = indent; + indent = (patNode.or != null) ? + indent : + indent.substring(0, indent.length() - 1) + " "; + for (int i = 0; i < s.length(); i++) + indent += " "; + System.out.println(ind + s); + print(patNode.and, indent); + if (patNode.or != null) + print(patNode.or, ind); + break; + case VariablePat(Tree tree): + String s = "-- STABLEID(" + tree + ": " + patNode.type + ") -> "; + String ind = indent; + indent = (patNode.or != null) ? + indent : + indent.substring(0, indent.length() - 1) + " "; + for (int i = 0; i < s.length(); i++) + indent += " "; + System.out.println(ind + s); + print(patNode.and, indent); + if (patNode.or != null) + print(patNode.or, ind); + break; + case AltPat(Header header): + System.out.println(indent + "-- ALTERNATIVES:"); + print(header, indent + " * "); + print(patNode.and, indent + " * -> "); + if (patNode.or != null) + print(patNode.or, indent); + break; + case Body(_, Tree[] guards, Tree[] stats): + if ((guards.length == 0) && (stats.length == 0)) + System.out.println(indent + "true"); + else + System.out.println(indent + "BODY(" + stats.length + ")"); + break; } } @@ -188,18 +188,18 @@ public class PatternMatcher extends PatternTool { */ protected void enter(Tree caseDef) { switch (caseDef) { - case CaseDef(Tree pat, Tree guard, Tree body): - CaseEnv env = new CaseEnv(owner, unit); - // PatternNode matched = match(pat, root); - PatternNode target = enter1(pat, -1, root, root.symbol(), env); - // if (target.and != null) - // unit.error(pat.pos, "duplicate case"); - if (target.and == null) - target.and = mk.Body(caseDef.pos, env.boundVars(), guard, body); - else if (target.and instanceof Body) - updateBody((Body)target.and, env.boundVars(), guard, body); - else - unit.error(pat.pos, "duplicate case"); + case CaseDef(Tree pat, Tree guard, Tree body): + CaseEnv env = new CaseEnv(owner, unit); + // PatternNode matched = match(pat, root); + PatternNode target = enter1(pat, -1, root, root.symbol(), env); + // if (target.and != null) + // unit.error(pat.pos, "duplicate case"); + if (target.and == null) + target.and = mk.Body(caseDef.pos, env.boundVars(), guard, body); + else if (target.and instanceof Body) + updateBody((Body)target.and, env.boundVars(), guard, body); + else + unit.error(pat.pos, "duplicate case"); } } @@ -222,66 +222,23 @@ public class PatternMatcher extends PatternTool { } } - /* - - // unused, thus commented out ! - - public PatternNode match(Tree pat, PatternNode target) { - // advance one step in pattern - PatternNode next = target.and; - // we are done (no match yet) - if (next == null) - return null; - // check if matched - switch (next) { - case Body(_, _, _): - return next; - case Header(_, _): - Header header = (Header)next; - // get pattern arguments - Tree[] patArgs = patternArgs(pat); - // get next pattern node - PatternNode patNode = patternNode(pat, header, null); - do { - next = header; - while ((next = next.or) != null) - if (next.subsumes( patNode ) && - ((target = match(patArgs, next)) != null)) - return target; - else if (next.isDefaultPat()) - return next.and; - } while ((header = header.next) != null); - return null; - default: - throw new ApplicationError(); - } - } - - public PatternNode match(Tree[] pats, PatternNode target) { - for (int i = 0; i < pats.length; i++) - if ((target = match(pats[i], target)) == null) - return null; - return target; - } - */ - protected Tree[] patternArgs(Tree tree) { switch (tree) { - case Bind(_, Tree pat): - return patternArgs(pat); - case Apply(_, Tree[] args): - if ( isSeqApply((Apply) tree) && !delegateSequenceMatching) - switch (args[0]) { - case Sequence(Tree[] ts): - return ts; - } - return args; - case Sequence(Tree[] ts): - if (!delegateSequenceMatching) - return ts; - return Tree.EMPTY_ARRAY; - default: - return Tree.EMPTY_ARRAY; + case Bind(_, Tree pat): + return patternArgs(pat); + case Apply(_, Tree[] args): + if ( isSeqApply((Apply) tree) && !delegateSequenceMatching) + switch (args[0]) { + case Sequence(Tree[] ts): + return ts; + } + return args; + case Sequence(Tree[] ts): + if (!delegateSequenceMatching) + return ts; + return Tree.EMPTY_ARRAY; + default: + return Tree.EMPTY_ARRAY; } } @@ -291,112 +248,111 @@ public class PatternMatcher extends PatternTool { } protected PatternNode patternNode(Tree tree, Header header, CaseEnv env) { - //System.out.println("patternNode("+tree+","+header+")"); - switch (tree) { - - case Bind(Name name, - Typed( Ident( Names.PATTERN_WILDCARD ), Tree tpe)): // x@_:Type - - if(header.type.isSubType(tpe.type)) { - PatternNode node = mk.DefaultPat(tree.pos, tpe.type); - env.newBoundVar( tree.symbol(), tree.type, header.selector ); - return node; - } else { - ConstrPat node = mk.ConstrPat(tree.pos, tpe.type); - env.newBoundVar( tree.symbol(), tree.type, gen.Ident(tree.pos, node.casted)); - return node; - } - - case Bind( Name name, Ident( Names.PATTERN_WILDCARD )): // x @ _ - PatternNode node = mk.DefaultPat(tree.pos, header.type); - if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) - env.newBoundVar( tree.symbol(), tree.type, header.selector); - return node; - - case Bind( Name name, Tree pat): - PatternNode node = patternNode(pat, header, env); - if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) { - Symbol casted = node.symbol(); - Tree theValue = (casted == Symbol.NONE) ? header.selector : gen.Ident(tree.pos, casted); - env.newBoundVar( tree.symbol(), tree.type, theValue ); - } - return node; - case Apply(Tree fn, Tree[] args): // pattern with args - if(isSeqApply((Apply)tree)) { - if (!delegateSequenceMatching) { - switch (args[0]) { - case Sequence(Tree[] ts): - return mk.SequencePat( tree.pos, tree.type, ts.length ); - } - } else { - PatternNode res = mk.ConstrPat(tree.pos, tree.type); - res.and = mk.Header(tree.pos, header.type, header.selector); - res.and.and = mk.SeqContainerPat( tree.pos, tree.type, args[ 0 ] ); - return res; - } - } else if ((fn.symbol() != null) && fn.symbol().isStable()) - return mk.VariablePat(tree.pos, tree); - return mk.ConstrPat(tree.pos, tree.type); - case Typed(Ident ident, Tree tpe): // variable pattern - boolean doTest = header.type.isSubType(tpe.type); - PatternNode node = doTest ? - mk.DefaultPat(tree.pos, tpe.type) - : mk.ConstrPat(tree.pos, tpe.type); - if ((env != null) && (ident.symbol() != defs.PATTERN_WILDCARD)) - switch (node) { - case ConstrPat(Symbol casted): - env.newBoundVar( - ((Tree.Typed)tree).expr.symbol(), - tpe.type, - gen.Ident(tree.pos, casted)); - break; - default: - env.newBoundVar( - ((Tree.Typed)tree).expr.symbol(), - tpe.type, - doTest ? header.selector : gen.Ident(tree.pos, ((ConstrPat) node).casted)); - } - return node; - case Ident(Name name): // pattern without args or variable - if (tree.symbol() == defs.PATTERN_WILDCARD) - return mk.DefaultPat(tree.pos, header.type); - else if (tree.symbol().isPrimaryConstructor()) { - assert false; // this may not happen ?? ----------------- Burak - return mk.ConstrPat(tree.pos, tree.type); - } else if (name.isVariable()) {// should be Bind ------------ Burak - assert false; - if (env != null) - env.newBoundVar(tree.symbol(), - tree.type, - header.selector); - return mk.DefaultPat(tree.pos, header.type); - } else - return mk.VariablePat(tree.pos, tree); - case Select(_, Name name): // variable - if (tree.symbol().isPrimaryConstructor()) - return mk.ConstrPat(tree.pos, tree.type); - else - return mk.VariablePat(tree.pos, tree); - case Literal(AConstant value): - return mk.ConstantPat(tree.pos, tree.type, value); - case Sequence(Tree[] ts): - if ( !delegateSequenceMatching ) { - return mk.SequencePat(tree.pos, tree.type, ts.length); - } else { - return mk.SeqContainerPat(tree.pos, tree.type, tree); - } - case Alternative(Tree[] ts): - assert ts.length > 1; - PatternNode subroot = mk.ConstrPat(header.pos, header.type); - subroot.and = mk.Header(header.pos, header.type, header.selector.duplicate()); - CaseEnv subenv = new CaseEnv(owner, unit); - for (int i = 0; i < ts.length; i++) { - PatternNode target = enter1(ts[i], -1, subroot, subroot.symbol(), subenv); - target.and = mk.Body(tree.pos); - } - return mk.AltPat(tree.pos, (Header)subroot.and); - default: - throw new ApplicationError("unit = " + unit + "; tree = "+tree); + //System.out.println("patternNode("+tree+","+header+")"); + switch (tree) { + case Bind(Name name, + Typed( Ident( Names.PATTERN_WILDCARD ), Tree tpe)): // x@_:Type + + if(header.type.isSubType(tpe.type)) { + PatternNode node = mk.DefaultPat(tree.pos, tpe.type); + env.newBoundVar( tree.symbol(), tree.type, header.selector ); + return node; + } else { + ConstrPat node = mk.ConstrPat(tree.pos, tpe.type); + env.newBoundVar( tree.symbol(), tree.type, gen.Ident(tree.pos, node.casted)); + return node; + } + + case Bind( Name name, Ident( Names.PATTERN_WILDCARD )): // x @ _ + PatternNode node = mk.DefaultPat(tree.pos, header.type); + if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) + env.newBoundVar( tree.symbol(), tree.type, header.selector); + return node; + + case Bind( Name name, Tree pat): + PatternNode node = patternNode(pat, header, env); + if ((env != null) && (tree.symbol() != defs.PATTERN_WILDCARD)) { + Symbol casted = node.symbol(); + Tree theValue = (casted == Symbol.NONE) ? header.selector : gen.Ident(tree.pos, casted); + env.newBoundVar( tree.symbol(), tree.type, theValue ); + } + return node; + case Apply(Tree fn, Tree[] args): // pattern with args + if(isSeqApply((Apply)tree)) { + if (!delegateSequenceMatching) { + switch (args[0]) { + case Sequence(Tree[] ts): + return mk.SequencePat(tree.pos, tree.type, ts.length); + } + } else { + PatternNode res = mk.ConstrPat(tree.pos, tree.type); + res.and = mk.Header(tree.pos, header.type, header.selector); + res.and.and = mk.SeqContainerPat(tree.pos, tree.type, args[0]); + return res; + } + } else if ((fn.symbol() != null) && fn.symbol().isStable()) + return mk.VariablePat(tree.pos, tree); + return mk.ConstrPat(tree.pos, tree.type); + case Typed(Ident ident, Tree tpe): // variable pattern + boolean doTest = header.type.isSubType(tpe.type); + PatternNode node = doTest ? + mk.DefaultPat(tree.pos, tpe.type) + : mk.ConstrPat(tree.pos, tpe.type); + if ((env != null) && (ident.symbol() != defs.PATTERN_WILDCARD)) + switch (node) { + case ConstrPat(Symbol casted): + env.newBoundVar( + ((Tree.Typed)tree).expr.symbol(), + tpe.type, + gen.Ident(tree.pos, casted)); + break; + default: + env.newBoundVar( + ((Tree.Typed)tree).expr.symbol(), + tpe.type, + doTest ? header.selector : gen.Ident(tree.pos, ((ConstrPat) node).casted)); + } + return node; + case Ident(Name name): // pattern without args or variable + if (tree.symbol() == defs.PATTERN_WILDCARD) + return mk.DefaultPat(tree.pos, header.type); + else if (tree.symbol().isPrimaryConstructor()) { + assert false; // this may not happen ?? ----------------- Burak + return mk.ConstrPat(tree.pos, tree.type); + } else if (name.isVariable()) {// should be Bind ------------ Burak + assert false; + if (env != null) + env.newBoundVar(tree.symbol(), + tree.type, + header.selector); + return mk.DefaultPat(tree.pos, header.type); + } else + return mk.VariablePat(tree.pos, tree); + case Select(_, Name name): // variable + if (tree.symbol().isPrimaryConstructor()) + return mk.ConstrPat(tree.pos, tree.type); + else + return mk.VariablePat(tree.pos, tree); + case Literal(AConstant value): + return mk.ConstantPat(tree.pos, tree.type, value); + case Sequence(Tree[] ts): + if ( !delegateSequenceMatching ) { + return mk.SequencePat(tree.pos, tree.type, ts.length); + } else { + return mk.SeqContainerPat(tree.pos, tree.type, tree); + } + case Alternative(Tree[] ts): + assert ts.length > 1; + PatternNode subroot = mk.ConstrPat(header.pos, header.type); + subroot.and = mk.Header(header.pos, header.type, header.selector.duplicate()); + CaseEnv subenv = new CaseEnv(owner, unit); + for (int i = 0; i < ts.length; i++) { + PatternNode target = enter1(ts[i], -1, subroot, subroot.symbol(), subenv); + target.and = mk.Body(tree.pos); + } + return mk.AltPat(tree.pos, (Header)subroot.and); + default: + throw new ApplicationError("unit = " + unit + "; tree = "+tree); } } @@ -406,12 +362,12 @@ public class PatternMatcher extends PatternTool { Symbol casted, CaseEnv env) { switch (target) { - case ConstrPat(Symbol newCasted): - return enter1(pat, index, target, newCasted, env); - case SequencePat(Symbol newCasted, int len): - return enter1(pat, index, target, newCasted, env); - default: - return enter1(pat, index, target, casted, env); + case ConstrPat(Symbol newCasted): + return enter1(pat, index, target, newCasted, env); + case SequencePat(Symbol newCasted, int len): + return enter1(pat, index, target, newCasted, env); + default: + return enter1(pat, index, target, casted, env); } } @@ -431,14 +387,14 @@ public class PatternMatcher extends PatternTool { Tree accTree = gen.Select( ident, ts); switch (accType) { // scala case accessor - case MethodType(_, _): - return mk.Header( - pos, - accType.resultType(), - gen.mkApply__(accTree)); - // jaco case accessor - default: - return mk.Header(pos, accType, accTree); + case MethodType(_, _): + return mk.Header( + pos, + accType.resultType(), + gen.mkApply__(accTree)); + // jaco case accessor + default: + return mk.Header(pos, accType, accTree); } } } @@ -452,52 +408,45 @@ public class PatternMatcher extends PatternTool { PatternNode target, Symbol casted, CaseEnv env) { - //System.err.println("enter(" + pat + ", " + index + ", " + target + ", " + casted + ")"); - + //System.err.println("enter(" + pat + ", " + index + ", " + target + ", " + casted + ")"); Tree[] patArgs = patternArgs(pat); // get pattern arguments Header curHeader = (Header)target.and; // advance one step in intermediate representation if (curHeader == null) { // check if we have to add a new header assert index >= 0 : casted; - target.and = curHeader = newHeader( pat.pos, casted, index ); - curHeader.or = patternNode( pat, curHeader, env ); - return enter( patArgs, curHeader.or, casted, env ); + target.and = curHeader = newHeader(pat.pos, casted, index); + curHeader.or = patternNode(pat, curHeader, env); + return enter(patArgs, curHeader.or, casted, env); } - // find most recent header while (curHeader.next != null) curHeader = curHeader.next; // create node PatternNode patNode = patternNode(pat, curHeader, env); PatternNode next = curHeader; - // add branch to curHeader, but reuse tests if possible while (true) - if ( next.isSameAs( patNode ) ) { // test for patNode already present --> reuse + if (next.isSameAs(patNode)) { // test for patNode already present --> reuse // substitute... !!! - switch( patNode ) { - case ConstrPat( Symbol ocasted ): - env.substitute( ocasted, gen.Ident(patNode.pos, - ((ConstrPat) next).casted)); + switch(patNode) { + case ConstrPat( Symbol ocasted ): + env.substitute(ocasted, gen.Ident(patNode.pos, + ((ConstrPat) next).casted)); } return enter(patArgs, next, casted, env); - } - else if ( next.isDefaultPat() || // default case reached, or - ((next.or == null) && // no more alternatives and - ( patNode.isDefaultPat() || next.subsumes( patNode )))) { - // new node is default or subsumed - - return enter( // create independent new header , because cannot use this one - patArgs, - (curHeader = (curHeader.next = - mk.Header(patNode.pos, curHeader.type, curHeader.selector))).or - = patNode, + } else if (next.isDefaultPat() || // default case reached, or + ((next.or == null) && // no more alternatives and + (patNode.isDefaultPat() || next.subsumes(patNode)))) { + // new node is default or subsumed + return enter(patArgs, + (curHeader = + (curHeader.next = + mk.Header(patNode.pos, curHeader.type, curHeader.selector))).or = + patNode, casted, env); - } - else if (next.or == null) { + } else if (next.or == null) { return enter(patArgs, next.or = patNode, casted, env); // add new branch - } - else + } else next = next.or; } @@ -505,13 +454,13 @@ public class PatternMatcher extends PatternTool { */ protected PatternNode enter(Tree[] pats, PatternNode target, Symbol casted, CaseEnv env) { switch (target) { - case ConstrPat(Symbol newCasted): - casted = newCasted; - break; - case SequencePat(Symbol newCasted, int len): - casted = newCasted; - break; - } + case ConstrPat(Symbol newCasted): + casted = newCasted; + break; + case SequencePat(Symbol newCasted, int len): + casted = newCasted; + break; + } for (int i = 0; i < pats.length; i++) target = enter1(pats[i], i, target, casted, env); return target; @@ -519,25 +468,25 @@ public class PatternMatcher extends PatternTool { protected int nCaseComponents(Tree tree) { switch (tree) { - case Apply(Tree fn, _): - Type tpe = tree.type.symbol().primaryConstructor().type(); - //System.out.println("~~~ " + tree.type() + ", " + tree.type().symbol().primaryConstructor()); - switch (tpe) { - // I'm not sure if this is a good idea, but obviously, currently all case classes - // without constructor arguments have type NoType - case NoType: - assert false; - return 0; - case MethodType(Symbol[] args, _): - return args.length; - case PolyType(Symbol[] tvars, MethodType(Symbol[] args, _)): - return args.length; - case PolyType(Symbol[] tvars, _): - return 0; - default: - throw new ApplicationError("not yet implemented;" + - "pattern matching for " + tree + ": " + tpe); - } + case Apply(Tree fn, _): + Type tpe = tree.type.symbol().primaryConstructor().type(); + //System.out.println("~~~ " + tree.type() + ", " + tree.type().symbol().primaryConstructor()); + switch (tpe) { + // I'm not sure if this is a good idea, but obviously, currently all case classes + // without constructor arguments have type NoType + case NoType: + assert false; + return 0; + case MethodType(Symbol[] args, _): + return args.length; + case PolyType(Symbol[] tvars, MethodType(Symbol[] args, _)): + return args.length; + case PolyType(Symbol[] tvars, _): + return 0; + default: + throw new ApplicationError("not yet implemented;" + + "pattern matching for " + tree + ": " + tpe); + } } return 0; } @@ -561,20 +510,20 @@ public class PatternMatcher extends PatternTool { PatternNode node = patNode; while ((node = node.or) != null) { switch (node) { - case ConstantPat(_): - break; - default: - return false; + case ConstantPat(_): + break; + default: + return false; } switch (node.and) { - case Body(ValDef[][] bound, Tree[] guard, _): - if ((guard.length > 1) || - (guard[0] != Tree.Empty) || - (bound[0].length > 0)) - return false; - break; - default: - return false; + case Body(ValDef[][] bound, Tree[] guard, _): + if ((guard.length > 1) || + (guard[0] != Tree.Empty) || + (bound[0].length > 0)) + return false; + break; + default: + return false; } } patNode = patNode.next(); @@ -592,35 +541,35 @@ public class PatternMatcher extends PatternTool { while ((node = node.or) != null) { boolean isCase = false; switch (node) { - case VariablePat(Tree tree): - System.out.println(((tree.symbol().flags & Modifiers.CASE) != 0)); - break; - case ConstrPat(_): - System.out.println(node.type + " / " + ((node.type.symbol().flags & Modifiers.CASE) != 0)); - PatternNode inner = node.and; - outer: while (true) { - switch (inner) { - case Header(_, Header next): - if (next != null) - return false; - inner = inner.or; - break; - case DefaultPat(): - inner = inner.and; - break; - case Body(ValDef[][] bound, Tree[] guard, _): - if ((guard.length > 1) || - (guard[0] != Tree.Empty)) - return false; - break outer; - default: - System.out.println(inner); - return false; - } - } - break; - default: - return false; + case VariablePat(Tree tree): + System.out.println(((tree.symbol().flags & Modifiers.CASE) != 0)); + break; + case ConstrPat(_): + System.out.println(node.type + " / " + ((node.type.symbol().flags & Modifiers.CASE) != 0)); + PatternNode inner = node.and; + outer: while (true) { + switch (inner) { + case Header(_, Header next): + if (next != null) + return false; + inner = inner.or; + break; + case DefaultPat(): + inner = inner.and; + break; + case Body(ValDef[][] bound, Tree[] guard, _): + if ((guard.length > 1) || + (guard[0] != Tree.Empty)) + return false; + break outer; + default: + System.out.println(inner); + return false; + } + } + break; + default: + return false; } } patNode = patNode.next(); @@ -657,10 +606,10 @@ public class PatternMatcher extends PatternTool { int n = 0; while ((patNode = patNode.or) != null) switch (patNode) { - case DefaultPat(): - break; - default: - n++; + case DefaultPat(): + break; + default: + n++; } return n; } @@ -670,8 +619,8 @@ public class PatternMatcher extends PatternTool { PatternNode node = patNode; while ((node = node.or) != null) switch (node) { - case DefaultPat(): - return bodyToTree(node.and); + case DefaultPat(): + return bodyToTree(node.and); } patNode = patNode.next(); } @@ -691,72 +640,70 @@ public class PatternMatcher extends PatternTool { // for one case we use a normal if-then-else instruction else if (ncases == 1) { switch (root.and.or) { - case ConstantPat(AConstant value): - return gen.If( - cf.Equals(selector, - gen.Literal(root.and.or.pos, value)), - bodyToTree(root.and.or.and), - defaultBody(root.and, matchError)); - default: - return generalSwitchToTree(); + case ConstantPat(AConstant value): + return gen.If(cf.Equals(selector, + gen.Literal(root.and.or.pos, value)), + bodyToTree(root.and.or.and), + defaultBody(root.and, matchError)); + default: + return generalSwitchToTree(); } } + // // if we have more than 2 cases than use a switch statement switch (root.and) { - case Header(_, Header next): - TagBodyPair mappings = null; - Tree defaultBody = null; - PatternNode patNode = root.and; - while (patNode != null) { - PatternNode node = patNode.or; - while (node != null) { - switch (node) { - case DefaultPat(): - if (defaultBody != null) - throw new ApplicationError(); - defaultBody = bodyToTree(node.and); - node = node.or; - break; - case ConstantPat(INT(int value)): - mappings = insert( - value, - bodyToTree(node.and), - mappings); - node = node.or; - break; - default: - throw new ApplicationError(node.toString()); - } - } - patNode = patNode.next(); - } - if (defaultBody == null) - defaultBody = cf.ThrowMatchError(selector.pos, resultVar.getType()); - if (mappings == null) { - return gen.Switch(selector, new int[0], new Tree[0], defaultBody, resultVar.getType()); - } else { - int n = mappings.length(); - int[] tags = new int[n]; - Tree[] bodies = new Tree[n]; - n = 0; - while (mappings != null) { - tags[n] = mappings.tag; - bodies[n++] = mappings.body; - mappings = mappings.next; - } - return gen.Switch(selector, tags, bodies, defaultBody, resultVar.getType()); - } - default: - throw new ApplicationError(); + case Header(_, Header next): + TagBodyPair mappings = null; + Tree defaultBody = matchError; + PatternNode patNode = root.and; + while (patNode != null) { + PatternNode node = patNode.or; + while (node != null) { + switch (node) { + case DefaultPat(): + if (defaultBody != null) + throw new ApplicationError(); + defaultBody = bodyToTree(node.and); + node = node.or; + break; + case ConstantPat(INT(int value)): + mappings = insert( + value, + bodyToTree(node.and), + mappings); + node = node.or; + break; + default: + throw new ApplicationError(node.toString()); + } + } + patNode = patNode.next(); + } + if (mappings == null) { + return gen.Switch(selector, new int[0], new Tree[0], defaultBody, resultVar.getType()); + } else { + int n = mappings.length(); + int[] tags = new int[n]; + Tree[] bodies = new Tree[n]; + n = 0; + while (mappings != null) { + tags[n] = mappings.tag; + bodies[n++] = mappings.body; + mappings = mappings.next; + } + return gen.Switch(selector, tags, bodies, defaultBody, resultVar.getType()); + } + default: + throw new ApplicationError(); } } protected Tree bodyToTree(PatternNode node) { switch (node) { - case Body(_, _, Tree[] body): - return body[0]; - default: - throw new ApplicationError(); + case Body(_, _, Tree[] body): + return body[0]; + default: + throw new ApplicationError(); } } @@ -772,7 +719,7 @@ public class PatternMatcher extends PatternTool { selector.pos, toTree(root.and), gen.Ident(selector.pos, resultVar), - cf.ThrowMatchError(selector.pos, resultVar.getType())); + cf.ThrowMatchError(selector.pos, resultVar.getType(), gen.Ident(selector.pos, root.symbol()))); return gen.mkBlock(selector.pos, ts, res); } @@ -780,36 +727,34 @@ public class PatternMatcher extends PatternTool { Tree res = gen.mkBooleanLit(node.pos, false); while (node != null) switch (node) { - case Header(Tree selector, Header next): - //res = cf.And(mkNegate(res), toTree(node.or, selector)); - //System.out.println("HEADER TYPE = " + selector.type); - if (optimize(node.type, node.or)) - res = cf.Or(res, toOptTree(node.or, selector)); - else - res = cf.Or(res, toTree(node.or, selector)); - node = next; - break; - case Body(ValDef[][] bound, Tree[] guard, Tree[] body): - if ((bound.length == 0) && - (guard.length == 0) && - (body.length == 0)) { - return gen.mkBooleanLit(node.pos, true); // cf.Or(res, gen.mkBooleanLit(node.pos, true)); - } else if (!doBinding) - bound = new ValDef[][]{new ValDef[]{}}; - for (int i = guard.length - 1; i >= 0; i--) { - Tree[] ts = bound[i]; - Tree res0 = gen.mkBlock( - gen.Assign( - gen.Ident(body[i].pos, resultVar), - body[i]), - gen.mkBooleanLit(body[i].pos, true)); - if (guard[i] != Tree.Empty) - res0 = cf.And(guard[i], res0); - res = cf.Or(gen.mkBlock(body[i].pos, ts, res0), res); - } - return res; - default: - throw new ApplicationError(); + case Header(Tree selector, Header next): + //res = cf.And(mkNegate(res), toTree(node.or, selector)); + //System.out.println("HEADER TYPE = " + selector.type); + if (optimize(node.type, node.or)) + res = cf.Or(res, toOptTree(node.or, selector)); + else + res = cf.Or(res, toTree(node.or, selector)); + node = next; + break; + case Body(ValDef[][] bound, Tree[] guard, Tree[] body): + if ((bound.length == 0) && + (guard.length == 0) && + (body.length == 0)) { + return gen.mkBooleanLit(node.pos, true); // cf.Or(res, gen.mkBooleanLit(node.pos, true)); + } else if (!doBinding) + bound = new ValDef[][]{new ValDef[]{}}; + for (int i = guard.length - 1; i >= 0; i--) { + Tree[] ts = bound[i]; + Tree res0 = gen.mkBlock(gen.Assign(gen.Ident(body[i].pos, resultVar), + body[i]), + gen.mkBooleanLit(body[i].pos, true)); + if (guard[i] != Tree.Empty) + res0 = cf.And(guard[i], res0); + res = cf.Or(gen.mkBlock(body[i].pos, ts, res0), res); + } + return res; + default: + throw new ApplicationError(); } return res; } @@ -820,16 +765,16 @@ public class PatternMatcher extends PatternTool { int cases = 0; while (alternatives != null) { switch (alternatives) { - case ConstrPat(_): - if (alternatives.type.symbol().isCaseClass()) - cases++; - else - return false; - break; - case DefaultPat(): - break; - default: - return false; + case ConstrPat(_): + if (alternatives.type.symbol().isCaseClass()) + cases++; + else + return false; + break; + case DefaultPat(): + break; + default: + return false; } alternatives = alternatives.or; } @@ -877,16 +822,16 @@ public class PatternMatcher extends PatternTool { PatternNode defaultCase = null; while (node != null) switch (node) { - case ConstrPat(Symbol casted): - cases = insertNode(node.type.symbol().tag(), node, cases); - node = node.or; - break; - case DefaultPat(): - defaultCase = node; - node = node.or; - break; - default: - throw new ApplicationError(); + case ConstrPat(Symbol casted): + cases = insertNode(node.type.symbol().tag(), node, cases); + node = node.or; + break; + case DefaultPat(): + defaultCase = node; + node = node.or; + break; + default: + throw new ApplicationError(); } int n = cases.length(); int[] tags = new int[n]; @@ -897,8 +842,7 @@ public class PatternMatcher extends PatternTool { bodies[n++] = toTree(cases.node, selector); cases = cases.next; } - return gen.Switch( - gen.mkApply__(gen.Select(selector.duplicate(), defs.SCALAOBJECT_TAG())), + return gen.Switch(gen.mkApply__(gen.Select(selector.duplicate(), defs.SCALAOBJECT_TAG())), tags, bodies, (defaultCase == null) ? gen.mkBooleanLit(selector.pos, false) @@ -911,50 +855,38 @@ public class PatternMatcher extends PatternTool { if (node == null) return gen.mkBooleanLit(selector.pos, false); switch (node) { - case DefaultPat(): - return toTree(node.and); - case ConstrPat(Symbol casted): - return gen.If( - gen.mkIsInstanceOf(selector.duplicate(), node.type), - gen.mkBlock( - gen.ValDef(casted, - gen.mkAsInstanceOf(selector.duplicate(), node.type)), - toTree(node.and)), - toTree(node.or, selector.duplicate())); - case SequencePat(Symbol casted, int len): - return gen.If( - cf.And( - gen.mkIsInstanceOf(selector.duplicate(), node.type), - cf.Equals( - gen.mkApply__( - gen.Select( - gen.mkAsInstanceOf( - selector.duplicate(), node.type), - defs.SEQ_LENGTH())), - gen.mkIntLit(selector.pos, len))), - gen.mkBlock( - gen.ValDef(casted, - gen.mkAsInstanceOf(selector.duplicate(), node.type)), - toTree(node.and)), - toTree(node.or, selector.duplicate())); - case ConstantPat(AConstant value): - return gen.If( - cf.Equals(selector.duplicate(), - gen.Literal(selector.pos, value)), - toTree(node.and), - toTree(node.or, selector.duplicate())); - case VariablePat(Tree tree): - return gen.If( - cf.Equals(selector.duplicate(), tree), - toTree(node.and), - toTree(node.or, selector.duplicate())); - case AltPat(Header header): - return gen.If( - toTree(header), - toTree(node.and), - toTree(node.or, selector.duplicate())); - default: - throw new ApplicationError(); + case DefaultPat(): + return toTree(node.and); + case ConstrPat(Symbol casted): + return gen.If(gen.mkIsInstanceOf(selector.duplicate(), node.type), + gen.mkBlock(gen.ValDef(casted, + gen.mkAsInstanceOf(selector.duplicate(), node.type)), + toTree(node.and)), + toTree(node.or, selector.duplicate())); + case SequencePat(Symbol casted, int len): + return gen.If(cf.And(gen.mkIsInstanceOf(selector.duplicate(), node.type), + cf.Equals(gen.mkApply__(gen.Select(gen.mkAsInstanceOf(selector.duplicate(), node.type), + defs.SEQ_LENGTH())), + gen.mkIntLit(selector.pos, len))), + gen.mkBlock(gen.ValDef(casted, + gen.mkAsInstanceOf(selector.duplicate(), node.type)), + toTree(node.and)), + toTree(node.or, selector.duplicate())); + case ConstantPat(AConstant value): + return gen.If(cf.Equals(selector.duplicate(), + gen.Literal(selector.pos, value)), + toTree(node.and), + toTree(node.or, selector.duplicate())); + case VariablePat(Tree tree): + return gen.If(cf.Equals(selector.duplicate(), tree), + toTree(node.and), + toTree(node.or, selector.duplicate())); + case AltPat(Header header): + return gen.If(toTree(header), + toTree(node.and), + toTree(node.or, selector.duplicate())); + default: + throw new ApplicationError(); } } } |