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