|
|
|
@ -147,6 +147,67 @@ public class CodeFlow implements Opcodes { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Called after the main expression evaluation method has been generated, this |
|
|
|
|
|
|
|
* method will callback any registered FieldAdders or ClinitAdders to add any |
|
|
|
|
|
|
|
* extra information to the class representing the compiled expression. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void finish() { |
|
|
|
|
|
|
|
if (this.fieldAdders != null) { |
|
|
|
|
|
|
|
for (FieldAdder fieldAdder : this.fieldAdders) { |
|
|
|
|
|
|
|
fieldAdder.generateField(cw,this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (this.clinitAdders != null) { |
|
|
|
|
|
|
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null); |
|
|
|
|
|
|
|
mv.visitCode(); |
|
|
|
|
|
|
|
this.nextFreeVariableId = 0; // To 0 because there is no 'this' in a clinit
|
|
|
|
|
|
|
|
for (ClinitAdder clinitAdder : this.clinitAdders) { |
|
|
|
|
|
|
|
clinitAdder.generateCode(mv, this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
mv.visitInsn(RETURN); |
|
|
|
|
|
|
|
mv.visitMaxs(0,0); // not supplied due to COMPUTE_MAXS
|
|
|
|
|
|
|
|
mv.visitEnd(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Register a FieldAdder which will add a new field to the generated |
|
|
|
|
|
|
|
* class to support the code produced by an ast nodes primary |
|
|
|
|
|
|
|
* generateCode() method. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void registerNewField(FieldAdder fieldAdder) { |
|
|
|
|
|
|
|
if (this.fieldAdders == null) { |
|
|
|
|
|
|
|
this.fieldAdders = new ArrayList<>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.fieldAdders.add(fieldAdder); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Register a ClinitAdder which will add code to the static |
|
|
|
|
|
|
|
* initializer in the generated class to support the code |
|
|
|
|
|
|
|
* produced by an ast nodes primary generateCode() method. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void registerNewClinit(ClinitAdder clinitAdder) { |
|
|
|
|
|
|
|
if (this.clinitAdders == null) { |
|
|
|
|
|
|
|
this.clinitAdders = new ArrayList<>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this.clinitAdders.add(clinitAdder); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public int nextFieldId() { |
|
|
|
|
|
|
|
return this.nextFieldId++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public int nextFreeVariableId() { |
|
|
|
|
|
|
|
return this.nextFreeVariableId++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getClassName() { |
|
|
|
|
|
|
|
return this.clazzName; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Insert any necessary cast and value call to convert from a boxed type to a |
|
|
|
* Insert any necessary cast and value call to convert from a boxed type to a |
|
|
|
* primitive value |
|
|
|
* primitive value |
|
|
|
@ -778,76 +839,6 @@ public class CodeFlow implements Opcodes { |
|
|
|
return descriptors; |
|
|
|
return descriptors; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Called after the main expression evaluation method has been generated, this |
|
|
|
|
|
|
|
* method will callback any registered FieldAdders or ClinitAdders to add any |
|
|
|
|
|
|
|
* extra information to the class representing the compiled expression. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void finish() { |
|
|
|
|
|
|
|
if (fieldAdders != null) { |
|
|
|
|
|
|
|
for (FieldAdder fieldAdder: fieldAdders) { |
|
|
|
|
|
|
|
fieldAdder.generateField(cw,this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (clinitAdders != null) { |
|
|
|
|
|
|
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null); |
|
|
|
|
|
|
|
mv.visitCode(); |
|
|
|
|
|
|
|
nextFreeVariableId = 0; // To 0 because there is no 'this' in a clinit
|
|
|
|
|
|
|
|
for (ClinitAdder clinitAdder: clinitAdders) { |
|
|
|
|
|
|
|
clinitAdder.generateCode(mv, this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
mv.visitInsn(RETURN); |
|
|
|
|
|
|
|
mv.visitMaxs(0,0); // not supplied due to COMPUTE_MAXS
|
|
|
|
|
|
|
|
mv.visitEnd(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Register a FieldAdder which will add a new field to the generated |
|
|
|
|
|
|
|
* class to support the code produced by an ast nodes primary |
|
|
|
|
|
|
|
* generateCode() method. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void registerNewField(FieldAdder fieldAdder) { |
|
|
|
|
|
|
|
if (fieldAdders == null) { |
|
|
|
|
|
|
|
fieldAdders = new ArrayList<>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
fieldAdders.add(fieldAdder); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Register a ClinitAdder which will add code to the static |
|
|
|
|
|
|
|
* initializer in the generated class to support the code |
|
|
|
|
|
|
|
* produced by an ast nodes primary generateCode() method. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void registerNewClinit(ClinitAdder clinitAdder) { |
|
|
|
|
|
|
|
if (clinitAdders == null) { |
|
|
|
|
|
|
|
clinitAdders = new ArrayList<>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
clinitAdders.add(clinitAdder); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public int nextFieldId() { |
|
|
|
|
|
|
|
return nextFieldId++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public int nextFreeVariableId() { |
|
|
|
|
|
|
|
return nextFreeVariableId++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getClassname() { |
|
|
|
|
|
|
|
return clazzName; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@FunctionalInterface |
|
|
|
|
|
|
|
public interface FieldAdder { |
|
|
|
|
|
|
|
void generateField(ClassWriter cw, CodeFlow codeflow); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@FunctionalInterface |
|
|
|
|
|
|
|
public interface ClinitAdder { |
|
|
|
|
|
|
|
void generateCode(MethodVisitor mv, CodeFlow codeflow); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Create the optimal instruction for loading a number on the stack. |
|
|
|
* Create the optimal instruction for loading a number on the stack. |
|
|
|
* @param mv where to insert the bytecode |
|
|
|
* @param mv where to insert the bytecode |
|
|
|
@ -979,4 +970,17 @@ public class CodeFlow implements Opcodes { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@FunctionalInterface |
|
|
|
|
|
|
|
public interface FieldAdder { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void generateField(ClassWriter cw, CodeFlow codeflow); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@FunctionalInterface |
|
|
|
|
|
|
|
public interface ClinitAdder { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void generateCode(MethodVisitor mv, CodeFlow codeflow); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|