KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > jjs > impl > JavaScriptObjectCaster


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.dev.jjs.impl;
17
18 import com.google.gwt.dev.jjs.ast.Context;
19 import com.google.gwt.dev.jjs.ast.JArrayRef;
20 import com.google.gwt.dev.jjs.ast.JBinaryOperation;
21 import com.google.gwt.dev.jjs.ast.JCastOperation;
22 import com.google.gwt.dev.jjs.ast.JConditional;
23 import com.google.gwt.dev.jjs.ast.JExpression;
24 import com.google.gwt.dev.jjs.ast.JLocalDeclarationStatement;
25 import com.google.gwt.dev.jjs.ast.JMethod;
26 import com.google.gwt.dev.jjs.ast.JMethodCall;
27 import com.google.gwt.dev.jjs.ast.JModVisitor;
28 import com.google.gwt.dev.jjs.ast.JParameter;
29 import com.google.gwt.dev.jjs.ast.JProgram;
30 import com.google.gwt.dev.jjs.ast.JReferenceType;
31 import com.google.gwt.dev.jjs.ast.JReturnStatement;
32 import com.google.gwt.dev.jjs.ast.JType;
33
34 /**
35  * Synthesize casts for JavaScriptObject types in cases where dynamic type
36  * information may be necessary.
37  */

38 public class JavaScriptObjectCaster {
39
40   /**
41    * Synthesize casts from JavaScriptObjects to trigger wrapping.
42    */

43   private class AssignmentVisitor extends JModVisitor {
44
45     private JMethod currentMethod;
46
47     // @Override
48
public void endVisit(JBinaryOperation x, Context ctx) {
49       if (x.isAssignment()) {
50         JType lhsType = x.getLhs().getType();
51         JExpression newRhs = checkAndReplaceJso(x.getRhs(), lhsType);
52         if (newRhs == x.getRhs()) {
53           // There's another case to check: if we have an array store that may
54
// trigger a type check, we need to wrap the rhs.
55
if (x.getLhs() instanceof JArrayRef) {
56             newRhs = checkAndReplaceJsoArrayStore(newRhs, lhsType);
57           }
58         }
59         if (newRhs != x.getRhs()) {
60           JBinaryOperation asg = new JBinaryOperation(program,
61               x.getSourceInfo(), lhsType, x.getOp(), x.getLhs(), newRhs);
62           ctx.replaceMe(asg);
63         }
64       }
65     }
66
67     // @Override
68
public void endVisit(JConditional x, Context ctx) {
69       JExpression newThen = checkAndReplaceJso(x.getThenExpr(), x.getType());
70       JExpression newElse = checkAndReplaceJso(x.getElseExpr(), x.getType());
71       if (newThen != x.getThenExpr() || newElse != x.getElseExpr()) {
72         JConditional newCond = new JConditional(program, x.getSourceInfo(),
73             x.getType(), x.getIfTest(), newThen, newElse);
74         ctx.replaceMe(newCond);
75       }
76     }
77
78     // @Override
79
public void endVisit(JLocalDeclarationStatement x, Context ctx) {
80       JExpression newInst = x.getInitializer();
81       if (newInst != null) {
82         newInst = checkAndReplaceJso(newInst, x.getLocalRef().getType());
83         if (newInst != x.getInitializer()) {
84           JLocalDeclarationStatement newStmt = new JLocalDeclarationStatement(
85               program, x.getSourceInfo(), x.getLocalRef(), newInst);
86           ctx.replaceMe(newStmt);
87         }
88       }
89     }
90
91     // @Override
92
public void endVisit(JMethod x, Context ctx) {
93       currentMethod = null;
94     }
95
96     // @Override
97
public void endVisit(JMethodCall x, Context ctx) {
98       for (int i = 0; i < x.getTarget().params.size(); ++i) {
99         JParameter param = (JParameter) x.getTarget().params.get(i);
100         JExpression newArg = checkAndReplaceJso(
101             (JExpression) x.getArgs().get(i), param.getType());
102         x.getArgs().set(i, newArg);
103       }
104       if (!x.getTarget().isStatic()) {
105         // for polymorphic calls, force wrapping
106
JExpression newInst = checkAndReplaceJso(x.getInstance(),
107             program.getTypeJavaLangObject());
108         if (newInst != x.getInstance()) {
109           JMethodCall newCall = new JMethodCall(program, x.getSourceInfo(),
110               newInst, x.getTarget(), x.isStaticDispatchOnly());
111           newCall.getArgs().addAll(x.getArgs());
112           ctx.replaceMe(newCall);
113         }
114       }
115     }
116
117     // @Override
118
public void endVisit(JReturnStatement x, Context ctx) {
119       if (x.getExpr() != null) {
120         JExpression newExpr = checkAndReplaceJso(x.getExpr(),
121             currentMethod.getType());
122         if (newExpr != x.getExpr()) {
123           JReturnStatement newStmt = new JReturnStatement(program,
124               x.getSourceInfo(), newExpr);
125           ctx.replaceMe(newStmt);
126         }
127       }
128     }
129
130     // @Override
131
public boolean visit(JMethod x, Context ctx) {
132       currentMethod = x;
133       return true;
134     }
135
136     /**
137      * Wraps a JSO-typed argument if the target type is a different type.
138      */

139     private JExpression checkAndReplaceJso(JExpression arg, JType targetType) {
140       JType argType = arg.getType();
141       if (argType == targetType) {
142         return arg;
143       }
144       if (!(targetType instanceof JReferenceType)) {
145         return arg;
146       }
147       if (!program.isJavaScriptObject(argType)) {
148         return arg;
149       }
150       // Synthesize a cast to the arg type to force a wrap
151
JCastOperation cast = new JCastOperation(program, arg.getSourceInfo(),
152           argType, arg);
153       return cast;
154     }
155
156     /**
157      * Wraps a JSO-typed argument if the target array element type might
158      * generate an array store check.
159      */

160     private JExpression checkAndReplaceJsoArrayStore(JExpression arg,
161         JType targetType) {
162       if (!(targetType instanceof JReferenceType)) {
163         return arg;
164       }
165       if (((JReferenceType) targetType).isFinal()) {
166         return arg;
167       }
168       if (!program.isJavaScriptObject(arg.getType())) {
169         return arg;
170       }
171       // Synthesize a cast to the target type
172
JCastOperation cast = new JCastOperation(program, arg.getSourceInfo(),
173           targetType, arg);
174       return cast;
175     }
176   }
177
178   public static void exec(JProgram program) {
179     new JavaScriptObjectCaster(program).execImpl();
180   }
181
182   private final JProgram program;
183
184   private JavaScriptObjectCaster(JProgram program) {
185     this.program = program;
186   }
187
188   private void execImpl() {
189     AssignmentVisitor visitor = new AssignmentVisitor();
190     visitor.accept(program);
191   }
192
193 }
194
Popular Tags