summaryrefslogblamecommitdiff
path: root/sources/scalac/transformer/matching/LeftTracerInScala.java
blob: 4c02ce28dc144842c2f0176694b539961e476cde (plain) (tree)
1
2
3
4
5
6
7
8






                                     
                         






                                              
                                                      
 
                  
 




                                                        
 


                                           
 

                                               

                                            
                                                
 

                                             

     
                                     















                                                                   
 

                                                    



                                                                            
                                  
 



                                                           
 













                                                                                     
 
                                            


                                                                  
                                   






                                                                  
     
 

                                                             
                      
                                                   
     
 



                                                                          
                                               
 













                                                                                   


                                                          

                                                                       



                                                                    
 
                                                                                           
                                                                                           
     

 

                             
                                                              
 
                                                               
 



                                                    
 
                                       


     


                                                                              
 

                                                    
 
                                        
 
                                                                       
 
                                                 
 
                                                       
 


                                    
 
                                                     
 



                                                                            
 
                                                         
 
                                  
                                                                  









                                                                      
     
 
                     
 
                         
 









                                                                                 
     
 

                                        

                                                

                                                                            
                                       
                                               
                                                       



                                                              
                                                      


             

                                        
                                                              
                                                                           
                                                                
                             

                               





                                           

                                                            
                                                               
                                      



                                                              
     

 
package scalac.transformer.matching ;

import scalac.*;
import scalac.ast.*;
import scalac.symtab.*;
import Tree.*;
import scalac.util.Name;
import scalac.util.Names;

import scalac.transformer.TransMatch.Matcher ;

import java.util.* ;

import ch.epfl.lamp.util.Position;

public class LeftTracerInScala extends TracerInScala {

    Tree selector;

    /** symbol of the accumulator ( scala.SequenceList )
     */
    Symbol accumSym;
    Type accumType;
    Type accumTypeArg;

    Type _accumType( Type elemType ) {
        return cf.SeqTraceType( elemType );
    }

    public LeftTracerInScala( DetWordAutom dfa,
                              Type elementType,
                              Symbol owner,
                              Tree selector,
                              CodeFactory cf ) {

        super( dfa, elementType, owner, cf );
        this.selector = selector;
    }

    protected void initializeSyms() {
        this.funSym =  new TermSymbol( pos,
                                       cf.fresh.newName( "left" ),
                                       owner,
                                       Modifiers.LABEL );

        this.iterSym = new TermSymbol( pos,
                                        cf.fresh.newName( "iter" ),
                                       owner,
                                       Modifiers.MUTABLE )
            .setType( cf._seqIterType( elementType ) ) ;

        this.stateSym = new TermSymbol( pos,
                                        cf.fresh.newName( "q" ),
                                        owner,
                                        Modifiers.MUTABLE )
            .setType( defs.INT_TYPE() ) ;

        this.accumType = _accumType( elementType );
        this.accumTypeArg = accumType.typeArgs()[0];
        this.accumSym = new TermSymbol( pos,                  // accumulator
                                        cf.fresh.newName( "acc" ),
                                        owner,
                                        Modifiers.MUTABLE )
            .setType( accumType );

        //this.funSym
        //    .setType( new Type.MethodType( new Symbol[] {
        //        accumSym, iterSym, stateSym},
        //                                   accumType));

        this.funSym
            .setType( new Type.MethodType( new Symbol[] {  // dummy symbol MethodType
                new TermSymbol( pos,
                                cf.fresh.newName( "q" ),   // q:int
                                funSym,
                                Modifiers.PARAM )
                .setType( defs.INT_TYPE() ),
                new TermSymbol( pos,       // acc:List[T] accumulator
                                cf.fresh.newName( "acc" ),
                                funSym,
                                Modifiers.PARAM )
                .setType( accumType )
            },
                                           accumType)); // result type = List[T]

        this.resultSym = new TermSymbol(pos,
                                        cf.fresh.newName("trace"),
                                        owner,
                                        0 )
            .setType( accumType ) ;

        this.curSym = new TermSymbol( pos, CURRENT_ELEM, owner, 0)
            .setType( elementType );

        this.hasnSym = new TermSymbol( pos, HASNEXT, owner, 0)
            .setType( defs.BOOLEAN_TYPE() );

    }

    /* should throw an exception here really, e.g. MatchError
     */
    Tree code_fail() {
        return gen.Ident( accumSym.pos, accumSym );
    }

    /** returns translation of transition with label from i.
     *  returns null if there is no such transition(no translation needed)
     */
    Tree code_delta( int i, Label label ) {
        Integer target = dfa.delta( i, label );

        /*
          System.out.println("LeftTracer:calling dfa.delta("+i+","+label+")");
          System.out.println("result: "+target);
        */
        if( target == null )
            return null;

        // (optimization) that one is a dead state (does not make sense for tracer)
        /*
          if( target == dfa.nstates - 1 )
          return code_fail();
        */

        /*
          Tree newAcc = cf.newSeqTraceCons(new Integer(i),
          currentElem(),
          _ref( accumSym ));
        */
        Tree hd = cf.newPair( gen.mkIntLit(cf.pos, i), currentElem() );
        Tree newAcc = gen.mkNewCons( cf.pos,
                                     accumTypeArg,
                                     hd,
                                     gen.Ident( cf.pos, accumSym ));

        //return callFun( new Tree[] { newAcc , _iter(), gen.mkIntLit( cf.pos, target )} );
        return callFun( new Tree[] { gen.mkIntLit( cf.pos, target.intValue() ), newAcc } );
    }


    public Tree code_body() {

        Tree body = code_error(); // never reached at runtime.

        // state [ nstates-1 ] is the dead state, so we skip it

        //`if( state == q ) <code_state> else {...}'
        for( int i = dfa.nstates-2; i >= 0; i-- ) {
            body = code_state( i, body );
        }

        return loadCurrentElem( body );

    }

    /** return code for state i of the dfa SAME AS IN SUPER, ONLY SINK IS GONE
     */
    Tree code_state( int i, Tree elseBody ) {

        Tree runFinished; // holds result of the run
        int  finalSwRes;

        runFinished = run_finished( i );

        Tree stateBody ; // action(delta) for one particular label/test

        // default action (fail if there is none)

        stateBody = code_delta( i, Label.DefaultLabel);

        if( stateBody == null )
            stateBody = code_fail();
        // transitions of state i

        HashMap trans = ((HashMap[])dfa.deltaq)[ i ];

        for( Iterator labs = ((HashMap)dfa.deltaq( i )).keySet().iterator();
             labs.hasNext() ; ) {
            Object label = labs.next();
            Integer next = (Integer) trans.get( label );

            Tree action = code_delta( i, (Label) label );

            if( action != null ) {
                stateBody = gen.If( currentMatches((Label) label),
                                    action,
                                    stateBody);
            }
        }
        stateBody = gen.If( cf.Negate( gen.Ident( cf.pos, hasnSym )),
                            runFinished,
                            stateBody );
        return gen.If( cf.Equals( _state(), gen.mkIntLit(cf.pos, i )),
                       stateBody ,
                       elseBody );
    }

    Tree getTrace() {

        initializeSyms();

        return cf.gen.mkBlock( cf.pos, new Tree[] {
            gen.ValDef( iterSym, cf.newIterator( selector, selector.getType() )),
            gen.ValDef( stateSym, gen.mkIntLit( cf.pos, 0) ),
            gen.ValDef( accumSym, gen.mkNil( cf.pos )),
            gen.ValDef( resultSym,
                        gen.LabelDef( this.funSym,
                                      new Ident[] {
                                          gen.Ident( pos, stateSym ),
                                          gen.Ident( pos, accumSym )
                                      }, code_body() /* code_body_new ? */ ))});
    }

    // calling the AlgebraicMatcher here
    Tree _cur_match( Tree pat ) {
        //return gen.mkBooleanLit(cf.pos, true);

        //System.out.println("calling algebraic matcher on type:"+pat.type);

        Matcher m = new Matcher( owner,
                                 currentElem(),
                                 defs.BOOLEAN_TYPE() );

        if( CollectVariableTraverser.containsBinding( pat )) {
            switch( pat ) {
            case Sequence(Tree[] pats):
                return gen.mkBooleanLit(cf.pos, true);
            }
        }

        am.construct( m, new CaseDef[] {
            cf.gen.CaseDef( pat,
                            gen.mkBooleanLit( cf.pos, true )),
            cf.gen.CaseDef( cf.gen.Ident( pat.pos, defs.PATTERN_WILDCARD ),
                            gen.mkBooleanLit( cf.pos, false)) },
                      false);
        Tree res = am.toTree();
        return res;
    }


    /** return the accumulator + last state
     */
    Tree run_finished( int state ) {
        Tree hd = cf.newPair( gen.mkIntLit( cf.pos, state ),
                              gen.mkDefaultValue(cf.pos,
                                                 elementType));
        //System.err.println(hd.type);
        return gen.mkNewCons(  cf.pos,
                               accumTypeArg,
                               hd,
                               gen.Ident( cf.pos, accumSym ));
    }

}