diff options
Diffstat (limited to 'sources/scalac')
-rw-r--r-- | sources/scalac/transformer/matching/CaseEnv.java | 4 | ||||
-rw-r--r-- | sources/scalac/transformer/matching/CodeFactory.java | 8 | ||||
-rw-r--r-- | sources/scalac/transformer/matching/PatternMatcher.java | 895 | ||||
-rw-r--r-- | sources/scalac/transformer/matching/PatternNode.java | 4 | ||||
-rw-r--r-- | sources/scalac/transformer/matching/PatternNodeCreator.java | 48 | ||||
-rw-r--r-- | sources/scalac/util/Names.java | 1 |
6 files changed, 35 insertions, 925 deletions
diff --git a/sources/scalac/transformer/matching/CaseEnv.java b/sources/scalac/transformer/matching/CaseEnv.java index cc59ec052b..ec2f5ffcf1 100644 --- a/sources/scalac/transformer/matching/CaseEnv.java +++ b/sources/scalac/transformer/matching/CaseEnv.java @@ -17,7 +17,7 @@ import Tree.ValDef; /** the environment for a body of a case */ -class CaseEnv { +public class CaseEnv { /** the owner of the variables created here */ @@ -33,7 +33,7 @@ class CaseEnv { /** constructor */ - CaseEnv( Symbol owner, CompilationUnit unit ) { + public CaseEnv( Symbol owner, CompilationUnit unit ) { this.owner = owner; this.defs = unit.global.definitions; this.gen = unit.global.treeGen; diff --git a/sources/scalac/transformer/matching/CodeFactory.java b/sources/scalac/transformer/matching/CodeFactory.java index 9d7b8ad0eb..f136b3da3e 100644 --- a/sources/scalac/transformer/matching/CodeFactory.java +++ b/sources/scalac/transformer/matching/CodeFactory.java @@ -31,7 +31,7 @@ public class CodeFactory extends PatternTool { /** a faked switch statement */ - Tree Switch( Tree condition[], + public Tree Switch( Tree condition[], Tree body[], Tree defaultBody ) { assert condition != null:"cond is null"; @@ -157,7 +157,7 @@ public class CodeFactory extends PatternTool { return gen.mkApply__(gen.Select(tree, defs.BOOLEAN_NOT())); } - /*protected*/ Tree And(Tree left, Tree right) { + /*protected*/ public Tree And(Tree left, Tree right) { switch (left) { case Literal(BOOLEAN(boolean value)): return value ? right : left; @@ -169,7 +169,7 @@ public class CodeFactory extends PatternTool { return gen.mkApply_V(gen.Select(left, defs.BOOLEAN_AND()), new Tree[]{right}); } - /*protected*/ Tree Or(Tree left, Tree right) { + /*protected*/ public Tree Or(Tree left, Tree right) { switch (left) { case Literal(BOOLEAN(boolean value)): return value ? left : right; @@ -265,7 +265,7 @@ public class CodeFactory extends PatternTool { } - Type pairType( Type left, Type right ) { + public Type pairType( Type left, Type right ) { return defs.TUPLE_TYPE(new Type[] { left, right } ); } diff --git a/sources/scalac/transformer/matching/PatternMatcher.java b/sources/scalac/transformer/matching/PatternMatcher.java deleted file mode 100644 index ca0b47bf2c..0000000000 --- a/sources/scalac/transformer/matching/PatternMatcher.java +++ /dev/null @@ -1,895 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -** ** -** $Id$ -\* */ - -package scalac.transformer.matching; - -import scala.tools.util.Position; -import scalac.*; -import scalac.ast.*; -import scalac.atree.AConstant; -import scalac.util.*; -import scalac.symtab.*; -import PatternNode.*; -import Tree.*; - - -public class PatternMatcher extends PatternTool { - - protected boolean optimize = true; - protected boolean delegateSequenceMatching = false; - protected boolean doBinding = true; - - /** the owner of the pattern matching expression - */ - protected Symbol owner; - - /** the selector expression - */ - protected Tree selector; - - /** the root of the pattern node structure - */ - protected PatternNode root; - - /** the symbol of the result variable - */ - protected Symbol resultVar; - - /** methods to generate scala code - */ - protected CodeFactory cf; - - /** methods to create pattern nodes - */ - protected PatternNodeCreator mk; - - /** constructor - */ - public PatternMatcher(CompilationUnit unit, Tree selector, - Symbol owner, Type resultType) { - super(unit); - initialize(selector, owner, resultType, true); - } - - /** constructor, used in subclass AlgebraicMatcher - */ - protected PatternMatcher(CompilationUnit unit) { - super(unit); - } - - /** init method, also needed in subclass AlgebraicMatcher - */ - protected void initialize(Tree selector, Symbol owner, Type resultType, boolean doBinding) { - this.mk = new PatternNodeCreator(unit, owner); - this.cf = new CodeFactory(unit, selector.pos); - this.root = mk.ConstrPat(selector.pos, selector.type.widen()); - this.root.and = mk.Header(selector.pos, - selector.type.widen(), - gen.Ident(selector.pos, root.symbol())); - this.resultVar = owner.newVariable(selector.pos, - Modifiers.MUTABLE, - fresh.newName(RESULT_N)); - this.resultVar.setType(resultType); - this.owner = owner; - this.selector = selector; - this.optimize &= (unit.global.target == Global.TARGET_JVM); - this.doBinding = doBinding; - } - - /** pretty printer - */ - public void print() { - print(root.and, ""); - } - - public void print(PatternNode patNode, String indent) { - if (patNode == null) - 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; - } - } - - /** enters a sequence of cases into the pattern matcher - */ - public void construct(Tree[] cases) { - for( int i = 0; i < cases.length; i++ ) - enter(cases[i]); - } - - /** enter a single case into the pattern matcher - */ - 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"); - } - } - - protected void updateBody(Body tree, ValDef[] bound, Tree guard, Tree body) { - if (tree.guard[tree.guard.length - 1] == Tree.Empty) { - //unit.error(body.pos, "unreachable code"); - } else { - ValDef[][] bd = new ValDef[tree.bound.length + 1][]; - Tree[] ng = new Tree[tree.guard.length + 1]; - Tree[] nb = new Tree[tree.body.length + 1]; - System.arraycopy(tree.bound, 0, bd, 0, tree.bound.length); - System.arraycopy(tree.guard, 0, ng, 0, tree.guard.length); - System.arraycopy(tree.body, 0, nb, 0, tree.body.length); - bd[bd.length - 1] = bound; - ng[ng.length - 1] = guard; - nb[nb.length - 1] = body; - tree.bound = bd; - tree.guard = ng; - tree.body = nb; - } - } - - 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; - } - } - - protected boolean isSeqApply( Tree.Apply tree ) { - if(( tree.args.length == 1 ) && (tree.type.symbol().flags & Modifiers.CASE) == 0) - switch (tree.args[0]) { - case Sequence( _ ): - return true; - default: - return false; - } - return false; - } - - 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() && - !(fn.symbol().isModule() && - ((fn.symbol().flags & Modifiers.CASE) != 0))) { - 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 : "encountered ident:"+name; - 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); - } - } - - protected PatternNode enter(Tree pat, - int index, - PatternNode target, - 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); - } - } - - private Header newHeader( int pos, Symbol casted, int index ) { - Tree ident = gen.Ident( pos, casted ); - if (casted.pos == Position.FIRSTPOS) { - Tree t = - gen.mkApply_V( - gen.Select( ident, defs.FUNCTION_APPLY( 1 )), - new Tree[]{ gen.mkIntLit( pos, index ) }); - Type seqType = t.type; - return mk.Header( pos, seqType, t ); - } else { - Symbol ts = ((ClassSymbol) casted.getType().symbol()) - .caseFieldAccessor(index); - Type accType = casted.getType().memberType(ts); - 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); - } - } - } - - /** main enter function - * - * invariant: ( curHeader == (Header)target.and ) holds - */ - protected PatternNode enter1(Tree pat, - int index, - PatternNode target, - Symbol casted, - CaseEnv env) { - //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); - } - // 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 - // substitute... !!! - 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(patArgs, - (curHeader = - (curHeader.next = - mk.Header(patNode.pos, curHeader.type, curHeader.selector))).or = - patNode, - casted, - env); - } else if (next.or == null) { - return enter(patArgs, next.or = patNode, casted, env); // add new branch - } else - next = next.or; - } - - /** calls enter for an array of patterns, see enter - */ - 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; - } - for (int i = 0; i < pats.length; i++) - target = enter1(pats[i], i, target, casted, env); - return target; - } - - 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); - } - } - return 0; - } - - - //////////// generator methods - - public Tree toTree() { - if (optimize && isSimpleIntSwitch()) - return intSwitchToTree(); - else if (false && optimize && isSimpleSwitch()) - return switchToTree(); - else - return generalSwitchToTree(); - } - - protected boolean isSimpleIntSwitch() { - if (selector.type.widen().isSameAs(defs.int_TYPE())) { - PatternNode patNode = root.and; - while (patNode != null) { - PatternNode node = patNode; - 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) || - (guard[0] != Tree.Empty) || - (bound[0].length > 0)) - return false; - break; - default: - return false; - } - } - patNode = patNode.next(); - } - return true; - } else - return false; - } - - protected boolean isSimpleSwitch() { - print(); - PatternNode patNode = root.and; - while (patNode != null) { - PatternNode node = patNode; - 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; - } - } - patNode = patNode.next(); - } - return true; - } - - static class TagBodyPair { - int tag; - Tree body; - TagBodyPair next; - - TagBodyPair(int tag, Tree body, TagBodyPair next) { - this.tag = tag; - this.body = body; - this.next = next; - } - - int length() { - return (next == null) ? 1 : (next.length() + 1); - } - } - - static TagBodyPair insert(int tag, Tree body, TagBodyPair current) { - if (current == null) - return new TagBodyPair(tag, body, null); - else if (tag > current.tag) - return new TagBodyPair(current.tag, current.body, insert(tag, body, current.next)); - else - return new TagBodyPair(tag, body, current); - } - - protected int numCases(PatternNode patNode) { - int n = 0; - while ((patNode = patNode.or) != null) - switch (patNode) { - case DefaultPat(): - break; - default: - n++; - } - return n; - } - - protected Tree defaultBody(PatternNode patNode, Tree otherwise) { - while (patNode != null) { - PatternNode node = patNode; - while ((node = node.or) != null) - switch (node) { - case DefaultPat(): - return bodyToTree(node.and); - } - patNode = patNode.next(); - } - return otherwise; - } - - /** This method translates pattern matching expressions that match - * on integers on the top level. - */ - public Tree intSwitchToTree() { - //print(); - int ncases = numCases(root.and); - Tree matchError = cf.ThrowMatchError(selector.pos, resultVar.getType()); - // without a case, we return a match error if there is no default case - if (ncases == 0) - return defaultBody(root.and, matchError); - // 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(); - } - } - // - // if we have more than 2 cases than use a switch statement - switch (root.and) { - 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(); - } - } - - public Tree switchToTree() { - throw new Error(); - } - - public Tree generalSwitchToTree() { - Tree[] ts = { - gen.ValDef(root.symbol(), selector), - gen.ValDef(resultVar, gen.mkDefaultValue(selector.pos, resultVar.getType()))}; - Tree res = gen.If( - selector.pos, - toTree(root.and), - gen.Ident(selector.pos, resultVar), - cf.ThrowMatchError(selector.pos, resultVar.getType(), gen.Ident(selector.pos, root.symbol()))); - return gen.mkBlock(selector.pos, ts, res); - } - - /*protected*/ public Tree toTree(PatternNode node) { - 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(); - } - return res; - } - - protected boolean optimize(Type selType, PatternNode alternatives) { - if (!optimize || !selType.isSubType(defs.SCALAOBJECT_TYPE())) - return false; - 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; - } - alternatives = alternatives.or; - } - return cases > 2; - } - - static class TagNodePair { - int tag; - PatternNode node; - TagNodePair next; - - TagNodePair(int tag, PatternNode node, TagNodePair next) { - this.tag = tag; - this.node = node; - this.next = next; - } - - int length() { - return (next == null) ? 1 : (next.length() + 1); - } - } - - static TagNodePair insert(int tag, PatternNode node, TagNodePair current) { - if (current == null) - return new TagNodePair(tag, node, null); - else if (tag > current.tag) - return new TagNodePair(current.tag, current.node, insert(tag, node, current.next)); - else if (tag == current.tag) { - PatternNode old = current.node; - (current.node = node).or = old; - return current; - } else - return new TagNodePair(tag, node, current); - } - - static TagNodePair insertNode(int tag, PatternNode node, TagNodePair current) { - PatternNode newnode = node.dup(); - newnode.or = null; - return insert(tag, newnode, current); - } - - protected Tree toOptTree(PatternNode node, Tree selector) { - //System.err.println("pm.toOptTree called"+node); - TagNodePair cases = null; - 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(); - } - int n = cases.length(); - int[] tags = new int[n]; - Tree[] bodies = new Tree[n]; - n = 0; - while (cases != null) { - tags[n] = cases.tag; - bodies[n++] = toTree(cases.node, selector); - cases = cases.next; - } - return gen.Switch(gen.mkApply__(gen.Select(selector.duplicate(), defs.SCALAOBJECT_TAG())), - tags, - bodies, - (defaultCase == null) ? gen.mkBooleanLit(selector.pos, false) - : toTree(defaultCase.and), - defs.boolean_TYPE()); - } - - protected Tree toTree(PatternNode node, Tree selector) { - //System.err.println("pm.toTree("+node+","+selector+")"); - 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(); - } - } -} diff --git a/sources/scalac/transformer/matching/PatternNode.java b/sources/scalac/transformer/matching/PatternNode.java index 59c3759412..7f08e04eb9 100644 --- a/sources/scalac/transformer/matching/PatternNode.java +++ b/sources/scalac/transformer/matching/PatternNode.java @@ -24,6 +24,10 @@ public class PatternNode { public PatternNode or; public PatternNode and; + public Type getType() { + return type; + } + public case Header(Tree selector, Header next) ; public case Body(Tree.ValDef[][] bound, Tree[] guard, Tree[] body); public case DefaultPat(); diff --git a/sources/scalac/transformer/matching/PatternNodeCreator.java b/sources/scalac/transformer/matching/PatternNodeCreator.java index a1e6b27da0..68f5c97639 100644 --- a/sources/scalac/transformer/matching/PatternNodeCreator.java +++ b/sources/scalac/transformer/matching/PatternNodeCreator.java @@ -43,39 +43,39 @@ public class PatternNodeCreator extends PatternTool { return node; } - public static DefaultPat DefaultPat(int pos, Type type) { - DefaultPat node = new DefaultPat(); - node.pos = pos; - node.type = type; - return node; + public DefaultPat DefaultPat(int pos, Type type) { + 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, AConstant value) { - ConstantPat node = new ConstantPat( value ); - node.pos = pos; - node.type = type; - return node; + public ConstantPat ConstantPat(int pos, Type type, AConstant value) { + 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; + public VariablePat VariablePat(int pos, Tree tree) { + 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; + public AltPat AltPat(int pos, Header header) { + AltPat node = new AltPat(header); + node.pos = pos; + node.type = header.type; + return node; } // factories diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java index 286038afa9..b4312e0220 100644 --- a/sources/scalac/util/Names.java +++ b/sources/scalac/util/Names.java @@ -202,6 +202,7 @@ public class Names { public static final Name print = Name.fromString("print"); public static final Name readResolve = Name.fromString("readResolve"); public static final Name report = Name.fromString("report"); + public static final Name result = Name.fromString("$result"); public static final Name runtime = Name.fromString("runtime"); public static final Name scala = Name.fromString("scala"); public static final Name setParents = Name.fromString("setParents"); |