Code for assignment
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
i22007 2024-05-31 10:46:23 +02:00
parent 1c77a99f54
commit 407b03620e
17 changed files with 186 additions and 45 deletions

View File

@ -33,6 +33,11 @@
<artifactId>asm</artifactId> <artifactId>asm</artifactId>
<version>9.7</version> <version>9.7</version>
</dependency> </dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-util</artifactId>
<version>9.2</version>
</dependency>
</dependencies> </dependencies>

View File

@ -1,12 +1,14 @@
package ast; package ast;
import ast.expression.ExpressionNode; import ast.expression.ExpressionNode;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable;
public class LiteralNode implements ExpressionNode { public class LiteralNode implements ExpressionNode, Visitable {
int value; public int value;
private String type; private String type;
public LiteralNode(int value) { public LiteralNode(int value) {
@ -26,4 +28,9 @@ public class LiteralNode implements ExpressionNode {
public TypeCheckResult accept(SemanticVisitor visitor) { public TypeCheckResult accept(SemanticVisitor visitor) {
return null; return null;
} }
@Override
public void accept(MethodVisitor methodVisitor) {
methodVisitor.visit(this);
}
} }

View File

@ -1,5 +1,6 @@
package ast.expression; package ast.expression;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable; import visitor.Visitable;
@ -19,4 +20,9 @@ public class BinaryExpressionNode implements ExpressionNode, Visitable {
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);
}
} }

View File

@ -1,6 +1,7 @@
package ast.expression; package ast.expression;
import ast.type.TypeNode; import ast.type.TypeNode;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -11,12 +12,18 @@ public class IdentifierExpressionNode implements ExpressionNode, Visitable {
public TypeNode type; public TypeNode type;
public IdentifierExpressionNode(String name) { public IdentifierExpressionNode(String name, TypeNode type) {
this.name = name; this.name = name;
this.type = type;
} }
@Override @Override
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);
}
} }

View File

@ -1,5 +1,6 @@
package ast.expression; package ast.expression;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable; import visitor.Visitable;
@ -17,6 +18,11 @@ public class UnaryExpressionNode implements ExpressionNode, Visitable {
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);
}
} }

View File

@ -1,6 +1,8 @@
package ast.statement; package ast.statement;
import ast.expression.BinaryExpressionNode; import ast.expression.BinaryExpressionNode;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable; import visitor.Visitable;
@ -16,4 +18,9 @@ public class AssignmentStatementNode extends StatementNode implements Visitable
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);
}
} }

View File

@ -1,10 +1,12 @@
package ast.statement; package ast.statement;
import ast.expression.ExpressionNode; import ast.expression.ExpressionNode;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable;
public class IfStatementNode extends StatementNode { public class IfStatementNode extends StatementNode implements Visitable {
public ExpressionNode condition; public ExpressionNode condition;
public StatementNode thenStatement; public StatementNode thenStatement;
public StatementNode elseStatement; public StatementNode elseStatement;
@ -19,4 +21,9 @@ public class IfStatementNode extends StatementNode {
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);
}
} }

View File

@ -1,10 +1,12 @@
package ast.statement; package ast.statement;
import ast.expression.ExpressionNode; import ast.expression.ExpressionNode;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable;
public class ReturnStatementNode extends StatementNode { public class ReturnStatementNode extends StatementNode implements Visitable {
public ExpressionNode expression; public ExpressionNode expression;
public ReturnStatementNode(ExpressionNode expression) { public ReturnStatementNode(ExpressionNode expression) {
@ -15,4 +17,9 @@ public class ReturnStatementNode extends StatementNode {
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);
}
} }

View File

@ -1,6 +1,7 @@
package ast.statement; package ast.statement;
import ast.ASTNode; import ast.ASTNode;
import bytecode.visitor.MethodVisitor;
import visitor.Visitable; import visitor.Visitable;
public abstract class StatementNode implements ASTNode, Visitable { public abstract class StatementNode implements ASTNode, Visitable {

View File

@ -2,10 +2,12 @@ package ast.statement;
import ast.expression.ExpressionNode; import ast.expression.ExpressionNode;
import ast.type.TypeNode; import ast.type.TypeNode;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable;
public class VariableDeclarationStatementNode extends StatementNode { public class VariableDeclarationStatementNode extends StatementNode implements Visitable {
public TypeNode type; public TypeNode type;
public String identifier; public String identifier;
public ExpressionNode expression; public ExpressionNode expression;
@ -19,4 +21,9 @@ public class VariableDeclarationStatementNode extends StatementNode {
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);
}
} }

View File

@ -1,10 +1,12 @@
package ast.statement; package ast.statement;
import ast.expression.ExpressionNode; import ast.expression.ExpressionNode;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor; import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable;
public class WhileStatementNode extends StatementNode { public class WhileStatementNode extends StatementNode implements Visitable {
public ExpressionNode condition; public ExpressionNode condition;
public StatementNode body; public StatementNode body;
@ -17,4 +19,9 @@ public class WhileStatementNode extends StatementNode {
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);
}
} }

View File

@ -8,9 +8,13 @@ public class ByteCodeGenerator implements ProgramVisitor {
@Override @Override
public void visit(ProgramNode programNode) { public void visit(ProgramNode programNode) {
//ASMCodeGenerator asmCodeGenerator = new ASMCodeGenerator();
//asmCodeGenerator.test();
for (ClassNode classDeclarationNode : programNode.classes) { for (ClassNode classDeclarationNode : programNode.classes) {
ClassCodeGen classCodeGen = new ClassCodeGen(); ClassCodeGen classCodeGen = new ClassCodeGen();
classDeclarationNode.accept(classCodeGen); classDeclarationNode.accept(classCodeGen);
} }
} }
} }

View File

@ -52,7 +52,7 @@ public class ClassCodeGen implements ClassVisitor {
} }
private void printIntoClassFile(byte[] byteCode, String name) { private void printIntoClassFile(byte[] byteCode, String name) {
String directoryPath = "src/main/java/classFileOutput"; String directoryPath = "src/main/resources/classFileOutput";
File directory = new File(directoryPath); File directory = new File(directoryPath);
if (!directory.exists()) { if (!directory.exists()) {
directory.mkdirs(); directory.mkdirs();

View File

@ -1,15 +1,18 @@
package bytecode; package bytecode;
import ast.LiteralNode;
import ast.expression.BinaryExpressionNode;
import ast.expression.IdentifierExpressionNode;
import ast.expression.UnaryExpressionNode;
import ast.member.ConstructorNode; import ast.member.ConstructorNode;
import ast.member.MethodNode; import ast.member.MethodNode;
import ast.parameter.ParameterListNode;
import ast.parameter.ParameterNode; import ast.parameter.ParameterNode;
import ast.statement.*;
import ast.type.BaseTypeNode; import ast.type.BaseTypeNode;
import ast.type.EnumTypeNode; import ast.type.ReferenceTypeNode;
import ast.type.TypeNode;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -50,7 +53,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
@Override @Override
public void visit(MethodNode methodNode) { public void visit(MethodNode methodNode) {
if (methodNode.type instanceof BaseTypeNode baseTypeNode) { if (methodNode.type instanceof BaseTypeNode baseTypeNode) {
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.visibility), methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.visibility) | ACC_STATIC,
methodNode.identifier, methodNode.identifier,
mapper.generateMethodDescriptor(baseTypeNode, methodNode.parameters), mapper.generateMethodDescriptor(baseTypeNode, methodNode.parameters),
null, null,
@ -58,43 +61,90 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
methodVisitor.visitCode(); methodVisitor.visitCode();
localVaribales.add("this"); localVaribales.add("this");
// Add all method parameters to localVariables
for (ParameterNode parameterNode : methodNode.parameters.parameters) { for (ParameterNode parameterNode : methodNode.parameters.parameters) {
localVaribales.add(parameterNode.identifier); localVaribales.add(parameterNode.identifier);
} }
//test(); // Visit all statements
for(StatementNode statementNode : methodNode.statements) {
statementNode.accept(this);
}
methodVisitor.visitMaxs(1, localVaribales.size()); methodVisitor.visitMaxs(1, localVaribales.size());
methodVisitor.visitEnd(); methodVisitor.visitEnd();
} }
} }
public void test() { @Override
Label start = new Label(); public void visit(AssignmentStatementNode assignmentStatementNode) {
Label loop = new Label(); BinaryExpressionNode expressionNode = assignmentStatementNode.expression;
Label end = new Label();
methodVisitor.visitLabel(start); if(expressionNode.left instanceof IdentifierExpressionNode) { // Local var
//methodVisitor.visitVarInsn(Opcodes.ICONST_M1, 99); expressionNode.right.accept(this);
//methodVisitor.visitInsn(Opcodes.ICONST_5); localVarAssignment((IdentifierExpressionNode) expressionNode.left);
methodVisitor.visitLdcInsn(99); } else if(expressionNode.left instanceof BinaryExpressionNode) { // Global var
// methodVisitor.visitInsn(Opcodes.ICONST_0); expressionNode.right.accept(this);
//methodVisitor.visitVarInsn(Opcodes.ILOAD, 2); globalVarAssignment((BinaryExpressionNode) expressionNode.left);
methodVisitor.visitVarInsn(Opcodes.ISTORE, 1); }
methodVisitor.visitLabel(loop);
methodVisitor.visitVarInsn(Opcodes.ILOAD, 1); assignmentStatementNode.expression.accept(this);
methodVisitor.visitInsn(Opcodes.ICONST_5); methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitJumpInsn(Opcodes.IF_ICMPGE, end); }
methodVisitor.visitFieldInsn(Opcodes.GETSTATIC,
"java/lang/System", "out", private void localVarAssignment(IdentifierExpressionNode expressionNode) {
"Ljava/io/PrintStream;"); methodVisitor.visitVarInsn(ILOAD, localVaribales.indexOf(expressionNode.name));
methodVisitor.visitLdcInsn("Bytecode"); }
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"java/io/PrintStream", "println", private void globalVarAssignment(BinaryExpressionNode expressionNode) {
"(Ljava/lang/String;)V", false); IdentifierExpressionNode identifierExpressionNode = (IdentifierExpressionNode) expressionNode.left;
methodVisitor.visitIincInsn(1, 1); IdentifierExpressionNode identifierExpressionNode1 = (IdentifierExpressionNode) expressionNode.right;
methodVisitor.visitJumpInsn(Opcodes.GOTO, loop); TypeNode type = identifierExpressionNode1.type;
methodVisitor.visitLabel(end); if(type instanceof BaseTypeNode) {
methodVisitor.visitVarInsn(Opcodes.ILOAD, 1); methodVisitor.visitFieldInsn(PUTFIELD, identifierExpressionNode.name, identifierExpressionNode1.name, mapper.getTypeChar(((BaseTypeNode) type).enumType));
methodVisitor.visitInsn(Opcodes.IRETURN); } else if (type instanceof ReferenceTypeNode) {
methodVisitor.visitEnd();
}
}
@Override
public void visit(IfStatementNode ifStatementNode) {
}
@Override
public void visit(ReturnStatementNode returnStatementNode) {
returnStatementNode.expression.accept(this);
methodVisitor.visitInsn(IRETURN);
}
@Override
public void visit(VariableDeclarationStatementNode variableDeclarationStatementNode) {
}
@Override
public void visit(WhileStatementNode whileStatementNode) {
}
@Override
public void visit(BinaryExpressionNode binaryExpressionNode) {
}
@Override
public void visit(IdentifierExpressionNode identifierExpressionNode) {
methodVisitor.visitVarInsn(ILOAD, localVaribales.indexOf(identifierExpressionNode.name));
}
@Override
public void visit(UnaryExpressionNode unaryExpressionNode) {
}
@Override
public void visit(LiteralNode literalNode) {
methodVisitor.visitVarInsn(BIPUSH, literalNode.value);
} }
} }

View File

@ -1,9 +1,23 @@
package bytecode.visitor; package bytecode.visitor;
import ast.LiteralNode;
import ast.expression.BinaryExpressionNode;
import ast.expression.IdentifierExpressionNode;
import ast.expression.UnaryExpressionNode;
import ast.member.ConstructorNode; import ast.member.ConstructorNode;
import ast.member.MethodNode; import ast.member.MethodNode;
import ast.statement.*;
public interface MethodVisitor { public interface MethodVisitor {
void visit(ConstructorNode constructorNode); void visit(ConstructorNode constructorNode);
void visit(MethodNode methodNode); void visit(MethodNode methodNode);
void visit(AssignmentStatementNode assignmentStatementNode);
void visit(IfStatementNode ifStatementNode);
void visit(ReturnStatementNode returnStatementNode);
void visit(VariableDeclarationStatementNode variableDeclarationStatementNode);
void visit(WhileStatementNode whileStatementNode);
void visit(BinaryExpressionNode binaryExpressionNode);
void visit(IdentifierExpressionNode identifierExpressionNode);
void visit(UnaryExpressionNode unaryExpressionNode);
void visit(LiteralNode literalNode);
} }

View File

@ -198,7 +198,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
return visit(ctx.literal()); return visit(ctx.literal());
} }
else if (ctx.IDENTIFIER() != null) { else if (ctx.IDENTIFIER() != null) {
return new IdentifierExpressionNode(ctx.IDENTIFIER().getText()); return new IdentifierExpressionNode(ctx.IDENTIFIER().getText(), null);
} }
return null; // Return null or throw an exception if no valid expression found return null; // Return null or throw an exception if no valid expression found

View File

@ -17,6 +17,7 @@ import ast.type.AccessTypeNode;
import ast.type.BaseTypeNode; import ast.type.BaseTypeNode;
import ast.type.EnumAccessTypeNode; import ast.type.EnumAccessTypeNode;
import ast.type.EnumTypeNode; import ast.type.EnumTypeNode;
import bytecode.ByteCodeGenerator;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import semantic.exeptions.AlreadyDeclearedException; import semantic.exeptions.AlreadyDeclearedException;
@ -79,8 +80,8 @@ public class SemanticTest {
List<StatementNode> statementNodeList = new ArrayList<StatementNode>(); List<StatementNode> statementNodeList = new ArrayList<StatementNode>();
ExpressionNode expressionNodeObjectVariableLeft = new IdentifierExpressionNode("this"); ExpressionNode expressionNodeObjectVariableLeft = new IdentifierExpressionNode("Example", null);
ExpressionNode expressionNodeObjectVariableRight = new IdentifierExpressionNode("objectVar"); ExpressionNode expressionNodeObjectVariableRight = new IdentifierExpressionNode("objectVar", new BaseTypeNode(EnumTypeNode.INT));
ExpressionNode expressionNodeLeft = new BinaryExpressionNode(expressionNodeObjectVariableLeft, expressionNodeObjectVariableRight, ExpresssionOperator.DOT); ExpressionNode expressionNodeLeft = new BinaryExpressionNode(expressionNodeObjectVariableLeft, expressionNodeObjectVariableRight, ExpresssionOperator.DOT);
@ -94,6 +95,8 @@ public class SemanticTest {
MemberNode memberNode3 = new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2",parameterListNode, statementNodeList ); MemberNode memberNode3 = new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2",parameterListNode, statementNodeList );
classNode.members.add(memberNode3); classNode.members.add(memberNode3);
classList.add(classNode); classList.add(classNode);
programNode.classes = classList; programNode.classes = classList;
@ -102,6 +105,9 @@ public class SemanticTest {
assertEquals(0, SemanticAnalyzer.errors.size()); assertEquals(0, SemanticAnalyzer.errors.size());
assertEquals(programNode, typedAst); assertEquals(programNode, typedAst);
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator();
byteCodeGenerator.visit((ProgramNode) typedAst);
} }
} }