summaryrefslogblamecommitdiff
path: root/sources/scalac/transformer/matching/SequenceMatcher.java
blob: 02cf68ddf62dc3cbef505f8fa2cf69f5f46c5ca8 (plain) (tree)


























































                                                                                    
                                                                                    







                                                                                     
                                                                                               




















                                                                                     


                                                            
                                                   
            


                                                                   
                                 




                                                                       
                                                                                                 






                                                                
            
                                                                     
















                                                                               
                                                                      


























                                                                           
                                                                                              

                                                  
                                                        
 
                                                                  






























                                                                             
                                                            





















                                                                                   
                                                             

























                                                                              
                                                                                       
















                                                                            
package scalac.transformer.matching ;

import scalac.*;
import scalac.ast.Tree;
import scalac.typechecker.*;
import Tree.*;

//import scala.compiler.printer.TextTreePrinter ; // DEBUGGING\
    //import scala.compiler.printer.XMLAutomPrinter ; // DEBUGGING\

import scalac.transformer.TransMatch.Matcher ;
import scalac.ast.* ;
import scalac.symtab.* ;

import java.util.* ;

import ch.epfl.lamp.util.Position;

/** constructs a matcher for a sequence pattern. plays two roles in
 *  described in design pattern Builder.
 *  is the "Director" for "Builder" class BerrySethi.
 *  is the "Builder" for "Director" class TransMatch.
 */

public class SequenceMatcher extends PatternTool {

      CodeFactory cf;

      Matcher _m;

      Tree pat[];
      Tree body[];

    /*
      public Tree[] getNested( HashMap varMap ) {
            Tree[][] stmsNest = new Tree[varMap.size()][];
            int i = 0;
            int k = 0;
            for( Iterator it = varMap.keySet().iterator() ; it.hasNext(); ) {
                  Tree pat = (Tree) it.next(); // contains variables
                  Symbol v = (Symbol) varMap.get( pat );

                  BindingBerrySethi build = new BindingBerrySethi();
                  NondetWordAutom leftNest = build.automatonFrom( pat,
                                                                  new Integer( 0 ));

                  DetWordAutom dLeftNest  = new DetWordAutom( leftNest );

                  NondetWordAutom rightNest = build.revnfa;

                  Matcher mNest = new Matcher( _m.owner, _m.selector, null );

                  LeftTracerInScala ltisNest =
                        new LeftTracerInScala( dLeftNest,
                                               cf.getElemType( pat.type() ),
                                               mNest,
                                               cf );
                  Tree stmsLeftNest[] = ltisNest.getTrace();

                  Tree selNest = gen.Ident( Position.FIRSTPOS, ltisNest.resultSym );

                  DetWordAutom dRightNest =
                        new DetWordAutom( rightNest, leftNest, dLeftNest);

                  RightTracerInScala rtisNest =
                        new RightTracerInScala( dRightNest, leftNest, mNest,
                                                cf, pat, cf.getElemType(pat.type()));

                  Tree stmsRightNest[] = rtisNest.getStms( gen.Ident( Position.FIRSTPOS, v ) );
                  stmsNest[ i ] = new Tree[ stmsLeftNest.length
                                            + stmsRightNest.length ];

                  System.arraycopy( stmsLeftNest, 0,
                                    stmsNest[ i ], 0, stmsLeftNest.length );
                  System.arraycopy( stmsRightNest, 0, stmsNest[ i ],
                                    stmsLeftNest.length, stmsRightNest.length );
                  k += stmsNest[ i ].length;
                  i++;
            }
            // flatten
            Tree[] res = new Tree[ k ];
            k = 0;
            for( i = 0; i < varMap.size(); i++ ) {
                  System.arraycopy( stmsNest[ i ], 0, res, k, stmsNest[ i ].length );
                  k += stmsNest[ i ].length;
            }
            return res;
      }
    */

    /** translates the det/switching automaton to scala code
     *  precondition: pat.type() corresponds to element type
     */
      Tree addBinderToBody( Tree pat, Tree body ) {
	  /*
            SplitNested spn = new SplitNested( pat, _m.owner, cf );


            pat = spn.flatPat; //

            for( Iterator it = spn.nestedVarToPats.keySet().iterator();
                 it.hasNext(); ){
                  Symbol v = (Symbol) it.next();
                  Tree nestPat = (Tree) spn.nestedVarToPats.get( v );
                  Matcher mNest = new Matcher( _m.owner, gen.Ident(Position.FIRSTPOS, v), null );

                  Matcher saveM = _m; _m = mNest;

                  Tree nbody = addBinderToBody( nestPat, body );
                  _m = saveM;
                  body = nbody;
            }
	  */
            Type elementType = cf.getElemType_Sequence( pat.type() );

            BindingBerrySethi build = new BindingBerrySethi();
            NondetWordAutom left =  build.automatonFrom( pat, new Integer(0) );
            NondetWordAutom right = build.revnfa;

            //  - - -> left

            DetWordAutom dLeft  =
                  new DetWordAutom( left );

            Matcher mL = new Matcher( _m.owner, _m.selector, null );

            LeftTracerInScala ltis =
                  new LeftTracerInScala( dLeft, elementType, mL, cf);

            Tree stms[] = ltis.getTrace();

            Tree sel = gen.Ident( Position.FIRSTPOS, ltis.resultSym );

            // <- - - right

            DetWordAutom dRight =
                  new DetWordAutom( right, left, dLeft);

            //System.out.println( "vars: "+vars );
            int j;

            RightTracerInScala rtis =
                  new RightTracerInScala( dRight, left, mL,
                                          cf, pat, elementType );

            Tree stms2[] = rtis.getStms( sel );             // to scala

            // run them, bind

            Tree items[] = new Tree[ stms.length
                                     + stms2.length
                                     + 1 ];

            System.arraycopy( stms, 0, items, 0, stms.length );
            System.arraycopy( stms2, 0, items, stms.length, stms2.length );

            j = stms.length + stms2.length ;
            items[ stms.length + stms2.length ] = body;

	    AttributedTreeCopier treeCopier = new AttributedTreeCopier(unit.global, cf.make) ;
            //System.out.println("helpmap");
            //System.out.println( rtis.helpMap2 );
	    treeCopier.pushSymbolSubst( rtis.helpMap2 );

    items[ stms.length + stms2.length ] = treeCopier.copy( body );

            return cf.Block( body.pos, items, body.type );
      }

      /** turns body `case pat(x,y,z) => body' into
       **  `{ <runLeft>;<runRight>;body }' if
       *  necessary.
       *  @param body the array containing the bodies of the visitor
       */
      Tree[] addBindersToBodies( Tree body[] ) {
            //System.out.println("addBindersToBodies");
            Tree nbody[] = new Tree[ body.length ];
            for( int i = 0; i < body.length; i++ ) {
                  Integer iI = new Integer( i );

                  if( !CollectVariableTraverser.containsBinding( pat[ i ] ) )
                        {
                              nbody[ i ] = body[ i ]; // no need for binding
                        }
                  else
                        {
                              nbody[ i ] =
                                    addBinderToBody( pat[ i ], body[ i ] );
                        }
            }
            return nbody;
      }
      Type elementType ;

      /** constructs a word recognizer from an array of patterns which
       *  should all be SequencePatterns ( no wildcard * )
       *  precondition: pat.type corresponds to element type
       *  @param _m          Matcher object, holds the result
       *  @param pat         the (Sequence) patterns
       *  @param body        the bodies
       *  @param defaultCase code that is run when nothing matches. may be null, it
       *                     becomes a ThrowMatchError then

       */
      public void construct( Matcher _m,
                             Tree[] pat,
                             Tree[] body,
                             Tree defaultCase,
                             boolean doBinding ) {

            this.pat  = pat;
            this.body = body;
            assert body.length == pat.length;
            this._m = _m;

            this.cf = new CodeFactory( unit, infer /*, _m.pos*/ );

            Type seqType = pat[ 0 ].type();

            elementType = cf.getElemType_Sequence( seqType );

            NondetWordAutom manyNfa[] = new NondetWordAutom[ pat.length ];

            BerrySethi build = new BerrySethi();

            for( int i = 0; i < pat.length; i++ )
                  {
                        manyNfa[ i ] = build.automatonFrom( pat[ i ],
                                                            new Integer( i ));
                  }

            // merge nfas into one if necessary

            NondetWordAutom nfa =
                  (pat.length > 1) ? new NondetWordAutom( manyNfa )
                  : manyNfa[ 0 ];

            DetWordAutom dfa = new DetWordAutom( nfa );

            WordAutomInScala scalaAut = new WordAutomInScala( dfa,
                                                              elementType,
                                                              _m.owner,
                                                              cf);
            scalaAut.translate();

            if( defaultCase == null )
                  defaultCase = cf.ThrowMatchError( Position.FIRSTPOS, _m.resultType );

            Tree newbody[] = doBinding ? addBindersToBodies( body ): body;

            _m.tree = scalaAut.getMatcherSwitch( _m.selector,
                                                 defaultCase,
                                                 newbody,
                                                 _m.resultType );
      } // construct (Matcher, Tree[], Tree[], Tree, boolean )

      /** constructor, invoked  by AlgebraicMatcher
       */
      SequenceMatcher( Unit unit, Infer infer ) {
            super( unit, infer );
            //Symbol predefSym = defs.getModule( defs.SCALA, Names.Predef );
            //Scope predefScope = predefSym.members();
      }
} // class SequenceMatcher