KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > kawa > reflect > TypeSwitch


1 // Copyright (c) 2001 Per M.A. Bothner and Brainfood Inc.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.kawa.reflect;
5 import gnu.expr.*;
6 import gnu.bytecode.*;
7 import gnu.mapping.*;
8
9 /** Implement 'typeswitch' (as in XQuery) or 'typecase'.
10  * Usage: (typeswitch SELECTOR CASE-LAMBDA ... DEFAULT-LAMBDA)
11  * Each CASE-LAMBDA is a 1-argument MethodProc, while DEFAULT-LAMBDA
12  * is a 0-argument Procedure. Calls the first CASE-LAMBDA such that
13  * SELECTOR is a valid argument; if there is none, calls DEFAULT-LAMBDA.
14  * In the current implementation, all of CASE-LAMBDA and DEFAULT-LAMBDA
15  * must be LambdaExps, and the call must be inlined.
16  */

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 JavaDoc name)
23   {
24     setName(name);
25   }
26
27   public int numArgs() { return 0xfffff002; }
28
29   public void apply (CallContext ctx) throws Throwable JavaDoc
30   {
31     Object JavaDoc[] args = ctx.getArgs();
32     Object JavaDoc 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 JavaDoc("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); // FIXME target
107
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