mirror of
https://github.com/irmen/prog8.git
synced 2024-09-28 17:54:58 +00:00
fix divmod; out args are written to and should be potential constants
This commit is contained in:
parent
2a3a27c56d
commit
ba1e907c79
@ -96,9 +96,9 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
||||
"sqrt__ubyte" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UBYTE))), DataType.UBYTE),
|
||||
"sqrt__uword" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD))), DataType.UBYTE),
|
||||
"sqrt__float" to FSignature(true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT),
|
||||
"divmod" to FSignature(false, listOf(FParam("number", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("divident", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("division", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("remainder", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||
"divmod__ubyte" to FSignature(false, listOf(FParam("number", arrayOf(DataType.UBYTE)), FParam("divident", arrayOf(DataType.UBYTE)), FParam("division", arrayOf(DataType.UBYTE)), FParam("remainder", arrayOf(DataType.UBYTE))), null),
|
||||
"divmod__uword" to FSignature(false, listOf(FParam("number", arrayOf(DataType.UWORD)), FParam("divident", arrayOf(DataType.UWORD)), FParam("division", arrayOf(DataType.UWORD)), FParam("remainder", arrayOf(DataType.UWORD))), null),
|
||||
"divmod" to FSignature(false, listOf(FParam("dividend", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("divisor", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("quotient", arrayOf(DataType.UBYTE, DataType.UWORD)), FParam("remainder", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||
"divmod__ubyte" to FSignature(false, listOf(FParam("dividend", arrayOf(DataType.UBYTE)), FParam("divisor", arrayOf(DataType.UBYTE)), FParam("quotient", arrayOf(DataType.UBYTE)), FParam("remainder", arrayOf(DataType.UBYTE))), null),
|
||||
"divmod__uword" to FSignature(false, listOf(FParam("dividend", arrayOf(DataType.UWORD)), FParam("divisor", arrayOf(DataType.UWORD)), FParam("quotient", arrayOf(DataType.UWORD)), FParam("remainder", arrayOf(DataType.UWORD))), null),
|
||||
"any" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), DataType.BOOL),
|
||||
"all" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), DataType.BOOL),
|
||||
"lsb" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE),
|
||||
@ -133,4 +133,9 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
||||
"call" to FSignature(false, listOf(FParam("address", arrayOf(DataType.UWORD))), DataType.UWORD),
|
||||
)
|
||||
|
||||
val InplaceModifyingBuiltinFunctions = setOf("setlsb", "setmsb", "rol", "ror", "rol2", "ror2", "sort", "reverse")
|
||||
val InplaceModifyingBuiltinFunctions = setOf(
|
||||
"setlsb", "setmsb",
|
||||
"rol", "ror", "rol2", "ror2",
|
||||
"sort", "reverse",
|
||||
"divmod", "divmod__ubyte", "divmod__uword"
|
||||
)
|
||||
|
@ -75,7 +75,7 @@ class VarConstantValueTypeAdjuster(
|
||||
val declValue = decl.value?.constValue(program)
|
||||
if (declValue != null) {
|
||||
// variable is never written to, so it can be replaced with a constant, IF the value is a constant
|
||||
errors.info("variable is never written to and was replaced by a constant", decl.position)
|
||||
errors.info("variable '${decl.name}' is never written to and was replaced by a constant", decl.position)
|
||||
val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, declValue, decl.sharedWithAsm, decl.splitArray, decl.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(decl, const, parent),
|
||||
@ -94,7 +94,7 @@ class VarConstantValueTypeAdjuster(
|
||||
)
|
||||
}
|
||||
// variable only has a single write and it is the initialization value, so it can be replaced with a constant, IF the value is a constant
|
||||
errors.info("variable is never written to and was replaced by a constant", decl.position)
|
||||
errors.info("variable '${decl.name}' is never written to and was replaced by a constant", decl.position)
|
||||
val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, singleAssignment.value, decl.sharedWithAsm, decl.splitArray, decl.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(decl, const, parent),
|
||||
|
@ -1264,7 +1264,14 @@ internal class AstChecker(private val program: Program,
|
||||
if(funcName[0]=="setlsb" || funcName[0]=="setmsb") {
|
||||
val firstArg = functionCallStatement.args[0]
|
||||
if(firstArg !is IdentifierReference && firstArg !is ArrayIndexedExpression)
|
||||
errors.err("invalid argument to a in-place modifying function", functionCallStatement.args.first().position)
|
||||
errors.err("invalid argument to a in-place modifying function", firstArg.position)
|
||||
} else if(funcName[0]=="divmod" || funcName[0].startsWith("divmod__")) {
|
||||
val thirdArg = functionCallStatement.args[2]
|
||||
val fourthArg = functionCallStatement.args[3]
|
||||
if(thirdArg !is IdentifierReference && thirdArg !is ArrayIndexedExpression)
|
||||
errors.err("invalid argument to a in-place modifying function", thirdArg.position)
|
||||
if(fourthArg !is IdentifierReference && fourthArg !is ArrayIndexedExpression)
|
||||
errors.err("invalid argument to a in-place modifying function", fourthArg.position)
|
||||
} else {
|
||||
if(functionCallStatement.args.any { it !is IdentifierReference && it !is ArrayIndexedExpression && it !is DirectMemoryRead })
|
||||
errors.err("invalid argument to a in-place modifying function", functionCallStatement.args.first().position)
|
||||
|
@ -2,6 +2,7 @@ package prog8tests
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.FunctionCallStatement
|
||||
@ -98,5 +99,19 @@ main {
|
||||
(a4.value as NumericLiteral).number shouldBe 200*256+100
|
||||
(a5.args[0] as NumericLiteral).number shouldBe 6.0
|
||||
}
|
||||
|
||||
test("divmod target args should be treated as variables that are written") {
|
||||
val src="""
|
||||
main {
|
||||
ubyte c
|
||||
ubyte l
|
||||
|
||||
sub start() {
|
||||
divmod(99, 10, c, l)
|
||||
}
|
||||
}"""
|
||||
|
||||
compileText(Cx16Target(), true, src, writeAssembly = true) shouldNotBe null
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -832,7 +832,7 @@ divmod (dividend, divisor, quotient, remainder)
|
||||
Performs division only once and returns both quotient and remainder in a single call, where using '/' and '%' separately
|
||||
would perform the division operation twice.
|
||||
All values are ubytes or all are uwords.
|
||||
The last two arguments must be ubyte variables to receive the quotient and remainder results, respectively.
|
||||
The last two arguments must be variables to receive the quotient and remainder results, respectively.
|
||||
|
||||
|
||||
Array operations
|
||||
|
@ -1,19 +1,15 @@
|
||||
%import diskio
|
||||
; test_divmode.p8
|
||||
%import textio
|
||||
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
|
||||
main {
|
||||
ubyte c
|
||||
ubyte l
|
||||
|
||||
sub start() {
|
||||
bool @shared flag
|
||||
|
||||
cx16.r0L = test(12345, flag, -42)
|
||||
|
||||
}
|
||||
|
||||
asmsub test(uword arg @AY, bool flag @Pc, byte value @X) -> ubyte @A, bool @Pc {
|
||||
%asm {{
|
||||
txa
|
||||
rts
|
||||
}}
|
||||
divmod(99, 10, c, l)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user