mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-28 02:08:04 +00:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
f0912ed01f
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,47 @@ 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 TypedExpression value;
|
private TypedExpression value;
|
||||||
|
private TypedFieldVarAccess location;
|
||||||
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();
|
value = convertExpression(clas, untyped.value());
|
||||||
value = getKindOfExpression(localVar, clas, untyped.value());
|
location = new TypedFieldVarAccess(clas, untyped.location());
|
||||||
}
|
}
|
||||||
|
|
||||||
@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(location.getName())) {
|
||||||
typeLeft = clas.getFieldType(varName);
|
typeLeft = clas.getFieldType(location.getName());
|
||||||
}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(location.getName())) {
|
||||||
|
typeLeft = clas.getCurrentMethod().getLocalVariableType(location.getName());
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Variable " + location.getName() + " not declared in method");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!clas.isCurrentMethodPresent() && clas.isCurrentConstructorPresent()) {
|
||||||
|
if (clas.getCurrentConstructor().isLocalVariableInConstructor(location.getName())) {
|
||||||
|
typeLeft = clas.getCurrentConstructor().getLocalVariableType(location.getName());
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Variable " + location.getName() + " 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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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<>()));
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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,58 @@ 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.isCurrentConstructorPresent()) {
|
||||||
type = clas.getFieldType(name);
|
if (clas.isParameterNameInCurrentConstructor(name)) {
|
||||||
return clas.getFieldType(name);
|
|
||||||
}else if(clas.isCurrentConstructorPresent()){
|
|
||||||
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 if(clas.isThereField(name)){
|
||||||
|
type = clas.getFieldType(name);
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
}else if(clas.isCurrentMethodPresent()){
|
else {
|
||||||
if(clas.isParameterWitNameInMethod(name)){
|
throw new RuntimeException("Variable " + name + " not declared in constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (clas.isCurrentMethodPresent()) {
|
||||||
|
if (clas.isParameterWitNameInMethod(name)) {
|
||||||
type = clas.getParameterTypeInCurrentMethod(name);
|
type = clas.getParameterTypeInCurrentMethod(name);
|
||||||
return clas.getParameterTypeInCurrentMethod(name);
|
return type;
|
||||||
|
} else if (clas.getCurrentMethod().isLocalVariablePresent(name)) {
|
||||||
|
type = clas.getCurrentMethod().getLocalVariableType(name);
|
||||||
|
return type;
|
||||||
|
} else if(clas.isThereField(name)){
|
||||||
|
type = clas.getFieldType(name);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException("Variable " + name + " not declared in method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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).getKind() != returnType.getKind()){
|
||||||
}
|
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
|
||||||
|
@ -10,7 +10,9 @@ 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;
|
||||||
|
|
||||||
|
//TODO: test this after fixing error from parser
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ -19,20 +21,42 @@ 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));
|
||||||
}
|
}
|
||||||
|
recipient.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type typeCheck(Map<String, Type> localVar, TypedClass clas) {
|
public Type typeCheck(TypedClass clas) {
|
||||||
//TODO: Implement typeCheck
|
/* if (clas.isCurrentMethodPresent()) {
|
||||||
|
|
||||||
|
List<TypedMethod> methods = clas.getTypedMethods().stream()
|
||||||
|
.filter(method -> method.getName().equals(name))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
for (TypedMethod method : methods) {
|
||||||
|
if (method.getTypedParameters().size() == args.size()) {
|
||||||
|
boolean allMatch = true;
|
||||||
|
for (int i = 0; i < args.size(); i++) {
|
||||||
|
if (!args.get(i).typeCheck(clas).equals(method.getTypedParameters().get(i).getType())) {
|
||||||
|
allMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allMatch) {
|
||||||
|
return method.getReturnType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} */
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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,23 @@ 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) {
|
||||||
type = ret.getType();
|
ret = convertExpression(clas, unTypedReturn.ret());
|
||||||
|
if(ret == null){
|
||||||
|
type = Type.VOID;
|
||||||
|
}else{
|
||||||
|
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());
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ public class ClassCanBeTyped {
|
|||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
ClassCanBeTyped b;
|
ClassCanBeTyped b;
|
||||||
|
ClassCanBeTyped c;
|
||||||
public ClassCanBeTyped(int x) {
|
public ClassCanBeTyped(int x) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
}
|
}
|
||||||
@ -16,6 +17,8 @@ public class ClassCanBeTyped {
|
|||||||
b = new ClassCanBeTyped(x);
|
b = new ClassCanBeTyped(x);
|
||||||
b.x = 10 + a;
|
b.x = 10 + a;
|
||||||
b.y = 20;
|
b.y = 20;
|
||||||
|
b.c.x = 20 + a;
|
||||||
|
b.c.b.y = b.x;
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user