mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-27 08:38:03 +00:00
Doing typeCheck for multi classes
This commit is contained in:
parent
fdac5aa346
commit
aaa8a27ff9
@ -99,7 +99,8 @@ public class Compiler {
|
||||
|
||||
public static void main(String[] args) {
|
||||
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java",
|
||||
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java"),
|
||||
List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall"));
|
||||
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java",
|
||||
"src/main/resources/JavaTestfiles/ComplexClass.java"),
|
||||
List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall","ComplexClass"));
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
|
||||
DecafParser.RecipientContext ctx = ctxList.get(lastElement);
|
||||
ctxList.remove(lastElement);
|
||||
if (ctx.id() != null) {
|
||||
return new FieldVarAccess(false, generateRecursiveOwnerChain(ctxList, recipient), ctx.id().IDENTIFIER().getText());
|
||||
return new FieldVarAccess(true, generateRecursiveOwnerChain(ctxList, recipient), ctx.id().IDENTIFIER().getText());
|
||||
}
|
||||
if (ctx.methName() != null) {
|
||||
List<Expression> args = new ArrayList<>();
|
||||
|
@ -34,7 +34,7 @@ public class TypedExpressionHelp {
|
||||
}
|
||||
else if (expression instanceof MethodCall methodCall) {
|
||||
TypedMethodCall typedMethodCall = new TypedMethodCall( typedProgram, methodCall);
|
||||
typedMethodCall.typeCheck( typedProgram);
|
||||
typedMethodCall.typeCheck(typedProgram);
|
||||
return typedMethodCall;
|
||||
}
|
||||
else if (expression instanceof New newStmt) {
|
||||
|
@ -31,20 +31,24 @@ public class TypedAssignment implements TypedStatement {
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
Type typeLeft = null;
|
||||
|
||||
if (typedProgram.getCurrentClass().isThereField(location.getName())) {
|
||||
if (typedProgram.getCurrentClass().isThereField(location.getName()) && location.getField()) {
|
||||
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 {
|
||||
} else if(typedProgram.getCurrentClass().isThereField(location.getName())){
|
||||
typeLeft = typedProgram.getCurrentClass().getFieldType(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 {
|
||||
}else if(typedProgram.getCurrentClass().isThereField(location.getName())){
|
||||
typeLeft = typedProgram.getCurrentClass().getFieldType(location.getName());
|
||||
}else {
|
||||
throw new RuntimeException("Variable " + location.getName() + " not declared in constructor");
|
||||
}
|
||||
}
|
||||
|
@ -28,13 +28,11 @@ public class TypedClass implements TypedNode {
|
||||
private TypedConstructor currentConstructor;
|
||||
private Type type;
|
||||
|
||||
public TypedClass(TypedProgram typedProgram, Class c) {
|
||||
public TypedClass(Class c) {
|
||||
className = c.classname();
|
||||
type = Type.REFERENCE(className);
|
||||
convertMethodsAndConstructorsAndFields(typedProgram, c);
|
||||
}
|
||||
|
||||
|
||||
public boolean isParameterNameInCurrentConstructor(String parameterName) {
|
||||
if (currentConstructor == null) {
|
||||
return false;
|
||||
@ -47,7 +45,7 @@ public class TypedClass implements TypedNode {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void convertMethodsAndConstructorsAndFields(TypedProgram typedProgram, Class c){
|
||||
public void convertMethodsAndConstructorsAndFields(TypedProgram typedProgram, Class c) {
|
||||
// Am Anfang werden die Attribute, die Konstruktoren und Methoden in die jeweilige Liste eingefügt.
|
||||
// damit die Methoden verwendet werden können, bevor deren Blöcke ausgeführt werden
|
||||
for (Declaration declaration : c.fieldDeclarations()) {
|
||||
@ -62,7 +60,7 @@ public class TypedClass implements TypedNode {
|
||||
}
|
||||
}
|
||||
|
||||
public void covertBlocksOfConstructorsAndMethods(TypedProgram typedProgram, Class c){
|
||||
public void covertBlocksOfConstructorsAndMethods(TypedProgram typedProgram, Class c) {
|
||||
// Hier werden die Blöcke der Konstruktoren ausgeführt
|
||||
int i = 0;
|
||||
for (Constructor constructor : c.constructors()) {
|
||||
|
@ -53,11 +53,19 @@ public class TypedConstructor implements TypedNode {
|
||||
name = unTypedConstructor.className();
|
||||
|
||||
for (Parameter param : unTypedConstructor.params()) {
|
||||
typedParameters.add(new TypedParameter(typedProgram, param));
|
||||
TypedParameter typedParameter = new TypedParameter(typedProgram, param);
|
||||
checkIfParameterExists(typedParameter.getParaName());
|
||||
typedParameters.add(typedParameter);
|
||||
localVariables.add(new TypedLocalVariable(typedParameter.getParaName(), typedParameter.getType()));
|
||||
}
|
||||
type = Type.VOID;
|
||||
}
|
||||
|
||||
public void checkIfParameterExists(String paraName) {
|
||||
if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(paraName))) {
|
||||
throw new RuntimeException("Parameter " + paraName + " already exists");
|
||||
}
|
||||
}
|
||||
public void convertToBlock(TypedProgram typedProgram, Constructor unTypedConstructor) {
|
||||
this.typedBlock = new TypedBlock(typedProgram, unTypedConstructor.block());
|
||||
typeCheck(typedProgram);
|
||||
|
@ -9,7 +9,6 @@ import lombok.NoArgsConstructor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import static de.maishai.typedast.Type.Kind.REFERENCE;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@ -30,27 +29,20 @@ public final class TypedDeclaration implements TypedNode {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
if(type.getReference() != null && !typedProgram.getCurrentClass().getClassName().equals(type.getReference())) {
|
||||
if (!typedProgram.isTypedClassPresent(type.getReference())) {
|
||||
throw new RuntimeException("Type " + type.getReference() + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
if (typedProgram.getCurrentClass().isThereField(name)) {
|
||||
throw new RuntimeException("Field " + name + " already declared");
|
||||
}
|
||||
|
||||
if (type.getKind() == REFERENCE) {
|
||||
if (!type.getReference().equals(typedProgram.getCurrentClass().getClassName())) {
|
||||
throw new RuntimeException("Field " + name + " has wrong type");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
public void codeGen(MethodVisitor mv, MethodContext ctx) {
|
||||
System.out.println("Generating code for local variable " + name);
|
||||
int index = ctx.addVariable(name);
|
||||
mv.visitLocalVariable(name, type.getDescriptor(), null, ctx.getStartLabel(), ctx.getEndLabel(), index);
|
||||
}
|
||||
*/
|
||||
public void codeGen(ClassWriter cw) {
|
||||
int access = Opcodes.ACC_PUBLIC; // laut Andi ist es ok, dass alle Felder public sind
|
||||
cw.visitField(access, name, type.getDescriptor(), null, null).visitEnd();
|
||||
|
@ -34,7 +34,10 @@ public class TypedFieldVarAccess implements TypedExpression {
|
||||
if (field) {
|
||||
if (typedProgram.getCurrentClass().isThereField(name)) {
|
||||
type = typedProgram.getCurrentClass().getFieldType(name);
|
||||
return typedProgram.getCurrentClass().getFieldType(name);
|
||||
return type;
|
||||
}else if(recursiveOwnerChain instanceof TypedFieldVarAccess typedFieldVarAccess){
|
||||
type = typedProgram.getCurrentClass().getFieldType(typedFieldVarAccess.getName());
|
||||
return type;
|
||||
}else{
|
||||
throw new RuntimeException("Field " + name + " not declared ");
|
||||
}
|
||||
|
@ -28,7 +28,10 @@ public class TypedMethod implements TypedNode {
|
||||
name = unTypedMethod.methodName();
|
||||
returnType = unTypedMethod.type();
|
||||
for (var parameter : unTypedMethod.params()) {
|
||||
typedParameters.add(new TypedParameter(typedProgram, parameter));
|
||||
TypedParameter typedParameter = new TypedParameter(typedProgram, parameter);
|
||||
checkIfParameterExists(typedParameter.getParaName());
|
||||
typedParameters.add(typedParameter);
|
||||
localVariables.add(new TypedLocalVariable(typedParameter.getParaName(), typedParameter.getType()));
|
||||
}
|
||||
|
||||
typedProgram.getCurrentClass().getTypedMethods().stream().filter(method -> method.equals(this)).findFirst().ifPresentOrElse(
|
||||
@ -37,6 +40,11 @@ public class TypedMethod implements TypedNode {
|
||||
}, () -> {
|
||||
});
|
||||
}
|
||||
public void checkIfParameterExists(String parameterName) {
|
||||
if (typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(parameterName))) {
|
||||
throw new RuntimeException("Parameter " + parameterName + " already exists");
|
||||
}
|
||||
}
|
||||
|
||||
public void convertToTypedBlock(TypedProgram typedProgram, Method unTypedMethod) {
|
||||
typedBlock = new TypedBlock(typedProgram, unTypedMethod.block());
|
||||
|
@ -8,10 +8,10 @@ import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||
|
||||
//TODO: test this after fixing error from parser
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@ -26,38 +26,60 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
|
||||
|
||||
public void convertToTypedMethodCall(TypedProgram typedProgram, MethodCall unTypedMethodCall) {
|
||||
recipient = new TypedFieldVarAccess(typedProgram, unTypedMethodCall.recipient());
|
||||
for (Expression arg : unTypedMethodCall.args()) {
|
||||
args.add(convertExpression(typedProgram, arg));
|
||||
}
|
||||
recipient.typeCheck(typedProgram);
|
||||
for (Expression arg : unTypedMethodCall.args()) {
|
||||
args.add(convertExpression(typedProgram, arg));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
if (typedProgram.getCurrentClass().isCurrentMethodPresent() || typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||
String ownerChainName = null;
|
||||
if (recipient.getRecursiveOwnerChain() != null) {
|
||||
ownerChainName = recipient.getRecursiveOwnerChain().getType().getReference();
|
||||
}
|
||||
|
||||
List<TypedMethod> methods = typedProgram.getCurrentClass().getTypedMethods().stream()
|
||||
.filter(method -> method.getName().equals(recipient.getName()))
|
||||
.toList();
|
||||
|
||||
for (TypedMethod method : methods) {
|
||||
if (method.getTypedParameters().size() == args.size()) {
|
||||
boolean allMatch = true;
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
if (!args.get(i).typeCheck(typedProgram).equals(method.getTypedParameters().get(i).getType())) {
|
||||
allMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allMatch) {
|
||||
type = method.getReturnType();
|
||||
return type;
|
||||
}
|
||||
}
|
||||
if (!typedProgram.getCurrentClass().getClassName().equals(ownerChainName) && ownerChainName != null) {
|
||||
Optional<Type> matchingMethod = findMatchingMethod(typedProgram.getTypedClass(ownerChainName), recipient.getName());
|
||||
if (matchingMethod.isPresent()) {
|
||||
type = matchingMethod.get();
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
if (typedProgram.getCurrentClass().isCurrentMethodPresent() || typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||
Optional<Type> matchingMethod = findMatchingMethod(typedProgram.getCurrentClass(), recipient.getName());
|
||||
if (matchingMethod.isPresent()) {
|
||||
type = matchingMethod.get();
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Method not found");
|
||||
}
|
||||
|
||||
public Optional<Type> findMatchingMethod(TypedClass ownerChain, String methodName) {
|
||||
List<TypedMethod> methods = ownerChain.getTypedMethods().stream()
|
||||
.filter(method -> method.getName().equals(methodName))
|
||||
.toList();
|
||||
|
||||
for (TypedMethod method : methods) {
|
||||
if (method.getTypedParameters().size() == args.size()) {
|
||||
boolean allMatch = true;
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
if (!args.get(i).getType().equals(method.getTypedParameters().get(i).getType())) {
|
||||
allMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allMatch) {
|
||||
return Optional.of(method.getReturnType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodContext ctx) {
|
||||
|
@ -28,6 +28,11 @@ public class TypedNew implements TypedExpression, TypedStatement {
|
||||
|
||||
@Override
|
||||
public Type typeCheck(TypedProgram typedProgram) {
|
||||
|
||||
if(typedProgram.isTypedClassPresent(type.getReference())){
|
||||
return Type.REFERENCE(type.getReference());
|
||||
}
|
||||
|
||||
for (var constructor : typedProgram.getCurrentClass().getTypedConstructors()) {
|
||||
if (constructor.getTypedParameters().size() == args.size()) {
|
||||
boolean valid = true;
|
||||
|
@ -19,10 +19,14 @@ public class TypedProgram {
|
||||
|
||||
public void startConversion(Program program) {
|
||||
|
||||
for(var clas : program.classes()){
|
||||
typedClasses.add(new TypedClass(clas));
|
||||
}
|
||||
|
||||
int k = 0;
|
||||
for (var clas : program.classes()) {
|
||||
enterCurrentClass(typedClasses.get(k));
|
||||
typedClasses.add(new TypedClass(this, clas));
|
||||
typedClasses.get(k).convertMethodsAndConstructorsAndFields(this, clas);
|
||||
exitCurrentClass();
|
||||
k++;
|
||||
}
|
||||
@ -39,9 +43,8 @@ public class TypedProgram {
|
||||
public TypedClass getTypedClass(String className) {
|
||||
return typedClasses.stream().filter(clas -> clas.getClassName().equals(className)).findFirst().get();
|
||||
}
|
||||
|
||||
public boolean isCurrentClassPresent() {
|
||||
return currentClass != null;
|
||||
public boolean isTypedClassPresent(String className) {
|
||||
return typedClasses.stream().anyMatch(clas -> clas.getClassName().equals(className));
|
||||
}
|
||||
|
||||
public void enterCurrentClass(TypedClass clas) {
|
||||
|
Loading…
Reference in New Issue
Block a user