diff options
author | Matthias Zenger <mzenger@gmail.com> | 2003-03-04 10:17:37 +0000 |
---|---|---|
committer | Matthias Zenger <mzenger@gmail.com> | 2003-03-04 10:17:37 +0000 |
commit | 9700a2088f806754bd8dd3d72b8d077f7b858079 (patch) | |
tree | c5ad8f462cba6f254657db4649764ef01614c4cf | |
parent | 95a5ffa2017e789cdcbbf9b7fe3f94f1b1eb788b (diff) | |
download | scala-9700a2088f806754bd8dd3d72b8d077f7b858079.tar.gz scala-9700a2088f806754bd8dd3d72b8d077f7b858079.tar.bz2 scala-9700a2088f806754bd8dd3d72b8d077f7b858079.zip |
* implemented new sequence patterns
* optimized code generation routines
-rw-r--r-- | sources/scalac/transformer/PatternMatcher.java | 171 | ||||
-rw-r--r-- | sources/scalac/transformer/PatternNode.java | 5 | ||||
-rw-r--r-- | sources/scalac/transformer/matching/PatternMatcher.java | 171 | ||||
-rw-r--r-- | sources/scalac/transformer/matching/PatternNode.java | 5 |
4 files changed, 302 insertions, 50 deletions
diff --git a/sources/scalac/transformer/PatternMatcher.java b/sources/scalac/transformer/PatternMatcher.java index 5b5d932954..4dfe5f3de6 100644 --- a/sources/scalac/transformer/PatternMatcher.java +++ b/sources/scalac/transformer/PatternMatcher.java @@ -32,6 +32,8 @@ public class PatternMatcher { public static final Name MATCHERROR_N = Name.fromString("MatchError"); public static final Name FAIL_N = Name.fromString("fail"); public static final Name WILDCARD_N = Name.fromString("_"); + public static final Name LENGTH_N = Name.fromString("length"); + public static final Name AT_N = Name.fromString("at"); /** the current compilation unit */ @@ -97,12 +99,12 @@ public class PatternMatcher { this.owner = owner; this.selector = selector; this.root = makeConstrPat(selector.pos, - selector.type); + selector.type.widen()); this.root.and = makeHeader(selector.pos, - selector.type, + selector.type.widen(), make.Ident(selector.pos, root.symbol().name) - .setType(selector.type) + .setType(selector.type.widen()) .setSymbol(root.symbol())); this.resultVar = new TermSymbol(selector.pos, RESULT_N, @@ -174,6 +176,14 @@ public class PatternMatcher { return node; } + public SequencePat makeSequencePat(int pos, Type type, int len) { + Symbol sym = newVar(Position.NOPOS, type); + SequencePat node = new SequencePat(sym, len); + node.pos = pos; + node.type = type; + return node; + } + public ConstantPat makeConstantPat(int pos, Type type, Object value) { ConstantPat node = new ConstantPat(value); node.pos = pos; @@ -232,6 +242,20 @@ public class PatternMatcher { 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) + @@ -331,6 +355,11 @@ public class PatternMatcher { protected Tree[] patternArgs(Tree tree) { switch (tree) { case Apply(_, Tree[] args): + if (args.length == 1) + switch (args[0]) { + case Tuple(Tree[] ts): + return ts; + } return args; default: return Tree.EMPTY_ARRAY; @@ -359,7 +388,12 @@ public class PatternMatcher { protected PatternNode patternNode(Tree tree, Header header, CaseEnv env) { switch (tree) { - case Apply(_, _): // pattern with args + case Apply(Tree fn, Tree[] args): // pattern with args + if (args.length == 1) + switch (args[0]) { + case Tuple(Tree[] ts): + return makeSequencePat(tree.pos, tree.type, ts.length); + } return makeConstrPat(tree.pos, getConstrType(tree.type)); case Typed(Ident(Name name), Tree tpe): // variable pattern if ((env != null) && (name != WILDCARD_N)) @@ -399,13 +433,19 @@ public class PatternMatcher { // return q.type.isSubType(p.type); } return false; - case ConstrPat(_): + case ConstrPat(_): switch (q) { case ConstrPat(_): return q.type.isSubType(p.type); } return false; - case ConstantPat(Object pval): + case SequencePat(_, int plen): + switch (q) { + case SequencePat(_, int qlen): + return (plen == qlen) && q.type.isSubType(p.type); + } + return false; + case ConstantPat(Object pval): switch (q) { case ConstantPat(Object qval): return pval.equals(qval); @@ -432,6 +472,8 @@ public class PatternMatcher { 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); } @@ -446,30 +488,62 @@ public class PatternMatcher { // get pattern arguments Tree[] patArgs = patternArgs(pat); // get case fields - assert patArgs.length == nCaseComponents(pat); + //assert patArgs.length == nCaseComponents(pat); // advance one step in pattern Header curHeader = (Header)target.and; // check if we have to add a new header if (curHeader == null) { assert index >= 0 : casted; - Symbol ts = ((ClassSymbol) casted.type().symbol()) - .caseFieldAccessor(index); - target.and = curHeader = makeHeader( - pat.pos, - getHeaderType(typeOf0(ts)), - make.Apply( + if (casted.pos == Position.NOPOS) { + Symbol atSym = casted.type().lookup(AT_N); + //System.out.println("casted type = " + typeOf(casted)); + Type seqType = casted.type().baseType(defs.SEQ_CLASS).typeArgs()[0]; + Tree t = make.Select( + pat.pos, + make.Ident(pat.pos, casted.name) + .setType(typeOf(casted)) + .setSymbol(casted), + AT_N); + switch (typeOf(atSym)) { + case OverloadedType(Symbol[] alts, Type[] alttypes): + infer.methodAlternative(t, alts, alttypes, + new Type[]{defs.INT_TYPE}, seqType); + t = make.Apply(pat.pos, t, + new Tree[]{ + make.Literal(pat.pos, new Integer(index)) + .setType(defs.INT_TYPE) + }).setType(seqType); + break; + default: + t.setSymbol(atSym); + t.setType(typeOf(atSym)); + t = make.Apply(pat.pos, t, + new Tree[]{ + make.Literal(pat.pos, new Integer(index)) + .setType(defs.INT_TYPE) + }).setType(seqType); + } + target.and = curHeader = makeHeader(pat.pos, seqType, t); + } else { + Symbol ts = ((ClassSymbol) casted.type().symbol()) + .caseFieldAccessor(index); + target.and = curHeader = makeHeader( pat.pos, - make.Select( + getHeaderType(typeOf0(ts)), + make.Apply( pat.pos, - make.Ident(pat.pos, casted.name) - .setType(typeOf(casted)) - .setSymbol(casted), - ts.name) - .setType(Type.MethodType( - Symbol.EMPTY_ARRAY, - getHeaderType(typeOf0(ts)))) - .setSymbol(ts), - Tree.EMPTY_ARRAY).setType(getHeaderType(typeOf0(ts)))); + make.Select( + pat.pos, + make.Ident(pat.pos, casted.name) + .setType(typeOf(casted)) + .setSymbol(casted), + ts.name) + .setType(Type.MethodType( + Symbol.EMPTY_ARRAY, + getHeaderType(typeOf0(ts)))) + .setSymbol(ts), + Tree.EMPTY_ARRAY).setType(getHeaderType(typeOf0(ts)))); + } curHeader.or = patternNode(pat, curHeader, env); return enter(patArgs, curHeader.or, casted, env); } @@ -502,6 +576,10 @@ public class PatternMatcher { switch (target) { 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); @@ -612,6 +690,43 @@ public class PatternMatcher { .setType(defs.UNIT_TYPE).setSymbol(casted), toTree(node.and)}, defs.BOOLEAN_TYPE), toTree(node.or, selector)).setType(defs.BOOLEAN_TYPE); + case SequencePat(Symbol casted, int len): + Symbol lenSym = casted.type().lookup(LENGTH_N); + Tree t = make.Select(selector.pos, + make.Ident(selector.pos, casted.name) + .setSymbol(casted) + .setType(node.type), + LENGTH_N); + switch (typeOf(lenSym)) { + case OverloadedType(Symbol[] alts, Type[] alttypes): + infer.methodAlternative(t, alts, alttypes, new Type[0], defs.INT_TYPE); + break; + default: + t.setSymbol(lenSym); + t.setType(typeOf(lenSym)); + } + return make.If( + selector.pos, + mkIs(selector, node.type), + mkBlock(selector.pos, + new Tree[]{ + make.ValDef(selector.pos, + 0, + casted.name, + gen.mkType(selector.pos, node.type), + mkAs(selector, node.type)) + .setType(defs.UNIT_TYPE).setSymbol(casted), + mkAnd( + mkEquals( + make.Apply( + selector.pos, t, + Tree.EMPTY_ARRAY) + .setType(defs.INT_TYPE), + make.Literal(selector.pos, new Integer(len)) + .setType(defs.INT_TYPE)), + toTree(node.and))}, defs.BOOLEAN_TYPE), + toTree(node.or, selector)) + .setType(defs.BOOLEAN_TYPE); case ConstantPat(Object value): return make.If( selector.pos, @@ -691,7 +806,10 @@ public class PatternMatcher { return right; else if (left.symbol() == falseSym) return left; - else if (right.symbol() == trueSym) + } + switch (right) { + case Select(_, _): + if (right.symbol() == trueSym) return left; } Symbol fun = left.type.lookup(AND_N); @@ -711,7 +829,10 @@ public class PatternMatcher { return left; else if (left.symbol() == falseSym) return right; - else if (right.symbol() == falseSym) + } + switch (right) { + case Select(_, _): + if (right.symbol() == falseSym) return left; } Symbol fun = left.type.lookup(OR_N); diff --git a/sources/scalac/transformer/PatternNode.java b/sources/scalac/transformer/PatternNode.java index 24404d0242..506fad2708 100644 --- a/sources/scalac/transformer/PatternNode.java +++ b/sources/scalac/transformer/PatternNode.java @@ -24,6 +24,7 @@ public class PatternNode { public case Body(Tree.ValDef[][] bound, Tree[] guard, Tree[] body); public case DefaultPat(); public case ConstrPat(Symbol casted); + public case SequencePat(Symbol casted, int len); public case ConstantPat(Object value); public case VariablePat(Tree tree); @@ -32,6 +33,8 @@ public class PatternNode { switch (this) { case ConstrPat(Symbol casted): return casted; + case SequencePat(Symbol casted, _): + return casted; default: return Symbol.NONE; } @@ -47,6 +50,8 @@ public class PatternNode { return "DefaultPat"; case ConstrPat(Symbol casted): return "ConstrPat(" + casted + ")"; + case SequencePat(Symbol casted, int len): + return "SequencePat(" + casted + ", " + len + ")"; case ConstantPat(Object value): return "ConstantPat(" + value + ")"; case VariablePat(Tree tree): diff --git a/sources/scalac/transformer/matching/PatternMatcher.java b/sources/scalac/transformer/matching/PatternMatcher.java index 5b5d932954..4dfe5f3de6 100644 --- a/sources/scalac/transformer/matching/PatternMatcher.java +++ b/sources/scalac/transformer/matching/PatternMatcher.java @@ -32,6 +32,8 @@ public class PatternMatcher { public static final Name MATCHERROR_N = Name.fromString("MatchError"); public static final Name FAIL_N = Name.fromString("fail"); public static final Name WILDCARD_N = Name.fromString("_"); + public static final Name LENGTH_N = Name.fromString("length"); + public static final Name AT_N = Name.fromString("at"); /** the current compilation unit */ @@ -97,12 +99,12 @@ public class PatternMatcher { this.owner = owner; this.selector = selector; this.root = makeConstrPat(selector.pos, - selector.type); + selector.type.widen()); this.root.and = makeHeader(selector.pos, - selector.type, + selector.type.widen(), make.Ident(selector.pos, root.symbol().name) - .setType(selector.type) + .setType(selector.type.widen()) .setSymbol(root.symbol())); this.resultVar = new TermSymbol(selector.pos, RESULT_N, @@ -174,6 +176,14 @@ public class PatternMatcher { return node; } + public SequencePat makeSequencePat(int pos, Type type, int len) { + Symbol sym = newVar(Position.NOPOS, type); + SequencePat node = new SequencePat(sym, len); + node.pos = pos; + node.type = type; + return node; + } + public ConstantPat makeConstantPat(int pos, Type type, Object value) { ConstantPat node = new ConstantPat(value); node.pos = pos; @@ -232,6 +242,20 @@ public class PatternMatcher { 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) + @@ -331,6 +355,11 @@ public class PatternMatcher { protected Tree[] patternArgs(Tree tree) { switch (tree) { case Apply(_, Tree[] args): + if (args.length == 1) + switch (args[0]) { + case Tuple(Tree[] ts): + return ts; + } return args; default: return Tree.EMPTY_ARRAY; @@ -359,7 +388,12 @@ public class PatternMatcher { protected PatternNode patternNode(Tree tree, Header header, CaseEnv env) { switch (tree) { - case Apply(_, _): // pattern with args + case Apply(Tree fn, Tree[] args): // pattern with args + if (args.length == 1) + switch (args[0]) { + case Tuple(Tree[] ts): + return makeSequencePat(tree.pos, tree.type, ts.length); + } return makeConstrPat(tree.pos, getConstrType(tree.type)); case Typed(Ident(Name name), Tree tpe): // variable pattern if ((env != null) && (name != WILDCARD_N)) @@ -399,13 +433,19 @@ public class PatternMatcher { // return q.type.isSubType(p.type); } return false; - case ConstrPat(_): + case ConstrPat(_): switch (q) { case ConstrPat(_): return q.type.isSubType(p.type); } return false; - case ConstantPat(Object pval): + case SequencePat(_, int plen): + switch (q) { + case SequencePat(_, int qlen): + return (plen == qlen) && q.type.isSubType(p.type); + } + return false; + case ConstantPat(Object pval): switch (q) { case ConstantPat(Object qval): return pval.equals(qval); @@ -432,6 +472,8 @@ public class PatternMatcher { 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); } @@ -446,30 +488,62 @@ public class PatternMatcher { // get pattern arguments Tree[] patArgs = patternArgs(pat); // get case fields - assert patArgs.length == nCaseComponents(pat); + //assert patArgs.length == nCaseComponents(pat); // advance one step in pattern Header curHeader = (Header)target.and; // check if we have to add a new header if (curHeader == null) { assert index >= 0 : casted; - Symbol ts = ((ClassSymbol) casted.type().symbol()) - .caseFieldAccessor(index); - target.and = curHeader = makeHeader( - pat.pos, - getHeaderType(typeOf0(ts)), - make.Apply( + if (casted.pos == Position.NOPOS) { + Symbol atSym = casted.type().lookup(AT_N); + //System.out.println("casted type = " + typeOf(casted)); + Type seqType = casted.type().baseType(defs.SEQ_CLASS).typeArgs()[0]; + Tree t = make.Select( + pat.pos, + make.Ident(pat.pos, casted.name) + .setType(typeOf(casted)) + .setSymbol(casted), + AT_N); + switch (typeOf(atSym)) { + case OverloadedType(Symbol[] alts, Type[] alttypes): + infer.methodAlternative(t, alts, alttypes, + new Type[]{defs.INT_TYPE}, seqType); + t = make.Apply(pat.pos, t, + new Tree[]{ + make.Literal(pat.pos, new Integer(index)) + .setType(defs.INT_TYPE) + }).setType(seqType); + break; + default: + t.setSymbol(atSym); + t.setType(typeOf(atSym)); + t = make.Apply(pat.pos, t, + new Tree[]{ + make.Literal(pat.pos, new Integer(index)) + .setType(defs.INT_TYPE) + }).setType(seqType); + } + target.and = curHeader = makeHeader(pat.pos, seqType, t); + } else { + Symbol ts = ((ClassSymbol) casted.type().symbol()) + .caseFieldAccessor(index); + target.and = curHeader = makeHeader( pat.pos, - make.Select( + getHeaderType(typeOf0(ts)), + make.Apply( pat.pos, - make.Ident(pat.pos, casted.name) - .setType(typeOf(casted)) - .setSymbol(casted), - ts.name) - .setType(Type.MethodType( - Symbol.EMPTY_ARRAY, - getHeaderType(typeOf0(ts)))) - .setSymbol(ts), - Tree.EMPTY_ARRAY).setType(getHeaderType(typeOf0(ts)))); + make.Select( + pat.pos, + make.Ident(pat.pos, casted.name) + .setType(typeOf(casted)) + .setSymbol(casted), + ts.name) + .setType(Type.MethodType( + Symbol.EMPTY_ARRAY, + getHeaderType(typeOf0(ts)))) + .setSymbol(ts), + Tree.EMPTY_ARRAY).setType(getHeaderType(typeOf0(ts)))); + } curHeader.or = patternNode(pat, curHeader, env); return enter(patArgs, curHeader.or, casted, env); } @@ -502,6 +576,10 @@ public class PatternMatcher { switch (target) { 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); @@ -612,6 +690,43 @@ public class PatternMatcher { .setType(defs.UNIT_TYPE).setSymbol(casted), toTree(node.and)}, defs.BOOLEAN_TYPE), toTree(node.or, selector)).setType(defs.BOOLEAN_TYPE); + case SequencePat(Symbol casted, int len): + Symbol lenSym = casted.type().lookup(LENGTH_N); + Tree t = make.Select(selector.pos, + make.Ident(selector.pos, casted.name) + .setSymbol(casted) + .setType(node.type), + LENGTH_N); + switch (typeOf(lenSym)) { + case OverloadedType(Symbol[] alts, Type[] alttypes): + infer.methodAlternative(t, alts, alttypes, new Type[0], defs.INT_TYPE); + break; + default: + t.setSymbol(lenSym); + t.setType(typeOf(lenSym)); + } + return make.If( + selector.pos, + mkIs(selector, node.type), + mkBlock(selector.pos, + new Tree[]{ + make.ValDef(selector.pos, + 0, + casted.name, + gen.mkType(selector.pos, node.type), + mkAs(selector, node.type)) + .setType(defs.UNIT_TYPE).setSymbol(casted), + mkAnd( + mkEquals( + make.Apply( + selector.pos, t, + Tree.EMPTY_ARRAY) + .setType(defs.INT_TYPE), + make.Literal(selector.pos, new Integer(len)) + .setType(defs.INT_TYPE)), + toTree(node.and))}, defs.BOOLEAN_TYPE), + toTree(node.or, selector)) + .setType(defs.BOOLEAN_TYPE); case ConstantPat(Object value): return make.If( selector.pos, @@ -691,7 +806,10 @@ public class PatternMatcher { return right; else if (left.symbol() == falseSym) return left; - else if (right.symbol() == trueSym) + } + switch (right) { + case Select(_, _): + if (right.symbol() == trueSym) return left; } Symbol fun = left.type.lookup(AND_N); @@ -711,7 +829,10 @@ public class PatternMatcher { return left; else if (left.symbol() == falseSym) return right; - else if (right.symbol() == falseSym) + } + switch (right) { + case Select(_, _): + if (right.symbol() == falseSym) return left; } Symbol fun = left.type.lookup(OR_N); diff --git a/sources/scalac/transformer/matching/PatternNode.java b/sources/scalac/transformer/matching/PatternNode.java index 24404d0242..506fad2708 100644 --- a/sources/scalac/transformer/matching/PatternNode.java +++ b/sources/scalac/transformer/matching/PatternNode.java @@ -24,6 +24,7 @@ public class PatternNode { public case Body(Tree.ValDef[][] bound, Tree[] guard, Tree[] body); public case DefaultPat(); public case ConstrPat(Symbol casted); + public case SequencePat(Symbol casted, int len); public case ConstantPat(Object value); public case VariablePat(Tree tree); @@ -32,6 +33,8 @@ public class PatternNode { switch (this) { case ConstrPat(Symbol casted): return casted; + case SequencePat(Symbol casted, _): + return casted; default: return Symbol.NONE; } @@ -47,6 +50,8 @@ public class PatternNode { return "DefaultPat"; case ConstrPat(Symbol casted): return "ConstrPat(" + casted + ")"; + case SequencePat(Symbol casted, int len): + return "SequencePat(" + casted + ", " + len + ")"; case ConstantPat(Object value): return "ConstantPat(" + value + ")"; case VariablePat(Tree tree): |