Merge remote-tracking branch 'origin/main'

This commit is contained in:
JonathanFleischmann 2024-07-03 22:51:24 +02:00
commit 371480a790
12 changed files with 53 additions and 51 deletions

View File

@ -11,7 +11,7 @@
- Laura Schleicher: Grammatik entwickeln, Records, Statements als Liste zurückgeben, Generator, Syntactic Sugar auflösen
- Julian Kraus: Grammatik entwickeln, Generator, Syntactic Sugar auflösen, Parser Exceptions sammeln
- Ahmad Juha: Typcheck
- Simon Wittmann: Codegen und Tool für ASM
- Simon Wittmann: Codegen, Logging, CommandLine Nutzung
- Jonathan Fleischmann:
- Schreiben von Tests, die die einzelnen Features abdecken
- Umwandlung der Testfiles in AST und TypedAST

View File

@ -5,6 +5,7 @@ import de.maishai.antlr.DecafParser;
import de.maishai.ast.records.Class;
import de.maishai.ast.records.Program;
import de.maishai.typedast.CodeGenUtils;
import de.maishai.typedast.MethodContext;
import de.maishai.typedast.typedclass.TypedClass;
import de.maishai.typedast.typedclass.TypedProgram;
import org.antlr.v4.runtime.*;
@ -13,6 +14,8 @@ import org.apache.commons.cli.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -21,11 +24,11 @@ public class Compiler {
private static final String JAVA_FILE_EXTENSION = ".java";
private static final Logger LOGGER = Logger.getLogger(Compiler.class.getName());
public static Program generateAST(List<String> fromSources) {
public static Program generateAST(List<String> sourcePaths) {
List<Class> classes = new ArrayList<>();
CollectingErrorListener errorListener = new CollectingErrorListener();
for (String fromSource : fromSources) {
CharStream input = CharStreams.fromString(fromSource);
for (String sourcePath : sourcePaths) {
CharStream input = CharStreams.fromString(sourcePath);
DecafLexer lexer = new DecafLexer(input);
//add custom error listener
@ -109,7 +112,12 @@ public class Compiler {
Logger rootLog = Logger.getLogger("");
rootLog.setLevel( Level.FINEST );
rootLog.getHandlers()[0].setLevel( Level.FINEST );
LOGGER.finest("Debug logging enabled");
Formatter logFormatter = new LogFormatter();
for (Handler handler : rootLog.getHandlers()) {
handler.setFormatter(logFormatter);
}
MethodContext.DEBUG = true;
LOGGER.info("Debug logging enabled");
}
if (cmd.getArgs().length == 0) {

View File

@ -0,0 +1,18 @@
package de.maishai;
import java.text.MessageFormat;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
public class LogFormatter extends Formatter {
@Override
public String format(LogRecord logRecord) {
String formattedMessage = MessageFormat.format(logRecord.getMessage(), logRecord.getParameters());
if (logRecord.getLevel() == Level.FINEST) {
return formattedMessage + "\n";
}
return logRecord.getLevel() + ": " + formattedMessage + "\n";
}
}

View File

@ -6,14 +6,16 @@ import org.objectweb.asm.Opcodes;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggingMethodVisitor extends MethodVisitor {
private static final Logger LOGGER = Logger.getLogger(LoggingMethodVisitor.class.getName());
private final Map<Label, String> labelNames = new HashMap<>();
private int labelCounter = 0;
public LoggingMethodVisitor(MethodVisitor methodVisitor) {
super(Opcodes.ASM9, methodVisitor);
System.out.println("\n--- Visiting Method ---");
}
private String getLabelName(Label label) {
@ -22,7 +24,7 @@ public class LoggingMethodVisitor extends MethodVisitor {
@Override
public void visitJumpInsn(int opcode, Label label) {
System.out.println("visitJumpInsn: " + opcodeToString(opcode) + ", " + getLabelName(label));
LOGGER.log(Level.FINEST, "visitJumpInsn: {0}, {1}", new Object[]{opcodeToString(opcode), getLabelName(label)});
super.visitJumpInsn(opcode, label);
}
@ -41,63 +43,63 @@ public class LoggingMethodVisitor extends MethodVisitor {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
System.out.println("visitMethodInsn: " + opcodeToString(opcode) + ", " + owner + ", " + name + ", " + descriptor + ", " + isInterface);
LOGGER.log(Level.FINEST, "visitMethodInsn: {0}, {1}, {2}, {3}, {4}", new Object[]{opcodeToString(opcode), owner, name, descriptor, isInterface});
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
@Override
public void visitVarInsn(int opcode, int varIndex) {
System.out.println("visitVarInsn: " + opcodeToString(opcode) + ", " + varIndex);
LOGGER.log(Level.FINEST, "visitVarInsn: {0}, {1}", new Object[]{opcodeToString(opcode), varIndex});
super.visitVarInsn(opcode, varIndex);
}
@Override
public void visitTypeInsn(int opcode, String type) {
System.out.println("visitTypeInsn: " + opcodeToString(opcode) + ", " + type);
LOGGER.log(Level.FINEST, "visitTypeInsn: {0}, {1}", new Object[]{opcodeToString(opcode), type});
super.visitTypeInsn(opcode, type);
}
@Override
public void visitInsn(int opcode) {
System.out.println("visitInsn: " + opcodeToString(opcode));
LOGGER.log(Level.FINEST, "visitInsn: {0}", opcodeToString(opcode));
super.visitInsn(opcode);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor) {
System.out.println("visitMethodInsn: " + opcodeToString(opcode) + ", " + owner + ", " + name + ", " + descriptor);
LOGGER.log(Level.FINEST, "visitMethodInsn: {0}, {1}, {2}, {3}", new Object[]{opcodeToString(opcode), owner, name, descriptor});
super.visitMethodInsn(opcode, owner, name, descriptor);
}
@Override
public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
System.out.println("visitFieldInsn: " + opcodeToString(opcode) + ", " + owner + ", " + name + ", " + descriptor);
LOGGER.log(Level.FINEST, "visitFieldInsn: {0}, {1}, {2}, {3}", new Object[]{opcodeToString(opcode), owner, name, descriptor});
super.visitFieldInsn(opcode, owner, name, descriptor);
}
@Override
public void visitMaxs(int maxStack, int maxLocals) {
System.out.println("visitMaxs: " + maxStack + ", " + maxLocals);
LOGGER.log(Level.FINEST, "visitMaxs: {0}, {1}", new Object[]{maxStack, maxLocals});
super.visitMaxs(maxStack, maxLocals);
}
@Override
public void visitIntInsn(int opcode, int operand) {
String opcodeString = opcode == Opcodes.BIPUSH ? "BIPUSH" : "SIPUSH";
System.out.println("visitIntInsn: " + opcodeString + ", " + operand);
LOGGER.log(Level.FINEST, "visitIntInsn: {0}, {1}", new Object[]{opcodeString, operand});
super.visitIntInsn(opcode, operand);
}
@Override
public void visitLabel(Label label) {
String labelName = getLabelName(label);
System.out.println("visitLabel: " + labelName);
LOGGER.log(Level.FINEST, "visitLabel: {0}", labelName);
super.visitLabel(label);
}
@Override
public void visitLdcInsn(Object value) {
System.out.println("visitLdcInsn: " + value);
LOGGER.log(Level.FINEST, "visitLdcInsn: {0}", value);
super.visitLdcInsn(value);
}
}

View File

@ -12,6 +12,7 @@ import java.util.logging.Logger;
@Getter
public class MethodContext {
private static final Logger LOGGER = Logger.getLogger(MethodContext.class.getName());
public static boolean DEBUG = false;
public record LocalVariable(String name, int index, Type type) {
}
@ -28,7 +29,7 @@ public class MethodContext {
private final Deque<Label> continueLabels = new ArrayDeque<>();
public MethodContext(ClassContext classContext, MethodVisitor mv, Type returnType) {
if (Objects.equals(System.getenv("DEBUG"), "true")) {
if (DEBUG) {
this.mv = new LoggingMethodVisitor(mv);
} else {
this.mv = mv;

View File

@ -10,7 +10,6 @@ import lombok.Data;
import org.objectweb.asm.Opcodes;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import static de.maishai.typedast.Util.TypedExpressionUtil.convertExpression;
@ -107,7 +106,6 @@ public class TypedAssignment implements TypedStatement {
receiver = location.getRecursiveOwnerChain().getType().getReference();
}
ctx.getMv().visitFieldInsn(Opcodes.PUTFIELD, receiver, location.getName(), value.getType().getDescriptor());
LOGGER.log(Level.FINEST, "PUTFIELD: {0} {1} {2}", new Object[]{receiver, location.getName(), value.getType().getDescriptor()});
ctx.popStack();
} else {
Optional<MethodContext.LocalVariable> localVariableOptional = ctx.getLocalVar(location.getName());
@ -117,10 +115,8 @@ public class TypedAssignment implements TypedStatement {
}
MethodContext.LocalVariable localVariable = localVariableOptional.get();
if (value.getType().getKind() == Type.Kind.REFERENCE) {
LOGGER.finest("ASTORE " + localVariable.index());
ctx.getMv().visitVarInsn(Opcodes.ASTORE, localVariable.index());
} else {
LOGGER.finest("ISTORE " + localVariable.index());
ctx.getMv().visitVarInsn(Opcodes.ISTORE, localVariable.index());
}
}

View File

@ -108,7 +108,6 @@ public class TypedConstructor implements TypedNode {
//super();
mctx.pushStack("this");
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", CONSTRUCTOR_METHOD_NAME, "()V", false);
LOGGER.finest("INVOKESPECIAL: " + "java/lang/Object" + " " + CONSTRUCTOR_METHOD_NAME + " " + "()V");
mctx.popStack();
typedBlock.codeGen(mctx);

View File

@ -163,13 +163,11 @@ public class TypedFieldVarAccess implements TypedExpression {
int loadOpcode = type.getKind() == Type.Kind.REFERENCE ? Opcodes.ALOAD : Opcodes.ILOAD;
Optional<MethodContext.LocalVariable> localVariableOptional = ctx.getLocalVar(name);
if (localVariableOptional.isEmpty()) {
LOGGER.log(Level.FINEST, "Variable {0} not declared", name);
LOGGER.log(Level.SEVERE, "Variable {0} not declared", name);
return;
}
MethodContext.LocalVariable localVariable = localVariableOptional.get();
ctx.getMv().visitVarInsn(loadOpcode, localVariable.index());
String opcode = loadOpcode == Opcodes.ALOAD ? "ALOAD " : "ILOAD ";
LOGGER.log(Level.FINEST, "{0} {1}", new Object[]{opcode, localVariable.index()});
}
ctx.pushAnonToStack();
}

View File

@ -9,14 +9,10 @@ import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.objectweb.asm.Opcodes;
import java.util.logging.Level;
import java.util.logging.Logger;
@Data
@AllArgsConstructor
@RequiredArgsConstructor
public class TypedIntLiteral implements TypedExpression {
private static final Logger LOGGER = Logger.getLogger(TypedIntLiteral.class.getName());
private Integer value;
private Type type;
@ -43,13 +39,10 @@ public class TypedIntLiteral implements TypedExpression {
public void codeGen(MethodContext ctx) {
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
ctx.getMv().visitIntInsn(Opcodes.BIPUSH, value);
LOGGER.log(Level.FINEST, "BIPUSH {0}", value);
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
ctx.getMv().visitIntInsn(Opcodes.SIPUSH, value);
LOGGER.log(Level.FINEST, "SIPUSH {0}", value);
} else {
ctx.getMv().visitLdcInsn(value);
LOGGER.log(Level.FINEST, "LDC {0}", value);
}
ctx.pushInstantToStack();
}

View File

@ -11,8 +11,6 @@ import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import static de.maishai.typedast.Util.TypedExpressionUtil.convertExpression;
@ -21,7 +19,6 @@ import static de.maishai.typedast.Util.TypedExpressionUtil.convertExpression;
@NoArgsConstructor
@AllArgsConstructor
public class TypedMethodCall implements TypedExpression, TypedStatement {
private static final Logger LOGGER = Logger.getLogger(TypedMethodCall.class.getName());
private TypedFieldVarAccess recipient;
private List<TypedExpression> args = new ArrayList<>();
private Type type;
@ -107,7 +104,6 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
methodOwnerClass = recipient.getRecursiveOwnerChain().getType().getReference();
}
ctx.getMv().visitMethodInsn(Opcodes.INVOKEVIRTUAL, methodOwnerClass, recipient.getName(), descriptor, false);
LOGGER.log(Level.FINEST, "INVOKEVIRTUAL {0} {1} {2}", new Object[]{methodOwnerClass, recipient.getName(), descriptor});
ctx.popStack();
for (int i = 0; i < args.size(); i++) {
ctx.popStack();

View File

@ -9,15 +9,12 @@ import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import static de.maishai.typedast.Util.TypedExpressionUtil.convertExpression;
@Data
@AllArgsConstructor
public class TypedNew implements TypedExpression, TypedStatement {
private static final Logger LOGGER = Logger.getLogger(TypedNew.class.getName());
private Type type;
private List<TypedExpression> args = new ArrayList<>();
@ -68,10 +65,8 @@ public class TypedNew implements TypedExpression, TypedStatement {
@Override
public void codeGen(MethodContext ctx) {
ctx.getMv().visitTypeInsn(Opcodes.NEW, type.getReference());
LOGGER.log(Level.FINEST, "NEW {0}", type.getReference());
ctx.pushAnonToStack();
ctx.getMv().visitInsn(Opcodes.DUP);
LOGGER.finest("DUP");
ctx.pushAnonToStack();
for (TypedExpression arg : args) {
arg.codeGen(ctx);
@ -79,7 +74,6 @@ public class TypedNew implements TypedExpression, TypedStatement {
String descriptor = CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), Type.VOID);
ctx.getMv().visitMethodInsn(Opcodes.INVOKESPECIAL, type.getReference(), "<init>", descriptor, false);
ctx.popStack();
LOGGER.log(Level.FINEST, "INVOKESPECIAL {0} <init> {1}", new Object[]{type.getReference(), descriptor});
for (int i = 0; i < args.size(); i++) {
ctx.popStack();
}

View File

@ -1,22 +1,22 @@
package de.maishai.typedast.typedclass;
import de.maishai.ast.records.*;
import de.maishai.typedast.*;
import de.maishai.ast.records.Return;
import de.maishai.typedast.MethodContext;
import de.maishai.typedast.Type;
import de.maishai.typedast.TypedExpression;
import de.maishai.typedast.TypedStatement;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.objectweb.asm.Opcodes;
import java.util.logging.Logger;
import static de.maishai.typedast.Util.TypedExpressionUtil.convertExpression;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TypedReturn implements TypedStatement {
private static final Logger LOGGER = Logger.getLogger(TypedReturn.class.getName());
private TypedExpression ret;
private Type type;
@ -56,15 +56,12 @@ public class TypedReturn implements TypedStatement {
public void codeGen(MethodContext ctx) {
if (ret == null) {
ctx.getMv().visitInsn(Opcodes.RETURN);
LOGGER.finest("RETURN");
} else {
ret.codeGen(ctx);
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
ctx.getMv().visitInsn(Opcodes.IRETURN);
LOGGER.finest("IRETURN");
} else {
ctx.getMv().visitInsn(Opcodes.ARETURN);
LOGGER.finest("ARETURN");
}
}