various fixes

print_f() no longer prints a leading space.
Better error message if using float in for loop.
Fix crash when using non-const as when choice value.
VM print_f() more closely resembles the CBM version.
This commit is contained in:
Irmen de Jong 2023-12-02 12:36:49 +01:00
parent 88a1aa4f3d
commit 1509de390e
8 changed files with 53 additions and 55 deletions

View File

@ -2,7 +2,6 @@ package prog8.optimizer
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.base.FatalAstException
import prog8.ast.expressions.*
import prog8.ast.maySwapOperandOrder
import prog8.ast.statements.ForLoop
@ -389,7 +388,7 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop))
}
}
else -> throw FatalAstException("invalid loopvar datatype $loopvar")
else -> { /* nothing for floats, these are not allowed in for loops and will give an error elsewhere */ }
}
return noModifications

View File

@ -3,7 +3,7 @@ floats {
%option merge, no_symbol_prefixing
sub print_f(float value) {
; ---- prints the floating point value (without a newline).
; ---- prints the floating point value (without a newline). No leading space (unlike BASIC)!
%asm {{
lda #<value
ldy #>value
@ -12,10 +12,13 @@ sub print_f(float value) {
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy #0
- lda (P8ZP_SCRATCH_W1),y
lda (P8ZP_SCRATCH_W1),y
cmp #' '
beq +
- lda (P8ZP_SCRATCH_W1),y
beq ++
jsr cbm.CHROUT
iny
+ iny
bne -
+ rts
}}

View File

@ -1348,7 +1348,7 @@ internal class AstChecker(private val program: Program,
if(choices!=null) {
for (c in choices) {
if(c in tally)
errors.err("choice value already occurs earlier", choiceNode.position)
errors.err("choice value already occurs elsewhere", choiceNode.position)
else
tally.add(c)
}
@ -1368,18 +1368,18 @@ internal class AstChecker(private val program: Program,
val whenStmt = whenChoice.parent as When
if(whenChoice.values!=null) {
val conditionType = whenStmt.condition.inferType(program)
val constvalues = whenChoice.values!!.map { it.constValue(program) }
for(constvalue in constvalues) {
val constvalues = whenChoice.values!!.map { it.constValue(program) to it.position }
for((constvalue, pos) in constvalues) {
when {
constvalue == null -> errors.err("choice value must be a constant", whenChoice.position)
constvalue.type !in IntegerDatatypes -> errors.err("choice value must be a byte or word", whenChoice.position)
constvalue == null -> errors.err("choice value must be a constant", pos)
constvalue.type !in IntegerDatatypes -> errors.err("choice value must be a byte or word", pos)
conditionType isnot constvalue.type -> {
if(conditionType.isKnown) {
if(conditionType.istype(DataType.BOOL)) {
if(constvalue.number!=0.0 && constvalue.number!=1.0)
errors.err("choice value datatype differs from condition value", whenChoice.position)
errors.err("choice value datatype differs from condition value", pos)
} else {
errors.err("choice value datatype differs from condition value", whenChoice.position)
errors.err("choice value datatype differs from condition value", pos)
}
}
}

View File

@ -191,11 +191,6 @@ internal class StatementReorderer(
errors.err("else choice must be the last one", whenStmt.choices[elseChoice].position)
}
val choices = whenStmt.choiceValues(program).sortedBy {
it.first?.first() ?: Int.MAX_VALUE
}
whenStmt.choices.clear()
choices.mapTo(whenStmt.choices) { it.second }
return noModifications
}

View File

@ -364,34 +364,17 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
override fun after(whenChoice: WhenChoice, parent: Node): Iterable<IAstModification> {
val conditionDt = (whenChoice.parent as When).condition.inferType(program)
if((parent as When).condition.inferType(program).isWords) {
val values = whenChoice.values
values?.toTypedArray()?.withIndex()?.forEach { (index, value) ->
val valueDt = value.inferType(program)
if(valueDt!=conditionDt) {
val castedValue = (value as NumericLiteral).cast(conditionDt.getOr(DataType.UNDEFINED))
if(castedValue.isValid) {
values[index] = castedValue.valueOrZero()
} else {
errors.err("choice value datatype differs from condition value", value.position)
}
}
}
} else {
val values = whenChoice.values
values?.toTypedArray()?.withIndex()?.forEach { (index, value) ->
val valueDt = value.inferType(program)
if(valueDt!=conditionDt) {
val castedValue = (value as NumericLiteral).cast(conditionDt.getOr(DataType.UNDEFINED))
if(castedValue.isValid) {
values[index] = castedValue.valueOrZero()
} else {
errors.err("choice value datatype differs from condition value", value.position)
}
val values = whenChoice.values
values?.toTypedArray()?.withIndex()?.forEach { (index, value) ->
val valueDt = value.inferType(program)
if(valueDt!=conditionDt) {
val castedValue = value.typecastTo(conditionDt.getOr(DataType.UNDEFINED), valueDt.getOr(DataType.UNDEFINED), true)
if(castedValue.first) {
castedValue.second.linkParents(whenChoice)
values[index] = castedValue.second
}
}
}
return noModifications
}

View File

@ -2,7 +2,6 @@
TODO
====
- don't print the leading space in print_f()
- uword scanline_buf = memory("scanline", 320, 0) different result when inside a sub or outside a sub??! (imageviewer iff module)
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
- once VAL_1 is merged into the kernal properly, remove all the workarounds in cx16 floats.parse_f()

View File

@ -1,21 +1,40 @@
%import textio
%import floats
%zeropage basicsafe
%import floats
%import textio
%option no_sysinit
main {
sub start() {
ubyte uw = 97
txt.print_ub( 10 * (uw/10) ) ; 90
floats.print_f(0.0)
txt.nl()
txt.print_ub( (uw/10) * 10 ) ; 90
floats.print_f(1.0)
txt.nl()
floats.print_f(11111.0)
txt.nl()
floats.print_f(1e10)
txt.nl()
floats.print_f(1.234)
txt.nl()
floats.print_f(111.234)
txt.nl()
floats.print_f(-111.234)
txt.nl()
floats.print_f(-111.234)
txt.nl()
float fl = 999.876
floats.print_f( 10 * (fl/10) ) ; 999.876
txt.nl()
floats.print_f( (fl/10) * 10 ) ; 999.876
txt.nl()
uword zz
const ubyte check = 99
when zz {
1,2,check -> {
cx16.r0++
}
9999 -> {
cx16.r0++
}
else -> {
cx16.r0++
}
}
}
}

View File

@ -348,8 +348,8 @@ object SysCalls {
}
Syscall.PRINT_F -> {
val value = getArgValues(callspec.arguments, vm).single() as Double
if(value==0.0)
print("0")
if(value.toInt().toDouble()==value)
print(value.toInt())
else
print(value)
}