summaryrefslogblamecommitdiff
path: root/sources/scalac/transformer/matching/LeftTracerInScala.java
blob: 336858d453d17c436c9bca7bfbf6311ebbf52b0e (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 elemType ) {
            return new Type.TypeRef( defs.SCALA_TYPE,
                                     cf.seqTraceSym(),
                                     new Type[] { elemType });
      }


      Matcher _m ;
      public LeftTracerInScala( DetWordAutom dfa,
                                Type elementType,
                                Matcher m,
                                CodeFactory cf ) {

	  super( dfa, elementType, m.owner, cf );
	  this._m = m;
	  this.selector = m.selector;
	  //helpMap = new HashMap(); moved up
	  helpVarDefs = new Vector();

      }


    // move WordAutom down.

    Vector  helpVarDefs;

    Symbol makeHelpVar( Symbol realVar ) {
	Symbol helpVar = new TermSymbol( pos,
					 cf.fresh.newName( realVar.name
							   .toString() ),
					 owner,
					 0)
	    .setType( cf.SeqListType( elementType ) ) ;

	helpMap.put( realVar, helpVar );

	Tree varDef = gen.ValDef(helpVar, cf.newSeqNil( elementType ));
	// set mutable flag of symbol helpVar ??
	helpVarDefs.add( varDef );
	return helpVar;
    }

    Symbol makeHelpVarSEQ( Tree pat ) {
	String  helpName = String.valueOf( pat.hashCode() ); //wicked, in'it ?
	Symbol helpVar =
	    new TermSymbol( pos,
			    cf.fresh.newName(Name.fromString( helpName )),
			    owner,
			    0)
	    .setType( cf.SeqListType( pat.type() )) ;

	ValDef varDef = (ValDef) gen.ValDef( helpVar,
					     cf.ignoreValue( cf.SeqListType( pat.type() )));
	helpVarDefs.add( varDef );
	return helpVar;
    }

    void handleVars( Vector freeVars ) {
	for(Iterator it = freeVars.iterator(); it.hasNext(); ) {
	    makeHelpVar( (Symbol) it.next() );
	}
    }

    /** returns a Tree whose type is boolean.
     *  now we care about free vars
     */
    /*
      Tree handleBody( HashMap helpMap ) {
      Tree res[] = new Tree[ helpMap.keySet().size() + 1 ];
      int j = 0;
      for( Iterator it = helpMap.keySet().iterator(); it.hasNext(); ) {
      Symbol vsym = (Symbol) it.next();
      Symbol hv   = (Symbol) helpMap.get( vsym );
      hv.type( cf.SeqListType( elementType ) ) ;
      Tree refv   = gen.Ident(Position.FIRSTPOS, vsym);
      Tree refhv  = gen.Ident(Position.FIRSTPOS, hv);
      res[ j++ ] = gen.Assign( refhv, refv );
      }

      res[ j ] = super.handleBody( freeVars ); // just `true'

      return cf.Block(Position.FIRSTPOS, res, res[j].type() );
      }
    */
    protected void initializeSyms() {
	funSymName = "leftTracer";

	nestedMap = new HashMap();

	super.initializeSyms();

	this.accumSym = newParam("accum")                    // accumulator
	    .setType( _accumType( elementType ));

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

	// 2 do: rename switchresultsym to something else...

	this.resultSym = new TermSymbol( //Kinds.VAR,
					pos,
					cf.fresh.newName("trace"),
					owner,
					0 )
	    .setType( _accumType( elementType ) ) ;

    }

    // 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 ));

	return callFun( new Tree[] { newAcc , _iter(), cf.Int( target )} );
    }


    /** 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 = cf.If( _cur_eq( _iter(), (Label) label ),
				   action,
				   stateBody);
	    }
	}

	return wrapStateBody( stateBody,
			      elseBody,
			      runFinished,
			      i );

    }

    Tree[] getTrace() {

	initializeSyms();
	Tree tb = code_body();
	theDefDef = gen.DefDef( this.funSym,
				tb );

	Vector v = new Vector();

	v.addAll( helpVarDefs );

	//
	// `def leftTracer(...) = ...'                 the function definition
	v.add( theDefDef );

	Tree emptyAcc    = cf._seqTraceNil( elementType );

	// the valdef is needed, because passing emptyAcc as a parameter
	//   results in a ClassCastException at runtime (?!)

	Symbol emptyAccSym = new TermSymbol( pos,
					     cf.fresh.newName("acc"),
					     owner,
					     0 )
	    .setType( _accumType( elementType ) ) ;

	// `val acc = SeqNil[ elementType ]'                 init accumulator
	v.add( gen.ValDef( pos, emptyAccSym, emptyAcc) );

	Tree run = callFun( new Tree[] {
	    gen.Ident( pos, emptyAccSym ),
	    cf.newIterator( selector, selector.type() ),
	    cf.Int( 0 )  });

	run = gen.ValDef( Position.FIRSTPOS, resultSym, run );

	v.add( run );

	// vars...
	for( Iterator it = helpMap.keySet().iterator(); it.hasNext(); ) {
	    v.add( bindVar( (Symbol) it.next()) );
	}

	/* IF YOU NEED DEBUG OUTPUT AT RUNTIME
	   v.add( cf.debugPrintRuntime( "the trace is" ) );
	   v.add( cf.debugPrintRuntime( gen.Ident( pos, resultSym ) ) );
	   v.add( cf.debugPrintNewlineRuntime( "" ) );
	*/

	Tree res[] = new Tree[ v.size() ];
	int j = 0;
	for( Iterator it = v.iterator(); it.hasNext(); )
	    res[ j++ ] = (Tree) it.next();

	_m.varMap = nestedMap;

	return res;

    }

    public HashMap nestedMap;

    // calling the AlgebraicMatcher here
    Tree _cur_match( Tree pat ) {
	//System.out.println("calling algebraic matcher on type:"+pat.type);

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

	if( CollectVariableTraverser.containsBinding( pat )) {
	    switch( pat ) {
	    case Sequence(Tree[] pats):
		//System.out.println("ouch! v Left");
		Symbol hv = makeHelpVarSEQ( pat );
		nestedMap.put( pat, hv );
		Tree stm  = gen.Assign( gen.Ident(Position.FIRSTPOS, hv), currentElem() );
		m.stms = new Tree[2];
		m.stms[0] = stm;
		m.stms[1] = gen.mkBooleanLit(Position.FIRSTPOS, true);
		return cf.Block( Position.FIRSTPOS, m.stms, m.stms[1].type() );
	    }
	}

	HashMap helpMap = FreshVariableTraverser.getVars( pat, owner, cf.fresh );
	//System.out.println("varMap: "+helpMap );

	m.varMap = helpMap;

	//replaceVars( pat );

	am.construct( m, new CaseDef[] {
	    (CaseDef) cf.make.CaseDef( pat.pos,
				       pat,
				       Tree.Empty,
				       handleBody( helpMap )),
	    (CaseDef) cf.make.CaseDef( pat.pos,
				       cf.make.Ident(pat.pos, Names.WILDCARD)
				       //DON'T .setSymbol( Symbol.NONE ) !
				       .setType(pat.type()),
				       Tree.Empty,
				       gen.mkBooleanLit(Position.FIRSTPOS, false)) },
		      false
		      );
	Tree res = am.toTree().setType( defs.BOOLEAN_TYPE );
	//System.out.println("freeVars: "+freeVars);

	return res;
    }


    /** return the accumulator + last state
     */
    Tree run_finished( int state ) {
	return cf.newSeqTraceCons(new Integer( state ),
				  cf.ignoreValue( elementType ),
				  _ref( accumSym ));
    }

}