prog8/compiler/test/codegeneration/TestVariousCodeGen.kt

205 lines
5.5 KiB
Kotlin
Raw Normal View History

package prog8tests.codegeneration
import io.kotest.core.spec.style.FunSpec
2023-02-09 21:49:34 +00:00
import io.kotest.matchers.ints.shouldBeGreaterThan
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain
2023-02-09 21:49:34 +00:00
import io.kotest.matchers.string.shouldStartWith
import io.kotest.matchers.types.instanceOf
import prog8.code.ast.PtArrayIndexer
import prog8.code.ast.PtAssignment
import prog8.code.ast.PtVariable
import prog8.code.core.DataType
import prog8.code.target.C64Target
2023-03-21 01:54:26 +00:00
import prog8.code.target.VMTarget
import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.compileText
2023-02-19 02:07:55 +00:00
class TestVariousCodeGen: FunSpec({
test("bool to byte cast in expression is correct") {
val text="""
main {
sub start() {
ubyte[3] values
2023-01-31 00:14:13 +00:00
func(22 in values)
ubyte @shared qq = 22 in values
}
sub func(ubyte arg) {
arg++
}
}"""
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
}
2023-02-03 23:02:50 +00:00
test("nested scoping") {
val text="""
main {
sub start() {
testscope.duplicate()
cx16.r0L = testscope.duplicate2()
}
}
testscope {
sub sub1() {
ubyte @shared duplicate
ubyte @shared duplicate2
}
sub duplicate() {
; do nothing
}
sub duplicate2() -> ubyte {
return cx16.r0L
}
}"""
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
}
test("word array indexing") {
val text="""
main {
sub start() {
uword[3] seed
cx16.r0 = seed[0] + seed[1] + seed[2]
}
}"""
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
}
2023-02-09 21:49:34 +00:00
test("ast result from compileText") {
val text="""
main {
sub start() {
uword[3] seed
cx16.r0 = seed[0] + seed[1] + seed[2]
}
}"""
val result = compileText(C64Target(), false, text, writeAssembly = true)!!
result.compilerAst.name shouldStartWith "on_the_fly"
result.codegenAst!!.name shouldBe result.compilerAst.name
result.codegenAst!!.children.size shouldBeGreaterThan 2
val start = result.codegenAst!!.entrypoint()!!
start.name shouldBe "start"
start.children.size shouldBeGreaterThan 2
val seed = start.children[0] as PtVariable
seed.name shouldBe "seed"
seed.value shouldBe null
seed.type shouldBe DataType.ARRAY_UW
val assign = start.children[1] as PtAssignment
assign.target.identifier!!.name shouldBe "cx16.r0"
assign.value shouldBe instanceOf<PtArrayIndexer>()
}
test("peek and poke argument types") {
val text="""
main {
sub start() {
uword[3] arr
ubyte i = 42
uword ww = peekw(arr[i])
ubyte xx = peek(arr[i])
xx = @(arr[i])
@(arr[i]) = 42
poke(arr[i], 42)
pokew(arr[i], 4242)
}
}"""
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
}
test("assigning memory byte into arrays works") {
val text="""
main {
sub start() {
uword factor1
ubyte[3] bytearray
uword[3] wordarray
@(factor1) = bytearray[0]
bytearray[0] = @(factor1)
@(factor1) = lsb(wordarray[0])
wordarray[0] = @(factor1)
@(5000) = bytearray[0]
@(5000) = lsb(wordarray[0])
bytearray[0] = @(5000)
wordarray[0] = @(5000)
}
}"""
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
}
test("reading memory from unknown var gives proper error") {
val text="""
main {
sub start() {
cx16.r0L = @(doesnotexist)
}
}"""
val errors = ErrorReporterForTests()
compileText(C64Target(), false, text, writeAssembly = true, errors = errors)
errors.errors.size shouldBe 1
errors.errors[0] shouldContain "undefined symbol: doesnotexist"
}
2023-03-21 01:54:26 +00:00
test("shifting by word value is ok") {
val text="""
main {
sub start() {
ubyte c = 1
@(15000 + c<<${'$'}0003) = 42
@(15000 + (c<<${'$'}0003)) = 42
@(15000 + c*${'$'}0008) = 42 ; *8 becomes a shift after opt
uword @shared qq = 15000 + c<<${'$'}0003
qq = 15000 + (c<<${'$'}0003)
qq = 16000 + c*${'$'}0008
}
}"""
2023-03-25 17:45:17 +00:00
compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null
compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null
compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null
2023-04-05 18:48:20 +00:00
// no newexpr for IR targets: compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null
2023-03-21 01:54:26 +00:00
}
test("builtin func in float expression") {
val src="""
%import floats
main {
sub start() {
float @shared fl =25.1
fl = abs(fl)+0.5
fl = sqrt(fl)+0.5
}
}"""
compileText(C64Target(), false, src, writeAssembly = true) shouldNotBe null
}
test("string vars in inlined subroutines are ok") {
val src="""
main {
sub start() {
void block2.curdir()
void block2.other()
}
}
block2 {
str result="zzzz"
sub curdir() -> str {
return result
}
sub other() -> str {
return "other"
}
}"""
compileText(C64Target(), true, src, writeAssembly = true) shouldNotBe null
compileText(VMTarget(), true, src, writeAssembly = true) shouldNotBe null
}
})