summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/matching/Autom2.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/matching/Autom2.scala')
-rw-r--r--src/compiler/scala/tools/nsc/matching/Autom2.scala196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/Autom2.scala b/src/compiler/scala/tools/nsc/matching/Autom2.scala
new file mode 100644
index 0000000000..b99db700b4
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/matching/Autom2.scala
@@ -0,0 +1,196 @@
+package scala.tools.nsc.matching ;
+
+//import java.util._ ;
+
+import scala.tools.nsc.util.Position;
+
+trait Autom2: TransMatcher {
+
+ import global._;
+
+ /** @param owner owner of the pattern matching expression
+ */
+ abstract class Autom2Scala {
+
+ val dfa: DetWordAutom;
+ val owner: Symbol;
+
+ protected var optimize = true;
+
+ final val FAIL = -1;
+
+ /** symbol of the matcher DefDef or Label */
+ var funSym:Symbol = _;
+
+ /** symbol of the iterator ( scala.SequenceIterator ) */
+ var iterSym: Symbol = _;
+
+ /** symbol of the switching result ( scala.Int ) */
+ var resultSym: Symbol = _;
+
+ /** symbol of the state variable ( scala.Int ) */
+ var stateSym: Symbol = _;
+
+ /** symbol of variable holding current label */
+ var curSym: Symbol = _;
+
+ /** symbol of boolean variable that indicates we have not reached end of sequence */
+ var hasnSym: Symbol = _;
+
+ val am = new AlgebraicMatcher();
+
+ var pos: Int = Position.FIRSTPOS;
+
+ val elementType: Type;
+
+ def funRetType(): Type = {
+ funSym.tpe match {
+ case MethodType( _, retType )=> retType;
+ case _ => scala.Predef.error("quoi?");
+ }
+ }
+
+ def callFun(args: List[Tree]): Tree = Apply(Ident(funSym),args);
+
+ // overridden in RightTracerInScala
+ def loadCurrentElem(body: Tree): Tree = {
+ Block(
+ List(
+ ValDef(this.hasnSym, _hasNext( _iter() ) ),
+ ValDef(this.curSym, If(Ident( hasnSym ),
+ _next( _iter() ),
+ EmptyTree))
+ ),
+ body
+ );
+ }
+
+ /** bug ?? */
+ def currentElem() = { Ident( curSym ) }
+
+ def currentMatches(label: Label): Tree = {
+ label match {
+ case TreeLabel( pat ) =>
+ _cur_match( pat );
+ case SimpleLabel(lit: Literal) =>
+ Equals( currentElem(), lit );
+ case _ => // cannot happen
+ scala.Predef.error("expected either algebraic or simple label:"+label);
+ }
+ }
+
+ //
+ // translation of automata to scala code
+ //
+
+
+ /** `[switchResult]' */
+ def _swres(): Tree = { Ident( resultSym );}
+
+ /** `<state>' param */
+ def _state(): Tree = { Ident( stateSym ); }
+
+ /** `<iterator>' param */
+ def _iter(): Tree = { Ident( iterSym ); }
+
+ /** simple optimization: if we are in a sink state, stop traversing sequence
+ */
+ def stateWrap(i: Int): Tree = {
+ if( dfa.isSink( i ))
+ run_finished( i ); // state won't change! optimization
+ else
+ If( Negate( Ident( hasnSym )),
+ run_finished( i ),
+ code_state_NEW( i ));
+ }
+
+ /** body of the matcherDefFun
+ */
+ def code_body_NEW(): Tree = {
+ var cases: List[CaseDef] = Nil;
+
+ //val tags = new Array[Int](dfa.nstates());
+ //val bodies = new Array[Tree](dfa.nstates());
+ var i = 0; while (i < dfa.nstates()) {
+ cases = CaseDef( Literal(i), stateWrap(i)) :: cases;
+ i = i + 1;
+ }
+ //if( optimize )
+ loadCurrentElem( Match( _state(), cases ));
+
+ /*
+ Tree res = code_error();
+ for( int i = dfa.nstates-2; i>= 0; i-- )
+ res = gen.If( Equals( _state(), gen.mkIntLit( pos, i )),
+ bodies[ i ] ,
+ res );
+
+ return loadCurrentElem( res );
+ */
+ }
+
+ /* calling the (AlgebraicMatcher)PatternMatcher here */
+ def _cur_match(pat: Tree): Tree = {
+ val m: PartialMatcher = new PartialMatcher {
+ val owner = Autom2Scala.this.funSym; /* owner*/
+ val selector = currentElem(); /* root */
+ /* defs.boolean_TYPE() restype */
+ };
+
+ am.construct( m, List (
+ CaseDef( pat, Literal(true)),
+ CaseDef( Ident(nme.WILDCARD), Literal(false))
+ ),
+ false);
+ am.toTree();
+ }
+
+ // @todo should be abstract
+ def code_delta( i:Int, label: Label): Tree = {
+ scala.Predef.error("should not happen");
+ }
+
+ /** some error happened which is due to bug in translation/automaton
+ */
+ final def code_error(): Tree = {
+ ThrowMatchError( pos , funRetType() );
+ }
+
+ def code_fail(): Tree = {
+ Literal( FAIL ); //gen.mkIntLit(Position.FIRSTPOS, FAIL );
+ }
+
+ /** code for the return value of the automaton translation
+ */
+ def run_finished(state: Int): Tree = {
+ if( dfa.isFinal( state ))
+ Literal(
+ dfa.finals.get( new Integer( state ) ).asInstanceOf[Integer]
+ .intValue()
+ )
+ else
+ Literal( FAIL );
+ }
+
+ def code_state_NEW(i: Int): Tree = {
+ var stateBody = code_delta( i, DefaultLabel() );
+ if( stateBody == null )
+ stateBody = code_fail();
+ val trans = dfa.deltaq( i );
+
+ val labs = dfa.labels().iterator();
+ while(labs.hasNext()) {
+ val label = labs.next();
+ val next = trans.get( label ).asInstanceOf[Integer];
+ val action = code_delta( i, label.asInstanceOf[Label] );
+ if( action != null ) {
+ /*assert*/ //stateBody != null : "stateBody is null";
+ stateBody = If( currentMatches(label.asInstanceOf[Label] ),
+ action,
+ stateBody);
+ }
+ }
+ stateBody;
+ }
+ }
+}