summaryrefslogblamecommitdiff
path: root/sources/scalac/transformer/TransMatch.java
blob: 37f7a7889c0a7d4d0cb9537a424e68a08ecc62dc (plain) (tree)
1
2
3
4
5
6
7
8



                                                                          

                                                                          

       






                           
                                    

              
                                                   

                                                     



                                                      
                                           



                                                  


                                                                                                            
                                 
 


                                               
 


                                      
 


                                                         
 


                                                  
 
                       
 

                                                                
 


                                         
 


                                                      
 


                                     
 

                                                  
 
                                                               
 
         
 
     
 

              

                                      



                                  



                                                                       

                                    

                                                                          














                                                                                                       
                          

                                                                        


                                           
                                                              
                                                                         
                                
                               
                                                                  



                               





                                      
                                                                          





                                                                                               
                                                                                                   










                                                                                               
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package scalac.transformer;

import java.io.*;
import java.util.*;
import scalac.*;
import scalac.ast.*;
import scalac.symtab.*;
import scalac.util.*;       // Names
import Tree.*;

import scalac.transformer.matching.PatternMatcher ;
import scalac.transformer.matching.TestRegTraverser ;
import scalac.transformer.matching.AlgebraicMatcher ;

/** A transformer for expanding match expressions into
 *  flat sequences of .is and .as method calls
 *
 *  @author     Matthias Zenger, Burak Emir
 *  @version    1.1
 */
public class TransMatch extends OwnerTransformer {

      /** container. classes AlgebraicMatcher and SequenceMatcher get input and store their results in here.
       *  resembles the 'Memento' design pattern, could also be named 'Liaison'
       */
    public static class Matcher {

        /** owner of the code we create (input)
         */
        public Symbol owner;

        /** the selector value (input)
         */
        public Tree   selector;

        /** type of the result of the whole match (input)
         */
        public Type   resultType;

        /** tree representing the matcher (output)
         */
        public Tree   tree;

        public int pos;

        public HashMap varMap;    // needed in LeftTracerInScala
        public Tree[]  stms;      // needed in LeftTracerInScala

        public Matcher(Symbol owner,
                       Tree root,
                       Type resultType) {

            assert( owner != null ) : "owner is null";
            assert owner != Symbol.NONE ;
            this.owner      = owner;

            assert root != null;
            assert root.type != null;
            this.selector   = root;

            assert this.resultType != Type.NoType;
            this.resultType = resultType;

            this.pos        = root.pos; // for convenience only

        }

    }

    Unit unit;

    public TransMatch(Global global) {
        super(global);
    }

    public void apply(Unit unit) {
        this.unit = unit;
        super.apply(unit);
    }

    protected Tree transform(Tree root, CaseDef[] cases, Type restpe) {
        boolean containsReg = false;
        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++;
        }
        if (containsReg) {
            AlgebraicMatcher am = new AlgebraicMatcher( unit );
            Matcher matcher = new Matcher( currentOwner, root, restpe );
            am.construct( matcher, cases );
            return matcher.tree;
        } else {
            PatternMatcher pm = new PatternMatcher(unit, root,
                                                   currentOwner, restpe);
            pm.construct(cases);
            if (global.log()) {
                global.log("internal pattern matching structure");
                pm.print();
            }
            return pm.toTree();
        }
    }

    public Tree transform(Tree tree) {
        if (tree == null)
            return null;
        switch (tree) {
            case Apply(Select( Tree receiver, Names.match ), Tree[] args):
                if ((args != null) && (args.length == 1))
                    switch (args[0]) {
                        case Visitor(CaseDef[] cases):
                            return transform(transform(receiver), transform(cases), tree.type);
                    }
                return tree;
            case Apply(TypeApply(Select( Tree receiver, Names.match ), Tree[] targs), Tree[] args):
                if ((args != null) && (args.length == 1))
                    switch (args[0]) {
                        case Visitor(CaseDef[] cases):
                            return transform(transform(receiver), transform(cases), tree.type);
                    }
                return tree;
            default:
                return super.transform(tree);
        }
    }
}