optimize assignment with literal value; const-convert value to target datatype literal if possible

This commit is contained in:
Irmen de Jong 2018-10-02 23:10:27 +02:00
parent 18c6165325
commit 34fb82969c
2 changed files with 54 additions and 43 deletions

View File

@ -1,53 +1,26 @@
%option enable_floats
~ main {
sub start() {
byte[10] barray1
byte[10] barray2 = 11
byte[10] barray3 = [1,2,3,4,5,6,7,8,9,255]
byte bvar = 128
word wvar = 128
float fvar = 128
word[10] warray1
word[10] warray2 = 112233
word[10] warray3 = [1,2000,3000,4,5,6,7,8,9, 65535]
byte[4,5] mvar1
byte[4,5] mvar2 = 22
byte[2,3] mvar3 = [1,2,3,4,5,6]
float[3] farray1
float[3] farray2 = 33.44
float[3] farray2b = 33
float[3] farray3 = [1,2,3]
float[3] farray4 = [1,2,35566]
float[3] farray5 = [1,2.22334,3.1415]
str name = "irmen"
byte i
word w
_vm_write_str(name)
_vm_write_char('\n')
name[2] = '@'
_vm_write_str(name)
_vm_write_char('\n')
for i in barray3 {
_vm_write_num(i)
_vm_write_char('\n')
}
for w in warray3 {
_vm_write_num(w)
_vm_write_char('\n')
}
for i in name {
_vm_write_num(i)
_vm_write_char('\n')
}
bvar = 1
bvar = 2.0
;bvar = 2.w ; @todo don't crash
wvar = 1 ; @todo optimize byte literal to word literal
wvar = 2.w
wvar = 2.0
wvar = bvar
fvar = 1 ; @todo optimize byte literal to float literal
fvar = 2.w ; @todo optimize word literal to float literal
fvar = 22.33
fvar = bvar
fvar = wvar
return

View File

@ -5,6 +5,7 @@ import prog8.compiler.HeapValues
import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE
import prog8.compiler.target.c64.FLOAT_MAX_POSITIVE
import prog8.compiler.target.c64.Petscii
import kotlin.math.floor
class ConstantFolding(private val namespace: INameScope, private val heap: HeapValues) : IAstProcessor {
@ -382,6 +383,43 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
}
return super.process(arrayIndexedExpression)
}
override fun process(assignment: Assignment): IStatement {
super.process(assignment)
val lv = assignment.value as? LiteralValue
if(lv!=null) {
val targetDt = assignment.target.determineDatatype(namespace, heap, assignment)
// see if we can promote/convert a literal value to the required datatype
when(targetDt) {
DataType.WORD -> {
if(lv.type==DataType.BYTE)
assignment.value = LiteralValue(DataType.WORD, wordvalue = lv.asIntegerValue, position=lv.position)
else if(lv.type==DataType.FLOAT) {
val d = lv.floatvalue!!
if(floor(d)==d && d in 0..65535) {
assignment.value = LiteralValue(DataType.WORD, wordvalue=floor(d).toInt(), position=lv.position)
}
}
}
DataType.FLOAT -> {
if(lv.isNumeric)
assignment.value = LiteralValue(DataType.FLOAT, floatvalue= lv.asNumericValue?.toDouble(), position=lv.position)
}
DataType.BYTE -> {
if(lv.type==DataType.WORD && lv.asIntegerValue in 0..255) {
assignment.value = LiteralValue(DataType.BYTE, lv.asIntegerValue?.toShort(), position=lv.position)
} else if(lv.type==DataType.FLOAT) {
val d = lv.floatvalue!!
if(floor(d)==d && d in 0..255) {
assignment.value = LiteralValue(DataType.BYTE, floor(d).toShort(), position=lv.position)
}
}
}
else -> {}
}
}
return assignment
}
}