package railo.transformer.bytecode.statement.tag;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import railo.commons.io.IOUtil;
import railo.commons.io.res.util.ResourceUtil;
import railo.runtime.exp.TemplateException;
import railo.transformer.bytecode.BytecodeContext;
import railo.transformer.bytecode.BytecodeException;
import railo.transformer.bytecode.Position;
import railo.transformer.bytecode.cast.CastBoolean;
import railo.transformer.bytecode.expression.Expression;
import railo.transformer.bytecode.statement.FlowControlBreak;
import railo.transformer.bytecode.statement.FlowControlContinue;
import railo.transformer.bytecode.statement.FlowControlFinal;
import railo.transformer.bytecode.statement.ForEach;
import railo.transformer.bytecode.util.ASMConstants;
import railo.transformer.bytecode.util.ExpressionUtil;
import railo.transformer.bytecode.util.Methods;
import railo.transformer.bytecode.util.Methods_Caster;
import railo.transformer.bytecode.util.Types;
import railo.transformer.bytecode.visitor.DecisionDoubleVisitor;
import railo.transformer.bytecode.visitor.DecisionIntVisitor;
import railo.transformer.bytecode.visitor.DecisionObjectVisitor;
import railo.transformer.bytecode.visitor.DoWhileVisitor;
import railo.transformer.bytecode.visitor.ForDoubleVisitor;
import railo.transformer.bytecode.visitor.ForVisitor;
import railo.transformer.bytecode.visitor.LoopVisitor;
import railo.transformer.bytecode.visitor.OnFinally;
import railo.transformer.bytecode.visitor.TryFinallyVisitor;
import railo.transformer.bytecode.visitor.WhileVisitor;
public final class TagLoop extends TagGroup implements FlowControlBreak,FlowControlContinue {
public static final int TYPE_FILE = 1;
public static final int TYPE_LIST = 2;
public static final int TYPE_INDEX = 3;
public static final int TYPE_CONDITION = 4;
public static final int TYPE_QUERY = 5;
public static final int TYPE_COLLECTION = 6;
public static final int TYPE_ARRAY = 7;
public static final int TYPE_GROUP = 8;
public static final int TYPE_INNER_GROUP = 9;
public static final int TYPE_INNER_QUERY = 10;
public static final int TYPE_NOTHING = 11;
// VariableReference getVariableReference(PageContext pc,String var)
private static final Method GET_VARIABLE_REFERENCE = new Method(
"getVariableReference",
Types.VARIABLE_REFERENCE,
new Type[]{Types.PAGE_CONTEXT,Types.STRING});
// Object set(PageContext pc, Object value)
private static final Method SET = new Method(
"set",
Types.OBJECT,
new Type[]{Types.PAGE_CONTEXT,Types.OBJECT});
// Object set(double value)
private static final Method SET_DOUBLE = new Method(
"set",
Types.VOID,
new Type[]{Types.DOUBLE_VALUE});
/*private static final Method KEYS = new Method(
"keyIterator",
Types.COLLECTION_KEY_ARRAY,
new Type[]{});*/
private static final Method GET = new Method(
"get",
Types.OBJECT,
new Type[]{Types.INT_VALUE,Types.OBJECT});
private static final Method NEXT = new Method(
"next",
Types.OBJECT,
new Type[]{});
private static final Method HAS_NEXT = new Method(
"hasNext",
Types.BOOLEAN_VALUE,
new Type[]{});
// File toFileExisting(PageContext pc ,String destination)
private static final Type RESOURCE_UTIL = Type.getType(ResourceUtil.class);
private static final Method TO_RESOURCE_EXISTING = new Method(
"toResourceExisting",
Types.RESOURCE,
new Type[]{Types.PAGE_CONTEXT,Types.STRING});
// Config getConfig()
private static final Method GET_CONFIG = new Method(
"getConfig",
Types.CONFIG_WEB,
new Type[]{});
// SecurityManager getSecurityManager()
private static final Method GET_SECURITY_MANAGER = new Method(
"getSecurityManager",
Types.SECURITY_MANAGER,
new Type[]{});
// void checkFileLocation(File file)
private static final Method CHECK_FILE_LOCATION = new Method(
"checkFileLocation",
Types.VOID,
new Type[]{Types.RESOURCE});
// Reader getReader(File file, String charset)
private static final Type IO_UTIL = Type.getType(IOUtil.class);
private static final Method GET_BUFFERED_READER = new Method(
"getBufferedReader",
Types.BUFFERED_READER,
new Type[]{Types.RESOURCE,Types.STRING});
// void closeEL(Reader r)
private static final Method CLOSE_EL = new Method(
"closeEL",
Types.VOID,
new Type[]{Types.READER});
// String readLine()
private static final Method READ_LINE = new Method(
"readLine",
Types.STRING,
new Type[]{});
// Array listToArrayRemoveEmpty(String list, String delimiter)
private static final Method LIST_TO_ARRAY_REMOVE_EMPTY_SS = new Method(
"listToArrayRemoveEmpty",
Types.ARRAY,
new Type[]{Types.STRING,Types.STRING});
// Array listToArrayRemoveEmpty(String list, char delimiter)
private static final Method LIST_TO_ARRAY_REMOVE_EMPTY_SC = new Method(
"listToArrayRemoveEmpty",
Types.ARRAY,
new Type[]{Types.STRING,Types.CHAR});
private static final Method SIZE = new Method(
"size",
Types.INT_VALUE,
new Type[]{});
// Object get(int key) klo
private static final Method GETE = new Method(
"getE",
Types.OBJECT,
new Type[]{Types.INT_VALUE});
// Query getQuery(String key)
public static final Method GET_QUERY_OBJ = new Method(
"getQuery",
Types.QUERY,
new Type[]{Types.OBJECT});
public static final Method GET_QUERY_STRING = new Method(
"getQuery",
Types.QUERY,
new Type[]{Types.STRING});
// int getCurrentrow()
static final Method GET_CURRENTROW_1 = new Method(
"getCurrentrow",
Types.INT_VALUE,
new Type[]{Types.INT_VALUE});
static final Method GO = new Method(
"go",
Types.BOOLEAN_VALUE,
new Type[]{Types.INT_VALUE,Types.INT_VALUE});
static final Method GET_ID = new Method(
"getId",
Types.INT_VALUE,
new Type[]{});
private static final Method READ = new Method(
"read",
Types.STRING,
new Type[]{Types.READER,Types.INT_VALUE});
private static final Method ENTRY_ITERATOR = new Method("entryIterator",Types.ITERATOR,new Type[]{});
private static final Method GET_KEY = new Method("getKey",Types.OBJECT,new Type[]{});
private static final Method GET_VALUE = new Method("getValue",Types.OBJECT,new Type[]{});
private int type;
private LoopVisitor loopVisitor;
private String label;
public TagLoop(Position start,Position end) {
super(start,end);
}
public void setType(int type) {
this.type=type;
}
/**
*
* @see railo.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter)
*/
public void _writeOut(BytecodeContext bc) throws BytecodeException {
boolean old;
switch(type) {
case TYPE_COLLECTION:
writeOutTypeCollection(bc);
break;
case TYPE_CONDITION:
writeOutTypeCondition(bc);
break;
case TYPE_FILE:
writeOutTypeFile(bc);
break;
case TYPE_INDEX:
writeOutTypeIndex(bc);
break;
case TYPE_LIST:
writeOutTypeListArray(bc,false);
break;
case TYPE_ARRAY:
writeOutTypeListArray(bc,true);
break;
case TYPE_QUERY:
old = bc.changeDoSubFunctions(false);
TagGroupUtil.writeOutTypeQuery(this,bc);
bc.changeDoSubFunctions(old);
//writeOutTypeQuery(bc);
break;
case TYPE_GROUP:
old = bc.changeDoSubFunctions(false);
TagGroupUtil.writeOutTypeGroup(this,bc);
bc.changeDoSubFunctions(old);
//writeOutTypeQuery(bc);
break;
case TYPE_INNER_GROUP:
old = bc.changeDoSubFunctions(false);
TagGroupUtil.writeOutTypeInnerGroup(this,bc);
bc.changeDoSubFunctions(old);
break;
case TYPE_INNER_QUERY:
old = bc.changeDoSubFunctions(false);
TagGroupUtil.writeOutTypeInnerQuery(this,bc);
bc.changeDoSubFunctions(old);
break;
case TYPE_NOTHING:
GeneratorAdapter a = bc.getAdapter();
DoWhileVisitor dwv=new DoWhileVisitor();
setLoopVisitor(dwv);
dwv.visitBeginBody(a);
getBody().writeOut(bc);
dwv.visitEndBodyBeginExpr(a);
a.push(false);
dwv.visitEndExpr(a);
break;
default:
throw new BytecodeException("invalid type",getStart());
}
}
/**
* write out collection loop
* @param adapter
* @throws TemplateException
*/
private void writeOutTypeCollection(BytecodeContext bc) throws BytecodeException {
GeneratorAdapter adapter = bc.getAdapter();
//VariableReference item=VariableInterpreter.getVariableReference(pc,index);
int index = -1;
Attribute attrIndex = getAttribute("index");
if(attrIndex!=null){
index = adapter.newLocal(Types.VARIABLE_REFERENCE);
adapter.loadArg(0);
attrIndex.getValue().writeOut(bc, Expression.MODE_REF);
adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
adapter.storeLocal(index);
}
//VariableReference item=VariableInterpreter.getVariableReference(pc,item);
int item = -1;
Attribute attrItem = getAttribute("item");
if(attrItem!=null){
item = adapter.newLocal(Types.VARIABLE_REFERENCE);
adapter.loadArg(0);
attrItem.getValue().writeOut(bc, Expression.MODE_REF);
adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
adapter.storeLocal(item);
}
boolean hasIndexAndItem=index!=-1 && item!=-1;
WhileVisitor whileVisitor = new WhileVisitor();
loopVisitor=whileVisitor;
// java.util.Iterator it=Caster.toIterator(@collection');
int it=adapter.newLocal(Types.ITERATOR);
getAttribute("collection").getValue().writeOut(bc,Expression.MODE_REF);
// item and index
int entry=-1;
if(hasIndexAndItem) {
entry = adapter.newLocal(Types.MAP_ENTRY);
// Caster.toCollection(collection)
adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_COLLECTION);
//coll.entryIterator();
adapter.invokeInterface(Types.COLLECTION, ENTRY_ITERATOR);
}
else {
adapter.invokeStatic(Types.CASTER,ForEach.TO_ITERATOR);
}
adapter.storeLocal(it);
// while(it.hasNext()) {
whileVisitor.visitBeforeExpression(bc);
adapter.loadLocal(it);
adapter.invokeInterface(Types.ITERATOR, HAS_NEXT);
whileVisitor.visitAfterExpressionBeforeBody(bc);
if(hasIndexAndItem) {
// entry=it.next();
adapter.loadLocal(it);
adapter.invokeInterface(Types.ITERATOR, NEXT);
adapter.storeLocal(entry);
// keyRef.set(pc,entry.getKey())
adapter.loadLocal(index);
adapter.loadArg(0);
adapter.loadLocal(entry);
adapter.invokeInterface(Types.MAP_ENTRY, GET_KEY);
adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_STRING);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
adapter.pop();
// valueRef.set(pc,entry.getKey())
adapter.loadLocal(item);
adapter.loadArg(0);
adapter.loadLocal(entry);
adapter.invokeInterface(Types.MAP_ENTRY, GET_VALUE);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
adapter.pop();
}
else {
if(index==-1) adapter.loadLocal(item);
else adapter.loadLocal(index);
adapter.loadArg(0);
adapter.loadLocal(it);
adapter.invokeInterface(Types.ITERATOR, NEXT);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
adapter.pop();
}
getBody().writeOut(bc);
whileVisitor.visitAfterBody(bc,getEnd());
}
/**
* write out condition loop
* @param adapter
* @throws TemplateException
*/
private void writeOutTypeCondition(BytecodeContext bc) throws BytecodeException {
WhileVisitor whileVisitor = new WhileVisitor();
loopVisitor=whileVisitor;
whileVisitor.visitBeforeExpression(bc);
CastBoolean.toExprBoolean(getAttribute("condition").getValue()).writeOut(bc, Expression.MODE_VALUE);
whileVisitor.visitAfterExpressionBeforeBody(bc);
getBody().writeOut(bc);
whileVisitor.visitAfterBody(bc,getEnd());
}
/**
* write out file loop
* @param adapter
* @throws TemplateException
*/
private void writeOutTypeFile(BytecodeContext bc) throws BytecodeException {
WhileVisitor whileVisitor = new WhileVisitor();
loopVisitor=whileVisitor;
GeneratorAdapter adapter = bc.getAdapter();
// charset=@charset
int charset=adapter.newLocal(Types.STRING);
Attribute attrCharset = getAttribute("charset");
if(attrCharset==null) adapter.visitInsn(Opcodes.ACONST_NULL);
else attrCharset.getValue().writeOut(bc, Expression.MODE_REF);
adapter.storeLocal(charset);
// startline=@startline
int startline=adapter.newLocal(Types.INT_VALUE);
Attribute attrStartLine = getAttribute("startline");
if(attrStartLine==null) attrStartLine = getAttribute("from"); // CF8
if(attrStartLine==null) adapter.push(1);
else {
attrStartLine.getValue().writeOut(bc, Expression.MODE_VALUE);
adapter.visitInsn(Opcodes.D2I);
}
adapter.storeLocal(startline);
// endline=@endline
int endline=adapter.newLocal(Types.INT_VALUE);
Attribute attrEndLine = getAttribute("endline");
if(attrEndLine==null) attrEndLine = getAttribute("to");
if(attrEndLine==null) adapter.push(-1);
else {
attrEndLine.getValue().writeOut(bc, Expression.MODE_VALUE);
adapter.visitInsn(Opcodes.D2I);
}
adapter.storeLocal(endline);
//VariableReference index=VariableInterpreter.getVariableReference(pc,@index);
int index=-1,item=-1;
// item
Attribute attrItem = getAttribute("item");
if(attrItem!=null) {
item = adapter.newLocal(Types.VARIABLE_REFERENCE);
adapter.loadArg(0);
attrItem.getValue().writeOut(bc, Expression.MODE_REF);
adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
adapter.storeLocal(item);
}
// index
Attribute attrIndex = getAttribute("index");
if(attrIndex!=null) {
index = adapter.newLocal(Types.VARIABLE_REFERENCE);
adapter.loadArg(0);
attrIndex.getValue().writeOut(bc, Expression.MODE_REF);
adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
adapter.storeLocal(index);
}
//java.io.File file=FileUtil.toResourceExisting(pc,@file);
int resource=adapter.newLocal(Types.RESOURCE);
adapter.loadArg(0);
getAttribute("file").getValue().writeOut(bc, Expression.MODE_REF);
adapter.invokeStatic(RESOURCE_UTIL, TO_RESOURCE_EXISTING);
adapter.storeLocal(resource);
// pc.getConfig().getSecurityManager().checkFileLocation(resource);
adapter.loadArg(0);
adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_CONFIG);
adapter.invokeInterface(Types.CONFIG_WEB, GET_SECURITY_MANAGER);
adapter.loadLocal(resource);
adapter.invokeInterface(Types.SECURITY_MANAGER, CHECK_FILE_LOCATION);
// char[] carr=new char[characters];
Attribute attr = getAttribute("characters");
int carr=-1;
if(attr!=null) {
carr=adapter.newLocal(Types.CHAR_ARRAY);
attr.getValue().writeOut(bc, Expression.MODE_VALUE);
adapter.cast(Types.DOUBLE_VALUE, Types.INT_VALUE);
adapter.newArray(Types.CHAR);
adapter.storeLocal(carr);
}
// BufferedReader reader = IOUtil.getBufferedReader(resource,charset);
final int br=adapter.newLocal(Types.BUFFERED_READER);
adapter.loadLocal(resource);
adapter.loadLocal(charset);
adapter.invokeStatic(IO_UTIL, GET_BUFFERED_READER);
adapter.storeLocal(br);
// String line;
int line=adapter.newLocal(Types.STRING);
// int count=0;
int count=adapter.newLocal(Types.INT_VALUE);
adapter.push(0);
adapter.storeLocal(count);
TryFinallyVisitor tfv=new TryFinallyVisitor(new OnFinally() {
public void writeOut(BytecodeContext bc) {
bc.getAdapter().loadLocal(br);
bc.getAdapter().invokeStatic(IO_UTIL, CLOSE_EL);
}
},null);
//TryFinallyVisitor tcfv=new TryFinallyVisitor();
// try
tfv.visitTryBegin(bc);
//tcfv.visitTryBegin(bc);
// while((line=br.readLine())!=null) {
//WhileVisitor wv=new WhileVisitor();
whileVisitor.visitBeforeExpression(bc);
DecisionObjectVisitor dv=new DecisionObjectVisitor();
dv.visitBegin();
if(attr!=null) {
// IOUtil.read(bufferedreader,12)
adapter.loadLocal(br);
adapter.loadLocal(carr);
adapter.arrayLength();
adapter.invokeStatic(Types.IOUTIL, READ);
}
else {
// br.readLine()
adapter.loadLocal(br);
adapter.invokeVirtual(Types.BUFFERED_READER, READ_LINE);
}
adapter.dup();
adapter.storeLocal(line);
dv.visitNEQ();
adapter.visitInsn(Opcodes.ACONST_NULL);
dv.visitEnd(bc);
whileVisitor.visitAfterExpressionBeforeBody(bc);
//if(++count < startLine) continue;
DecisionIntVisitor dv2=new DecisionIntVisitor();
dv2.visitBegin();
adapter.iinc(count, 1);
adapter.loadLocal(count);
dv2.visitLT();
adapter.loadLocal(startline);
dv2.visitEnd(bc);
Label end=new Label();
adapter.ifZCmp(Opcodes.IFEQ, end);
whileVisitor.visitContinue(bc);
adapter.visitLabel(end);
// if(endLine!=-1 && count > endLine) break;
DecisionIntVisitor div=new DecisionIntVisitor();
div.visitBegin();
adapter.loadLocal(endline);
div.visitNEQ();
adapter.push(-1);
div.visitEnd(bc);
Label end2=new Label();
adapter.ifZCmp(Opcodes.IFEQ, end2);
DecisionIntVisitor div2 = new DecisionIntVisitor();
div2.visitBegin();
adapter.loadLocal(count);
div2.visitGT();
adapter.loadLocal(endline);
div2.visitEnd(bc);
Label end3=new Label();
adapter.ifZCmp(Opcodes.IFEQ, end3);
whileVisitor.visitBreak(bc);
adapter.visitLabel(end3);
adapter.visitLabel(end2);
// index and item
if(index!=-1 && item!=-1) {
// index.set(pc,line);
adapter.loadLocal(index);
adapter.loadArg(0);
adapter.loadLocal(count);
adapter.cast(Types.INT_VALUE,Types.DOUBLE_VALUE);
adapter.invokeStatic(Types.CASTER, Methods.METHOD_TO_DOUBLE_FROM_DOUBLE);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
adapter.pop();
// item.set(pc,line);
adapter.loadLocal(item);
adapter.loadArg(0);
adapter.loadLocal(line);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
adapter.pop();
}
// only index
else if(index!=-1) {
// index.set(pc,line);
adapter.loadLocal(index);
adapter.loadArg(0);
adapter.loadLocal(line);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
adapter.pop();
}
// only item
else {
// item.set(pc,line);
adapter.loadLocal(item);
adapter.loadArg(0);
adapter.loadLocal(line);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
adapter.pop();
}
getBody().writeOut(bc);
whileVisitor.visitAfterBody(bc,getEnd());
tfv.visitTryEnd(bc);
}
/**
* write out index loop
* @param adapter
* @throws TemplateException
*/
private void writeOutTypeIndex(BytecodeContext bc) throws BytecodeException {
ForDoubleVisitor forDoubleVisitor = new ForDoubleVisitor();
loopVisitor=forDoubleVisitor;
GeneratorAdapter adapter = bc.getAdapter();
// int from=(int)@from;
int from=adapter.newLocal(Types.DOUBLE_VALUE);
ExpressionUtil.writeOutSilent(getAttribute("from").getValue(), bc, Expression.MODE_VALUE);
adapter.storeLocal(from);
// int to=(int)@to;
int to=adapter.newLocal(Types.DOUBLE_VALUE);
ExpressionUtil.writeOutSilent(getAttribute("to").getValue(), bc, Expression.MODE_VALUE);
adapter.storeLocal(to);
// int step=(int)@step;
int step=adapter.newLocal(Types.DOUBLE_VALUE);
Attribute attrStep = getAttribute("step");
if(attrStep!=null) {
ExpressionUtil.writeOutSilent(attrStep.getValue(), bc, Expression.MODE_VALUE);
}
else {
adapter.push(1D);
}
adapter.storeLocal(step);
// boolean dirPlus=(step > 0);
int dirPlus=adapter.newLocal(Types.BOOLEAN_VALUE);
DecisionDoubleVisitor div=new DecisionDoubleVisitor();
div.visitBegin();
adapter.loadLocal(step);
div.visitGT();
adapter.push(0D);
div.visitEnd(bc);
adapter.storeLocal(dirPlus);
//if(step!=0) {
div=new DecisionDoubleVisitor();
div.visitBegin();
adapter.loadLocal(step);
div.visitNEQ();
adapter.push(0D);
div.visitEnd(bc);
Label ifEnd=new Label();
adapter.ifZCmp(Opcodes.IFEQ, ifEnd);
// VariableReference index>=VariableInterpreter.getVariableReference(pc,@index));
int index = adapter.newLocal(Types.VARIABLE_REFERENCE);
adapter.loadArg(0);
ExpressionUtil.writeOutSilent(getAttribute("index").getValue(), bc, Expression.MODE_REF);
adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
adapter.storeLocal(index);
// index.set(from);
adapter.loadLocal(index);
adapter.loadLocal(from);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE);
// for
//int i=forConditionVisitor.visitBeforeExpression(adapter,from,step,true);
// init
adapter.visitLabel(forDoubleVisitor.beforeInit);
forDoubleVisitor.forInit(adapter, from, true);
adapter.goTo(forDoubleVisitor.beforeExpr);
// update
adapter.visitLabel(forDoubleVisitor.beforeUpdate);
adapter.loadLocal(index);
//forConditionVisitor.forUpdate(adapter, step, true);
adapter.visitVarInsn(Opcodes.DLOAD, forDoubleVisitor.i);
adapter.loadLocal(step);
adapter.visitInsn(Opcodes.DADD);
adapter.visitInsn(Opcodes.DUP2);
adapter.visitVarInsn(Opcodes.DSTORE, forDoubleVisitor.i);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE);
// expression
adapter.visitLabel(forDoubleVisitor.beforeExpr);
int i=forDoubleVisitor.i;
adapter.loadLocal(dirPlus);
Label l1 = new Label();
adapter.visitJumpInsn(Opcodes.IFEQ, l1);
div=new DecisionDoubleVisitor();
div.visitBegin();
adapter.visitVarInsn(Opcodes.DLOAD, i);
div.visitLTE();
adapter.loadLocal(to);
div.visitEnd(bc);
Label l2 = new Label();
adapter.visitJumpInsn(Opcodes.GOTO, l2);
adapter.visitLabel(l1);
div=new DecisionDoubleVisitor();
div.visitBegin();
adapter.visitVarInsn(Opcodes.DLOAD, i);
div.visitGTE();
adapter.loadLocal(to);
div.visitEnd(bc);
adapter.visitLabel(l2);
forDoubleVisitor.visitAfterExpressionBeginBody(adapter);
//adapter.loadLocal(index);
//adapter.visitVarInsn(Opcodes.DLOAD, i);
//adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE);
getBody().writeOut(bc);
forDoubleVisitor.visitEndBody(bc,getEnd());
////// set i after usage
//adapter.loadLocal(index);
//adapter.visitVarInsn(Opcodes.DLOAD, i);
//adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE);
adapter.visitLabel(ifEnd);
}
/**
* write out list loop
* @param adapter
* @throws TemplateException
*/
private void writeOutTypeListArray(BytecodeContext bc, boolean isArray) throws BytecodeException {
ForVisitor forVisitor = new ForVisitor();
loopVisitor=forVisitor;
GeneratorAdapter adapter = bc.getAdapter();
//List.listToArrayRemoveEmpty("", 'c')
int array = adapter.newLocal(Types.ARRAY);
int len = adapter.newLocal(Types.INT_VALUE);
if(isArray) {
getAttribute("array").getValue().writeOut(bc, Expression.MODE_REF);
}
else {
// array=List.listToArrayRemoveEmpty(list, delimter)
getAttribute("list").getValue().writeOut(bc, Expression.MODE_REF);
if(containsAttribute("delimiters")) {
getAttribute("delimiters").getValue().writeOut(bc, Expression.MODE_REF);
adapter.invokeStatic(Types.LIST_UTIL, LIST_TO_ARRAY_REMOVE_EMPTY_SS);
}
else {
adapter.visitIntInsn(Opcodes.BIPUSH, 44);// ','
//adapter.push(',');
adapter.invokeStatic(Types.LIST_UTIL, LIST_TO_ARRAY_REMOVE_EMPTY_SC);
}
}
adapter.storeLocal(array);
// int len=array.size();
adapter.loadLocal(array);
adapter.invokeInterface(Types.ARRAY, SIZE);
adapter.storeLocal(len);
//VariableInterpreter.getVariableReference(pc,Caster.toString(index));
Attribute attrIndex = getAttribute("index");
int index = -1;
if(attrIndex!=null) {
index = adapter.newLocal(Types.VARIABLE_REFERENCE);
adapter.loadArg(0);
attrIndex.getValue().writeOut(bc, Expression.MODE_REF);
adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
adapter.storeLocal(index);
}
//VariableInterpreter.getVariableReference(pc,Caster.toString(item));
Attribute attrItem = getAttribute("item");
int item = -1;
if(attrItem!=null) {
item = adapter.newLocal(Types.VARIABLE_REFERENCE);
adapter.loadArg(0);
attrItem.getValue().writeOut(bc, Expression.MODE_REF);
adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE);
adapter.storeLocal(item);
}
int obj=0;
if(isArray)obj=adapter.newLocal(Types.OBJECT);
// for(int i=1;i<=len;i++) {
int i = forVisitor.visitBegin(adapter, 1, false);
// index.set(pc, list.get(i));
if(isArray) {
// value
adapter.loadLocal(array);
adapter.visitVarInsn(Opcodes.ILOAD, i);
ASMConstants.NULL(adapter);
adapter.invokeInterface(Types.ARRAY, GET);
adapter.dup();
adapter.storeLocal(obj);
Label endIf=new Label();
//adapter.loadLocal(obj);
adapter.visitJumpInsn(Opcodes.IFNONNULL, endIf);
adapter.goTo(forVisitor.getContinueLabel());
adapter.visitLabel(endIf);
if(item==-1) adapter.loadLocal(index);
else adapter.loadLocal(item);
adapter.loadArg(0);
adapter.loadLocal(obj);
}
else {
if(item==-1) adapter.loadLocal(index);
else adapter.loadLocal(item);
adapter.loadArg(0);
adapter.loadLocal(array);
adapter.visitVarInsn(Opcodes.ILOAD, i);
adapter.invokeInterface(Types.ARRAY, GETE);
}
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
adapter.pop();
// key
if(index!=-1 && item!=-1) {
adapter.loadLocal(index);
adapter.loadArg(0);
adapter.visitVarInsn(Opcodes.ILOAD, i);
adapter.cast(Types.INT_VALUE,Types.DOUBLE_VALUE);
adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DOUBLE[Methods_Caster.DOUBLE]);
adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET);
adapter.pop();
}
getBody().writeOut(bc);
forVisitor.visitEnd(bc, len, true,getStart());
}
/* *
* write out query loop
* @param adapter
* @throws TemplateException
* /
private void writeOutTypeQuery(BytecodeContext bc) throws BytecodeException {
ForConditionIntVisitor forConditionVisitor = new ForConditionIntVisitor();// TODO replace with ForIntVisitor
loopVisitor=forConditionVisitor;
final GeneratorAdapter adapter = bc.getAdapter();
// railo.runtime.type.Query query=pc.getQuery(@query);
final int query=adapter.newLocal(Types.QUERY);
adapter.loadArg(0);
Expression val = getAttribute("query").getValue();
val.writeOut(bc, Expression.MODE_REF);
if(val instanceof LitString)
adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_QUERY_STRING);
else
adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_QUERY_OBJ);
//adapter.dup();
adapter.storeLocal(query);
//int queryImpl = adapter.newLocal(Types.QUERY_IMPL);
//adapter.checkCast(Types.QUERY_IMPL);
//adapter.storeLocal(queryImpl);
// int startAt=query.getCurrentrow();
final int startAt=adapter.newLocal(Types.INT_VALUE);
adapter.loadLocal(query);
adapter.loadArg(0);
adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID);
adapter.invokeInterface(Types.QUERY, GET_CURRENTROW_1);
adapter.storeLocal(startAt);
// startrow
int start=adapter.newLocal(Types.INT_VALUE);
Attribute attrStartRow = getAttribute("startrow");
if(attrStartRow!=null){
//railo.runtime.util.NumberRange.range(@startrow,1)
attrStartRow.getValue().writeOut(bc, Expression.MODE_VALUE);
adapter.push(1d);
adapter.invokeStatic(Types.NUMBER_RANGE, RANGE);
adapter.visitInsn(Opcodes.D2I);
}
else {
adapter.push(1);
}
adapter.storeLocal(start);
// endrow
int end=adapter.newLocal(Types.INT_VALUE);
Attribute attrEndRow = getAttribute("endrow");
if(attrEndRow!=null){
attrEndRow.getValue().writeOut(bc, Expression.MODE_VALUE);
adapter.visitInsn(Opcodes.D2I);
adapter.storeLocal(end);
}
// pc.us().addQuery(query);
adapter.loadArg(0);
adapter.invokeVirtual(Types.PAGE_CONTEXT, US);
adapter.loadLocal(query);
adapter.invokeInterface(UNDEFINED, ADD_QUERY);
// try
TryFinallyVisitor tfv=new TryFinallyVisitor(new OnFinally() {
public void writeOut(BytecodeContext bc) {
//GeneratorAdapter ga = bc.getAdapter();
// pc.us().removeCollection();
adapter.loadArg(0);
adapter.invokeVirtual(Types.PAGE_CONTEXT, US);
adapter.invokeInterface(UNDEFINED, REMOVE_QUERY);
// query.go(startAt);
adapter.loadLocal(query);
adapter.loadLocal(startAt);
adapter.loadArg(0);
adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID);
adapter.invokeInterface(Types.QUERY, GO);
adapter.pop();
}
});
tfv.visitTryBegin(bc);
// For
int i=forConditionVisitor.visitBegin(adapter, start, true);
getBody().writeOut(bc);
forConditionVisitor.visitEndBeforeCondition(bc,1,false,getStart());
// && i<=endrow
if(attrEndRow!=null){
AndVisitor av=new AndVisitor();
av.visitBegin();
adapter.loadLocal(query);
adapter.visitVarInsn(Opcodes.ILOAD, i);
adapter.loadArg(0);
adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID);
adapter.invokeInterface(Types.QUERY, GO);
av.visitMiddle(bc);
//LitBoolean.TRUE.writeOut(bc, Expression.MODE_VALUE);
DecisionIntVisitor dv=new DecisionIntVisitor();
dv.visitBegin();
adapter.visitVarInsn(Opcodes.ILOAD, i);
dv.visitLTE();
adapter.loadLocal(end);
dv.visitEnd(bc);
av.visitEnd(bc);
}
else {
adapter.loadLocal(query);
adapter.visitVarInsn(Opcodes.ILOAD, i);
adapter.loadArg(0);
adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID);
adapter.invokeInterface(Types.QUERY, GO);
}
forConditionVisitor.visitEndAfterCondition(bc);
// Finally
tfv.visitTryEnd(bc);
}*/
/**
* @see railo.transformer.bytecode.statement.FlowControl#getBreakLabel()
*/
public Label getBreakLabel() {
return loopVisitor.getBreakLabel();
}
/**
* @see railo.transformer.bytecode.statement.FlowControl#getContinueLabel()
*/
public Label getContinueLabel() {
return loopVisitor.getContinueLabel();
}
@Override
public short getType() {
return TAG_LOOP;
}
public void setLoopVisitor(LoopVisitor loopVisitor) {
this.loopVisitor=loopVisitor;
}
@Override
public FlowControlFinal getFlowControlFinal() {
return null;
}
public void setLabel(String label) {
this.label=label;
}
@Override
public String getLabel() {
return label;
}
}