mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-28 16:48:03 +00:00
refactor ctx structure
This commit is contained in:
parent
ba97c04414
commit
4fe433f961
16
src/main/java/de/maishai/typedast/ClassContext.java
Normal file
16
src/main/java/de/maishai/typedast/ClassContext.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package de.maishai.typedast;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ClassContext {
|
||||||
|
private Type name;
|
||||||
|
private ClassWriter cw;
|
||||||
|
|
||||||
|
public ClassContext(String name, ClassWriter cw) {
|
||||||
|
this.name = Type.REFERENCE(name);
|
||||||
|
this.cw = cw;
|
||||||
|
}
|
||||||
|
}
|
@ -9,16 +9,16 @@ import java.util.Map;
|
|||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
|
||||||
@Data
|
|
||||||
public class MethodContext {
|
public class MethodContext {
|
||||||
|
private record LocalVariable(String name, int index, Type type) {}
|
||||||
private Label startLabel;
|
private Label startLabel;
|
||||||
private Label endLabel;
|
private Label endLabel;
|
||||||
private MethodVisitor mv;
|
private MethodVisitor mv;
|
||||||
private String classname;
|
private String classname;
|
||||||
private int localVarIndex = 0;
|
private int localVarIndex = 0;
|
||||||
private Map<String, Integer> variableIndex = new HashMap<>();
|
private final Map<String, LocalVariable> variableIndex = new HashMap<>();
|
||||||
//private Stack<Integer> stack = new Stack<>();
|
private Stack<Integer> stack = new Stack<>();
|
||||||
|
private int maxStack = 0;
|
||||||
|
|
||||||
public MethodContext(MethodVisitor mv) {
|
public MethodContext(MethodVisitor mv) {
|
||||||
startLabel = new Label();
|
startLabel = new Label();
|
||||||
@ -28,16 +28,35 @@ public class MethodContext {
|
|||||||
mv.visitLabel(startLabel);
|
mv.visitLabel(startLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int addVariable(String name) {
|
public int addVariable(String name, Type type) {
|
||||||
int index = localVarIndex;
|
int index = localVarIndex;
|
||||||
localVarIndex++;
|
localVarIndex++;
|
||||||
variableIndex.put(name, index);
|
variableIndex.put(name, new LocalVariable(name, index, type));
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void wrapUp(int maxStack, int maxLocals) {
|
public int getVariableIndex(String name) {
|
||||||
|
int index = variableIndex.get(name).index;
|
||||||
|
if (index == -1) {
|
||||||
|
throw new RuntimeException("Variable not declared");
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushStack() {
|
||||||
|
stack.push(localVarIndex);
|
||||||
|
if (stack.size() > maxStack) {
|
||||||
|
maxStack = stack.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void popStack() {
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void wrapUp() {
|
||||||
mv.visitLabel(endLabel);
|
mv.visitLabel(endLabel);
|
||||||
mv.visitMaxs(maxStack, maxLocals);
|
mv.visitMaxs(maxStack, localVarIndex);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package de.maishai.typedast;
|
package de.maishai.typedast;
|
||||||
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
|
||||||
|
|
||||||
public interface TypedExpression extends TypedNode {
|
public interface TypedExpression extends TypedNode {
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx);
|
public void codeGen(MethodContext ctx);
|
||||||
|
|
||||||
public Type getType();
|
public Type getType();
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package de.maishai.typedast;
|
package de.maishai.typedast;
|
||||||
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
|
||||||
|
|
||||||
public interface TypedStatement extends TypedNode {
|
public interface TypedStatement extends TypedNode {
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx);
|
public void codeGen(MethodContext ctx);
|
||||||
}
|
}
|
||||||
|
@ -56,11 +56,10 @@ public class TypedAssignment implements TypedStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
if (value instanceof TypedIntLiteral) {
|
if (value instanceof TypedIntLiteral) {
|
||||||
TypedIntLiteral intLiteral = (TypedIntLiteral) value;
|
ctx.getMv().visitIntInsn(Opcodes.BIPUSH, ((TypedIntLiteral) value).getValue());
|
||||||
mv.visitIntInsn(Opcodes.BIPUSH, ((TypedIntLiteral) value).getValue());
|
ctx.getMv().visitVarInsn(Opcodes.ISTORE, ctx.getLocalVarIndex());
|
||||||
mv.visitVarInsn(Opcodes.ISTORE, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ public class TypedBinary implements TypedExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,12 +116,12 @@ public class TypedBlock implements TypedNode {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
for (TypedLocalVariable var : vars) {
|
for (TypedLocalVariable var : vars) {
|
||||||
//var.codeGen(mv, ctx);
|
//var.codeGen(ctx);
|
||||||
}
|
}
|
||||||
for (TypedStatement stmt : stmts) {
|
for (TypedStatement stmt : stmts) {
|
||||||
stmt.codeGen(mv, ctx);
|
stmt.codeGen(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,11 +35,11 @@ public class TypedBoolLiteral implements TypedExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
if(value){
|
if(value){
|
||||||
mv.visitInsn(Opcodes.ICONST_1);
|
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||||
}else{
|
}else{
|
||||||
mv.visitInsn(Opcodes.ICONST_0);
|
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ public class TypedBreak implements TypedStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public class TypedCharLiteral implements TypedExpression {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
mv.visitLdcInsn(value);
|
ctx.getMv().visitLdcInsn(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package de.maishai.typedast.typedclass;
|
|||||||
import de.maishai.ast.Operator;
|
import de.maishai.ast.Operator;
|
||||||
import de.maishai.ast.records.*;
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.ast.records.Class;
|
import de.maishai.ast.records.Class;
|
||||||
|
import de.maishai.typedast.ClassContext;
|
||||||
import de.maishai.typedast.CodeGenUtils;
|
import de.maishai.typedast.CodeGenUtils;
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -196,17 +197,18 @@ public class TypedClass implements TypedNode {
|
|||||||
|
|
||||||
public byte[] codeGen() {
|
public byte[] codeGen() {
|
||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||||
|
ClassContext ctx = new ClassContext(className, cw);
|
||||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);
|
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);
|
||||||
for (TypedField field : typedFields) {
|
for (TypedField field : typedFields) {
|
||||||
field.codeGen(cw);
|
field.codeGen(cw);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TypedConstructor constructor : typedConstructors) {
|
for (TypedConstructor constructor : typedConstructors) {
|
||||||
constructor.codeGen(cw);
|
constructor.codeGen(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TypedMethod m : typedMethods) {
|
for (TypedMethod m : typedMethods) {
|
||||||
m.codeGen(cw);
|
m.codeGen(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cw.toByteArray();
|
return cw.toByteArray();
|
||||||
|
@ -2,10 +2,7 @@ package de.maishai.typedast.typedclass;
|
|||||||
|
|
||||||
import de.maishai.ast.records.Constructor;
|
import de.maishai.ast.records.Constructor;
|
||||||
import de.maishai.ast.records.Parameter;
|
import de.maishai.ast.records.Parameter;
|
||||||
import de.maishai.typedast.CodeGenUtils;
|
import de.maishai.typedast.*;
|
||||||
import de.maishai.typedast.MethodContext;
|
|
||||||
import de.maishai.typedast.TypedNode;
|
|
||||||
import de.maishai.typedast.Type;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -55,20 +52,20 @@ public class TypedConstructor implements TypedNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void codeGen(ClassWriter cw) {
|
public void codeGen(ClassContext ctx) {
|
||||||
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
||||||
MethodVisitor mv = cw.visitMethod(accessModifier, "<init>", CodeGenUtils.generateDescriptor(typedParameters, Type.VOID), null, null);
|
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, "<init>", CodeGenUtils.generateDescriptor(typedParameters, Type.VOID), null, null);
|
||||||
MethodContext context = new MethodContext(mv);
|
MethodContext mctx = new MethodContext(mv);
|
||||||
context.addVariable("this");
|
mctx.addVariable("this", ctx.getName());
|
||||||
typedParameters.forEach(param -> context.addVariable(param.getParaName()));
|
typedParameters.forEach(param -> mctx.addVariable(param.getParaName(), param.getType()));
|
||||||
//super();
|
//super();
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, mctx.getVariableIndex("this"));
|
||||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
|
||||||
typedBlock.codeGen(mv, context);
|
typedBlock.codeGen(mctx);
|
||||||
|
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
|
||||||
context.wrapUp(0,0);
|
mctx.wrapUp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ public class TypedDoWhile implements TypedStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public class TypedFieldVarAccess implements TypedExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ public class TypedFor implements TypedStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,18 +42,18 @@ public class TypedIfElse implements TypedStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
Label falseLabel = new Label();
|
Label falseLabel = new Label();
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
typedCon.codeGen(mv, ctx);
|
typedCon.codeGen(ctx);
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, falseLabel);
|
ctx.getMv().visitJumpInsn(Opcodes.IFEQ, falseLabel);
|
||||||
ifTypedBlock.codeGen(mv, ctx);
|
ifTypedBlock.codeGen(ctx);
|
||||||
mv.visitJumpInsn(Opcodes.GOTO, end);
|
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||||
|
|
||||||
mv.visitLabel(falseLabel);
|
ctx.getMv().visitLabel(falseLabel);
|
||||||
if (elseTypedBlock != null) {
|
if (elseTypedBlock != null) {
|
||||||
elseTypedBlock.codeGen(mv, ctx);
|
elseTypedBlock.codeGen(ctx);
|
||||||
}
|
}
|
||||||
mv.visitLabel(end);
|
ctx.getMv().visitLabel(end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ public class TypedIntLiteral implements TypedExpression {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
mv.visitLdcInsn(value);
|
ctx.getMv().visitLdcInsn(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,9 +40,6 @@ public final class TypedLocalVariable implements TypedNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
||||||
System.out.println("Generating code for local variable " + name);
|
ctx.addVariable(name, type);
|
||||||
int index = ctx.addVariable(name);
|
|
||||||
mv.visitLocalVariable(name, type.getDescriptor(), null, ctx.getStartLabel(), ctx.getEndLabel(), index);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,8 @@ public class TypedMethod implements TypedNode {
|
|||||||
if (method.getName().equals(name) && method.getTypedParameters().size() == typedParameters.size()
|
if (method.getName().equals(name) && method.getTypedParameters().size() == typedParameters.size()
|
||||||
&& method.getReturnType().equals(returnType)) {
|
&& method.getReturnType().equals(returnType)) {
|
||||||
|
|
||||||
for (int i = 0; i < method.getTypedParameters().size(); i++){
|
for (int i = 0; i < method.getTypedParameters().size(); i++) {
|
||||||
if(method.getTypedParameters().get(i).getType().equals(typedParameters.get(i).getType())){
|
if (method.getTypedParameters().get(i).getType().equals(typedParameters.get(i).getType())) {
|
||||||
throw new RuntimeException("Method " + name + " already exists");
|
throw new RuntimeException("Method " + name + " already exists");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,16 +69,16 @@ public class TypedMethod implements TypedNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void codeGen(ClassWriter cw) {
|
public void codeGen(ClassContext ctx) {
|
||||||
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
||||||
MethodVisitor mv = cw.visitMethod(accessModifier, name,
|
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, name,
|
||||||
CodeGenUtils.generateDescriptor(typedParameters, returnType), null, null);
|
CodeGenUtils.generateDescriptor(typedParameters, returnType), null, null);
|
||||||
MethodContext context = new MethodContext(mv);
|
MethodContext context = new MethodContext(mv);
|
||||||
context.addVariable("this");
|
context.addVariable("this", ctx.getName());
|
||||||
typedParameters.forEach(param -> context.addVariable(param.getParaName()));
|
typedParameters.forEach(param -> context.addVariable(param.getParaName(), param.getType()));
|
||||||
|
|
||||||
typedBlock.codeGen(mv, context);
|
typedBlock.codeGen(context);
|
||||||
context.wrapUp(0, 0);
|
context.wrapUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ public class TypedNew implements TypedExpression, TypedStatement {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,15 +42,15 @@ public class TypedReturn implements TypedStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
ctx.getMv().visitInsn(Opcodes.RETURN);
|
||||||
} else {
|
} else {
|
||||||
ret.codeGen(mv, ctx);
|
ret.codeGen(ctx);
|
||||||
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
|
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
|
||||||
mv.visitInsn(Opcodes.IRETURN);
|
ctx.getMv().visitInsn(Opcodes.IRETURN);
|
||||||
} else {
|
} else {
|
||||||
mv.visitInsn(Opcodes.ARETURN);
|
ctx.getMv().visitInsn(Opcodes.ARETURN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,14 +46,14 @@ public class TypedUnary implements TypedExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
right.codeGen(mv, ctx);
|
right.codeGen(ctx);
|
||||||
if(op == UnaryOperator.NOT){
|
if(op == UnaryOperator.NOT){
|
||||||
mv.visitInsn(Opcodes.ICONST_1);
|
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||||
mv.visitInsn(Opcodes.IXOR);
|
ctx.getMv().visitInsn(Opcodes.IXOR);
|
||||||
}
|
}
|
||||||
if(op == UnaryOperator.SUB){
|
if(op == UnaryOperator.SUB){
|
||||||
mv.visitInsn(Opcodes.INEG);
|
ctx.getMv().visitInsn(Opcodes.INEG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ public class TypedWhile implements TypedStatement {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user