1 4 package gnu.expr; 5 import gnu.bytecode.*; 6 import gnu.kawa.reflect.OccurrenceType; 7 8 11 12 public class ConsumerTarget extends Target 13 { 14 Variable consumer; 15 boolean isContextTarget; 16 17 public ConsumerTarget(Variable consumer) 18 { 19 this.consumer = consumer; 20 } 21 22 public Variable getConsumerVariable() { return consumer; } 23 24 25 public final boolean isContextTarget () { return isContextTarget; } 26 27 28 public static Target makeContextTarget (Compilation comp) 29 { 30 CodeAttr code = comp.getCode(); 31 comp.loadCallContext(); 32 code.emitGetField(Compilation.typeCallContext 33 .getDeclaredField("consumer")); 34 Scope scope = code.getCurrentScope(); 35 Variable result 36 = scope.addVariable(code, Compilation.typeConsumer, "$result"); 37 code.emitStore(result); 38 ConsumerTarget target = new ConsumerTarget(result); 39 target.isContextTarget = true; 40 return target; 41 } 42 43 44 public static void compileUsingConsumer(Expression exp, 45 Compilation comp, Target target) 46 { 47 if (target instanceof ConsumerTarget || target instanceof IgnoreTarget) 48 exp.compile(comp, target); 49 else 50 { 51 ClassType typeValues = Compilation.typeValues; 52 compileUsingConsumer(exp, comp, target, 53 typeValues.getDeclaredMethod("make", 0), 54 typeValues.getDeclaredMethod("canonicalize", 0)); 55 } 56 } 57 58 public static void compileUsingConsumer (Expression exp, Compilation comp, 59 Target target, 60 Method makeMethod, 61 Method resultMethod) 62 { 63 CodeAttr code = comp.getCode(); 64 Scope scope = code.pushScope(); 65 Type ctype; 66 if (makeMethod.getName() == "<init>") 67 { 68 ClassType cltype = makeMethod.getDeclaringClass(); 69 ctype = cltype; 70 code.emitNew(cltype); 71 code.emitDup(ctype); 72 code.emitInvoke(makeMethod); 73 } 74 else 75 { 76 ctype = makeMethod.getReturnType(); 77 code.emitInvokeStatic(makeMethod); 78 } 79 Variable consumer = scope.addVariable(code, ctype, null); 80 ConsumerTarget ctarget = new ConsumerTarget(consumer); 81 code.emitStore(consumer); 82 exp.compile(comp, ctarget); 83 code.emitLoad(consumer); 84 if (resultMethod != null) 85 code.emitInvoke(resultMethod); 86 code.popScope(); 87 target.compileFromStack(comp, resultMethod == null ? ctype 88 : resultMethod.getReturnType()); 89 } 90 91 92 public void compileFromStack(Compilation comp, Type stackType) 93 { 94 compileFromStack(comp, stackType, -1); 95 } 96 97 102 void compileFromStack(Compilation comp, 103 Type stackType, int consumerPushed) 104 { 105 CodeAttr code = comp.getCode(); 106 String methodName = null; 107 Method method = null; 108 boolean islong = false; 109 stackType = stackType.getImplementationType(); 110 char sig; 111 if (stackType instanceof PrimType) 112 { 113 sig = stackType.getSignature().charAt(0); 114 switch (sig) 115 { 116 case 'B': case 'S': case 'I': 117 methodName = "writeInt"; break; 118 case 'J': methodName = "writeLong"; islong = true; break; 119 case 'F': methodName = "writeFloat"; break; 120 case 'D': methodName = "writeDouble"; islong = true; break; 121 case 'C': methodName = "append"; break; 122 case 'Z': methodName = "writeBoolean"; break; 123 case 'V': return; 124 } 125 } 126 else 127 { 128 sig = '\0'; 129 if (consumerPushed == 1 || OccurrenceType.itemCountIsOne(stackType)) 130 methodName = "writeObject"; 131 else 132 { 133 method = (Compilation.typeValues 134 .getDeclaredMethod("writeValues", 2)); 135 code.emitLoad(consumer); 136 if (consumerPushed == 0) 137 code.emitSwap(); 138 code.emitInvokeStatic(method); 139 return; 140 } 141 } 142 if (consumerPushed >= 0) 143 ; 144 else if (islong) 145 { 146 code.pushScope(); 147 Variable temp = code.addLocal(stackType); 148 code.emitStore(temp); 149 code.emitLoad(consumer); 150 code.emitLoad(temp); 151 code.popScope(); 152 } 153 else 154 { 155 code.emitLoad(consumer); 156 code.emitSwap(); 157 } 158 if (method == null && methodName != null) 159 method = Compilation.typeConsumer.getDeclaredMethod(methodName, 1); 160 if (method != null) 161 code.emitInvokeInterface(method); 162 if (sig == 'C') 163 code.emitPop(1); } 165 166 public boolean compileWrite (Expression exp, Compilation comp) 167 { 168 Type stackType = exp.getType(); 169 Type implType = stackType.getImplementationType(); 170 if ((implType instanceof PrimType && ! implType.isVoid()) 171 || gnu.kawa.reflect.OccurrenceType.itemCountIsOne(implType)) 172 { 173 comp.getCode().emitLoad(this.consumer); 175 Target starget = StackTarget.getInstance(implType); 176 exp.compile(comp, starget); 177 compileFromStack(comp, implType, 1); 178 return true; 179 } 180 return false; 181 } 182 183 public Type getType() { return Compilation.scmSequenceType; } 184 } 185 | Popular Tags |