Implement target t AST

This commit is contained in:
Victorious3 2022-05-03 21:37:14 +02:00
parent e8cc6ade11
commit 590a4f04ae
37 changed files with 382 additions and 20 deletions

View File

@ -124,7 +124,8 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<configuration>
<source>17</source>
<target>17</target>
</configuration>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -0,0 +1,7 @@
package de.dhbwstuttgart.target.bytecode;
public class CodeGenException extends RuntimeException {
public CodeGenException(String cause) {
super(cause);
}
}

View File

@ -5,10 +5,15 @@ import de.dhbwstuttgart.target.tree.TargetConstructor;
import de.dhbwstuttgart.target.tree.TargetField;
import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
import de.dhbwstuttgart.target.tree.expression.TargetExpression;
import de.dhbwstuttgart.target.tree.expression.TargetVarDecl;
import de.dhbwstuttgart.target.tree.type.TargetType;
import javassist.compiler.CodeGen;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import java.util.Map;
import static org.objectweb.asm.Opcodes.*;
public class Codegen {
@ -20,8 +25,72 @@ public class Codegen {
this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
}
private void generateBlock(MethodVisitor mv, TargetBlock block) {
private record LocalVar(int index, String name, TargetType type) {}
private class Scope {
Scope parent;
Map<String, LocalVar> locals;
Scope(Scope parent) {
this.parent = parent;
}
void add(LocalVar var) {
locals.put(var.name, var);
}
LocalVar get(String name) {
var local = locals.get(name);
if (local != null ){
return local;
}
if (parent != null) {
return parent.get(name);
}
throw new CodeGenException("Unknown symbol '" + name + "'");
}
}
private class State {
Scope scope = new Scope(null);
int localCounter = 1;
MethodVisitor mv;
State(MethodVisitor mv) {
this.mv = mv;
}
void enterScope() {
this.scope = new Scope(this.scope);
}
void exitScope() {
this.scope = this.scope.parent;
}
void createVariable(String name, TargetType type) {
scope.add(new LocalVar(localCounter, name, type));
localCounter += 1;
}
}
private void generate(State state, TargetExpression expr) {
switch (expr) {
case TargetBlock block:
var localCounter = state.localCounter;
state.enterScope();
for (var e : block.statements()) {
generate(state, e);
}
state.exitScope();
state.localCounter = localCounter;
break;
case TargetVarDecl varDecl:
state.createVariable(varDecl.name(), varDecl.varType());
break;
default:
throw new IllegalStateException("Unexpected value: " + expr);
}
}
private void generateField(TargetField field) {
@ -29,21 +98,21 @@ public class Codegen {
}
private void generateConstructor(TargetConstructor constructor) {
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, null);
MethodVisitor mv = cw.visitMethod(constructor.access(), "<init>", constructor.getDescriptor(), null, null);
generate(new State(mv), constructor.block());
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private void generateMethod(TargetMethod method) {
// TODO Access modifier
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, method.name(), method.getDescriptor(), null, null);
generateBlock(mv, method.block());
MethodVisitor mv = cw.visitMethod(method.access(), method.name(), method.getDescriptor(), null, null);
generate(new State(mv), method.block());
mv.visitMaxs(0, 0);
mv.visitEnd();
}
public byte[] generate() {
// TODO Access modifier and signature
cw.visit(V12, ACC_PUBLIC, clazz.qualifiedName(),
cw.visit(V1_8, clazz.modifiers(), clazz.qualifiedName(),
null, clazz.superType().toSignature(),
clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new)
);

View File

@ -1,8 +1,10 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
import java.util.List;
public record TargetConstructor(List<MethodParameter> parameterTypes) {
public record TargetConstructor(int access, List<MethodParameter> parameterTypes, TargetBlock block) {
public String getDescriptor() {
// TODO

View File

@ -1,11 +1,16 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.target.tree.type.TargetType;
import org.objectweb.asm.Opcodes;
public record TargetField(int access, TargetType type, String name) {
public String getDescriptor() {
// TODO
return null;
}
public boolean isStatic() {
return (access & Opcodes.ACC_STATIC) != 0;
}
}

View File

@ -4,7 +4,7 @@ import de.dhbwstuttgart.target.tree.expression.TargetBlock;
import java.util.List;
public record TargetMethod(String name, List<MethodParameter> parameterTypes, TargetBlock block) {
public record TargetMethod(int access, String name, List<MethodParameter> parameterTypes, TargetBlock block) {
public String getDescriptor() {
// TODO
return null;

View File

@ -1,4 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetAssign(TargetExpression leftSide, TargetExpression rightSide) implements TargetExpression {
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetAssign(TargetType type, TargetExpression leftSide, TargetExpression rightSide) implements TargetExpression {
}

View File

@ -0,0 +1,40 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.expression.TargetExpression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public sealed interface TargetBinaryOp extends TargetExpression {
TargetExpression left();
TargetExpression right();
// Artihmetic
record Add(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Sub(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Div(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Mul(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Rem(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
// Bitwise
record BAnd(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record BOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record XOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Shl(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Shr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record UShr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
// Conditional
record And(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Or(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
// Comparison
record Equal(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Greater(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record GreaterOrEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Less(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record LessOrEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record NotEqual(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
record Assign(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {}
}

View File

@ -1,6 +1,12 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetBlock(List<TargetExpression> statememts) implements TargetExpression {
public record TargetBlock(List<TargetExpression> statements) implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetBreak() implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetCast(TargetType type, TargetExpression expr) implements TargetExpression {
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetContinue() implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetDot(TargetType type, boolean isStatic, TargetExpression left, String right) implements TargetExpression {
}

View File

@ -3,5 +3,7 @@ package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.*;
public sealed interface TargetExpression
permits TargetBlock, TargetLambdaExpression, TargetReturn, TargetThis, TargetSuper, TargetNew, TargetAssign {
permits TargetAssign, TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetContinue, TargetDot, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetMethodCall, TargetNew, TargetReturn, TargetSuper, TargetSwitch, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile {
TargetType type();
}

View File

@ -0,0 +1,7 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.TargetField;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetFieldVar(TargetType type, TargetField field) implements TargetExpression {
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetFor(TargetExpression init, TargetExpression termination, TargetExpression increment, TargetExpression body) implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetForEach(TargetExpression vardecl, TargetExpression list) implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -0,0 +1,10 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetIf(TargetExpression expr, TargetExpression if_body, TargetExpression else_body) implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -0,0 +1,12 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetInstanceOf(Expression left, TargetType right) implements TargetExpression {
@Override
public TargetType type() {
return TargetType.Boolean;
}
}

View File

@ -1,8 +1,9 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.MethodParameter;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetLambdaExpression(List<MethodParameter> params, TargetExpression block) implements TargetExpression {
public record TargetLambdaExpression(TargetType type, List<MethodParameter> params, TargetExpression block) implements TargetExpression {
}

View File

@ -0,0 +1,35 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public sealed interface TargetLiteral extends TargetExpression {
Object value();
record CharLiteral(Integer value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Char;
}
}
record IntLiteral(Integer value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Integer;
}
}
record LongLiteral(Long value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Long;
}
}
record StringLiteral(String value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.String;
}
}
}

View File

@ -0,0 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetLocalVar(TargetType type, String name) implements TargetExpression {
}

View File

@ -0,0 +1,9 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetMethod method) implements TargetExpression {
}

View File

@ -4,5 +4,5 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetNew(TargetType instantiatedType, List<TargetExpression> params) implements TargetExpression {
public record TargetNew(TargetType type, List<TargetExpression> params) implements TargetExpression {
}

View File

@ -1,4 +1,10 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetReturn(TargetExpression expression) implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -1,4 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetSuper() implements TargetExpression {
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetSuper(TargetType type) implements TargetExpression {
}

View File

@ -0,0 +1,16 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetSwitch(Expression expr, List<Case> cases, Expression default_) implements TargetExpression {
@Override
public TargetType type() {
return null;
}
record Case(Expression value, Expression body) {}
}

View File

@ -1,4 +1,6 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetThis() implements TargetExpression {
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetThis(TargetType type) implements TargetExpression {
}

View File

@ -0,0 +1,15 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public sealed interface TargetUnaryOp extends TargetExpression {
TargetExpression expr();
record Negate(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
record PreIncrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
record PostIncrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
record PreDecrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
record PostDecrement(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetVarDecl(String name, TargetType varType) implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetWhile(TargetExpression expr, TargetExpression body) implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -2,6 +2,10 @@ package de.dhbwstuttgart.target.tree.type;
import java.util.List;
public record TargetExtendsWildcard(TargetType innerType) implements TargetType{
public record TargetExtendsWildcard(TargetType innerType) implements TargetType {
@Override
public String toSignature() {
return null;
}
}

View File

@ -3,4 +3,8 @@ package de.dhbwstuttgart.target.tree.type;
import java.util.List;
public record TargetFunNType(int N, List<TargetRefType> params) implements TargetType {
@Override
public String toSignature() {
return "Fun$$" + N;
}
}

View File

@ -1,4 +1,8 @@
package de.dhbwstuttgart.target.tree.type;
public record TargetGenericType(String name) implements TargetType {
@Override
public String toSignature() {
return null;
}
}

View File

@ -7,6 +7,6 @@ import java.util.List;
public record TargetRefType(String name, List<TargetType> params) implements TargetType {
@Override
public String toSignature() {
return this.name;
return "L" + this.name.replaceAll("\\.", "/");
}
}

View File

@ -1,4 +1,8 @@
package de.dhbwstuttgart.target.tree.type;
public record TargetSuperWildcard(TargetType innerType) implements TargetType {
@Override
public String toSignature() {
return null;
}
}

View File

@ -1,7 +1,20 @@
package de.dhbwstuttgart.target.tree.type;
import java.util.List;
public sealed interface TargetType
permits TargetExtendsWildcard, TargetFunNType, TargetGenericType, TargetRefType, TargetSuperWildcard {
public String toSignature();
// Builtin types
TargetRefType Boolean = new TargetRefType("java.lang.Boolean", List.of());
TargetRefType Char = new TargetRefType("java.lang.Character", List.of());
TargetRefType Byte = new TargetRefType("java.lang.Byte", List.of());
TargetRefType Short = new TargetRefType("java.lang.Short", List.of());
TargetRefType Integer = new TargetRefType("java.lang.Integer", List.of());
TargetRefType Long = new TargetRefType("java.lang.Long", List.of());
TargetRefType Float = new TargetRefType("java.lang.Float", List.of());
TargetRefType Double = new TargetRefType("java.lang.Double", List.of());
TargetRefType String = new TargetRefType("java.lang.String", List.of());
String toSignature();
}