2024-09-08 14:03:57 +00:00
|
|
|
package prog8tests.compiler
|
2022-02-21 00:32:29 +00:00
|
|
|
|
|
|
|
import io.kotest.core.spec.style.FunSpec
|
2023-01-24 22:59:53 +00:00
|
|
|
import io.kotest.matchers.shouldBe
|
2024-03-26 20:59:36 +00:00
|
|
|
import io.kotest.matchers.shouldNotBe
|
2023-01-24 22:59:53 +00:00
|
|
|
import prog8.ast.expressions.NumericLiteral
|
|
|
|
import prog8.ast.statements.Assignment
|
2023-12-03 16:11:12 +00:00
|
|
|
import prog8.ast.statements.FunctionCallStatement
|
2023-02-09 00:46:23 +00:00
|
|
|
import prog8.code.core.BuiltinFunctions
|
|
|
|
import prog8.code.core.RegisterOrPair
|
2022-07-02 21:27:08 +00:00
|
|
|
import prog8.code.target.Cx16Target
|
|
|
|
import prog8tests.helpers.compileText
|
2022-02-21 00:32:29 +00:00
|
|
|
|
|
|
|
class TestBuiltinFunctions: FunSpec({
|
|
|
|
|
2023-02-09 00:46:23 +00:00
|
|
|
test("pure func with fixed type") {
|
|
|
|
val func = BuiltinFunctions.getValue("sgn")
|
|
|
|
func.parameters.size shouldBe 1
|
|
|
|
func.parameters[0].name shouldBe "value"
|
2024-02-04 22:41:01 +00:00
|
|
|
func.parameters[0].possibleDatatypes shouldBe NumericDatatypes
|
2023-02-09 00:46:23 +00:00
|
|
|
func.pure shouldBe true
|
|
|
|
func.returnType shouldBe DataType.BYTE
|
|
|
|
|
|
|
|
val conv = func.callConvention(listOf(DataType.UBYTE))
|
|
|
|
conv.params.size shouldBe 1
|
|
|
|
conv.params[0].dt shouldBe DataType.UBYTE
|
|
|
|
conv.params[0].reg shouldBe RegisterOrPair.A
|
|
|
|
conv.params[0].variable shouldBe false
|
|
|
|
conv.returns.dt shouldBe DataType.BYTE
|
|
|
|
conv.returns.floatFac1 shouldBe false
|
|
|
|
conv.returns.reg shouldBe RegisterOrPair.A
|
|
|
|
}
|
|
|
|
|
|
|
|
test("not-pure func with varying result value type") {
|
|
|
|
val func = BuiltinFunctions.getValue("cmp")
|
|
|
|
func.parameters.size shouldBe 2
|
|
|
|
func.pure shouldBe false
|
|
|
|
func.returnType shouldBe null
|
|
|
|
|
|
|
|
val conv = func.callConvention(listOf(DataType.UWORD, DataType.UWORD))
|
|
|
|
conv.params.size shouldBe 2
|
|
|
|
conv.returns.dt shouldBe null
|
|
|
|
conv.returns.floatFac1 shouldBe false
|
|
|
|
conv.returns.reg shouldBe null
|
|
|
|
}
|
|
|
|
|
|
|
|
test("func without return type") {
|
|
|
|
val func = BuiltinFunctions.getValue("poke")
|
|
|
|
func.parameters.size shouldBe 2
|
|
|
|
func.parameters[0].name shouldBe "address"
|
|
|
|
func.parameters[0].possibleDatatypes shouldBe arrayOf(DataType.UWORD)
|
|
|
|
func.parameters[1].name shouldBe "value"
|
|
|
|
func.parameters[1].possibleDatatypes shouldBe arrayOf(DataType.UBYTE)
|
|
|
|
func.pure shouldBe false
|
|
|
|
func.returnType shouldBe null
|
|
|
|
|
|
|
|
val conv = func.callConvention(listOf(DataType.UWORD, DataType.UBYTE))
|
|
|
|
conv.params.size shouldBe 2
|
|
|
|
conv.params[0].dt shouldBe DataType.UWORD
|
|
|
|
conv.params[0].reg shouldBe null
|
|
|
|
conv.params[0].variable shouldBe true
|
|
|
|
conv.params[1].dt shouldBe DataType.UBYTE
|
|
|
|
conv.params[1].reg shouldBe null
|
|
|
|
conv.params[1].variable shouldBe true
|
|
|
|
conv.returns.dt shouldBe null
|
|
|
|
conv.returns.floatFac1 shouldBe false
|
|
|
|
conv.returns.reg shouldBe null
|
|
|
|
}
|
|
|
|
|
2023-01-24 22:59:53 +00:00
|
|
|
test("certain builtin functions should be compile time evaluated") {
|
|
|
|
val src="""
|
|
|
|
main {
|
|
|
|
sub start() {
|
|
|
|
uword[] array = [1,2,3]
|
|
|
|
str name = "hello"
|
|
|
|
cx16.r0L = len(array)
|
2023-12-03 16:11:12 +00:00
|
|
|
cx16.r1L = len(name)
|
|
|
|
cx16.r2L = sizeof(array)
|
|
|
|
cx16.r4 = mkword(200,100)
|
|
|
|
test(sizeof(array))
|
|
|
|
}
|
|
|
|
sub test(uword value) {
|
|
|
|
value++
|
2023-01-24 22:59:53 +00:00
|
|
|
}
|
|
|
|
}"""
|
|
|
|
val result = compileText(Cx16Target(), false, src, writeAssembly = false)
|
2023-02-09 00:46:23 +00:00
|
|
|
val statements = result!!.compilerAst.entrypoint.statements
|
2023-12-03 16:11:12 +00:00
|
|
|
statements.size shouldBe 7
|
2023-01-24 22:59:53 +00:00
|
|
|
val a1 = statements[2] as Assignment
|
|
|
|
val a2 = statements[3] as Assignment
|
|
|
|
val a3 = statements[4] as Assignment
|
|
|
|
val a4 = statements[5] as Assignment
|
2023-12-03 16:11:12 +00:00
|
|
|
val a5 = statements[6] as FunctionCallStatement
|
2023-01-24 22:59:53 +00:00
|
|
|
(a1.value as NumericLiteral).number shouldBe 3.0
|
|
|
|
(a2.value as NumericLiteral).number shouldBe 5.0
|
|
|
|
(a3.value as NumericLiteral).number shouldBe 6.0
|
|
|
|
(a4.value as NumericLiteral).number shouldBe 200*256+100
|
2023-12-03 16:11:12 +00:00
|
|
|
(a5.args[0] as NumericLiteral).number shouldBe 6.0
|
2023-01-24 22:59:53 +00:00
|
|
|
}
|
2024-03-26 20:59:36 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2022-02-21 00:32:29 +00:00
|
|
|
})
|
|
|
|
|