summaryrefslogtreecommitdiff
path: root/sources/scalac/transformer/matching
diff options
context:
space:
mode:
authorMatthias Zenger <mzenger@gmail.com>2004-03-08 10:51:36 +0000
committerMatthias Zenger <mzenger@gmail.com>2004-03-08 10:51:36 +0000
commitce039b7db18521e8fadf244099ed90ad1020ec5e (patch)
treefced47f3961d311587daeddcf6914e017be9fd2b /sources/scalac/transformer/matching
parent8ba6023e7aa181b4e7e3206caf29c0550315f5b4 (diff)
downloadscala-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.java11
-rw-r--r--sources/scalac/transformer/matching/PatternMatcher.java986
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();
}
}
}