Merge remote-tracking branch 'origin/FixingError'

# Conflicts:
#	src/main/java/de/maishai/typedast/typedclass/TypedBoolLiteral.java
#	src/main/java/de/maishai/typedast/typedclass/TypedConstructor.java
#	src/main/java/de/maishai/typedast/typedclass/TypedLocalVariable.java
#	src/main/java/de/maishai/typedast/typedclass/TypedMethod.java
#	src/main/java/de/maishai/typedast/typedclass/TypedUnary.java
This commit is contained in:
ahmad 2024-05-12 19:02:52 +02:00
commit cef0c5ba86
25 changed files with 505 additions and 393 deletions

View File

@ -9,45 +9,45 @@ import java.util.Map;
public class TypedExpressionHelp { public class TypedExpressionHelp {
public static TypedExpression getKindOfExpression(Map<String, Type> localVar, TypedClass clas, Expression expression) { public static TypedExpression convertExpression( TypedClass clas, Expression expression) {
if (expression instanceof BoolLiteral boolLiteral) { if (expression instanceof BoolLiteral boolLiteral) {
TypedBoolLiteral typedBoolLiteral = new TypedBoolLiteral(localVar, clas, boolLiteral); TypedBoolLiteral typedBoolLiteral = new TypedBoolLiteral( clas, boolLiteral);
typedBoolLiteral.typeCheck(localVar, clas); typedBoolLiteral.typeCheck( clas);
return typedBoolLiteral; return typedBoolLiteral;
} }
else if (expression instanceof CharLiteral charLiteral) { else if (expression instanceof CharLiteral charLiteral) {
TypedCharLiteral typedCharLiteral = new TypedCharLiteral(localVar, clas, charLiteral); TypedCharLiteral typedCharLiteral = new TypedCharLiteral( clas, charLiteral);
typedCharLiteral.typeCheck(localVar, clas); typedCharLiteral.typeCheck( clas);
return typedCharLiteral; return typedCharLiteral;
} }
else if (expression instanceof IntLiteral intLiteral) { else if (expression instanceof IntLiteral intLiteral) {
TypedIntLiteral typedIntLiteral = new TypedIntLiteral(localVar, clas, intLiteral); TypedIntLiteral typedIntLiteral = new TypedIntLiteral( clas, intLiteral);
typedIntLiteral.typeCheck(localVar, clas); typedIntLiteral.typeCheck( clas);
return typedIntLiteral; return typedIntLiteral;
} }
else if (expression instanceof Binary binary) { else if (expression instanceof Binary binary) {
TypedBinary typedBinary = new TypedBinary(localVar, clas, binary); TypedBinary typedBinary = new TypedBinary( clas, binary);
typedBinary.typeCheck(localVar, clas); typedBinary.typeCheck( clas);
return typedBinary; return typedBinary;
} }
else if (expression instanceof FieldVarAccess fieldVarAccess) { else if (expression instanceof FieldVarAccess fieldVarAccess) {
TypedFieldVarAccess typedFieldVarAccess = new TypedFieldVarAccess(localVar, clas, fieldVarAccess); TypedFieldVarAccess typedFieldVarAccess = new TypedFieldVarAccess( clas, fieldVarAccess);
typedFieldVarAccess.typeCheck(localVar, clas); typedFieldVarAccess.typeCheck( clas);
return typedFieldVarAccess; return typedFieldVarAccess;
} }
else if (expression instanceof MethodCall methodCall) { else if (expression instanceof MethodCall methodCall) {
TypedMethodCall typedMethodCall = new TypedMethodCall(localVar, clas, methodCall); TypedMethodCall typedMethodCall = new TypedMethodCall( clas, methodCall);
typedMethodCall.typeCheck(localVar, clas); typedMethodCall.typeCheck( clas);
return typedMethodCall; return typedMethodCall;
} }
else if (expression instanceof New newStmt) { else if (expression instanceof New newStmt) {
TypedNew typedNew = new TypedNew(localVar, clas, newStmt); TypedNew typedNew = new TypedNew( clas, newStmt);
typedNew.typeCheck(localVar, clas); typedNew.typeCheck( clas);
return typedNew; return typedNew;
} }
else if (expression instanceof Unary unary) { else if (expression instanceof Unary unary) {
TypedUnary typedUnary = new TypedUnary(localVar, clas, unary); TypedUnary typedUnary = new TypedUnary( clas, unary);
typedUnary.typeCheck(localVar, clas); typedUnary.typeCheck( clas);
return typedUnary; return typedUnary;
} else { } else {
return null; return null;

View File

@ -1,10 +1,7 @@
package de.maishai.typedast; package de.maishai.typedast;
import de.maishai.ast.records.Node;
import de.maishai.typedast.typedclass.TypedClass; import de.maishai.typedast.typedclass.TypedClass;
import java.util.Map;
public interface TypedNode { public interface TypedNode {
Type typeCheck(Map<String, Type> localVar, TypedClass clas); Type typeCheck(TypedClass clas);
} }

View File

@ -1,6 +1,7 @@
package de.maishai.typedast.typedclass; package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Assignment; import de.maishai.ast.records.Assignment;
import de.maishai.ast.records.Expression;
import de.maishai.typedast.MethodContext; import de.maishai.typedast.MethodContext;
import de.maishai.typedast.TypedExpression; import de.maishai.typedast.TypedExpression;
import de.maishai.typedast.TypedStatement; import de.maishai.typedast.TypedStatement;
@ -11,42 +12,49 @@ import org.objectweb.asm.Opcodes;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
public class TypedAssignment implements TypedStatement { public class TypedAssignment implements TypedStatement {
private String varName; private String varName;
private TypedExpression value; private TypedExpression value;
private TypedExpression recursiveOwnerChain;
private Type type; private Type type;
public TypedAssignment(Map<String, Type> localVar, TypedClass clas, Assignment untyped) { public TypedAssignment(TypedClass clas, Assignment untyped) {
convertToTypedAssignment(localVar, clas, untyped); convertToTypedAssignment(clas, untyped);
} }
public void convertToTypedAssignment(Map<String, Type> localVar, TypedClass clas, Assignment untyped) { public void convertToTypedAssignment(TypedClass clas, Assignment untyped) {
varName = untyped.location().id(); varName = untyped.location().id();
value = getKindOfExpression(localVar, clas, untyped.value()); value = convertExpression(clas, untyped.value());
recursiveOwnerChain = convertExpression( clas, untyped.location().recursiveOwnerChain());
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
Type typeLeft = null; Type typeLeft = null;
if (!localVar.containsKey(varName)) {
if(clas.isThereField(varName)){ if (clas.isThereField(varName)) {
typeLeft = clas.getFieldType(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");
}
} else { } 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); Type typeRight = value.typeCheck(clas);
if (typeLeft.equals(typeRight)) { if (typeLeft.equals(typeRight)) {
type = typeLeft; type = typeLeft;

View File

@ -11,7 +11,7 @@ import org.objectweb.asm.MethodVisitor;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -21,45 +21,49 @@ public class TypedBinary implements TypedExpression {
private TypedExpression right; private TypedExpression right;
private Type type; private Type type;
public TypedBinary(Map<String, Type> localVar, TypedClass clas, Binary unTypedBinary) { public TypedBinary(TypedClass clas, Binary unTypedBinary) {
convertToTypedBinary(localVar, clas, unTypedBinary); convertToTypedBinary(clas, unTypedBinary);
} }
public void convertToTypedBinary(Map<String, Type> localVar, TypedClass clas, Binary unTypedBinary) { public void convertToTypedBinary(TypedClass clas, Binary unTypedBinary) {
left = getKindOfExpression(localVar, clas, unTypedBinary.left()); left = convertExpression(clas, unTypedBinary.left());
right = getKindOfExpression(localVar, clas, unTypedBinary.right()); right = convertExpression(clas, unTypedBinary.right());
op = unTypedBinary.op(); op = unTypedBinary.op();
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
Type leftType = left.typeCheck(clas);
Type rightType = right.typeCheck(clas);
if (op == Operator.ADD || op == Operator.SUB || op == Operator.MUL) { if (op == Operator.ADD || op == Operator.SUB || op == Operator.MUL) {
if (left.typeCheck(localVar, clas) == Type.INT && if (leftType == Type.INT && rightType == Type.INT) {
right.typeCheck(localVar, clas) == Type.INT) {
type = Type.INT; type = Type.INT;
return Type.INT; return Type.INT;
} else { } else {
throw new RuntimeException("Type mismatch in " + op); throw new RuntimeException("Type mismatch in " + op);
} }
} else if (op == Operator.GT || op == Operator.LT || op == Operator.GE || op == Operator.LE || op == Operator.EQ || op == Operator.NE ) { } else if (op == Operator.GT || op == Operator.LT || op == Operator.GE || op == Operator.LE) {
if (left.typeCheck(localVar, clas) == Type.INT && if (leftType == Type.INT && rightType == Type.INT) {
right.typeCheck(localVar, clas) == Type.INT) {
type = Type.BOOL; type = Type.BOOL;
return Type.BOOL; return Type.BOOL;
} else { } else {
throw new RuntimeException("Type mismatch in " + op); throw new RuntimeException("Type mismatch in " + op);
} }
} else if (op == Operator.AND || op == Operator.OR) { } else if (op == Operator.AND || op == Operator.OR) {
if (left.typeCheck(localVar, clas) == Type.BOOL && if (leftType == Type.BOOL && rightType == Type.BOOL) {
right.typeCheck(localVar, clas) == Type.BOOL) {
type = Type.BOOL; type = Type.BOOL;
return Type.BOOL; return Type.BOOL;
} else { } else {
throw new RuntimeException("Type mismatch in " + op); throw new RuntimeException("Type mismatch in " + op);
} }
} else {
throw new RuntimeException("Invalid operator");
} }
if (leftType == rightType && leftType != Type.VOID) {
type = rightType;
return type;
}
throw new RuntimeException("Void can not be compared with Void");
} }
@Override @Override

View File

@ -1,7 +1,10 @@
package de.maishai.typedast.typedclass; package de.maishai.typedast.typedclass;
import de.maishai.ast.records.*; import de.maishai.ast.records.*;
import de.maishai.typedast.*; import de.maishai.typedast.MethodContext;
import de.maishai.typedast.Type;
import de.maishai.typedast.TypedNode;
import de.maishai.typedast.TypedStatement;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -20,99 +23,99 @@ public class TypedBlock implements TypedNode {
private Type type; private Type type;
public TypedBlock(TypedClass clas, Block unTypedBlock) {
public TypedBlock(Map<String, Type> localVar, TypedClass clas, Block unTypedBlock) { convertToTypedBlock(clas, unTypedBlock);
convertToTypedBlock(localVar, clas, unTypedBlock);
} }
public TypedBlock(List<TypedLocalVariable> vars, List<TypedStatement> stmts) { public TypedBlock(List<TypedLocalVariable> vars, List<TypedStatement> stmts) {
this.vars = vars; this.vars = vars;
this.stmts = stmts; this.stmts = stmts;
} }
public void convertToTypedBlock(Map<String, Type> localVar, TypedClass clas, Block unTypedBlock) { public void convertToTypedBlock(TypedClass clas, Block unTypedBlock) {
if(unTypedBlock == null) { if (unTypedBlock == null) {
return; return;
} }
for (Declaration var : unTypedBlock.localVariables()) { for (Declaration var : unTypedBlock.localVariables()) {
TypedLocalVariable typedVar = new TypedLocalVariable(localVar, clas, var); vars.add(new TypedLocalVariable(clas, var));
vars.add(typedVar);
} }
for (var stmt : unTypedBlock.stmts()) { for (var stmt : unTypedBlock.stmts()) {
if (stmt instanceof Assignment assignment) { if (stmt instanceof Assignment assignment) {
TypedAssignment typedAssignment = new TypedAssignment(localVar, clas, assignment); TypedAssignment typedAssignment = new TypedAssignment(clas, assignment);
typedAssignment.typeCheck(localVar, clas); typedAssignment.typeCheck(clas);
stmts.add(typedAssignment); stmts.add(typedAssignment);
continue; continue;
} }
if (stmt instanceof For forStmt) { if (stmt instanceof For forStmt) {
TypedFor typedFor = new TypedFor(localVar, clas, forStmt); TypedFor typedFor = new TypedFor(clas, forStmt);
typedFor.typeCheck(localVar, clas); typedFor.typeCheck(clas);
stmts.add(typedFor); stmts.add(typedFor);
continue; continue;
} }
if (stmt instanceof IfElse ifElse) { if (stmt instanceof IfElse ifElse) {
TypedIfElse typedIfElse = new TypedIfElse(localVar, clas, ifElse); TypedIfElse typedIfElse = new TypedIfElse(clas, ifElse);
typedIfElse.typeCheck(localVar, clas); typedIfElse.typeCheck(clas);
stmts.add(typedIfElse); stmts.add(typedIfElse);
continue; continue;
} }
if (stmt instanceof While whileStmt) { if (stmt instanceof While whileStmt) {
TypedWhile typedWhile = new TypedWhile(localVar, clas, whileStmt); TypedWhile typedWhile = new TypedWhile(clas, whileStmt);
typedWhile.typeCheck(localVar, clas); typedWhile.typeCheck(clas);
stmts.add(typedWhile); stmts.add(typedWhile);
continue; continue;
} }
if (stmt instanceof DoWhile doWhile) { if (stmt instanceof DoWhile doWhile) {
TypedDoWhile typedDoWhile = new TypedDoWhile(localVar, clas, doWhile); TypedDoWhile typedDoWhile = new TypedDoWhile(clas, doWhile);
typedDoWhile.typeCheck(localVar, clas); typedDoWhile.typeCheck(clas);
stmts.add(typedDoWhile); stmts.add(typedDoWhile);
continue; continue;
} }
if (stmt instanceof Return returnStmt) { if (stmt instanceof Return returnStmt) {
TypedReturn typedReturn = new TypedReturn(localVar, clas, returnStmt); TypedReturn typedReturn = new TypedReturn(clas, returnStmt);
typedReturn.typeCheck(localVar, clas); typedReturn.typeCheck(clas);
stmts.add(typedReturn); stmts.add(typedReturn);
continue; continue;
} }
if (stmt instanceof New newStmt) { if (stmt instanceof New newStmt) {
TypedNew typedNew = new TypedNew(localVar, clas, newStmt); TypedNew typedNew = new TypedNew(clas, newStmt);
typedNew.typeCheck(localVar, clas); typedNew.typeCheck(clas);
stmts.add(typedNew); stmts.add(typedNew);
continue; continue;
} }
if (stmt instanceof Break) { if (stmt instanceof Break) {
TypedBreak typedBreak = new TypedBreak(); stmts.add(new TypedBreak());
typedBreak.typeCheck(localVar, clas);
stmts.add(typedBreak);
continue; continue;
} }
if (stmt instanceof MethodCall methodCall) { if (stmt instanceof MethodCall methodCall) {
TypedMethodCall typedMethodCall = new TypedMethodCall(localVar, clas, methodCall); TypedMethodCall typedMethodCall = new TypedMethodCall(clas, methodCall);
typedMethodCall.typeCheck(localVar, clas); typedMethodCall.typeCheck(clas);
stmts.add(typedMethodCall); stmts.add(typedMethodCall);
} }
} }
this.typeCheck(localVar, clas); this.typeCheck(clas);
System.out.println("TypedBlock: " + this.toString());
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
Type chekType = null;
for (TypedLocalVariable var : vars) {
var.typeCheck(localVar, clas);
}
for (TypedStatement stmt : stmts) { for (TypedStatement stmt : stmts) {
stmt.typeCheck(localVar, clas); stmt.typeCheck(clas);
if(stmt instanceof TypedReturn returnStmt) {
chekType = returnStmt.getType();
}
} }
type = Type.VOID; if(chekType == null) {
chekType = Type.VOID;
}
type = chekType;
return type; return type;
} }

View File

@ -12,6 +12,7 @@ import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.Map; import java.util.Map;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
public class TypedBoolLiteral implements TypedExpression { public class TypedBoolLiteral implements TypedExpression {
@ -20,17 +21,17 @@ public class TypedBoolLiteral implements TypedExpression {
private Type type; private Type type;
public TypedBoolLiteral(Map<String, Type> localVar, TypedClass clas, BoolLiteral unTypedBoolLiteral) { public TypedBoolLiteral(TypedClass clas, BoolLiteral unTypedBoolLiteral) {
convertToTypedBoolLiteral(localVar, clas, unTypedBoolLiteral); convertToTypedBoolLiteral(clas, unTypedBoolLiteral);
} }
public void convertToTypedBoolLiteral(Map<String, Type> localVar, TypedClass clas, BoolLiteral unTypedBoolLiteral) { public void convertToTypedBoolLiteral(TypedClass clas, BoolLiteral unTypedBoolLiteral) {
value = unTypedBoolLiteral.value(); value = unTypedBoolLiteral.value();
type = Type.BOOL; type = Type.BOOL;
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
return type; return type;
} }

View File

@ -10,16 +10,17 @@ import lombok.Data;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import java.util.Map; import java.util.Map;
@Data @Data
public class TypedBreak implements TypedStatement { public class TypedBreak implements TypedStatement {
private Type type = Type.VOID; private Type type = Type.VOID;
public TypedBreak convertToTypedBreak(Map<String, Type> localVar, TypedClass clas, Break unTypedBreak) { public TypedBreak convertToTypedBreak(TypedClass clas, Break unTypedBreak) {
return this; return this;
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
type = Type.VOID;
return type; return type;
} }

View File

@ -10,20 +10,23 @@ import lombok.Data;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import java.util.Map; import java.util.Map;
@Data @Data
public class TypedCharLiteral implements TypedExpression { public class TypedCharLiteral implements TypedExpression {
private char value; private char value;
private Type type; private Type type;
public TypedCharLiteral(Map<String, Type> localVar, TypedClass clas, CharLiteral unTypedCharLiteral) { public TypedCharLiteral(TypedClass clas, CharLiteral unTypedCharLiteral) {
convertToCharLiteral(localVar, clas, unTypedCharLiteral); convertToCharLiteral(clas, unTypedCharLiteral);
} }
public void convertToCharLiteral(Map<String, Type> localVar, TypedClass clas, CharLiteral unTypedCharLiteral) {
value = unTypedCharLiteral.value(); public void convertToCharLiteral(TypedClass clas, CharLiteral unTypedCharLiteral) {
type = Type.CHAR; value = unTypedCharLiteral.value();
type = Type.CHAR;
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
return type; return type;
} }

View File

@ -23,34 +23,41 @@ import java.util.Map;
@NoArgsConstructor @NoArgsConstructor
public class TypedClass implements TypedNode { public class TypedClass implements TypedNode {
private String className; private String className;
private List<TypedField> typedFields = new ArrayList<>(); private List<TypedDeclaration> typedDeclarations = new ArrayList<>();
private List<TypedMethod> typedMethods = new ArrayList<>(); private List<TypedMethod> typedMethods = new ArrayList<>();
private List<TypedConstructor> typedConstructors = new ArrayList<>(); private List<TypedConstructor> typedConstructors = new ArrayList<>();
private TypedMethod currentMethod; private TypedMethod currentMethod;
private TypedConstructor currentConstructor; private TypedConstructor currentConstructor;
private Type type; private Type type;
public TypedClass(Map<String, Type> localVar, Class c) { public TypedClass(Class c) {
convertToTypedClass(localVar, c); convertToTypedClass(c);
} }
public void enterMethod(TypedMethod method) {
public void enterCurrentMethod(TypedMethod method) {
currentMethod = method; currentMethod = method;
} }
public void exitMethod() {
public void exitCurrentMethod() {
currentMethod = null; currentMethod = null;
} }
public void enterConstructor(TypedConstructor constructor) {
public void enterCurrentConstructor(TypedConstructor constructor) {
currentConstructor = constructor; currentConstructor = constructor;
} }
public void exitConstructor() {
public void exitCurrentConstructor() {
currentConstructor = null; currentConstructor = null;
} }
public boolean isCurrentMethodPresent() { public boolean isCurrentMethodPresent() {
return currentMethod != null; return currentMethod != null;
} }
public boolean isCurrentConstructorPresent() { public boolean isCurrentConstructorPresent() {
return currentConstructor != null; return currentConstructor != null;
} }
public boolean isParameterNameInCurrentMethod(String parameterName) { public boolean isParameterNameInCurrentMethod(String parameterName) {
if (currentMethod == null) { if (currentMethod == null) {
return false; return false;
@ -62,6 +69,7 @@ public class TypedClass implements TypedNode {
} }
return false; return false;
} }
public boolean isParameterNameInCurrentConstructor(String parameterName) { public boolean isParameterNameInCurrentConstructor(String parameterName) {
if (currentConstructor == null) { if (currentConstructor == null) {
return false; return false;
@ -74,52 +82,51 @@ public class TypedClass implements TypedNode {
return false; return false;
} }
public void convertToTypedClass(Map<String, Type> localVar, Class c) { public void convertToTypedClass(Class c) {
className = c.classname(); className = c.classname();
type = Type.REFERENCE(className); type = Type.REFERENCE(className);
for (Declaration field : c.fieldDeclarations()) { for (Declaration declaration : c.fieldDeclarations()) {
typedFields.add(new TypedField(localVar, this, field)); typedDeclarations.add(new TypedDeclaration(this, declaration));
} }
// Am Anfang werden die Konstruktoren und Methoden in die Listen eingefügt
// Methoden können verwendet werden, bevor deren Blöcke ausgeführt werden
for (Constructor constructor : c.constructors()) { for (Constructor constructor : c.constructors()) {
typedConstructors.add(new TypedConstructor(localVar, this, constructor)); typedConstructors.add(new TypedConstructor(this, constructor));
enterConstructor(typedConstructors.get(typedConstructors.size() - 1));
typedConstructors.get(typedConstructors.size() - 1).convertToBlock(localVar, this, constructor);
exitConstructor();
} }
for (Method method : c.methods()) { for (Method method : c.methods()) {
typedMethods.add(new TypedMethod(localVar, this, method)); typedMethods.add(new TypedMethod(this, method));
enterMethod(typedMethods.get(typedMethods.size() - 1));
typedMethods.get(typedMethods.size() - 1).convertToTypedBlock(localVar, this, method);
exitMethod();
} }
// Hier werden die Blöcke der Konstruktoren und Methoden ausgeführt
int i = 0;
for (Constructor constructor : c.constructors()) {
enterCurrentConstructor(typedConstructors.get(i));
typedConstructors.get(i).convertToBlock(this, constructor);
exitCurrentConstructor();
i++;
}
int j = 0;
for (Method method : c.methods()) {
enterCurrentMethod(typedMethods.get(j));
typedMethods.get(j).convertToTypedBlock(this, method);
exitCurrentMethod();
j++;
}
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
return type;
if (clas == null) {
throw new RuntimeException("Class not found");
}
for (TypedField field : typedFields) {
field.typeCheck(localVar, clas);
}
for (TypedConstructor constructor : typedConstructors) {
constructor.typeCheck(localVar, clas);
}
for (TypedMethod typedMethod : typedMethods) {
typedMethod.typeCheck(localVar, clas);
}
return Type.REFERENCE(className);
} }
public TypedNode startConversion(Class c) { public TypedNode startConversion(Class c) {
Map<String, Type> local = new HashMap<>(); Map<String, Type> local = new HashMap<>();
return new TypedClass(local, c); return new TypedClass(c);
} }
public boolean isParameterWitNameInMethod(String parameterName) { public boolean isParameterWitNameInMethod(String parameterName) {
@ -132,6 +139,7 @@ public class TypedClass implements TypedNode {
} }
return false; return false;
} }
public boolean isParameterWitNameInConstructor(String parameterName) { public boolean isParameterWitNameInConstructor(String parameterName) {
for (TypedConstructor c : typedConstructors) { for (TypedConstructor c : typedConstructors) {
for (TypedParameter p : c.getTypedParameters()) { for (TypedParameter p : c.getTypedParameters()) {
@ -153,6 +161,7 @@ public class TypedClass implements TypedNode {
} }
return null; 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)) {
@ -163,28 +172,23 @@ public class TypedClass implements TypedNode {
} }
public boolean isThereField(String fieldName) { public boolean isThereField(String fieldName) {
for (TypedDeclaration f : typedDeclarations) {
for (TypedField f : typedFields) { if (f.getName().equals(fieldName)) {
if (f.getVarName().equals(getFieldNameWithOutThis(fieldName))) {
return true; return true;
} }
} }
return false; return false;
} }
private String getFieldNameWithOutThis(String fieldName) {
if(fieldName.startsWith("this.")){
fieldName = fieldName.substring(5);
}
return fieldName;
}
public Type getFieldType(String fieldName) { public Type getFieldType(String fieldName) {
for (TypedField f : typedFields) { for (TypedDeclaration f : typedDeclarations) {
if (f.getVarName().equals(getFieldNameWithOutThis(fieldName))) { if (f.getName().equals(fieldName)) {
return f.getType(); return f.getType();
} }
} }
return null; return null;
} }
public Type getMethodType(String methodName) { public Type getMethodType(String methodName) {
for (TypedMethod m : typedMethods) { for (TypedMethod m : typedMethods) {
if (m.getName().equals(methodName)) { if (m.getName().equals(methodName)) {
@ -199,8 +203,8 @@ public class TypedClass implements TypedNode {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
ClassContext ctx = new ClassContext(className, cw); ClassContext ctx = new ClassContext(className, cw);
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null); cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);
for (TypedField field : typedFields) { for (TypedDeclaration declaration : typedDeclarations) {
field.codeGen(cw); declaration.codeGen(cw);
} }
for (TypedConstructor constructor : typedConstructors) { for (TypedConstructor constructor : typedConstructors) {
@ -220,9 +224,9 @@ public class TypedClass implements TypedNode {
c.setClassName("SomeClass"); c.setClassName("SomeClass");
//Fields //Fields
TypedField f1 = new TypedField("someNumber", Type.INT); TypedDeclaration f1 = new TypedDeclaration("someNumber", Type.INT);
TypedField f2 = new TypedField("someChar", Type.CHAR); TypedDeclaration f2 = new TypedDeclaration("someChar", Type.CHAR);
c.typedFields = List.of(f1, f2); c.typedDeclarations = List.of(f1, f2);
//Constructors //Constructors
TypedConstructor constructor = new TypedConstructor("SomeClass", List.of(new TypedParameter("test", Type.INT)), new TypedBlock(new ArrayList<>(), new ArrayList<>())); TypedConstructor constructor = new TypedConstructor("SomeClass", List.of(new TypedParameter("test", Type.INT)), new TypedBlock(new ArrayList<>(), new ArrayList<>()));

View File

@ -23,31 +23,55 @@ public class TypedConstructor implements TypedNode {
private List<TypedParameter> typedParameters = new ArrayList<>(); private List<TypedParameter> typedParameters = new ArrayList<>();
private TypedBlock typedBlock; private TypedBlock typedBlock;
private Type type; private Type type;
private List<TypedLocalVariable> localVariables = new ArrayList<>();
public TypedConstructor(String name, List<TypedParameter> typedParameters, TypedBlock typedBlock) { public TypedConstructor(String name, List<TypedParameter> typedParameters, TypedBlock typedBlock) {
this.name = name; this.name = name;
this.typedParameters = typedParameters; this.typedParameters = typedParameters;
this.typedBlock = typedBlock; this.typedBlock = typedBlock;
} }
public TypedConstructor(Map<String, Type> localVar, TypedClass clas, Constructor unTypedConstructor) {
convertToTypedConstructor(localVar, clas, unTypedConstructor); public TypedConstructor(TypedClass clas, Constructor unTypedConstructor) {
convertToTypedConstructor(clas, unTypedConstructor);
} }
public void convertToTypedConstructor(Map<String, Type> localVar, TypedClass clas, Constructor 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(TypedClass clas, Constructor unTypedConstructor) {
name = unTypedConstructor.className(); name = unTypedConstructor.className();
for (Parameter param : unTypedConstructor.params()) { for (Parameter param : unTypedConstructor.params()) {
typedParameters.add(new TypedParameter(localVar, clas, param)); typedParameters.add(new TypedParameter(clas, param));
} }
// Konstrukteur hat den Rückgabetyp wie der Klassenname, obwohl es keinen expliziten Rückgabetyp gibt type = Type.VOID;
type = clas.getType();
} }
public void convertToBlock(Map<String, Type> localVar, TypedClass clas, Constructor unTypedConstructor) {
this.typedBlock = new TypedBlock(localVar, clas ,unTypedConstructor.block()); public void convertToBlock(TypedClass clas, Constructor unTypedConstructor) {
this.typedBlock = new TypedBlock(clas, unTypedConstructor.block());
typeCheck(clas);
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
type = typedBlock.typeCheck(clas);
if(type != Type.VOID){
throw new RuntimeException("Constructor must not habe a return statement");
}
return type; return type;
} }

View File

@ -0,0 +1,62 @@
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 TypedDeclaration implements TypedNode {
private String name;
private Type type;
public TypedDeclaration(TypedClass clas, Declaration declaration) {
convertToTypedDeclaration(clas, declaration);
}
public void convertToTypedDeclaration(TypedClass clas, Declaration declaration) {
name = declaration.name();
type = declaration.type();
typeCheck(clas);
}
@Override
public Type typeCheck(TypedClass clas) {
if (clas.isThereField(name)) {
throw new RuntimeException("Field " + name + " already declared");
}
if (type.getKind() == REFERENCE) {
if (!type.getReference().equals(clas.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();
}
}

View File

@ -7,7 +7,7 @@ import org.objectweb.asm.MethodVisitor;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
public class TypedDoWhile implements TypedStatement { public class TypedDoWhile implements TypedStatement {
@ -15,20 +15,21 @@ public class TypedDoWhile implements TypedStatement {
private TypedExpression cond; private TypedExpression cond;
private Type type; private Type type;
public TypedDoWhile(Map<String, Type> localVar, TypedClass clas, DoWhile unTypedDoWhile) { public TypedDoWhile(TypedClass clas, DoWhile unTypedDoWhile) {
convertToTypedDoWhile(localVar, clas, unTypedDoWhile); convertToTypedDoWhile(clas, unTypedDoWhile);
} }
public void convertToTypedDoWhile(Map<String, Type> localVar, TypedClass clas, DoWhile unTypedDoWhile) {
typedBlock = new TypedBlock(localVar, clas, unTypedDoWhile.block()); public void convertToTypedDoWhile(TypedClass clas, DoWhile unTypedDoWhile) {
cond = getKindOfExpression(localVar, clas, unTypedDoWhile.cond()); typedBlock = new TypedBlock(clas, unTypedDoWhile.block());
cond = convertExpression(clas, unTypedDoWhile.cond());
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
if (cond.typeCheck(localVar, clas) != Type.BOOL) { if (cond.typeCheck(clas) != Type.BOOL) {
throw new RuntimeException("Condition must be boolean"); throw new RuntimeException("Condition must be boolean");
} }
typedBlock.typeCheck(localVar, clas); typedBlock.typeCheck(clas);
this.type = Type.VOID; this.type = Type.VOID;
return Type.VOID; return Type.VOID;
} }

View File

@ -1,55 +0,0 @@
package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Declaration;
import de.maishai.ast.records.Node;
import de.maishai.typedast.TypedNode;
import de.maishai.typedast.Type;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import java.util.Map;
import static de.maishai.typedast.Type.Kind.REFERENCE;
@AllArgsConstructor
@RequiredArgsConstructor
@Data
public class TypedField implements TypedNode {
private String varName;
private Type type;
public TypedField(Map<String, Type> localVar, TypedClass clas, Declaration declaration){
convertToTypedField(localVar, clas, declaration);
}
public void convertToTypedField(Map<String, Type> localVar, TypedClass clas, Declaration declaration){
this.type = declaration.type();
varName = declaration.name();
this.typeCheck(localVar, clas);
}
@Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) {
if(clas.isThereField(varName)){
throw new RuntimeException("Field " + varName + " already declared");
}
if(type.getKind() == REFERENCE){
if(!type.getReference().equals(clas.getClassName())){
throw new RuntimeException("Field " + varName + " has wrong type");
}
}
return type;
}
public void codeGen(ClassWriter cw) {
int access = Opcodes.ACC_PUBLIC; // laut Andi ist es ok, dass alle Felder public sind
cw.visitField(access, varName, type.getDescriptor(), null, null).visitEnd();
}
}

View File

@ -10,7 +10,7 @@ import org.objectweb.asm.MethodVisitor;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -20,43 +20,52 @@ public class TypedFieldVarAccess implements TypedExpression {
private String name; private String name;
private Type type; private Type type;
public TypedFieldVarAccess(Map<String, Type> localVar, TypedClass clas, FieldVarAccess unTypedFieldVarAccess) { public TypedFieldVarAccess(TypedClass clas, FieldVarAccess unTypedFieldVarAccess) {
convertToTypedFieldVarAccess(localVar, clas, unTypedFieldVarAccess); convertToTypedFieldVarAccess(clas, unTypedFieldVarAccess);
} }
public void convertToTypedFieldVarAccess(Map<String, Type> localVar, TypedClass clas, FieldVarAccess unTypedFieldVarAccess) {
public void convertToTypedFieldVarAccess(TypedClass clas, FieldVarAccess unTypedFieldVarAccess) {
field = unTypedFieldVarAccess.field(); field = unTypedFieldVarAccess.field();
recursiveOwnerChain = getKindOfExpression(localVar, clas, unTypedFieldVarAccess.recursiveOwnerChain()); recursiveOwnerChain = convertExpression(clas, unTypedFieldVarAccess.recursiveOwnerChain());
name = unTypedFieldVarAccess.id(); name = unTypedFieldVarAccess.id();
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
if(field){ if (field) {
if (clas.isThereField(name)) { if (clas.isThereField(name)) {
type = clas.getFieldType(name); type = clas.getFieldType(name);
return clas.getFieldType(name); return clas.getFieldType(name);
}else{
throw new RuntimeException("Field " + name + " not declared ");
} }
}else{ } else {
if (clas.isThereField(name)) { if (clas.isThereField(name)) {
type = clas.getFieldType(name); type = clas.getFieldType(name);
return clas.getFieldType(name); return type;
}else if(clas.isCurrentConstructorPresent()){ } else if (clas.isCurrentConstructorPresent()) {
if(clas.isParameterNameInCurrentConstructor(name)){ if (clas.isParameterNameInCurrentConstructor(name)) {
type = clas.getParameterTypeInCurrentConstructor(name); type = clas.getParameterTypeInCurrentConstructor(name);
return clas.getParameterTypeInCurrentConstructor(name); return type;
} else if (clas.getCurrentConstructor().isLocalVariablePresent(name)) {
type = clas.getCurrentConstructor().getLocalVariableType(name);
return type;
} else {
throw new RuntimeException("Variable " + name + " not declared ");
} }
}else if(clas.isCurrentMethodPresent()){ } else if (clas.isCurrentMethodPresent()) {
if(clas.isParameterWitNameInMethod(name)){ if (clas.isParameterWitNameInMethod(name)) {
type = clas.getParameterTypeInCurrentMethod(name); type = clas.getParameterTypeInCurrentMethod(name);
return clas.getParameterTypeInCurrentMethod(name); return clas.getParameterTypeInCurrentMethod(name);
} else if (clas.getCurrentMethod().isLocalVariablePresent(name)) {
type = clas.getCurrentMethod().getLocalVariableType(name);
return type;
} else {
throw new RuntimeException("Variable " + name + " not declared ");
} }
} }
if(localVar.containsKey(name)) { throw new RuntimeException("Variable " + name + " not declared ");
type = localVar.get(name);
return localVar.get(name);
}
} }
throw new RuntimeException("Variable "+name+" not declared ");
} }
@Override @Override

View File

@ -9,7 +9,7 @@ import org.objectweb.asm.MethodVisitor;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@ -19,26 +19,28 @@ public class TypedFor implements TypedStatement {
private TypedExpression cond; private TypedExpression cond;
private TypedAssignment inc; private TypedAssignment inc;
private TypedBlock typedBlock; private TypedBlock typedBlock;
//TODO: add Type private Type type;
public TypedFor(Map<String, Type> localVar, TypedClass clas, For unTypedFor) { public TypedFor(TypedClass clas, For unTypedFor) {
convertToTypedFor(localVar, clas, unTypedFor); convertToTypedFor(clas, unTypedFor);
} }
public void convertToTypedFor(Map<String, Type> localVar,TypedClass clas, For unTypedFor) {
assign = new TypedAssignment(localVar, clas, unTypedFor.assign()); public void convertToTypedFor(TypedClass clas, For unTypedFor) {
cond = getKindOfExpression(localVar, clas, unTypedFor.cond()); assign = new TypedAssignment(clas, unTypedFor.assign());
inc = new TypedAssignment(localVar, clas, unTypedFor.inc()); cond = convertExpression(clas, unTypedFor.cond());
typedBlock = new TypedBlock(localVar, clas, unTypedFor.block()); inc = new TypedAssignment(clas, unTypedFor.inc());
typedBlock = new TypedBlock(clas, unTypedFor.block());
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
assign.typeCheck(localVar, clas); assign.typeCheck(clas);
if (!cond.typeCheck(localVar, clas).equals(Type.BOOL)) { if (!cond.typeCheck(clas).equals(Type.BOOL)) {
throw new RuntimeException("Condition must be a boolean"); throw new RuntimeException("Condition must be a boolean");
} }
inc.typeCheck(localVar, clas); inc.typeCheck(clas);
return typedBlock.typeCheck(localVar, clas); type = typedBlock.typeCheck(clas);
return type;
} }
@Override @Override

View File

@ -10,7 +10,7 @@ import org.objectweb.asm.Opcodes;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -18,27 +18,40 @@ public class TypedIfElse implements TypedStatement {
private TypedExpression typedCon; private TypedExpression typedCon;
private TypedBlock ifTypedBlock; private TypedBlock ifTypedBlock;
private TypedBlock elseTypedBlock; private TypedBlock elseTypedBlock;
//TODO: add Type private Type type;
public TypedIfElse(Map<String, Type> localVar, TypedClass clas, IfElse unTypedIfElse) { public TypedIfElse(TypedClass clas, IfElse unTypedIfElse) {
convertToTypedIfElse(localVar, clas, unTypedIfElse); convertToTypedIfElse(clas, unTypedIfElse);
} }
public void convertToTypedIfElse(Map<String, Type> localVar, TypedClass clas, IfElse unTypedIfElse) {
ifTypedBlock = new TypedBlock(localVar, clas, unTypedIfElse.ifBlock()); public void convertToTypedIfElse(TypedClass clas, IfElse unTypedIfElse) {
elseTypedBlock = new TypedBlock(localVar, clas, unTypedIfElse.elseBlock()); ifTypedBlock = new TypedBlock(clas, unTypedIfElse.ifBlock());
typedCon = getKindOfExpression(localVar, clas, unTypedIfElse.cond()); elseTypedBlock = new TypedBlock(clas, unTypedIfElse.elseBlock());
typedCon = convertExpression(clas, unTypedIfElse.cond());
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
/*
if (typedCon.typeCheck(localVar, clas) != Type.BOOL) { if (typedCon.typeCheck(clas) != Type.BOOL) {
throw new RuntimeException("If condition must be a boolean"); throw new RuntimeException("If condition must be a boolean");
} }
if (ifTypedBlock.typeCheck(localVar, clas) != Type.VOID) { if (ifTypedBlock.typeCheck(clas) != Type.VOID) {
throw new RuntimeException("If block must be of type void"); throw new RuntimeException("If block must be of type void");
} }
return Type.VOID; */
//TODO: it still not catching the all cases when return is used
if (ifTypedBlock.typeCheck(clas) == elseTypedBlock.typeCheck(clas)) {
type = ifTypedBlock.typeCheck(clas);
}
if (elseTypedBlock.typeCheck(clas) == Type.VOID) {
type = ifTypedBlock.typeCheck(clas);
}
if (ifTypedBlock.typeCheck(clas) == Type.VOID) {
type = elseTypedBlock.typeCheck(clas);
}
return type;
} }
@Override @Override

View File

@ -20,18 +20,20 @@ public class TypedIntLiteral implements TypedExpression {
private Type type; private Type type;
public TypedIntLiteral(Map<String, Type> localVar, TypedClass clas, IntLiteral unTypedIntLiteral) { public TypedIntLiteral(TypedClass clas, IntLiteral unTypedIntLiteral) {
convertToTypedIntLiteral(localVar, clas, unTypedIntLiteral); convertToTypedIntLiteral(clas, unTypedIntLiteral);
} }
public void convertToTypedIntLiteral(Map<String, Type> localVar, TypedClass clas, IntLiteral unTypedIntLiteral) {
public void convertToTypedIntLiteral(TypedClass clas, IntLiteral unTypedIntLiteral) {
value = unTypedIntLiteral.value(); value = unTypedIntLiteral.value();
type = Type.INT; type = Type.INT;
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
return type; return type;
} }
public TypedIntLiteral(Integer value) { public TypedIntLiteral(Integer value) {
this.value = value; this.value = value;
} }

View File

@ -8,9 +8,14 @@ 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.ClassWriter;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Type.Kind.REFERENCE;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@ -18,25 +23,33 @@ public final class TypedLocalVariable implements TypedNode {
private String name; private String name;
private Type type; private Type type;
public TypedLocalVariable(Map<String, Type> localVar, TypedClass clas, Declaration declaration){ public TypedLocalVariable(TypedClass clas, Declaration declaration) {
convertToTypedLocalVariable(localVar, clas, declaration); convertToTypedLocalVariable(clas, declaration);
} }
public void convertToTypedLocalVariable(Map<String, Type> localVar, TypedClass clas, Declaration declaration){
if(localVar.containsKey(declaration.name())){ public void convertToTypedLocalVariable(TypedClass clas, Declaration declaration) {
throw new RuntimeException("Variable " + declaration.name() + " already declared"); name = declaration.name();
} type = declaration.type();
this.setName(declaration.name()); typeCheck(clas);
this.setType(declaration.type());
localVar.put(this.name, this.type);
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
Type type = localVar.get(name); if (clas.isCurrentMethodPresent() && !clas.isCurrentConstructorPresent()) {
if(type == this.type) { if (clas.getCurrentMethod().isLocalVariableInMethod(name)) {
return type; throw new RuntimeException("Variable " + name + " already declared");
} }
throw new RuntimeException("type of left not equals with type of right"); 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(MethodVisitor mv, MethodContext ctx) { public void codeGen(MethodVisitor mv, MethodContext ctx) {

View File

@ -20,54 +20,69 @@ public class TypedMethod implements TypedNode {
private String name; private String name;
private Type returnType; private Type returnType;
private List<TypedParameter> typedParameters = new ArrayList<>(); private List<TypedParameter> typedParameters = new ArrayList<>();
private List<TypedLocalVariable> localVariables = new ArrayList<>();
private TypedBlock typedBlock; private TypedBlock typedBlock;
public TypedMethod(Map<String, Type> localVar, TypedClass clas, Method unTypedMethod) { public TypedMethod(TypedClass clas, Method unTypedMethod) {
convertToTypedMethod(localVar, clas, unTypedMethod); convertToTypedMethod(clas, unTypedMethod);
} }
public void convertToTypedMethod(Map<String, Type> localVar, TypedClass clas, Method unTypedMethod) { public void convertToTypedMethod(TypedClass clas, Method unTypedMethod) {
name = unTypedMethod.methodName(); name = unTypedMethod.methodName();
returnType = unTypedMethod.type(); returnType = unTypedMethod.type();
for (Parameter parameter : unTypedMethod.params()) { for (var parameter : unTypedMethod.params()) {
typedParameters.add(new TypedParameter(localVar, clas, parameter)); typedParameters.add(new TypedParameter(clas, parameter));
} }
for (var method : clas.getTypedMethods()) {
if (method.getName().equals(name) && method.getTypedParameters().size() == typedParameters.size()
&& method.getReturnType().equals(returnType)) {
for (int i = 0; i < method.getTypedParameters().size(); i++) { clas.getTypedMethods().stream().filter(method -> method.equals(this)).findFirst().ifPresentOrElse(
if (method.getTypedParameters().get(i).getType().equals(typedParameters.get(i).getType())) { method -> {
throw new RuntimeException("Method " + name + " already exists");
}
}
if (method.getTypedParameters().isEmpty() && typedParameters.isEmpty()) {
throw new RuntimeException("Method " + name + " already exists"); throw new RuntimeException("Method " + name + " already exists");
} }, () -> {
} });
}
localVar.put(name, returnType);
} }
public void convertToTypedBlock(Map<String, Type> localVar, TypedClass clas, Method unTypedMethod) { public void convertToTypedBlock(TypedClass clas, Method unTypedMethod) {
typedBlock = new TypedBlock(localVar, clas, unTypedMethod.block()); typedBlock = new TypedBlock(clas, unTypedMethod.block());
typeCheck(clas);
}
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 @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
if (localVar.containsKey(name)) { if(returnType != Type.VOID){
throw new RuntimeException("Method " + name + " already exists"); if(typedBlock.typeCheck(clas) != returnType){
} throw new RuntimeException("Method " + name + " must return " + returnType);
localVar.put(name, returnType); }
for (TypedParameter typedParameter : typedParameters) {
typedParameter.typeCheck(localVar, clas);
} }
return returnType; 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(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

View File

@ -10,7 +10,7 @@ import org.objectweb.asm.MethodVisitor;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -19,20 +19,20 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
private List<TypedExpression> args; private List<TypedExpression> args;
private Type type; private Type type;
public TypedMethodCall(Map<String, Type> localVar, TypedClass clas, MethodCall unTypedMethodCall) { public TypedMethodCall(TypedClass clas, MethodCall unTypedMethodCall) {
convertToTypedMethodCall(localVar, clas, unTypedMethodCall); convertToTypedMethodCall(clas, unTypedMethodCall);
} }
public void convertToTypedMethodCall(Map<String, Type> localVar, TypedClass clas, MethodCall unTypedMethodCall) { public void convertToTypedMethodCall(TypedClass clas, MethodCall unTypedMethodCall) {
recipient = new TypedFieldVarAccess(localVar, clas, unTypedMethodCall.recipient()); recipient = new TypedFieldVarAccess(clas, unTypedMethodCall.recipient());
for (Expression arg : unTypedMethodCall.args()) { for (Expression arg : unTypedMethodCall.args()) {
args.add(getKindOfExpression(localVar, clas, arg)); args.add(convertExpression(clas, arg));
} }
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
//TODO: Implement typeCheck //TODO: implement this
return null; return null;
} }

View File

@ -10,39 +10,36 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
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<>();
public TypedNew(Map<String, Type> localVar, TypedClass clas, New unTypedNew) { public TypedNew(TypedClass clas, New unTypedNew) {
convertToTypedNew(localVar, clas, unTypedNew); convertToTypedNew(clas, unTypedNew);
} }
public void convertToTypedNew(Map<String, Type> localVar, TypedClass clas, New unTypedNew) {
public void convertToTypedNew(TypedClass clas, New unTypedNew) {
type = unTypedNew.type(); type = unTypedNew.type();
for (Expression arg : unTypedNew.args()) { for (Expression arg : unTypedNew.args()) {
args.add(getKindOfExpression(localVar, clas, arg)); args.add(convertExpression(clas, arg));
} }
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
if(clas == null){ for (var constructor : clas.getTypedConstructors()) {
throw new RuntimeException("Class not found"); if (constructor.getTypedParameters().size() == args.size()) {
}
for(var constructor : clas.getTypedConstructors()){
if(constructor.getTypedParameters().size() == args.size()){
boolean valid = true; boolean valid = true;
for(int i = 0; i < args.size(); i++){ for (int i = 0; i < args.size(); i++) {
if(!constructor.getTypedParameters().get(i).getType().equals(args.get(i).typeCheck(localVar, clas))){ if (!constructor.getTypedParameters().get(i).getType().equals(args.get(i).typeCheck(clas))) {
valid = false; valid = false;
break; break;
} }
} }
if(valid){ if (valid) {
return Type.REFERENCE(clas.getClassName()); return Type.REFERENCE(clas.getClassName());
} }
} }

View File

@ -1,41 +1,47 @@
package de.maishai.typedast.typedclass; package de.maishai.typedast.typedclass;
import de.maishai.ast.records.Node;
import de.maishai.ast.records.Parameter; import de.maishai.ast.records.Parameter;
import de.maishai.typedast.TypedNode;
import de.maishai.typedast.Type; import de.maishai.typedast.Type;
import de.maishai.typedast.TypedNode;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.RequiredArgsConstructor;
import java.util.Map; import java.util.Map;
@AllArgsConstructor @AllArgsConstructor
@RequiredArgsConstructor
@Data @Data
public class TypedParameter implements TypedNode { public class TypedParameter implements TypedNode {
private String paraName; private String paraName;
private Type type; private Type type;
public TypedParameter(Map<String, Type> localVar, TypedClass clas, Parameter unTypedParameter) { public TypedParameter(TypedClass clas, Parameter unTypedParameter) {
convertToTypedParameter(localVar, clas, unTypedParameter); convertToTypedParameter(clas, unTypedParameter);
} }
public void convertToTypedParameter(Map<String, Type> localVar, TypedClass clas, Parameter unTypedParameter) {
public void convertToTypedParameter(TypedClass clas, Parameter unTypedParameter) {
paraName = unTypedParameter.name(); paraName = unTypedParameter.name();
type = unTypedParameter.type(); type = unTypedParameter.type();
//localVar.put(paraName, type); }
@Override
public boolean equals(Object obj) {
if (obj instanceof TypedParameter) {
TypedParameter other = (TypedParameter) obj;
return paraName.equals(other.paraName) && type.equals(other.type);
}
return false;
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
if(clas.isCurrentMethodPresent()){ if (clas.isCurrentMethodPresent()) {
if(clas.isParameterWitNameInMethod(paraName)) { if (clas.isParameterWitNameInMethod(paraName)) {
throw new RuntimeException("Parameter " + paraName + " already exists"); throw new RuntimeException("Parameter " + paraName + " already exists");
} }
}else if(clas.isCurrentConstructorPresent()){ } else if (clas.isCurrentConstructorPresent()) {
if(clas.isParameterWitNameInConstructor(paraName)) { if (clas.isParameterWitNameInConstructor(paraName)) {
throw new RuntimeException("Parameter " + paraName + " already exists"); throw new RuntimeException("Parameter " + paraName + " already exists");
} }
} }
@ -44,5 +50,4 @@ public class TypedParameter implements TypedNode {
} }
} }

View File

@ -10,7 +10,7 @@ import org.objectweb.asm.Opcodes;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -18,18 +18,19 @@ public class TypedReturn implements TypedStatement {
private TypedExpression ret; private TypedExpression ret;
private Type type; private Type type;
public TypedReturn(Map<String, Type> localVar, TypedClass clas, Return unTypedReturn) { public TypedReturn(TypedClass clas, Return unTypedReturn) {
convertToTypedReturn(localVar, clas, unTypedReturn); convertToTypedReturn(clas, unTypedReturn);
} }
public void convertToTypedReturn(Map<String, Type> localVar, TypedClass clas, Return unTypedReturn) {
ret = getKindOfExpression(localVar, clas, unTypedReturn.ret()); public void convertToTypedReturn(TypedClass clas, Return unTypedReturn) {
ret = convertExpression(clas, unTypedReturn.ret());
type = ret.getType(); type = ret.getType();
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
if(clas.isCurrentMethodPresent()){ if (clas.isCurrentMethodPresent()) {
if(clas.getCurrentMethod().getReturnType().getKind() != this.type.getKind()){ if (clas.getCurrentMethod().getReturnType().getKind() != this.type.getKind()) {
StringBuilder exp = new StringBuilder(); StringBuilder exp = new StringBuilder();
exp.append("\nMismatched return type: "); exp.append("\nMismatched return type: ");
exp.append("\nExpected: ").append(clas.getCurrentMethod().getReturnType().getKind()); exp.append("\nExpected: ").append(clas.getCurrentMethod().getReturnType().getKind());

View File

@ -11,7 +11,7 @@ import org.objectweb.asm.Opcodes;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
public class TypedUnary implements TypedExpression { public class TypedUnary implements TypedExpression {
@ -19,25 +19,27 @@ public class TypedUnary implements TypedExpression {
private TypedExpression right; private TypedExpression right;
private Type type; private Type type;
public TypedUnary(Map<String, Type> localVar, TypedClass clas, Unary unTypedUnary){ public TypedUnary(TypedClass clas, Unary unTypedUnary) {
convertToTypedUnary(localVar, clas, unTypedUnary); convertToTypedUnary(clas, unTypedUnary);
} }
public void convertToTypedUnary(Map<String, Type> localVar, TypedClass clas, Unary unTypedUnary) {
op = unTypedUnary.op();
right = getKindOfExpression(localVar, clas, unTypedUnary.right());
}
@Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) {
if(op == UnaryOperator.NOT){ public void convertToTypedUnary(TypedClass clas, Unary unTypedUnary) {
if(right.typeCheck(localVar, clas) != Type.BOOL){ op = unTypedUnary.op();
right = convertExpression(clas, unTypedUnary.right());
}
@Override
public Type typeCheck(TypedClass clas) {
if (op == UnaryOperator.NOT) {
if (right.typeCheck(clas) != Type.BOOL) {
throw new RuntimeException("Not operator must be applied to boolean"); throw new RuntimeException("Not operator must be applied to boolean");
} }
return Type.BOOL; return Type.BOOL;
} }
if(op == UnaryOperator.SUB){ if (op == UnaryOperator.SUB) {
if(right.typeCheck(localVar, clas) != Type.INT){ if (right.typeCheck(clas) != Type.INT) {
throw new RuntimeException("Minus operator must be applied to int"); throw new RuntimeException("Minus operator must be applied to int");
} }
return Type.INT; return Type.INT;

View File

@ -7,7 +7,7 @@ import org.objectweb.asm.MethodVisitor;
import java.util.Map; import java.util.Map;
import static de.maishai.typedast.Help.TypedExpressionHelp.getKindOfExpression; import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@Data @Data
public class TypedWhile implements TypedStatement { public class TypedWhile implements TypedStatement {
@ -15,22 +15,22 @@ public class TypedWhile implements TypedStatement {
private TypedBlock typedBlock; private TypedBlock typedBlock;
private Type type; private Type type;
public TypedWhile(Map<String, Type> localVar, TypedClass clas, While unTypedWhile) { public TypedWhile(TypedClass clas, While unTypedWhile) {
convertToTypedWhile(localVar, clas, unTypedWhile); convertToTypedWhile(clas, unTypedWhile);
} }
public void convertToTypedWhile(Map<String, Type> localVar, TypedClass clas, While unTypedWhile) { public void convertToTypedWhile(TypedClass clas, While unTypedWhile) {
cond = getKindOfExpression(localVar, clas, unTypedWhile.cond()); cond = convertExpression(clas, unTypedWhile.cond());
typedBlock = new TypedBlock(localVar, clas, unTypedWhile.block()); typedBlock = new TypedBlock(clas, unTypedWhile.block());
} }
@Override @Override
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) { public Type typeCheck(TypedClass clas) {
if(cond.typeCheck(localVar, clas) != Type.BOOL){ if (cond.typeCheck(clas) != Type.BOOL) {
throw new RuntimeException("While condition must be a boolean"); throw new RuntimeException("While condition must be a boolean");
} }
typedBlock.typeCheck(localVar, clas); type = typedBlock.typeCheck(clas);
this.type = Type.VOID; return type;
return Type.BOOL;
} }