mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
better error message when attempting to cast a float to integer
This commit is contained in:
parent
b24df31c2b
commit
a8be94de6b
@ -3,7 +3,7 @@ package prog8.code.ast
|
|||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.round
|
import kotlin.math.truncate
|
||||||
|
|
||||||
|
|
||||||
sealed class PtExpression(val type: DataType, position: Position) : PtNode(position) {
|
sealed class PtExpression(val type: DataType, position: Position) : PtNode(position) {
|
||||||
@ -227,9 +227,9 @@ class PtNumber(type: DataType, val number: Double, position: Position) : PtExpre
|
|||||||
if(type==DataType.BOOL)
|
if(type==DataType.BOOL)
|
||||||
throw IllegalArgumentException("bool should have become ubyte @$position")
|
throw IllegalArgumentException("bool should have become ubyte @$position")
|
||||||
if(type!=DataType.FLOAT) {
|
if(type!=DataType.FLOAT) {
|
||||||
val rounded = round(number)
|
val trunc = truncate(number)
|
||||||
if (rounded != number)
|
if (trunc != number)
|
||||||
throw IllegalArgumentException("refused rounding of float to avoid loss of precision @$position")
|
throw IllegalArgumentException("refused truncating of float to avoid loss of precision @$position")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class VarConstantValueTypeAdjuster(private val program: Program, private val err
|
|||||||
&& declConstValue.type != decl.datatype) {
|
&& declConstValue.type != decl.datatype) {
|
||||||
// avoid silent float roundings
|
// avoid silent float roundings
|
||||||
if(decl.datatype in IntegerDatatypes && declConstValue.type == DataType.FLOAT) {
|
if(decl.datatype in IntegerDatatypes && declConstValue.type == DataType.FLOAT) {
|
||||||
errors.err("refused rounding of float to avoid loss of precision", decl.value!!.position)
|
errors.err("refused truncating of float to avoid loss of precision", decl.value!!.position)
|
||||||
} else {
|
} else {
|
||||||
// cast the numeric literal to the appropriate datatype of the variable
|
// cast the numeric literal to the appropriate datatype of the variable
|
||||||
declConstValue.linkParents(decl)
|
declConstValue.linkParents(decl)
|
||||||
|
@ -652,7 +652,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
if(decl.type==VarDeclType.CONST) {
|
if(decl.type==VarDeclType.CONST) {
|
||||||
err("const declaration needs a compile-time constant initializer value, or range")
|
err("const declaration needs a compile-time constant initializer value")
|
||||||
super.visit(decl)
|
super.visit(decl)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1069,8 +1069,12 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(!typecast.expression.inferType(program).isKnown)
|
if(!typecast.expression.inferType(program).isKnown)
|
||||||
errors.err("this expression doesn't return a value", typecast.expression.position)
|
errors.err("this expression doesn't return a value", typecast.expression.position)
|
||||||
|
|
||||||
if(typecast.expression is NumericLiteral)
|
if(typecast.expression is NumericLiteral) {
|
||||||
errors.err("can't cast the value to the requested target type", typecast.expression.position)
|
val castResult = (typecast.expression as NumericLiteral).cast(typecast.type)
|
||||||
|
if(castResult.isValid)
|
||||||
|
throw FatalAstException("cast should have been performed in const eval already")
|
||||||
|
errors.err(castResult.whyFailed!!, typecast.expression.position)
|
||||||
|
}
|
||||||
|
|
||||||
super.visit(typecast)
|
super.visit(typecast)
|
||||||
}
|
}
|
||||||
|
@ -35,16 +35,16 @@ class TestNumericLiteral: FunSpec({
|
|||||||
sameValueAndType(NumericLiteral(DataType.UWORD, 12345.0, dummyPos), NumericLiteral(DataType.UWORD, 12345.0, dummyPos)) shouldBe true
|
sameValueAndType(NumericLiteral(DataType.UWORD, 12345.0, dummyPos), NumericLiteral(DataType.UWORD, 12345.0, dummyPos)) shouldBe true
|
||||||
}
|
}
|
||||||
|
|
||||||
test("test rounding") {
|
test("test truncating") {
|
||||||
shouldThrow<ExpressionError> {
|
shouldThrow<ExpressionError> {
|
||||||
NumericLiteral(DataType.BYTE, -2.345, dummyPos)
|
NumericLiteral(DataType.BYTE, -2.345, dummyPos)
|
||||||
}.message shouldContain "refused rounding"
|
}.message shouldContain "refused truncating"
|
||||||
shouldThrow<ExpressionError> {
|
shouldThrow<ExpressionError> {
|
||||||
NumericLiteral(DataType.BYTE, -2.6, dummyPos)
|
NumericLiteral(DataType.BYTE, -2.6, dummyPos)
|
||||||
}.message shouldContain "refused rounding"
|
}.message shouldContain "refused truncating"
|
||||||
shouldThrow<ExpressionError> {
|
shouldThrow<ExpressionError> {
|
||||||
NumericLiteral(DataType.UWORD, 2222.345, dummyPos)
|
NumericLiteral(DataType.UWORD, 2222.345, dummyPos)
|
||||||
}.message shouldContain "refused rounding"
|
}.message shouldContain "refused truncating"
|
||||||
NumericLiteral(DataType.UBYTE, 2.0, dummyPos).number shouldBe 2.0
|
NumericLiteral(DataType.UBYTE, 2.0, dummyPos).number shouldBe 2.0
|
||||||
NumericLiteral(DataType.BYTE, -2.0, dummyPos).number shouldBe -2.0
|
NumericLiteral(DataType.BYTE, -2.0, dummyPos).number shouldBe -2.0
|
||||||
NumericLiteral(DataType.UWORD, 2222.0, dummyPos).number shouldBe 2222.0
|
NumericLiteral(DataType.UWORD, 2222.0, dummyPos).number shouldBe 2222.0
|
||||||
|
@ -541,7 +541,7 @@ class TestOptimization: FunSpec({
|
|||||||
val errors = ErrorReporterForTests()
|
val errors = ErrorReporterForTests()
|
||||||
compileText(C64Target(), optimize=false, src, writeAssembly=false, errors = errors) shouldBe null
|
compileText(C64Target(), optimize=false, src, writeAssembly=false, errors = errors) shouldBe null
|
||||||
errors.errors.size shouldBe 1
|
errors.errors.size shouldBe 1
|
||||||
errors.errors[0] shouldContain "can't cast"
|
errors.errors[0] shouldContain "no cast"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("test augmented expression asmgen") {
|
test("test augmented expression asmgen") {
|
||||||
|
@ -33,16 +33,16 @@ class TestPtNumber: FunSpec({
|
|||||||
sameValueAndType(PtNumber(DataType.UWORD, 12345.0, dummyPos), PtNumber(DataType.UWORD, 12345.0, dummyPos)) shouldBe true
|
sameValueAndType(PtNumber(DataType.UWORD, 12345.0, dummyPos), PtNumber(DataType.UWORD, 12345.0, dummyPos)) shouldBe true
|
||||||
}
|
}
|
||||||
|
|
||||||
test("test rounding") {
|
test("test truncating") {
|
||||||
shouldThrow<IllegalArgumentException> {
|
shouldThrow<IllegalArgumentException> {
|
||||||
PtNumber(DataType.BYTE, -2.345, dummyPos)
|
PtNumber(DataType.BYTE, -2.345, dummyPos)
|
||||||
}.message shouldContain "refused rounding"
|
}.message shouldContain "refused truncating"
|
||||||
shouldThrow<IllegalArgumentException> {
|
shouldThrow<IllegalArgumentException> {
|
||||||
PtNumber(DataType.BYTE, -2.6, dummyPos)
|
PtNumber(DataType.BYTE, -2.6, dummyPos)
|
||||||
}.message shouldContain "refused rounding"
|
}.message shouldContain "refused truncating"
|
||||||
shouldThrow<IllegalArgumentException> {
|
shouldThrow<IllegalArgumentException> {
|
||||||
PtNumber(DataType.UWORD, 2222.345, dummyPos)
|
PtNumber(DataType.UWORD, 2222.345, dummyPos)
|
||||||
}.message shouldContain "refused rounding"
|
}.message shouldContain "refused truncating"
|
||||||
PtNumber(DataType.UBYTE, 2.0, dummyPos).number shouldBe 2.0
|
PtNumber(DataType.UBYTE, 2.0, dummyPos).number shouldBe 2.0
|
||||||
PtNumber(DataType.BYTE, -2.0, dummyPos).number shouldBe -2.0
|
PtNumber(DataType.BYTE, -2.0, dummyPos).number shouldBe -2.0
|
||||||
PtNumber(DataType.UWORD, 2222.0, dummyPos).number shouldBe 2222.0
|
PtNumber(DataType.UWORD, 2222.0, dummyPos).number shouldBe 2222.0
|
||||||
|
@ -762,11 +762,11 @@ main {
|
|||||||
val errors = ErrorReporterForTests()
|
val errors = ErrorReporterForTests()
|
||||||
compileText(C64Target(), false, text, writeAssembly = true, errors=errors) shouldBe null
|
compileText(C64Target(), false, text, writeAssembly = true, errors=errors) shouldBe null
|
||||||
errors.errors.size shouldBe 2
|
errors.errors.size shouldBe 2
|
||||||
errors.errors[0] shouldContain "can't cast"
|
errors.errors[0] shouldContain "no cast"
|
||||||
errors.errors[1] shouldContain "can't cast"
|
errors.errors[1] shouldContain "no cast"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("refuse to round float literal 1") {
|
test("refuse to truncate float literal 1") {
|
||||||
val text = """
|
val text = """
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
main {
|
main {
|
||||||
@ -778,11 +778,11 @@ main {
|
|||||||
val errors = ErrorReporterForTests()
|
val errors = ErrorReporterForTests()
|
||||||
compileText(C64Target(), false, text, errors=errors) shouldBe null
|
compileText(C64Target(), false, text, errors=errors) shouldBe null
|
||||||
errors.errors.size shouldBe 2
|
errors.errors.size shouldBe 2
|
||||||
errors.errors[0] shouldContain "can't cast"
|
errors.errors[0] shouldContain "refused"
|
||||||
errors.errors[1] shouldContain "can't cast"
|
errors.errors[1] shouldContain "refused"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("refuse to round float literal 2") {
|
test("refuse to truncate float literal 2") {
|
||||||
val text = """
|
val text = """
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
main {
|
main {
|
||||||
@ -798,7 +798,7 @@ main {
|
|||||||
errors.errors[0] shouldContain "in-place makes no sense"
|
errors.errors[0] shouldContain "in-place makes no sense"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("refuse to round float literal 3") {
|
test("refuse to truncate float literal 3") {
|
||||||
val text = """
|
val text = """
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
main {
|
main {
|
||||||
@ -811,8 +811,8 @@ main {
|
|||||||
val errors = ErrorReporterForTests()
|
val errors = ErrorReporterForTests()
|
||||||
compileText(C64Target(), false, text, errors=errors) shouldBe null
|
compileText(C64Target(), false, text, errors=errors) shouldBe null
|
||||||
errors.errors.size shouldBe 2
|
errors.errors.size shouldBe 2
|
||||||
errors.errors[0] shouldContain "can't cast"
|
errors.errors[0] shouldContain "refused"
|
||||||
errors.errors[1] shouldContain "can't cast"
|
errors.errors[1] shouldContain "refused"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("correct implicit casts of signed number comparison and logical expressions") {
|
test("correct implicit casts of signed number comparison and logical expressions") {
|
||||||
@ -1063,7 +1063,7 @@ main {
|
|||||||
val errors=ErrorReporterForTests()
|
val errors=ErrorReporterForTests()
|
||||||
compileText(C64Target(), false, src, writeAssembly = false, errors=errors) shouldBe null
|
compileText(C64Target(), false, src, writeAssembly = false, errors=errors) shouldBe null
|
||||||
errors.errors.size shouldBe 5
|
errors.errors.size shouldBe 5
|
||||||
errors.errors[0] shouldContain "can't cast"
|
errors.errors[0] shouldContain "no cast"
|
||||||
errors.errors[1] shouldContain "overflow"
|
errors.errors[1] shouldContain "overflow"
|
||||||
errors.errors[2] shouldContain "LONG doesn't match"
|
errors.errors[2] shouldContain "LONG doesn't match"
|
||||||
errors.errors[3] shouldContain "out of range"
|
errors.errors[3] shouldContain "out of range"
|
||||||
|
@ -13,7 +13,7 @@ import prog8.code.core.*
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
import kotlin.math.round
|
import kotlin.math.truncate
|
||||||
|
|
||||||
|
|
||||||
sealed class Expression: Node {
|
sealed class Expression: Node {
|
||||||
@ -447,10 +447,10 @@ class NumericLiteral(val type: DataType, // only numerical types allowed
|
|||||||
if(type==DataType.FLOAT)
|
if(type==DataType.FLOAT)
|
||||||
numbervalue
|
numbervalue
|
||||||
else {
|
else {
|
||||||
val rounded = round(numbervalue)
|
val trunc = truncate(numbervalue)
|
||||||
if(rounded != numbervalue)
|
if(trunc != numbervalue)
|
||||||
throw ExpressionError("refused rounding of float to avoid loss of precision", position)
|
throw ExpressionError("refused truncating of float to avoid loss of precision", position)
|
||||||
rounded
|
trunc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,7 +540,7 @@ class NumericLiteral(val type: DataType, // only numerical types allowed
|
|||||||
|
|
||||||
operator fun compareTo(other: NumericLiteral): Int = number.compareTo(other.number)
|
operator fun compareTo(other: NumericLiteral): Int = number.compareTo(other.number)
|
||||||
|
|
||||||
class CastValue(val isValid: Boolean, private val value: NumericLiteral?) {
|
class CastValue(val isValid: Boolean, val whyFailed: String?, private val value: NumericLiteral?) {
|
||||||
fun valueOrZero() = if(isValid) value!! else NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
fun valueOrZero() = if(isValid) value!! else NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||||
fun linkParent(parent: Node) {
|
fun linkParent(parent: Node) {
|
||||||
value?.linkParents(parent)
|
value?.linkParents(parent)
|
||||||
@ -555,122 +555,122 @@ class NumericLiteral(val type: DataType, // only numerical types allowed
|
|||||||
|
|
||||||
private fun internalCast(targettype: DataType): CastValue {
|
private fun internalCast(targettype: DataType): CastValue {
|
||||||
if(type==targettype)
|
if(type==targettype)
|
||||||
return CastValue(true, this)
|
return CastValue(true, null, this)
|
||||||
when(type) {
|
when(type) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
if(targettype== DataType.BYTE && number <= 127)
|
if(targettype== DataType.BYTE && number <= 127)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype== DataType.WORD || targettype== DataType.UWORD)
|
if(targettype== DataType.WORD || targettype== DataType.UWORD)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype== DataType.FLOAT)
|
if(targettype== DataType.FLOAT)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.LONG)
|
if(targettype==DataType.LONG)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, fromBoolean(number!=0.0, position))
|
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
||||||
}
|
}
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
if(targettype== DataType.UBYTE) {
|
if(targettype== DataType.UBYTE) {
|
||||||
if(number in -128.0..0.0)
|
if(number in -128.0..0.0)
|
||||||
return CastValue(true, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
|
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
|
||||||
else if(number in 0.0..255.0)
|
else if(number in 0.0..255.0)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
if(targettype== DataType.UWORD) {
|
if(targettype== DataType.UWORD) {
|
||||||
if(number in -32768.0..0.0)
|
if(number in -32768.0..0.0)
|
||||||
return CastValue(true, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position))
|
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position))
|
||||||
else if(number in 0.0..65535.0)
|
else if(number in 0.0..65535.0)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
if(targettype== DataType.WORD)
|
if(targettype== DataType.WORD)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype== DataType.FLOAT)
|
if(targettype== DataType.FLOAT)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, fromBoolean(number!=0.0, position))
|
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
||||||
if(targettype==DataType.LONG)
|
if(targettype==DataType.LONG)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
DataType.UWORD -> {
|
DataType.UWORD -> {
|
||||||
if(targettype== DataType.BYTE && number <= 127)
|
if(targettype== DataType.BYTE && number <= 127)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype== DataType.UBYTE && number <= 255)
|
if(targettype== DataType.UBYTE && number <= 255)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype== DataType.WORD && number <= 32767)
|
if(targettype== DataType.WORD && number <= 32767)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype== DataType.FLOAT)
|
if(targettype== DataType.FLOAT)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, fromBoolean(number!=0.0, position))
|
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
||||||
if(targettype==DataType.LONG)
|
if(targettype==DataType.LONG)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
if(targettype== DataType.BYTE && number >= -128 && number <=127)
|
if(targettype== DataType.BYTE && number >= -128 && number <=127)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype== DataType.UBYTE) {
|
if(targettype== DataType.UBYTE) {
|
||||||
if(number in -128.0..0.0)
|
if(number in -128.0..0.0)
|
||||||
return CastValue(true, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
|
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
|
||||||
else if(number in 0.0..255.0)
|
else if(number in 0.0..255.0)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
if(targettype== DataType.UWORD) {
|
if(targettype== DataType.UWORD) {
|
||||||
if(number in -32768.0 .. 0.0)
|
if(number in -32768.0 .. 0.0)
|
||||||
return CastValue(true, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position))
|
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position))
|
||||||
else if(number in 0.0..65535.0)
|
else if(number in 0.0..65535.0)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
if(targettype== DataType.FLOAT)
|
if(targettype== DataType.FLOAT)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, fromBoolean(number!=0.0, position))
|
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
||||||
if(targettype==DataType.LONG)
|
if(targettype==DataType.LONG)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
try {
|
try {
|
||||||
if (targettype == DataType.BYTE && number >= -128 && number <= 127)
|
if (targettype == DataType.BYTE && number >= -128 && number <= 127)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.UBYTE && number >= 0 && number <= 255)
|
if (targettype == DataType.UBYTE && number >= 0 && number <= 255)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.WORD && number >= -32768 && number <= 32767)
|
if (targettype == DataType.WORD && number >= -32768 && number <= 32767)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.UWORD && number >= 0 && number <= 65535)
|
if (targettype == DataType.UWORD && number >= 0 && number <= 65535)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.LONG && number >=0 && number <= 2147483647)
|
if(targettype==DataType.LONG && number >=0 && number <= 2147483647)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, fromBoolean(number!=0.0, position))
|
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
||||||
} catch (x: ExpressionError) {
|
} catch (x: ExpressionError) {
|
||||||
return CastValue(false, null)
|
return CastValue(false, x.message,null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.BOOL -> {
|
DataType.BOOL -> {
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
DataType.LONG -> {
|
DataType.LONG -> {
|
||||||
try {
|
try {
|
||||||
if (targettype == DataType.BYTE && number >= -128 && number <= 127)
|
if (targettype == DataType.BYTE && number >= -128 && number <= 127)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.UBYTE && number >= 0 && number <= 255)
|
if (targettype == DataType.UBYTE && number >= 0 && number <= 255)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.WORD && number >= -32768 && number <= 32767)
|
if (targettype == DataType.WORD && number >= -32768 && number <= 32767)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.UWORD && number >= 0 && number <= 65535)
|
if (targettype == DataType.UWORD && number >= 0 && number <= 65535)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, fromBoolean(number!=0.0, position))
|
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
||||||
if(targettype== DataType.FLOAT)
|
if(targettype== DataType.FLOAT)
|
||||||
return CastValue(true, NumericLiteral(targettype, number, position))
|
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
||||||
} catch (x: ExpressionError) {
|
} catch (x: ExpressionError) {
|
||||||
return CastValue(false, null)
|
return CastValue(false, x.message, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw FatalAstException("type cast of weird type $type")
|
throw FatalAstException("type cast of weird type $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CastValue(false, null)
|
return CastValue(false, "no cast available between these types", null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ For instance ``%1001_0001`` is a valid binary number and ``3_000_000.99`` is a v
|
|||||||
Data type conversion
|
Data type conversion
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
Many type conversions are possible by just writing ``as <type>`` at the end of an expression,
|
Many type conversions are possible by just writing ``as <type>`` at the end of an expression,
|
||||||
for example ``ubyte ub = floatvalue as ubyte`` will convert the floating point value to an unsigned byte.
|
for example ``word ww = bytevalue as word`` will convert the byte value to a signed word.
|
||||||
|
|
||||||
|
|
||||||
Memory mapped variables
|
Memory mapped variables
|
||||||
|
@ -4,6 +4,8 @@ TODO
|
|||||||
|
|
||||||
- merge branch optimize-st for some optimizations regarding SymbolTable use
|
- merge branch optimize-st for some optimizations regarding SymbolTable use
|
||||||
|
|
||||||
|
- fix that pesky unit test that puts temp files in the compiler directory
|
||||||
|
|
||||||
- [on branch: call-pointers] allow calling a subroutine via a pointer variable (indirect JSR, optimized form of callfar())
|
- [on branch: call-pointers] allow calling a subroutine via a pointer variable (indirect JSR, optimized form of callfar())
|
||||||
modify programs (shell, paint) that now use callfar
|
modify programs (shell, paint) that now use callfar
|
||||||
|
|
||||||
|
@ -1,53 +1,13 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%import string
|
%import floats
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
bool @shared statusc = test_carry_set()
|
const uword vera_freq = (136.5811 / 0.3725290298461914) as uword
|
||||||
bool @shared statusv = test_v_set()
|
const uword v_f_10 = (136.5811 / 0.3725290298461914 + 0.5) as uword
|
||||||
bool @shared statusz = test_z_set()
|
|
||||||
bool @shared statusn = test_n_set()
|
|
||||||
|
|
||||||
if test_carry_set() {
|
txt.print_uw(v_f_10)
|
||||||
txt.print("set!\n")
|
txt.print_uw(vera_freq)
|
||||||
}
|
|
||||||
if test_v_set() {
|
|
||||||
txt.print("set!\n")
|
|
||||||
}
|
|
||||||
if test_z_set() {
|
|
||||||
txt.print("set!\n")
|
|
||||||
}
|
|
||||||
if test_n_set() {
|
|
||||||
txt.print("set!\n")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
asmsub test_carry_set() -> bool @Pc {
|
|
||||||
%asm {{
|
|
||||||
sec
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
asmsub test_v_set() -> bool @Pv {
|
|
||||||
%asm {{
|
|
||||||
sec
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
asmsub test_z_set() -> bool @Pz {
|
|
||||||
%asm {{
|
|
||||||
sec
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
asmsub test_n_set() -> bool @Pn {
|
|
||||||
%asm {{
|
|
||||||
sec
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user