mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
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:
parent
88a1aa4f3d
commit
1509de390e
@ -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
|
||||
|
@ -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
|
||||
}}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user