diff options
author | Matthias Zenger <mzenger@gmail.com> | 2003-11-11 13:21:09 +0000 |
---|---|---|
committer | Matthias Zenger <mzenger@gmail.com> | 2003-11-11 13:21:09 +0000 |
commit | 2521f5270d8599a6407588cd3ab92143c77bc827 (patch) | |
tree | 1c84600ef4c627d56c24f090c6ab3fba3a8f4c76 /sources/scalac/transformer | |
parent | 6a5131fc32787d2d4865918a4fb1e480bfc14f8f (diff) | |
download | scala-2521f5270d8599a6407588cd3ab92143c77bc827.tar.gz scala-2521f5270d8599a6407588cd3ab92143c77bc827.tar.bz2 scala-2521f5270d8599a6407588cd3ab92143c77bc827.zip |
Added support for | in algebraic patterns;
Added support for reading ConstantValue attributes;
Diffstat (limited to 'sources/scalac/transformer')
5 files changed, 187 insertions, 133 deletions
diff --git a/sources/scalac/transformer/TransMatch.java b/sources/scalac/transformer/TransMatch.java index 4cea1d9770..5942f28b94 100644 --- a/sources/scalac/transformer/TransMatch.java +++ b/sources/scalac/transformer/TransMatch.java @@ -91,25 +91,24 @@ public class TransMatch extends OwnerTransformer { int i = 0; while (i < cases.length) { containsReg = TestRegTraverser.apply(cases[i]) || containsReg; - Set nilvars = TestRegTraverser.getNilVariables(); - if(!nilvars.isEmpty()) { - //System.err.println("nilvars present"); - Tree[] newBody = new Tree[ nilvars.size() + 1 ]; - int j=0; - for( Iterator it = nilvars.iterator(); it.hasNext(); ) { - Symbol v = (Symbol) it.next(); - newBody[ j++ ] = unit.global.treeGen.ValDef(v, - unit.global.treeGen.Nil(cases[i].pos)); - } - newBody[ newBody.length - 1 ] = cases[i].body; - cases[i].body = unit.global.treeGen.mkBlock( newBody ); - } - i++; - } - + Set nilvars = TestRegTraverser.getNilVariables(); + if(!nilvars.isEmpty()) { + //System.err.println("nilvars present"); + Tree[] newBody = new Tree[ nilvars.size() + 1 ]; + int j=0; + for( Iterator it = nilvars.iterator(); it.hasNext(); ) { + Symbol v = (Symbol) it.next(); + newBody[ j++ ] = unit.global.treeGen.ValDef(v, + unit.global.treeGen.Nil(cases[i].pos)); + } + newBody[ newBody.length - 1 ] = cases[i].body; + cases[i].body = unit.global.treeGen.mkBlock( newBody ); + } + i++; + } if (containsReg) { - AlgebraicMatcher am = new AlgebraicMatcher( unit ); - Matcher matcher = new Matcher( currentOwner, root, restpe ); + AlgebraicMatcher am = new AlgebraicMatcher( unit ); + Matcher matcher = new Matcher( currentOwner, root, restpe ); am.construct( matcher, cases ); return matcher.tree; } else { @@ -117,7 +116,7 @@ public class TransMatch extends OwnerTransformer { currentOwner, restpe); pm.enter(cases); if (global.log()) { - global.log("internal pattern matching structure"); + global.log("internal pattern matching structure"); pm.print(); } return pm.toTree(); diff --git a/sources/scalac/transformer/matching/AlgebraicMatcher.java b/sources/scalac/transformer/matching/AlgebraicMatcher.java index 9bcddb3e11..4708dd6258 100644 --- a/sources/scalac/transformer/matching/AlgebraicMatcher.java +++ b/sources/scalac/transformer/matching/AlgebraicMatcher.java @@ -53,6 +53,10 @@ public class AlgebraicMatcher extends PatternMatcher { for( int i = 0; i < cases.length; i++ ) { enter( cases[ i ] );//(CaseDef) cases[i], i); } + if (unit.global.log()) { + unit.global.log("internal pattern matching structure"); + print(); + } _m.tree = toTree(); } diff --git a/sources/scalac/transformer/matching/PatternMatcher.java b/sources/scalac/transformer/matching/PatternMatcher.java index 99a921e2e4..793cc83a7e 100644 --- a/sources/scalac/transformer/matching/PatternMatcher.java +++ b/sources/scalac/transformer/matching/PatternMatcher.java @@ -52,7 +52,7 @@ public class PatternMatcher extends PatternTool { public PatternMatcher(Unit unit, Tree selector, Symbol owner, Type resultType) { super(unit); - initialize(selector, owner, resultType, true); + initialize(selector, owner, resultType, true); } /** constructor, used in subclass ALgebraicMatcher @@ -75,10 +75,10 @@ public class PatternMatcher extends PatternTool { owner, Modifiers.MUTABLE); this.resultVar.setType(resultType); - this.owner = owner; + this.owner = owner; this.selector = selector; this.optimize &= (unit.global.target == Global.TARGET_JVM); - this.doBinding = doBinding; + this.doBinding = doBinding; } /** pretty printer @@ -160,8 +160,18 @@ public class PatternMatcher extends PatternTool { if (patNode.or != null) print(patNode.or, ind); break; - case Body(_, _, Tree[] stats): - System.out.println(indent + "BODY(" + stats.length + ")"); + 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; } } @@ -187,9 +197,8 @@ public class PatternMatcher extends PatternTool { 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 { + else unit.error(pat.pos, "duplicate case"); - } } } @@ -274,82 +283,81 @@ public class PatternMatcher extends PatternTool { } protected boolean isSeqApply( Tree.Apply tree ) { - return (tree.args.length == 1 && - (tree.type.symbol().flags & Modifiers.CASE) == 0); + return (tree.args.length == 1 && + (tree.type.symbol().flags & Modifiers.CASE) == 0); } protected PatternNode patternNode(Tree tree, Header header, CaseEnv env) { switch (tree) { - case Bind(Name name, Typed( Ident( Names.PATTERN_WILDCARD ), Tree tpe)): // little opt. for 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 )): // little opt. for 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)) - env.newBoundVar( tree.symbol(), - tree.type, - header.selector); + case Bind(Name name, Typed( Ident( Names.PATTERN_WILDCARD ), Tree tpe)): // little opt. for 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 )): // little opt. for 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)) + env.newBoundVar( tree.symbol(), + tree.type, + header.selector); + 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 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; - } - } - 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) + 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); + assert false; // this may not happen ?? ----------------- Burak + return mk.ConstrPat(tree.pos, tree.type); } else if (name.isVariable()) {// should be Bind ------------ Burak - assert false; + assert false; if (env != null) - env.newBoundVar( - tree.symbol(), + env.newBoundVar(tree.symbol(), tree.type, header.selector); return mk.DefaultPat(tree.pos, header.type); @@ -368,17 +376,19 @@ public class PatternMatcher extends PatternTool { } else { return mk.SeqContainerPat(tree.pos, tree.type, tree); } - case Alternative(Tree[] ts): // CAN THIS WORK ? - assert ts.length > 0; - PatternNode res = patternNode( ts[ 0 ], header, env ); - for (int i = 1; i < ts.length; i++) { - res.or = patternNode(ts[i], header, env); - res = res.or ; + 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 res; + return mk.AltPat(tree.pos, (Header)subroot.and); default: new scalac.ast.printer.TextTreePrinter().print(tree).flush(); - throw new ApplicationError("unit "+unit+" tree"+tree); + throw new ApplicationError("unit = " + unit + "; tree = "+tree); } } @@ -603,7 +613,13 @@ public class PatternMatcher extends PatternTool { PatternNode patNode = root.and; while (patNode != null) { PatternNode node = patNode; - while ((node = node.or) != null) + while ((node = node.or) != null) { + switch (node) { + case ConstantPat(_): + break; + default: + return false; + } switch (node.and) { case Body(ValDef[][] bound, Tree[] guard, _): if ((guard.length > 1) || @@ -614,6 +630,7 @@ public class PatternMatcher extends PatternTool { default: return false; } + } patNode = patNode.next(); } return true; @@ -828,7 +845,12 @@ public class PatternMatcher extends PatternTool { node = next; break; case Body(ValDef[][] bound, Tree[] guard, Tree[] body): - if (!doBinding) bound = new ValDef[][] { new ValDef[] {} }; + 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 = new Tree[bound[i].length + 1]; System.arraycopy(bound[i], 0, ts, 0, bound[i].length); @@ -986,6 +1008,11 @@ public class PatternMatcher extends PatternTool { 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(); } diff --git a/sources/scalac/transformer/matching/PatternNode.java b/sources/scalac/transformer/matching/PatternNode.java index 3cd583c5d8..03e73fda97 100644 --- a/sources/scalac/transformer/matching/PatternNode.java +++ b/sources/scalac/transformer/matching/PatternNode.java @@ -14,9 +14,9 @@ import scalac.ast.*; import scalac.symtab.*; import scalac.typechecker.*; -/** intermediary data structure for algebraic matching - */ +/** Intermediate data structure for algebraic matcher + */ public class PatternNode { public int pos = Position.FIRSTPOS; public Type type; @@ -27,11 +27,11 @@ 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); // only used in PatternMatcher - public case SeqContainerPat(Symbol casted, Tree seqpat); // in AlgebraicMatcher public case ConstantPat(Object value); public case VariablePat(Tree tree); - + public case AltPat(Header subheader); + public case SequencePat(Symbol casted, int len); // only used in PatternMatcher + public case SeqContainerPat(Symbol casted, Tree seqpat); // in AlgebraicMatcher public PatternNode dup() { PatternNode res; @@ -60,6 +60,9 @@ public class PatternNode { case VariablePat(Tree tree): res = VariablePat(tree); break; + case AltPat(Header subheader): + res = AltPat(subheader); + break; default: throw new ApplicationError(); } diff --git a/sources/scalac/transformer/matching/PatternNodeCreator.java b/sources/scalac/transformer/matching/PatternNodeCreator.java index 16574d625b..d0a2cddef1 100644 --- a/sources/scalac/transformer/matching/PatternNodeCreator.java +++ b/sources/scalac/transformer/matching/PatternNodeCreator.java @@ -17,6 +17,15 @@ import java.util.Vector ; public class PatternNodeCreator extends PatternTool { + /** the owner of the variable symbols that might be created */ + Symbol owner; + + public PatternNodeCreator(Unit unit, Symbol owner) { + super(unit); + assert owner != null; + this.owner = owner; + } + public SequencePat SequencePat(int pos, Type type, int len) { Symbol sym = newVar(Position.FIRSTPOS, type); SequencePat node = new SequencePat(sym, len); @@ -24,6 +33,7 @@ public class PatternNodeCreator extends PatternTool { node.type = type; return node; } + public SeqContainerPat SeqContainerPat(int pos, Type type, Tree seqpat) { Symbol sym = newVar(Position.NOPOS, type); SeqContainerPat node = new SeqContainerPat(sym, seqpat); @@ -31,29 +41,40 @@ public class PatternNodeCreator extends PatternTool { node.type = type; return node; } + public static DefaultPat DefaultPat(int pos, Type type) { - DefaultPat node = new DefaultPat(); - node.pos = pos; - node.type = type; - return node; + DefaultPat node = new DefaultPat(); + node.pos = pos; + node.type = type; + return node; } + public ConstrPat ConstrPat(int pos, Type type) { - ConstrPat node = new ConstrPat(newVar(pos, type)); - node.pos = pos; - node.type = type; - return node; + ConstrPat node = new ConstrPat(newVar(pos, type)); + node.pos = pos; + node.type = type; + return node; } + public static ConstantPat ConstantPat(int pos, Type type, Object value) { - ConstantPat node = new ConstantPat( value ); - node.pos = pos; - node.type = type; - return node; + ConstantPat node = new ConstantPat( value ); + node.pos = pos; + node.type = type; + return node; } + public static VariablePat VariablePat(int pos, Tree tree) { - VariablePat node = new VariablePat( tree ); - node.pos = pos; - node.type = tree.type; - return node; + VariablePat node = new VariablePat( tree ); + node.pos = pos; + node.type = tree.type; + return node; + } + + public static AltPat AltPat(int pos, Header header) { + AltPat node = new AltPat(header); + node.pos = pos; + node.type = header.type; + return node; } // factories @@ -64,11 +85,19 @@ public class PatternNodeCreator extends PatternTool { node.type = type; return node; } + + public Body Body(int pos) { + Body node = new Body(new ValDef[0][], new Tree[0], new Tree[0]); + node.pos = pos; + return node; + } + public Body Body(int pos, ValDef[] bound, Tree guard, Tree body) { Body node = new Body(new ValDef[][]{bound}, new Tree[]{guard}, new Tree[]{body}); node.pos = pos; return node; } + public TermSymbol newVar(int pos, Name name, Type type) { TermSymbol sym = new TermSymbol(pos, name, owner, 0); sym.setType(type); @@ -76,16 +105,8 @@ public class PatternNodeCreator extends PatternTool { //System.out.println("owner: "+sym.owner()); return sym; } + public TermSymbol newVar(int pos, Type type) { return newVar(pos, fresh.newName("temp"), type); } - - /** the owner of the variable symbols that might be created */ - Symbol owner; - - public PatternNodeCreator( Unit unit, Symbol owner ) { - super( unit ); - assert owner != null; - this.owner = owner; - } } |