001 package railo.transformer.bytecode.statement; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 006 import org.objectweb.asm.Label; 007 import org.objectweb.asm.Type; 008 import org.objectweb.asm.commons.GeneratorAdapter; 009 import org.objectweb.asm.commons.Method; 010 011 import railo.transformer.bytecode.Body; 012 import railo.transformer.bytecode.BytecodeContext; 013 import railo.transformer.bytecode.BytecodeException; 014 import railo.transformer.bytecode.expression.Expression; 015 import railo.transformer.bytecode.util.Types; 016 017 public final class Switch extends StatementBase implements FlowControl,HasBodies { 018 019 private static final Type ARRAY_IMPL=Type.getType(railo.runtime.type.ArrayImpl.class); 020 021 // Object append(Object o) 022 private static final Method APPEND = new Method( 023 "append", 024 Types.OBJECT, 025 new Type[]{Types.OBJECT} 026 ); 027 028 private static final Method INIT = new Method( 029 "<init>", 030 Types.VOID, 031 new Type[]{} 032 ); 033 034 // int find(Array array, Object object) 035 private static final Method FIND = new Method( 036 "find", 037 Types.INT_VALUE, 038 new Type[]{Types.ARRAY,Types.OBJECT} 039 ); 040 041 private ArrayList cases=new ArrayList(); 042 private Body defaultCase; 043 private Expression expr; 044 045 private NativeSwitch ns; 046 047 048 public Switch(Expression expr,int startline,int endline) { 049 super(startline, endline); 050 this.expr=expr; 051 } 052 053 public void addCase(Expression expr, Body body) { 054 addCase(expr, body, -1, -1); 055 } 056 public void addCase(Expression expr, Body body,int startline,int endline) { 057 //if(cases==null) cases=new ArrayList(); 058 cases.add(new Case(expr,body,startline,endline)); 059 body.setParent(this); 060 } 061 public void setDefaultCase(Body body) { 062 defaultCase=body; 063 body.setParent(this); 064 } 065 066 067 public final class Case { 068 private Expression expression; 069 private Body body; 070 private int startline; 071 private int endline; 072 073 public Case(Expression expression, Body body,int startline,int endline) { 074 this.expression=expression; 075 this.body=body; 076 this.startline=startline; 077 this.endline=endline; 078 } 079 } 080 081 /** 082 * @see railo.transformer.bytecode.statement.StatementBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter) 083 */ 084 public void _writeOut(BytecodeContext bc) throws BytecodeException { 085 GeneratorAdapter adapter = bc.getAdapter(); 086 087 // Array cases=new ArrayImpl(); 088 int array=adapter.newLocal(Types.ARRAY); 089 adapter.newInstance(ARRAY_IMPL); 090 adapter.dup(); 091 adapter.invokeConstructor(ARRAY_IMPL, INIT); 092 093 adapter.storeLocal(array); 094 095 // cases.append(case.value); 096 Iterator it = cases.iterator(); 097 Case c; 098 while(it.hasNext()) { 099 c=(Case) it.next(); 100 101 102 adapter.loadLocal(array); 103 c.expression.writeOut(bc, Expression.MODE_REF); 104 adapter.invokeVirtual(ARRAY_IMPL, APPEND); 105 adapter.pop(); 106 } 107 108 // int result=ArrayUtil.find(array,expression); 109 int result=adapter.newLocal(Types.INT_VALUE); 110 adapter.loadLocal(array); 111 expr.writeOut(bc, Expression.MODE_REF); 112 adapter.invokeStatic(Types.ARRAY_UTIL, FIND); 113 adapter.storeLocal(result); 114 115 // switch(result) 116 ns=new NativeSwitch(result,NativeSwitch.LOCAL_REF,getStartLine(),getEndLine()); 117 it = cases.iterator(); 118 int count=1; 119 while(it.hasNext()) { 120 c=(Case) it.next(); 121 ns.addCase(count++, c.body,c.startline,c.endline,false); 122 } 123 if(defaultCase!=null)ns.addDefaultCase(defaultCase); 124 125 ns.writeOut(bc); 126 127 } 128 129 /** 130 * 131 * @see railo.transformer.bytecode.statement.FlowControl#getBreakLabel() 132 */ 133 public Label getBreakLabel() { 134 return ns.getBreakLabel(); 135 } 136 137 /** 138 * 139 * @see railo.transformer.bytecode.statement.FlowControl#getContinueLabel() 140 */ 141 public Label getContinueLabel() { 142 return ns.getContinueLabel(); 143 } 144 145 146 /** 147 * @see railo.transformer.bytecode.statement.HasBodies#getBodies() 148 */ 149 public Body[] getBodies() { 150 if(cases==null) { 151 if(defaultCase!=null) return new Body[]{defaultCase}; 152 return new Body[]{}; 153 } 154 155 int len=cases.size(),count=0; 156 if(defaultCase!=null)len++; 157 Body[] bodies=new Body[len]; 158 Case c; 159 Iterator it = cases.iterator(); 160 while(it.hasNext()) { 161 c=(Case) it.next(); 162 bodies[count++]=c.body; 163 } 164 if(defaultCase!=null)bodies[count++]=defaultCase; 165 166 return bodies; 167 } 168 169 }