diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedAssignment.java b/src/main/java/de/maishai/typedast/typedclass/TypedAssignment.java index 6960010..fed0d27 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedAssignment.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedAssignment.java @@ -18,7 +18,7 @@ import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression; public class TypedAssignment implements TypedStatement { private String varName; private TypedExpression value; - // private TypedExpression recursiveOwnerChain; + // private TypedExpression recursiveOwnerChain; private Type type; public TypedAssignment(Map localVar, TypedClass clas, Assignment untyped) { @@ -28,25 +28,30 @@ public class TypedAssignment implements TypedStatement { public void convertToTypedAssignment(Map localVar, TypedClass clas, Assignment untyped) { varName = untyped.location().id(); value = convertExpression(localVar, clas, untyped.value()); - // recursiveOwnerChain = convertExpression(localVar, clas, untyped.location().recursiveOwnerChain()); + // recursiveOwnerChain = convertExpression(localVar, clas, untyped.location().recursiveOwnerChain()); } @Override public Type typeCheck(Map localVar, TypedClass clas) { Type typeLeft = null; - if (!localVar.containsKey(varName)) { - if (clas.isThereField(varName)) { - typeLeft = clas.getFieldType(varName); - } else if (clas.isParameterWitNameInMethod(varName)) { - typeLeft = clas.getParameterTypeInCurrentMethod(varName); - } else if (clas.isParameterNameInCurrentConstructor(varName)) { - typeLeft = clas.getParameterTypeInCurrentConstructor(varName); - } else { - throw new RuntimeException("Variable not declared"); - } + if (clas.isThereField(varName)) { + typeLeft = clas.getFieldType(varName); } else { - typeLeft = localVar.get(varName); + if (clas.isCurrentMethodPresent() && !clas.isCurrentConstructorPresent()) { + if (clas.getCurrentMethod().isLocalVariableInMethod(varName)) { + typeLeft = clas.getCurrentMethod().getLocalVariableType(varName); + } else { + throw new RuntimeException("Variable " + varName + " not declared in method"); + } + } + if (!clas.isCurrentMethodPresent() && clas.isCurrentConstructorPresent()) { + if (clas.getCurrentConstructor().isLocalVariableInConstructor(varName)) { + typeLeft = clas.getCurrentConstructor().getLocalVariableType(varName); + } else { + throw new RuntimeException("Variable " + varName + " not declared in constructor"); + } + } } Type typeRight = value.typeCheck(localVar, clas); diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedBlock.java b/src/main/java/de/maishai/typedast/typedclass/TypedBlock.java index e77c7e4..c1eeaf3 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedBlock.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedBlock.java @@ -18,7 +18,7 @@ import java.util.Map; @AllArgsConstructor @Data public class TypedBlock implements TypedNode { - private List vars = new ArrayList<>(); + private List vars = new ArrayList<>(); private List stmts = new ArrayList<>(); private Type type; @@ -27,7 +27,7 @@ public class TypedBlock implements TypedNode { convertToTypedBlock(localVar, clas, unTypedBlock); } - public TypedBlock(List vars, List stmts) { + public TypedBlock(List vars, List stmts) { this.vars = vars; this.stmts = stmts; } @@ -37,11 +37,10 @@ public class TypedBlock implements TypedNode { if (unTypedBlock == null) { return; } - /* + for (Declaration var : unTypedBlock.localVariables()) { - TypedDeclaration typedVar = new TypedDeclaration(localVar, clas, var); - vars.add(typedVar); - } */ + vars.add(new TypedLocalVariable(localVar, clas, var)); + } for (var stmt : unTypedBlock.stmts()) { if (stmt instanceof Assignment assignment) { @@ -105,10 +104,6 @@ public class TypedBlock implements TypedNode { @Override public Type typeCheck(Map localVar, TypedClass clas) { - for (TypedDeclaration var : vars) { - var.typeCheck(localVar, clas); - } - for (TypedStatement stmt : stmts) { stmt.typeCheck(localVar, clas); } @@ -119,7 +114,7 @@ public class TypedBlock implements TypedNode { } public void codeGen(MethodVisitor mv, MethodContext ctx) { - for (TypedDeclaration var : vars) { + for (TypedLocalVariable var : vars) { //var.codeGen(mv, ctx); } for (TypedStatement stmt : stmts) { diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedConstructor.java b/src/main/java/de/maishai/typedast/typedclass/TypedConstructor.java index fbf868f..4ef748d 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedConstructor.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedConstructor.java @@ -26,6 +26,7 @@ public class TypedConstructor implements TypedNode { private List typedParameters = new ArrayList<>(); private TypedBlock typedBlock; private Type type; + private List localVariables = new ArrayList<>(); public TypedConstructor(String name, List typedParameters, TypedBlock typedBlock) { this.name = name; @@ -37,6 +38,21 @@ public class TypedConstructor implements TypedNode { convertToTypedConstructor(localVar, clas, unTypedConstructor); } + public boolean isLocalVariablePresent(String localVarName) { + return localVariables.stream().anyMatch(localVariable -> localVariable.getName().equals(localVarName)); + } + + public boolean isParameterPresent(String parameterName) { + return typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(parameterName)); + } + + public boolean isLocalVariableInConstructor(String localVarName) { + return isLocalVariablePresent(localVarName) || isParameterPresent(localVarName); + } + public Type getLocalVariableType(String localVarName) { + return localVariables.stream().filter(localVariable -> localVariable.getName().equals(localVarName)).findFirst().get().getType(); + } + public void convertToTypedConstructor(Map localVar, TypedClass clas, Constructor unTypedConstructor) { name = unTypedConstructor.className(); diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedDeclaration.java b/src/main/java/de/maishai/typedast/typedclass/TypedDeclaration.java index b33175e..31948ff 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedDeclaration.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedDeclaration.java @@ -23,16 +23,16 @@ public final class TypedDeclaration implements TypedNode { private Type type; public TypedDeclaration(Map localVar, TypedClass clas, Declaration declaration) { - convertToTypedLocalVariable(localVar, clas, declaration); + convertToTypedDeclaration(localVar, clas, declaration); } - public void convertToTypedLocalVariable(Map localVar, TypedClass clas, Declaration declaration) { + public void convertToTypedDeclaration(Map localVar, TypedClass clas, Declaration declaration) { if (localVar.containsKey(declaration.name())) { throw new RuntimeException("Variable " + declaration.name() + " already declared"); } name = declaration.name(); type = declaration.type(); - //localVar.put(this.name, this.type); + typeCheck(localVar, clas); } @Override diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedLocalVariable.java b/src/main/java/de/maishai/typedast/typedclass/TypedLocalVariable.java new file mode 100644 index 0000000..0c301a6 --- /dev/null +++ b/src/main/java/de/maishai/typedast/typedclass/TypedLocalVariable.java @@ -0,0 +1,63 @@ + +package de.maishai.typedast.typedclass; + +import de.maishai.ast.records.Declaration; +import de.maishai.typedast.MethodContext; +import de.maishai.typedast.TypedNode; +import de.maishai.typedast.Type; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.util.Map; + +import static de.maishai.typedast.Type.Kind.REFERENCE; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public final class TypedLocalVariable implements TypedNode { + private String name; + private Type type; + + public TypedLocalVariable(Map localVar, TypedClass clas, Declaration declaration) { + convertToTypedLocalVariable(localVar, clas, declaration); + } + + public void convertToTypedLocalVariable(Map localVar, TypedClass clas, Declaration declaration) { + if (localVar.containsKey(declaration.name())) { + throw new RuntimeException("Variable " + declaration.name() + " already declared"); + } + name = declaration.name(); + type = declaration.type(); + typeCheck(localVar, clas); + } + + @Override + public Type typeCheck(Map localVar, TypedClass clas) { + if (clas.isCurrentMethodPresent() && !clas.isCurrentConstructorPresent()){ + if(clas.getCurrentMethod().isLocalVariableInMethod(name)){ + throw new RuntimeException("Variable " + name + " already declared"); + } + clas.getCurrentMethod().getLocalVariables().add(this); + return type; + } + if (!clas.isCurrentMethodPresent() && clas.isCurrentConstructorPresent()){ + if(clas.getCurrentConstructor().isLocalVariableInConstructor(name)){ + throw new RuntimeException("Variable " + name + " already declared"); + } + clas.getCurrentConstructor().getLocalVariables().add(this); + return type; + } + + throw new RuntimeException("not found method or constructor in class"); + } + + 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(); + } +} diff --git a/src/main/java/de/maishai/typedast/typedclass/TypedMethod.java b/src/main/java/de/maishai/typedast/typedclass/TypedMethod.java index 50fba3c..cdee9cf 100644 --- a/src/main/java/de/maishai/typedast/typedclass/TypedMethod.java +++ b/src/main/java/de/maishai/typedast/typedclass/TypedMethod.java @@ -21,21 +21,12 @@ public class TypedMethod implements TypedNode { private Type returnType; private List typedParameters = new ArrayList<>(); private TypedBlock typedBlock; - //private List localVariables = new ArrayList<>(); + private List localVariables = new ArrayList<>(); public TypedMethod(Map localVar, TypedClass clas, Method unTypedMethod) { convertToTypedMethod(localVar, clas, unTypedMethod); } - @Override - public boolean equals(Object obj) { - if (obj instanceof TypedMethod) { - TypedMethod other = (TypedMethod) obj; - return name.equals(other.name) && returnType.equals(other.returnType) && typedParameters.equals(other.typedParameters); - } - return false; - } - public void convertToTypedMethod(Map localVar, TypedClass clas, Method unTypedMethod) { name = unTypedMethod.methodName(); @@ -56,6 +47,19 @@ public class TypedMethod implements TypedNode { public void convertToTypedBlock(Map localVar, TypedClass clas, Method unTypedMethod) { typedBlock = new TypedBlock(localVar, clas, unTypedMethod.block()); } + public boolean isLocalVariablePresent(String localVarName) { + return localVariables.stream().anyMatch(localVariable -> localVariable.getName().equals(localVarName)); + } + public boolean isParameterPresent(String parameterName) { + return typedParameters.stream().anyMatch(parameter -> parameter.getParaName().equals(parameterName)); + } + + public boolean isLocalVariableInMethod(String localVarName) { + return isLocalVariablePresent(localVarName) || isParameterPresent(localVarName); + } + public Type getLocalVariableType(String localVarName) { + return localVariables.stream().filter(localVariable -> localVariable.getName().equals(localVarName)).findFirst().get().getType(); + } @Override @@ -70,6 +74,15 @@ public class TypedMethod implements TypedNode { return returnType; } + @Override + public boolean equals(Object obj) { + if (obj instanceof TypedMethod) { + TypedMethod other = (TypedMethod) obj; + return name.equals(other.name) && returnType.equals(other.returnType) && typedParameters.equals(other.typedParameters); + } + return false; + } + public void codeGen(ClassWriter cw) { int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok