Compare commits
4 Commits
f6b34bf70b
...
8eba420d48
Author | SHA1 | Date | |
---|---|---|---|
8eba420d48 | |||
fbff03c3d7 | |||
721e1caa79 | |||
6d3e1f859e |
@ -1,6 +1,7 @@
|
|||||||
package ast.expressions.unaryexpressions;
|
package ast.expressions.unaryexpressions;
|
||||||
|
|
||||||
import ast.ASTNode;
|
import ast.ASTNode;
|
||||||
|
import ast.type.type.ITypeNode;
|
||||||
import bytecode.visitor.MethodVisitor;
|
import bytecode.visitor.MethodVisitor;
|
||||||
|
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
@ -13,6 +14,7 @@ import java.util.List;
|
|||||||
public class MemberAccessNode implements ASTNode, Visitable {
|
public class MemberAccessNode implements ASTNode, Visitable {
|
||||||
public Boolean thisExpr;
|
public Boolean thisExpr;
|
||||||
public List<String> identifiers = new ArrayList<>();
|
public List<String> identifiers = new ArrayList<>();
|
||||||
|
private ITypeNode typeNode;
|
||||||
|
|
||||||
public MemberAccessNode(Boolean thisExpr) {
|
public MemberAccessNode(Boolean thisExpr) {
|
||||||
this.thisExpr = thisExpr;
|
this.thisExpr = thisExpr;
|
||||||
@ -31,5 +33,13 @@ public class MemberAccessNode implements ASTNode, Visitable {
|
|||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ITypeNode getTypeNode() {
|
||||||
|
return typeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeNode(ITypeNode typeNode) {
|
||||||
|
this.typeNode = typeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package ast.statementexpressions;
|
|||||||
|
|
||||||
import ast.expressions.unaryexpressions.MemberAccessNode;
|
import ast.expressions.unaryexpressions.MemberAccessNode;
|
||||||
import ast.type.type.ITypeNode;
|
import ast.type.type.ITypeNode;
|
||||||
|
import bytecode.visitor.MethodVisitor;
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
import semantic.TypeCheckResult;
|
import semantic.TypeCheckResult;
|
||||||
|
|
||||||
|
@ -2,10 +2,12 @@ package ast.statementexpressions.crementexpressions;
|
|||||||
|
|
||||||
import ast.statementexpressions.AssignableNode;
|
import ast.statementexpressions.AssignableNode;
|
||||||
import ast.statementexpressions.IStatementExpressionNode;
|
import ast.statementexpressions.IStatementExpressionNode;
|
||||||
|
import bytecode.visitor.MethodVisitor;
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
import semantic.TypeCheckResult;
|
import semantic.TypeCheckResult;
|
||||||
|
import visitor.Visitable;
|
||||||
|
|
||||||
public class DecrementNode implements IStatementExpressionNode {
|
public class DecrementNode implements IStatementExpressionNode, Visitable {
|
||||||
public CrementType crementType;
|
public CrementType crementType;
|
||||||
public AssignableNode assignableExpression;
|
public AssignableNode assignableExpression;
|
||||||
|
|
||||||
@ -18,4 +20,9 @@ public class DecrementNode implements IStatementExpressionNode {
|
|||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(MethodVisitor methodVisitor) {
|
||||||
|
methodVisitor.visit(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@ package ast.statementexpressions.crementexpressions;
|
|||||||
|
|
||||||
import ast.statementexpressions.AssignableNode;
|
import ast.statementexpressions.AssignableNode;
|
||||||
import ast.statementexpressions.IStatementExpressionNode;
|
import ast.statementexpressions.IStatementExpressionNode;
|
||||||
|
import bytecode.visitor.MethodVisitor;
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
|
import visitor.Visitable;
|
||||||
import semantic.TypeCheckResult;
|
import semantic.TypeCheckResult;
|
||||||
|
|
||||||
public class IncrementNode implements IStatementExpressionNode {
|
public class IncrementNode implements IStatementExpressionNode, Visitable {
|
||||||
public CrementType crementType;
|
public CrementType crementType;
|
||||||
public AssignableNode assignableExpression;
|
public AssignableNode assignableExpression;
|
||||||
|
|
||||||
@ -18,4 +20,9 @@ public class IncrementNode implements IStatementExpressionNode {
|
|||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(MethodVisitor methodVisitor) {
|
||||||
|
methodVisitor.visit(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,6 @@ public class ChainedMethodNode implements ASTNode, Visitable {
|
|||||||
expressions.add(expression);
|
expressions.add(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void accept(MethodVisitor methodVisitor) {
|
|
||||||
methodVisitor.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ast.statements;
|
package ast.statements;
|
||||||
|
|
||||||
|
import bytecode.visitor.MethodVisitor;
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
import semantic.TypeCheckResult;
|
import semantic.TypeCheckResult;
|
||||||
import visitor.Visitable;
|
import visitor.Visitable;
|
||||||
@ -22,4 +23,9 @@ public class BlockNode implements IStatementNode, Visitable {
|
|||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(MethodVisitor methodVisitor) {
|
||||||
|
methodVisitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ast.statements;
|
package ast.statements;
|
||||||
|
|
||||||
|
import bytecode.visitor.MethodVisitor;
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
import semantic.TypeCheckResult;
|
import semantic.TypeCheckResult;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ast.statements;
|
package ast.statements;
|
||||||
|
|
||||||
|
import bytecode.visitor.MethodVisitor;
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
import semantic.TypeCheckResult;
|
import semantic.TypeCheckResult;
|
||||||
|
|
||||||
@ -20,6 +21,11 @@ public class IfElseNode implements IStatementNode {
|
|||||||
elseIfStatements.add(elseIfStament);
|
elseIfStatements.add(elseIfStament);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(MethodVisitor methodVisitor) {
|
||||||
|
methodVisitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ast.statements;
|
package ast.statements;
|
||||||
|
|
||||||
import ast.expressions.IExpressionNode;
|
import ast.expressions.IExpressionNode;
|
||||||
|
import bytecode.visitor.MethodVisitor;
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
import semantic.TypeCheckResult;
|
import semantic.TypeCheckResult;
|
||||||
|
|
||||||
@ -17,6 +18,11 @@ public class WhileNode implements IStatementNode {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(MethodVisitor methodVisitor) {
|
||||||
|
methodVisitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
|
@ -27,7 +27,7 @@ public class ClassCodeGen implements ClassVisitor {
|
|||||||
private final boolean generateClassFiles;
|
private final boolean generateClassFiles;
|
||||||
|
|
||||||
public ClassCodeGen(JarOutputStream jarOutputStream, String outputDirectory, boolean generateJar, boolean generateClassFiles) {
|
public ClassCodeGen(JarOutputStream jarOutputStream, String outputDirectory, boolean generateJar, boolean generateClassFiles) {
|
||||||
mapper = new Mapper();
|
this.mapper = new Mapper();
|
||||||
this.jarOutputStream = jarOutputStream;
|
this.jarOutputStream = jarOutputStream;
|
||||||
this.outputDirectory = outputDirectory;
|
this.outputDirectory = outputDirectory;
|
||||||
this.generateJar = generateJar;
|
this.generateJar = generateJar;
|
||||||
|
@ -3,6 +3,7 @@ package bytecode;
|
|||||||
import ast.parameters.ParameterNode;
|
import ast.parameters.ParameterNode;
|
||||||
import ast.type.*;
|
import ast.type.*;
|
||||||
import ast.type.type.BaseType;
|
import ast.type.type.BaseType;
|
||||||
|
import ast.type.type.ITypeNode;
|
||||||
import ast.type.type.ReferenceType;
|
import ast.type.type.ReferenceType;
|
||||||
import ast.type.type.TypeEnum;
|
import ast.type.type.TypeEnum;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@ -24,7 +25,7 @@ public class Mapper {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateMethodDescriptor(BaseType type, List<ParameterNode> parameters) {
|
public String generateMethodDescriptor(ITypeNode type, List<ParameterNode> parameters) {
|
||||||
String descriptor = "(";
|
String descriptor = "(";
|
||||||
for (ParameterNode parameterNode : parameters) {
|
for (ParameterNode parameterNode : parameters) {
|
||||||
if(parameterNode.type instanceof BaseType) {
|
if(parameterNode.type instanceof BaseType) {
|
||||||
@ -35,7 +36,11 @@ public class Mapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
descriptor += ")";
|
descriptor += ")";
|
||||||
descriptor += getTypeChar(type);
|
if(type instanceof BaseType) {
|
||||||
|
descriptor += getTypeChar((BaseType) type);
|
||||||
|
} else if(type instanceof ReferenceType) {
|
||||||
|
descriptor += "L" + ((ReferenceType) type).getIdentifier() +";";
|
||||||
|
}
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,9 +14,10 @@ import ast.statementexpressions.NewDeclarationNode;
|
|||||||
import ast.statementexpressions.crementexpressions.CrementType;
|
import ast.statementexpressions.crementexpressions.CrementType;
|
||||||
import ast.statementexpressions.crementexpressions.DecrementNode;
|
import ast.statementexpressions.crementexpressions.DecrementNode;
|
||||||
import ast.statementexpressions.crementexpressions.IncrementNode;
|
import ast.statementexpressions.crementexpressions.IncrementNode;
|
||||||
import ast.statementexpressions.methodcallstatementnexpressions.ChainedMethodNode;
|
|
||||||
import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
|
import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
|
||||||
import ast.statements.*;
|
import ast.statements.*;
|
||||||
|
import ast.type.AccessModifierNode;
|
||||||
|
import ast.type.EnumAccessModifierNode;
|
||||||
import ast.type.ValueNode;
|
import ast.type.ValueNode;
|
||||||
import ast.type.type.BaseType;
|
import ast.type.type.BaseType;
|
||||||
import ast.type.type.ReferenceType;
|
import ast.type.type.ReferenceType;
|
||||||
@ -70,9 +71,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
|
|
||||||
// Visit all statements
|
// Visit all statements
|
||||||
for (IStatementNode statementNode : constructorNode.block.statements) {
|
for (IStatementNode statementNode : constructorNode.block.statements) {
|
||||||
if (statementNode != null) {
|
statementNode.accept(this);
|
||||||
statementNode.accept(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
methodVisitor.visitMaxs(0, 0);
|
methodVisitor.visitMaxs(0, 0);
|
||||||
@ -81,8 +80,10 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MainMethodNode mainMethodNode) {
|
public void visit(MainMethodNode mainMethodNode) {
|
||||||
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(mainMethodNode.accesModifier),
|
AccessModifierNode accessModifierNode = new AccessModifierNode("");
|
||||||
mainMethodNode.getIdentifier(),
|
accessModifierNode.accessType = EnumAccessModifierNode.PUBLIC_STATIC;
|
||||||
|
methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||||
|
"main",
|
||||||
"([Ljava/lang/String;)V",
|
"([Ljava/lang/String;)V",
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
@ -104,7 +105,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
public void visit(MethodNode methodNode) {
|
public void visit(MethodNode methodNode) {
|
||||||
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.accesModifier),
|
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.accesModifier),
|
||||||
methodNode.getIdentifier(),
|
methodNode.getIdentifier(),
|
||||||
mapper.generateMethodDescriptor((BaseType) methodNode.getType(), methodNode.parameters),
|
mapper.generateMethodDescriptor(methodNode.getType(), methodNode.parameters),
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
|
|
||||||
@ -240,7 +241,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
nonCalculationNode.unaryExpression.accept(this);
|
nonCalculationNode.unaryExpression.accept(this);
|
||||||
nonCalculationNode.expression.accept(this);
|
nonCalculationNode.expression.accept(this);
|
||||||
if (nonCalculationNode.unaryExpression.getType() instanceof BaseType && nonCalculationNode.expression.getType() instanceof BaseType) {
|
if (nonCalculationNode.unaryExpression.getType() instanceof BaseType && nonCalculationNode.expression.getType() instanceof BaseType) {
|
||||||
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
methodVisitor.visitJumpInsn(IF_ICMPEQ, labelFalse);
|
||||||
} else {
|
} else {
|
||||||
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
||||||
}
|
}
|
||||||
@ -265,9 +266,17 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(MemberAccessNode memberAccessNode) {
|
public void visit(MemberAccessNode memberAccessNode) {
|
||||||
// Only used to get, not to put
|
// Only used to get, not to put
|
||||||
if (memberAccessNode.thisExpr) { // Field
|
int localVarIndex = localVariables.indexOf("memberAccessNode.identifier"); // TODO
|
||||||
// methodVisitor.visitFieldInsn(GETFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), );
|
if (localVarIndex >= 0) { // local var object
|
||||||
} else { // Object Attribut
|
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||||
|
} else { // this field
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memberAccessNode.getTypeNode() instanceof BaseType) {
|
||||||
|
methodVisitor.visitFieldInsn(GETFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), mapper.getTypeChar((BaseType) memberAccessNode.getTypeNode()));
|
||||||
|
} else if (memberAccessNode.getTypeNode() instanceof ReferenceType) {
|
||||||
|
methodVisitor.visitFieldInsn(GETFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), "L" + ((ReferenceType) memberAccessNode.getTypeNode()).getIdentifier() + ";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,9 +322,17 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
|
|
||||||
// Statements
|
// Statements
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BlockNode blockNode) {
|
||||||
|
for(IStatementNode statementNode : blockNode.statements) {
|
||||||
|
statementNode.accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IfElseNode ifElseNode) {
|
public void visit(IfElseNode ifElseNode) {
|
||||||
Label elseLabel = new Label();
|
Label elseLabel = new Label();
|
||||||
|
Label endLabel = new Label();
|
||||||
|
|
||||||
Label[] elseIfLabels = new Label[ifElseNode.elseIfStatements.size()];
|
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++) {
|
||||||
@ -330,9 +347,9 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
// else if statements
|
// else if statements
|
||||||
methodVisitor.visitJumpInsn(IFEQ, elseIfLabels[0]);
|
methodVisitor.visitJumpInsn(IFEQ, elseIfLabels[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ifElseNode.ifStatement.block.accept(this); // accept if block
|
ifElseNode.ifStatement.block.accept(this); // accept if block
|
||||||
|
|
||||||
Label endLabel = new Label();
|
|
||||||
methodVisitor.visitJumpInsn(GOTO, endLabel);
|
methodVisitor.visitJumpInsn(GOTO, endLabel);
|
||||||
|
|
||||||
for (int i = 0; i < ifElseNode.elseIfStatements.size(); i++) {
|
for (int i = 0; i < ifElseNode.elseIfStatements.size(); i++) {
|
||||||
@ -351,6 +368,8 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
if (ifElseNode.elseStatement != null) {
|
if (ifElseNode.elseStatement != null) {
|
||||||
methodVisitor.visitLabel(elseLabel);
|
methodVisitor.visitLabel(elseLabel);
|
||||||
ifElseNode.elseStatement.block.accept(this);
|
ifElseNode.elseStatement.block.accept(this);
|
||||||
|
} else {
|
||||||
|
methodVisitor.visitLabel(elseLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
methodVisitor.visitLabel(endLabel);
|
methodVisitor.visitLabel(endLabel);
|
||||||
@ -361,22 +380,17 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
if (localVariableDeclarationNode.expression != null) {
|
if (localVariableDeclarationNode.expression != null) {
|
||||||
// Process expression
|
// Process expression
|
||||||
localVariableDeclarationNode.expression.accept(this);
|
localVariableDeclarationNode.expression.accept(this);
|
||||||
// Store result of expression in variable
|
// add local var to list if not in list
|
||||||
if (localVariables.contains(localVariableDeclarationNode.identifier)) {
|
if (!localVariables.contains(localVariableDeclarationNode.identifier)) {
|
||||||
if (localVariableDeclarationNode.type instanceof BaseType) {
|
|
||||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
|
||||||
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
|
||||||
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
localVariables.add(localVariableDeclarationNode.identifier);
|
localVariables.add(localVariableDeclarationNode.identifier);
|
||||||
if (localVariableDeclarationNode.type instanceof BaseType) {
|
}
|
||||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
if (localVariableDeclarationNode.type instanceof BaseType) {
|
||||||
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||||
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
||||||
}
|
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Local var declaration
|
||||||
if (!localVariables.contains(localVariableDeclarationNode.identifier)) {
|
if (!localVariables.contains(localVariableDeclarationNode.identifier)) {
|
||||||
localVariables.add(localVariableDeclarationNode.identifier);
|
localVariables.add(localVariableDeclarationNode.identifier);
|
||||||
}
|
}
|
||||||
@ -385,38 +399,105 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignNode assignNode) {
|
public void visit(AssignNode assignNode) {
|
||||||
// Process expression
|
if (assignNode.assignable.memberAccess != null) { // this / object
|
||||||
if (assignNode.expression instanceof IncrementNode incrementNode) {
|
if (assignNode.expression instanceof IncrementNode) {
|
||||||
|
if (((IncrementNode) assignNode.expression).crementType.equals(CrementType.PREFIX)) { // ++i
|
||||||
|
fieldOrObjectVarPrefixCrementAssign(assignNode);
|
||||||
|
} else { // i++
|
||||||
|
fieldOrObjectVarSuffixCrementAssign(assignNode);
|
||||||
|
}
|
||||||
|
} else if (assignNode.expression instanceof DecrementNode) {
|
||||||
|
if (((DecrementNode) assignNode.expression).crementType.equals(CrementType.PREFIX)) {
|
||||||
|
fieldOrObjectVarPrefixCrementAssign(assignNode);
|
||||||
|
} else {
|
||||||
|
fieldOrObjectVarSuffixCrementAssign(assignNode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assignFieldOrObjectVar(assignNode);
|
||||||
|
}
|
||||||
|
} else { // local var
|
||||||
|
if (assignNode.expression instanceof IncrementNode || assignNode.expression instanceof DecrementNode) {
|
||||||
|
localVarCrementAssign(assignNode);
|
||||||
|
} else {
|
||||||
|
assignNode.expression.accept(this);
|
||||||
|
assignLocalVar(assignNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void localVarCrementAssign(AssignNode assignNode) {
|
||||||
|
if (assignNode.expression instanceof IncrementNode) {
|
||||||
|
IncrementNode incrementNode = (IncrementNode) assignNode.expression;
|
||||||
if (incrementNode.crementType.equals(CrementType.PREFIX)) { // ++i
|
if (incrementNode.crementType.equals(CrementType.PREFIX)) { // ++i
|
||||||
methodVisitor.visitIincInsn(localVariables.indexOf(incrementNode.assignableExpression.identifier), 1);
|
incrementNode.accept(this);
|
||||||
assign(assignNode);
|
assignLocalVar(assignNode);
|
||||||
} else if (incrementNode.crementType.equals(CrementType.SUFFIX)) { // Suffix: i++
|
} else { // i++
|
||||||
assign(assignNode);
|
loadBeforeCrement(assignNode);
|
||||||
methodVisitor.visitIincInsn(localVariables.indexOf(incrementNode.assignableExpression.identifier), 1);
|
assignLocalVar(assignNode);
|
||||||
|
incrementNode.accept(this);
|
||||||
}
|
}
|
||||||
} else if (assignNode.expression instanceof DecrementNode decrementNode) {
|
} else if (assignNode.expression instanceof DecrementNode decrementNode) {
|
||||||
if (decrementNode.crementType.equals(CrementType.PREFIX)) {
|
if (decrementNode.crementType.equals(CrementType.PREFIX)) {
|
||||||
methodVisitor.visitIincInsn(localVariables.indexOf(decrementNode.assignableExpression.identifier), -1);
|
decrementNode.accept(this);
|
||||||
assign(assignNode);
|
assignLocalVar(assignNode);
|
||||||
} else if (decrementNode.crementType.equals(CrementType.SUFFIX)) {
|
} else {
|
||||||
assign(assignNode);
|
loadBeforeCrement(assignNode);
|
||||||
methodVisitor.visitIincInsn(localVariables.indexOf(decrementNode.assignableExpression.identifier), 1);
|
assignLocalVar(assignNode);
|
||||||
|
decrementNode.accept(this);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
assignNode.expression.accept(this);
|
|
||||||
assign(assignNode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assign(AssignNode assignNode) {
|
private void fieldOrObjectVarPrefixCrementAssign(AssignNode assignNode) {
|
||||||
if (assignNode.assignable.memberAccess.thisExpr) {
|
int localVarIndex = localVariables.indexOf(assignNode.assignable.identifier);
|
||||||
assignField(assignNode);
|
if(localVarIndex >= 0) { // object
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||||
|
} else if(assignNode.assignable.memberAccess.thisExpr) { // field
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||||
} else {
|
} else {
|
||||||
assignLocalVar(assignNode);
|
localVariables.add(assignNode.assignable.identifier);
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assignNode.expression.accept(this);
|
||||||
|
methodVisitor.visitInsn(DUP_X1);
|
||||||
|
|
||||||
|
if (assignNode.expression instanceof BaseType) {
|
||||||
|
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
||||||
|
} else if (assignNode.expression instanceof ReferenceType) {
|
||||||
|
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
||||||
|
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L" + referenceType.getIdentifier() + ";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fieldOrObjectVarSuffixCrementAssign(AssignNode assignNode) {
|
||||||
|
int localVarIndex = localVariables.indexOf(assignNode.assignable.identifier);
|
||||||
|
if(localVarIndex >= 0) { // object
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||||
|
} else if(assignNode.assignable.memberAccess.thisExpr) { // field
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||||
|
} else {
|
||||||
|
localVariables.add(assignNode.assignable.identifier);
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
loadBeforeCrement(assignNode);
|
||||||
|
|
||||||
|
if (assignNode.expression instanceof BaseType) {
|
||||||
|
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
||||||
|
} else if (assignNode.expression instanceof ReferenceType) {
|
||||||
|
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
||||||
|
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L" + referenceType.getIdentifier() + ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
assignNode.expression.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignLocalVar(AssignNode assignNode) {
|
private void assignLocalVar(AssignNode assignNode) {
|
||||||
|
methodVisitor.visitInsn(DUP);
|
||||||
|
if (!localVariables.contains(assignNode.assignable.identifier)) {
|
||||||
|
localVariables.add(assignNode.assignable.identifier);
|
||||||
|
}
|
||||||
if (assignNode.expression instanceof BaseType) {
|
if (assignNode.expression instanceof BaseType) {
|
||||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(assignNode.assignable.identifier));
|
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(assignNode.assignable.identifier));
|
||||||
} else if (assignNode.expression instanceof ReferenceType) {
|
} else if (assignNode.expression instanceof ReferenceType) {
|
||||||
@ -424,12 +505,105 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignField(AssignNode assignNode) {
|
private void assignFieldOrObjectVar(AssignNode assignNode) {
|
||||||
|
int localVarIndex = localVariables.indexOf(assignNode.assignable.identifier);
|
||||||
|
if (localVarIndex >= 0) { // object
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||||
|
} else if (assignNode.assignable.memberAccess.thisExpr) { // this
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||||
|
} else {
|
||||||
|
localVariables.add(assignNode.assignable.identifier);
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
assignNode.expression.accept(this);
|
||||||
|
methodVisitor.visitInsn(DUP_X1);
|
||||||
|
|
||||||
if (assignNode.expression instanceof BaseType) {
|
if (assignNode.expression instanceof BaseType) {
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
||||||
} else if (assignNode.expression instanceof ReferenceType) {
|
} else if (assignNode.expression instanceof ReferenceType) {
|
||||||
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
||||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L"+referenceType.getIdentifier()+";");
|
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L" + referenceType.getIdentifier() + ";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadBeforeCrement(AssignNode assignNode) {
|
||||||
|
if(assignNode.expression instanceof IncrementNode) {
|
||||||
|
IncrementNode incrementNode = (IncrementNode) assignNode.expression;
|
||||||
|
if(incrementNode.assignableExpression.memberAccess != null) {
|
||||||
|
incrementNode.assignableExpression.memberAccess.accept(this);
|
||||||
|
} else {
|
||||||
|
if(assignNode.assignable.typeNode instanceof BaseType) {
|
||||||
|
methodVisitor.visitVarInsn(ILOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||||
|
} else if(assignNode.assignable.typeNode instanceof ReferenceType) {
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(assignNode.expression instanceof DecrementNode) {
|
||||||
|
DecrementNode decrementNode = (DecrementNode) assignNode.expression;
|
||||||
|
if(decrementNode.assignableExpression.memberAccess != null) {
|
||||||
|
decrementNode.assignableExpression.memberAccess.accept(this);
|
||||||
|
} else {
|
||||||
|
if(assignNode.assignable.typeNode instanceof BaseType) {
|
||||||
|
methodVisitor.visitVarInsn(ILOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||||
|
} else if(assignNode.assignable.typeNode instanceof ReferenceType) {
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IncrementNode incrementNode) {
|
||||||
|
if (incrementNode.assignableExpression.memberAccess != null) { // Object var / field
|
||||||
|
int localVarIndex = localVariables.indexOf(incrementNode.assignableExpression.identifier);
|
||||||
|
if (localVarIndex >= 0) { // object
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||||
|
} else { // this
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||||
|
}
|
||||||
|
if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
||||||
|
methodVisitor.visitFieldInsn(GETFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) incrementNode.assignableExpression.memberAccess.getTypeNode()));
|
||||||
|
} else if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
||||||
|
methodVisitor.visitFieldInsn(GETFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) incrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
||||||
|
}
|
||||||
|
methodVisitor.visitInsn(DUP);
|
||||||
|
methodVisitor.visitInsn(ICONST_1);
|
||||||
|
methodVisitor.visitInsn(IADD);
|
||||||
|
if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
||||||
|
methodVisitor.visitFieldInsn(PUTFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) incrementNode.assignableExpression.memberAccess.getTypeNode()));
|
||||||
|
} else if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
||||||
|
methodVisitor.visitFieldInsn(PUTFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) incrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
||||||
|
}
|
||||||
|
} else { // local var
|
||||||
|
methodVisitor.visitIincInsn(localVariables.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(DecrementNode decrementNode) {
|
||||||
|
if (decrementNode.assignableExpression.memberAccess != null) { // Object var / field
|
||||||
|
int localVarIndex = localVariables.indexOf(decrementNode.assignableExpression.identifier);
|
||||||
|
if (localVarIndex >= 0) { // object
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||||
|
} else { // this
|
||||||
|
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||||
|
}
|
||||||
|
methodVisitor.visitInsn(DUP);
|
||||||
|
if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
||||||
|
methodVisitor.visitFieldInsn(GETFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) decrementNode.assignableExpression.memberAccess.getTypeNode()));
|
||||||
|
} else if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
||||||
|
methodVisitor.visitFieldInsn(GETFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) decrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
||||||
|
}
|
||||||
|
methodVisitor.visitInsn(ICONST_1);
|
||||||
|
methodVisitor.visitInsn(ISUB);
|
||||||
|
if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
||||||
|
methodVisitor.visitFieldInsn(PUTFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) decrementNode.assignableExpression.memberAccess.getTypeNode()));
|
||||||
|
} else if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
||||||
|
methodVisitor.visitFieldInsn(PUTFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) decrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
||||||
|
}
|
||||||
|
} else { // local var
|
||||||
|
methodVisitor.visitIincInsn(localVariables.indexOf(decrementNode.assignableExpression.identifier), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,8 +616,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
expressionNode.accept(this);
|
expressionNode.accept(this);
|
||||||
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
||||||
}
|
}
|
||||||
methodVisitor.visitMethodInsn(INVOKESPECIAL, newDeclarationNode.identifier, "<init>", mapper.generateMethodDescriptor(new BaseType(TypeEnum.VOID),parameterNodes), false);
|
methodVisitor.visitMethodInsn(INVOKESPECIAL, newDeclarationNode.identifier, "<init>", mapper.generateMethodDescriptor(new BaseType(TypeEnum.VOID), parameterNodes), false);
|
||||||
localVariables.add(newDeclarationNode.identifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -515,19 +688,13 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
|||||||
methodVisitor.visitLabel(endOfLoopLabel);
|
methodVisitor.visitLabel(endOfLoopLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(ChainedMethodNode chainedMethodNode) {
|
|
||||||
// TODO: Erstmal abwarten
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MethodCallNode methodCallNode) {
|
public void visit(MethodCallNode methodCallNode) {
|
||||||
List<ParameterNode> parameterNodes = new ArrayList<>();
|
List<ParameterNode> parameterNodes = new ArrayList<>();
|
||||||
for(IExpressionNode expressionNode : methodCallNode.parameters) {
|
for (IExpressionNode expressionNode : methodCallNode.parameters) {
|
||||||
expressionNode.accept(this);
|
expressionNode.accept(this);
|
||||||
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
||||||
}
|
}
|
||||||
// TODO: Klassenname und Returntype
|
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, methodCallNode.target.memberAccess.identifiers.get(0), methodCallNode.identifier, mapper.generateMethodDescriptor(methodCallNode.type, parameterNodes), false);
|
||||||
//methodVisitor.visitMethodInsn(INVOKEVIRTUAL, classname, methodCallNode.identifier, mapper.generateMethodDescriptor(returntype, parameterNodes), false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,5 @@ import ast.members.FieldNode;
|
|||||||
|
|
||||||
public interface ClassVisitor {
|
public interface ClassVisitor {
|
||||||
void visit(ClassNode classNode);
|
void visit(ClassNode classNode);
|
||||||
|
|
||||||
void visit(FieldNode fieldNode);
|
void visit(FieldNode fieldNode);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ import ast.members.MainMethodNode;
|
|||||||
import ast.members.MethodNode;
|
import ast.members.MethodNode;
|
||||||
import ast.statementexpressions.AssignNode;
|
import ast.statementexpressions.AssignNode;
|
||||||
import ast.statementexpressions.NewDeclarationNode;
|
import ast.statementexpressions.NewDeclarationNode;
|
||||||
|
import ast.statementexpressions.crementexpressions.DecrementNode;
|
||||||
|
import ast.statementexpressions.crementexpressions.IncrementNode;
|
||||||
import ast.statementexpressions.methodcallstatementnexpressions.ChainedMethodNode;
|
import ast.statementexpressions.methodcallstatementnexpressions.ChainedMethodNode;
|
||||||
import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
|
import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
|
||||||
import ast.statements.*;
|
import ast.statements.*;
|
||||||
@ -41,8 +43,12 @@ public interface MethodVisitor {
|
|||||||
void visit(UnaryNode unaryExpressionNode);
|
void visit(UnaryNode unaryExpressionNode);
|
||||||
|
|
||||||
// statements
|
// statements
|
||||||
|
void visit(BlockNode blockNode);
|
||||||
void visit(IfElseNode ifElseNode);
|
void visit(IfElseNode ifElseNode);
|
||||||
|
|
||||||
|
void visit(IncrementNode incrementNode);
|
||||||
|
void visit(DecrementNode decrementNode);
|
||||||
|
|
||||||
void visit(LocalVariableDeclarationNode localVariableDeclarationNode);
|
void visit(LocalVariableDeclarationNode localVariableDeclarationNode);
|
||||||
|
|
||||||
void visit(ReturnNode returnNode);
|
void visit(ReturnNode returnNode);
|
||||||
@ -50,8 +56,6 @@ public interface MethodVisitor {
|
|||||||
void visit(WhileNode whileNode);
|
void visit(WhileNode whileNode);
|
||||||
|
|
||||||
// statement expression
|
// statement expression
|
||||||
void visit(ChainedMethodNode chainedMethodNode);
|
|
||||||
|
|
||||||
void visit(MethodCallNode methodCallNode);
|
void visit(MethodCallNode methodCallNode);
|
||||||
|
|
||||||
void visit(AssignNode assignNode);
|
void visit(AssignNode assignNode);
|
||||||
|
Loading…
Reference in New Issue
Block a user