mirror of
https://github.com/irmen/prog8.git
synced 2024-10-25 00:24:16 +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.Node
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.FatalAstException
|
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.maySwapOperandOrder
|
import prog8.ast.maySwapOperandOrder
|
||||||
import prog8.ast.statements.ForLoop
|
import prog8.ast.statements.ForLoop
|
||||||
@ -389,7 +388,7 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
|
|||||||
return listOf(IAstModification.ReplaceNode(forLoop.iterable, newIter, forLoop))
|
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
|
return noModifications
|
||||||
|
@ -3,7 +3,7 @@ floats {
|
|||||||
%option merge, no_symbol_prefixing
|
%option merge, no_symbol_prefixing
|
||||||
|
|
||||||
sub print_f(float value) {
|
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 {{
|
%asm {{
|
||||||
lda #<value
|
lda #<value
|
||||||
ldy #>value
|
ldy #>value
|
||||||
@ -12,10 +12,13 @@ sub print_f(float value) {
|
|||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_W1+1
|
sty P8ZP_SCRATCH_W1+1
|
||||||
ldy #0
|
ldy #0
|
||||||
- lda (P8ZP_SCRATCH_W1),y
|
lda (P8ZP_SCRATCH_W1),y
|
||||||
|
cmp #' '
|
||||||
beq +
|
beq +
|
||||||
|
- lda (P8ZP_SCRATCH_W1),y
|
||||||
|
beq ++
|
||||||
jsr cbm.CHROUT
|
jsr cbm.CHROUT
|
||||||
iny
|
+ iny
|
||||||
bne -
|
bne -
|
||||||
+ rts
|
+ rts
|
||||||
}}
|
}}
|
||||||
|
@ -1348,7 +1348,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(choices!=null) {
|
if(choices!=null) {
|
||||||
for (c in choices) {
|
for (c in choices) {
|
||||||
if(c in tally)
|
if(c in tally)
|
||||||
errors.err("choice value already occurs earlier", choiceNode.position)
|
errors.err("choice value already occurs elsewhere", choiceNode.position)
|
||||||
else
|
else
|
||||||
tally.add(c)
|
tally.add(c)
|
||||||
}
|
}
|
||||||
@ -1368,18 +1368,18 @@ internal class AstChecker(private val program: Program,
|
|||||||
val whenStmt = whenChoice.parent as When
|
val whenStmt = whenChoice.parent as When
|
||||||
if(whenChoice.values!=null) {
|
if(whenChoice.values!=null) {
|
||||||
val conditionType = whenStmt.condition.inferType(program)
|
val conditionType = whenStmt.condition.inferType(program)
|
||||||
val constvalues = whenChoice.values!!.map { it.constValue(program) }
|
val constvalues = whenChoice.values!!.map { it.constValue(program) to it.position }
|
||||||
for(constvalue in constvalues) {
|
for((constvalue, pos) in constvalues) {
|
||||||
when {
|
when {
|
||||||
constvalue == null -> errors.err("choice value must be a constant", 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", whenChoice.position)
|
constvalue.type !in IntegerDatatypes -> errors.err("choice value must be a byte or word", pos)
|
||||||
conditionType isnot constvalue.type -> {
|
conditionType isnot constvalue.type -> {
|
||||||
if(conditionType.isKnown) {
|
if(conditionType.isKnown) {
|
||||||
if(conditionType.istype(DataType.BOOL)) {
|
if(conditionType.istype(DataType.BOOL)) {
|
||||||
if(constvalue.number!=0.0 && constvalue.number!=1.0)
|
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 {
|
} 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)
|
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
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,34 +364,17 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
|||||||
|
|
||||||
override fun after(whenChoice: WhenChoice, parent: Node): Iterable<IAstModification> {
|
override fun after(whenChoice: WhenChoice, parent: Node): Iterable<IAstModification> {
|
||||||
val conditionDt = (whenChoice.parent as When).condition.inferType(program)
|
val conditionDt = (whenChoice.parent as When).condition.inferType(program)
|
||||||
if((parent as When).condition.inferType(program).isWords) {
|
|
||||||
val values = whenChoice.values
|
val values = whenChoice.values
|
||||||
values?.toTypedArray()?.withIndex()?.forEach { (index, value) ->
|
values?.toTypedArray()?.withIndex()?.forEach { (index, value) ->
|
||||||
val valueDt = value.inferType(program)
|
val valueDt = value.inferType(program)
|
||||||
if(valueDt!=conditionDt) {
|
if(valueDt!=conditionDt) {
|
||||||
val castedValue = (value as NumericLiteral).cast(conditionDt.getOr(DataType.UNDEFINED))
|
val castedValue = value.typecastTo(conditionDt.getOr(DataType.UNDEFINED), valueDt.getOr(DataType.UNDEFINED), true)
|
||||||
if(castedValue.isValid) {
|
if(castedValue.first) {
|
||||||
values[index] = castedValue.valueOrZero()
|
castedValue.second.linkParents(whenChoice)
|
||||||
} else {
|
values[index] = castedValue.second
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
TODO
|
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)
|
- 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 ....
|
- [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()
|
- 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
|
%zeropage basicsafe
|
||||||
|
%import floats
|
||||||
|
%import textio
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte uw = 97
|
floats.print_f(0.0)
|
||||||
txt.print_ub( 10 * (uw/10) ) ; 90
|
|
||||||
txt.nl()
|
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()
|
txt.nl()
|
||||||
|
|
||||||
float fl = 999.876
|
uword zz
|
||||||
floats.print_f( 10 * (fl/10) ) ; 999.876
|
const ubyte check = 99
|
||||||
txt.nl()
|
|
||||||
floats.print_f( (fl/10) * 10 ) ; 999.876
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
|
when zz {
|
||||||
|
1,2,check -> {
|
||||||
|
cx16.r0++
|
||||||
|
}
|
||||||
|
9999 -> {
|
||||||
|
cx16.r0++
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
cx16.r0++
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,8 +348,8 @@ object SysCalls {
|
|||||||
}
|
}
|
||||||
Syscall.PRINT_F -> {
|
Syscall.PRINT_F -> {
|
||||||
val value = getArgValues(callspec.arguments, vm).single() as Double
|
val value = getArgValues(callspec.arguments, vm).single() as Double
|
||||||
if(value==0.0)
|
if(value.toInt().toDouble()==value)
|
||||||
print("0")
|
print(value.toInt())
|
||||||
else
|
else
|
||||||
print(value)
|
print(value)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user