mirror of
https://github.com/irmen/prog8.git
synced 2024-11-23 07:32:10 +00:00
b7a622c68e
fix alignment of uninitialized arrays in aligned blocks (make them initialized with zeros so they don't end up in the BSS section)
179 lines
8.2 KiB
Kotlin
179 lines
8.2 KiB
Kotlin
package prog8tests
|
|
|
|
import io.kotest.assertions.fail
|
|
import io.kotest.core.spec.style.FunSpec
|
|
import io.kotest.matchers.shouldBe
|
|
import io.kotest.matchers.shouldNotBe
|
|
import io.kotest.matchers.types.shouldBeSameInstanceAs
|
|
import prog8.code.*
|
|
import prog8.code.ast.*
|
|
import prog8.code.core.DataType
|
|
import prog8.code.core.Position
|
|
import prog8.code.core.SourceCode
|
|
import prog8.code.core.ZeropageWish
|
|
import prog8tests.helpers.DummyMemsizer
|
|
import prog8tests.helpers.DummyStringEncoder
|
|
|
|
|
|
class TestSymbolTable: FunSpec({
|
|
test("empty symboltable") {
|
|
val astNode = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
|
val st = SymbolTable(astNode)
|
|
st.name shouldBe "test"
|
|
st.type shouldBe StNodeType.GLOBAL
|
|
st.children shouldBe mutableMapOf()
|
|
st.astNode shouldBeSameInstanceAs astNode
|
|
st.astNode.position shouldBe Position.DUMMY
|
|
}
|
|
|
|
test("symboltable flatten") {
|
|
val st = makeSt()
|
|
st.flat["zzzzz"] shouldBe null
|
|
st.flat.getValue("msb").type shouldBe StNodeType.BUILTINFUNC
|
|
st.flat.getValue("block2").type shouldBe StNodeType.BLOCK
|
|
st.flat.getValue("block2.sub2.subsub.label").type shouldBe StNodeType.LABEL
|
|
st.flat["block2.sub2.subsub.label.zzzz"] shouldBe null
|
|
}
|
|
|
|
test("symboltable global lookups") {
|
|
val st = makeSt()
|
|
st.lookupUnscoped("undefined") shouldBe null
|
|
st.lookup("undefined") shouldBe null
|
|
st.lookup("undefined.undefined") shouldBe null
|
|
var default = st.lookupUnscopedOrElse("undefined") { StNode("default", StNodeType.LABEL, PtIdentifier("default", DataType.BYTE, Position.DUMMY)) }
|
|
default.name shouldBe "default"
|
|
default = st.lookupUnscopedOrElse("undefined") { StNode("default", StNodeType.LABEL, PtIdentifier("default", DataType.BYTE, Position.DUMMY)) }
|
|
default.name shouldBe "default"
|
|
|
|
val msbFunc = st.lookupUnscopedOrElse("msb") { fail("msb must be found") }
|
|
msbFunc.type shouldBe StNodeType.BUILTINFUNC
|
|
|
|
val variable = st.lookupOrElse("block1.sub2.v2") { fail("v2 must be found") }
|
|
variable.type shouldBe StNodeType.STATICVAR
|
|
}
|
|
|
|
test("symboltable nested lookups") {
|
|
val st = makeSt()
|
|
|
|
val sub1 = st.lookupOrElse("block1.sub1") { fail("should find sub1") }
|
|
sub1.name shouldBe "sub1"
|
|
sub1.scopedName shouldBe "block1.sub1"
|
|
sub1.type shouldBe StNodeType.SUBROUTINE
|
|
sub1.children.size shouldBe 4
|
|
|
|
val v1 = sub1.lookupUnscopedOrElse("v1") { fail("v1 must be found") } as StStaticVariable
|
|
v1.type shouldBe StNodeType.STATICVAR
|
|
v1.name shouldBe "v1"
|
|
v1.dt shouldBe DataType.BYTE
|
|
|
|
val blockc = sub1.lookupUnscopedOrElse("blockc") { fail("blockc") } as StConstant
|
|
blockc.type shouldBe StNodeType.CONSTANT
|
|
blockc.value shouldBe 999.0
|
|
|
|
val subsub = st.lookupOrElse("block2.sub2.subsub") { fail("should find subsub") }
|
|
subsub.lookupUnscoped("blockc") shouldBe null
|
|
subsub.lookupUnscoped("label") shouldNotBe null
|
|
}
|
|
|
|
test("symboltable collections") {
|
|
val st= makeSt()
|
|
|
|
st.allVariables.size shouldBe 4
|
|
st.allMemMappedVariables.single().scopedName shouldBe "block1.sub1.v3"
|
|
st.allMemorySlabs.single().scopedName shouldBe "block1.sub1.slab1"
|
|
}
|
|
|
|
test("static vars") {
|
|
val node = PtIdentifier("dummy", DataType.UBYTE, Position.DUMMY)
|
|
val stVar1 = StStaticVariable("initialized", DataType.UBYTE, 99.0, null, null, null, ZeropageWish.DONTCARE, node)
|
|
val stVar2 = StStaticVariable("uninitialized", DataType.UBYTE, null, null, null, null, ZeropageWish.DONTCARE, node)
|
|
val arrayInitNonzero = listOf(StArrayElement(1.1, null), StArrayElement(2.2, null), StArrayElement(3.3, null))
|
|
val arrayInitAllzero = listOf(StArrayElement(0.0, null), StArrayElement(0.0, null), StArrayElement(0.0, null))
|
|
val stVar3 = StStaticVariable("initialized", DataType.ARRAY_UW, null, null, arrayInitNonzero, 3, ZeropageWish.DONTCARE, node)
|
|
val stVar4 = StStaticVariable("initialized", DataType.ARRAY_UW, null, null, arrayInitAllzero, 3, ZeropageWish.DONTCARE, node)
|
|
val stVar5 = StStaticVariable("uninitialized", DataType.ARRAY_UW, null, null, null, 3, ZeropageWish.DONTCARE, node)
|
|
|
|
stVar1.uninitialized shouldBe false
|
|
stVar1.length shouldBe null
|
|
stVar2.uninitialized shouldBe true
|
|
stVar2.length shouldBe null
|
|
stVar3.uninitialized shouldBe false
|
|
stVar3.length shouldBe 3
|
|
stVar4.uninitialized shouldBe false
|
|
stVar4.length shouldBe 3
|
|
stVar5.uninitialized shouldBe true
|
|
stVar5.length shouldBe 3
|
|
}
|
|
})
|
|
|
|
|
|
private fun makeSt(): SymbolTable {
|
|
|
|
// first build the AST
|
|
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
|
val astBlock1 = PtBlock("block1", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("block1"), Position.DUMMY)
|
|
val astConstant1 = PtConstant("c1", DataType.UWORD, 12345.0, Position.DUMMY)
|
|
val astConstant2 = PtConstant("blockc", DataType.UWORD, 999.0, Position.DUMMY)
|
|
astBlock1.add(astConstant1)
|
|
astBlock1.add(astConstant2)
|
|
val astSub1 = PtSub("sub1", emptyList(), null, Position.DUMMY)
|
|
val astSub2 = PtSub("sub2", emptyList(), null, Position.DUMMY)
|
|
val astSub1v1 = PtVariable("v1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)
|
|
val astSub1v2 = PtVariable("v2", DataType.BYTE, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
|
val astSub1v3 = PtVariable("v3", DataType.FLOAT, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
|
val astSub1v4 = PtVariable("slab1", DataType.UWORD, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
|
val astSub2v1 = PtVariable("v1", DataType.BYTE, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
|
val astSub2v2 = PtVariable("v2", DataType.BYTE, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
|
astSub1.add(astSub1v1)
|
|
astSub1.add(astSub1v2)
|
|
astSub1.add(astSub1v3)
|
|
astSub1.add(astSub1v4)
|
|
astSub2.add(astSub2v2)
|
|
astSub2.add(astSub2v2)
|
|
astBlock1.add(astSub1)
|
|
astBlock1.add(astSub2)
|
|
val astBfunc = PtIdentifier("msb", DataType.UBYTE, Position.DUMMY)
|
|
astBlock1.add(astBfunc)
|
|
val astBlock2 = PtBlock("block2", null, false, false, false, PtBlock.BlockAlignment.NONE, SourceCode.Generated("block2"), Position.DUMMY)
|
|
val astSub21 = PtSub("sub1", emptyList(), null, Position.DUMMY)
|
|
val astSub22 = PtSub("sub2", emptyList(), null, Position.DUMMY)
|
|
val astSub221 = PtSub("subsub", emptyList(), null, Position.DUMMY)
|
|
val astLabel = PtLabel("label", Position.DUMMY)
|
|
astSub221.add(astLabel)
|
|
astSub22.add(astSub221)
|
|
astBlock2.add(astSub21)
|
|
astBlock2.add(astSub22)
|
|
astProgram.add(astBlock1)
|
|
astProgram.add(astBlock2)
|
|
|
|
// now hook up the SymbolTable on that AST
|
|
val st = SymbolTable(astProgram)
|
|
val block1 = StNode("block1", StNodeType.BLOCK, astBlock1)
|
|
val sub11 = StNode("sub1", StNodeType.SUBROUTINE, astSub1)
|
|
val sub12 = StNode("sub2", StNodeType.SUBROUTINE, astSub2)
|
|
block1.add(sub11)
|
|
block1.add(sub12)
|
|
block1.add(StConstant("c1", DataType.UWORD, 12345.0, astConstant1))
|
|
block1.add(StConstant("blockc", DataType.UWORD, 999.0, astConstant2))
|
|
sub11.add(StStaticVariable("v1", DataType.BYTE, null, null, null, null, ZeropageWish.DONTCARE, astSub1v1))
|
|
sub11.add(StStaticVariable("v2", DataType.BYTE, null, null, null, null, ZeropageWish.DONTCARE, astSub1v2))
|
|
sub11.add(StMemVar("v3", DataType.FLOAT, 12345u, null, astSub1v3))
|
|
sub11.add(StMemorySlab("slab1", 200u, 64u, astSub1v4))
|
|
sub12.add(StStaticVariable("v1", DataType.BYTE, null, null, null, null, ZeropageWish.DONTCARE, astSub2v1))
|
|
sub12.add(StStaticVariable("v2", DataType.BYTE, null, null, null, null, ZeropageWish.DONTCARE, astSub2v2))
|
|
val block2 = StNode("block2", StNodeType.BLOCK, astBlock2)
|
|
val sub21 = StNode("sub1", StNodeType.SUBROUTINE, astSub21)
|
|
val sub22 = StNode("sub2", StNodeType.SUBROUTINE, astSub22)
|
|
block2.add(sub21)
|
|
block2.add(sub22)
|
|
val sub221 = StNode("subsub", StNodeType.SUBROUTINE, astSub221)
|
|
sub221.add(StNode("label", StNodeType.LABEL, astLabel))
|
|
sub22.add(sub221)
|
|
|
|
val builtinfunc = StNode("msb", StNodeType.BUILTINFUNC, astBfunc)
|
|
st.add(block1)
|
|
st.add(block2)
|
|
st.add(builtinfunc)
|
|
return st
|
|
}
|