You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JvstTypeChecker.java 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later.
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package javassist.compiler;
  16. import javassist.*;
  17. import javassist.compiler.ast.*;
  18. /* Type checker accepting extended Java syntax for Javassist.
  19. */
  20. public class JvstTypeChecker extends TypeChecker {
  21. private JvstCodeGen codeGen;
  22. public JvstTypeChecker(CtClass cc, ClassPool cp, JvstCodeGen gen) {
  23. super(cc, cp);
  24. codeGen = gen;
  25. }
  26. /* If the type of the expression compiled last is void,
  27. * add ACONST_NULL and change exprType, arrayDim, className.
  28. */
  29. public void addNullIfVoid() {
  30. if (exprType == VOID) {
  31. exprType = CLASS;
  32. arrayDim = 0;
  33. className = jvmJavaLangObject;
  34. }
  35. }
  36. /* To support $args, $sig, and $type.
  37. * $args is an array of parameter list.
  38. */
  39. public void atMember(Member mem) throws CompileError {
  40. String name = mem.get();
  41. if (name.equals(codeGen.paramArrayName)) {
  42. exprType = CLASS;
  43. arrayDim = 1;
  44. className = jvmJavaLangObject;
  45. }
  46. else if (name.equals(JvstCodeGen.sigName)) {
  47. exprType = CLASS;
  48. arrayDim = 1;
  49. className = "java/lang/Class";
  50. }
  51. else if (name.equals(JvstCodeGen.dollarTypeName)
  52. || name.equals(JvstCodeGen.clazzName)) {
  53. exprType = CLASS;
  54. arrayDim = 0;
  55. className = "java/lang/Class";
  56. }
  57. else
  58. super.atMember(mem);
  59. }
  60. protected void atFieldAssign(Expr expr, int op, ASTree left, ASTree right)
  61. throws CompileError
  62. {
  63. if (left instanceof Member
  64. && ((Member)left).get().equals(codeGen.paramArrayName)) {
  65. right.accept(this);
  66. CtClass[] params = codeGen.paramTypeList;
  67. if (params == null)
  68. return;
  69. int n = params.length;
  70. for (int i = 0; i < n; ++i)
  71. compileUnwrapValue(params[i]);
  72. }
  73. else
  74. super.atFieldAssign(expr, op, left, right);
  75. }
  76. public void atCastExpr(CastExpr expr) throws CompileError {
  77. ASTList classname = expr.getClassName();
  78. if (classname != null && expr.getArrayDim() == 0) {
  79. ASTree p = classname.head();
  80. if (p instanceof Symbol && classname.tail() == null) {
  81. String typename = ((Symbol)p).get();
  82. if (typename.equals(codeGen.returnCastName)) {
  83. atCastToRtype(expr);
  84. return;
  85. }
  86. else if (typename.equals(JvstCodeGen.wrapperCastName)) {
  87. atCastToWrapper(expr);
  88. return;
  89. }
  90. }
  91. }
  92. super.atCastExpr(expr);
  93. }
  94. /**
  95. * Inserts a cast operator to the return type.
  96. * If the return type is void, this does nothing.
  97. */
  98. protected void atCastToRtype(CastExpr expr) throws CompileError {
  99. CtClass returnType = codeGen.returnType;
  100. expr.getOprand().accept(this);
  101. if (exprType == VOID || CodeGen.isRefType(exprType) || arrayDim > 0)
  102. compileUnwrapValue(returnType);
  103. else if (returnType instanceof CtPrimitiveType) {
  104. CtPrimitiveType pt = (CtPrimitiveType)returnType;
  105. int destType = MemberResolver.descToType(pt.getDescriptor());
  106. exprType = destType;
  107. arrayDim = 0;
  108. className = null;
  109. }
  110. }
  111. protected void atCastToWrapper(CastExpr expr) throws CompileError {
  112. expr.getOprand().accept(this);
  113. if (CodeGen.isRefType(exprType) || arrayDim > 0)
  114. return; // Object type. do nothing.
  115. CtClass clazz = resolver.lookupClass(exprType, arrayDim, className);
  116. if (clazz instanceof CtPrimitiveType) {
  117. exprType = CLASS;
  118. arrayDim = 0;
  119. className = jvmJavaLangObject;
  120. }
  121. }
  122. /* Delegates to a ProcHandler object if the method call is
  123. * $proceed(). It may process $cflow().
  124. */
  125. public void atCallExpr(CallExpr expr) throws CompileError {
  126. ASTree method = expr.oprand1();
  127. if (method instanceof Member) {
  128. String name = ((Member)method).get();
  129. if (codeGen.procHandler != null
  130. && name.equals(codeGen.proceedName)) {
  131. codeGen.procHandler.setReturnType(this,
  132. (ASTList)expr.oprand2());
  133. return;
  134. }
  135. else if (name.equals(JvstCodeGen.cflowName)) {
  136. atCflow((ASTList)expr.oprand2());
  137. return;
  138. }
  139. }
  140. super.atCallExpr(expr);
  141. }
  142. /* To support $cflow().
  143. */
  144. protected void atCflow(ASTList cname) throws CompileError {
  145. exprType = INT;
  146. arrayDim = 0;
  147. className = null;
  148. }
  149. /* To support $$. ($$) is equivalent to ($1, ..., $n).
  150. * It can be used only as a parameter list of method call.
  151. */
  152. public boolean isParamListName(ASTList args) {
  153. if (codeGen.paramTypeList != null
  154. && args != null && args.tail() == null) {
  155. ASTree left = args.head();
  156. return (left instanceof Member
  157. && ((Member)left).get().equals(codeGen.paramListName));
  158. }
  159. else
  160. return false;
  161. }
  162. public int getMethodArgsLength(ASTList args) {
  163. String pname = codeGen.paramListName;
  164. int n = 0;
  165. while (args != null) {
  166. ASTree a = args.head();
  167. if (a instanceof Member && ((Member)a).get().equals(pname)) {
  168. if (codeGen.paramTypeList != null)
  169. n += codeGen.paramTypeList.length;
  170. }
  171. else
  172. ++n;
  173. args = args.tail();
  174. }
  175. return n;
  176. }
  177. public void atMethodArgs(ASTList args, int[] types, int[] dims,
  178. String[] cnames) throws CompileError {
  179. CtClass[] params = codeGen.paramTypeList;
  180. String pname = codeGen.paramListName;
  181. int i = 0;
  182. while (args != null) {
  183. ASTree a = args.head();
  184. if (a instanceof Member && ((Member)a).get().equals(pname)) {
  185. if (params != null) {
  186. int n = params.length;
  187. for (int k = 0; k < n; ++k) {
  188. CtClass p = params[k];
  189. setType(p);
  190. types[i] = exprType;
  191. dims[i] = arrayDim;
  192. cnames[i] = className;
  193. ++i;
  194. }
  195. }
  196. }
  197. else {
  198. a.accept(this);
  199. types[i] = exprType;
  200. dims[i] = arrayDim;
  201. cnames[i] = className;
  202. ++i;
  203. }
  204. args = args.tail();
  205. }
  206. }
  207. /* called by Javac#recordSpecialProceed().
  208. */
  209. void compileInvokeSpecial(ASTree target, String classname,
  210. String methodname, String descriptor,
  211. ASTList args)
  212. throws CompileError
  213. {
  214. target.accept(this);
  215. int nargs = getMethodArgsLength(args);
  216. atMethodArgs(args, new int[nargs], new int[nargs],
  217. new String[nargs]);
  218. setReturnType(descriptor);
  219. addNullIfVoid();
  220. }
  221. protected void compileUnwrapValue(CtClass type) throws CompileError
  222. {
  223. if (type == CtClass.voidType)
  224. addNullIfVoid();
  225. else
  226. setType(type);
  227. }
  228. /* Sets exprType, arrayDim, and className;
  229. * If type is void, then this method does nothing.
  230. */
  231. public void setType(CtClass type) throws CompileError {
  232. setType(type, 0);
  233. }
  234. private void setType(CtClass type, int dim) throws CompileError {
  235. if (type.isPrimitive()) {
  236. CtPrimitiveType pt = (CtPrimitiveType)type;
  237. exprType = MemberResolver.descToType(pt.getDescriptor());
  238. arrayDim = dim;
  239. className = null;
  240. }
  241. else if (type.isArray())
  242. try {
  243. setType(type.getComponentType(), dim + 1);
  244. }
  245. catch (NotFoundException e) {
  246. throw new CompileError("undefined type: " + type.getName());
  247. }
  248. else {
  249. exprType = CLASS;
  250. arrayDim = dim;
  251. className = MemberResolver.javaToJvmName(type.getName());
  252. }
  253. }
  254. }