aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javassist/compiler')
-rw-r--r--src/main/javassist/compiler/CodeGen.java13
-rw-r--r--src/main/javassist/compiler/MemberCodeGen.java70
-rw-r--r--src/main/javassist/compiler/Parser.java17
-rw-r--r--src/main/javassist/compiler/TypeChecker.java19
-rw-r--r--src/main/javassist/compiler/ast/ArrayInit.java15
-rw-r--r--src/main/javassist/compiler/ast/NewExpr.java8
-rw-r--r--src/main/javassist/compiler/ast/Visitor.java1
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 {}
}