1 4 package gnu.kawa.reflect; 5 import gnu.expr.*; 6 import gnu.bytecode.*; 7 import gnu.mapping.*; 8 9 17 18 public class TypeSwitch extends MethodProc implements CanInline, Inlineable 19 { 20 public static final TypeSwitch typeSwitch = new TypeSwitch("typeswitch"); 21 22 public TypeSwitch(String name) 23 { 24 setName(name); 25 } 26 27 public int numArgs() { return 0xfffff002; } 28 29 public void apply (CallContext ctx) throws Throwable 30 { 31 Object [] args = ctx.getArgs(); 32 Object selector = args[0]; 33 int n = args.length-1; 34 for (int i = 1; i < n; i++) 35 { 36 MethodProc caseProc = (MethodProc) args[i]; 37 int m = caseProc.match1(selector, ctx); 38 if (m >= 0) 39 return; 40 } 41 Procedure defaultProc = (Procedure) args[n]; 42 defaultProc.check1(selector, ctx); 43 } 44 45 public Expression inline (ApplyExp exp, ExpWalker walker) 46 { 47 Expression[] args = exp.getArgs(); 48 for (int i = 1; i < args.length; i++) 49 { 50 if (args[i] instanceof LambdaExp) 51 { 52 LambdaExp lexp = (LambdaExp) args[i]; 53 lexp.setInlineOnly(true); 54 lexp.returnContinuation = exp; 55 } 56 } 57 return exp; 58 } 59 60 public void compile (ApplyExp exp, Compilation comp, Target target) 61 { 62 Expression[] args = exp.getArgs(); 63 64 CodeAttr code = comp.getCode(); 65 code.pushScope(); 66 Variable selector = code.addLocal(Type.pointer_type); 67 args[0].compile(comp, Target.pushObject); 68 code.emitStore(selector); 69 70 for (int i = 1; i < args.length - 1; i++) 71 { 72 if (i > 1) 73 code.emitElse(); 74 75 if (args[i] instanceof LambdaExp) 76 { 77 LambdaExp lambda = (LambdaExp) args[i]; 78 Declaration param = lambda.firstDecl(); 79 Type type = param.getType(); 80 param.allocateVariable(code); 81 82 if (type instanceof TypeValue) 83 ((TypeValue) type).emitTestIf(selector, param, comp); 84 else 85 { 86 code.emitLoad(selector); 87 type.emitIsInstance(code); 88 code.emitIfIntNotZero(); 89 90 code.emitLoad(selector); 91 param.compileStore(comp); 92 } 93 lambda.allocChildClasses(comp); 94 lambda.body.compileWithPosition(comp, target); 95 } 96 else 97 { 98 throw new Error ("not implemented: typeswitch arg not LambdaExp"); 99 } 100 } 101 int i = args.length - 2; 102 if (i > 0) 103 code.emitElse(); 104 LambdaExp lambda = (LambdaExp) args[args.length - 1]; 105 lambda.allocChildClasses(comp); 106 lambda.body.compileWithPosition(comp, target); while (--i >= 0) 108 code.emitFi(); 109 110 code.popScope(); 111 } 112 113 114 public Type getReturnType (Expression[] args) 115 { 116 return Type.pointer_type; 117 } 118 } 119 | Popular Tags |