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