Merge remote-tracking branch 'origin/code-generator' into Tests
This commit is contained in:
commit
e862a7427b
@ -4,6 +4,7 @@ import ast.type.AccessModifierNode;
|
||||
import ast.members.ConstructorNode;
|
||||
import ast.members.MemberNode;
|
||||
import ast.members.MethodNode;
|
||||
import bytecode.visitor.ClassVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
@ -44,4 +45,9 @@ public class ClassNode implements ASTNode, Visitable {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ClassVisitor classVisitor) {
|
||||
classVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package ast.expressions.binaryexpressions;
|
||||
|
||||
import ast.type.type.*;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
@ -1,4 +1,5 @@
|
||||
package ast.literal;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.type.type.ITypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
|
@ -20,10 +20,4 @@ public class DecrementNode implements IStatementExpressionNode {
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,10 +19,4 @@ public class IncrementNode implements IStatementExpressionNode {
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,49 +18,60 @@ public class ByteCodeGenerator implements ProgramVisitor {
|
||||
private JarOutputStream jarOutputStream;
|
||||
private ByteArrayOutputStream byteArrayOutputStream;
|
||||
private String outputDirectory;
|
||||
private boolean generateJar;
|
||||
private boolean generateClassFiles;
|
||||
|
||||
public ByteCodeGenerator(String outputDirectory) {
|
||||
public ByteCodeGenerator(String outputDirectory, boolean generateJar, boolean generateClassFiles) {
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.generateJar = generateJar;
|
||||
this.generateClassFiles = generateClassFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ProgramNode programNode) {
|
||||
byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
try {
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
|
||||
boolean foundMainClass = false;
|
||||
for (ClassNode classNode : programNode.classes) {
|
||||
if (foundMainClass) {
|
||||
break;
|
||||
}
|
||||
for (MemberNode memberNode : classNode.members) {
|
||||
if (memberNode instanceof MainMethodNode) {
|
||||
manifest.getMainAttributes().putValue("Main-Class", classNode.identifier);
|
||||
foundMainClass = true;
|
||||
if(generateJar) {
|
||||
byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
try {
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
|
||||
boolean foundMainClass = false;
|
||||
for (ClassNode classNode : programNode.classes) {
|
||||
if (foundMainClass) {
|
||||
break;
|
||||
}
|
||||
for (MemberNode memberNode : classNode.members) {
|
||||
if (memberNode instanceof MainMethodNode) {
|
||||
manifest.getMainAttributes().putValue("Main-Class", classNode.identifier);
|
||||
foundMainClass = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jarOutputStream = new JarOutputStream(byteArrayOutputStream, manifest);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
for (ClassNode classDeclarationNode : programNode.classes) {
|
||||
ClassCodeGen classCodeGen = new ClassCodeGen(jarOutputStream, outputDirectory, generateJar, generateClassFiles);
|
||||
classDeclarationNode.accept(classCodeGen);
|
||||
}
|
||||
|
||||
jarOutputStream = new JarOutputStream(byteArrayOutputStream, manifest);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
try {
|
||||
jarOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
saveJarFile(byteArrayOutputStream.toByteArray(), "output.jar");
|
||||
} else {
|
||||
for (ClassNode classDeclarationNode : programNode.classes) {
|
||||
ClassCodeGen classCodeGen = new ClassCodeGen(jarOutputStream, outputDirectory, generateJar, generateClassFiles);
|
||||
classDeclarationNode.accept(classCodeGen);
|
||||
}
|
||||
}
|
||||
|
||||
for (ClassNode classDeclarationNode : programNode.classes) {
|
||||
ClassCodeGen classCodeGen = new ClassCodeGen(jarOutputStream, outputDirectory);
|
||||
classDeclarationNode.accept(classCodeGen);
|
||||
}
|
||||
|
||||
try {
|
||||
jarOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
saveJarFile(byteArrayOutputStream.toByteArray(), "output.jar");
|
||||
}
|
||||
|
||||
private void saveJarFile(byte[] jarBytes, String jarFileName) {
|
||||
|
@ -23,11 +23,15 @@ public class ClassCodeGen implements ClassVisitor {
|
||||
private ClassWriter classWriter;
|
||||
private JarOutputStream jarOutputStream;
|
||||
private String outputDirectory;
|
||||
private boolean generateJar;
|
||||
private boolean generateClassFiles;
|
||||
|
||||
public ClassCodeGen(JarOutputStream jarOutputStream, String outputDirectory) {
|
||||
public ClassCodeGen(JarOutputStream jarOutputStream, String outputDirectory, boolean generateJar, boolean generateClassFiles) {
|
||||
mapper = new Mapper();
|
||||
this.jarOutputStream = jarOutputStream;
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.generateJar = generateJar;
|
||||
this.generateClassFiles = generateClassFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -45,9 +49,12 @@ public class ClassCodeGen implements ClassVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
classWriter.visitEnd();
|
||||
printIntoClassFile(classWriter.toByteArray(), classNode.identifier, outputDirectory);
|
||||
writeToJar(classWriter.toByteArray(), classNode.identifier);
|
||||
if (generateJar) {
|
||||
writeToJar(classWriter.toByteArray(), classNode.identifier);
|
||||
}
|
||||
if (generateClassFiles) {
|
||||
printIntoClassFile(classWriter.toByteArray(), classNode.identifier, outputDirectory);
|
||||
}
|
||||
|
||||
classWriter.visitEnd();
|
||||
}
|
||||
|
@ -27,18 +27,18 @@ public class Mapper {
|
||||
public String generateMethodDescriptor(BaseType type, List<ParameterNode> parameters) {
|
||||
String descriptor = "(";
|
||||
for (ParameterNode parameterNode : parameters) {
|
||||
descriptor += getTypeChar((BaseType) parameterNode.type);
|
||||
if(parameterNode.type instanceof BaseType) {
|
||||
descriptor += getTypeChar((BaseType) parameterNode.type);
|
||||
} else {
|
||||
ReferenceType referenceType = (ReferenceType) parameterNode.type;
|
||||
descriptor += "L" + referenceType.getIdentifier() + ";";
|
||||
}
|
||||
}
|
||||
descriptor += ")";
|
||||
descriptor += getTypeChar(type);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public String generateMethodDescriptor(ReferenceType type, List<ParameterNode> parameters) {
|
||||
String descriptor = "()V";
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public String getTypeChar(BaseType type) {
|
||||
String typeChar = "";
|
||||
switch (type.getTypeEnum()) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package bytecode;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.expressions.binaryexpressions.*;
|
||||
import ast.expressions.unaryexpressions.MemberAccessNode;
|
||||
import ast.expressions.unaryexpressions.NotNode;
|
||||
@ -10,6 +11,7 @@ import ast.members.MethodNode;
|
||||
import ast.parameters.ParameterNode;
|
||||
import ast.statementexpressions.AssignNode;
|
||||
import ast.statementexpressions.NewDeclarationNode;
|
||||
import ast.statementexpressions.crementexpressions.CrementType;
|
||||
import ast.statementexpressions.crementexpressions.DecrementNode;
|
||||
import ast.statementexpressions.crementexpressions.IncrementNode;
|
||||
import ast.statementexpressions.methodcallstatementnexpressions.ChainedMethodNode;
|
||||
@ -18,6 +20,7 @@ import ast.statementexpressions.methodcallstatementnexpressions.TargetNode;
|
||||
import ast.statements.*;
|
||||
import ast.type.ValueNode;
|
||||
import ast.type.type.BaseType;
|
||||
import ast.type.type.ReferenceType;
|
||||
import ast.type.type.TypeEnum;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Label;
|
||||
@ -68,7 +71,9 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
|
||||
// Visit all statements
|
||||
for (IStatementNode statementNode : constructorNode.block.statements) {
|
||||
statementNode.accept(this);
|
||||
if (statementNode != null) {
|
||||
statementNode.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
methodVisitor.visitMaxs(0, 0);
|
||||
@ -130,32 +135,44 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(CalculationNode calculationNode) {
|
||||
calculationNode.dotExpression.accept(this);
|
||||
calculationNode.calculationExpression.accept(this);
|
||||
switch (calculationNode.operator) {
|
||||
case PLUS:
|
||||
methodVisitor.visitInsn(IADD);
|
||||
break;
|
||||
case MINUS:
|
||||
methodVisitor.visitInsn(ISUB);
|
||||
break;
|
||||
if (calculationNode.dotExpression != null) {
|
||||
calculationNode.dotExpression.accept(this);
|
||||
}
|
||||
if (calculationNode.calculationExpression != null) {
|
||||
calculationNode.calculationExpression.accept(this);
|
||||
}
|
||||
if (calculationNode.operator != null) {
|
||||
switch (calculationNode.operator) {
|
||||
case PLUS:
|
||||
methodVisitor.visitInsn(IADD);
|
||||
break;
|
||||
case MINUS:
|
||||
methodVisitor.visitInsn(ISUB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DotNode dotNode) {
|
||||
dotNode.dotExpression.accept(this);
|
||||
dotNode.dotSubstractionExpression.accept(this);
|
||||
switch (dotNode.operator) {
|
||||
case DIV:
|
||||
methodVisitor.visitInsn(IDIV);
|
||||
break;
|
||||
case MULT:
|
||||
methodVisitor.visitInsn(IMUL);
|
||||
break;
|
||||
case MOD:
|
||||
methodVisitor.visitInsn(IREM);
|
||||
break;
|
||||
if (dotNode.dotExpression != null) {
|
||||
dotNode.dotExpression.accept(this);
|
||||
}
|
||||
if (dotNode.dotSubstractionExpression != null) {
|
||||
dotNode.dotSubstractionExpression.accept(this);
|
||||
}
|
||||
if (dotNode.operator != null) {
|
||||
switch (dotNode.operator) {
|
||||
case DIV:
|
||||
methodVisitor.visitInsn(IDIV);
|
||||
break;
|
||||
case MULT:
|
||||
methodVisitor.visitInsn(IMUL);
|
||||
break;
|
||||
case MOD:
|
||||
methodVisitor.visitInsn(IREM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,6 +195,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
public void visit(NonCalculationNode nonCalculationNode) {
|
||||
Label labelFalse = new Label();
|
||||
Label labelTrue = new Label();
|
||||
// TODO: Null check
|
||||
switch (nonCalculationNode.operator) {
|
||||
case AND:
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
@ -249,7 +267,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
@Override
|
||||
public void visit(MemberAccessNode memberAccessNode) {
|
||||
if (memberAccessNode.thisExpr) {
|
||||
//methodVisitor.visitFieldInsn(PUTFIELD);
|
||||
// methodVisitor.visitFieldInsn(PUTFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), );
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,7 +293,21 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(UnaryNode unaryNode) {
|
||||
|
||||
if (unaryNode.thisExp != null) {
|
||||
methodVisitor.visitVarInsn(ALOAD, 0); // this
|
||||
} else if (unaryNode.identifier != null) {
|
||||
methodVisitor.visitVarInsn(ILOAD, localVaribales.indexOf(unaryNode.identifier));
|
||||
} else if (unaryNode.memberAccess != null) {
|
||||
unaryNode.memberAccess.accept(this);
|
||||
} else if (unaryNode.value != null) {
|
||||
unaryNode.value.accept(this);
|
||||
} else if (unaryNode.notExpression != null) {
|
||||
unaryNode.notExpression.accept(this);
|
||||
} else if (unaryNode.statement != null) {
|
||||
unaryNode.statement.accept(this);
|
||||
} else if (unaryNode.expression != null) {
|
||||
unaryNode.expression.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -286,7 +318,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
Label elseLabel = new Label();
|
||||
|
||||
Label[] elseIfLabels = new Label[ifElseNode.elseIfStatements.size()];
|
||||
for(int i = 0; i < ifElseNode.elseIfStatements.size(); i++) {
|
||||
for (int i = 0; i < ifElseNode.elseIfStatements.size(); i++) {
|
||||
elseIfLabels[i] = new Label();
|
||||
}
|
||||
|
||||
@ -303,12 +335,12 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
Label endLabel = new Label();
|
||||
methodVisitor.visitJumpInsn(GOTO, endLabel);
|
||||
|
||||
for(int i = 0; i < ifElseNode.elseIfStatements.size(); i++) {
|
||||
for (int i = 0; i < ifElseNode.elseIfStatements.size(); i++) {
|
||||
methodVisitor.visitLabel(elseIfLabels[i]);
|
||||
ifElseNode.elseIfStatements.get(i).expression.accept(this);
|
||||
if(i + 1 < elseIfLabels.length) {
|
||||
if (i + 1 < elseIfLabels.length) {
|
||||
// at least one more else if
|
||||
methodVisitor.visitJumpInsn(IFEQ, elseIfLabels[i+1]);
|
||||
methodVisitor.visitJumpInsn(IFEQ, elseIfLabels[i + 1]);
|
||||
} else {
|
||||
methodVisitor.visitJumpInsn(IFEQ, elseLabel);
|
||||
}
|
||||
@ -316,7 +348,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
methodVisitor.visitJumpInsn(GOTO, endLabel);
|
||||
}
|
||||
|
||||
if(ifElseNode.elseStatement != null) {
|
||||
if (ifElseNode.elseStatement != null) {
|
||||
methodVisitor.visitLabel(elseLabel);
|
||||
ifElseNode.elseStatement.block.accept(this);
|
||||
}
|
||||
@ -326,29 +358,88 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(LocalVariableDeclarationNode localVariableDeclarationNode) {
|
||||
// Process expression
|
||||
localVariableDeclarationNode.expression.accept(this);
|
||||
// Store result of expression in variable
|
||||
methodVisitor.visitVarInsn(ISTORE, localVaribales.indexOf(localVariableDeclarationNode.identifier));
|
||||
if (localVariableDeclarationNode.expression != null) {
|
||||
// Process expression
|
||||
localVariableDeclarationNode.expression.accept(this);
|
||||
// Store result of expression in variable
|
||||
if (localVaribales.contains(localVariableDeclarationNode.identifier)) {
|
||||
if (localVariableDeclarationNode.type instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ISTORE, localVaribales.indexOf(localVariableDeclarationNode.identifier));
|
||||
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
||||
methodVisitor.visitVarInsn(ASTORE, localVaribales.indexOf(localVariableDeclarationNode.identifier));
|
||||
}
|
||||
} else {
|
||||
localVaribales.add(localVariableDeclarationNode.identifier);
|
||||
if (localVariableDeclarationNode.type instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ISTORE, localVaribales.indexOf(localVariableDeclarationNode.identifier));
|
||||
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
||||
methodVisitor.visitVarInsn(ASTORE, localVaribales.indexOf(localVariableDeclarationNode.identifier));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!localVaribales.contains(localVariableDeclarationNode.identifier)) {
|
||||
localVaribales.add(localVariableDeclarationNode.identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AssignNode assignNode) {
|
||||
// Process expression
|
||||
assignNode.expression.accept(this);
|
||||
if (assignNode.expression instanceof IncrementNode) {
|
||||
IncrementNode incrementNode = (IncrementNode) assignNode.expression;
|
||||
if (incrementNode.crementType.equals(CrementType.PREFIX)) { // ++i
|
||||
methodVisitor.visitIincInsn(localVaribales.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||
assign(assignNode);
|
||||
} else if (incrementNode.crementType.equals(CrementType.SUFFIX)) { // Suffix: i++
|
||||
assign(assignNode);
|
||||
methodVisitor.visitIincInsn(localVaribales.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||
}
|
||||
} else if (assignNode.expression instanceof DecrementNode) {
|
||||
DecrementNode decrementNode = (DecrementNode) assignNode.expression;
|
||||
if (decrementNode.crementType.equals(CrementType.PREFIX)) {
|
||||
methodVisitor.visitIincInsn(localVaribales.indexOf(decrementNode.assignableExpression.identifier), -1);
|
||||
assign(assignNode);
|
||||
} else if (decrementNode.crementType.equals(CrementType.SUFFIX)) {
|
||||
assign(assignNode);
|
||||
methodVisitor.visitIincInsn(localVaribales.indexOf(decrementNode.assignableExpression.identifier), 1);
|
||||
}
|
||||
} else {
|
||||
assignNode.expression.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void assign(AssignNode assignNode) {
|
||||
// Store result of expression in variable
|
||||
if (assignNode.assignable.memberAccess.thisExpr) {
|
||||
// Global var
|
||||
// /methodVisitor.visitFieldInsn(PUTFIELD, identifierExpressionNode.name, identifierExpressionNode1.name, mapper.getTypeChar(((BaseTypeNode) type).enumType));
|
||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||
if (assignNode.expression instanceof BaseType) {
|
||||
//methodVisitor.visitFieldInsn(PUTFIELD, class name, var identifier, mapper.getTypeChar(((BaseTypeNode) type).enumType));
|
||||
} else if (assignNode.expression instanceof ReferenceType) {
|
||||
//methodVisitor.visitFieldInsn(PUTFIELD, class name, var identifier, "L"class name object +";");
|
||||
}
|
||||
} else {
|
||||
// Local var
|
||||
methodVisitor.visitVarInsn(ISTORE, localVaribales.indexOf(assignNode.assignable.identifier));
|
||||
if (assignNode.expression instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ISTORE, localVaribales.indexOf(assignNode.assignable.identifier));
|
||||
} else if (assignNode.expression instanceof ReferenceType) {
|
||||
methodVisitor.visitVarInsn(ASTORE, localVaribales.indexOf(assignNode.assignable.identifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewDeclarationNode newDeclarationNode) {
|
||||
|
||||
methodVisitor.visitTypeInsn(NEW, newDeclarationNode.identifier);
|
||||
methodVisitor.visitInsn(DUP);
|
||||
for (IExpressionNode expressionNode : newDeclarationNode.expressions) {
|
||||
expressionNode.accept(this);
|
||||
}
|
||||
// TODO
|
||||
//methodVisitor.visitMethodInsn(INVOKESPECIAL, class name, "<init>", mapper.generateMethodDescriptor(), false);
|
||||
// TODO: kann ein Field auch definiert werden? Abfrage ob local var oder field
|
||||
localVaribales.add(newDeclarationNode.identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -395,7 +486,11 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
// Process expression
|
||||
returnNode.expression.accept(this);
|
||||
// Return result of expression
|
||||
methodVisitor.visitInsn(IRETURN);
|
||||
if (returnNode.expression.getType() instanceof BaseType) {
|
||||
methodVisitor.visitInsn(IRETURN);
|
||||
} else if (returnNode.expression.getType() instanceof ReferenceType) {
|
||||
methodVisitor.visitInsn(ARETURN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,55 +505,19 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
whileNode.expression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IFEQ, endOfLoopLabel); // if condition is false, jump out of loop
|
||||
|
||||
// TODO: Unterscheidung bei increment/decrement der for Schleife
|
||||
if (whileNode.block.statements.size() == 2) { // For loop
|
||||
whileNode.block.statements.get(0).accept(this);
|
||||
|
||||
} else {
|
||||
whileNode.block.statements.get(0).accept(this);
|
||||
}
|
||||
whileNode.block.accept(this);
|
||||
methodVisitor.visitJumpInsn(GOTO, loopLabel);
|
||||
|
||||
methodVisitor.visitLabel(endOfLoopLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DecrementNode decrementNode) {
|
||||
switch (decrementNode.crementType) {
|
||||
case PREFIX: // --i
|
||||
if (decrementNode.assignableExpression.memberAccess == null) { // local Var
|
||||
methodVisitor.visitIincInsn(localVaribales.indexOf(decrementNode.assignableExpression.identifier), -1);
|
||||
} else { // Field or var from other object
|
||||
|
||||
}
|
||||
break;
|
||||
case SUFFIX: // i--
|
||||
if (decrementNode.assignableExpression.memberAccess == null) { // local Var
|
||||
methodVisitor.visitIincInsn(localVaribales.indexOf(decrementNode.assignableExpression.identifier), -1);
|
||||
} else { // Field or var from other object
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IncrementNode incrementNode) {
|
||||
switch (incrementNode.crementType) {
|
||||
case PREFIX: // ++i
|
||||
if (incrementNode.assignableExpression.memberAccess == null) { // local Var
|
||||
methodVisitor.visitIincInsn(localVaribales.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||
methodVisitor.visitVarInsn(ISTORE, localVaribales.indexOf(incrementNode.assignableExpression.identifier));
|
||||
|
||||
} else { // Field or var from other object
|
||||
|
||||
}
|
||||
break;
|
||||
case SUFFIX: // i++
|
||||
if (incrementNode.assignableExpression.memberAccess == null) { // local Var
|
||||
methodVisitor.visitVarInsn(ISTORE, localVaribales.indexOf(incrementNode.assignableExpression.identifier));
|
||||
methodVisitor.visitIincInsn(localVaribales.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||
} else { // Field or var from other object
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ChainedMethodNode chainedMethodNode) {
|
||||
|
||||
|
@ -44,9 +44,6 @@ public interface MethodVisitor {
|
||||
void visit(WhileNode whileNode);
|
||||
|
||||
// statement expression
|
||||
void visit(DecrementNode decrementNode);
|
||||
void visit(IncrementNode incrementNode);
|
||||
|
||||
void visit(ChainedMethodNode chainedMethodNode);
|
||||
void visit(MethodCallNode methodCallNode);
|
||||
void visit(TargetNode targetNode);
|
||||
|
Loading…
Reference in New Issue
Block a user