@@ -5279,6 +5279,229 @@ class QAST::CompilerJAST {
5279
5279
$ il ;
5280
5280
}
5281
5281
5282
+ method dynquant ($ node ) {
5283
+ my $ il := JAST::InstructionList. new ();
5284
+
5285
+ my $ backtrack := $ node . backtrack || ' g' ;
5286
+ my $ sep := $ node [2 ];
5287
+ my $ prefix := self . unique (' rxdynquant' ~ $ backtrack );
5288
+ my $ looplabel := JAST::Label. new ( : name($ prefix ~ ' _loop' ) );
5289
+ my $ donelabel := JAST::Label. new ( : name($ prefix ~ ' _done' ) );
5290
+ my $ skip0label := JAST::Label. new ( : name($ prefix ~ ' _skip0' ));
5291
+ my $ skip1label := JAST::Label. new ( : name($ prefix ~ ' _skip1' ));
5292
+ my $ skip2label := JAST::Label. new ( : name($ prefix ~ ' _skip2' ));
5293
+ my $ skip3label := JAST::Label. new ( : name($ prefix ~ ' _skip3' ));
5294
+ my $ skip4label := JAST::Label. new ( : name($ prefix ~ ' _skip4' ));
5295
+ my $ skip5label := JAST::Label. new ( : name($ prefix ~ ' _skip5' ));
5296
+ my $ skip6label := JAST::Label. new ( : name($ prefix ~ ' _skip6' ));
5297
+ my $ skip7label := JAST::Label. new ( : name($ prefix ~ ' _skip7' ));
5298
+ my $ skip8label := JAST::Label. new ( : name($ prefix ~ ' _skip8' ));
5299
+ my $ skip9label := JAST::Label. new ( : name($ prefix ~ ' _skip9' ));
5300
+ my $ needrep := $ * TA . fresh_i();
5301
+ my $ needmark := $ * TA . fresh_i();
5302
+
5303
+ my $ minmax := $ node [1 ];
5304
+ my $ min_reg := $ * TA . fresh_i();
5305
+ my $ max_reg := $ * TA . fresh_i();
5306
+
5307
+ my $ res_reg := self . as_jast($ minmax , : want($ RT_OBJ ));
5308
+ $ il . append ($ res_reg . jast);
5309
+ $ * STACK . obtain($ il , $ res_reg );
5310
+ $ il . append ($ DUP );
5311
+ $ il . append ($ IVAL_ZERO );
5312
+ $ il . append ($ ALOAD_1 );
5313
+ $ il . append (JAST::Instruction. new ( : op(' invokestatic' ), $ TYPE_OPS ,
5314
+ " atpos_i" , ' Long' , $ TYPE_SMO , ' Long' , $ TYPE_TC ));
5315
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), $ min_reg ));
5316
+ $ il . append ($ IVAL_ONE );
5317
+ $ il . append ($ ALOAD_1 );
5318
+ $ il . append (JAST::Instruction. new ( : op(' invokestatic' ), $ TYPE_OPS ,
5319
+ " atpos_i" , ' Long' , $ TYPE_SMO , ' Long' , $ TYPE_TC ));
5320
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), $ max_reg ));
5321
+
5322
+ # return if $min == 0 && $max == 0;
5323
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ min_reg ));
5324
+ $ il . append ($ IVAL_ZERO );
5325
+ $ il . append ($ LCMP );
5326
+ $ il . append (JAST::Instruction. new ( : op(' ifne' ), $ skip0label ));
5327
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ max_reg ));
5328
+ $ il . append ($ IVAL_ZERO );
5329
+ $ il . append ($ LCMP );
5330
+ $ il . append (JAST::Instruction. new ( : op(' ifeq' ), $ skip1label ));
5331
+ $ il . append ($ skip0label );
5332
+
5333
+ # $needrep := $min > 1 || $max > 1;
5334
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ min_reg ));
5335
+ $ il . append ($ IVAL_ONE );
5336
+ $ il . append ($ LCMP );
5337
+ $ il . append (JAST::Instruction. new ( : op(' iflt' ), $ skip2label ));
5338
+ $ il . append ($ IVAL_ONE );
5339
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), $ needrep ));
5340
+ $ il . append ($ skip2label );
5341
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ max_reg ));
5342
+ $ il . append ($ IVAL_ONE );
5343
+ $ il . append ($ LCMP );
5344
+ $ il . append (JAST::Instruction. new ( : op(' iflt' ), $ skip3label ));
5345
+ $ il . append ($ IVAL_ONE );
5346
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), $ needrep ));
5347
+ $ il . append ($ skip3label );
5348
+
5349
+ # $needmark := $needrep || $backtrack eq 'r';
5350
+ if $ backtrack eq ' r' {
5351
+ $ il . append ($ IVAL_ONE );
5352
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), $ needmark ));
5353
+ }
5354
+ else {
5355
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ needrep ));
5356
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), $ needmark ));
5357
+ }
5358
+
5359
+ if $ backtrack eq ' f' {
5360
+ my $ seplabel := JAST::Label. new ( : name($ prefix ~ ' _sep' ));
5361
+ my $ mark := & * REGISTER_MARK ($ looplabel );
5362
+ $ il . append ($ IVAL_ZERO );
5363
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), % * REG <rep > ));
5364
+
5365
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ min_reg )); # if $min < 1 {
5366
+ $ il . append ($ IVAL_ONE );
5367
+ $ il . append ($ LCMP );
5368
+ $ il . append (JAST::Instruction. new ( : op(' ifge' ), $ skip4label ));
5369
+ self . regex_mark($ il , $ mark ,
5370
+ JAST::Instruction. new ( : op(' lload' ), % * REG <pos > ),
5371
+ JAST::Instruction. new ( : op(' lload' ), % * REG <rep > ));
5372
+ $ il . append (JAST::Instruction. new ( : op(' goto' ), $ donelabel ));
5373
+ $ il . append ($ skip4label ); # }
5374
+
5375
+ $ il . append (JAST::Instruction. new ( : op(' goto' ), $ seplabel )) if $ sep ;
5376
+ $ il . append ($ looplabel );
5377
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), % * REG <rep > ));
5378
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), % * REG <itemp > ));
5379
+ if $ sep {
5380
+ $ il . append (self . regex_jast($ sep ));
5381
+ $ il . append ($ seplabel );
5382
+ }
5383
+ $ il . append (self . regex_jast($ node [0 ]));
5384
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), % * REG <itemp > ));
5385
+ $ il . append ($ IVAL_ONE );
5386
+ $ il . append ($ LADD );
5387
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), % * REG <rep > ));
5388
+
5389
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ min_reg )); # if $min > 1 {
5390
+ $ il . append ($ IVAL_ONE );
5391
+ $ il . append ($ LCMP );
5392
+ $ il . append (JAST::Instruction. new ( : op(' ifle' ), $ skip5label ));
5393
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), % * REG <rep > ));
5394
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ min_reg ));
5395
+ $ il . append ($ LCMP );
5396
+ $ il . append (JAST::Instruction. new ( : op(' iflt' ), $ looplabel ));
5397
+ $ il . append ($ skip5label ); # }
5398
+
5399
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ max_reg )); # if $max > 1 {
5400
+ $ il . append ($ IVAL_ONE );
5401
+ $ il . append ($ LCMP );
5402
+ $ il . append (JAST::Instruction. new ( : op(' ifle' ), $ skip6label ));
5403
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), % * REG <rep > ));
5404
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ max_reg ));
5405
+ $ il . append ($ LCMP );
5406
+ $ il . append (JAST::Instruction. new ( : op(' ifge' ), $ donelabel ));
5407
+ $ il . append ($ skip6label ); # }
5408
+
5409
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ max_reg )); # if $max != 1 {
5410
+ $ il . append ($ IVAL_ONE );
5411
+ $ il . append ($ LCMP );
5412
+ $ il . append (JAST::Instruction. new ( : op(' ifeq' ), $ skip7label ));
5413
+ self . regex_mark($ il , $ mark ,
5414
+ JAST::Instruction. new ( : op(' lload' ), % * REG <pos > ),
5415
+ JAST::Instruction. new ( : op(' lload' ), % * REG <rep > ));
5416
+ $ il . append ($ skip7label ); # }
5417
+
5418
+ $ il . append ($ donelabel );
5419
+ }
5420
+ else {
5421
+ my $ mark := & * REGISTER_MARK ($ donelabel );
5422
+
5423
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ min_reg )); # if $min == 0 {
5424
+ $ il . append ($ IVAL_ZERO );
5425
+ $ il . append ($ LCMP );
5426
+ $ il . append (JAST::Instruction. new ( : op(' ifne' ), $ skip4label ));
5427
+ self . regex_mark($ il , $ mark ,
5428
+ JAST::Instruction. new ( : op(' lload' ), % * REG <pos > ),
5429
+ $ IVAL_ZERO );
5430
+ $ il . append ($ skip4label ); # }
5431
+
5432
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ min_reg )); # elsif $needmark {
5433
+ $ il . append ($ IVAL_ZERO );
5434
+ $ il . append ($ LCMP );
5435
+ $ il . append (JAST::Instruction. new ( : op(' ifeq' ), $ skip5label ));
5436
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ needmark ));
5437
+ $ il . append ($ IVAL_ZERO );
5438
+ $ il . append ($ LCMP );
5439
+ $ il . append (JAST::Instruction. new ( : op(' ifeq' ), $ skip5label ));
5440
+ self . regex_mark($ il , $ mark , $ IVAL_MINUSONE , $ IVAL_ZERO );
5441
+ $ il . append ($ skip5label ); # }
5442
+
5443
+ $ il . append ($ looplabel );
5444
+ $ il . append (self . regex_jast($ node [0 ]));
5445
+
5446
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ needmark )); # if $needmark {
5447
+ $ il . append ($ IVAL_ZERO );
5448
+ $ il . append ($ LCMP );
5449
+ $ il . append (JAST::Instruction. new ( : op(' ifeq' ), $ skip6label ));
5450
+ $ il . append (JAST::Instruction. new ( : op(' aload' ), % * REG <bstack > ));
5451
+ $ il . append ($ DUP );
5452
+ $ il . append (JAST::PushIVal. new ( : value($ mark ) ));
5453
+ $ il . append ($ ALOAD_1 );
5454
+ $ il . append (JAST::Instruction. new ( : op(' invokestatic' ), $ TYPE_OPS ,
5455
+ " rxpeek" , ' Long' , $ TYPE_SMO , ' Long' , $ TYPE_TC ));
5456
+ $ il . append (JAST::PushIVal. new ( : value(2 ) ));
5457
+ $ il . append ($ LADD );
5458
+ $ il . append ($ ALOAD_1 );
5459
+ $ il . append (JAST::Instruction. new ( : op(' invokestatic' ), $ TYPE_OPS ,
5460
+ " atpos_i" , ' Long' , $ TYPE_SMO , ' Long' , $ TYPE_TC ));
5461
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), % * REG <rep > ));
5462
+ self . regex_commit($ il , $ mark ) if $ backtrack eq ' r' ;
5463
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), % * REG <rep > ));
5464
+ $ il . append ($ IVAL_ONE );
5465
+ $ il . append ($ LADD );
5466
+ $ il . append (JAST::Instruction. new ( : op(' lstore' ), % * REG <rep > ));
5467
+
5468
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ max_reg )); # if $max > 1
5469
+ $ il . append ($ IVAL_ONE );
5470
+ $ il . append ($ LCMP );
5471
+ $ il . append (JAST::Instruction. new ( : op(' ifle' ), $ skip7label ));
5472
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), % * REG <rep > ));
5473
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ max_reg ));
5474
+ $ il . append ($ LCMP );
5475
+ $ il . append (JAST::Instruction. new ( : op(' ifge' ), $ donelabel ));
5476
+ $ il . append ($ skip7label ); # }
5477
+ $ il . append ($ skip6label ); # }
5478
+
5479
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ max_reg )); # unless $max == 1 {
5480
+ $ il . append ($ IVAL_ONE );
5481
+ $ il . append ($ LCMP );
5482
+ $ il . append (JAST::Instruction. new ( : op(' ifeq' ), $ skip8label ));
5483
+ self . regex_mark($ il , $ mark ,
5484
+ JAST::Instruction. new ( : op(' lload' ), % * REG <pos > ),
5485
+ JAST::Instruction. new ( : op(' lload' ), % * REG <rep > ));
5486
+ $ il . append (self . regex_jast($ sep )) if $ sep ;
5487
+ $ il . append (JAST::Instruction. new ( : op(' goto' ), $ looplabel ));
5488
+ $ il . append ($ skip8label ); # }
5489
+ $ il . append ($ donelabel );
5490
+
5491
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ min_reg )); # if $min > 1 {
5492
+ $ il . append ($ IVAL_ONE );
5493
+ $ il . append ($ LCMP );
5494
+ $ il . append (JAST::Instruction. new ( : op(' iflt' ), $ skip9label ));
5495
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), % * REG <rep > ));
5496
+ $ il . append (JAST::Instruction. new ( : op(' lload' ), $ min_reg ));
5497
+ $ il . append ($ LCMP );
5498
+ $ il . append (JAST::Instruction. new ( : op(' iflt' ), % * REG <fail > ));
5499
+ $ il . append ($ skip9label ); # }
5500
+ }
5501
+ $ il . append ($ skip1label );
5502
+ $ il
5503
+ }
5504
+
5282
5505
method quant ($ node ) {
5283
5506
my $ il := JAST::InstructionList. new ();
5284
5507
my $ backtrack := $ node . backtrack || ' g' ;
0 commit comments