prog8/compiler/test/TestBuiltinFunctions.kt

119 lines
4.1 KiB
Kotlin
Raw Normal View History

package prog8tests.compiler
import io.kotest.core.spec.style.FunSpec
import io.kotest.inspectors.shouldForAll
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
import prog8.code.core.BaseDataType
2023-02-09 00:46:23 +00:00
import prog8.code.core.BuiltinFunctions
import prog8.code.core.RegisterOrPair
import prog8.code.core.isNumeric
2022-07-02 21:27:08 +00:00
import prog8.code.target.Cx16Target
import prog8tests.helpers.compileText
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"
func.parameters[0].possibleDatatypes. shouldForAll { it.isNumeric }
2023-02-09 00:46:23 +00:00
func.pure shouldBe true
func.returnType shouldBe BaseDataType.BYTE
2023-02-09 00:46:23 +00:00
val conv = func.callConvention(listOf(BaseDataType.UBYTE))
2023-02-09 00:46:23 +00:00
conv.params.size shouldBe 1
conv.params[0].dt shouldBe BaseDataType.UBYTE
2023-02-09 00:46:23 +00:00
conv.params[0].reg shouldBe RegisterOrPair.A
conv.params[0].variable shouldBe false
conv.returns.dt shouldBe BaseDataType.BYTE
2023-02-09 00:46:23 +00:00
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(BaseDataType.UWORD, BaseDataType.UWORD))
2023-02-09 00:46:23 +00:00
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(BaseDataType.UWORD)
2023-02-09 00:46:23 +00:00
func.parameters[1].name shouldBe "value"
func.parameters[1].possibleDatatypes shouldBe arrayOf(BaseDataType.UBYTE)
2023-02-09 00:46:23 +00:00
func.pure shouldBe false
func.returnType shouldBe null
val conv = func.callConvention(listOf(BaseDataType.UWORD, BaseDataType.UBYTE))
2023-02-09 00:46:23 +00:00
conv.params.size shouldBe 2
conv.params[0].dt shouldBe BaseDataType.UWORD
2023-02-09 00:46:23 +00:00
conv.params[0].reg shouldBe null
conv.params[0].variable shouldBe true
conv.params[1].dt shouldBe BaseDataType.UBYTE
2023-02-09 00:46:23 +00:00
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
}
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)
cx16.r1L = len(name)
cx16.r2L = sizeof(array)
cx16.r4 = mkword(200,100)
test(sizeof(array))
}
sub test(uword value) {
value++
}
}"""
val result = compileText(Cx16Target(), false, src, writeAssembly = false)
2023-02-09 00:46:23 +00:00
val statements = result!!.compilerAst.entrypoint.statements
statements.size shouldBe 7
val a1 = statements[2] as Assignment
val a2 = statements[3] as Assignment
val a3 = statements[4] as Assignment
val a4 = statements[5] as Assignment
val a5 = statements[6] as FunctionCallStatement
(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
(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
}
})