diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java index 2a76c569b..81aad2e0e 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java @@ -43,6 +43,8 @@ public class OperatorGetHigh extends OperatorUnary { return SymbolType.WORD; } else if(SymbolType.STRING.equals(operandType)) { return SymbolType.BYTE; + } else if(SymbolType.NUMBER.equals(operandType)) { + return SymbolType.NUMBER; } throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java index bd8d030f3..81fc490c0 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java @@ -43,6 +43,8 @@ public class OperatorGetLow extends OperatorUnary { return SymbolType.WORD; } else if(SymbolType.STRING.equals(operandType)) { return SymbolType.BYTE; + } else if(SymbolType.NUMBER.equals(operandType)) { + return SymbolType.NUMBER; } throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java index bb14a9cd1..c6c7f3f72 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java @@ -2,6 +2,8 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; +import dk.camelot64.kickc.model.types.SymbolTypeInteger; import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantBool; import dk.camelot64.kickc.model.values.ConstantInteger; @@ -24,7 +26,11 @@ public class OperatorShiftLeft extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { - return left; + if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { + return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right); + } else { + return left; + } } } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java index 6b3adb2b7..dc9c66a69 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java @@ -2,6 +2,8 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeConversion; +import dk.camelot64.kickc.model.types.SymbolTypeInteger; import dk.camelot64.kickc.model.types.SymbolTypeSimple; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -23,7 +25,11 @@ public class OperatorShiftRight extends OperatorBinary { @Override public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) { - return left; + if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) { + return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right); + } else { + return left; + } } diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java index 4967f0bfa..acef7130b 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java @@ -48,8 +48,13 @@ public class SymbolTypeNumberInference { // Calculate resulting constant literal ConstantLiteral leftLiteral = leftValue.calculateLiteral(programScope); ConstantLiteral rightLiteral = rightValue.calculateLiteral(programScope); - ConstantLiteral constantLiteral = operator.calculateLiteral(leftLiteral, rightLiteral); - return inferTypes(programScope, constantLiteral); + ConstantLiteral literal = operator.calculateLiteral(leftLiteral, rightLiteral); + if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) { + SymbolType literalType = SymbolTypeInference.inferType(programScope, leftValue, operator, rightValue); + ((ConstantInteger) literal).setType(literalType); + throw new InternalError("Unexpected advanced literal type calculation!"); + } + return inferTypes(programScope, literal); } else { throw new InternalError("Both operands must be number type."); } @@ -64,8 +69,13 @@ public class SymbolTypeNumberInference { if(SymbolType.NUMBER.equals(constantValue.getType(programScope))) { // Calculate resulting constant literal ConstantLiteral operandLiteral = constantValue.calculateLiteral(programScope); - ConstantLiteral constantLiteral = operator.calculateLiteral(operandLiteral, programScope); - return inferTypes(programScope, constantLiteral); + ConstantLiteral literal = operator.calculateLiteral(operandLiteral, programScope); + if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) { + SymbolType literalType = SymbolTypeInference.inferType(programScope, operator, constantValue); + ((ConstantInteger) literal).setType(literalType); + throw new InternalError("Unexpected advanced literal type calculation!"); + } + return inferTypes(programScope, literal); } else { throw new InternalError("Operand must be number type."); } diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java index e15ed558a..df51994a4 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java @@ -50,7 +50,11 @@ public class ConstantBinary implements ConstantValue { @Override public ConstantLiteral calculateLiteral(ProgramScope scope) { - return operator.calculateLiteral(left.calculateLiteral(scope), right.calculateLiteral(scope)); + ConstantLiteral literal = operator.calculateLiteral(left.calculateLiteral(scope), right.calculateLiteral(scope)); + if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(scope))) { + ((ConstantInteger) literal).setType(getType(scope)); + } + return literal; } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java index 80fc32871..a111b9c07 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java @@ -38,7 +38,11 @@ public class ConstantUnary implements ConstantValue { @Override public ConstantLiteral calculateLiteral(ProgramScope scope) { - return operator.calculateLiteral(operand.calculateLiteral(scope), scope); + ConstantLiteral literal = operator.calculateLiteral(operand.calculateLiteral(scope), scope); + if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(scope))) { + ((ConstantInteger) literal).setType(getType(scope)); + } + return literal; } @Override diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index f9a125777..6a0063197 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testToD018Problem() throws IOException, URISyntaxException { + compileAndCompare("tod018-problem", log()); + } + @Test public void testHelloWorld0() throws IOException, URISyntaxException { compileAndCompare("helloworld0"); diff --git a/src/test/kc/examples/sinsprites/sinus-sprites.kc b/src/test/kc/examples/sinsprites/sinus-sprites.kc index d27f76bb9..a81055760 100644 --- a/src/test/kc/examples/sinsprites/sinus-sprites.kc +++ b/src/test/kc/examples/sinsprites/sinus-sprites.kc @@ -104,7 +104,7 @@ void place_sprites() { *SPRITES_EXPAND_X = %01111111; *SPRITES_EXPAND_Y = %01111111; byte* sprites_ptr = SCREEN+$3f8; - byte spr_id = (byte)(sprites/$40); + byte spr_id = (byte)((word)sprites/$40); byte spr_x = 60; byte j2 = 0; byte col = $5; diff --git a/src/test/kc/inline-kasm-resource.kc b/src/test/kc/inline-kasm-resource.kc index 6b7bf9b32..a0d9b8593 100644 --- a/src/test/kc/inline-kasm-resource.kc +++ b/src/test/kc/inline-kasm-resource.kc @@ -14,7 +14,7 @@ const byte* SPRITES_XPOS = $d000; const byte* SPRITES_YPOS = $d001; void main() { - *(SCREEN+$3f8) = (byte)(SPRITE/$40); + *(SCREEN+$3f8) = (byte)((word)SPRITE/$40); *SPRITES_ENABLE = 1; *SPRITES_XPOS = 100; *SPRITES_YPOS = 100; diff --git a/src/test/kc/tod018-problem.kc b/src/test/kc/tod018-problem.kc new file mode 100644 index 000000000..cb6b2e5c7 --- /dev/null +++ b/src/test/kc/tod018-problem.kc @@ -0,0 +1,9 @@ +// Tests a problem with tod018 not calculating types correctly + +void main() { + const byte *D018 = 0xd018; + const byte* screen = 0x0400; + byte d018val = >((word)screen&$3fff); + *D018 = d018val; +} +