mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-28 16:28:04 +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) {
|
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"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,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<>();
|
||||||
|
@ -31,12 +31,14 @@ public class TypedAssignment implements TypedStatement {
|
|||||||
public Type typeCheck(TypedProgram typedProgram) {
|
public Type typeCheck(TypedProgram typedProgram) {
|
||||||
Type typeLeft = null;
|
Type typeLeft = null;
|
||||||
|
|
||||||
if (typedProgram.getCurrentClass().isThereField(location.getName())) {
|
if (typedProgram.getCurrentClass().isThereField(location.getName()) && location.getField()) {
|
||||||
typeLeft = typedProgram.getCurrentClass().getFieldType(location.getName());
|
typeLeft = typedProgram.getCurrentClass().getFieldType(location.getName());
|
||||||
} else {
|
} else {
|
||||||
if (typedProgram.getCurrentClass().isCurrentMethodPresent() && !typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
if (typedProgram.getCurrentClass().isCurrentMethodPresent() && !typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||||
if (typedProgram.getCurrentClass().getCurrentMethod().isLocalVariableInMethod(location.getName())) {
|
if (typedProgram.getCurrentClass().getCurrentMethod().isLocalVariableInMethod(location.getName())) {
|
||||||
typeLeft = typedProgram.getCurrentClass().getCurrentMethod().getLocalVariableType(location.getName());
|
typeLeft = typedProgram.getCurrentClass().getCurrentMethod().getLocalVariableType(location.getName());
|
||||||
|
} else if(typedProgram.getCurrentClass().isThereField(location.getName())){
|
||||||
|
typeLeft = typedProgram.getCurrentClass().getFieldType(location.getName());
|
||||||
}else {
|
}else {
|
||||||
throw new RuntimeException("Variable " + location.getName() + " not declared in method");
|
throw new RuntimeException("Variable " + location.getName() + " not declared in method");
|
||||||
}
|
}
|
||||||
@ -44,6 +46,8 @@ public class TypedAssignment implements TypedStatement {
|
|||||||
if (!typedProgram.getCurrentClass().isCurrentMethodPresent() && typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
if (!typedProgram.getCurrentClass().isCurrentMethodPresent() && typedProgram.getCurrentClass().isCurrentConstructorPresent()) {
|
||||||
if (typedProgram.getCurrentClass().getCurrentConstructor().isLocalVariableInConstructor(location.getName())) {
|
if (typedProgram.getCurrentClass().getCurrentConstructor().isLocalVariableInConstructor(location.getName())) {
|
||||||
typeLeft = typedProgram.getCurrentClass().getCurrentConstructor().getLocalVariableType(location.getName());
|
typeLeft = typedProgram.getCurrentClass().getCurrentConstructor().getLocalVariableType(location.getName());
|
||||||
|
}else if(typedProgram.getCurrentClass().isThereField(location.getName())){
|
||||||
|
typeLeft = typedProgram.getCurrentClass().getFieldType(location.getName());
|
||||||
}else {
|
}else {
|
||||||
throw new RuntimeException("Variable " + location.getName() + " not declared in constructor");
|
throw new RuntimeException("Variable " + location.getName() + " not declared in constructor");
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -53,11 +53,19 @@ 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);
|
||||||
|
@ -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,20 @@ 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();
|
||||||
|
@ -34,7 +34,10 @@ public class TypedFieldVarAccess implements TypedExpression {
|
|||||||
if (field) {
|
if (field) {
|
||||||
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(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 ");
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,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(
|
||||||
@ -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) {
|
public void convertToTypedBlock(TypedProgram typedProgram, Method unTypedMethod) {
|
||||||
typedBlock = new TypedBlock(typedProgram, unTypedMethod.block());
|
typedBlock = new TypedBlock(typedProgram, unTypedMethod.block());
|
||||||
|
@ -8,10 +8,10 @@ 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
|
||||||
@ -26,6 +26,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 +34,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) {
|
||||||
|
@ -28,6 +28,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;
|
||||||
|
@ -19,10 +19,14 @@ public class TypedProgram {
|
|||||||
|
|
||||||
public void startConversion(Program program) {
|
public void startConversion(Program program) {
|
||||||
|
|
||||||
|
for(var clas : program.classes()){
|
||||||
|
typedClasses.add(new TypedClass(clas));
|
||||||
|
}
|
||||||
|
|
||||||
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++;
|
||||||
}
|
}
|
||||||
@ -39,9 +43,8 @@ public class TypedProgram {
|
|||||||
public TypedClass getTypedClass(String className) {
|
public TypedClass getTypedClass(String className) {
|
||||||
return typedClasses.stream().filter(clas -> clas.getClassName().equals(className)).findFirst().get();
|
return typedClasses.stream().filter(clas -> clas.getClassName().equals(className)).findFirst().get();
|
||||||
}
|
}
|
||||||
|
public boolean isTypedClassPresent(String className) {
|
||||||
public boolean isCurrentClassPresent() {
|
return typedClasses.stream().anyMatch(clas -> clas.getClassName().equals(className));
|
||||||
return currentClass != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enterCurrentClass(TypedClass clas) {
|
public void enterCurrentClass(TypedClass clas) {
|
||||||
|
Loading…
Reference in New Issue
Block a user