@@ -624,6 +624,160 @@ class QAST::MASTRegexCompiler {
624
624
@ ins
625
625
}
626
626
627
+ method dynquant ($ node ) {
628
+ my @ ins := nqp ::list();
629
+
630
+ my $ backtrack := $ node . backtrack || ' g' ;
631
+ my $ sep := $ node [2 ];
632
+ my $ prefix := self . unique ($ * RXPREFIX ~ ' _rxdynquant_' ~ $ backtrack );
633
+ my $ looplabel_index := rxjump($ prefix ~ ' _loop' );
634
+ my $ looplabel := @ * RXJUMPS [$ looplabel_index ];
635
+ my $ donelabel_index := rxjump($ prefix ~ ' _done' );
636
+ my $ donelabel := @ * RXJUMPS [$ donelabel_index ];
637
+ my $ skip0label := label($ prefix ~ ' _skip0' );
638
+ my $ skip1label := label($ prefix ~ ' _skip1' );
639
+ my $ skip2label := label($ prefix ~ ' _skip2' );
640
+ my $ skip3label := label($ prefix ~ ' _skip3' );
641
+ my $ skip4label := label($ prefix ~ ' _skip4' );
642
+ my $ skip5label := label($ prefix ~ ' _skip5' );
643
+ my $ skip6label := label($ prefix ~ ' _skip6' );
644
+ my $ skip7label := label($ prefix ~ ' _skip7' );
645
+ my $ skip8label := label($ prefix ~ ' _skip8' );
646
+ my $ needrep := fresh_i();
647
+ my $ needmark := fresh_i();
648
+ my $ rep := % * REG <rep >;
649
+ my $ pos := % * REG <pos >;
650
+ my $ ireg := fresh_i();
651
+
652
+ my $ minmax := $ node [1 ];
653
+ my $ minmax_reg := fresh_o();
654
+ my $ min_reg := fresh_i();
655
+ my $ max_reg := fresh_i();
656
+ my $ zero := fresh_i();
657
+ my $ one := fresh_i();
658
+
659
+ my $ minmax_mast := $ * QASTCOMPILER . as_mast($ minmax , : want($ MVM_reg_obj ));
660
+ my $ res_reg := $ minmax_mast . result_reg;
661
+ merge_ins(@ ins , $ minmax_mast . instructions);
662
+ merge_ins(@ ins , [
663
+ op(' const_i64' , $ zero , ival(0 )),
664
+ op(' const_i64' , $ one , ival(1 )),
665
+ op(' atpos_i' , $ min_reg , $ res_reg , $ zero ),
666
+ op(' atpos_i' , $ max_reg , $ res_reg , $ one ),
667
+ ]);
668
+
669
+ # return if $min == 0 && $max == 0;
670
+ merge_ins(@ ins , [
671
+ op(' if_i' , $ min_reg , $ skip8label ),
672
+ op(' unless_i' , $ max_reg , $ skip7label ),
673
+ $ skip8label
674
+ ]);
675
+
676
+ # $needrep := $min > 1 || $max > 1;
677
+ merge_ins(@ ins , [
678
+ op(' gt_i' , $ needrep , $ min_reg , $ one ),
679
+ op(' if_i' , $ needrep , $ skip0label ),
680
+ op(' gt_i' , $ needrep , $ max_reg , $ one ),
681
+ $ skip0label
682
+ ]);
683
+
684
+ # $needmark := $needrep || $backtrack eq 'r';
685
+ if $ backtrack eq ' r' {
686
+ nqp :: push (@ ins , op(' set' , $ needmark , $ one ));
687
+ }
688
+ else {
689
+ nqp :: push (@ ins , op(' set' , $ needmark , $ needrep ));
690
+ }
691
+
692
+ if $ backtrack eq ' f' {
693
+ my $ seplabel := label($ prefix ~ ' _sep' );
694
+ nqp :: push (@ ins , op(' set' , $ rep , % * REG <zero >));
695
+
696
+ nqp :: push (@ ins , op(' ge_i' , $ ireg , $ min_reg , $ one )); # if $min < 1 {
697
+ nqp :: push (@ ins , op(' if_i' , $ ireg , $ skip1label ));
698
+ self . regex_mark(@ ins , $ looplabel_index , $ pos , $ rep );
699
+ nqp :: push (@ ins , op(' goto' , $ donelabel ));
700
+ nqp :: push (@ ins , $ skip1label ); # }
701
+
702
+ nqp :: push (@ ins , op(' goto' , $ seplabel )) if $ sep ;
703
+ nqp :: push (@ ins , $ looplabel );
704
+ nqp :: push (@ ins , op(' set' , $ ireg , $ rep ));
705
+ if $ sep {
706
+ merge_ins(@ ins , self . regex_mast($ sep ));
707
+ nqp :: push (@ ins , $ seplabel );
708
+ }
709
+ merge_ins(@ ins , self . regex_mast($ node [0 ]));
710
+ merge_ins(@ ins , [
711
+ op(' set' , $ rep , $ ireg ),
712
+ op(' inc_i' , $ rep ),
713
+
714
+ op(' le_i' , $ ireg , $ min_reg , $ one ), # if $min > 1 {
715
+ op(' if_i' , $ ireg , $ skip2label ),
716
+ op(' lt_i' , $ ireg , $ rep , $ min_reg ),
717
+ op(' if_i' , $ ireg , $ looplabel ),
718
+ $ skip2label , # }
719
+
720
+ op(' le_i' , $ ireg , $ max_reg , $ one ), # if $max > 1 {
721
+ op(' if_i' , $ ireg , $ skip3label ),
722
+ op(' ge_i' , $ ireg , $ rep , $ max_reg ),
723
+ op(' if_i' , $ ireg , $ donelabel ),
724
+ $ skip3label , # }
725
+
726
+ op(' eq_i' , $ ireg , $ max_reg , $ one ), # unless $max == 1 {
727
+ op(' if_i' , $ ireg , $ skip4label ),
728
+ ]);
729
+ self . regex_mark(@ ins , $ looplabel_index , $ pos , $ rep );
730
+ nqp :: push (@ ins , $ skip4label ); # }
731
+
732
+ nqp :: push (@ ins , $ donelabel );
733
+ }
734
+ else {
735
+ nqp :: push (@ ins , op(' if_i' , $ min_reg , $ skip1label )); # if $min == 0 {
736
+ self . regex_mark(@ ins , $ donelabel_index , $ pos , % * REG <zero >);
737
+ nqp :: push (@ ins , $ skip1label ); # }
738
+
739
+ nqp :: push (@ ins , op(' unless_i' , $ min_reg , $ skip2label )); # elsif $needmark {
740
+ nqp :: push (@ ins , op(' unless_i' , $ needmark , $ skip2label ));
741
+ self . regex_mark(@ ins , $ donelabel_index , % * REG <negone >, % * REG <zero >);
742
+ nqp :: push (@ ins , $ skip2label ); # }
743
+
744
+ nqp :: push (@ ins , $ looplabel );
745
+ merge_ins(@ ins , self . regex_mast($ node [0 ]));
746
+
747
+ nqp :: push (@ ins , op(' unless_i' , $ needmark , $ skip3label )); # if $needmark {
748
+ self . regex_peek(@ ins , $ donelabel_index , MAST::Local. new (: index(-1 )), $ rep );
749
+ self . regex_commit(@ ins , $ donelabel_index ) if $ backtrack eq ' r' ;
750
+ merge_ins(@ ins , [
751
+ op(' inc_i' , $ rep ),
752
+
753
+ op(' le_i' , $ ireg , $ max_reg , $ one ), # if $max > 1 {
754
+ op(' if_i' , $ ireg , $ skip4label ),
755
+ op(' ge_i' , $ ireg , $ rep , $ max_reg ),
756
+ op(' if_i' , $ ireg , $ donelabel ),
757
+ $ skip4label , # }
758
+ $ skip3label , # }
759
+
760
+ op(' eq_i' , $ ireg , $ max_reg , $ one ), # unless $max == 1 {
761
+ op(' if_i' , $ ireg , $ skip5label ),
762
+ ]);
763
+ self . regex_mark(@ ins , $ donelabel_index , $ pos , $ rep );
764
+ merge_ins(@ ins , self . regex_mast($ sep )) if $ sep ;
765
+ merge_ins(@ ins , [
766
+ op(' goto' , $ looplabel ),
767
+ $ skip5label , # }
768
+ $ donelabel ,
769
+
770
+ op(' le_i' , $ ireg , $ min_reg , $ one ), # if $min > 1 {
771
+ op(' if_i' , $ ireg , $ skip6label ),
772
+ op(' lt_i' , $ ireg , $ rep , $ min_reg ),
773
+ op(' if_i' , $ ireg , % * REG <fail >),
774
+ $ skip6label , # }
775
+ ]);
776
+ }
777
+ nqp :: push (@ ins , $ skip7label );
778
+ @ ins
779
+ }
780
+
627
781
method quant ($ node ) {
628
782
my @ ins := nqp ::list();
629
783
my $ min := $ node . min ;
0 commit comments