From 94243878031d507098ff00761a80f11b7d1c9549 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 16 Jan 2019 23:24:47 +0100 Subject: [PATCH] added ast check for invalid type cast --- compiler/src/prog8/ast/AstChecker.kt | 2 + compiler/src/prog8/compiler/Compiler.kt | 12 +-- .../src/prog8/compiler/intermediate/Value.kt | 17 ++-- examples/test.p8 | 99 ++++++------------- 4 files changed, 45 insertions(+), 85 deletions(-) diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index fb209344d..75f4a21ff 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -697,6 +697,8 @@ class AstChecker(private val namespace: INameScope, } override fun process(typecast: TypecastExpression): IExpression { + if(typecast.type in IterableDatatypes) + checkResult.add(ExpressionError("cannot type cast to string or array type", typecast.position)) val funcTarget = (typecast.expression as? IFunctionCall)?.target?.targetStatement(namespace) if(funcTarget is Subroutine && funcTarget.asmReturnvaluesRegisters.isNotEmpty() && diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index e29f45b6f..f5eebadd2 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -2190,7 +2190,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, DataType.UWORD-> prog.instr(Opcode.CAST_UW_TO_UB) DataType.WORD-> prog.instr(Opcode.CAST_W_TO_UB) DataType.FLOAT -> prog.instr(Opcode.CAST_F_TO_UB) - else -> throw CompilerException("invalid cast type $sourceDt") + else -> throw CompilerException("invalid cast $sourceDt to ${expr.type} -- should be an Ast check") } DataType.BYTE -> when(sourceDt) { DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_B) @@ -2198,7 +2198,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, DataType.UWORD -> prog.instr(Opcode.CAST_UW_TO_B) DataType.WORD -> prog.instr(Opcode.CAST_W_TO_B) DataType.FLOAT -> prog.instr(Opcode.CAST_F_TO_B) - else -> throw CompilerException("invalid cast type $sourceDt") + else -> throw CompilerException("invalid cast $sourceDt to ${expr.type} -- should be an Ast check") } DataType.UWORD -> when(sourceDt) { DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_UW) @@ -2206,7 +2206,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, DataType.UWORD -> {} DataType.WORD -> prog.instr(Opcode.CAST_W_TO_UW) DataType.FLOAT -> prog.instr(Opcode.CAST_F_TO_UW) - else -> throw CompilerException("invalid cast type $sourceDt") + else -> throw CompilerException("invalid cast $sourceDt to ${expr.type} -- should be an Ast check") } DataType.WORD -> when(sourceDt) { DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_W) @@ -2214,7 +2214,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, DataType.UWORD -> prog.instr(Opcode.CAST_UW_TO_W) DataType.WORD -> {} DataType.FLOAT -> prog.instr(Opcode.CAST_F_TO_W) - else -> throw CompilerException("invalid cast type $sourceDt") + else -> throw CompilerException("invalid cast $sourceDt to ${expr.type} -- should be an Ast check") } DataType.FLOAT -> when(sourceDt) { DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_F) @@ -2222,9 +2222,9 @@ private class StatementTranslator(private val prog: IntermediateProgram, DataType.UWORD -> prog.instr(Opcode.CAST_UW_TO_F) DataType.WORD -> prog.instr(Opcode.CAST_W_TO_F) DataType.FLOAT -> {} - else -> throw CompilerException("invalid cast type $sourceDt") + else -> throw CompilerException("invalid cast $sourceDt to ${expr.type} -- should be an Ast check") } - else -> throw CompilerException("can't typecast to ${expr.type}") + else -> throw CompilerException("invalid cast $sourceDt to ${expr.type} -- should be an Ast check") } } diff --git a/compiler/src/prog8/compiler/intermediate/Value.kt b/compiler/src/prog8/compiler/intermediate/Value.kt index 50c533bce..69664233a 100644 --- a/compiler/src/prog8/compiler/intermediate/Value.kt +++ b/compiler/src/prog8/compiler/intermediate/Value.kt @@ -3,7 +3,6 @@ package prog8.compiler.intermediate import prog8.ast.* import java.lang.Exception import kotlin.math.abs -import kotlin.math.floor import kotlin.math.pow @@ -414,7 +413,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) { DataType.UWORD -> Value(DataType.UWORD, numericValue()) DataType.WORD -> Value(DataType.WORD, numericValue()) DataType.FLOAT -> Value(DataType.FLOAT, numericValue()) - else -> TODO("invalid type cast from $type to $targetType - should be an ast-check") + else -> throw ValueException("invalid type cast from $type to $targetType") } } DataType.BYTE -> { @@ -424,7 +423,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) { DataType.UWORD -> Value(DataType.UWORD, integerValue() and 65535) DataType.WORD -> Value(DataType.WORD, integerValue()) DataType.FLOAT -> Value(DataType.FLOAT, numericValue()) - else -> TODO("invalid type cast from $type to $targetType - should be an ast-check") + else -> throw ValueException("invalid type cast from $type to $targetType") } } DataType.UWORD -> { @@ -438,7 +437,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) { Value(DataType.WORD, -(65536-integerValue())) } DataType.FLOAT -> Value(DataType.FLOAT, numericValue()) - else -> TODO("invalid type cast from $type to $targetType - should be an ast-check") + else -> throw ValueException("invalid type cast from $type to $targetType") } } DataType.WORD -> { @@ -447,7 +446,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) { DataType.UWORD -> Value(DataType.UWORD, integerValue() and 65535) DataType.WORD -> this DataType.FLOAT -> Value(DataType.FLOAT, numericValue()) - else -> TODO("invalid type cast from $type to $targetType - should be an ast-check") + else -> throw ValueException("invalid type cast from $type to $targetType") } } DataType.FLOAT -> { @@ -457,7 +456,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) { if(integer in -128..127) Value(DataType.BYTE, integer) else - TODO("overflow when casting float to byte: $this - should be an ast-check") + throw ValueException("overflow when casting float to byte: $this") } DataType.UBYTE -> Value(DataType.UBYTE, numericValue().toInt() and 255) DataType.UWORD -> Value(DataType.UWORD, numericValue().toInt() and 65535) @@ -466,13 +465,13 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) { if(integer in -32768..32767) Value(DataType.WORD, integer) else - TODO("overflow when casting float to word: $this - should be an ast-check") + throw ValueException("overflow when casting float to word: $this") } DataType.FLOAT -> this - else -> TODO("invalid type cast from $type to $targetType - should be an ast-check") + else -> throw ValueException("invalid type cast from $type to $targetType") } } - else -> TODO("invalid type cast from $type to $targetType - should be an ast-check") + else -> throw ValueException("invalid type cast from $type to $targetType") } } diff --git a/examples/test.p8 b/examples/test.p8 index 8d36f0023..cbd1f104a 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,80 +5,39 @@ sub start() { - while(true) - A++ + ubyte ub + byte b + word w + uword uw - repeat A++ until(false) + ubyte[2] uba + byte[2] ba + word[2] wa + uword[2] uwa + str s + str_p sp + str_s ss + str_ps sps + + s = ub as str + sp = ub as str_p + ss = ub as str_s + sps = ub as str_ps + s = b as str + sp = b as str_p + ss = b as str_s + sps = b as str_ps + s = w as str + sp = w as str_p + ss = w as str_s + sps = w as str_ps + s = uw as str + sp = uw as str_p + ss = uw as str_s + sps = uw as str_ps - for ubyte i in 0 to 10 - A++ - - -; c64scr.print_ub(c64utils.str2ubyte("1")) -; c64.CHROUT('\n') -; c64scr.print_ub(c64utils.str2ubyte("12")) -; c64.CHROUT('\n') -; c64scr.print_ub(c64utils.str2ubyte("123")) -; c64.CHROUT('\n') -; c64scr.print_ub(c64utils.str2ubyte("1234")) -; c64.CHROUT('\n') -; c64scr.print_ub(c64utils.str2ubyte("12xyz")) -; c64.CHROUT('\n') -; c64.CHROUT('\n') -; -; c64scr.print_ub(c64utils.str2ubyte("19")) -; c64.CHROUT('\n') -; c64scr.print_ub(c64utils.str2ubyte("199")) -; c64.CHROUT('\n') -; c64scr.print_ub(c64utils.str2ubyte("29")) -; c64.CHROUT('\n') -; c64scr.print_ub(c64utils.str2ubyte("99xyz")) -; c64.CHROUT('\n') -; c64scr.print_ub(c64utils.str2ubyte("199xyz")) -; c64.CHROUT('\n') -; c64.CHROUT('\n') - - c64scr.print_b(c64utils.str2byte("1")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("12")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("123")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("1234")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2ubyte("12xyz")) - c64.CHROUT('\n') - c64.CHROUT('\n') - - c64scr.print_b(c64utils.str2byte("19")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("29")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("199")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("299")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2ubyte("99zzxyz")) - c64.CHROUT('\n') - c64.CHROUT('\n') - - c64scr.print_b(c64utils.str2byte("-9")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("-99")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("-199")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("-1111")) - c64.CHROUT('\n') - c64scr.print_b(c64utils.str2byte("-12xyz")) - c64.CHROUT('\n') - - } - - sub foo(ubyte param1, ubyte param2) { - ubyte local1 } }