mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-27 08:58:02 +00:00
Merge branch 'main' of https://github.com/JonathanFleischmann/CompilerULTIMATE
This commit is contained in:
commit
9aedcd646d
@ -99,7 +99,8 @@ public class Compiler {
|
||||
|
||||
public static void main(String[] args) {
|
||||
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java",
|
||||
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java"),
|
||||
List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall"));
|
||||
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java",
|
||||
"src/main/resources/JavaTestfiles/ComplexClass.java"),
|
||||
List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall","ComplexClass"));
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
|
||||
DecafParser.RecipientContext ctx = ctxList.get(lastElement);
|
||||
ctxList.remove(lastElement);
|
||||
if (ctx.id() != null) {
|
||||
return new FieldVarAccess(false, generateRecursiveOwnerChain(ctxList, recipient), ctx.id().IDENTIFIER().getText());
|
||||
return new FieldVarAccess(true, generateRecursiveOwnerChain(ctxList, recipient), ctx.id().IDENTIFIER().getText());
|
||||
}
|
||||
if (ctx.methName() != null) {
|
||||
List<Expression> args = new ArrayList<>();
|
||||
|
@ -6,11 +6,13 @@ import org.objectweb.asm.ClassWriter;
|
||||
|
||||
@Data
|
||||
public class ClassContext {
|
||||
private Type name;
|
||||
private String name;
|
||||
private Type type;
|
||||
private ClassWriter cw;
|
||||
|
||||
public ClassContext(String name, ClassWriter cw) {
|
||||
this.name = Type.REFERENCE(name);
|
||||
this.name = name;
|
||||
type = Type.REFERENCE(name);
|
||||
this.cw = cw;
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ import java.util.List;
|
||||
|
||||
public class CodeGenUtils {
|
||||
|
||||
public static String generateDescriptor(List<TypedParameter> arguments, Type returnType) {
|
||||
public static String generateDescriptor(List<Type> argTypes, Type returnType) {
|
||||
if (returnType == null) {
|
||||
returnType = Type.VOID;
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append('(');
|
||||
arguments.forEach(type -> builder.append(type.getType().getDescriptor()));
|
||||
argTypes.forEach(type -> builder.append(type.getDescriptor()));
|
||||
builder.append(')');
|
||||
builder.append(returnType.getDescriptor());
|
||||
return builder.toString();
|
||||
|
@ -34,7 +34,7 @@ public class TypedExpressionHelp {
|
||||
}
|
||||
else if (expression instanceof MethodCall methodCall) {
|
||||
TypedMethodCall typedMethodCall = new TypedMethodCall( typedProgram, methodCall);
|
||||
typedMethodCall.typeCheck( typedProgram);
|
||||
typedMethodCall.typeCheck(typedProgram);
|
||||
return typedMethodCall;
|
||||
}
|
||||
else if (expression instanceof New newStmt) {
|
||||
|
@ -7,11 +7,12 @@ import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Stack;
|
||||
|
||||
@Getter
|
||||
public class MethodContext {
|
||||
private record LocalVariable(String name, int index, Type type) {
|
||||
public record LocalVariable(String name, int index, Type type) {
|
||||
}
|
||||
|
||||
private Label startLabel;
|
||||
@ -28,7 +29,7 @@ public class MethodContext {
|
||||
endLabel = new Label();
|
||||
this.mv = mv;
|
||||
this.classContext = classContext;
|
||||
registerVariable("this", classContext.getName());
|
||||
registerVariable("this", classContext.getType());
|
||||
mv.visitCode();
|
||||
mv.visitLabel(startLabel);
|
||||
}
|
||||
@ -39,12 +40,9 @@ public class MethodContext {
|
||||
variableIndex.put(name, new LocalVariable(name, index, type));
|
||||
}
|
||||
|
||||
public int getVariableIndex(String name) {
|
||||
int index = variableIndex.get(name).index;
|
||||
if (index == -1) {
|
||||
throw new RuntimeException("Variable not declared");
|
||||
}
|
||||
return index;
|
||||
public Optional<LocalVariable> getLocalVar(String name) {
|
||||
LocalVariable index = variableIndex.get(name);
|
||||
return Optional.ofNullable(index);
|
||||
}
|
||||
|
||||
public void pushStack(String varName) {
|
||||
@ -58,6 +56,22 @@ public class MethodContext {
|
||||
} else {
|
||||
mv.visitVarInsn(Opcodes.ILOAD, localVariable.index);
|
||||
}
|
||||
System.out.println("Pushed " + variableIndex.get(varName) + " to stack");
|
||||
}
|
||||
|
||||
public void pushAnonToStack() {
|
||||
stack.push(localVarIndex);
|
||||
if (stack.size() > maxStack) {
|
||||
maxStack = stack.size();
|
||||
}
|
||||
System.out.println("Pushed anon to stack");
|
||||
}
|
||||
|
||||
public void pushInstantToStack () {
|
||||
stack.push(localVarIndex);
|
||||
if (stack.size() > maxStack) {
|
||||
maxStack = stack.size();
|
||||
}
|
||||
}
|
||||
|
||||
public void popStack() {
|
||||
@ -66,6 +80,7 @@ public class MethodContext {
|
||||
|
||||
public void wrapUp() {
|
||||
mv.visitLabel(endLabel);
|
||||
System.out.println("maxStack: " + maxStack + " localVarIndex: " + localVarIndex);
|
||||
mv.visitMaxs(maxStack, localVarIndex);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
@ -25,31 +25,13 @@ public class TypedAssignment implements TypedStatement {
|
||||
public void convertToTypedAssignment(TypedProgram typedProgram, Assignment untyped) {
|
||||
value = convertExpression(typedProgram, untyped.value());
|
||||
location = new TypedFieldVarAccess(typedProgram, untyped.location());
|
||||
location.typeCheck(typedProgram);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
Type typeLeft = null;
|
||||
|
||||
if (typedProgram.getCurrentClass().isThereField(location.getName())) {
|
||||
typeLeft = typedProgram.getCurrentClass().getFieldType(location.getName());
|
||||
} else {
|
||||
if (typedProgram.getCurrentClass().isCurrentMethodPresent() && !typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||
if (typedProgram.getCurrentClass().getCurrentMethod().isLocalVariableInMethod(location.getName())) {
|
||||
typeLeft = typedProgram.getCurrentClass().getCurrentMethod().getLocalVariableType(location.getName());
|
||||
} else {
|
||||
throw new RuntimeException("Variable " + location.getName() + " not declared in method");
|
||||
}
|
||||
}
|
||||
if (!typedProgram.getCurrentClass().isCurrentMethodPresent() && typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||
if (typedProgram.getCurrentClass().getCurrentConstructor().isLocalVariableInConstructor(location.getName())) {
|
||||
typeLeft = typedProgram.getCurrentClass().getCurrentConstructor().getLocalVariableType(location.getName());
|
||||
} else {
|
||||
throw new RuntimeException("Variable " + location.getName() + " not declared in constructor");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Type typeLeft = getTypeLeft(typedProgram);
|
||||
Type typeRight = value.typeCheck(typedProgram);
|
||||
|
||||
if (typeLeft.equals(typeRight)) {
|
||||
@ -59,11 +41,82 @@ public class TypedAssignment implements TypedStatement {
|
||||
throw new RuntimeException("type of left not equals with type of right");
|
||||
}
|
||||
|
||||
private Type getTypeLeft(TypedProgram typedProgram) {
|
||||
String name = location.getName();
|
||||
TypedClass currentClass = typedProgram.getCurrentClass();
|
||||
|
||||
if (currentClass.isThereField(name) && location.getField()) {
|
||||
return currentClass.getFieldType(name);
|
||||
}
|
||||
|
||||
if (currentClass.isCurrentMethodPresent() && !currentClass.isCurrentConstructorPresent()) {
|
||||
return getTypeFromMethodOrField(currentClass.getCurrentMethod(), name, currentClass);
|
||||
}
|
||||
|
||||
if (!currentClass.isCurrentMethodPresent() && currentClass.isCurrentConstructorPresent()) {
|
||||
return getTypeFromConstructorOrField(currentClass.getCurrentConstructor(), name, currentClass);
|
||||
}
|
||||
|
||||
throw new RuntimeException("Variable " + name + " not declared");
|
||||
}
|
||||
|
||||
private Type getTypeFromMethodOrField(TypedMethod currentMethod, String name, TypedClass currentClass) {
|
||||
if (currentMethod.isLocalVariableInMethod(name)) {
|
||||
return currentMethod.getLocalVariableType(name);
|
||||
} else if (currentClass.isThereField(name)) {
|
||||
return currentClass.getFieldType(name);
|
||||
} else {
|
||||
throw new RuntimeException("Variable " + name + " not declared in method");
|
||||
}
|
||||
}
|
||||
|
||||
private Type getTypeFromConstructorOrField(TypedConstructor currentConstructor, String name, TypedClass currentClass) {
|
||||
if (currentConstructor.isLocalVariableInConstructor(name)) {
|
||||
return currentConstructor.getLocalVariableType(name);
|
||||
} else if (currentClass.isThereField(name)) {
|
||||
return currentClass.getFieldType(name);
|
||||
} else {
|
||||
throw new RuntimeException("Variable " + name + " not declared in constructor");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
if (value instanceof TypedIntLiteral) {
|
||||
ctx.getMv().visitIntInsn(Opcodes.BIPUSH, ((TypedIntLiteral) value).getValue());
|
||||
ctx.getMv().visitVarInsn(Opcodes.ISTORE, ctx.getLocalVarIndex());
|
||||
if(value instanceof TypedNew) {
|
||||
value.codeGen(ctx);
|
||||
getOwnerChain(ctx);
|
||||
} else {
|
||||
ctx.pushStack("this");
|
||||
getOwnerChain(ctx);
|
||||
value.codeGen(ctx);
|
||||
}
|
||||
|
||||
|
||||
//save value in field
|
||||
if (location.getField()) {
|
||||
|
||||
String receiver = ctx.getClassContext().getName();
|
||||
if (location.getRecursiveOwnerChain() != null) {
|
||||
receiver = location.getRecursiveOwnerChain().getType().getReference();
|
||||
}
|
||||
ctx.getMv().visitFieldInsn(Opcodes.PUTFIELD, receiver, location.getName(), value.getType().getDescriptor());
|
||||
System.out.println("PUTFIELD: " + receiver + " " + location.getName() + " " + value.getType().getDescriptor());
|
||||
} else {
|
||||
if(value.getType().getKind() == Type.Kind.REFERENCE) {
|
||||
System.out.println("ASTORE " + ctx.getLocalVar(location.getName()).get().index());
|
||||
ctx.getMv().visitVarInsn(Opcodes.ASTORE, ctx.getLocalVar(location.getName()).get().index());
|
||||
} else {
|
||||
ctx.getMv().visitVarInsn(Opcodes.ISTORE, ctx.getLocalVar(location.getName()).get().index());
|
||||
}
|
||||
}
|
||||
//ctx.popStack();
|
||||
//ctx.popStack();
|
||||
}
|
||||
|
||||
private void getOwnerChain(MethodContext ctx) {
|
||||
if (location.getRecursiveOwnerChain() != null) {
|
||||
location.getRecursiveOwnerChain().codeGen(ctx);
|
||||
ctx.pushAnonToStack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,11 @@ import de.maishai.typedast.Type;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||
|
||||
@ -67,6 +72,139 @@ public class TypedBinary implements TypedExpression {
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
if (op == Operator.AND) {
|
||||
Label end = new Label();
|
||||
Label returnTrue = new Label();
|
||||
Label returnFalse = new Label();
|
||||
left.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IFNE, returnFalse);
|
||||
right.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IFNE, returnFalse);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, returnTrue);
|
||||
|
||||
ctx.getMv().visitLabel(returnFalse);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||
ctx.getMv().visitLabel(returnTrue);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
ctx.getMv().visitLabel(end);
|
||||
} else if (op == Operator.OR) {
|
||||
Label end = new Label();
|
||||
Label returnTrue = new Label();
|
||||
Label returnFalse = new Label();
|
||||
left.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IFNE, returnTrue);
|
||||
right.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IFNE, returnTrue);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, returnFalse);
|
||||
|
||||
ctx.getMv().visitLabel(returnFalse);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||
ctx.getMv().visitLabel(returnTrue);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
ctx.getMv().visitLabel(end);
|
||||
} else if (op == Operator.EQ) {
|
||||
Label end = new Label();
|
||||
Label returnTrue = new Label();
|
||||
Label returnFalse = new Label();
|
||||
left.codeGen(ctx);
|
||||
right.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IF_ICMPNE, returnFalse);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, returnTrue);
|
||||
|
||||
ctx.getMv().visitLabel(returnFalse);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||
ctx.getMv().visitLabel(returnTrue);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
ctx.getMv().visitLabel(end);
|
||||
} else if (op == Operator.GT) {
|
||||
Label end = new Label();
|
||||
Label returnTrue = new Label();
|
||||
Label returnFalse = new Label();
|
||||
left.codeGen(ctx);
|
||||
right.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IF_ICMPLE, returnFalse);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, returnTrue);
|
||||
|
||||
ctx.getMv().visitLabel(returnFalse);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||
ctx.getMv().visitLabel(returnTrue);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
ctx.getMv().visitLabel(end);
|
||||
} else if (op == Operator.LT) {
|
||||
Label end = new Label();
|
||||
Label returnTrue = new Label();
|
||||
Label returnFalse = new Label();
|
||||
left.codeGen(ctx);
|
||||
right.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IF_ICMPGE, returnFalse);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, returnTrue);
|
||||
|
||||
ctx.getMv().visitLabel(returnFalse);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||
ctx.getMv().visitLabel(returnTrue);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
ctx.getMv().visitLabel(end);
|
||||
} else if (op == Operator.GE) {
|
||||
Label end = new Label();
|
||||
Label returnTrue = new Label();
|
||||
Label returnFalse = new Label();
|
||||
left.codeGen(ctx);
|
||||
right.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IF_ICMPLT, returnFalse);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, returnTrue);
|
||||
|
||||
ctx.getMv().visitLabel(returnFalse);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||
ctx.getMv().visitLabel(returnTrue);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
ctx.getMv().visitLabel(end);
|
||||
} else if (op == Operator.LE) {
|
||||
Label end = new Label();
|
||||
Label returnTrue = new Label();
|
||||
Label returnFalse = new Label();
|
||||
left.codeGen(ctx);
|
||||
right.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IF_ICMPGT, returnFalse);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, returnTrue);
|
||||
|
||||
ctx.getMv().visitLabel(returnFalse);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||
ctx.getMv().visitLabel(returnTrue);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
ctx.getMv().visitLabel(end);
|
||||
} else if (op == Operator.NE) {
|
||||
Label end = new Label();
|
||||
Label returnTrue = new Label();
|
||||
Label returnFalse = new Label();
|
||||
left.codeGen(ctx);
|
||||
right.codeGen(ctx);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.IF_ICMPEQ, returnFalse);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, returnTrue);
|
||||
|
||||
ctx.getMv().visitLabel(returnFalse);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||
ctx.getMv().visitLabel(returnTrue);
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
ctx.getMv().visitLabel(end);
|
||||
} else {
|
||||
left.codeGen(ctx);
|
||||
right.codeGen(ctx);
|
||||
if (op == Operator.ADD) {
|
||||
ctx.getMv().visitInsn(Opcodes.IADD);
|
||||
} else if (op == Operator.SUB) {
|
||||
ctx.getMv().visitInsn(Opcodes.ISUB);
|
||||
} else if (op == Operator.MUL) {
|
||||
ctx.getMv().visitInsn(Opcodes.IMUL);
|
||||
}
|
||||
}
|
||||
ctx.popStack();
|
||||
}
|
||||
}
|
||||
|
@ -103,12 +103,12 @@ public class TypedBlock implements TypedNode {
|
||||
Type chekType = null;
|
||||
for (TypedStatement stmt : stmts) {
|
||||
stmt.typeCheck(typedProgram);
|
||||
if(stmt instanceof TypedReturn returnStmt) {
|
||||
if (stmt instanceof TypedReturn returnStmt) {
|
||||
chekType = returnStmt.getType();
|
||||
}
|
||||
}
|
||||
|
||||
if(chekType == null) {
|
||||
if (chekType == null) {
|
||||
chekType = Type.VOID;
|
||||
}
|
||||
type = chekType;
|
||||
@ -117,7 +117,7 @@ public class TypedBlock implements TypedNode {
|
||||
|
||||
public void codeGen(MethodContext ctx) {
|
||||
for (TypedLocalVariable var : vars) {
|
||||
//var.codeGen(ctx);
|
||||
ctx.registerVariable(var.getName(), var.getType());
|
||||
}
|
||||
for (TypedStatement stmt : stmts) {
|
||||
stmt.codeGen(ctx);
|
||||
|
@ -4,12 +4,14 @@ import de.maishai.ast.records.BoolLiteral;
|
||||
import de.maishai.typedast.MethodContext;
|
||||
import de.maishai.typedast.TypedExpression;
|
||||
import de.maishai.typedast.Type;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TypedBoolLiteral implements TypedExpression {
|
||||
|
||||
private Boolean value;
|
||||
@ -32,10 +34,11 @@ public class TypedBoolLiteral implements TypedExpression {
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
if(value){
|
||||
if (value) {
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
}else{
|
||||
} else {
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||
}
|
||||
ctx.pushInstantToStack();
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,6 @@ import lombok.Data;
|
||||
public class TypedBreak implements TypedStatement {
|
||||
private Type type = Type.VOID;
|
||||
|
||||
public TypedBreak convertToTypedBreak(TypedClass clas, Break unTypedBreak) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
return type;
|
||||
|
@ -4,9 +4,11 @@ import de.maishai.ast.records.CharLiteral;
|
||||
import de.maishai.typedast.MethodContext;
|
||||
import de.maishai.typedast.TypedExpression;
|
||||
import de.maishai.typedast.Type;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class TypedCharLiteral implements TypedExpression {
|
||||
private char value;
|
||||
private Type type;
|
||||
@ -29,5 +31,6 @@ public class TypedCharLiteral implements TypedExpression {
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
ctx.getMv().visitLdcInsn(value);
|
||||
ctx.pushInstantToStack();
|
||||
}
|
||||
}
|
||||
|
@ -28,13 +28,11 @@ public class TypedClass implements TypedNode {
|
||||
private TypedConstructor currentConstructor;
|
||||
private Type type;
|
||||
|
||||
public TypedClass(TypedProgram typedProgram, Class c) {
|
||||
public TypedClass(Class c) {
|
||||
className = c.classname();
|
||||
type = Type.REFERENCE(className);
|
||||
convertMethodsAndConstructorsAndFields(typedProgram, c);
|
||||
}
|
||||
|
||||
|
||||
public boolean isParameterNameInCurrentConstructor(String parameterName) {
|
||||
if (currentConstructor == null) {
|
||||
return false;
|
||||
@ -47,7 +45,7 @@ public class TypedClass implements TypedNode {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void convertMethodsAndConstructorsAndFields(TypedProgram typedProgram, Class c){
|
||||
public void convertMethodsAndConstructorsAndFields(TypedProgram typedProgram, Class c) {
|
||||
// Am Anfang werden die Attribute, die Konstruktoren und Methoden in die jeweilige Liste eingefügt.
|
||||
// damit die Methoden verwendet werden können, bevor deren Blöcke ausgeführt werden
|
||||
for (Declaration declaration : c.fieldDeclarations()) {
|
||||
@ -62,7 +60,7 @@ public class TypedClass implements TypedNode {
|
||||
}
|
||||
}
|
||||
|
||||
public void covertBlocksOfConstructorsAndMethods(TypedProgram typedProgram, Class c){
|
||||
public void covertBlocksOfConstructorsAndMethods(TypedProgram typedProgram, Class c) {
|
||||
// Hier werden die Blöcke der Konstruktoren ausgeführt
|
||||
int i = 0;
|
||||
for (Constructor constructor : c.constructors()) {
|
||||
@ -119,6 +117,24 @@ public class TypedClass implements TypedNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isMethodOfCurrentClass(String methodName) {
|
||||
for (TypedMethod m : typedMethods) {
|
||||
if (m.getName().equals(methodName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Type getMethodType(String methodName) {
|
||||
for (TypedMethod m : typedMethods) {
|
||||
if (m.getName().equals(methodName)) {
|
||||
return m.getReturnType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Type getParameterTypeInCurrentConstructor(String parameterName) {
|
||||
for (TypedParameter p : currentConstructor.getTypedParameters()) {
|
||||
if (p.getParaName().equals(parameterName)) {
|
||||
|
@ -53,11 +53,20 @@ public class TypedConstructor implements TypedNode {
|
||||
name = unTypedConstructor.className();
|
||||
|
||||
for (Parameter param : unTypedConstructor.params()) {
|
||||
typedParameters.add(new TypedParameter(typedProgram, param));
|
||||
TypedParameter typedParameter = new TypedParameter(typedProgram, param);
|
||||
checkIfParameterExists(typedParameter.getParaName());
|
||||
typedParameters.add(typedParameter);
|
||||
localVariables.add(new TypedLocalVariable(typedParameter.getParaName(), typedParameter.getType()));
|
||||
}
|
||||
type = Type.VOID;
|
||||
}
|
||||
|
||||
public void checkIfParameterExists(String paraName) {
|
||||
if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(paraName))) {
|
||||
throw new RuntimeException("Parameter " + paraName + " already exists");
|
||||
}
|
||||
}
|
||||
|
||||
public void convertToBlock(TypedProgram typedProgram, Constructor unTypedConstructor) {
|
||||
this.typedBlock = new TypedBlock(typedProgram, unTypedConstructor.block());
|
||||
typeCheck(typedProgram);
|
||||
@ -76,12 +85,15 @@ public class TypedConstructor implements TypedNode {
|
||||
|
||||
public void codeGen(ClassContext ctx) {
|
||||
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
||||
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, "<init>", CodeGenUtils.generateDescriptor(typedParameters, Type.VOID), null, null);
|
||||
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, "<init>", CodeGenUtils.generateDescriptor(typedParameters.stream().map(TypedParameter::getType).toList(), Type.VOID), null, null);
|
||||
System.out.println("Visiting method: " + "<init>" + CodeGenUtils.generateDescriptor(typedParameters.stream().map(TypedParameter::getType).toList(), Type.VOID));
|
||||
MethodContext mctx = new MethodContext(ctx, mv);
|
||||
typedParameters.forEach(param -> mctx.registerVariable(param.getParaName(), param.getType()));
|
||||
//super();
|
||||
mctx.pushStack("this");
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
System.out.println("INVOKESPECIAL: " + "java/lang/Object" + " " + "<init>" + " " + "()V");
|
||||
mctx.popStack();
|
||||
|
||||
typedBlock.codeGen(mctx);
|
||||
|
||||
|
@ -9,7 +9,6 @@ import lombok.NoArgsConstructor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import static de.maishai.typedast.Type.Kind.REFERENCE;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@ -30,27 +29,17 @@ public final class TypedDeclaration implements TypedNode {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
if (type.getReference() != null && !typedProgram.getCurrentClass().getClassName().equals(type.getReference())) {
|
||||
if (!typedProgram.isTypedClassPresent(type.getReference())) {
|
||||
throw new RuntimeException("Type " + type.getReference() + " not found");
|
||||
}
|
||||
}
|
||||
if (typedProgram.getCurrentClass().isThereField(name)) {
|
||||
throw new RuntimeException("Field " + name + " already declared");
|
||||
}
|
||||
|
||||
if (type.getKind() == REFERENCE) {
|
||||
if (!type.getReference().equals(typedProgram.getCurrentClass().getClassName())) {
|
||||
throw new RuntimeException("Field " + name + " has wrong type");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
||||
System.out.println("Generating code for local variable " + name);
|
||||
int index = ctx.addVariable(name);
|
||||
mv.visitLocalVariable(name, type.getDescriptor(), null, ctx.getStartLabel(), ctx.getEndLabel(), index);
|
||||
}
|
||||
*/
|
||||
public void codeGen(ClassWriter cw) {
|
||||
int access = Opcodes.ACC_PUBLIC; // laut Andi ist es ok, dass alle Felder public sind
|
||||
cw.visitField(access, name, type.getDescriptor(), null, null).visitEnd();
|
||||
|
@ -7,6 +7,10 @@ import de.maishai.typedast.Type;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||
|
||||
@ -32,49 +36,88 @@ public class TypedFieldVarAccess implements TypedExpression {
|
||||
@Override
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
if (field) {
|
||||
if (typedProgram.getCurrentClass().isThereField(name)) {
|
||||
type = typedProgram.getCurrentClass().getFieldType(name);
|
||||
return typedProgram.getCurrentClass().getFieldType(name);
|
||||
}else{
|
||||
throw new RuntimeException("Field " + name + " not declared ");
|
||||
}
|
||||
type = checkFieldOrMethodType(typedProgram);
|
||||
return type;
|
||||
} else {
|
||||
if (typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||
if (typedProgram.getCurrentClass().isParameterNameInCurrentConstructor(name)) {
|
||||
type = typedProgram.getCurrentClass().getParameterTypeInCurrentConstructor(name);
|
||||
return type;
|
||||
} else if (typedProgram.getCurrentClass().getCurrentConstructor().isLocalVariablePresent(name)) {
|
||||
type = typedProgram.getCurrentClass().getCurrentConstructor().getLocalVariableType(name);
|
||||
return type;
|
||||
} else if(typedProgram.getCurrentClass().isThereField(name)){
|
||||
type = typedProgram.getCurrentClass().getFieldType(name);
|
||||
return type;
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Variable " + name + " not declared in constructor");
|
||||
}
|
||||
|
||||
} else if (typedProgram.getCurrentClass().isCurrentMethodPresent()) {
|
||||
if (typedProgram.getCurrentClass().isParameterWitNameInMethod(name)) {
|
||||
type = typedProgram.getCurrentClass().getParameterTypeInCurrentMethod(name);
|
||||
return type;
|
||||
} else if (typedProgram.getCurrentClass().getCurrentMethod().isLocalVariablePresent(name)) {
|
||||
type = typedProgram.getCurrentClass().getCurrentMethod().getLocalVariableType(name);
|
||||
return type;
|
||||
} else if(typedProgram.getCurrentClass().isThereField(name)){
|
||||
type = typedProgram.getCurrentClass().getFieldType(name);
|
||||
return type;
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Variable " + name + " not declared in method");
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Variable " + name + " not declared ");
|
||||
type = checkVariableType(typedProgram);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
private Type checkFieldOrMethodType(TypedProgram typedProgram) {
|
||||
if (typedProgram.getCurrentClass().isThereField(name)) {
|
||||
type = typedProgram.getCurrentClass().getFieldType(name);
|
||||
return type;
|
||||
} else if (typedProgram.getCurrentClass().isMethodOfCurrentClass(name)) {
|
||||
type = typedProgram.getCurrentClass().getMethodType(name);
|
||||
return type;
|
||||
} else if (recursiveOwnerChain instanceof TypedFieldVarAccess typedFieldVarAccess) {
|
||||
type = typedProgram.getCurrentClass().getFieldType(typedFieldVarAccess.getName());
|
||||
return type;
|
||||
} else {
|
||||
throw new RuntimeException("Field " + name + " not declared");
|
||||
}
|
||||
}
|
||||
|
||||
private Type checkVariableType(TypedProgram typedProgram) {
|
||||
if (typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||
return checkConstructorVariableType(typedProgram);
|
||||
} else if (typedProgram.getCurrentClass().isCurrentMethodPresent()) {
|
||||
return checkMethodVariableType(typedProgram);
|
||||
} else {
|
||||
throw new RuntimeException("Variable " + name + " not declared");
|
||||
}
|
||||
}
|
||||
|
||||
private Type checkConstructorVariableType(TypedProgram typedProgram) {
|
||||
if (typedProgram.getCurrentClass().isParameterNameInCurrentConstructor(name)) {
|
||||
type = typedProgram.getCurrentClass().getParameterTypeInCurrentConstructor(name);
|
||||
} else if (typedProgram.getCurrentClass().getCurrentConstructor().isLocalVariablePresent(name)) {
|
||||
type = typedProgram.getCurrentClass().getCurrentConstructor().getLocalVariableType(name);
|
||||
} else {
|
||||
return checkFieldOrMethodOrRecursiveType(typedProgram);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private Type checkMethodVariableType(TypedProgram typedProgram) {
|
||||
if (typedProgram.getCurrentClass().isParameterWitNameInMethod(name)) {
|
||||
type = typedProgram.getCurrentClass().getParameterTypeInCurrentMethod(name);
|
||||
} else if (typedProgram.getCurrentClass().getCurrentMethod().isLocalVariablePresent(name)) {
|
||||
type = typedProgram.getCurrentClass().getCurrentMethod().getLocalVariableType(name);
|
||||
} else {
|
||||
return checkFieldOrMethodOrRecursiveType(typedProgram);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private Type checkFieldOrMethodOrRecursiveType(TypedProgram typedProgram) {
|
||||
if (typedProgram.getCurrentClass().isThereField(name)) {
|
||||
type = typedProgram.getCurrentClass().getFieldType(name);
|
||||
} else if (typedProgram.getCurrentClass().isMethodOfCurrentClass(name)) {
|
||||
type = typedProgram.getCurrentClass().getMethodType(name);
|
||||
} else if (recursiveOwnerChain instanceof TypedFieldVarAccess typedFieldVarAccess) {
|
||||
type = typedProgram.getCurrentClass().getFieldType(typedFieldVarAccess.getName());
|
||||
} else {
|
||||
throw new RuntimeException("Variable " + name + " not declared");
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
|
||||
if (recursiveOwnerChain != null) {
|
||||
recursiveOwnerChain.codeGen(ctx);
|
||||
}
|
||||
if (field && recursiveOwnerChain == null) {
|
||||
ctx.pushStack("this");
|
||||
}
|
||||
if (field) {
|
||||
ctx.getMv().visitFieldInsn(Opcodes.GETFIELD, recursiveOwnerChain.getType().getReference(), name, type.getDescriptor());
|
||||
} else {
|
||||
int loadOpcode = type.getKind() == Type.Kind.REFERENCE ? Opcodes.ALOAD : Opcodes.ILOAD;
|
||||
ctx.getMv().visitVarInsn(loadOpcode, ctx.getLocalVar(name).get().index());
|
||||
System.out.println(loadOpcode == Opcodes.ALOAD ? "ALOAD " + ctx.getLocalVar(name).get().index() : "ILOAD " + ctx.getLocalVar(name).get().index());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package de.maishai.typedast.typedclass;
|
||||
|
||||
import de.maishai.ast.records.*;
|
||||
import de.maishai.typedast.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.objectweb.asm.Label;
|
||||
@ -11,6 +12,7 @@ import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TypedIfElse implements TypedStatement {
|
||||
private TypedExpression typedCon;
|
||||
private TypedBlock ifTypedBlock;
|
||||
|
@ -7,6 +7,10 @@ import de.maishai.typedast.Type;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@ -37,6 +41,16 @@ public class TypedIntLiteral implements TypedExpression {
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
ctx.getMv().visitLdcInsn(value);
|
||||
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||
ctx.getMv().visitIntInsn(Opcodes.BIPUSH, value);
|
||||
System.out.println("BIPUSH " + value);
|
||||
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||
ctx.getMv().visitIntInsn(Opcodes.SIPUSH, value);
|
||||
System.out.println("SIPUSH " + value);
|
||||
} else {
|
||||
ctx.getMv().visitLdcInsn(value);
|
||||
System.out.println("LDC " + value);
|
||||
}
|
||||
ctx.pushInstantToStack();
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package de.maishai.typedast.typedclass;
|
||||
|
||||
import de.maishai.ast.records.Method;
|
||||
import de.maishai.typedast.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
@ -12,6 +13,7 @@ import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TypedMethod implements TypedNode {
|
||||
private String name;
|
||||
private Type returnType;
|
||||
@ -28,7 +30,10 @@ public class TypedMethod implements TypedNode {
|
||||
name = unTypedMethod.methodName();
|
||||
returnType = unTypedMethod.type();
|
||||
for (var parameter : unTypedMethod.params()) {
|
||||
typedParameters.add(new TypedParameter(typedProgram, parameter));
|
||||
TypedParameter typedParameter = new TypedParameter(typedProgram, parameter);
|
||||
checkIfParameterExists(typedParameter.getParaName());
|
||||
typedParameters.add(typedParameter);
|
||||
localVariables.add(new TypedLocalVariable(typedParameter.getParaName(), typedParameter.getType()));
|
||||
}
|
||||
|
||||
typedProgram.getCurrentClass().getTypedMethods().stream().filter(method -> method.equals(this)).findFirst().ifPresentOrElse(
|
||||
@ -38,6 +43,12 @@ public class TypedMethod implements TypedNode {
|
||||
});
|
||||
}
|
||||
|
||||
public void checkIfParameterExists(String parameterName) {
|
||||
if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(parameterName))) {
|
||||
throw new RuntimeException("Parameter " + parameterName + " already exists");
|
||||
}
|
||||
}
|
||||
|
||||
public void convertToTypedBlock(TypedProgram typedProgram, Method unTypedMethod) {
|
||||
typedBlock = new TypedBlock(typedProgram, unTypedMethod.block());
|
||||
typeCheck(typedProgram);
|
||||
@ -109,7 +120,7 @@ public class TypedMethod implements TypedNode {
|
||||
public void codeGen(ClassContext ctx) {
|
||||
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
||||
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, name,
|
||||
CodeGenUtils.generateDescriptor(typedParameters, returnType), null, null);
|
||||
CodeGenUtils.generateDescriptor(typedParameters.stream().map(TypedParameter::getType).toList(), returnType), null, null);
|
||||
MethodContext context = new MethodContext(ctx, mv);
|
||||
typedParameters.forEach(param -> context.registerVariable(param.getParaName(), param.getType()));
|
||||
|
||||
|
@ -3,18 +3,20 @@ package de.maishai.typedast.typedclass;
|
||||
import de.maishai.ast.records.Expression;
|
||||
import de.maishai.ast.records.MethodCall;
|
||||
import de.maishai.typedast.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||
|
||||
//TODO: test this after fixing error from parser
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TypedMethodCall implements TypedExpression, TypedStatement {
|
||||
private TypedFieldVarAccess recipient;
|
||||
private List<TypedExpression> args = new ArrayList<>();
|
||||
@ -26,38 +28,60 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
|
||||
|
||||
public void convertToTypedMethodCall(TypedProgram typedProgram, MethodCall unTypedMethodCall) {
|
||||
recipient = new TypedFieldVarAccess(typedProgram, unTypedMethodCall.recipient());
|
||||
for (Expression arg : unTypedMethodCall.args()) {
|
||||
args.add(convertExpression(typedProgram, arg));
|
||||
}
|
||||
recipient.typeCheck(typedProgram);
|
||||
for (Expression arg : unTypedMethodCall.args()) {
|
||||
args.add(convertExpression(typedProgram, arg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
if (typedProgram.getCurrentClass().isCurrentMethodPresent() || typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||
String ownerChainName = null;
|
||||
if (recipient.getRecursiveOwnerChain() != null) {
|
||||
ownerChainName = recipient.getRecursiveOwnerChain().getType().getReference();
|
||||
}
|
||||
|
||||
List<TypedMethod> methods = typedProgram.getCurrentClass().getTypedMethods().stream()
|
||||
.filter(method -> method.getName().equals(recipient.getName()))
|
||||
.toList();
|
||||
|
||||
for (TypedMethod method : methods) {
|
||||
if (method.getTypedParameters().size() == args.size()) {
|
||||
boolean allMatch = true;
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
if (!args.get(i).typeCheck(typedProgram).equals(method.getTypedParameters().get(i).getType())) {
|
||||
allMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allMatch) {
|
||||
type = method.getReturnType();
|
||||
return type;
|
||||
}
|
||||
}
|
||||
if (!typedProgram.getCurrentClass().getClassName().equals(ownerChainName) && ownerChainName != null) {
|
||||
Optional<Type> matchingMethod = findMatchingMethod(typedProgram.getTypedClass(ownerChainName), recipient.getName());
|
||||
if (matchingMethod.isPresent()) {
|
||||
type = matchingMethod.get();
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
if (typedProgram.getCurrentClass().isCurrentMethodPresent() || typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||
Optional<Type> matchingMethod = findMatchingMethod(typedProgram.getCurrentClass(), recipient.getName());
|
||||
if (matchingMethod.isPresent()) {
|
||||
type = matchingMethod.get();
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Method not found");
|
||||
}
|
||||
|
||||
public Optional<Type> findMatchingMethod(TypedClass ownerChain, String methodName) {
|
||||
List<TypedMethod> methods = ownerChain.getTypedMethods().stream()
|
||||
.filter(method -> method.getName().equals(methodName))
|
||||
.toList();
|
||||
|
||||
for (TypedMethod method : methods) {
|
||||
if (method.getTypedParameters().size() == args.size()) {
|
||||
boolean allMatch = true;
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
if (!args.get(i).getType().equals(method.getTypedParameters().get(i).getType())) {
|
||||
allMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allMatch) {
|
||||
return Optional.of(method.getReturnType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
|
@ -3,7 +3,10 @@ package de.maishai.typedast.typedclass;
|
||||
import de.maishai.ast.records.Expression;
|
||||
import de.maishai.ast.records.New;
|
||||
import de.maishai.typedast.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -11,6 +14,7 @@ import java.util.List;
|
||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class TypedNew implements TypedExpression, TypedStatement {
|
||||
private Type type;
|
||||
private List<TypedExpression> args = new ArrayList<>();
|
||||
@ -28,6 +32,11 @@ public class TypedNew implements TypedExpression, TypedStatement {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
|
||||
if (typedProgram.isTypedClassPresent(type.getReference())) {
|
||||
return Type.REFERENCE(type.getReference());
|
||||
}
|
||||
|
||||
for (var constructor : typedProgram.getCurrentClass().getTypedConstructors()) {
|
||||
if (constructor.getTypedParameters().size() == args.size()) {
|
||||
boolean valid = true;
|
||||
@ -48,6 +57,21 @@ public class TypedNew implements TypedExpression, TypedStatement {
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
//pop the stack
|
||||
//ctx.popStack();
|
||||
//ctx.getMv().visitInsn(Opcodes.POP);
|
||||
//System.out.println("Popped stack");
|
||||
|
||||
ctx.getMv().visitTypeInsn(Opcodes.NEW, type.getReference());
|
||||
System.out.println("NEW " + type.getReference());
|
||||
ctx.pushAnonToStack();
|
||||
ctx.getMv().visitInsn(Opcodes.DUP);
|
||||
System.out.println("DUP");
|
||||
ctx.pushAnonToStack();
|
||||
for (TypedExpression arg : args) {
|
||||
arg.codeGen(ctx);
|
||||
}
|
||||
ctx.getMv().visitMethodInsn(Opcodes.INVOKESPECIAL, type.getReference(), "<init>", CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), Type.VOID), false);
|
||||
System.out.println("INVOKESPECIAL " + type.getReference() + "<init> " + CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), Type.VOID));
|
||||
}
|
||||
}
|
||||
|
@ -19,16 +19,23 @@ public class TypedProgram {
|
||||
|
||||
public void startConversion(Program program) {
|
||||
|
||||
// Initialisiere die Klassen nur mit den Klassennamen und deren Typ
|
||||
for (var clas : program.classes()) {
|
||||
typedClasses.add(new TypedClass(clas));
|
||||
}
|
||||
|
||||
// Konvertiere die Methoden, Konstruktoren und Felder von den jeweiligen Klassen
|
||||
int k = 0;
|
||||
for (var clas : program.classes()) {
|
||||
enterCurrentClass(typedClasses.get(k));
|
||||
typedClasses.add(new TypedClass(this, clas));
|
||||
typedClasses.get(k).convertMethodsAndConstructorsAndFields(this, clas);
|
||||
exitCurrentClass();
|
||||
k++;
|
||||
}
|
||||
|
||||
// Konvertiere die Blöcke der Konstruktoren und Methoden von den jeweiligen Klassen
|
||||
int i = 0;
|
||||
for(var clas : program.classes()){
|
||||
for (var clas : program.classes()) {
|
||||
enterCurrentClass(typedClasses.get(i));
|
||||
typedClasses.get(i).covertBlocksOfConstructorsAndMethods(this, clas);
|
||||
exitCurrentClass();
|
||||
@ -40,8 +47,8 @@ public class TypedProgram {
|
||||
return typedClasses.stream().filter(clas -> clas.getClassName().equals(className)).findFirst().get();
|
||||
}
|
||||
|
||||
public boolean isCurrentClassPresent() {
|
||||
return currentClass != null;
|
||||
public boolean isTypedClassPresent(String className) {
|
||||
return typedClasses.stream().anyMatch(clas -> clas.getClassName().equals(className));
|
||||
}
|
||||
|
||||
public void enterCurrentClass(TypedClass clas) {
|
||||
@ -52,4 +59,18 @@ public class TypedProgram {
|
||||
currentClass = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
TypedProgram other = (TypedProgram) obj;
|
||||
if(typedClasses.equals(other.typedClasses) &&
|
||||
(currentClass == null && other.currentClass == null
|
||||
|| currentClass.equals(other.currentClass))) {
|
||||
return true;
|
||||
} else {
|
||||
System.out.println("TypedPrograms are not equal:\n" + this.typedClasses + "\n" + other.typedClasses + "\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package de.maishai.typedast.typedclass;
|
||||
|
||||
import de.maishai.ast.records.*;
|
||||
import de.maishai.typedast.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@ -11,6 +12,7 @@ import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TypedReturn implements TypedStatement {
|
||||
private TypedExpression ret;
|
||||
private Type type;
|
||||
@ -21,9 +23,9 @@ public class TypedReturn implements TypedStatement {
|
||||
|
||||
public void convertToTypedReturn(TypedProgram typedProgram, Return unTypedReturn) {
|
||||
ret = convertExpression(typedProgram, unTypedReturn.ret());
|
||||
if(ret == null){
|
||||
if (ret == null) {
|
||||
type = Type.VOID;
|
||||
}else{
|
||||
} else {
|
||||
type = ret.getType();
|
||||
}
|
||||
}
|
||||
@ -48,6 +50,7 @@ public class TypedReturn implements TypedStatement {
|
||||
if (ret == null) {
|
||||
ctx.getMv().visitInsn(Opcodes.RETURN);
|
||||
} else {
|
||||
System.out.println("return: " + ret);
|
||||
ret.codeGen(ctx);
|
||||
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
|
||||
ctx.getMv().visitInsn(Opcodes.IRETURN);
|
||||
|
@ -47,11 +47,11 @@ public class TypedUnary implements TypedExpression {
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
right.codeGen(ctx);
|
||||
if(op == UnaryOperator.NOT){
|
||||
if (op == UnaryOperator.NOT) {
|
||||
ctx.getMv().visitInsn(Opcodes.ICONST_1);
|
||||
ctx.getMv().visitInsn(Opcodes.IXOR);
|
||||
}
|
||||
if(op == UnaryOperator.SUB){
|
||||
if (op == UnaryOperator.SUB) {
|
||||
ctx.getMv().visitInsn(Opcodes.INEG);
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +165,6 @@ public class AbstractSyntax_ClassWithConstructor {
|
||||
localVariables,
|
||||
statementList
|
||||
);
|
||||
|
||||
return new Constructor(
|
||||
"ClassWithConstructor",
|
||||
parameters,
|
||||
|
@ -0,0 +1,902 @@
|
||||
//public class ComplexClass {
|
||||
//
|
||||
// int x;
|
||||
// int y;
|
||||
// ComplexClass b;
|
||||
// ComplexClass c;
|
||||
//
|
||||
// public ComplexClass() {
|
||||
// this.y = 10;
|
||||
// this.x = 2;
|
||||
// int i;
|
||||
// for (i = 0; i < (this.y + 1); i = i + 1) {
|
||||
// int j;
|
||||
// for (j = 0; j < this.y; j += 1) {
|
||||
// this.x = this.x * this.x;
|
||||
// if (this.x == 100) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// this.y = 2;
|
||||
// do {
|
||||
// this.y = this.y + 1;
|
||||
// } while (this.y < 10);
|
||||
//
|
||||
// int k;
|
||||
// k = 0;
|
||||
// for (k = 0; k < 10; k = k + 1) {
|
||||
// if (k == 5) {
|
||||
// return this;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public ComplexClass(int x) {
|
||||
// this.b = new ComplexClass();
|
||||
// this.c = new ComplexClass();
|
||||
// this.x = x;
|
||||
// this.b.x = 7;
|
||||
// this.b.y = 13;
|
||||
// this.c.x = this.b.getX() * this.b.y * this.b.getX('g');
|
||||
// this.c.y = 25;
|
||||
// }
|
||||
//
|
||||
// public ComplexClass(int x, int y) {
|
||||
// this.x = x;
|
||||
// this.y = y;
|
||||
// }
|
||||
//
|
||||
// public ComplexClass initComplexClass(int x) {
|
||||
// int a;
|
||||
// a = 10;
|
||||
// this.b = new ComplexClass(x);
|
||||
// this.b.x = 10 + a;
|
||||
// this.b.y = 20;
|
||||
// this.b.c.x = 20 + a;
|
||||
// if (methodCall()) {
|
||||
// this.b.getC().b.y = this.b.x;
|
||||
// }
|
||||
// return this.b;
|
||||
// }
|
||||
//
|
||||
// public ComplexClass init(int x, int y) {
|
||||
// return new ComplexClass(x, y);
|
||||
// }
|
||||
//
|
||||
// public ComplexClass(int x, int y, char z) {
|
||||
// this.x = x;
|
||||
// this.y = y;
|
||||
// }
|
||||
//
|
||||
// public int getX(char z) {
|
||||
// return this.x;
|
||||
// }
|
||||
//
|
||||
// public ComplexClass getC() {
|
||||
// return this.c;
|
||||
// }
|
||||
//
|
||||
// public int getX() {
|
||||
// return this.x;
|
||||
// }
|
||||
//
|
||||
// public boolean methodCall() {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
|
||||
import de.maishai.ast.Operator;
|
||||
import de.maishai.ast.records.*;
|
||||
import de.maishai.ast.records.Class;
|
||||
import de.maishai.typedast.Type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("DuplicateExpressions")
|
||||
public class AbstractSyntax_ComplexClass {
|
||||
public static Program get() {
|
||||
List<Declaration> declarationList = List.of(
|
||||
new Declaration(
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new Declaration(
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
new Declaration(
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
new Declaration(
|
||||
"c",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
)
|
||||
);
|
||||
List<Method> methodList = getMethods();
|
||||
List<Constructor> constructorList = getConstructors();
|
||||
return new Program(
|
||||
List.of(
|
||||
new Class(
|
||||
"ComplexClass",
|
||||
declarationList,
|
||||
methodList,
|
||||
constructorList
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static List<Constructor> getConstructors() {
|
||||
return List.of(
|
||||
getConstructor1(),
|
||||
getConstructor2(),
|
||||
getConstructor3(),
|
||||
getConstructor4()
|
||||
);
|
||||
}
|
||||
|
||||
private static Constructor getConstructor1() {
|
||||
Block block = new Block(
|
||||
List.of(
|
||||
new Declaration(
|
||||
"i",
|
||||
Type.INT
|
||||
),
|
||||
new Declaration(
|
||||
"k",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
List.of(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y"),
|
||||
new IntLiteral(10)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"),
|
||||
new IntLiteral(2)
|
||||
),
|
||||
new For(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"i"),
|
||||
new IntLiteral(0)
|
||||
),
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"i"),
|
||||
Operator.LT,
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y"),
|
||||
Operator.ADD,
|
||||
new IntLiteral(1)
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"i"),
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"i"),
|
||||
Operator.ADD,
|
||||
new IntLiteral(1)
|
||||
)
|
||||
),
|
||||
new Block(
|
||||
List.of(
|
||||
new Declaration(
|
||||
"j",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
List.of(
|
||||
new For(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"j"),
|
||||
new IntLiteral(0)
|
||||
),
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"j"),
|
||||
Operator.LT,
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y"
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"j"),
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"j"),
|
||||
Operator.ADD,
|
||||
new IntLiteral(1)
|
||||
)
|
||||
),
|
||||
new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"),
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"),
|
||||
Operator.MUL,
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"
|
||||
)
|
||||
)
|
||||
),
|
||||
new IfElse(
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"),
|
||||
Operator.EQ,
|
||||
new IntLiteral(100)
|
||||
),
|
||||
new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Break()
|
||||
)
|
||||
),
|
||||
null
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y"),
|
||||
new IntLiteral(2)
|
||||
),
|
||||
new DoWhile(
|
||||
new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y"),
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y"),
|
||||
Operator.ADD,
|
||||
new IntLiteral(1)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y"),
|
||||
Operator.LT,
|
||||
new IntLiteral(10)
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"k"),
|
||||
new IntLiteral(0)
|
||||
),
|
||||
new For(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"k"),
|
||||
new IntLiteral(0)
|
||||
),
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"k"),
|
||||
Operator.LT,
|
||||
new IntLiteral(10)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"k"),
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"k"),
|
||||
Operator.ADD,
|
||||
new IntLiteral(1)
|
||||
)
|
||||
),
|
||||
new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new IfElse(
|
||||
new Binary(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"k"),
|
||||
Operator.EQ,
|
||||
new IntLiteral(5)
|
||||
),
|
||||
new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Return(
|
||||
new This()
|
||||
)
|
||||
)
|
||||
),
|
||||
null
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
return new Constructor(
|
||||
"ComplexClass",
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static Constructor getConstructor2() {
|
||||
Block block = new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"b"),
|
||||
new New(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of()
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"c"),
|
||||
new New(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of()
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"),
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x"
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"),
|
||||
"x"),
|
||||
new IntLiteral(7)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"),
|
||||
"y"),
|
||||
new IntLiteral(13)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"c"),
|
||||
"x"),
|
||||
new Binary(
|
||||
new Binary(
|
||||
new MethodCall(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"),
|
||||
"getX"
|
||||
),
|
||||
List.of()
|
||||
),
|
||||
Operator.MUL,
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"),
|
||||
"y"
|
||||
)
|
||||
),
|
||||
Operator.MUL,
|
||||
new MethodCall(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"),
|
||||
"getX"
|
||||
),
|
||||
List.of(
|
||||
new CharLiteral('g')
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"c"),
|
||||
"y"),
|
||||
new IntLiteral(25)
|
||||
)
|
||||
)
|
||||
);
|
||||
return new Constructor(
|
||||
"ComplexClass",
|
||||
List.of(
|
||||
new Parameter(
|
||||
"x",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static Constructor getConstructor3() {
|
||||
Block block = new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"),
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x"
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y"),
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"y"
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
return new Constructor(
|
||||
"ComplexClass",
|
||||
List.of(
|
||||
new Parameter(
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new Parameter(
|
||||
"y",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static Constructor getConstructor4() {
|
||||
Block block = new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"),
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x"
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y"),
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"y"
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
return new Constructor(
|
||||
"ComplexClass",
|
||||
List.of(
|
||||
new Parameter(
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new Parameter(
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
new Parameter(
|
||||
"z",
|
||||
Type.CHAR
|
||||
)
|
||||
),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static List<Method> getMethods() {
|
||||
return List.of(
|
||||
getMethod1(),
|
||||
getMethod2(),
|
||||
getMethod3(),
|
||||
getMethod4(),
|
||||
getMethod5(),
|
||||
getMethod6()
|
||||
);
|
||||
}
|
||||
|
||||
private static Method getMethod1() {
|
||||
Block block = new Block(
|
||||
List.of(
|
||||
new Declaration(
|
||||
"a",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
List.of(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"a"),
|
||||
new IntLiteral(10)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"b"),
|
||||
new New(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x"
|
||||
)
|
||||
)
|
||||
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"),
|
||||
"x"),
|
||||
new Binary(
|
||||
new IntLiteral(10),
|
||||
Operator.ADD,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"a"
|
||||
)
|
||||
)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"),
|
||||
"y"),
|
||||
new IntLiteral(20)
|
||||
),
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"),
|
||||
"c"),
|
||||
"x"),
|
||||
new Binary(
|
||||
new IntLiteral(20),
|
||||
Operator.ADD,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"a"
|
||||
)
|
||||
)
|
||||
),
|
||||
new IfElse(
|
||||
new MethodCall(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"methodCall"),
|
||||
List.of()
|
||||
),
|
||||
new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Assignment(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
new MethodCall(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"
|
||||
),
|
||||
"getC"
|
||||
),
|
||||
List.of()
|
||||
),
|
||||
"b"),
|
||||
"y"),
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b"
|
||||
),
|
||||
"x"
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
null
|
||||
),
|
||||
new Return(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"b"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
);
|
||||
return new Method(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
"initComplexClass",
|
||||
List.of(
|
||||
new Parameter(
|
||||
"x",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static Method getMethod2() {
|
||||
Block block = new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Return(
|
||||
new New(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of(
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x"
|
||||
),
|
||||
new FieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"y"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
return new Method(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
"init",
|
||||
List.of(
|
||||
new Parameter(
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new Parameter(
|
||||
"y",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static Method getMethod3() {
|
||||
Block block = new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Return(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
return new Method(
|
||||
Type.INT,
|
||||
"getX",
|
||||
List.of(
|
||||
new Parameter(
|
||||
"z",
|
||||
Type.CHAR
|
||||
)
|
||||
),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static Method getMethod4() {
|
||||
Block block = new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Return(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"c"
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
return new Method(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
"getC",
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static Method getMethod5() {
|
||||
Block block = new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Return(
|
||||
new FieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x"
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
return new Method(
|
||||
Type.INT,
|
||||
"getX",
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static Method getMethod6() {
|
||||
Block block = new Block(
|
||||
List.of(),
|
||||
List.of(
|
||||
new Return(
|
||||
new BoolLiteral(false)
|
||||
)
|
||||
)
|
||||
);
|
||||
return new Method(
|
||||
Type.BOOL,
|
||||
"methodCall",
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
}
|
19
src/main/resources/JavaTestfiles/ClassCanBeTyped.java
Normal file
19
src/main/resources/JavaTestfiles/ClassCanBeTyped.java
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
public class ClassCanBeTyped{
|
||||
public int c;
|
||||
public ClassCanBeTyped d;
|
||||
public int x;
|
||||
|
||||
public ClassCanBeTyped() {
|
||||
}
|
||||
|
||||
public ClassCanBeTyped(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public ClassCanBeTyped test(int i) {
|
||||
ClassCanBeTyped a;
|
||||
a = new ClassCanBeTyped(i);
|
||||
return a;
|
||||
}
|
||||
}
|
@ -4,44 +4,21 @@ public class ComplexClass {
|
||||
int y;
|
||||
ComplexClass b;
|
||||
ComplexClass c;
|
||||
public ComplexClass(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
public ComplexClass(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
public ComplexClass initComplexClass(int x) {
|
||||
int a;
|
||||
a = 10;
|
||||
b = new ComplexClass(x);
|
||||
b.x = 10 + a;
|
||||
b.y = 20;
|
||||
b.c.x = 20 + a;
|
||||
b.c.b.y = b.x;
|
||||
|
||||
return b;
|
||||
}
|
||||
public ComplexClass init(int x, int y) {
|
||||
return new ComplexClass(x, y);
|
||||
}
|
||||
public ComplexClass(int x) {
|
||||
this.x = x;
|
||||
int i;
|
||||
b = b.getX().c.getC();
|
||||
i = b.getX().c.getX();
|
||||
}
|
||||
|
||||
public ComplexClass() {
|
||||
this.x = 10;
|
||||
this.y = 10;
|
||||
this.x = 2;
|
||||
int i;
|
||||
for (i = 0; i < (x + 1); i = i + 1) {
|
||||
for (i = 0; i < (this.y + 1); i = i + 1) {
|
||||
int j;
|
||||
for (j = 0; j < this.x; j += 1) {
|
||||
for (j = 0; j < this.y; j += 1) {
|
||||
this.x = this.x * this.x;
|
||||
break;
|
||||
if (this.x == 100) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.y = 2;
|
||||
do {
|
||||
this.y = this.y + 1;
|
||||
} while (this.y < 10);
|
||||
@ -50,12 +27,44 @@ public class ComplexClass {
|
||||
k = 0;
|
||||
for (k = 0; k < 10; k = k + 1) {
|
||||
if (k == 5) {
|
||||
return;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ComplexClass(int x) {
|
||||
this.b = new ComplexClass();
|
||||
this.c = new ComplexClass();
|
||||
this.x = x;
|
||||
this.b.x = 7;
|
||||
this.b.y = 13;
|
||||
this.c.x = this.b.getX() * this.b.y * this.b.getX('g');
|
||||
this.c.y = 25;
|
||||
}
|
||||
|
||||
public ComplexClass(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public ComplexClass initComplexClass(int x) {
|
||||
int a;
|
||||
a = 10;
|
||||
this.b = new ComplexClass(x);
|
||||
this.b.x = 10 + a;
|
||||
this.b.y = 20;
|
||||
this.b.c.x = 20 + a;
|
||||
if (methodCall()) {
|
||||
this.b.getC().b.y = this.b.x;
|
||||
}
|
||||
return this.b;
|
||||
}
|
||||
|
||||
public ComplexClass init(int x, int y) {
|
||||
return new ComplexClass(x, y);
|
||||
}
|
||||
|
||||
public ComplexClass(int x, int y, char z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
@ -66,16 +75,15 @@ public class ComplexClass {
|
||||
}
|
||||
|
||||
public ComplexClass getC() {
|
||||
return c;
|
||||
return this.c;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public boolean methodCall() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -35,9 +35,10 @@ public class TypedAbstractSyntax_ClassWithConstructor {
|
||||
getConstructors(),
|
||||
null,
|
||||
null,
|
||||
Type.REFERENCE("ClassWithField")
|
||||
Type.REFERENCE("ClassWithConstructor")
|
||||
)
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@ -203,20 +204,20 @@ public class TypedAbstractSyntax_ClassWithConstructor {
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
Type.INT
|
||||
Type.VOID
|
||||
),
|
||||
Type.INT
|
||||
Type.VOID
|
||||
)
|
||||
),
|
||||
Type.INT
|
||||
Type.VOID
|
||||
),
|
||||
Type.INT
|
||||
Type.VOID
|
||||
)
|
||||
);
|
||||
TypedBlock typedBlock = new TypedBlock(
|
||||
typedLocalVariables,
|
||||
typedStatementList,
|
||||
Type.INT
|
||||
Type.VOID
|
||||
);
|
||||
|
||||
return new TypedConstructor(
|
||||
|
@ -38,7 +38,8 @@ public class TypedAbstractSyntax_ClassWithField {
|
||||
null,
|
||||
Type.REFERENCE("ClassWithField")
|
||||
)
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,960 @@
|
||||
//public class ComplexClass {
|
||||
//
|
||||
// int x;
|
||||
// int y;
|
||||
// ComplexClass b;
|
||||
// ComplexClass c;
|
||||
//
|
||||
// public ComplexClass() {
|
||||
// this.y = 10;
|
||||
// this.x = 2;
|
||||
// int i;
|
||||
// for (i = 0; i < (this.y + 1); i = i + 1) {
|
||||
// int j;
|
||||
// for (j = 0; j < this.y; j += 1) {
|
||||
// this.x = this.x * this.x;
|
||||
// if (this.x == 100) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// this.y = 2;
|
||||
// do {
|
||||
// this.y = this.y + 1;
|
||||
// } while (this.y < 10);
|
||||
//
|
||||
// int k;
|
||||
// k = 0;
|
||||
// for (k = 0; k < 10; k = k + 1) {
|
||||
// if (k == 5) {
|
||||
// return this;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public ComplexClass(int x) {
|
||||
// this.b = new ComplexClass();
|
||||
// this.c = new ComplexClass();
|
||||
// this.x = x;
|
||||
// this.b.x = 7;
|
||||
// this.b.y = 13;
|
||||
// this.c.x = this.b.getX() * this.b.y * this.b.getX('g');
|
||||
// this.c.y = 25;
|
||||
// }
|
||||
//
|
||||
// public ComplexClass(int x, int y) {
|
||||
// this.x = x;
|
||||
// this.y = y;
|
||||
// }
|
||||
//
|
||||
// public ComplexClass initComplexClass(int x) {
|
||||
// int a;
|
||||
// a = 10;
|
||||
// this.b = new ComplexClass(x);
|
||||
// this.b.x = 10 + a;
|
||||
// this.b.y = 20;
|
||||
// this.b.c.x = 20 + a;
|
||||
// if (methodCall()) {
|
||||
// this.b.getC().b.y = this.b.x;
|
||||
// }
|
||||
// return this.b;
|
||||
// }
|
||||
//
|
||||
// public ComplexClass init(int x, int y) {
|
||||
// return new ComplexClass(x, y);
|
||||
// }
|
||||
//
|
||||
// public ComplexClass(int x, int y, char z) {
|
||||
// this.x = x;
|
||||
// this.y = y;
|
||||
// }
|
||||
//
|
||||
// public int getX(char z) {
|
||||
// return this.x;
|
||||
// }
|
||||
//
|
||||
// public ComplexClass getC() {
|
||||
// return this.c;
|
||||
// }
|
||||
//
|
||||
// public int getX() {
|
||||
// return this.x;
|
||||
// }
|
||||
//
|
||||
// public boolean methodCall() {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
|
||||
import de.maishai.ast.Operator;
|
||||
import de.maishai.typedast.Type;
|
||||
import de.maishai.typedast.typedclass.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class TypedAbstractSyntax_ComplexClass {
|
||||
public static TypedProgram get() {
|
||||
return new TypedProgram(
|
||||
getClasses(),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
private static List<TypedClass> getClasses() {
|
||||
return List.of(
|
||||
getClass1()
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedClass getClass1() {
|
||||
return new TypedClass(
|
||||
"ComplexClass",
|
||||
getFields(),
|
||||
getMethods(),
|
||||
getConstructors(),
|
||||
null,
|
||||
null,
|
||||
Type.REFERENCE("ComplexClass")
|
||||
);
|
||||
}
|
||||
|
||||
private static List<TypedDeclaration> getFields() {
|
||||
return List.of(
|
||||
new TypedDeclaration("x", Type.INT),
|
||||
new TypedDeclaration("y", Type.INT),
|
||||
new TypedDeclaration("b", Type.REFERENCE("ComplexClass")),
|
||||
new TypedDeclaration("c", Type.REFERENCE("ComplexClass"))
|
||||
);
|
||||
}
|
||||
|
||||
private static List<TypedConstructor> getConstructors() {
|
||||
return List.of(
|
||||
getConstructor1(),
|
||||
getConstructor2(),
|
||||
getConstructor3(),
|
||||
getConstructor4()
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedConstructor getConstructor1() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(
|
||||
new TypedLocalVariable("i", Type.INT),
|
||||
new TypedLocalVariable("k", Type.INT)
|
||||
),
|
||||
List.of(
|
||||
new TypedAssignment(
|
||||
new TypedIntLiteral(10),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedIntLiteral(2),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedFor(
|
||||
new TypedAssignment(
|
||||
new TypedIntLiteral(0),
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"i",
|
||||
Type.INT),
|
||||
Type.INT
|
||||
),
|
||||
new TypedBinary(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"i",
|
||||
Type.INT),
|
||||
Operator.LT,
|
||||
new TypedBinary(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Operator.ADD,
|
||||
new TypedIntLiteral(1),
|
||||
Type.INT
|
||||
),
|
||||
Type.BOOL
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedBinary(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"i",
|
||||
Type.INT),
|
||||
Operator.ADD,
|
||||
new TypedIntLiteral(1),
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"i",
|
||||
Type.INT),
|
||||
Type.INT
|
||||
),
|
||||
new TypedBlock(
|
||||
List.of(
|
||||
new TypedLocalVariable(
|
||||
"j",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
List.of(
|
||||
new TypedFor(
|
||||
new TypedAssignment(
|
||||
new TypedIntLiteral(0),
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"j",
|
||||
Type.INT),
|
||||
Type.INT
|
||||
),
|
||||
new TypedBinary(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"j",
|
||||
Type.INT),
|
||||
Operator.LT,
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Type.BOOL
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedBinary(
|
||||
new TypedIntLiteral(1),
|
||||
Operator.ADD,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"j",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"j",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedAssignment(
|
||||
new TypedBinary(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Operator.MUL,
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedIfElse(
|
||||
new TypedBinary(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Operator.EQ,
|
||||
new TypedIntLiteral(100),
|
||||
Type.BOOL
|
||||
),
|
||||
new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedBreak()
|
||||
)
|
||||
),
|
||||
null,
|
||||
Type.VOID
|
||||
)
|
||||
)
|
||||
),
|
||||
Type.VOID
|
||||
)
|
||||
)
|
||||
),
|
||||
Type.VOID
|
||||
)
|
||||
|
||||
)
|
||||
);
|
||||
return new TypedConstructor(
|
||||
"ComplexClass",
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedConstructor getConstructor2() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedAssignment(
|
||||
new TypedNew(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of()
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedNew(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of()
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedIntLiteral(7),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedIntLiteral(13),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedBinary(
|
||||
new TypedBinary(
|
||||
new TypedMethodCall(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"getX",
|
||||
Type.INT
|
||||
),
|
||||
List.of(),
|
||||
Type.INT
|
||||
),
|
||||
Operator.MUL,
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
Operator.MUL,
|
||||
new TypedMethodCall(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"getX",
|
||||
Type.INT
|
||||
),
|
||||
List.of(
|
||||
new TypedCharLiteral(
|
||||
'g',
|
||||
Type.CHAR
|
||||
)
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"c",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedIntLiteral(25),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"c",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
)
|
||||
)
|
||||
);
|
||||
return new TypedConstructor(
|
||||
"ComplexClass",
|
||||
List.of(
|
||||
new TypedParameter(
|
||||
"x",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedConstructor getConstructor3() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedAssignment(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
)
|
||||
)
|
||||
);
|
||||
return new TypedConstructor(
|
||||
"ComplexClass",
|
||||
List.of(
|
||||
new TypedParameter(
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new TypedParameter(
|
||||
"y",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedConstructor getConstructor4() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedAssignment(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
)
|
||||
)
|
||||
);
|
||||
return new TypedConstructor(
|
||||
"ComplexClass",
|
||||
List.of(
|
||||
new TypedParameter(
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new TypedParameter(
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
new TypedParameter(
|
||||
"z",
|
||||
Type.CHAR
|
||||
)
|
||||
),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static List<TypedMethod> getMethods() {
|
||||
return List.of(
|
||||
getMethod1(),
|
||||
getMethod2(),
|
||||
getMethod3(),
|
||||
getMethod4(),
|
||||
getMethod5(),
|
||||
getMethod6()
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedMethod getMethod1() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(
|
||||
new TypedLocalVariable("a", Type.INT)
|
||||
),
|
||||
List.of(
|
||||
new TypedAssignment(
|
||||
new TypedIntLiteral(10),
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"a",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedNew(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
)
|
||||
)
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedBinary(
|
||||
new TypedIntLiteral(10),
|
||||
Operator.ADD,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"a",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedIntLiteral(20),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedAssignment(
|
||||
new TypedBinary(
|
||||
new TypedIntLiteral(20),
|
||||
Operator.ADD,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"a",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"c",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
),
|
||||
new TypedIfElse(
|
||||
new TypedMethodCall(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"methodCall",
|
||||
Type.BOOL
|
||||
),
|
||||
List.of(),
|
||||
Type.BOOL
|
||||
),
|
||||
new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedAssignment(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
new TypedMethodCall(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"getC",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
List.of(),
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
"y",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
)
|
||||
)
|
||||
),
|
||||
null,
|
||||
Type.VOID
|
||||
),
|
||||
new TypedReturn(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"b",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
Type.REFERENCE("ComplexClass")
|
||||
)
|
||||
)
|
||||
);
|
||||
return new TypedMethod(
|
||||
"initComplexClass",
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of(
|
||||
new TypedParameter(
|
||||
"x",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedMethod getMethod2() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedReturn(
|
||||
new TypedNew(
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of(
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new TypedFieldVarAccess(
|
||||
false,
|
||||
null,
|
||||
"y",
|
||||
Type.INT
|
||||
)
|
||||
)
|
||||
),
|
||||
Type.REFERENCE("ComplexClass")
|
||||
)
|
||||
)
|
||||
);
|
||||
return new TypedMethod(
|
||||
"init",
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of(
|
||||
new TypedParameter(
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
new TypedParameter(
|
||||
"y",
|
||||
Type.INT
|
||||
)
|
||||
),
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedMethod getMethod3() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedReturn(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
)
|
||||
)
|
||||
);
|
||||
return new TypedMethod(
|
||||
"getX",
|
||||
Type.INT,
|
||||
List.of(
|
||||
new TypedParameter(
|
||||
"z",
|
||||
Type.CHAR
|
||||
)
|
||||
),
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedMethod getMethod4() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedReturn(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"c",
|
||||
Type.REFERENCE("ComplexClass")
|
||||
),
|
||||
Type.REFERENCE("ComplexClass")
|
||||
)
|
||||
)
|
||||
);
|
||||
return new TypedMethod(
|
||||
"getC",
|
||||
Type.REFERENCE("ComplexClass"),
|
||||
List.of(),
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedMethod getMethod5() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedReturn(
|
||||
new TypedFieldVarAccess(
|
||||
true,
|
||||
null,
|
||||
"x",
|
||||
Type.INT
|
||||
),
|
||||
Type.INT
|
||||
)
|
||||
)
|
||||
);
|
||||
return new TypedMethod(
|
||||
"getX",
|
||||
Type.INT,
|
||||
List.of(),
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
private static TypedMethod getMethod6() {
|
||||
TypedBlock block = new TypedBlock(
|
||||
List.of(),
|
||||
List.of(
|
||||
new TypedReturn(
|
||||
new TypedBoolLiteral(
|
||||
false,
|
||||
Type.BOOL
|
||||
),
|
||||
Type.BOOL
|
||||
)
|
||||
)
|
||||
);
|
||||
return new TypedMethod(
|
||||
"methodCall",
|
||||
Type.BOOL,
|
||||
List.of(),
|
||||
List.of(),
|
||||
block
|
||||
);
|
||||
}
|
||||
}
|
@ -31,7 +31,8 @@ public class TypedAbstractSyntax_PublicClass {
|
||||
null,
|
||||
Type.REFERENCE("PublicClass")
|
||||
)
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
16
src/test/java/CodegeneratorTests.java
Normal file
16
src/test/java/CodegeneratorTests.java
Normal file
@ -0,0 +1,16 @@
|
||||
import de.maishai.Compiler;
|
||||
import de.maishai.ast.records.Program;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class CodegeneratorTests {
|
||||
|
||||
// @Test
|
||||
// public void testPublicClass() {
|
||||
// byte[] resultBytecode = Compiler.generateByteCodeArrayFromTypedAst();
|
||||
// assertEquals(AbstractSyntax_PublicClass.get(), resultBytecode);
|
||||
// }
|
||||
}
|
@ -59,6 +59,6 @@ public class ScannerParserTests {
|
||||
@Test
|
||||
public void testComplexClass() {
|
||||
Program resultAst = Compiler.generateASTFromFile(List.of("src/main/resources/JavaTestfiles/ComplexClass.java"));
|
||||
assertEquals(AbstractSyntax_ClassWithConstructorAndMethodCall.get(), resultAst);
|
||||
assertEquals(TypedAbstractSyntax_ComplexClass.get(), resultAst);
|
||||
}
|
||||
}
|
||||
|
@ -23,4 +23,10 @@ public class TypingTests {
|
||||
TypedProgram resultTypedAst = Compiler.generateTypedASTFromAst(AbstractSyntax_ClassWithConstructor.get());
|
||||
assertEquals(TypedAbstractSyntax_ClassWithConstructor.get(), resultTypedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexClass() {
|
||||
TypedProgram resultTypedAst = Compiler.generateTypedASTFromAst(AbstractSyntax_ComplexClass.get());
|
||||
assertEquals(TypedAbstractSyntax_ComplexClass.get(), resultTypedAst);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user