1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-27 04:49:27 +00:00

Cleaning up type inference.

This commit is contained in:
jespergravgaard 2019-05-23 00:38:35 +02:00
parent 49a61ecbdd
commit 65c92716f0
4 changed files with 37 additions and 54 deletions

View File

@ -3,43 +3,15 @@ package dk.camelot64.kickc.model.types;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.operators.OperatorBinary;
import dk.camelot64.kickc.model.operators.OperatorUnary;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.values.*;
/**
* Type inference of expressions (rValues & unary/binary operators)
* Type inference of an RValue
*/
public class SymbolTypeInference {
/**
* Infer the type of a unary operator on a value
*
* @param programScope The program scope usable for accessing the symbol table
* @param operator The unary operator
* @param rValue The value
* @return The type of the resulting value
*/
public static SymbolType inferType(ProgramScope programScope, OperatorUnary operator, RValue rValue) {
SymbolType valueType = inferType(programScope, rValue);
return operator.inferType(valueType);
}
/**
* Infer the type of a binary operator on a value
*
* @param programScope The program scope usable for accessing the symbol table
* @param left The left value
* @param operator The binary operator
* @param rValue The right value
* @return The type of the resulting value
*/
public static SymbolType inferType(ProgramScope programScope, RValue left, OperatorBinary operator, RValue right) {
SymbolType leftType = inferType(programScope, left);
SymbolType rightType = inferType(programScope, right);
return operator.inferType(leftType, rightType);
}
public static SymbolType inferType(ProgramScope symbols, RValue rValue) {
SymbolType type = null;
if(rValue instanceof VariableRef) {
@ -61,10 +33,13 @@ public class SymbolTypeInference {
type = SymbolType.BOOLEAN;
} else if(rValue instanceof ConstantUnary) {
ConstantUnary constUnary = (ConstantUnary) rValue;
return inferType(symbols, constUnary.getOperator(), constUnary.getOperand());
SymbolType valueType = inferType(symbols, constUnary.getOperand());
return constUnary.getOperator().inferType(valueType);
} else if(rValue instanceof ConstantBinary) {
ConstantBinary constBin = (ConstantBinary) rValue;
return inferType(symbols, constBin.getLeft(), constBin.getOperator(), constBin.getRight());
SymbolType leftType = inferType(symbols, constBin.getLeft());
SymbolType rightType = inferType(symbols, constBin.getRight());
return constBin.getOperator().inferType(leftType, rightType);
} else if(rValue instanceof ValueList) {
type = inferTypeList(symbols, (ValueList) rValue);
} else if(rValue instanceof PointerDereference) {
@ -103,7 +78,26 @@ public class SymbolTypeInference {
Procedure procedure = symbols.getProcedure((ProcedureRef) rValue);
return procedure.getType();
} else if(rValue instanceof AssignmentRValue) {
return inferTypeRValue(symbols, ((AssignmentRValue) rValue).getAssignment());
StatementAssignment assignment = ((AssignmentRValue) rValue).getAssignment();
SymbolType rValueType;
RValue rValue1 = assignment.getrValue1();
RValue rValue2 = assignment.getrValue2();
if(assignment.getrValue1() == null && assignment.getOperator() == null) {
// Copy assignment
rValueType = inferType(symbols, rValue2);
} else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary) {
// Unary operation assignment
SymbolType valueType = inferType(symbols, rValue2);
rValueType = ((OperatorUnary) assignment.getOperator()).inferType(valueType);
} else if(assignment.getOperator() instanceof OperatorBinary) {
// Binary operation assignment
SymbolType leftType = inferType(symbols, rValue1);
SymbolType rightType = inferType(symbols, rValue2);
rValueType = ((OperatorBinary) assignment.getOperator()).inferType(leftType, rightType);
} else {
throw new CompileError("Cannot infer type of " + assignment.toString());
}
return rValueType;
}
if(type == null) {
throw new RuntimeException("Cannot infer type for " + rValue.toString());
@ -137,20 +131,4 @@ public class SymbolTypeInference {
}
}
private static SymbolType inferTypeRValue(ProgramScope symbols, StatementAssignment assignment) {
SymbolType rValueType;
RValue rValue1 = assignment.getrValue1();
RValue rValue2 = assignment.getrValue2();
if(assignment.getrValue1() == null && assignment.getOperator() == null) {
rValueType = inferType(symbols, rValue2);
} else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary) {
rValueType = inferType(symbols, (OperatorUnary) assignment.getOperator(), rValue2);
} else if(assignment.getOperator() instanceof OperatorBinary) {
rValueType = inferType(symbols, rValue1, (OperatorBinary) assignment.getOperator(), rValue2);
} else {
throw new CompileError("Cannot infer type of " + assignment.toString());
}
return rValueType;
}
}

View File

@ -59,7 +59,9 @@ public class ConstantBinary implements ConstantValue {
@Override
public SymbolType getType(ProgramScope scope) {
return SymbolTypeInference.inferType(scope, left, operator, right);
SymbolType leftType = SymbolTypeInference.inferType(scope, left);
SymbolType rightType = SymbolTypeInference.inferType(scope, right);
return operator.inferType(leftType, rightType);
}
@Override

View File

@ -47,7 +47,8 @@ public class ConstantUnary implements ConstantValue {
@Override
public SymbolType getType(ProgramScope scope) {
return SymbolTypeInference.inferType(scope, operator, operand);
SymbolType valueType = SymbolTypeInference.inferType(scope, operand);
return operator.inferType(valueType);
}
@Override

View File

@ -9,6 +9,7 @@ import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.VariableIntermediate;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.values.AssignmentRValue;
import dk.camelot64.kickc.model.values.PointerDereferenceIndexed;
import dk.camelot64.kickc.model.values.PointerDereferenceSimple;
import dk.camelot64.kickc.model.values.RValue;
@ -35,12 +36,13 @@ public class Pass2DeInlineWordDerefIdx extends Pass2SsaOptimization {
getLog().append("De-inlining pointer[w] to *(pointer+w) "+currentStmt.toString(getProgram(), false));
Scope currentScope = getScope().getScope(currentBlock.getScope());
VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
SymbolType pointerType = SymbolTypeInference.inferType(getScope(), dereferenceIndexed.getPointer(), Operators.PLUS, indexValue);
tmpVar.setType(pointerType);
stmtIt.previous();
stmtIt.add(new StatementAssignment(tmpVar.getRef(), dereferenceIndexed.getPointer(), Operators.PLUS, indexValue, currentStmt.getSource(), Comment.NO_COMMENTS));
StatementAssignment tmpVarAssignment = new StatementAssignment(tmpVar.getRef(), dereferenceIndexed.getPointer(), Operators.PLUS, indexValue, currentStmt.getSource(), Comment.NO_COMMENTS);
stmtIt.add(tmpVarAssignment);
stmtIt.next();
programValue.set(new PointerDereferenceSimple(tmpVar.getRef()));
SymbolType pointerType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(tmpVarAssignment));
tmpVar.setType(pointerType);
optimized.set(true);
}
}