KickJava   Java API By Example, From Geeks To Geeks.

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


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.JAbsentArrayDimension;
20 import com.google.gwt.dev.jjs.ast.JArrayRef;
21 import com.google.gwt.dev.jjs.ast.JArrayType;
22 import com.google.gwt.dev.jjs.ast.JBinaryOperation;
23 import com.google.gwt.dev.jjs.ast.JBinaryOperator;
24 import com.google.gwt.dev.jjs.ast.JExpression;
25 import com.google.gwt.dev.jjs.ast.JLiteral;
26 import com.google.gwt.dev.jjs.ast.JMethod;
27 import com.google.gwt.dev.jjs.ast.JMethodCall;
28 import com.google.gwt.dev.jjs.ast.JModVisitor;
29 import com.google.gwt.dev.jjs.ast.JNewArray;
30 import com.google.gwt.dev.jjs.ast.JNullType;
31 import com.google.gwt.dev.jjs.ast.JProgram;
32 import com.google.gwt.dev.jjs.ast.JReferenceType;
33 import com.google.gwt.dev.jjs.ast.JType;
34 import com.google.gwt.dev.jjs.ast.js.JsonArray;
35
36 /**
37  * Replace array accesses and instantiations with calls to the Array class.
38  * Depends on {@link com.google.gwt.dev.jjs.impl.CompoundAssignmentNormalizer}
39  * and {@link com.google.gwt.dev.jjs.impl.CastNormalizer} having already run.
40  */

41 public class ArrayNormalizer {
42
43   private class ArrayVisitor extends JModVisitor {
44
45     // @Override
46
public void endVisit(JBinaryOperation x, Context ctx) {
47       if (x.getOp() == JBinaryOperator.ASG && x.getLhs() instanceof JArrayRef) {
48         JArrayRef arrayRef = (JArrayRef) x.getLhs();
49         if (arrayRef.getType() instanceof JNullType) {
50           // will generate a null pointer exception instead
51
return;
52         }
53         JArrayType arrayType = (JArrayType) arrayRef.getInstance().getType();
54         JType elementType = arrayType.getElementType();
55
56         // see if we need to do a checked store
57
// primitives and (effectively) final are statically correct
58
if (elementType instanceof JReferenceType
59             && (!((JReferenceType) elementType).isFinal())
60             || elementType != x.getRhs().getType()) {
61           // replace this assignment with a call to setCheck()
62

63           JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
64               setCheckMethod);
65           call.getArgs().add(arrayRef.getInstance());
66           call.getArgs().add(arrayRef.getIndexExpr());
67           call.getArgs().add(x.getRhs());
68           ctx.replaceMe(call);
69         }
70       }
71     }
72
73     // @Override
74
public void endVisit(JNewArray x, Context ctx) {
75       JArrayType type = x.getArrayType();
76       JLiteral litTypeName = program.getLiteralString(calcClassName(type));
77
78       if (x.initializers != null) {
79         processInitializers(x, ctx, type, litTypeName);
80       } else {
81         processDims(x, ctx, type, litTypeName);
82       }
83     }
84
85     private char[] calcClassName(JArrayType type) {
86       String JavaDoc leafName = type.getLeafType().getJsniSignatureName();
87       leafName = leafName.replace('/', '.');
88       int leafLength = leafName.length();
89       int nDims = type.getDims();
90       char[] className = new char[leafLength + nDims];
91       for (int i = 0; i < nDims; ++i) {
92         className[i] = '[';
93       }
94
95       leafName.getChars(0, leafLength, className, nDims);
96       return className;
97     }
98
99     private void processDims(JNewArray x, Context ctx, JArrayType arrayType,
100         JLiteral litTypeName) {
101       // override the type of the called method with the array's type
102
JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
103           initDims, arrayType);
104       JsonArray typeIdList = new JsonArray(program);
105       JsonArray queryIdList = new JsonArray(program);
106       JsonArray dimList = new JsonArray(program);
107       JType leafType = arrayType.getLeafType();
108       int outstandingDims = arrayType.getDims();
109       for (int i = 0; i < x.dims.size(); ++i) {
110         JExpression dim = (JExpression) x.dims.get(i);
111         if (dim instanceof JAbsentArrayDimension) {
112           break;
113         }
114
115         /*
116          * For each non-empty dimension, reduce the number of dims on the end
117          * type.
118          *
119          * new int[2][ ][ ]->int[][]
120          *
121          * new int[2][3][ ]->int[]
122          *
123          * new int[2][3][4]->int
124          *
125          */

126         JArrayType cur = program.getTypeArray(leafType, outstandingDims--);
127         JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(cur));
128         typeIdList.exprs.add(typeIdLit);
129         JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(cur));
130         queryIdList.exprs.add(queryIdLit);
131         dimList.exprs.add(dim);
132       }
133       JType targetType = leafType;
134       if (outstandingDims > 0) {
135         targetType = program.getTypeArray(targetType, outstandingDims);
136       }
137
138       call.getArgs().add(litTypeName);
139       call.getArgs().add(typeIdList);
140       call.getArgs().add(queryIdList);
141       call.getArgs().add(dimList);
142       call.getArgs().add(targetType.getDefaultValue());
143       ctx.replaceMe(call);
144     }
145
146     private void processInitializers(JNewArray x, Context ctx,
147         JArrayType arrayType, JLiteral litTypeName) {
148       // override the type of the called method with the array's type
149
JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
150           initValues, arrayType);
151       JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(arrayType));
152       JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(arrayType));
153       JsonArray initList = new JsonArray(program);
154       for (int i = 0; i < x.initializers.size(); ++i) {
155         initList.exprs.add(x.initializers.get(i));
156       }
157       call.getArgs().add(litTypeName);
158       call.getArgs().add(typeIdLit);
159       call.getArgs().add(queryIdLit);
160       call.getArgs().add(initList);
161       ctx.replaceMe(call);
162     }
163
164     private int tryGetQueryId(JArrayType type) {
165       JType elementType = type.getElementType();
166       int leafTypeId = -1;
167       if (elementType instanceof JReferenceType) {
168         leafTypeId = program.getQueryId((JReferenceType) elementType);
169       }
170       return leafTypeId;
171     }
172   }
173
174   public static void exec(JProgram program) {
175     new ArrayNormalizer(program).execImpl();
176   }
177
178   private final JMethod initDims;
179   private final JMethod initValues;
180   private final JProgram program;
181   private final JMethod setCheckMethod;
182
183   private ArrayNormalizer(JProgram program) {
184     this.program = program;
185     setCheckMethod = program.getSpecialMethod("Array.setCheck");
186     initDims = program.getSpecialMethod("Array.initDims");
187     initValues = program.getSpecialMethod("Array.initValues");
188   }
189
190   private void execImpl() {
191     ArrayVisitor visitor = new ArrayVisitor();
192     visitor.accept(program);
193   }
194
195 }
196
Popular Tags