1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-20 02:32:36 +00:00

Working on number conversion... not compiling atm.

This commit is contained in:
jespergravgaard 2019-05-06 08:06:18 +02:00
parent d0d5b5715b
commit 49ae6a0e66

View File

@ -1,12 +1,16 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.BinaryExpressionIterator;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantLiteral;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.RValue;
/**
* Add casts to {@link SymbolType#NUMBER} expressions that meet a typed value in a binary expression (including assignment)
@ -22,38 +26,86 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
BinaryExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
RValue left = binaryExpression.getLeft();
RValue right = binaryExpression.getRight();
SymbolType conversionType = getNumberConversionType(left, right);
if(conversionType != null) {
// Convert both left and right to the found type
getLog().append("Adding number conversion cast (" + fixedType+ ") " + binaryExpression.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
SymbolType leftType = SymbolTypeInference.inferType(getScope(), left);
SymbolType rightType = SymbolTypeInference.inferType(getScope(), right);
if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) {
SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType;
// Attempt to find number conversion!
if(right instanceof ConstantValue) {
ConstantLiteral constantLiteral = ((ConstantValue) right).calculateLiteral(getProgram().getScope());
if(constantLiteral instanceof ConstantInteger) {
ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
if(SymbolType.NUMBER.equals(constantInteger.getType())) {
Long value = constantInteger.getValue();
if(leftIntType.getMinValue()<=value && leftIntType.getMaxValue()>=value) {
// The value matches the left type!
getLog().append("Adding number conversion cast ("+leftIntType+") "+binaryExpression.getRight().toString()+" in "+currentStmt.toString(getProgram(), false));
binaryExpression.addRightCast(leftIntType);
} else {
throw new InternalError("TODO: Implement number conversion for non-equal types "+right.toString(), currentStmt);
}
} else {
throw new InternalError("Non-number constant has type number "+right.toString(), currentStmt);
}
}
} else {
// Postpone til later!
// Maybe handle AssignmentRValue separately!
getLog().append("Postponed number conversion " + right.toString());
}
}
});
return false;
}
private SymbolType getNumberConversionType(RValue left, RValue right) {
SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
if(SymbolType.NUMBER.equals(leftType) || SymbolType.NUMBER.equals(rightType)) {
// A special type number is assigned to integer constants without a postfix literal.
// Numbers are flexible and will take a type based on their actual value when they meet a typed number in a calculation.
// Number types are only usable at compile time.
if(leftType.equals(rightType)) {
// a) If the two operands are numbers the result is a number
return null;
}
RValue numberVal;
SymbolTypeIntegerFixed fixedType;
if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) {
// Left is the number
numberVal = left;
fixedType = (SymbolTypeIntegerFixed) rightType;
} else if(SymbolType.NUMBER.equals(rightType) && SymbolType.isInteger(leftType)) {
// Right is the number
numberVal = right;
fixedType = (SymbolTypeIntegerFixed) leftType;
} else {
// Non-integer number binary
throw new CompileError("Error! Incompatible operands "+left.toString()+" and "+right.toString());
}
if(numberVal instanceof ConstantValue) {
ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(getProgram().getScope());
if(constantLiteral instanceof ConstantInteger) {
ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
if(SymbolType.NUMBER.equals(constantInteger.getType())) {
Long value = constantInteger.getValue();
if(fixedType.getMinValue() <= value && fixedType.getMaxValue() >= value) {
// The value matches the left type!
binaryExpression.addRightCast(leftIntType);
} else {
throw new InternalError("TODO: Implement number conversion for non-equal types " + right.toString(), currentStmt);
}
} else {
throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
}
}
} else {
// Postpone til later!
// Maybe handle AssignmentRValue separately!
getLog().append("Postponed number conversion " + right.toString());
}
}
// No number conversion
return null;
if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) {
SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType;
// Attempt to find number conversion!
}
return null;
}
}