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