Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

JvstTypeChecker.java 9.0KB

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