diff options
Diffstat (limited to 'src/main/javassist/compiler')
-rw-r--r-- | src/main/javassist/compiler/CodeGen.java | 13 | ||||
-rw-r--r-- | src/main/javassist/compiler/MemberCodeGen.java | 70 | ||||
-rw-r--r-- | src/main/javassist/compiler/Parser.java | 17 | ||||
-rw-r--r-- | src/main/javassist/compiler/TypeChecker.java | 19 | ||||
-rw-r--r-- | src/main/javassist/compiler/ast/ArrayInit.java | 15 | ||||
-rw-r--r-- | src/main/javassist/compiler/ast/NewExpr.java | 8 | ||||
-rw-r--r-- | src/main/javassist/compiler/ast/Visitor.java | 1 |
7 files changed, 122 insertions, 21 deletions
diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java index 9b401804..6739c17a 100644 --- a/src/main/javassist/compiler/CodeGen.java +++ b/src/main/javassist/compiler/CodeGen.java @@ -709,13 +709,15 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { */ ASTree init = d.getInitializer(); if (init != null) { - doTypeCheck(init); + doTypeCheck(init); atVariableAssign(null, '=', null, d, init, false); } } public abstract void atNewExpr(NewExpr n) throws CompileError; + public abstract void atArrayInit(ArrayInit init) throws CompileError; + public void atAssignExpr(AssignExpr expr) throws CompileError { atAssignExpr(expr, true); } @@ -770,7 +772,11 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { if (op != '=') atVariable(var); - atAssignCore(expr, op, right, varType, varArray, varClass); + // expr is null if the caller is atDeclarator(). + if (expr == null && right instanceof ArrayInit) + atArrayVariableAssign((ArrayInit)right, varType, varArray, varClass); + else + atAssignCore(expr, op, right, varType, varArray, varClass); if (doDup) if (is2word(varType, varArray)) @@ -796,6 +802,9 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { className = varClass; } + protected abstract void atArrayVariableAssign(ArrayInit init, + int varType, int varArray, String varClass) throws CompileError; + private void atArrayAssign(Expr expr, int op, Expr array, ASTree right, boolean doDup) throws CompileError { diff --git a/src/main/javassist/compiler/MemberCodeGen.java b/src/main/javassist/compiler/MemberCodeGen.java index 88023202..ae586d68 100644 --- a/src/main/javassist/compiler/MemberCodeGen.java +++ b/src/main/javassist/compiler/MemberCodeGen.java @@ -18,6 +18,7 @@ package javassist.compiler; import javassist.*; import javassist.bytecode.*; import javassist.compiler.ast.*; + import java.util.ArrayList; /* Code generator methods depending on javassist.* classes. @@ -29,8 +30,7 @@ public class MemberCodeGen extends CodeGen { protected boolean resultStatic; - public MemberCodeGen(Bytecode b, CtClass cc, ClassPool cp) - { + public MemberCodeGen(Bytecode b, CtClass cc, ClassPool cp) { super(b); resolver = new MemberResolver(cp); thisClass = cc; @@ -239,26 +239,46 @@ public class MemberCodeGen extends CodeGen { } public void atNewArrayExpr(NewExpr expr) throws CompileError { - if (expr.getInitializer() != null) - throw new CompileError("array initializer is not supported"); - int type = expr.getArrayType(); ASTList size = expr.getArraySize(); ASTList classname = expr.getClassName(); + ArrayInit init = expr.getInitializer(); if (size.length() > 1) { + if (init != null) + throw new CompileError( + "sorry, multi-dimensional array initializer " + + "for new is not supported"); + atMultiNewArray(type, classname, size); return; } - size.head().accept(this); - exprType = type; - arrayDim = 1; + ASTree sizeExpr = size.head(); + atNewArrayExpr2(type, sizeExpr, Declarator.astToClassName(classname, '/'), init); + } + + private void atNewArrayExpr2(int type, ASTree sizeExpr, + String jvmClassname, ArrayInit init) throws CompileError { + if (init == null) + if (sizeExpr == null) + throw new CompileError("no array size"); + else + sizeExpr.accept(this); + else + if (sizeExpr == null) { + int s = init.length(); + bytecode.addIconst(s); + } + else + throw new CompileError("unnecessary array size specified for new"); + + String elementClass; if (type == CLASS) { - className = resolveClassName(classname); - bytecode.addAnewarray(MemberResolver.jvmToJavaName(className)); + elementClass = resolveClassName(jvmClassname); + bytecode.addAnewarray(MemberResolver.jvmToJavaName(elementClass)); } else { - className = null; + elementClass = null; int atype = 0; switch (type) { case BOOLEAN : @@ -293,12 +313,40 @@ public class MemberCodeGen extends CodeGen { bytecode.addOpcode(NEWARRAY); bytecode.add(atype); } + + if (init != null) { + int s = init.length(); + ASTList list = init; + for (int i = 0; i < s; i++) { + bytecode.addOpcode(DUP); + bytecode.addIconst(i); + list.head().accept(this); + if (!isRefType(type)) + atNumCastExpr(exprType, type); + + bytecode.addOpcode(getArrayWriteOp(type, 0)); + list = list.tail(); + } + } + + exprType = type; + arrayDim = 1; + className = elementClass; } private static void badNewExpr() throws CompileError { throw new CompileError("bad new expression"); } + protected void atArrayVariableAssign(ArrayInit init, int varType, + int varArray, String varClass) throws CompileError { + atNewArrayExpr2(varType, null, varClass, init); + } + + public void atArrayInit(ArrayInit init) throws CompileError { + throw new CompileError("array initializer is not supported"); + } + protected void atMultiNewArray(int type, ASTList classname, ASTList size) throws CompileError { diff --git a/src/main/javassist/compiler/Parser.java b/src/main/javassist/compiler/Parser.java index e1a0d5b2..5b61ae42 100644 --- a/src/main/javassist/compiler/Parser.java +++ b/src/main/javassist/compiler/Parser.java @@ -660,11 +660,22 @@ public final class Parser implements TokenId { /* array.initializer : * '{' (( array.initializer | expression ) ',')* '}' */ - private ASTree parseArrayInitializer(SymbolTable tbl) + private ArrayInit parseArrayInitializer(SymbolTable tbl) throws CompileError { lex.get(); // '{' - throw new CompileError("array initializer is not supported", lex); + ASTree expr = parseExpression(tbl); + ArrayInit init = new ArrayInit(expr); + while (lex.lookAhead() == ',') { + lex.get(); + expr = parseExpression(tbl); + ASTList.append(init, expr); + } + + if (lex.get() != '}') + throw new SyntaxError(lex); + + return init; } /* par.expression : '(' expression ')' @@ -1250,7 +1261,7 @@ public final class Parser implements TokenId { * | primitive.type array.size [ array.initializer ] */ private NewExpr parseNew(SymbolTable tbl) throws CompileError { - ASTree init = null; + ArrayInit init = null; int t = lex.lookAhead(); if (isBuiltinType(t)) { lex.get(); diff --git a/src/main/javassist/compiler/TypeChecker.java b/src/main/javassist/compiler/TypeChecker.java index 543ecdf8..56417922 100644 --- a/src/main/javassist/compiler/TypeChecker.java +++ b/src/main/javassist/compiler/TypeChecker.java @@ -106,10 +106,17 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { int type = expr.getArrayType(); ASTList size = expr.getArraySize(); ASTList classname = expr.getClassName(); + ASTree init = expr.getInitializer(); + if (init != null) + init.accept(this); + if (size.length() > 1) atMultiNewArray(type, classname, size); else { - size.head().accept(this); + ASTree sizeExpr = size.head(); + if (sizeExpr != null) + sizeExpr.accept(this); + exprType = type; arrayDim = 1; if (type == CLASS) @@ -119,6 +126,16 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { } } + public void atArrayInit(ArrayInit init) throws CompileError { + ASTList list = init; + while (list != null) { + ASTree h = list.head(); + list = list.tail(); + if (h != null) + h.accept(this); + } + } + protected void atMultiNewArray(int type, ASTList classname, ASTList size) throws CompileError { diff --git a/src/main/javassist/compiler/ast/ArrayInit.java b/src/main/javassist/compiler/ast/ArrayInit.java new file mode 100644 index 00000000..bdc35a75 --- /dev/null +++ b/src/main/javassist/compiler/ast/ArrayInit.java @@ -0,0 +1,15 @@ +package javassist.compiler.ast; + +import javassist.compiler.CompileError; +/** + * Array initializer such as <code>{ 1, 2, 3 }</code>. + */ +public class ArrayInit extends ASTList { + public ArrayInit(ASTree firstElement) { + super(firstElement); + } + + public void accept(Visitor v) throws CompileError { v.atArrayInit(this); } + + public String getTag() { return "array"; } +} diff --git a/src/main/javassist/compiler/ast/NewExpr.java b/src/main/javassist/compiler/ast/NewExpr.java index 1a1a3f08..b570ea0b 100644 --- a/src/main/javassist/compiler/ast/NewExpr.java +++ b/src/main/javassist/compiler/ast/NewExpr.java @@ -31,7 +31,7 @@ public class NewExpr extends ASTList implements TokenId { arrayType = CLASS; } - public NewExpr(int type, ASTList arraySize, ASTree init) { + public NewExpr(int type, ASTList arraySize, ArrayInit init) { super(null, new ASTList(arraySize)); newArray = true; arrayType = type; @@ -40,7 +40,7 @@ public class NewExpr extends ASTList implements TokenId { } public static NewExpr makeObjectArray(ASTList className, - ASTList arraySize, ASTree init) { + ASTList arraySize, ArrayInit init) { NewExpr e = new NewExpr(className, arraySize); e.newArray = true; if (init != null) @@ -61,12 +61,12 @@ public class NewExpr extends ASTList implements TokenId { public ASTList getArraySize() { return getArguments(); } - public ASTree getInitializer() { + public ArrayInit getInitializer() { ASTree t = getRight().getRight(); if (t == null) return null; else - return t.getLeft(); + return (ArrayInit)t.getLeft(); } public void accept(Visitor v) throws CompileError { v.atNewExpr(this); } diff --git a/src/main/javassist/compiler/ast/Visitor.java b/src/main/javassist/compiler/ast/Visitor.java index f8af3198..5c361d8d 100644 --- a/src/main/javassist/compiler/ast/Visitor.java +++ b/src/main/javassist/compiler/ast/Visitor.java @@ -47,4 +47,5 @@ public class Visitor { public void atStringL(StringL n) throws CompileError {} public void atIntConst(IntConst n) throws CompileError {} public void atDoubleConst(DoubleConst n) throws CompileError {} + public void atArrayInit(ArrayInit n) throws CompileError {} } |