mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-28 17:28:03 +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) {
|
public static void main(String[] args) {
|
||||||
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java",
|
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java",
|
||||||
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java"),
|
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java",
|
||||||
List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall"));
|
"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);
|
DecafParser.RecipientContext ctx = ctxList.get(lastElement);
|
||||||
ctxList.remove(lastElement);
|
ctxList.remove(lastElement);
|
||||||
if (ctx.id() != null) {
|
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) {
|
if (ctx.methName() != null) {
|
||||||
List<Expression> args = new ArrayList<>();
|
List<Expression> args = new ArrayList<>();
|
||||||
|
@ -6,11 +6,13 @@ import org.objectweb.asm.ClassWriter;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ClassContext {
|
public class ClassContext {
|
||||||
private Type name;
|
private String name;
|
||||||
|
private Type type;
|
||||||
private ClassWriter cw;
|
private ClassWriter cw;
|
||||||
|
|
||||||
public ClassContext(String name, ClassWriter cw) {
|
public ClassContext(String name, ClassWriter cw) {
|
||||||
this.name = Type.REFERENCE(name);
|
this.name = name;
|
||||||
|
type = Type.REFERENCE(name);
|
||||||
this.cw = cw;
|
this.cw = cw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,14 @@ import java.util.List;
|
|||||||
|
|
||||||
public class CodeGenUtils {
|
public class CodeGenUtils {
|
||||||
|
|
||||||
public static String generateDescriptor(List<TypedParameter> arguments, Type returnType) {
|
public static String generateDescriptor(List<Type> argTypes, Type returnType) {
|
||||||
if (returnType == null) {
|
if (returnType == null) {
|
||||||
returnType = Type.VOID;
|
returnType = Type.VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append('(');
|
builder.append('(');
|
||||||
arguments.forEach(type -> builder.append(type.getType().getDescriptor()));
|
argTypes.forEach(type -> builder.append(type.getDescriptor()));
|
||||||
builder.append(')');
|
builder.append(')');
|
||||||
builder.append(returnType.getDescriptor());
|
builder.append(returnType.getDescriptor());
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
|
@ -7,11 +7,12 @@ import org.objectweb.asm.Opcodes;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class MethodContext {
|
public class MethodContext {
|
||||||
private record LocalVariable(String name, int index, Type type) {
|
public record LocalVariable(String name, int index, Type type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Label startLabel;
|
private Label startLabel;
|
||||||
@ -28,7 +29,7 @@ public class MethodContext {
|
|||||||
endLabel = new Label();
|
endLabel = new Label();
|
||||||
this.mv = mv;
|
this.mv = mv;
|
||||||
this.classContext = classContext;
|
this.classContext = classContext;
|
||||||
registerVariable("this", classContext.getName());
|
registerVariable("this", classContext.getType());
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitLabel(startLabel);
|
mv.visitLabel(startLabel);
|
||||||
}
|
}
|
||||||
@ -39,12 +40,9 @@ public class MethodContext {
|
|||||||
variableIndex.put(name, new LocalVariable(name, index, type));
|
variableIndex.put(name, new LocalVariable(name, index, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVariableIndex(String name) {
|
public Optional<LocalVariable> getLocalVar(String name) {
|
||||||
int index = variableIndex.get(name).index;
|
LocalVariable index = variableIndex.get(name);
|
||||||
if (index == -1) {
|
return Optional.ofNullable(index);
|
||||||
throw new RuntimeException("Variable not declared");
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushStack(String varName) {
|
public void pushStack(String varName) {
|
||||||
@ -58,6 +56,22 @@ public class MethodContext {
|
|||||||
} else {
|
} else {
|
||||||
mv.visitVarInsn(Opcodes.ILOAD, localVariable.index);
|
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() {
|
public void popStack() {
|
||||||
@ -66,6 +80,7 @@ public class MethodContext {
|
|||||||
|
|
||||||
public void wrapUp() {
|
public void wrapUp() {
|
||||||
mv.visitLabel(endLabel);
|
mv.visitLabel(endLabel);
|
||||||
|
System.out.println("maxStack: " + maxStack + " localVarIndex: " + localVarIndex);
|
||||||
mv.visitMaxs(maxStack, localVarIndex);
|
mv.visitMaxs(maxStack, localVarIndex);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
@ -25,31 +25,13 @@ public class TypedAssignment implements TypedStatement {
|
|||||||
public void convertToTypedAssignment(TypedProgram typedProgram, Assignment untyped) {
|
public void convertToTypedAssignment(TypedProgram typedProgram, Assignment untyped) {
|
||||||
value = convertExpression(typedProgram, untyped.value());
|
value = convertExpression(typedProgram, untyped.value());
|
||||||
location = new TypedFieldVarAccess(typedProgram, untyped.location());
|
location = new TypedFieldVarAccess(typedProgram, untyped.location());
|
||||||
|
location.typeCheck(typedProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(TypedProgram typedProgram) {
|
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);
|
Type typeRight = value.typeCheck(typedProgram);
|
||||||
|
|
||||||
if (typeLeft.equals(typeRight)) {
|
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");
|
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
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
if (value instanceof TypedIntLiteral) {
|
if(value instanceof TypedNew) {
|
||||||
ctx.getMv().visitIntInsn(Opcodes.BIPUSH, ((TypedIntLiteral) value).getValue());
|
value.codeGen(ctx);
|
||||||
ctx.getMv().visitVarInsn(Opcodes.ISTORE, ctx.getLocalVarIndex());
|
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.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
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;
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@ -67,6 +72,139 @@ public class TypedBinary implements TypedExpression {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ public class TypedBlock implements TypedNode {
|
|||||||
|
|
||||||
public void codeGen(MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
for (TypedLocalVariable var : vars) {
|
for (TypedLocalVariable var : vars) {
|
||||||
//var.codeGen(ctx);
|
ctx.registerVariable(var.getName(), var.getType());
|
||||||
}
|
}
|
||||||
for (TypedStatement stmt : stmts) {
|
for (TypedStatement stmt : stmts) {
|
||||||
stmt.codeGen(ctx);
|
stmt.codeGen(ctx);
|
||||||
|
@ -4,12 +4,14 @@ import de.maishai.ast.records.BoolLiteral;
|
|||||||
import de.maishai.typedast.MethodContext;
|
import de.maishai.typedast.MethodContext;
|
||||||
import de.maishai.typedast.TypedExpression;
|
import de.maishai.typedast.TypedExpression;
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class TypedBoolLiteral implements TypedExpression {
|
public class TypedBoolLiteral implements TypedExpression {
|
||||||
|
|
||||||
private Boolean value;
|
private Boolean value;
|
||||||
@ -37,5 +39,6 @@ public class TypedBoolLiteral implements TypedExpression {
|
|||||||
} else {
|
} else {
|
||||||
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
ctx.getMv().visitInsn(Opcodes.ICONST_0);
|
||||||
}
|
}
|
||||||
|
ctx.pushInstantToStack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,6 @@ import lombok.Data;
|
|||||||
public class TypedBreak implements TypedStatement {
|
public class TypedBreak implements TypedStatement {
|
||||||
private Type type = Type.VOID;
|
private Type type = Type.VOID;
|
||||||
|
|
||||||
public TypedBreak convertToTypedBreak(TypedClass clas, Break unTypedBreak) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(TypedProgram typedProgram) {
|
public Type typeCheck(TypedProgram typedProgram) {
|
||||||
return type;
|
return type;
|
||||||
|
@ -4,9 +4,11 @@ import de.maishai.ast.records.CharLiteral;
|
|||||||
import de.maishai.typedast.MethodContext;
|
import de.maishai.typedast.MethodContext;
|
||||||
import de.maishai.typedast.TypedExpression;
|
import de.maishai.typedast.TypedExpression;
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
public class TypedCharLiteral implements TypedExpression {
|
public class TypedCharLiteral implements TypedExpression {
|
||||||
private char value;
|
private char value;
|
||||||
private Type type;
|
private Type type;
|
||||||
@ -29,5 +31,6 @@ public class TypedCharLiteral implements TypedExpression {
|
|||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
ctx.getMv().visitLdcInsn(value);
|
ctx.getMv().visitLdcInsn(value);
|
||||||
|
ctx.pushInstantToStack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,13 +28,11 @@ public class TypedClass implements TypedNode {
|
|||||||
private TypedConstructor currentConstructor;
|
private TypedConstructor currentConstructor;
|
||||||
private Type type;
|
private Type type;
|
||||||
|
|
||||||
public TypedClass(TypedProgram typedProgram, Class c) {
|
public TypedClass(Class c) {
|
||||||
className = c.classname();
|
className = c.classname();
|
||||||
type = Type.REFERENCE(className);
|
type = Type.REFERENCE(className);
|
||||||
convertMethodsAndConstructorsAndFields(typedProgram, c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isParameterNameInCurrentConstructor(String parameterName) {
|
public boolean isParameterNameInCurrentConstructor(String parameterName) {
|
||||||
if (currentConstructor == null) {
|
if (currentConstructor == null) {
|
||||||
return false;
|
return false;
|
||||||
@ -119,6 +117,24 @@ public class TypedClass implements TypedNode {
|
|||||||
return null;
|
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) {
|
public Type getParameterTypeInCurrentConstructor(String parameterName) {
|
||||||
for (TypedParameter p : currentConstructor.getTypedParameters()) {
|
for (TypedParameter p : currentConstructor.getTypedParameters()) {
|
||||||
if (p.getParaName().equals(parameterName)) {
|
if (p.getParaName().equals(parameterName)) {
|
||||||
|
@ -53,11 +53,20 @@ public class TypedConstructor implements TypedNode {
|
|||||||
name = unTypedConstructor.className();
|
name = unTypedConstructor.className();
|
||||||
|
|
||||||
for (Parameter param : unTypedConstructor.params()) {
|
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;
|
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) {
|
public void convertToBlock(TypedProgram typedProgram, Constructor unTypedConstructor) {
|
||||||
this.typedBlock = new TypedBlock(typedProgram, unTypedConstructor.block());
|
this.typedBlock = new TypedBlock(typedProgram, unTypedConstructor.block());
|
||||||
typeCheck(typedProgram);
|
typeCheck(typedProgram);
|
||||||
@ -76,12 +85,15 @@ public class TypedConstructor implements TypedNode {
|
|||||||
|
|
||||||
public void codeGen(ClassContext ctx) {
|
public void codeGen(ClassContext ctx) {
|
||||||
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
||||||
MethodVisitor mv = 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);
|
MethodContext mctx = new MethodContext(ctx, mv);
|
||||||
typedParameters.forEach(param -> mctx.registerVariable(param.getParaName(), param.getType()));
|
typedParameters.forEach(param -> mctx.registerVariable(param.getParaName(), param.getType()));
|
||||||
//super();
|
//super();
|
||||||
mctx.pushStack("this");
|
mctx.pushStack("this");
|
||||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
System.out.println("INVOKESPECIAL: " + "java/lang/Object" + " " + "<init>" + " " + "()V");
|
||||||
|
mctx.popStack();
|
||||||
|
|
||||||
typedBlock.codeGen(mctx);
|
typedBlock.codeGen(mctx);
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import lombok.NoArgsConstructor;
|
|||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import static de.maishai.typedast.Type.Kind.REFERENCE;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ -30,27 +29,17 @@ public final class TypedDeclaration implements TypedNode {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(TypedProgram typedProgram) {
|
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)) {
|
if (typedProgram.getCurrentClass().isThereField(name)) {
|
||||||
throw new RuntimeException("Field " + name + " already declared");
|
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;
|
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) {
|
public void codeGen(ClassWriter cw) {
|
||||||
int access = Opcodes.ACC_PUBLIC; // laut Andi ist es ok, dass alle Felder public sind
|
int access = Opcodes.ACC_PUBLIC; // laut Andi ist es ok, dass alle Felder public sind
|
||||||
cw.visitField(access, name, type.getDescriptor(), null, null).visitEnd();
|
cw.visitField(access, name, type.getDescriptor(), null, null).visitEnd();
|
||||||
|
@ -7,6 +7,10 @@ import de.maishai.typedast.Type;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
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;
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@ -32,49 +36,88 @@ public class TypedFieldVarAccess implements TypedExpression {
|
|||||||
@Override
|
@Override
|
||||||
public Type typeCheck(TypedProgram typedProgram) {
|
public Type typeCheck(TypedProgram typedProgram) {
|
||||||
if (field) {
|
if (field) {
|
||||||
|
type = checkFieldOrMethodType(typedProgram);
|
||||||
|
return type;
|
||||||
|
} else {
|
||||||
|
type = checkVariableType(typedProgram);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type checkFieldOrMethodType(TypedProgram typedProgram) {
|
||||||
if (typedProgram.getCurrentClass().isThereField(name)) {
|
if (typedProgram.getCurrentClass().isThereField(name)) {
|
||||||
type = typedProgram.getCurrentClass().getFieldType(name);
|
type = typedProgram.getCurrentClass().getFieldType(name);
|
||||||
return 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 {
|
} else {
|
||||||
throw new RuntimeException("Field " + name + " not declared");
|
throw new RuntimeException("Field " + name + " not declared");
|
||||||
}
|
}
|
||||||
} 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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Type checkVariableType(TypedProgram typedProgram) {
|
||||||
|
if (typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||||
|
return checkConstructorVariableType(typedProgram);
|
||||||
} else if (typedProgram.getCurrentClass().isCurrentMethodPresent()) {
|
} else if (typedProgram.getCurrentClass().isCurrentMethodPresent()) {
|
||||||
if (typedProgram.getCurrentClass().isParameterWitNameInMethod(name)) {
|
return checkMethodVariableType(typedProgram);
|
||||||
type = typedProgram.getCurrentClass().getParameterTypeInCurrentMethod(name);
|
} else {
|
||||||
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");
|
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
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
@ -11,6 +12,7 @@ import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class TypedIfElse implements TypedStatement {
|
public class TypedIfElse implements TypedStatement {
|
||||||
private TypedExpression typedCon;
|
private TypedExpression typedCon;
|
||||||
private TypedBlock ifTypedBlock;
|
private TypedBlock ifTypedBlock;
|
||||||
|
@ -7,6 +7,10 @@ import de.maishai.typedast.Type;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ -37,6 +41,16 @@ public class TypedIntLiteral implements TypedExpression {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
|
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);
|
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.ast.records.Method;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
@ -12,6 +13,7 @@ import java.util.List;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class TypedMethod implements TypedNode {
|
public class TypedMethod implements TypedNode {
|
||||||
private String name;
|
private String name;
|
||||||
private Type returnType;
|
private Type returnType;
|
||||||
@ -28,7 +30,10 @@ public class TypedMethod implements TypedNode {
|
|||||||
name = unTypedMethod.methodName();
|
name = unTypedMethod.methodName();
|
||||||
returnType = unTypedMethod.type();
|
returnType = unTypedMethod.type();
|
||||||
for (var parameter : unTypedMethod.params()) {
|
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(
|
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) {
|
public void convertToTypedBlock(TypedProgram typedProgram, Method unTypedMethod) {
|
||||||
typedBlock = new TypedBlock(typedProgram, unTypedMethod.block());
|
typedBlock = new TypedBlock(typedProgram, unTypedMethod.block());
|
||||||
typeCheck(typedProgram);
|
typeCheck(typedProgram);
|
||||||
@ -109,7 +120,7 @@ public class TypedMethod implements TypedNode {
|
|||||||
public void codeGen(ClassContext ctx) {
|
public void codeGen(ClassContext ctx) {
|
||||||
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
||||||
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, name,
|
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);
|
MethodContext context = new MethodContext(ctx, mv);
|
||||||
typedParameters.forEach(param -> context.registerVariable(param.getParaName(), param.getType()));
|
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.Expression;
|
||||||
import de.maishai.ast.records.MethodCall;
|
import de.maishai.ast.records.MethodCall;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
//TODO: test this after fixing error from parser
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class TypedMethodCall implements TypedExpression, TypedStatement {
|
public class TypedMethodCall implements TypedExpression, TypedStatement {
|
||||||
private TypedFieldVarAccess recipient;
|
private TypedFieldVarAccess recipient;
|
||||||
private List<TypedExpression> args = new ArrayList<>();
|
private List<TypedExpression> args = new ArrayList<>();
|
||||||
@ -26,6 +28,7 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
|
|||||||
|
|
||||||
public void convertToTypedMethodCall(TypedProgram typedProgram, MethodCall unTypedMethodCall) {
|
public void convertToTypedMethodCall(TypedProgram typedProgram, MethodCall unTypedMethodCall) {
|
||||||
recipient = new TypedFieldVarAccess(typedProgram, unTypedMethodCall.recipient());
|
recipient = new TypedFieldVarAccess(typedProgram, unTypedMethodCall.recipient());
|
||||||
|
recipient.typeCheck(typedProgram);
|
||||||
for (Expression arg : unTypedMethodCall.args()) {
|
for (Expression arg : unTypedMethodCall.args()) {
|
||||||
args.add(convertExpression(typedProgram, arg));
|
args.add(convertExpression(typedProgram, arg));
|
||||||
}
|
}
|
||||||
@ -33,31 +36,52 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(TypedProgram typedProgram) {
|
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()
|
if (!typedProgram.getCurrentClass().getClassName().equals(ownerChainName) && ownerChainName != null) {
|
||||||
.filter(method -> method.getName().equals(recipient.getName()))
|
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();
|
.toList();
|
||||||
|
|
||||||
for (TypedMethod method : methods) {
|
for (TypedMethod method : methods) {
|
||||||
if (method.getTypedParameters().size() == args.size()) {
|
if (method.getTypedParameters().size() == args.size()) {
|
||||||
boolean allMatch = true;
|
boolean allMatch = true;
|
||||||
for (int i = 0; i < args.size(); i++) {
|
for (int i = 0; i < args.size(); i++) {
|
||||||
if (!args.get(i).typeCheck(typedProgram).equals(method.getTypedParameters().get(i).getType())) {
|
if (!args.get(i).getType().equals(method.getTypedParameters().get(i).getType())) {
|
||||||
allMatch = false;
|
allMatch = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (allMatch) {
|
if (allMatch) {
|
||||||
type = method.getReturnType();
|
return Optional.of(method.getReturnType());
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
throw new RuntimeException("Method not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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.Expression;
|
||||||
import de.maishai.ast.records.New;
|
import de.maishai.ast.records.New;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -11,6 +14,7 @@ import java.util.List;
|
|||||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
public class TypedNew implements TypedExpression, TypedStatement {
|
public class TypedNew implements TypedExpression, TypedStatement {
|
||||||
private Type type;
|
private Type type;
|
||||||
private List<TypedExpression> args = new ArrayList<>();
|
private List<TypedExpression> args = new ArrayList<>();
|
||||||
@ -28,6 +32,11 @@ public class TypedNew implements TypedExpression, TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(TypedProgram typedProgram) {
|
public Type typeCheck(TypedProgram typedProgram) {
|
||||||
|
|
||||||
|
if (typedProgram.isTypedClassPresent(type.getReference())) {
|
||||||
|
return Type.REFERENCE(type.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
for (var constructor : typedProgram.getCurrentClass().getTypedConstructors()) {
|
for (var constructor : typedProgram.getCurrentClass().getTypedConstructors()) {
|
||||||
if (constructor.getTypedParameters().size() == args.size()) {
|
if (constructor.getTypedParameters().size() == args.size()) {
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
@ -48,6 +57,21 @@ public class TypedNew implements TypedExpression, TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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,14 +19,21 @@ public class TypedProgram {
|
|||||||
|
|
||||||
public void startConversion(Program program) {
|
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;
|
int k = 0;
|
||||||
for (var clas : program.classes()) {
|
for (var clas : program.classes()) {
|
||||||
enterCurrentClass(typedClasses.get(k));
|
enterCurrentClass(typedClasses.get(k));
|
||||||
typedClasses.add(new TypedClass(this, clas));
|
typedClasses.get(k).convertMethodsAndConstructorsAndFields(this, clas);
|
||||||
exitCurrentClass();
|
exitCurrentClass();
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Konvertiere die Blöcke der Konstruktoren und Methoden von den jeweiligen Klassen
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (var clas : program.classes()) {
|
for (var clas : program.classes()) {
|
||||||
enterCurrentClass(typedClasses.get(i));
|
enterCurrentClass(typedClasses.get(i));
|
||||||
@ -40,8 +47,8 @@ public class TypedProgram {
|
|||||||
return typedClasses.stream().filter(clas -> clas.getClassName().equals(className)).findFirst().get();
|
return typedClasses.stream().filter(clas -> clas.getClassName().equals(className)).findFirst().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCurrentClassPresent() {
|
public boolean isTypedClassPresent(String className) {
|
||||||
return currentClass != null;
|
return typedClasses.stream().anyMatch(clas -> clas.getClassName().equals(className));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enterCurrentClass(TypedClass clas) {
|
public void enterCurrentClass(TypedClass clas) {
|
||||||
@ -52,4 +59,18 @@ public class TypedProgram {
|
|||||||
currentClass = null;
|
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.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@ -11,6 +12,7 @@ import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class TypedReturn implements TypedStatement {
|
public class TypedReturn implements TypedStatement {
|
||||||
private TypedExpression ret;
|
private TypedExpression ret;
|
||||||
private Type type;
|
private Type type;
|
||||||
@ -48,6 +50,7 @@ public class TypedReturn implements TypedStatement {
|
|||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
ctx.getMv().visitInsn(Opcodes.RETURN);
|
ctx.getMv().visitInsn(Opcodes.RETURN);
|
||||||
} else {
|
} else {
|
||||||
|
System.out.println("return: " + ret);
|
||||||
ret.codeGen(ctx);
|
ret.codeGen(ctx);
|
||||||
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
|
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
|
||||||
ctx.getMv().visitInsn(Opcodes.IRETURN);
|
ctx.getMv().visitInsn(Opcodes.IRETURN);
|
||||||
|
@ -165,7 +165,6 @@ public class AbstractSyntax_ClassWithConstructor {
|
|||||||
localVariables,
|
localVariables,
|
||||||
statementList
|
statementList
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Constructor(
|
return new Constructor(
|
||||||
"ClassWithConstructor",
|
"ClassWithConstructor",
|
||||||
parameters,
|
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;
|
int y;
|
||||||
ComplexClass b;
|
ComplexClass b;
|
||||||
ComplexClass c;
|
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() {
|
public ComplexClass() {
|
||||||
this.x = 10;
|
this.y = 10;
|
||||||
|
this.x = 2;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < (x + 1); i = i + 1) {
|
for (i = 0; i < (this.y + 1); i = i + 1) {
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; j < this.x; j += 1) {
|
for (j = 0; j < this.y; j += 1) {
|
||||||
this.x = this.x * this.x;
|
this.x = this.x * this.x;
|
||||||
|
if (this.x == 100) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
this.y = 2;
|
||||||
do {
|
do {
|
||||||
this.y = this.y + 1;
|
this.y = this.y + 1;
|
||||||
} while (this.y < 10);
|
} while (this.y < 10);
|
||||||
@ -50,12 +27,44 @@ public class ComplexClass {
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (k = 0; k < 10; k = k + 1) {
|
for (k = 0; k < 10; k = k + 1) {
|
||||||
if (k == 5) {
|
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) {
|
public ComplexClass(int x, int y, char z) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
@ -66,16 +75,15 @@ public class ComplexClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ComplexClass getC() {
|
public ComplexClass getC() {
|
||||||
return c;
|
return this.c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getX() {
|
public int getX() {
|
||||||
return x;
|
return this.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean methodCall() {
|
public boolean methodCall() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,10 @@ public class TypedAbstractSyntax_ClassWithConstructor {
|
|||||||
getConstructors(),
|
getConstructors(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
Type.REFERENCE("ClassWithField")
|
Type.REFERENCE("ClassWithConstructor")
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,20 +204,20 @@ public class TypedAbstractSyntax_ClassWithConstructor {
|
|||||||
Type.INT
|
Type.INT
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Type.INT
|
Type.VOID
|
||||||
),
|
),
|
||||||
Type.INT
|
Type.VOID
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Type.INT
|
Type.VOID
|
||||||
),
|
),
|
||||||
Type.INT
|
Type.VOID
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
TypedBlock typedBlock = new TypedBlock(
|
TypedBlock typedBlock = new TypedBlock(
|
||||||
typedLocalVariables,
|
typedLocalVariables,
|
||||||
typedStatementList,
|
typedStatementList,
|
||||||
Type.INT
|
Type.VOID
|
||||||
);
|
);
|
||||||
|
|
||||||
return new TypedConstructor(
|
return new TypedConstructor(
|
||||||
|
@ -38,7 +38,8 @@ public class TypedAbstractSyntax_ClassWithField {
|
|||||||
null,
|
null,
|
||||||
Type.REFERENCE("ClassWithField")
|
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,
|
null,
|
||||||
Type.REFERENCE("PublicClass")
|
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
|
@Test
|
||||||
public void testComplexClass() {
|
public void testComplexClass() {
|
||||||
Program resultAst = Compiler.generateASTFromFile(List.of("src/main/resources/JavaTestfiles/ComplexClass.java"));
|
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());
|
TypedProgram resultTypedAst = Compiler.generateTypedASTFromAst(AbstractSyntax_ClassWithConstructor.get());
|
||||||
assertEquals(TypedAbstractSyntax_ClassWithConstructor.get(), resultTypedAst);
|
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