fix some struct type and symbol lookup errors

This commit is contained in:
Irmen de Jong
2025-05-10 23:09:59 +02:00
parent 0b789b5f0b
commit 59c378089e
16 changed files with 271 additions and 69 deletions

View File

@@ -1,11 +1,18 @@
package prog8tests.compiler
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import io.kotest.engine.spec.tempdir
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.types.instanceOf
import prog8.code.ast.PtReturn
import prog8.code.ast.PtSubSignature
import prog8.code.target.C64Target
import prog8.code.target.VMTarget
import prog8.vm.VmRunner
import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.compileText
import kotlin.io.path.readText
@@ -38,4 +45,169 @@ thing {
VmRunner().runProgram(virtfile.readText(), true)
}
test("passing struct instances to subroutines and returning a struct instance is not allowed") {
val src="""
main {
sub start() {
}
struct Node {
bool flag
}
sub faulty(Node arg) -> Node {
return cx16.r0
}
}
"""
val errors = ErrorReporterForTests()
compileText(VMTarget(), false, src, outputDir, errors=errors)
val err = errors.errors
err.size shouldBe 3
err[0] shouldContain "uword doesn't match"
err[1] shouldContain "structs can only be passed via a pointer"
err[2] shouldContain "structs can only be returned via a pointer"
}
test("pointers in subroutine return values") {
val src="""
main {
sub start() {
^^thing.Node @shared ptr = thing.new()
}
}
thing {
struct Node {
bool flag
^^Node next
}
sub new() -> ^^Node {
cx16.r0++
^^Node pointer = 2000
return pointer
}
}"""
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
// TODO compileText(C64Target(), false, src, outputDir) shouldNotBe null
}
test("creating instances") {
val src="""
main {
struct MyNode {
bool flag
^^MyNode next
}
sub start() {
^^MyNode @shared m1 = MyNode()
^^MyNode @shared m2 = MyNode(true, 0)
^^thing.Node @shared n1 = thing.Node()
^^thing.Node @shared n2 = thing.Node(true, 0)
}
}
thing {
struct Node {
bool flag
^^Node next
}
}"""
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
compileText(VMTarget(), true, src, outputDir) shouldNotBe null
// TODO compileText(C64Target(), false, src, outputDir) shouldNotBe null
// TODO compileText(C64Target(), true, src, outputDir) shouldNotBe null
}
test("creating instances with optimization should all be removed") {
val src="""
main {
struct MyNode {
bool flag
^^MyNode next
}
sub start() {
^^MyNode m1 = MyNode()
^^MyNode m2 = MyNode(true, 0)
^^thing.Node n1 = thing.Node()
^^thing.Node n2 = thing.Node(true, 0)
}
}
thing {
struct Node {
bool flag
^^Node next
}
}"""
var result = compileText(VMTarget(), true, src, outputDir)!!
withClue("all variables should have been optimized away") {
val start = result.codegenAst!!.entrypoint()!!
start.children.size shouldBe 2
start.children[0] shouldBe instanceOf<PtSubSignature>()
start.children[1] shouldBe instanceOf<PtReturn>()
}
// TODO compileText(C64Target(), true, src, outputDir) shouldNotBe null
}
test("creating instances should have correct number of args") {
val src="""
main {
struct Node {
bool flag
ubyte value
^^Node next
}
sub start() {
^^Node ptr = Node(true) ; error
}
}"""
val errors = ErrorReporterForTests()
compileText(VMTarget(), false, src, outputDir, errors=errors)
val err = errors.errors
err.size shouldBe 1
err[0] shouldContain("expected 3 or 0, got 1")
}
test("pointer uword compatibility") {
val src="""
main {
struct MyNode {
bool flag
^^MyNode next
}
sub start() {
cx16.r0 = MyNode()
^^MyNode @shared ptr1 = cx16.r0
ptr1 = 2000
ptr1 = 20
ptr1 = 20.2222
}
}"""
val errors = ErrorReporterForTests()
compileText(VMTarget(), false, src, outputDir, errors=errors)
val err = errors.errors
err.size shouldBe 1
err[0] shouldContain("15:16: can only assign uword or correct pointer type to a pointer")
}
})

View File

@@ -73,7 +73,7 @@ class TestSubroutines: FunSpec({
func.statements.isEmpty() shouldBe true
}
test("cannot call a subroutine via pointer") {
test("cannot call a subroutine via a pointer") {
val src="""
main {
sub start() {