001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.transformer.bytecode.statement.tag; 020 021import lucee.runtime.type.scope.Undefined; 022import lucee.runtime.util.NumberIterator; 023import lucee.transformer.bytecode.BytecodeContext; 024import lucee.transformer.bytecode.BytecodeException; 025import lucee.transformer.bytecode.Statement; 026import lucee.transformer.bytecode.cast.CastInt; 027import lucee.transformer.bytecode.expression.Expression; 028import lucee.transformer.bytecode.literal.LitString; 029import lucee.transformer.bytecode.util.Types; 030import lucee.transformer.bytecode.visitor.DecisionIntVisitor; 031import lucee.transformer.bytecode.visitor.NotVisitor; 032import lucee.transformer.bytecode.visitor.OnFinally; 033import lucee.transformer.bytecode.visitor.ParseBodyVisitor; 034import lucee.transformer.bytecode.visitor.TryFinallyVisitor; 035import lucee.transformer.bytecode.visitor.WhileVisitor; 036 037import org.objectweb.asm.Label; 038import org.objectweb.asm.Opcodes; 039import org.objectweb.asm.Type; 040import org.objectweb.asm.commons.GeneratorAdapter; 041import org.objectweb.asm.commons.Method; 042 043public class TagGroupUtil { 044 045 046 // Undefined us() 047 public static final Type UNDEFINED = Type.getType(Undefined.class); 048 public static final Method US = new Method( 049 "us", 050 UNDEFINED, 051 new Type[]{}); 052 053 // void addQuery(Query coll) 054 public static final Method ADD_QUERY = new Method( 055 "addQuery", 056 Types.VOID, 057 new Type[]{Types.QUERY}); 058 059 // void removeQuery() 060 public static final Method REMOVE_QUERY = new Method( 061 "removeQuery", 062 Types.VOID, 063 new Type[]{}); 064 065 066 // int getRecordcount() 067 public static final Method GET_RECORDCOUNT = new Method( 068 "getRecordcount", 069 Types.INT_VALUE, 070 new Type[]{}); 071 072 // double range(double number, double from) 073 public static final Method RANGE = new Method( 074 "range", 075 Types.INT_VALUE, 076 new Type[]{Types.INT_VALUE,Types.INT_VALUE}); 077 078 public static final Type NUMBER_ITERATOR = Type.getType(NumberIterator.class); 079 080 // NumberIterator load(double from, double to, double max) 081 public static final Method LOAD_MAX = new Method( 082 "loadMax", 083 NUMBER_ITERATOR, 084 new Type[]{Types.INT_VALUE,Types.INT_VALUE,Types.INT_VALUE}); 085 086 public static final Method LOAD_END = new Method( 087 "loadEnd", 088 NUMBER_ITERATOR, 089 new Type[]{Types.INT_VALUE,Types.INT_VALUE,Types.INT_VALUE}); 090 091 092 // NumberIterator load(double from, double to, double max) 093 public static final Method LOAD_2 = new Method( 094 "load", 095 NUMBER_ITERATOR, 096 new Type[]{Types.INT_VALUE,Types.INT_VALUE}); 097 098 099 // NumberIterator load(NumberIterator ni, Query query, String groupName, boolean caseSensitive) 100 public static final Method LOAD_5 = new Method( 101 "load", 102 NUMBER_ITERATOR, 103 new Type[]{Types.PAGE_CONTEXT, NUMBER_ITERATOR,Types.QUERY,Types.STRING,Types.BOOLEAN_VALUE}); 104 105 // boolean isValid() 106 /*public static final Method IS_VALID_0 = new Method( 107 "isValid", 108 Types.BOOLEAN_VALUE, 109 new Type[]{});*/ 110 111 public static final Method IS_VALID_1 = new Method( 112 "isValid", 113 Types.BOOLEAN_VALUE, 114 new Type[]{Types.INT_VALUE}); 115 116 // int current() 117 public static final Method CURRENT = new Method( 118 "current", 119 Types.INT_VALUE, 120 new Type[]{}); 121 122 // void release(NumberIterator ni) 123 public static final Method REALEASE = new Method( 124 "release", 125 Types.VOID, 126 new Type[]{NUMBER_ITERATOR}); 127 128 // void setCurrent(int current) 129 public static final Method SET_CURRENT = new Method( 130 "setCurrent", 131 Types.VOID, 132 new Type[]{Types.INT_VALUE}); 133 134 135 // void reset() 136 public static final Method RESET = new Method( 137 "reset", 138 Types.VOID, 139 new Type[]{Types.INT_VALUE}); 140 141 // int first() 142 public static final Method FIRST = new Method( 143 "first", 144 Types.INT_VALUE, 145 new Type[]{}); 146 public static final Method GET_ID = new Method( 147 "getId", 148 Types.INT_VALUE, 149 new Type[]{}); 150 151 152 153 154 public static void writeOutTypeQuery(final TagGroup tag, BytecodeContext bc) throws BytecodeException { 155 final GeneratorAdapter adapter = bc.getAdapter(); 156 157 tag.setNumberIterator(adapter.newLocal(NUMBER_ITERATOR)); 158 boolean isOutput=tag.getType()==TagGroup.TAG_OUTPUT; 159 ParseBodyVisitor pbv=isOutput?new ParseBodyVisitor():null; 160 if(isOutput)pbv.visitBegin(bc); 161 162 163 // Query query=pc.getQuery(@query); 164 tag.setQuery(adapter.newLocal(Types.QUERY)); 165 adapter.loadArg(0); 166 Expression val = tag.getAttribute("query").getValue(); 167 val.writeOut(bc, Expression.MODE_REF); 168 if(val instanceof LitString) 169 adapter.invokeVirtual(Types.PAGE_CONTEXT, TagLoop.GET_QUERY_STRING); 170 else 171 adapter.invokeVirtual(Types.PAGE_CONTEXT, TagLoop.GET_QUERY_OBJ); 172 173 adapter.storeLocal(tag.getQuery()); 174 175 176 tag.setPID(adapter.newLocal(Types.INT_VALUE)); 177 adapter.loadArg(0); 178 adapter.invokeVirtual(Types.PAGE_CONTEXT, TagLoop.GET_ID); 179 adapter.storeLocal(tag.getPID()); 180 181 182 183 // int startAt=query.getCurrentrow(); 184 final int startAt=adapter.newLocal(Types.INT_VALUE); 185 adapter.loadLocal(tag.getQuery()); 186 187 adapter.loadLocal(tag.getPID()); 188 //adapter.loadArg(0); 189 //adapter.invokeVirtual(Types.PAGE_CONTEXT, TagLoop.GET_ID); 190 adapter.invokeInterface(Types.QUERY, TagLoop.GET_CURRENTROW_1); 191 192 adapter.storeLocal(startAt); 193 194 195 196 // if(query.getRecordcount()>0) { 197 DecisionIntVisitor div=new DecisionIntVisitor(); 198 div.visitBegin(); 199 adapter.loadLocal(tag.getQuery()); 200 adapter.invokeInterface(Types.QUERY, GET_RECORDCOUNT); 201 div.visitGT(); 202 adapter.push(0); 203 div.visitEnd(bc); 204 Label ifRecCount=new Label(); 205 adapter.ifZCmp(Opcodes.IFEQ, ifRecCount); 206 207 // startrow 208 int from = adapter.newLocal(Types.INT_VALUE); 209 Attribute attrStartRow = tag.getAttribute("startrow"); 210 if(attrStartRow!=null){ 211 // NumberRange.range(@startrow,1) 212 //attrStartRow.getValue().writeOut(bc, Expression.MODE_VALUE); 213 CastInt.toExprInt(attrStartRow.getValue()).writeOut(bc, Expression.MODE_VALUE); 214 //adapter.visitInsn(Opcodes.D2I); 215 adapter.push(1); 216 adapter.invokeStatic(Types.NUMBER_RANGE, RANGE); 217 //adapter.visitInsn(Opcodes.D2I); 218 } 219 else { 220 adapter.push(1); 221 } 222 adapter.storeLocal(from); 223 224 // numberIterator 225 226 227 adapter.loadLocal(from); 228 adapter.loadLocal(tag.getQuery()); 229 adapter.invokeInterface(Types.QUERY, GET_RECORDCOUNT); 230 //adapter.visitInsn(Opcodes.I2D); 231 232 Attribute attrMaxRow = tag.getAttribute("maxrows"); 233 Attribute attrEndRow = tag.getAttribute("endrow"); 234 if(attrMaxRow!=null) { 235 CastInt.toExprInt(attrMaxRow.getValue()).writeOut(bc, Expression.MODE_VALUE); 236 adapter.invokeStatic(NUMBER_ITERATOR, LOAD_MAX); 237 } 238 else if(attrEndRow!=null) { 239 CastInt.toExprInt(attrEndRow.getValue()).writeOut(bc, Expression.MODE_VALUE); 240 adapter.invokeStatic(NUMBER_ITERATOR, LOAD_END); 241 } 242 else { 243 adapter.invokeStatic(NUMBER_ITERATOR, LOAD_2); 244 } 245 adapter.storeLocal(tag.getNumberIterator()); 246 247 // Group 248 Attribute attrGroup = tag.getAttribute("group"); 249 Attribute attrGroupCS = tag.getAttribute("groupcasesensitive"); 250 tag.setGroup(adapter.newLocal(Types.STRING)); 251 final int groupCaseSensitive=adapter.newLocal(Types.BOOLEAN_VALUE); 252 if(attrGroup!=null) { 253 attrGroup.getValue().writeOut(bc, Expression.MODE_REF); 254 adapter.storeLocal(tag.getGroup()); 255 256 if(attrGroupCS!=null) attrGroupCS.getValue().writeOut(bc, Expression.MODE_VALUE); 257 else adapter.push(false); 258 adapter.storeLocal(groupCaseSensitive); 259 } 260 261 // pc.us().addQuery(query); 262 adapter.loadArg(0); 263 adapter.invokeVirtual(Types.PAGE_CONTEXT, US); 264 adapter.loadLocal(tag.getQuery()); 265 adapter.invokeInterface(UNDEFINED, ADD_QUERY); 266 267 // current 268 final int current=adapter.newLocal(Types.INT_VALUE); 269 adapter.loadLocal(from); 270 adapter.push(1); 271 adapter.visitInsn(Opcodes.ISUB); 272 adapter.storeLocal(current); 273 274 275 // Try 276 TryFinallyVisitor tfv=new TryFinallyVisitor(new OnFinally() { 277 public void _writeOut(BytecodeContext bc) { 278 // query.reset(); 279 280 // query.go(startAt); 281 adapter.loadLocal(tag.getQuery()); 282 adapter.loadLocal(startAt); 283 284 adapter.loadLocal(tag.getPID()); 285 //adapter.loadArg(0); 286 //adapter.invokeVirtual(Types.PAGE_CONTEXT, TagLoop.GET_ID); 287 adapter.invokeInterface(Types.QUERY, TagLoop.GO); 288 adapter.pop(); 289 290 291 292 293 // pc.us().removeQuery(); 294 adapter.loadArg(0); 295 adapter.invokeVirtual(Types.PAGE_CONTEXT, US); 296 adapter.invokeInterface(UNDEFINED, REMOVE_QUERY); 297 298 // NumberIterator.release(ni); 299 adapter.loadLocal(tag.getNumberIterator()); 300 adapter.invokeStatic(NUMBER_ITERATOR, REALEASE); 301 } 302 },null); 303 tfv.visitTryBegin(bc); 304 WhileVisitor wv = new WhileVisitor(); 305 if(tag instanceof TagLoop) ((TagLoop)tag).setLoopVisitor(wv); 306 wv.visitBeforeExpression(bc); 307 308 //while(ni.isValid()) { 309 adapter.loadLocal(tag.getNumberIterator()); 310 adapter.loadLocal(current); 311 adapter.push(1); 312 adapter.visitInsn(Opcodes.IADD); 313 adapter.invokeVirtual(NUMBER_ITERATOR, IS_VALID_1); 314 315 wv.visitAfterExpressionBeforeBody(bc); 316 317 // if(!query.go(ni.current()))break; 318 adapter.loadLocal(tag.getQuery()); 319 adapter.loadLocal(tag.getNumberIterator()); 320 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 321 322 adapter.loadLocal(tag.getPID()); 323 adapter.invokeInterface(Types.QUERY, TagLoop.GO); 324 325 NotVisitor.visitNot(bc); 326 Label _if=new Label(); 327 adapter.ifZCmp(Opcodes.IFEQ, _if); 328 wv.visitBreak(bc); 329 adapter.visitLabel(_if); 330 331 if(attrGroup!=null) { 332 // NumberIterator oldNi=numberIterator; 333 int oldNi=adapter.newLocal(NUMBER_ITERATOR); 334 adapter.loadLocal(tag.getNumberIterator()); 335 adapter.storeLocal(oldNi); 336 337 // numberIterator=NumberIterator.load(ni,query,group,grp_case); 338 adapter.loadArg(0); 339 adapter.loadLocal(tag.getNumberIterator()); 340 adapter.loadLocal(tag.getQuery()); 341 adapter.loadLocal(tag.getGroup()); 342 adapter.loadLocal(groupCaseSensitive); 343 adapter.invokeStatic(NUMBER_ITERATOR, LOAD_5); 344 adapter.storeLocal(tag.getNumberIterator()); 345 346 // current=oldNi.current(); 347 adapter.loadLocal(oldNi); 348 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 349 adapter.storeLocal(current); 350 351 tag.getBody().writeOut(bc); 352 353 //tmp(adapter,current); 354 355 // NumberIterator.release(ni); 356 adapter.loadLocal(tag.getNumberIterator()); 357 adapter.invokeStatic(NUMBER_ITERATOR, REALEASE); 358 359 // numberIterator=oldNi; 360 adapter.loadLocal(oldNi); 361 adapter.storeLocal(tag.getNumberIterator()); 362 } 363 else { 364 // current=ni.current(); 365 adapter.loadLocal(tag.getNumberIterator()); 366 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 367 adapter.storeLocal(current); 368 369 tag.getBody().writeOut(bc); 370 } 371 372 // ni.setCurrent(current+1); 373 /*adapter.loadLocal(tag.getNumberIterator()); 374 adapter.loadLocal(current); 375 adapter.push(1); 376 adapter.visitInsn(Opcodes.IADD); 377 adapter.invokeVirtual(NUMBER_ITERATOR, SET_CURRENT);*/ 378 379 wv.visitAfterBody(bc,tag.getEnd()); 380 381 tfv.visitTryEnd(bc); 382 383 adapter.visitLabel(ifRecCount); 384 385 386 if(isOutput)pbv.visitEnd(bc); 387 } 388 389 390 391 public static void writeOutTypeGroup(TagGroup tag,BytecodeContext bc) throws BytecodeException { 392 GeneratorAdapter adapter = bc.getAdapter(); 393 boolean isOutput=tag.getType()==TagGroup.TAG_OUTPUT; 394 ParseBodyVisitor pbv=isOutput?new ParseBodyVisitor():null; 395 if(isOutput)pbv.visitBegin(bc); 396 397 // Group 398 Attribute attrGroup = tag.getAttribute("group"); 399 tag.setGroup(adapter.newLocal(Types.STRING)); 400 attrGroup.getValue().writeOut(bc, Expression.MODE_REF); 401 adapter.storeLocal(tag.getGroup()); 402 403 // Group Case Sensitve 404 Attribute attrGroupCS = tag.getAttribute("groupcasesensitive"); 405 int groupCaseSensitive=adapter.newLocal(Types.BOOLEAN_VALUE); 406 if(attrGroupCS!=null) attrGroupCS.getValue().writeOut(bc, Expression.MODE_VALUE); 407 else adapter.push(true); 408 adapter.storeLocal(groupCaseSensitive); 409 410 TagGroup parent = getParentTagGroupQuery(tag,tag.getType()); 411 tag.setNumberIterator(parent.getNumberIterator()); 412 tag.setQuery(parent.getQuery()); 413 //queryImpl = parent.getQueryImpl(); 414 415 // current 416 int current=adapter.newLocal(Types.INT_VALUE); 417 adapter.loadLocal(tag.getNumberIterator()); 418 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 419 adapter.storeLocal(current); 420 421 422 // current 423 int icurrent=adapter.newLocal(Types.INT_VALUE); 424 425 adapter.loadLocal(current); 426 adapter.push(1); 427 adapter.visitInsn(Opcodes.ISUB); 428 adapter.storeLocal(icurrent); 429 430 431 WhileVisitor wv = new WhileVisitor(); 432 if(tag instanceof TagLoop) ((TagLoop)tag).setLoopVisitor(wv); 433 wv.visitBeforeExpression(bc); 434 435 //while(ni.isValid()) { 436 adapter.loadLocal(tag.getNumberIterator()); 437 adapter.loadLocal(icurrent); 438 adapter.push(1); 439 adapter.visitInsn(Opcodes.IADD); 440 adapter.invokeVirtual(NUMBER_ITERATOR, IS_VALID_1); 441 442 wv.visitAfterExpressionBeforeBody(bc); 443 444 // if(!query.go(ni.current()))break; 445 adapter.loadLocal(tag.getQuery()); 446 adapter.loadLocal(tag.getNumberIterator()); 447 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 448 449 adapter.loadArg(0); 450 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 451 adapter.invokeInterface(Types.QUERY, TagLoop.GO); 452 453 NotVisitor.visitNot(bc); 454 Label _if=new Label(); 455 adapter.ifZCmp(Opcodes.IFEQ, _if); 456 wv.visitBreak(bc); 457 adapter.visitLabel(_if); 458 459 // NumberIterator oldNi=numberIterator; 460 int oldNi=adapter.newLocal(NUMBER_ITERATOR); 461 462 adapter.loadLocal(tag.getNumberIterator()); 463 adapter.storeLocal(oldNi); 464 465 // numberIterator=NumberIterator.load(ni,query,group,grp_case); 466 adapter.loadArg(0); 467 adapter.loadLocal(tag.getNumberIterator()); 468 adapter.loadLocal(tag.getQuery()); 469 adapter.loadLocal(tag.getGroup()); 470 adapter.loadLocal(groupCaseSensitive); 471 adapter.invokeStatic(NUMBER_ITERATOR, LOAD_5); 472 adapter.storeLocal(tag.getNumberIterator()); 473 474 // current=oldNi.current(); 475 adapter.loadLocal(oldNi); 476 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 477 adapter.storeLocal(icurrent); 478 479 tag.getBody().writeOut(bc); 480 481 //tmp(adapter,current); 482 483 484 // NumberIterator.release(ni); 485 adapter.loadLocal(tag.getNumberIterator()); 486 adapter.invokeStatic(NUMBER_ITERATOR, REALEASE); 487 488 // numberIterator=oldNi; 489 adapter.loadLocal(oldNi); 490 adapter.storeLocal(tag.getNumberIterator()); 491 492 // ni.setCurrent(current+1); 493 /*adapter.loadLocal(tag.getNumberIterator()); 494 adapter.loadLocal(icurrent); 495 adapter.push(1); 496 adapter.visitInsn(Opcodes.IADD); 497 adapter.invokeVirtual(NUMBER_ITERATOR, SET_CURRENT); 498 */ 499 wv.visitAfterBody(bc,tag.getEnd()); 500 501 502 //query.go(ni.current(),pc.getId()) 503 resetCurrentrow(adapter,tag,current); 504 505 // ni.first(); 506 adapter.loadLocal(tag.getNumberIterator()); 507 adapter.invokeVirtual(NUMBER_ITERATOR, FIRST); 508 adapter.pop(); 509 510 511 if(isOutput)pbv.visitEnd(bc); 512 } 513 514 public static void writeOutTypeInnerGroup(TagGroup tag,BytecodeContext bc) throws BytecodeException { 515 GeneratorAdapter adapter = bc.getAdapter(); 516 517 TagGroup parent = getParentTagGroupQuery(tag,tag.getType()); 518 tag.setNumberIterator(parent.getNumberIterator()); 519 tag.setQuery(parent.getQuery()); 520 //queryImpl = parent.getQueryImpl(); 521 522 int current=adapter.newLocal(Types.INT_VALUE); 523 adapter.loadLocal(tag.getNumberIterator()); 524 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 525 adapter.storeLocal(current); 526 527 528 // inner current 529 int icurrent=adapter.newLocal(Types.INT_VALUE); 530 531 adapter.loadLocal(current); 532 adapter.push(1); 533 adapter.visitInsn(Opcodes.ISUB); 534 adapter.storeLocal(icurrent); 535 536 537 538 WhileVisitor wv = new WhileVisitor(); 539 if(tag instanceof TagLoop) ((TagLoop)tag).setLoopVisitor(wv); 540 wv.visitBeforeExpression(bc); 541 542 //while(ni.isValid()) { 543 adapter.loadLocal(tag.getNumberIterator()); 544 adapter.loadLocal(icurrent); 545 adapter.push(1); 546 adapter.visitInsn(Opcodes.IADD); 547 adapter.invokeVirtual(NUMBER_ITERATOR, IS_VALID_1); 548 549 wv.visitAfterExpressionBeforeBody(bc); 550 551 // if(!query.go(ni.current()))break; 552 553 adapter.loadLocal(tag.getQuery()); 554 adapter.loadLocal(tag.getNumberIterator()); 555 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 556 557 adapter.loadArg(0); 558 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 559 adapter.invokeInterface(Types.QUERY, TagLoop.GO); 560 561 /*OLD 562 adapter.invokeInterface(Types.QUERY, TagLoop.GO_1); 563 */ 564 NotVisitor.visitNot(bc); 565 Label _if=new Label(); 566 adapter.ifZCmp(Opcodes.IFEQ, _if); 567 wv.visitBreak(bc); 568 adapter.visitLabel(_if); 569 570 // current=ni.current(); 571 adapter.loadLocal(tag.getNumberIterator()); 572 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 573 adapter.storeLocal(icurrent); 574 575 tag.getBody().writeOut(bc); 576 577 // ni.setCurrent(current+1); 578 /*adapter.loadLocal(tag.getNumberIterator()); 579 adapter.loadLocal(icurrent); 580 adapter.push(1); 581 adapter.visitInsn(Opcodes.IADD); 582 adapter.invokeVirtual(NUMBER_ITERATOR, SET_CURRENT);*/ 583 584 wv.visitAfterBody(bc,tag.getEnd()); 585 586 resetCurrentrow(adapter,tag,current); 587 588 589 // ni.first(); 590 adapter.loadLocal(tag.getNumberIterator()); 591 adapter.invokeVirtual(NUMBER_ITERATOR, FIRST); 592 adapter.pop(); 593 } 594 595 public static void writeOutTypeInnerQuery(TagGroup tag,BytecodeContext bc) throws BytecodeException { 596 GeneratorAdapter adapter = bc.getAdapter(); 597 //if(tr ue)return ; 598 TagGroup parent = getParentTagGroupQuery(tag,tag.getType()); 599 tag.setNumberIterator(parent.getNumberIterator()); 600 tag.setQuery(parent.getQuery()); 601 tag.setPID(parent.getPID()); 602 //queryImpl = parent.getQueryImpl(); 603 604 //int currentOuter=ni.current(); 605 int current=adapter.newLocal(Types.INT_VALUE); 606 adapter.loadLocal(tag.getNumberIterator()); 607 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 608 adapter.storeLocal(current); 609 610 // current 611 int icurrent=adapter.newLocal(Types.INT_VALUE); 612 613 adapter.loadLocal(current); 614 adapter.push(1); 615 adapter.visitInsn(Opcodes.ISUB); 616 adapter.storeLocal(icurrent); 617 618 619 WhileVisitor wv = new WhileVisitor(); 620 if(tag instanceof TagLoop) ((TagLoop)tag).setLoopVisitor(wv); 621 wv.visitBeforeExpression(bc); 622 623 //while(ni.isValid()) { 624 adapter.loadLocal(tag.getNumberIterator()); 625 adapter.loadLocal(icurrent); 626 adapter.push(1); 627 adapter.visitInsn(Opcodes.IADD); 628 adapter.invokeVirtual(NUMBER_ITERATOR, IS_VALID_1); 629 630 wv.visitAfterExpressionBeforeBody(bc); 631 632 // if(!query.go(ni.current()))break; 633 adapter.loadLocal(tag.getQuery()); 634 adapter.loadLocal(tag.getNumberIterator()); 635 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 636 637 adapter.loadLocal(tag.getPID()); 638 adapter.invokeInterface(Types.QUERY, TagLoop.GO); 639 640 NotVisitor.visitNot(bc); 641 Label _if=new Label(); 642 adapter.ifZCmp(Opcodes.IFEQ, _if); 643 wv.visitBreak(bc); 644 adapter.visitLabel(_if); 645 646 // current=ni.current(); 647 adapter.loadLocal(tag.getNumberIterator()); 648 adapter.invokeVirtual(NUMBER_ITERATOR, CURRENT); 649 adapter.storeLocal(icurrent); 650 651 tag.getBody().writeOut(bc); 652 653 // ni.setCurrent(current+1); 654 /*adapter.loadLocal(tag.getNumberIterator()); 655 adapter.loadLocal(icurrent); 656 adapter.push(1); 657 adapter.visitInsn(Opcodes.IADD); 658 adapter.invokeVirtual(NUMBER_ITERATOR, SET_CURRENT);*/ 659 660 wv.visitAfterBody(bc,tag.getEnd()); 661 662 663 // ni.setCurrent(currentOuter); 664 adapter.loadLocal(tag.getNumberIterator()); 665 adapter.loadLocal(current); 666 adapter.invokeVirtual(NUMBER_ITERATOR, SET_CURRENT); 667 668 adapter.loadLocal(tag.getQuery()); 669 adapter.loadLocal(current); 670 671 adapter.loadLocal(tag.getPID()); 672 //adapter.loadArg(0); 673 //adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 674 adapter.invokeInterface(Types.QUERY, TagLoop.GO); 675 adapter.pop(); 676 //adapter.pop(); 677 } 678 679 public static TagGroup getParentTagGroupQuery(Statement st, short type) throws BytecodeException { 680 Statement parent=st.getParent(); 681 if(parent==null) throw new BytecodeException("there is no parent output with query",null); 682 else if(parent instanceof TagGroup && type==((TagGroup)parent).getType()) { 683 if(((TagGroup)parent).hasQuery()) 684 return ((TagGroup)parent); 685 } 686 return getParentTagGroupQuery(parent,type); 687 } 688 689 private static void resetCurrentrow(GeneratorAdapter adapter,TagGroup tg, int current) { 690 //query.go(ni.current(),pc.getId()) 691 adapter.loadLocal(tg.getQuery()); 692 adapter.loadLocal(current); 693 adapter.loadArg(0); 694 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 695 adapter.invokeInterface(Types.QUERY, TagLoop.GO); 696 697 /* OLD 698 adapter.invokeInterface(Types.QUERY, TagLoop.GO_1); 699 */ 700 adapter.pop(); 701 702 } 703 704}