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