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.commons.io.IOUtil;
010    import railo.commons.io.res.util.ResourceUtil;
011    import railo.runtime.exp.TemplateException;
012    import railo.runtime.type.scope.Undefined;
013    import railo.transformer.bytecode.BytecodeContext;
014    import railo.transformer.bytecode.BytecodeException;
015    import railo.transformer.bytecode.cast.CastBoolean;
016    import railo.transformer.bytecode.expression.Expression;
017    import railo.transformer.bytecode.statement.FlowControl;
018    import railo.transformer.bytecode.util.ASMConstants;
019    import railo.transformer.bytecode.util.ExpressionUtil;
020    import railo.transformer.bytecode.util.Types;
021    import railo.transformer.bytecode.visitor.AndVisitor;
022    import railo.transformer.bytecode.visitor.DecisionDoubleVisitor;
023    import railo.transformer.bytecode.visitor.DecisionIntVisitor;
024    import railo.transformer.bytecode.visitor.DecisionObjectVisitor;
025    import railo.transformer.bytecode.visitor.ForConditionIntVisitor;
026    import railo.transformer.bytecode.visitor.ForDoubleVisitor;
027    import railo.transformer.bytecode.visitor.ForVisitor;
028    import railo.transformer.bytecode.visitor.LoopVisitor;
029    import railo.transformer.bytecode.visitor.TryFinallyVisitor;
030    import railo.transformer.bytecode.visitor.WhileVisitor;
031    
032    public final class TagLoop extends TagBase implements FlowControl {
033    
034    
035            public static final int TYPE_FILE = 0;
036            public static final int TYPE_LIST = 1;
037            public static final int TYPE_INDEX = 2;
038            public static final int TYPE_CONDITION = 3;
039            public static final int TYPE_QUERY = 4;
040            public static final int TYPE_COLLECTION = 5;
041            public static final int TYPE_ARRAY = 6;
042            
043    
044            
045    
046            // VariableReference getVariableReference(PageContext pc,String var)
047            private static final Method GET_VARIABLE_REFERENCE = new Method(
048                            "getVariableReference",
049                            Types.VARIABLE_REFERENCE,
050                            new Type[]{Types.PAGE_CONTEXT,Types.STRING});
051    
052    
053            // Object set(PageContext pc, Object value)
054            private static final Method SET = new Method(
055                            "set",
056                            Types.OBJECT,
057                            new Type[]{Types.PAGE_CONTEXT,Types.OBJECT});
058            // Object set(double value)
059            private static final Method SET_DOUBLE = new Method(
060                            "set",
061                            Types.VOID,
062                            new Type[]{Types.DOUBLE_VALUE});
063    
064            // Iterator toIterator(Object o)
065            private static final Method TO_ITERATOR = new Method(
066                            "toIterator",
067                            Types.ITERATOR,
068                            new Type[]{Types.OBJECT});
069    
070            private static final Method KEYS = new Method(
071                            "keyIterator",
072                            Types.COLLECTION_KEY_ARRAY,
073                            new Type[]{});
074    
075            private static final Method GET = new Method(
076                            "get",
077                            Types.OBJECT,
078                            new Type[]{Types.INT_VALUE,Types.OBJECT});
079    
080            private static final Method NEXT = new Method(
081                            "next",
082                            Types.OBJECT,
083                            new Type[]{});
084    
085            private static final Method HAS_NEXT = new Method(
086                            "hasNext",
087                            Types.BOOLEAN_VALUE,
088                            new Type[]{});
089    
090            // File toFileExisting(PageContext pc ,String destination)
091            private static final Type RESOURCE_UTIL = Type.getType(ResourceUtil.class);
092            private static final Method TO_RESOURCE_EXISTING = new Method(
093                            "toResourceExisting",
094                            Types.RESOURCE,
095                            new Type[]{Types.PAGE_CONTEXT,Types.STRING});
096    
097            // Config getConfig()
098            private static final Method GET_CONFIG = new Method(
099                            "getConfig",
100                            Types.CONFIG_WEB,
101                            new Type[]{});
102    
103            // SecurityManager getSecurityManager()
104            private static final Method GET_SECURITY_MANAGER = new Method(
105                            "getSecurityManager",
106                            Types.SECURITY_MANAGER,
107                            new Type[]{});
108    
109            // void checkFileLocation(File file)
110            private static final Method CHECK_FILE_LOCATION = new Method(
111                            "checkFileLocation",
112                            Types.VOID,
113                            new Type[]{Types.RESOURCE});
114    
115            // Reader getReader(File file, String charset)
116            private static final Type IO_UTIL = Type.getType(IOUtil.class);
117            private static final Method GET_BUFFERED_READER = new Method(
118                            "getBufferedReader",
119                            Types.BUFFERED_READER,
120                            new Type[]{Types.RESOURCE,Types.STRING});
121    
122            // void closeEL(Reader r)
123            private static final Method CLOSE_EL = new Method(
124                            "closeEL",
125                            Types.VOID,
126                            new Type[]{Types.READER});
127    
128            // String readLine()
129            private static final Method READ_LINE = new Method(
130                            "readLine",
131                            Types.STRING,
132                            new Type[]{});
133            
134    
135            // Array listToArrayRemoveEmpty(String list, String delimeter)
136            private static final Method LIST_TO_ARRAY_REMOVE_EMPTY_SS = new Method(
137                            "listToArrayRemoveEmpty",
138                            Types.ARRAY,
139                            new Type[]{Types.STRING,Types.STRING});
140            
141            // Array listToArrayRemoveEmpty(String list, char delimeter)
142            private static final Method LIST_TO_ARRAY_REMOVE_EMPTY_SC = new Method(
143                            "listToArrayRemoveEmpty",
144                            Types.ARRAY,
145                            new Type[]{Types.STRING,Types.CHAR});
146    
147            private static final Method SIZE =  new Method(
148                            "size",
149                            Types.INT_VALUE,
150                            new Type[]{});
151    
152    
153            // Object get(int key) klo
154            private static final Method GETE = new Method(
155                            "getE",
156                            Types.OBJECT,
157                            new Type[]{Types.INT_VALUE});
158    
159    
160    
161    
162            // Query getQuery(String key)
163            private static final Method GET_QUERY = new Method(
164                            "getQuery",
165                            Types.QUERY,
166                            new Type[]{Types.STRING});
167    
168            // int getCurrentrow()
169            static final Method GET_CURRENTROW_0 = new Method(
170                            "getCurrentrow",
171                            Types.INT_VALUE,
172                            new Type[]{});
173            
174            // int getCurrentrow()
175            static final Method GET_CURRENTROW_1 = new Method(
176                            "getCurrentrow",
177                            Types.INT_VALUE,
178                            new Type[]{Types.INT_VALUE});
179    
180            // double range(double number, double from)
181            private static final Method RANGE = new Method(
182                            "range",
183                            Types.DOUBLE_VALUE,
184                            new Type[]{Types.DOUBLE_VALUE,Types.DOUBLE_VALUE});
185    
186            
187            // Undefined us()
188            private static final Type UNDEFINED = Type.getType(Undefined.class);
189            private static final Method US = new Method(
190                            "us",
191                            UNDEFINED,
192                            new Type[]{});
193    
194            // void addCollection(Query coll)
195            private static final Method ADD_QUERY = new Method(
196                            "addQuery",
197                            Types.VOID,
198                            new Type[]{Types.QUERY});
199    
200            // void removeCollection()
201            private static final Method REMOVE_QUERY = new Method(
202                            "removeQuery",
203                            Types.VOID,
204                            new Type[]{});
205    
206            // boolean go(int index)
207            static final Method GO_1 = new Method(
208                            "go",
209                            Types.BOOLEAN_VALUE,
210                            new Type[]{Types.INT_VALUE});
211            static final Method GO_2 = new Method(
212                            "go",
213                            Types.BOOLEAN_VALUE,
214                            new Type[]{Types.INT_VALUE,Types.INT_VALUE});
215    
216            static final Method GET_ID = new Method(
217                            "getId",
218                            Types.INT_VALUE,
219                            new Type[]{});
220            private static final Method READ = new Method(
221                            "read",
222                            Types.STRING,
223                            new Type[]{Types.READER,Types.INT_VALUE});
224            
225            
226            
227            
228            
229            private int type;
230            private LoopVisitor loopVisitor;
231    
232            public TagLoop(int line) {
233                    super(line);
234            }
235            public TagLoop(int sl,int el) {
236                    super(sl,el);
237            }
238    
239            public void setType(int type) {
240                    this.type=type;
241            }
242            
243    
244            /**
245             *
246             * @see railo.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter)
247             */
248            public void _writeOut(BytecodeContext bc) throws BytecodeException {
249                    switch(type) {
250                    case TYPE_COLLECTION:
251                            writeOutTypeCollection(bc);
252                    break;
253                    case TYPE_CONDITION:
254                            writeOutTypeCondition(bc);
255                    break;
256                    case TYPE_FILE:
257                            writeOutTypeFile(bc);
258                    break;
259                    case TYPE_INDEX:
260                            writeOutTypeIndex(bc);
261                    break;
262                    case TYPE_LIST:
263                            writeOutTypeListArray(bc,false);
264                    break;
265                    case TYPE_ARRAY:
266                            writeOutTypeListArray(bc,true);
267                    break;
268                    case TYPE_QUERY:
269                            writeOutTypeQuery(bc);
270                    break;
271                    default:
272                            throw new BytecodeException("invalid type",getLine());
273                    }
274            }
275    
276            /**
277             * write out collection loop
278             * @param adapter
279             * @throws TemplateException
280             */
281            private void writeOutTypeCollection(BytecodeContext bc) throws BytecodeException {
282                    WhileVisitor whileVisitor = new WhileVisitor();
283                    loopVisitor=whileVisitor;
284                    GeneratorAdapter adapter = bc.getAdapter();
285                    // java.util.Iterator it=Caster.toIterator(@collection');
286                    int it=adapter.newLocal(Types.ITERATOR);
287                    getAttribute("collection").getValue().writeOut(bc,Expression.MODE_REF);
288                    adapter.invokeStatic(Types.CASTER,TO_ITERATOR);
289                    adapter.storeLocal(it);
290                    
291                    //VariableReference item=VariableInterpreter.getVariableReference(pc,item);
292                    int item = adapter.newLocal(Types.VARIABLE_REFERENCE);
293                    adapter.loadArg(0);
294                    
295                    getAttribute("item").getValue().writeOut(bc, Expression.MODE_REF);
296    //              if(Variable.register Key(bc, getAttribute("item").getValue()))
297                    
298                    //      adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE_KEY);
299                    //else
300                            adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
301                    adapter.storeLocal(item);
302                    
303                    // while(it.hasNext()) {
304                    whileVisitor.visitBeforeExpression(bc);
305                            adapter.loadLocal(it);
306                            adapter.invokeInterface(Types.ITERATOR, HAS_NEXT);
307                    
308                    whileVisitor.visitAfterExpressionBeforeBody(bc);
309                            // item.set(pc,it.next());
310                            adapter.loadLocal(item);
311                            adapter.loadArg(0);
312                                    adapter.loadLocal(it);
313                            adapter.invokeInterface(Types.ITERATOR, NEXT);
314                            adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
315                            adapter.pop();
316                    
317                            getBody().writeOut(bc);
318                    whileVisitor.visitAfterBody(bc,getEndLine());
319                    
320            }
321    
322            /**
323             * write out condition loop
324             * @param adapter
325             * @throws TemplateException
326             */
327            private void writeOutTypeCondition(BytecodeContext bc) throws BytecodeException {
328                    WhileVisitor whileVisitor = new WhileVisitor();
329                    loopVisitor=whileVisitor;
330                    whileVisitor.visitBeforeExpression(bc);
331                            CastBoolean.toExprBoolean(getAttribute("condition").getValue()).writeOut(bc, Expression.MODE_VALUE);
332                    whileVisitor.visitAfterExpressionBeforeBody(bc);
333                            getBody().writeOut(bc);
334                    whileVisitor.visitAfterBody(bc,getEndLine());
335                    
336            }
337            
338            /**
339             * write out file loop
340             * @param adapter
341             * @throws TemplateException
342             */
343            private void writeOutTypeFile(BytecodeContext bc) throws BytecodeException {
344                    WhileVisitor whileVisitor = new WhileVisitor();
345                    loopVisitor=whileVisitor;
346                    GeneratorAdapter adapter = bc.getAdapter();
347                    
348                    // charset=@charset
349                    int charset=adapter.newLocal(Types.STRING);
350                    Attribute attrCharset = getAttribute("charset");
351                    if(attrCharset==null) adapter.visitInsn(Opcodes.ACONST_NULL);
352                    else attrCharset.getValue().writeOut(bc, Expression.MODE_REF);
353                    adapter.storeLocal(charset);
354                    
355                    // startline=@startline
356                    int startline=adapter.newLocal(Types.INT_VALUE);
357                    Attribute attrStartLine = getAttribute("startline");
358                    if(attrStartLine==null) attrStartLine = getAttribute("from"); // CF8
359                    if(attrStartLine==null) adapter.push(1);
360                    else {
361                            attrStartLine.getValue().writeOut(bc, Expression.MODE_VALUE);
362                            adapter.visitInsn(Opcodes.D2I);
363                    }
364                    adapter.storeLocal(startline);
365                    
366                    // endline=@endline
367                    int endline=adapter.newLocal(Types.INT_VALUE);
368                    Attribute attrEndLine = getAttribute("endline");
369                    if(attrEndLine==null) attrEndLine = getAttribute("to");
370                    if(attrEndLine==null) adapter.push(-1);
371                    else {
372                            attrEndLine.getValue().writeOut(bc, Expression.MODE_VALUE);
373                            adapter.visitInsn(Opcodes.D2I);
374                    }
375                    adapter.storeLocal(endline);
376    
377                    
378                    //VariableReference index=VariableInterpreter.getVariableReference(pc,@index);
379                    int index = adapter.newLocal(Types.VARIABLE_REFERENCE);
380                    adapter.loadArg(0);
381                    
382                    getAttribute("index").getValue().writeOut(bc, Expression.MODE_REF);
383                    adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
384                    adapter.storeLocal(index);
385                    
386                    //java.io.File file=FileUtil.toResourceExisting(pc,@file);
387                    int resource=adapter.newLocal(Types.RESOURCE);
388                    adapter.loadArg(0);
389                    getAttribute("file").getValue().writeOut(bc, Expression.MODE_REF);
390                    adapter.invokeStatic(RESOURCE_UTIL, TO_RESOURCE_EXISTING);
391                    adapter.storeLocal(resource);
392                    
393                    // pc.getConfig().getSecurityManager().checkFileLocation(resource);
394                    adapter.loadArg(0);
395                    adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_CONFIG);
396                    adapter.invokeInterface(Types.CONFIG_WEB, GET_SECURITY_MANAGER);
397                    adapter.loadLocal(resource);
398                    adapter.invokeInterface(Types.SECURITY_MANAGER, CHECK_FILE_LOCATION);
399                    
400                    // char[] carr=new char[characters];
401                    Attribute attr = getAttribute("characters");
402                    int carr=-1;
403                    if(attr!=null) {
404                            carr=adapter.newLocal(Types.CHAR_ARRAY);
405                            attr.getValue().writeOut(bc, Expression.MODE_VALUE);
406                            adapter.cast(Types.DOUBLE_VALUE, Types.INT_VALUE);
407                            adapter.newArray(Types.CHAR);
408                            adapter.storeLocal(carr);
409                    }
410                    
411                    // BufferedReader reader = IOUtil.getBufferedReader(resource,charset);
412                    int br=adapter.newLocal(Types.BUFFERED_READER);
413                    adapter.loadLocal(resource);
414                    adapter.loadLocal(charset);
415                    adapter.invokeStatic(IO_UTIL, GET_BUFFERED_READER);
416                    adapter.storeLocal(br);
417                    
418                    // String line;
419                    int line=adapter.newLocal(Types.STRING);
420                    
421                    // int count=0;  
422                    int count=adapter.newLocal(Types.INT_VALUE);
423                    adapter.push(0);
424                    adapter.storeLocal(count);
425                    
426    
427                    TryFinallyVisitor tcfv=new TryFinallyVisitor();
428                    // try
429                    tcfv.visitTryBegin(bc);
430                            // while((line=br.readLine())!=null) { 
431                            //WhileVisitor wv=new WhileVisitor();
432                            whileVisitor.visitBeforeExpression(bc);
433                                    DecisionObjectVisitor dv=new DecisionObjectVisitor();
434                                    dv.visitBegin();
435                                            if(attr!=null) {
436                                                    // IOUtil.read(bufferedreader,12)
437                                                    adapter.loadLocal(br);
438                                                    adapter.loadLocal(carr);
439                                                    adapter.arrayLength();
440                                                    adapter.invokeStatic(Types.IOUTIL, READ);
441                                            }
442                                            else {
443                                                    // br.readLine()
444                                                    adapter.loadLocal(br);
445                                                    adapter.invokeVirtual(Types.BUFFERED_READER, READ_LINE);
446                                            }
447                                            adapter.dup();
448                                            adapter.storeLocal(line);
449                                            
450                                    dv.visitNEQ();
451                                            adapter.visitInsn(Opcodes.ACONST_NULL);
452                                    dv.visitEnd(bc);
453                                    
454                            whileVisitor.visitAfterExpressionBeforeBody(bc);
455                                    //if(++count < startLine) continue; 
456                                    DecisionIntVisitor dv2=new DecisionIntVisitor();
457                                    dv2.visitBegin();
458                                            adapter.iinc(count, 1);
459                                            adapter.loadLocal(count);
460                                    dv2.visitLT();
461                                            adapter.loadLocal(startline);
462                                    dv2.visitEnd(bc);
463                                    Label end=new Label();
464                                    adapter.ifZCmp(Opcodes.IFEQ, end);
465                                            whileVisitor.visitContinue(bc);
466                                    adapter.visitLabel(end);
467                                    
468                                    // if(endLine!=-1 && count > endLine) break; 
469                                    DecisionIntVisitor div=new DecisionIntVisitor();
470                                    div.visitBegin();
471                                            adapter.loadLocal(endline);
472                                    div.visitNEQ();
473                                            adapter.push(-1);
474                                    div.visitEnd(bc);
475                                    Label end2=new Label();
476                                    adapter.ifZCmp(Opcodes.IFEQ, end2);
477                                    
478                                            DecisionIntVisitor div2 = new DecisionIntVisitor();
479                                            div2.visitBegin();
480                                                    adapter.loadLocal(count);
481                                            div2.visitGT();
482                                                    adapter.loadLocal(endline);
483                                            div2.visitEnd(bc);
484                                            Label end3=new Label();
485                                            adapter.ifZCmp(Opcodes.IFEQ, end3);
486                                                    whileVisitor.visitBreak(bc);
487                                            adapter.visitLabel(end3);
488                                    adapter.visitLabel(end2);
489                                    
490                                    // index.set(pc,line); 
491                                    adapter.loadLocal(index);
492                                    adapter.loadArg(0);
493                                    adapter.loadLocal(line);
494                                    adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
495                                    adapter.pop();
496                                    
497                                    getBody().writeOut(bc);
498                                    
499                            whileVisitor.visitAfterBody(bc,getEndLine());
500                            
501                    
502                    tcfv.visitTryEndFinallyBegin(bc);
503                    
504                    
505                    // finally
506                    //tcfv.visitFinallyBegin(adapter);
507                            //IOUtil.closeEL(reader);
508                            adapter.loadLocal(br);
509                            adapter.invokeStatic(IO_UTIL, CLOSE_EL);
510                    
511                    tcfv.visitFinallyEnd(bc);
512                    
513            }
514    
515            /**
516             * write out index loop
517             * @param adapter
518             * @throws TemplateException
519             */
520            private void writeOutTypeIndex(BytecodeContext bc) throws BytecodeException {
521                    ForDoubleVisitor forDoubleVisitor = new ForDoubleVisitor();
522                    loopVisitor=forDoubleVisitor;
523                    GeneratorAdapter adapter = bc.getAdapter();
524    
525                    // int from=(int)@from;
526                    int from=adapter.newLocal(Types.DOUBLE_VALUE);
527                    ExpressionUtil.writeOutSilent(getAttribute("from").getValue(), bc, Expression.MODE_VALUE);
528                    adapter.storeLocal(from);       
529                    
530                    // int to=(int)@to;
531                    int to=adapter.newLocal(Types.DOUBLE_VALUE);
532                    ExpressionUtil.writeOutSilent(getAttribute("to").getValue(), bc, Expression.MODE_VALUE);
533                    adapter.storeLocal(to); 
534                    
535                    // int step=(int)@step;
536                    int step=adapter.newLocal(Types.DOUBLE_VALUE);
537                    Attribute attrStep = getAttribute("step");
538                    if(attrStep!=null) {
539                            ExpressionUtil.writeOutSilent(attrStep.getValue(), bc, Expression.MODE_VALUE);
540                    }
541                    else {
542                            adapter.push(1D);
543                    }
544                    adapter.storeLocal(step);
545                    
546                    // boolean dirPlus=(step > 0);
547                    int dirPlus=adapter.newLocal(Types.BOOLEAN_VALUE);
548                    DecisionDoubleVisitor div=new DecisionDoubleVisitor();
549                    div.visitBegin();
550                            adapter.loadLocal(step);
551                    div.visitGT();
552                            adapter.push(0D);
553                    div.visitEnd(bc);
554                    adapter.storeLocal(dirPlus);
555                    
556                    //if(step!=0) {
557                    div=new DecisionDoubleVisitor();
558                    div.visitBegin();
559                            adapter.loadLocal(step);
560                    div.visitNEQ();
561                            adapter.push(0D);
562                    div.visitEnd(bc);
563                    Label ifEnd=new Label();
564                    adapter.ifZCmp(Opcodes.IFEQ, ifEnd);
565                            
566                            // VariableReference index>=VariableInterpreter.getVariableReference(pc,@index));
567                            int index = adapter.newLocal(Types.VARIABLE_REFERENCE);
568                            adapter.loadArg(0);
569                            ExpressionUtil.writeOutSilent(getAttribute("index").getValue(), bc, Expression.MODE_REF);
570                            adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
571                            adapter.storeLocal(index);
572                            
573    
574                            // index.set(from);
575                            adapter.loadLocal(index);
576                            adapter.loadLocal(from);
577                            adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE);
578                            
579                            // for
580                                    
581                            //int i=forConditionVisitor.visitBeforeExpression(adapter,from,step,true);
582                            
583                            // init
584                            adapter.visitLabel(forDoubleVisitor.beforeInit);
585                            forDoubleVisitor.forInit(adapter, from, true);
586                            adapter.goTo(forDoubleVisitor.beforeExpr);
587                            
588                            // update
589                            adapter.visitLabel(forDoubleVisitor.beforeUpdate);
590                            adapter.loadLocal(index);
591                            //forConditionVisitor.forUpdate(adapter, step, true);
592                            adapter.visitVarInsn(Opcodes.DLOAD, forDoubleVisitor.i);
593                            adapter.loadLocal(step);
594                            adapter.visitInsn(Opcodes.DADD);
595                            adapter.visitInsn(Opcodes.DUP2);
596                            adapter.visitVarInsn(Opcodes.DSTORE, forDoubleVisitor.i);
597                            
598                            
599                            
600                            adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE);
601                            
602                            
603                            
604                            
605                            // expression
606                            adapter.visitLabel(forDoubleVisitor.beforeExpr);
607                            int i=forDoubleVisitor.i;
608                            
609                            
610                            
611                            
612                            
613                                    adapter.loadLocal(dirPlus);
614                                    Label l1 = new Label();
615                                    adapter.visitJumpInsn(Opcodes.IFEQ, l1);
616                                    
617                                            div=new DecisionDoubleVisitor();
618                                            div.visitBegin();
619                                                    adapter.visitVarInsn(Opcodes.DLOAD, i);
620                                            div.visitLTE();
621                                                    adapter.loadLocal(to);
622                                            div.visitEnd(bc);
623                                            
624                                    Label l2 = new Label();
625                                    adapter.visitJumpInsn(Opcodes.GOTO, l2);
626                                    adapter.visitLabel(l1);
627                                    
628                                            div=new DecisionDoubleVisitor();
629                                            div.visitBegin();
630                                                    adapter.visitVarInsn(Opcodes.DLOAD, i);
631                                            div.visitGTE();
632                                                    adapter.loadLocal(to);
633                                            div.visitEnd(bc);
634                                    
635                                    adapter.visitLabel(l2);
636                            forDoubleVisitor.visitAfterExpressionBeginBody(adapter);
637                                    
638                                    //adapter.loadLocal(index);
639                                    //adapter.visitVarInsn(Opcodes.DLOAD, i);
640                                    //adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE);
641                                    
642                                    getBody().writeOut(bc);
643                            
644                            forDoubleVisitor.visitEndBody(bc,getEndLine());
645                                    
646                            
647                            
648                            ////// set i after usage
649                            //adapter.loadLocal(index);
650                            //adapter.visitVarInsn(Opcodes.DLOAD, i);
651                            //adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE);
652                            
653                    adapter.visitLabel(ifEnd);
654                    
655            }
656            
657            /**
658             * write out list loop
659             * @param adapter
660             * @throws TemplateException
661             */
662            private void writeOutTypeListArray(BytecodeContext bc, boolean isArray) throws BytecodeException {
663                    ForVisitor forVisitor = new ForVisitor();
664                    loopVisitor=forVisitor;
665                    GeneratorAdapter adapter = bc.getAdapter();
666    
667                    //List.listToArrayRemoveEmpty("", 'c')
668                    int array = adapter.newLocal(Types.ARRAY);
669                    int len = adapter.newLocal(Types.INT_VALUE);
670                    int index = adapter.newLocal(Types.VARIABLE_REFERENCE);
671                    
672                    if(isArray) {
673                            getAttribute("array").getValue().writeOut(bc, Expression.MODE_REF);
674                    }
675                    else {
676                            // array=List.listToArrayRemoveEmpty(list, delimter)
677                            getAttribute("list").getValue().writeOut(bc, Expression.MODE_REF);
678                            if(containsAttribute("delimiters")) {
679                                    getAttribute("delimiters").getValue().writeOut(bc, Expression.MODE_REF);
680                                    adapter.invokeStatic(Types.LIST, LIST_TO_ARRAY_REMOVE_EMPTY_SS);
681                            }
682                            else {
683                                    adapter.visitIntInsn(Opcodes.BIPUSH, 44);// ','
684                                    //adapter.push(',');
685                                    adapter.invokeStatic(Types.LIST, LIST_TO_ARRAY_REMOVE_EMPTY_SC);
686                            }
687                    }
688                    adapter.storeLocal(array);
689            
690                    
691                    // int len=array.size();
692                    adapter.loadLocal(array);
693                    adapter.invokeInterface(Types.ARRAY, SIZE);
694                    adapter.storeLocal(len);
695    
696                    //VariableInterpreter.getVariableReference(pc,Caster.toString(index));
697                    adapter.loadArg(0);
698                    getAttribute("index").getValue().writeOut(bc, Expression.MODE_REF);
699                    adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
700                    adapter.storeLocal(index);
701                    
702                    int obj=0;
703                    if(isArray)obj=adapter.newLocal(Types.OBJECT);
704                    
705                    // for(int i=1;i<=len;i++) {         
706                    int i = forVisitor.visitBegin(adapter, 1, false);
707                            // index.set(pc, list.get(i));
708                            
709                            if(isArray) {
710                                    
711    
712                                    adapter.loadLocal(array);
713                                    adapter.visitVarInsn(Opcodes.ILOAD, i);
714                                    ASMConstants.NULL(adapter);
715                                    adapter.invokeInterface(Types.ARRAY, GET);
716                                    adapter.dup();
717                                    adapter.storeLocal(obj);
718                                    Label endIf=new Label();
719                                    //adapter.loadLocal(obj);
720                                    adapter.visitJumpInsn(Opcodes.IFNONNULL, endIf);
721                                            adapter.goTo(forVisitor.getContinueLabel());
722                                    adapter.visitLabel(endIf);
723                                    
724                                    adapter.loadLocal(index);
725                                    adapter.loadArg(0);
726                                    
727                                    
728                                    adapter.loadLocal(obj);
729                                    
730                            }
731                            else {
732                                    adapter.loadLocal(index);
733                                    adapter.loadArg(0);
734                                            adapter.loadLocal(array);
735                                            adapter.visitVarInsn(Opcodes.ILOAD, i);
736                                            adapter.invokeInterface(Types.ARRAY, GETE);
737                                            
738                                    
739                            }
740                            adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
741                            adapter.pop();
742                            getBody().writeOut(bc);
743                    forVisitor.visitEnd(bc, len, true,getStartLine()); 
744            }
745            
746            /**
747             * write out query loop
748             * @param adapter
749             * @throws TemplateException
750             */
751            private void writeOutTypeQuery(BytecodeContext bc) throws BytecodeException {
752                    ForConditionIntVisitor forConditionVisitor = new ForConditionIntVisitor();// TODO replace with ForIntVisitor 
753                    loopVisitor=forConditionVisitor;
754                    GeneratorAdapter adapter = bc.getAdapter();
755                    // railo.runtime.type.Query query=pc.getQuery(@query);
756                    int query=adapter.newLocal(Types.QUERY);
757                    adapter.loadArg(0);
758                    getAttribute("query").getValue().writeOut(bc, Expression.MODE_REF);
759                    adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_QUERY);
760                    //adapter.dup();
761                    adapter.storeLocal(query);
762                    
763                    //int queryImpl = adapter.newLocal(Types.QUERY_IMPL);
764                    //adapter.checkCast(Types.QUERY_IMPL);
765                    //adapter.storeLocal(queryImpl);
766                    
767                    
768                    // int startAt=query.getCurrentrow();
769                    int startAt=adapter.newLocal(Types.INT_VALUE);
770                    /* FUTURE
771                    adapter.loadLocal(query);
772                    adapter.loadArg(0);
773                    adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID);
774                    adapter.invokeInterface(Types.QUERY, GET_CURRENTROW_1);
775                    adapter.storeLocal(startAt);
776                    
777                    */
778                    adapter.loadLocal(query);
779                    adapter.invokeInterface(Types.QUERY, GET_CURRENTROW_0);
780                    adapter.storeLocal(startAt);
781                    
782                    
783                    // startrow
784                    int start=adapter.newLocal(Types.INT_VALUE);
785                    Attribute attrStartRow = getAttribute("startrow");
786                    if(attrStartRow!=null){
787                            //railo.runtime.util.NumberRange.range(@startrow,1)
788                            attrStartRow.getValue().writeOut(bc, Expression.MODE_VALUE);
789                            adapter.push(1d);
790                            adapter.invokeStatic(Types.NUMBER_RANGE, RANGE);
791                            adapter.visitInsn(Opcodes.D2I);
792                    }
793                    else {
794                            adapter.push(1);
795                    }
796                    adapter.storeLocal(start);
797                    
798                    // endrow
799                    int end=adapter.newLocal(Types.INT_VALUE);
800                    Attribute attrEndRow = getAttribute("endrow");
801                    if(attrEndRow!=null){
802                            attrEndRow.getValue().writeOut(bc, Expression.MODE_VALUE);
803                            adapter.visitInsn(Opcodes.D2I);
804                            adapter.storeLocal(end);
805                    }
806                    
807                    // pc.us().addCollection(query);
808                    adapter.loadArg(0);
809                    adapter.invokeVirtual(Types.PAGE_CONTEXT, US);
810                    adapter.loadLocal(query);
811                    adapter.invokeInterface(UNDEFINED, ADD_QUERY);
812                    
813                    // try
814                    TryFinallyVisitor tfv=new TryFinallyVisitor();
815                    tfv.visitTryBegin(bc);
816                            // For
817                            
818                            int i=forConditionVisitor.visitBegin(adapter, start, true);
819                                    getBody().writeOut(bc);
820                            forConditionVisitor.visitEndBeforeCondition(bc,1,false,getStartLine());
821                                    
822                                    // && i<=endrow
823                                    if(attrEndRow!=null){
824                                            AndVisitor av=new AndVisitor();
825                                            av.visitBegin();
826                                                    adapter.loadLocal(query);
827                                                    adapter.visitVarInsn(Opcodes.ILOAD, i);
828                                                    /* FUTURE
829                                                    adapter.loadArg(0);
830                                                    adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID);
831                                                    adapter.invokeVirtual(Types.QUERY, GO_2); 
832                                                    */
833                                                    adapter.invokeInterface(Types.QUERY, GO_1); 
834                                            
835                                                    av.visitMiddle(bc);
836                                                    //LitBoolean.TRUE.writeOut(bc, Expression.MODE_VALUE);
837                                                    DecisionIntVisitor dv=new DecisionIntVisitor();
838                                                    dv.visitBegin();
839                                                            adapter.visitVarInsn(Opcodes.ILOAD, i);
840                                                    dv.visitLTE();
841                                                            adapter.loadLocal(end);
842                                                    dv.visitEnd(bc);
843                                            av.visitEnd(bc);
844                                    }
845                                    else {
846                                            adapter.loadLocal(query);
847                                            adapter.visitVarInsn(Opcodes.ILOAD, i);
848                                            /* FUTURE
849                                            adapter.loadArg(0);
850                                            adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID);
851                                            adapter.invokeInterface(Types.QUERY, GO_2);
852                                            */
853                                            adapter.invokeInterface(Types.QUERY, GO_1);
854    
855                                    
856                                    
857                                    }
858                                    
859                                    
860                            forConditionVisitor.visitEndAfterCondition(bc);
861    
862                    // Finally
863                    tfv.visitTryEndFinallyBegin(bc);
864                            // pc.us().removeCollection();
865                            adapter.loadArg(0);
866                            adapter.invokeVirtual(Types.PAGE_CONTEXT, US);
867                            adapter.invokeInterface(UNDEFINED, REMOVE_QUERY);
868                    
869                            // query.go(startAt);
870                            adapter.loadLocal(query);
871                            adapter.loadLocal(startAt);
872                            /* FUTURE
873                            adapter.loadArg(0);
874                            adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID);
875                            adapter.invokeInterface(Types.QUERY, GO_2);
876                            */
877                            adapter.invokeInterface(Types.QUERY, GO_1);
878                            
879                            adapter.pop();
880                            
881                            
882                            
883                    tfv.visitFinallyEnd(bc);
884            }
885    
886            /**
887             * @see railo.transformer.bytecode.statement.FlowControl#getBreakLabel()
888             */
889            public Label getBreakLabel() {
890                    return loopVisitor.getBreakLabel();
891            }
892    
893            /**
894             * @see railo.transformer.bytecode.statement.FlowControl#getContinueLabel()
895             */
896            public Label getContinueLabel() {
897                    return loopVisitor.getContinueLabel();
898            }
899    
900    
901    }