1 15 16 package javassist.compiler; 17 18 import javassist.CtClass; 19 import javassist.CtPrimitiveType; 20 import javassist.CtMember; 21 import javassist.CtField; 22 import javassist.CtBehavior; 23 import javassist.CtMethod; 24 import javassist.CtConstructor; 25 import javassist.CannotCompileException; 26 import javassist.Modifier; 27 import javassist.bytecode.Bytecode; 28 import javassist.bytecode.CodeAttribute; 29 import javassist.bytecode.LocalVariableAttribute; 30 import javassist.bytecode.Opcode; 31 import javassist.NotFoundException; 32 33 import javassist.compiler.ast.*; 34 35 public class Javac { 36 JvstCodeGen gen; 37 SymbolTable stable; 38 private Bytecode bytecode; 39 40 public static final String param0Name = "$0"; 41 public static final String resultVarName = "$_"; 42 public static final String proceedName = "$proceed"; 43 44 50 public Javac(CtClass thisClass) { 51 this(new Bytecode(thisClass.getClassFile2().getConstPool(), 0, 0), 52 thisClass); 53 } 54 55 63 public Javac(Bytecode b, CtClass thisClass) { 64 gen = new JvstCodeGen(b, thisClass, thisClass.getClassPool()); 65 stable = new SymbolTable(); 66 bytecode = b; 67 } 68 69 72 public Bytecode getBytecode() { return bytecode; } 73 74 86 public CtMember compile(String src) throws CompileError { 87 Parser p = new Parser(new Lex(src)); 88 ASTList mem = p.parseMember1(stable); 89 try { 90 if (mem instanceof FieldDecl) 91 return compileField((FieldDecl)mem); 92 else 93 return compileMethod(p, (MethodDecl)mem); 94 } 95 catch (CannotCompileException e) { 96 throw new CompileError(e.getMessage()); 97 } 98 } 99 100 public static class CtFieldWithInit extends CtField { 101 private ASTree init; 102 103 CtFieldWithInit(CtClass type, String name, CtClass declaring) 104 throws CannotCompileException 105 { 106 super(type, name, declaring); 107 init = null; 108 } 109 110 protected void setInit(ASTree i) { init = i; } 111 112 protected ASTree getInitAST() { 113 return init; 114 } 115 } 116 117 private CtField compileField(FieldDecl fd) 118 throws CompileError, CannotCompileException 119 { 120 CtFieldWithInit f; 121 Declarator d = fd.getDeclarator(); 122 f = new CtFieldWithInit(gen.resolver.lookupClass(d), 123 d.getVariable().get(), gen.getThisClass()); 124 f.setModifiers(MemberResolver.getModifiers(fd.getModifiers())); 125 if (fd.getInit() != null) 126 f.setInit(fd.getInit()); 127 128 return f; 129 } 130 131 private CtMember compileMethod(Parser p, MethodDecl md) 132 throws CompileError 133 { 134 int mod = MemberResolver.getModifiers(md.getModifiers()); 135 CtClass[] plist = gen.makeParamList(md); 136 CtClass[] tlist = gen.makeThrowsList(md); 137 recordParams(plist, Modifier.isStatic(mod)); 138 md = p.parseMethod2(stable, md); 139 try { 140 if (md.isConstructor()) { 141 CtConstructor cons = new CtConstructor(plist, 142 gen.getThisClass()); 143 cons.setModifiers(mod); 144 md.accept(gen); 145 cons.getMethodInfo().setCodeAttribute( 146 bytecode.toCodeAttribute()); 147 cons.setExceptionTypes(tlist); 148 return cons; 149 } 150 else { 151 Declarator r = md.getReturn(); 152 CtClass rtype = gen.resolver.lookupClass(r); 153 recordReturnType(rtype, false); 154 CtMethod method = new CtMethod(rtype, r.getVariable().get(), 155 plist, gen.getThisClass()); 156 method.setModifiers(mod); 157 gen.setThisMethod(method); 158 md.accept(gen); 159 if (md.getBody() != null) 160 method.getMethodInfo().setCodeAttribute( 161 bytecode.toCodeAttribute()); 162 else 163 method.setModifiers(mod | Modifier.ABSTRACT); 164 165 method.setExceptionTypes(tlist); 166 return method; 167 } 168 } 169 catch (NotFoundException e) { 170 throw new CompileError(e.toString()); 171 } 172 } 173 174 180 public Bytecode compileBody(CtBehavior method, String src) 181 throws CompileError 182 { 183 try { 184 int mod = method.getModifiers(); 185 recordParams(method.getParameterTypes(), Modifier.isStatic(mod)); 186 187 CtClass rtype; 188 if (method instanceof CtMethod) { 189 gen.setThisMethod((CtMethod)method); 190 rtype = ((CtMethod)method).getReturnType(); 191 } 192 else 193 rtype = CtClass.voidType; 194 195 recordReturnType(rtype, false); 196 boolean isVoid = rtype == CtClass.voidType; 197 198 if (src == null) 199 makeDefaultBody(bytecode, rtype); 200 else { 201 Parser p = new Parser(new Lex(src)); 202 SymbolTable stb = new SymbolTable(stable); 203 Stmnt s = p.parseStatement(stb); 204 boolean callSuper = false; 205 if (method instanceof CtConstructor) 206 callSuper = !((CtConstructor)method).isClassInitializer(); 207 208 gen.atMethodBody(s, callSuper, isVoid); 209 } 210 211 return bytecode; 212 } 213 catch (NotFoundException e) { 214 throw new CompileError(e.toString()); 215 } 216 } 217 218 private static void makeDefaultBody(Bytecode b, CtClass type) { 219 int op; 220 int value; 221 if (type instanceof CtPrimitiveType) { 222 CtPrimitiveType pt = (CtPrimitiveType)type; 223 op = pt.getReturnOp(); 224 if (op == Opcode.DRETURN) 225 value = Opcode.DCONST_0; 226 else if (op == Opcode.FRETURN) 227 value = Opcode.FCONST_0; 228 else if (op == Opcode.LRETURN) 229 value = Opcode.LCONST_0; 230 else if (op == Opcode.RETURN) 231 value = Opcode.NOP; 232 else 233 value = Opcode.ICONST_0; 234 } 235 else { 236 op = Opcode.ARETURN; 237 value = Opcode.ACONST_NULL; 238 } 239 240 if (value != Opcode.NOP) 241 b.addOpcode(value); 242 243 b.addOpcode(op); 244 } 245 246 255 public boolean recordLocalVariables(CodeAttribute ca, int pc) 256 throws CompileError 257 { 258 LocalVariableAttribute va 259 = (LocalVariableAttribute) 260 ca.getAttribute(LocalVariableAttribute.tag); 261 if (va == null) 262 return false; 263 264 int n = va.tableLength(); 265 for (int i = 0; i < n; ++i) { 266 int start = va.startPc(i); 267 int len = va.codeLength(i); 268 if (start <= pc && pc < start + len) 269 gen.recordVariable(va.descriptor(i), va.variableName(i), 270 va.index(i), stable); 271 } 272 273 return true; 274 } 275 276 285 public boolean recordParamNames(CodeAttribute ca, int numOfLocalVars) 286 throws CompileError 287 { 288 LocalVariableAttribute va 289 = (LocalVariableAttribute) 290 ca.getAttribute(LocalVariableAttribute.tag); 291 if (va == null) 292 return false; 293 294 int n = va.tableLength(); 295 for (int i = 0; i < n; ++i) { 296 int index = va.index(i); 297 if (index < numOfLocalVars) 298 gen.recordVariable(va.descriptor(i), va.variableName(i), 299 index, stable); 300 } 301 302 return true; 303 } 304 305 306 315 public int recordParams(CtClass[] params, boolean isStatic) 316 throws CompileError 317 { 318 return gen.recordParams(params, isStatic, "$", "$args", "$$", stable); 319 } 320 321 341 public int recordParams(String target, CtClass[] params, 342 boolean use0, int varNo, boolean isStatic) 343 throws CompileError 344 { 345 return gen.recordParams(params, isStatic, "$", "$args", "$$", 346 use0, varNo, target, stable); 347 } 348 349 363 public int recordReturnType(CtClass type, boolean useResultVar) 364 throws CompileError 365 { 366 gen.recordType(type); 367 return gen.recordReturnType(type, "$r", 368 (useResultVar ? resultVarName : null), stable); 369 } 370 371 377 public void recordType(CtClass t) { 378 gen.recordType(t); 379 } 380 381 387 public int recordVariable(CtClass type, String name) 388 throws CompileError 389 { 390 return gen.recordVariable(type, name, stable); 391 } 392 393 402 public void recordProceed(String target, String method) 403 throws CompileError 404 { 405 Parser p = new Parser(new Lex(target)); 406 final ASTree texpr = p.parseExpression(stable); 407 final String m = method; 408 409 ProceedHandler h = new ProceedHandler() { 410 public void doit(JvstCodeGen gen, Bytecode b, ASTList args) 411 throws CompileError 412 { 413 ASTree expr = new Member(m); 414 if (texpr != null) 415 expr = Expr.make('.', texpr, expr); 416 417 expr = CallExpr.makeCall(expr, args); 418 gen.compileExpr(expr); 419 gen.addNullIfVoid(); 420 } 421 422 public void setReturnType(JvstTypeChecker check, ASTList args) 423 throws CompileError 424 { 425 ASTree expr = new Member(m); 426 if (texpr != null) 427 expr = Expr.make('.', texpr, expr); 428 429 expr = CallExpr.makeCall(expr, args); 430 expr.accept(check); 431 check.addNullIfVoid(); 432 } 433 }; 434 435 gen.setProceedHandler(h, proceedName); 436 } 437 438 447 public void recordStaticProceed(String targetClass, String method) 448 throws CompileError 449 { 450 final String c = targetClass; 451 final String m = method; 452 453 ProceedHandler h = new ProceedHandler() { 454 public void doit(JvstCodeGen gen, Bytecode b, ASTList args) 455 throws CompileError 456 { 457 Expr expr = Expr.make(TokenId.MEMBER, 458 new Symbol(c), new Member(m)); 459 expr = CallExpr.makeCall(expr, args); 460 gen.compileExpr(expr); 461 gen.addNullIfVoid(); 462 } 463 464 public void setReturnType(JvstTypeChecker check, ASTList args) 465 throws CompileError 466 { 467 Expr expr = Expr.make(TokenId.MEMBER, 468 new Symbol(c), new Member(m)); 469 expr = CallExpr.makeCall(expr, args); 470 expr.accept(check); 471 check.addNullIfVoid(); 472 } 473 }; 474 475 gen.setProceedHandler(h, proceedName); 476 } 477 478 489 public void recordSpecialProceed(String target, String classname, 490 String methodname, String descriptor) 491 throws CompileError 492 { 493 Parser p = new Parser(new Lex(target)); 494 final ASTree texpr = p.parseExpression(stable); 495 final String cname = classname; 496 final String method = methodname; 497 final String desc = descriptor; 498 499 ProceedHandler h = new ProceedHandler() { 500 public void doit(JvstCodeGen gen, Bytecode b, ASTList args) 501 throws CompileError 502 { 503 gen.compileInvokeSpecial(texpr, cname, method, desc, args); 504 } 505 506 public void setReturnType(JvstTypeChecker c, ASTList args) 507 throws CompileError 508 { 509 c.compileInvokeSpecial(texpr, cname, method, desc, args); 510 } 511 512 }; 513 514 gen.setProceedHandler(h, proceedName); 515 } 516 517 520 public void recordProceed(ProceedHandler h) { 521 gen.setProceedHandler(h, proceedName); 522 } 523 524 533 public void compileStmnt(String src) throws CompileError { 534 Parser p = new Parser(new Lex(src)); 535 SymbolTable stb = new SymbolTable(stable); 536 while (p.hasMore()) { 537 Stmnt s = p.parseStatement(stb); 538 if (s != null) 539 s.accept(gen); 540 } 541 } 542 543 552 public void compileExpr(String src) throws CompileError { 553 Parser p = new Parser(new Lex(src)); 554 ASTree e = p.parseExpression(stable); 555 compileExpr(e); 556 } 557 558 567 public void compileExpr(ASTree e) throws CompileError { 568 if (e != null) 569 e.accept(gen); 570 } 571 } 572 | Popular Tags |