System.Text.RegularExpressions.RegexCompiler.GenerateOneCode C# (CSharp) Method

GenerateOneCode() private method

private GenerateOneCode ( ) : void
return void
        internal void GenerateOneCode() {
#if DBG
            if ((_options & RegexOptions.Debug) != 0) {
                Mvlocfld(_textposV, _textposF);
                Mvlocfld(_trackposV, _trackposF);
                Mvlocfld(_stackposV, _stackposF);
                Ldthis();
                Callvirt(_dumpstateM);
                StringBuilder sb = new StringBuilder();
                if (_backpos > 0)
                    sb.AppendFormat("{0:D6} ", _backpos);
                else
                    sb.Append("       ");
                sb.Append(_code.OpcodeDescription(_codepos));
                if (IsBack())
                    sb.Append(" Back");
                if (IsBack2())
                    sb.Append(" Back2");
                Message(sb.ToString());
            }
#endif

            switch (_regexopcode) {
                case RegexCode.Stop:
                    //: return;
                    Mvlocfld(_textposV, _textposF);       // update _textpos
                    Ret();
                    break;

                case RegexCode.Nothing:
                    //: break Backward;
                    Back();
                    break;

                case RegexCode.Goto:
                    //: Goto(Operand(0));
                    Goto(Operand(0));
                    break;

                case RegexCode.Testref:
                    //: if (!_match.IsMatched(Operand(0)))
                    //:     break Backward;
                    Ldthis();
                    Ldc(Operand(0));
                    Callvirt(_ismatchedM);
                    BrfalseFar(_backtrack);
                    break;

                case RegexCode.Lazybranch:
                    //: Track(Textpos());
                    PushTrack(_textposV);
                    Track();
                    break;

                case RegexCode.Lazybranch | RegexCode.Back:
                    //: Trackframe(1);
                    //: Textto(Tracked(0));
                    //: Goto(Operand(0));
                    PopTrack();
                    Stloc(_textposV);
                    Goto(Operand(0));
                    break;

                case RegexCode.Nullmark:
                    //: Stack(-1);
                    //: Track();
                    ReadyPushStack();
                    Ldc(-1);
                    DoPush();
                    TrackUnique(stackpop);
                    break;

                case RegexCode.Setmark:
                    //: Stack(Textpos());
                    //: Track();
                    PushStack(_textposV);
                    TrackUnique(stackpop);
                    break;

                case RegexCode.Nullmark | RegexCode.Back:
                case RegexCode.Setmark | RegexCode.Back:
                    //: Stackframe(1);
                    //: break Backward;
                    PopDiscardStack();
                    Back();
                    break;

                case RegexCode.Getmark:
                    //: Stackframe(1);
                    //: Track(Stacked(0));
                    //: Textto(Stacked(0));
                    ReadyPushTrack();
                    PopStack();
                    Dup();
                    Stloc(_textposV);
                    DoPush();

                    Track();
                    break;

                case RegexCode.Getmark | RegexCode.Back:
                    //: Trackframe(1);
                    //: Stack(Tracked(0));
                    //: break Backward;
                    ReadyPushStack();
                    PopTrack();
                    DoPush();
                    Back();
                    break;

                case RegexCode.Capturemark:
                    //: if (!IsMatched(Operand(1)))
                    //:     break Backward;
                    //: Stackframe(1);
                    //: if (Operand(1) != -1)
                    //:     TransferCapture(Operand(0), Operand(1), Stacked(0), Textpos());
                    //: else
                    //:     Capture(Operand(0), Stacked(0), Textpos());
                    //: Track(Stacked(0));

                    //: Stackframe(1);
                    //: Capture(Operand(0), Stacked(0), Textpos());
                    //: Track(Stacked(0));

                    if (Operand(1) != -1) {
                        Ldthis();
                        Ldc(Operand(1));
                        Callvirt(_ismatchedM);
                        BrfalseFar(_backtrack);
                    }

                    PopStack();
                    Stloc(_tempV);

                    if (Operand(1) != -1) {
                        Ldthis();
                        Ldc(Operand(0));
                        Ldc(Operand(1));
                        Ldloc(_tempV);
                        Ldloc(_textposV);
                        Callvirt(_transferM);
                    }
                    else {
                        Ldthis();
                        Ldc(Operand(0));
                        Ldloc(_tempV);
                        Ldloc(_textposV);
                        Callvirt(_captureM);
                    }

                    PushTrack(_tempV);

                    if (Operand(0) != -1 && Operand(1) != -1)
                        TrackUnique(capback2);
                    else
                        TrackUnique(capback);

                    break;


                case RegexCode.Capturemark | RegexCode.Back:
                    //: Trackframe(1);
                    //: Stack(Tracked(0));
                    //: Uncapture();
                    //: if (Operand(0) != -1 && Operand(1) != -1)
                    //:     Uncapture();
                    //: break Backward;
                    ReadyPushStack();
                    PopTrack();
                    DoPush();
                    Ldthis();
                    Callvirt(_uncaptureM);
                    if (Operand(0) != -1 && Operand(1) != -1) {
                        Ldthis();
                        Callvirt(_uncaptureM);
                    }
                    Back();
                    break;

                case RegexCode.Branchmark:
                    //: Stackframe(1);
                    //: 
                    //: if (Textpos() != Stacked(0))
                    //: {                                   // Nonempty match -> loop now
                    //:     Track(Stacked(0), Textpos());   // Save old mark, textpos
                    //:     Stack(Textpos());               // Make new mark
                    //:     Goto(Operand(0));               // Loop
                    //: }
                    //: else
                    //: {                                   // Empty match -> straight now
                    //:     Track2(Stacked(0));             // Save old mark
                    //:     Advance(1);                     // Straight
                    //: }
                    //: continue Forward;
                    {
                        LocalBuilder mark = _tempV;
                        Label      l1   = DefineLabel();

                        PopStack();
                        Dup();
                        Stloc(mark);                            // Stacked(0) -> temp
                        PushTrack(mark);
                        Ldloc(_textposV);
                        Beq(l1);                                // mark == textpos -> branch

                        // (matched != 0)

                        PushTrack(_textposV);
                        PushStack(_textposV);
                        Track();
                        Goto(Operand(0));                       // Goto(Operand(0))

                        // else

                        MarkLabel(l1);
                        TrackUnique2(branchmarkback2);
                        break;
                    }

                case RegexCode.Branchmark | RegexCode.Back:
                    //: Trackframe(2);
                    //: Stackframe(1);
                    //: Textto(Tracked(1));                     // Recall position
                    //: Track2(Tracked(0));                     // Save old mark
                    //: Advance(1);
                    PopTrack();
                    Stloc(_textposV);
                    PopStack();
                    Pop();
                    // track spot 0 is already in place
                    TrackUnique2(branchmarkback2);
                    Advance();
                    break;

                case RegexCode.Branchmark | RegexCode.Back2:
                    //: Trackframe(1);
                    //: Stack(Tracked(0));                      // Recall old mark
                    //: break Backward;                         // Backtrack
                    ReadyPushStack();
                    PopTrack();
                    DoPush();
                    Back();
                    break;


                case RegexCode.Lazybranchmark:
                    //: StackPop();
                    //: int oldMarkPos = StackPeek();
                    //: 
                    //: if (Textpos() != oldMarkPos) {         // Nonempty match -> next loop
                    //: {                                   // Nonempty match -> next loop
                    //:     if (oldMarkPos != -1)
                    //:         Track(Stacked(0), Textpos());   // Save old mark, textpos
                    //:     else
                    //:         TrackPush(Textpos(), Textpos());   
                    //: }
                    //: else
                    //: {                                   // Empty match -> no loop
                    //:     Track2(Stacked(0));             // Save old mark
                    //: }
                    //: Advance(1);
                    //: continue Forward;
                    {
                        LocalBuilder mark = _tempV;
                        Label      l1   = DefineLabel();
                        Label      l2   = DefineLabel();
                        Label      l3   = DefineLabel();

                        PopStack();
                        Dup();
                        Stloc(mark);                      // Stacked(0) -> temp

                        // if (oldMarkPos != -1)
                        Ldloc(mark);
                        Ldc(-1);
                        Beq(l2);                                // mark == -1 -> branch
                            PushTrack(mark);
                            Br(l3);
                        // else
                            MarkLabel(l2);
                            PushTrack(_textposV);
                        MarkLabel(l3);
                            
                        // if (Textpos() != mark)
                        Ldloc(_textposV);
                        Beq(l1);                                // mark == textpos -> branch
                            PushTrack(_textposV);
                            Track();
                            Br(AdvanceLabel());                 // Advance (near)
                        // else
                            MarkLabel(l1);
                            ReadyPushStack();                   // push the current textPos on the stack. 
							        // May be ignored by 'back2' or used by a true empty match.
                            Ldloc(mark);                        

                            DoPush();
                            TrackUnique2(lazybranchmarkback2);

                        break;
                    }

                case RegexCode.Lazybranchmark | RegexCode.Back:
                    //: Trackframe(2);
                    //: Track2(Tracked(0));                     // Save old mark
                    //: Stack(Textpos());                       // Make new mark
                    //: Textto(Tracked(1));                     // Recall position
                    //: Goto(Operand(0));                       // Loop

                    PopTrack();
                    Stloc(_textposV);
                    PushStack(_textposV);
                    TrackUnique2(lazybranchmarkback2);
                    Goto(Operand(0));
                    break;

                case RegexCode.Lazybranchmark | RegexCode.Back2:
                    //: Stackframe(1);
                    //: Trackframe(1);
                    //: Stack(Tracked(0));                  // Recall old mark
                    //: break Backward;
                    ReadyReplaceStack(0);
                    PopTrack();
                    DoReplace();
                    Back();
                    break;

                case RegexCode.Nullcount:
                    //: Stack(-1, Operand(0));
                    //: Track();
                    ReadyPushStack();
                    Ldc(-1);
                    DoPush();
                    ReadyPushStack();
                    Ldc(Operand(0));
                    DoPush();
                    TrackUnique(stackpop2);
                    break;

                case RegexCode.Setcount:
                    //: Stack(Textpos(), Operand(0));
                    //: Track();
                    PushStack(_textposV);
                    ReadyPushStack();
                    Ldc(Operand(0));
                    DoPush();
                    TrackUnique(stackpop2);
                    break;


                case RegexCode.Nullcount | RegexCode.Back:
                case RegexCode.Setcount | RegexCode.Back:
                    //: Stackframe(2);
                    //: break Backward;
                    PopDiscardStack(2);
                    Back();
                    break;


                case RegexCode.Branchcount:
                    //: Stackframe(2);
                    //: int mark = Stacked(0);
                    //: int count = Stacked(1);
                    //: 
                    //: if (count >= Operand(1) || Textpos() == mark && count >= 0)
                    //: {                                   // Max loops or empty match -> straight now
                    //:     Track2(mark, count);            // Save old mark, count
                    //:     Advance(2);                     // Straight
                    //: }
                    //: else
                    //: {                                   // Nonempty match -> count+loop now
                    //:     Track(mark);                    // remember mark
                    //:     Stack(Textpos(), count + 1);    // Make new mark, incr count
                    //:     Goto(Operand(0));               // Loop
                    //: }
                    //: continue Forward;
                    {
                        LocalBuilder count = _tempV;
                        LocalBuilder mark  = _temp2V;
                        Label      l1    = DefineLabel();
                        Label      l2    = DefineLabel();

                        PopStack();
                        Stloc(count);                           // count -> temp
                        PopStack();
                        Dup();
                        Stloc(mark);                            // mark -> temp2
                        PushTrack(mark);

                        Ldloc(_textposV);
                        Bne(l1);                                // mark != textpos -> l1
                        Ldloc(count);
                        Ldc(0);
                        Bge(l2);                                // count >= 0 && mark == textpos -> l2

                        MarkLabel(l1);
                        Ldloc(count);
                        Ldc(Operand(1));
                        Bge(l2);                                // count >= Operand(1) -> l2

                        // else
                        PushStack(_textposV);
                        ReadyPushStack();
                        Ldloc(count);                           // mark already on track
                        Ldc(1);
                        Add();
                        DoPush();
                        Track();
                        Goto(Operand(0));

                        // if (count >= Operand(1) || Textpos() == mark)
                        MarkLabel(l2);
                        PushTrack(count);                       // mark already on track
                        TrackUnique2(branchcountback2);
                        break;
                    }

                case RegexCode.Branchcount | RegexCode.Back:
                    //: Trackframe(1);
                    //: Stackframe(2);
                    //: if (Stacked(1) > 0)                     // Positive -> can go straight
                    //: {
                    //:     Textto(Stacked(0));                 // Zap to mark
                    //:     Track2(Tracked(0), Stacked(1) - 1); // Save old mark, old count
                    //:     Advance(2);                         // Straight
                    //:     continue Forward;
                    //: }
                    //: Stack(Tracked(0), Stacked(1) - 1);      // recall old mark, old count
                    //: break Backward;
                    {

                        LocalBuilder count = _tempV;
                        Label      l1    = DefineLabel();
                        PopStack();
                        Ldc(1);
                        Sub();
                        Dup();
                        Stloc(count);
                        Ldc(0);
                        Blt(l1);

                        // if (count >= 0)
                        PopStack();
                        Stloc(_textposV);
                        PushTrack(count);                       // Tracked(0) is alredy on the track
                        TrackUnique2(branchcountback2);
                        Advance();

                        // else
                        MarkLabel(l1);
                        ReadyReplaceStack(0);
                        PopTrack();
                        DoReplace();
                        PushStack(count);
                        Back();
                        break;
                    }

                case RegexCode.Branchcount | RegexCode.Back2:
                    //: Trackframe(2);
                    //: Stack(Tracked(0), Tracked(1));      // Recall old mark, old count
                    //: break Backward;                     // Backtrack

                    PopTrack();
                    Stloc(_tempV);
                    ReadyPushStack();
                    PopTrack();
                    DoPush();
                    PushStack(_tempV);
                    Back();
                    break;

                case RegexCode.Lazybranchcount:
                    //: Stackframe(2);
                    //: int mark = Stacked(0);
                    //: int count = Stacked(1);
                    //:
                    //: if (count < 0)
                    //: {                                   // Negative count -> loop now
                    //:     Track2(mark);                   // Save old mark
                    //:     Stack(Textpos(), count + 1);    // Make new mark, incr count
                    //:     Goto(Operand(0));               // Loop
                    //: }
                    //: else
                    //: {                                   // Nonneg count or empty match -> straight now
                    //:     Track(mark, count, Textpos());  // Save mark, count, position
                    //: }
                    {
                        LocalBuilder count = _tempV;
                        LocalBuilder mark  = _temp2V;
                        Label      l1    = DefineLabel();
                        Label      l2    = DefineLabel();
                        Label      l3    = _labels[NextCodepos()];

                        PopStack();
                        Stloc(count);                           // count -> temp
                        PopStack();
                        Stloc(mark);                            // mark -> temp2

                        Ldloc(count);
                        Ldc(0);
                        Bge(l1);                                // count >= 0 -> l1

                        // if (count < 0)
                        PushTrack(mark);
                        PushStack(_textposV);
                        ReadyPushStack();
                        Ldloc(count);
                        Ldc(1);
                        Add();
                        DoPush();
                        TrackUnique2(lazybranchcountback2);
                        Goto(Operand(0));

                        // else
                        MarkLabel(l1);
                        PushTrack(mark);
                        PushTrack(count);
                        PushTrack(_textposV);
                        Track();
                        break;
                    }

                case RegexCode.Lazybranchcount | RegexCode.Back:
                    //: Trackframe(3);
                    //: int mark = Tracked(0);
                    //: int textpos = Tracked(2);
                    //: if (Tracked(1) <= Operand(1) && textpos != mark)
                    //: {
                    //:     Textto(Tracked(2));                 // Recall position
                    //:     Stack(Textpos(), Tracked(1) + 1);   // Make new mark, incr count
                    //:     Track2(Tracked(0));                 // Save old mark
                    //:     Goto(Operand(0));                   // Loop
                    //:     continue Forward;
                    //: }
                    //: else
                    //: {
                    //:     Stack(Tracked(0), Tracked(1));      // Recall old mark, count
                    //:     break Backward;                     // backtrack
                    //: }
                    {
                        Label       l1 = DefineLabel();
                        LocalBuilder  cV = _tempV;
                        PopTrack();
                        Stloc(_textposV);
                        PopTrack();
                        Dup();
                        Stloc(cV);
                        Ldc(Operand(1));
                        Bgt(l1);                                // Tracked(1) > Operand(1) -> l1

                        Ldloc(_textposV);
                        TopTrack();
                        Beq(l1);                                // textpos == mark -> l1

                        PushStack(_textposV);
                        ReadyPushStack();
                        Ldloc(cV);
                        Ldc(1);
                        Add();
                        DoPush();
                        TrackUnique2(lazybranchcountback2);
                        Goto(Operand(0));

                        MarkLabel(l1);
                        ReadyPushStack();
                        PopTrack();
                        DoPush();
                        PushStack(cV);
                        Back();
                        break;
                    }

                case RegexCode.Lazybranchcount | RegexCode.Back2:

                    ReadyReplaceStack(1);
                    PopTrack();
                    DoReplace();
                    ReadyReplaceStack(0);
                    TopStack();
                    Ldc(1);
                    Sub();
                    DoReplace();
                    Back();
                    break;


                case RegexCode.Setjump:
                    //: Stack(Trackpos(), Crawlpos());
                    //: Track();
                    ReadyPushStack();
                    Ldthisfld(_trackF);
                    Ldlen();
                    Ldloc(_trackposV);
                    Sub();
                    DoPush();
                    ReadyPushStack();
                    Ldthis();
                    Callvirt(_crawlposM);
                    DoPush();
                    TrackUnique(stackpop2);
                    break;

                case RegexCode.Setjump | RegexCode.Back:
                    //: Stackframe(2);
                    PopDiscardStack(2);
                    Back();
                    break;


                case RegexCode.Backjump:
                    //: Stackframe(2);
                    //: Trackto(Stacked(0));
                    //: while (Crawlpos() != Stacked(1))
                    //:     Uncapture();
                    //: break Backward;
                    {
                        Label      l1    = DefineLabel();
                        Label      l2    = DefineLabel();

                        PopStack();
                        Ldthisfld(_trackF);
                        Ldlen();
                        PopStack();
                        Sub();
                        Stloc(_trackposV);
                        Dup();
                        Ldthis();
                        Callvirt(_crawlposM);
                        Beq(l2);

                        MarkLabel(l1);
                        Ldthis();
                        Callvirt(_uncaptureM);
                        Dup();
                        Ldthis();
                        Callvirt(_crawlposM);
                        Bne(l1);

                        MarkLabel(l2);
                        Pop();
                        Back();
                        break;
                    }

                case RegexCode.Forejump:
                    //: Stackframe(2);
                    //: Trackto(Stacked(0));
                    //: Track(Stacked(1));
                    PopStack();
                    Stloc(_tempV);
                    Ldthisfld(_trackF);
                    Ldlen();
                    PopStack();
                    Sub();
                    Stloc(_trackposV);
                    PushTrack(_tempV);
                    TrackUnique(forejumpback);
                    break;

                case RegexCode.Forejump | RegexCode.Back:
                    //: Trackframe(1);
                    //: while (Crawlpos() != Tracked(0))
                    //:     Uncapture();
                    //: break Backward;
                    {
                        Label      l1    = DefineLabel();
                        Label      l2    = DefineLabel();

                        PopTrack();

                        Dup();
                        Ldthis();
                        Callvirt(_crawlposM);
                        Beq(l2);

                        MarkLabel(l1);
                        Ldthis();
                        Callvirt(_uncaptureM);
                        Dup();
                        Ldthis();
                        Callvirt(_crawlposM);
                        Bne(l1);

                        MarkLabel(l2);
                        Pop();
                        Back();
                        break;
                    }

                case RegexCode.Bol:
                    //: if (Leftchars() > 0 && CharAt(Textpos() - 1) != '\n')
                    //:     break Backward;
                    {
                        Label      l1    = _labels[NextCodepos()];
                        Ldloc(_textposV);
                        Ldloc(_textbegV);
                        Ble(l1);
                        Leftchar();
                        Ldc((int)'\n');
                        BneFar(_backtrack);
                        break;
                    }

                case RegexCode.Eol:
                    //: if (Rightchars() > 0 && CharAt(Textpos()) != '\n')
                    //:     break Backward;
                    {
                        Label      l1    = _labels[NextCodepos()];
                        Ldloc(_textposV);
                        Ldloc(_textendV);
                        Bge(l1);
                        Rightchar();
                        Ldc((int)'\n');
                        BneFar(_backtrack);
                        break;
                    }

                case RegexCode.Boundary:
                case RegexCode.Nonboundary:
                    //: if (!IsBoundary(Textpos(), _textbeg, _textend))
                    //:     break Backward;
                    Ldthis();
                    Ldloc(_textposV);
                    Ldloc(_textbegV);
                    Ldloc(_textendV);
                    Callvirt(_isboundaryM);
                    if (Code() == RegexCode.Boundary)
                        BrfalseFar(_backtrack);
                    else
                        BrtrueFar(_backtrack);
                    break;

                case RegexCode.ECMABoundary:
                case RegexCode.NonECMABoundary:
                    //: if (!IsECMABoundary(Textpos(), _textbeg, _textend))
                    //:     break Backward;
                    Ldthis();
                    Ldloc(_textposV);
                    Ldloc(_textbegV);
                    Ldloc(_textendV);
                    Callvirt(_isECMABoundaryM);
                    if (Code() == RegexCode.ECMABoundary)
                        BrfalseFar(_backtrack);
                    else
                        BrtrueFar(_backtrack);
                    break;

                case RegexCode.Beginning:
                    //: if (Leftchars() > 0)
                    //:    break Backward;
                    Ldloc(_textposV);
                    Ldloc(_textbegV);
                    BgtFar(_backtrack);
                    break;

                case RegexCode.Start:
                    //: if (Textpos() != Textstart())
                    //:    break Backward;
                    Ldloc(_textposV);
                    Ldthisfld(_textstartF);
                    BneFar(_backtrack);
                    break;

                case RegexCode.EndZ:
                    //: if (Rightchars() > 1 || Rightchars() == 1 && CharAt(Textpos()) != '\n')
                    //:    break Backward;
                    Ldloc(_textposV);
                    Ldloc(_textendV);
                    Ldc(1);
                    Sub();
                    BltFar(_backtrack);
                    Ldloc(_textposV);
                    Ldloc(_textendV);
                    Bge(_labels[NextCodepos()]);
                    Rightchar();
                    Ldc((int)'\n');
                    BneFar(_backtrack);
                    break;

                case RegexCode.End:
                    //: if (Rightchars() > 0)
                    //:    break Backward;
                    Ldloc(_textposV);
                    Ldloc(_textendV);
                    BltFar(_backtrack);
                    break;

                case RegexCode.One:
                case RegexCode.Notone:
                case RegexCode.Set:
                case RegexCode.One      | RegexCode.Rtl:
                case RegexCode.Notone   | RegexCode.Rtl:
                case RegexCode.Set      | RegexCode.Rtl:
                case RegexCode.One      | RegexCode.Ci:
                case RegexCode.Notone   | RegexCode.Ci:
                case RegexCode.Set      | RegexCode.Ci:
                case RegexCode.One      | RegexCode.Ci  | RegexCode.Rtl:
                case RegexCode.Notone   | RegexCode.Ci  | RegexCode.Rtl:
                case RegexCode.Set      | RegexCode.Ci  | RegexCode.Rtl:

                    //: if (Rightchars() < 1 || Rightcharnext() != (char)Operand(0))
                    //:    break Backward;
                    Ldloc(_textposV);

                    if (!IsRtl()) {
                        Ldloc(_textendV);
                        BgeFar(_backtrack);
                        Rightcharnext();
                    }
                    else {
                        Ldloc(_textbegV);
                        BleFar(_backtrack);
                        Leftcharnext();
                    }

                    if (IsCi())
                        CallToLower();

                    if (Code() == RegexCode.Set) {

                        Ldstr(_strings[Operand(0)]);
                        Call(_charInSetM);

                        BrfalseFar(_backtrack);
                    }
                    else {
                        Ldc(Operand(0));
                        if (Code() == RegexCode.One)
                            BneFar(_backtrack);
                        else
                            BeqFar(_backtrack);
                    }
                    break;

                case RegexCode.Multi:
                case RegexCode.Multi | RegexCode.Ci:
                    //

                    {
                        int i;
                        String str;

                        str = _strings[Operand(0)];

                        Ldc(str.Length);
                        Ldloc(_textendV);
                        Ldloc(_textposV);
                        Sub();
                        BgtFar(_backtrack);

                        // unroll the string
                        for (i = 0; i < str.Length; i++) {
                            Ldloc(_textV);
                            Ldloc(_textposV);
                            if (i != 0) {
                                Ldc(i);
                                Add();
                            }
                            Callvirt(_getcharM);
                            if (IsCi())
                                CallToLower();
                            
                            Ldc((int)str[i]);
                            BneFar(_backtrack);
                        }

                        Ldloc(_textposV);
                        Ldc(str.Length);
                        Add();
                        Stloc(_textposV);
                        break;
                    }


                case RegexCode.Multi | RegexCode.Rtl:
                case RegexCode.Multi | RegexCode.Ci  | RegexCode.Rtl:
                    //: String Str = _strings[Operand(0)];
                    //: int c;
                    //: if (Leftchars() < (c = Str.Length))
                    //:     break Backward;
                    //: while (c > 0)
                    //:     if (Str[--c] != Leftcharnext())
                    //:         break Backward;
                    {
                        int i;
                        String str;

                        str = _strings[Operand(0)];

                        Ldc(str.Length);
                        Ldloc(_textposV);
                        Ldloc(_textbegV);
                        Sub();
                        BgtFar(_backtrack);

                        // unroll the string
                        for (i = str.Length; i > 0;) {
                            i--;
                            Ldloc(_textV);
                            Ldloc(_textposV);
                            Ldc(str.Length - i);
                            Sub();
                            Callvirt(_getcharM);
                            if (IsCi()) 
                            {
                                CallToLower();
                            }
                            Ldc((int)str[i]);
                            BneFar(_backtrack);
                        }

                        Ldloc(_textposV);
                        Ldc(str.Length);
                        Sub();
                        Stloc(_textposV);

                        break;
                    }

                case RegexCode.Ref:
                case RegexCode.Ref | RegexCode.Rtl:
                case RegexCode.Ref | RegexCode.Ci:
                case RegexCode.Ref | RegexCode.Ci | RegexCode.Rtl:
                    //: int capnum = Operand(0);
                    //: int j, c;
                    //: if (!_match.IsMatched(capnum)) {
                    //:     if (!RegexOptions.ECMAScript)
                    //:         break Backward;
                    //: } else {
                    //:     if (Rightchars() < (c = _match.MatchLength(capnum)))
                    //:         break Backward;
                    //:     for (j = _match.MatchIndex(capnum); c > 0; j++, c--)
                    //:         if (CharAt(j) != Rightcharnext())
                    //:             break Backward;
                    //: }
                    {
                        LocalBuilder lenV     = _tempV;
                        LocalBuilder indexV   = _temp2V;
                        Label      l1       = DefineLabel();

                        Ldthis();
                        Ldc(Operand(0));
                        Callvirt(_ismatchedM);
                        if ((_options & RegexOptions.ECMAScript) != 0)
                            Brfalse(AdvanceLabel());
                        else
                            BrfalseFar(_backtrack); // !IsMatched() -> back

                        Ldthis();
                        Ldc(Operand(0));
                        Callvirt(_matchlengthM);
                        Dup();
                        Stloc(lenV);
                        if (!IsRtl()) {
                            Ldloc(_textendV);
                            Ldloc(_textposV);
                        }
                        else {
                            Ldloc(_textposV);
                            Ldloc(_textbegV);
                        }
                        Sub();
                        BgtFar(_backtrack);         // Matchlength() > Rightchars() -> back

                        Ldthis();
                        Ldc(Operand(0));
                        Callvirt(_matchindexM);
                        if (!IsRtl()) {
                            Ldloc(lenV);
                            Add(IsRtl());
                        }
                        Stloc(indexV);              // index += len

                        Ldloc(_textposV);
                        Ldloc(lenV);
                        Add(IsRtl());
                        Stloc(_textposV);           // texpos += len

                        MarkLabel(l1);
                        Ldloc(lenV);
                        Ldc(0);
                        Ble(AdvanceLabel());
                        Ldloc(_textV);
                        Ldloc(indexV);
                        Ldloc(lenV);
                        if (IsRtl()) {
                            Ldc(1);
                            Sub();
                            Dup();
                            Stloc(lenV);
                        }
                        Sub(IsRtl());
                        Callvirt(_getcharM);
                        if (IsCi())
                            CallToLower();
                        
                        Ldloc(_textV);
                        Ldloc(_textposV);
                        Ldloc(lenV);
                        if (!IsRtl()) {
                            Dup();
                            Ldc(1);
                            Sub();
                            Stloc(lenV);
                        }
                        Sub(IsRtl());
                        Callvirt(_getcharM);
                        if (IsCi())
                            CallToLower();
                        
                        Beq(l1);
                        Back();
                        break;
                    }


                case RegexCode.Onerep:
                case RegexCode.Notonerep:
                case RegexCode.Setrep:
                case RegexCode.Onerep | RegexCode.Rtl:
                case RegexCode.Notonerep | RegexCode.Rtl:
                case RegexCode.Setrep | RegexCode.Rtl:
                case RegexCode.Onerep | RegexCode.Ci:
                case RegexCode.Notonerep | RegexCode.Ci:
                case RegexCode.Setrep | RegexCode.Ci:
                case RegexCode.Onerep | RegexCode.Ci | RegexCode.Rtl:
                case RegexCode.Notonerep | RegexCode.Ci | RegexCode.Rtl:
                case RegexCode.Setrep | RegexCode.Ci | RegexCode.Rtl:
                    //: int c = Operand(1);
                    //: if (Rightchars() < c)
                    //:     break Backward;
                    //: char ch = (char)Operand(0);
                    //: while (c-- > 0)
                    //:     if (Rightcharnext() != ch)
                    //:         break Backward;
                    {
                        LocalBuilder lenV = _tempV;
                        Label      l1   = DefineLabel();

                        int c = Operand(1);

                        if (c == 0)
                            break;

                        Ldc(c);
                        if (!IsRtl()) {
                            Ldloc(_textendV);
                            Ldloc(_textposV);
                        }
                        else {
                            Ldloc(_textposV);
                            Ldloc(_textbegV);
                        }
                        Sub();
                        BgtFar(_backtrack);         // Matchlength() > Rightchars() -> back

                        Ldloc(_textposV);
                        Ldc(c);
                        Add(IsRtl());
                        Stloc(_textposV);           // texpos += len

                        Ldc(c);
                        Stloc(lenV);

                        MarkLabel(l1);
                        Ldloc(_textV);
                        Ldloc(_textposV);
                        Ldloc(lenV);
                        if (IsRtl()) {
                            Ldc(1);
                            Sub();
                            Dup();
                            Stloc(lenV);
                            Add();
                        }
                        else {
                            Dup();
                            Ldc(1);
                            Sub();
                            Stloc(lenV);
                            Sub();
                        }
                        Callvirt(_getcharM);
                        if (IsCi())
                            CallToLower();
                        
                        if (Code() == RegexCode.Setrep) {
                            Ldstr(_strings[Operand(0)]);
                            Call(_charInSetM);

                            BrfalseFar(_backtrack);
                        }
                        else {
                            Ldc(Operand(0));
                            if (Code() == RegexCode.Onerep)
                                BneFar(_backtrack);
                            else
                                BeqFar(_backtrack);
                        }
                        Ldloc(lenV);
                        Ldc(0);
                        if (Code() == RegexCode.Setrep)
                            BgtFar(l1);
                        else
                            Bgt(l1);
                        break;
                    }


                case RegexCode.Oneloop:
                case RegexCode.Notoneloop:
                case RegexCode.Setloop:
                case RegexCode.Oneloop | RegexCode.Rtl:
                case RegexCode.Notoneloop | RegexCode.Rtl:
                case RegexCode.Setloop | RegexCode.Rtl:
                case RegexCode.Oneloop | RegexCode.Ci:
                case RegexCode.Notoneloop | RegexCode.Ci:
                case RegexCode.Setloop | RegexCode.Ci:
                case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl:
                case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl:
                case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl:
                    //: int c = Operand(1);
                    //: if (c > Rightchars())
                    //:     c = Rightchars();
                    //: char ch = (char)Operand(0);
                    //: int i;
                    //: for (i = c; i > 0; i--)
                    //: {
                    //:     if (Rightcharnext() != ch)
                    //:     {
                    //:         Leftnext();
                    //:         break;
                    //:     }
                    //: }
                    //: if (c > i)
                    //:     Track(c - i - 1, Textpos() - 1);

                    {
                        LocalBuilder cV   = _tempV;
                        LocalBuilder lenV = _temp2V;
                        Label      l1   = DefineLabel();
                        Label      l2   = DefineLabel();

                        int c = Operand(1);

                        if (c == 0)
                            break;
                        if (!IsRtl()) {
                            Ldloc(_textendV);
                            Ldloc(_textposV);
                        }
                        else {
                            Ldloc(_textposV);
                            Ldloc(_textbegV);
                        }
                        Sub();
                        if (c != Int32.MaxValue) {
                            Label l4 = DefineLabel();
                            Dup();
                            Ldc(c);
                            Blt(l4);
                            Pop();
                            Ldc(c);
                            MarkLabel(l4);
                        }
                        Dup();
                        Stloc(lenV);
                        Ldc(1);
                        Add();
                        Stloc(cV);

                        MarkLabel(l1);
                        Ldloc(cV);
                        Ldc(1);
                        Sub();
                        Dup();
                        Stloc(cV);
                        Ldc(0);
                        if (Code() == RegexCode.Setloop)
                            BleFar(l2);
                        else
                            Ble(l2);

                        if (IsRtl())
                            Leftcharnext();
                        else
                            Rightcharnext();
                        if (IsCi()) 
                            CallToLower();
                        
                        if (Code() == RegexCode.Setloop) {
                            Ldstr(_strings[Operand(0)]);
                            Call(_charInSetM);

                            BrtrueFar(l1);
                        }
                        else {
                            Ldc(Operand(0));
                            if (Code() == RegexCode.Oneloop)
                                Beq(l1);
                            else
                                Bne(l1);
                        }

                        Ldloc(_textposV);
                        Ldc(1);
                        Sub(IsRtl());
                        Stloc(_textposV);

                        MarkLabel(l2);
                        Ldloc(lenV);
                        Ldloc(cV);
                        Ble(AdvanceLabel());

                        ReadyPushTrack();
                        Ldloc(lenV);
                        Ldloc(cV);
                        Sub();
                        Ldc(1);
                        Sub();
                        DoPush();

                        ReadyPushTrack();
                        Ldloc(_textposV);
                        Ldc(1);
                        Sub(IsRtl());
                        DoPush();

                        Track();
                        break;
                    }

                case RegexCode.Oneloop | RegexCode.Back:
                case RegexCode.Notoneloop | RegexCode.Back:
                case RegexCode.Setloop | RegexCode.Back:
                case RegexCode.Oneloop | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Notoneloop | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Setloop | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Back:
                case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Back:
                case RegexCode.Setloop | RegexCode.Ci | RegexCode.Back:
                case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
                    //: Trackframe(2);
                    //: int i   = Tracked(0);
                    //: int pos = Tracked(1);
                    //: Textto(pos);
                    //: if (i > 0)
                    //:     Track(i - 1, pos - 1);
                    //: Advance(2);
                    PopTrack();
                    Stloc(_textposV);
                    PopTrack();
                    Stloc(_tempV);
                    Ldloc(_tempV);
                    Ldc(0);
                    BleFar(AdvanceLabel());
                    ReadyPushTrack();
                    Ldloc(_tempV);
                    Ldc(1);
                    Sub();
                    DoPush();
                    ReadyPushTrack();
                    Ldloc(_textposV);
                    Ldc(1);
                    Sub(IsRtl());
                    DoPush();
                    Trackagain();
                    Advance();
                    break;

                case RegexCode.Onelazy:
                case RegexCode.Notonelazy:
                case RegexCode.Setlazy:
                case RegexCode.Onelazy | RegexCode.Rtl:
                case RegexCode.Notonelazy | RegexCode.Rtl:
                case RegexCode.Setlazy | RegexCode.Rtl:
                case RegexCode.Onelazy | RegexCode.Ci:
                case RegexCode.Notonelazy | RegexCode.Ci:
                case RegexCode.Setlazy | RegexCode.Ci:
                case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl:
                case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl:
                case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl:
                    //: int c = Operand(1);
                    //: if (c > Rightchars())
                    //:     c = Rightchars();
                    //: if (c > 0)
                    //:     Track(c - 1, Textpos());
                    {
                        LocalBuilder cV   = _tempV;

                        int c = Operand(1);

                        if (c == 0)
                            break;

                        if (!IsRtl()) {
                            Ldloc(_textendV);
                            Ldloc(_textposV);
                        }
                        else {
                            Ldloc(_textposV);
                            Ldloc(_textbegV);
                        }
                        Sub();
                        if (c != Int32.MaxValue) {
                            Label l4 = DefineLabel();
                            Dup();
                            Ldc(c);
                            Blt(l4);
                            Pop();
                            Ldc(c);
                            MarkLabel(l4);
                        }
                        Dup();
                        Stloc(cV);
                        Ldc(0);
                        Ble(AdvanceLabel());
                        ReadyPushTrack();
                        Ldloc(cV);
                        Ldc(1);
                        Sub();
                        DoPush();
                        PushTrack(_textposV);
                        Track();
                        break;
                    }

                case RegexCode.Onelazy | RegexCode.Back:
                case RegexCode.Notonelazy | RegexCode.Back:
                case RegexCode.Setlazy | RegexCode.Back:
                case RegexCode.Onelazy | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Notonelazy | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Setlazy | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Back:
                case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Back:
                case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Back:
                case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
                case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
                    //: Trackframe(2);
                    //: int pos = Tracked(1);
                    //: Textto(pos);
                    //: if (Rightcharnext() != (char)Operand(0))
                    //:     break Backward;
                    //: int i = Tracked(0);
                    //: if (i > 0)
                    //:     Track(i - 1, pos + 1);

                    PopTrack();
                    Stloc(_textposV);
                    PopTrack();
                    Stloc(_temp2V);

                    if (!IsRtl())
                        Rightcharnext();
                    else
                        Leftcharnext();

                    if (IsCi())
                        CallToLower();

                    if (Code() == RegexCode.Setlazy) {
                        Ldstr(_strings[Operand(0)]);
                        Call(_charInSetM);

                        BrfalseFar(_backtrack);
                    }
                    else {
                        Ldc(Operand(0));
                        if (Code() == RegexCode.Onelazy)
                            BneFar(_backtrack);
                        else
                            BeqFar(_backtrack);
                    }

                    Ldloc(_temp2V);
                    Ldc(0);
                    BleFar(AdvanceLabel());
                    ReadyPushTrack();
                    Ldloc(_temp2V);
                    Ldc(1);
                    Sub();
                    DoPush();
                    PushTrack(_textposV);
                    Trackagain();
                    Advance();
                    break;

                default:
                    throw new NotImplementedException(SR.GetString(SR.UnimplementedState));
            }
        }
    }