From 448d176c243fd92331c517d0350a1ad38dd898c2 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 4 Mar 2023 15:35:54 +0100 Subject: [PATCH] fix vm crash on empty string --- codeCore/src/prog8/code/SymbolTable.kt | 16 ++++++++++++++-- compiler/test/TestSymbolTable.kt | 17 ++++++++++++++--- docs/source/todo.rst | 3 --- .../src/prog8/intermediate/IRFileReader.kt | 3 +++ intermediate/test/TestIRFileInOut.kt | 5 ++++- 5 files changed, 35 insertions(+), 9 deletions(-) diff --git a/codeCore/src/prog8/code/SymbolTable.kt b/codeCore/src/prog8/code/SymbolTable.kt index 3286d6937..489402fa6 100644 --- a/codeCore/src/prog8/code/SymbolTable.kt +++ b/codeCore/src/prog8/code/SymbolTable.kt @@ -54,7 +54,17 @@ class SymbolTable(astProgram: PtProgram) : StNode(astProgram.name, StNodeType.GL } val allMemorySlabs: Collection by lazy { - children.mapNotNull { if (it.value.type == StNodeType.MEMORYSLAB) it.value as StMemorySlab else null } + val vars = mutableListOf() + fun collect(node: StNode) { + for(child in node.children) { + if(child.value.type== StNodeType.MEMORYSLAB) + vars.add(child.value as StMemorySlab) + else + collect(child.value) + } + } + collect(this) + vars } override fun lookup(scopedName: String) = flat[scopedName] @@ -168,7 +178,9 @@ class StStaticVariable(name: String, } if(onetimeInitializationArrayValue!=null) { require(dt in ArrayDatatypes) - require(onetimeInitializationArrayValue.any { it.number!=0.0} ) { "array of all zerors as init value should just remain uninitialized"} + if(onetimeInitializationArrayValue.all { it.number!=null} ) { + require(onetimeInitializationArrayValue.any { it.number != 0.0 }) { "array of all zerors as init value should just remain uninitialized" } + } } if(onetimeInitializationStringValue!=null) { require(dt == DataType.STR) diff --git a/compiler/test/TestSymbolTable.kt b/compiler/test/TestSymbolTable.kt index fb9c4509e..f245ce40f 100644 --- a/compiler/test/TestSymbolTable.kt +++ b/compiler/test/TestSymbolTable.kt @@ -59,7 +59,7 @@ class TestSymbolTable: FunSpec({ sub1.name shouldBe "sub1" sub1.scopedName shouldBe "block1.sub1" sub1.type shouldBe StNodeType.SUBROUTINE - sub1.children.size shouldBe 2 + sub1.children.size shouldBe 4 val v1 = sub1.lookupUnscopedOrElse("v1") { fail("v1 must be found") } as StStaticVariable v1.type shouldBe StNodeType.STATICVAR @@ -75,7 +75,13 @@ class TestSymbolTable: FunSpec({ subsub.lookupUnscoped("label") shouldNotBe null } - // TODO add more SymbolTable tests + 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" + } }) @@ -93,10 +99,14 @@ private fun makeSt(): SymbolTable { 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) @@ -126,9 +136,10 @@ private fun makeSt(): SymbolTable { 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) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 55e940952..7e495acfa 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next minor release ^^^^^^^^^^^^^^^^^^^^^^ -- fix compiler crash on Virtual Textelite example - add optimizations for integer X <= Y-1 ---> X= Y+1 ---> X>Y - add optimizations for integer: X >= 1 => X > 0 (signed and unsigned) @@ -11,8 +10,6 @@ For next minor release X <= -1 => X >= 0 (signed only) X > -1 => X >= 0 (signed only) -- TestSymbolTable: add some more tests - ... diff --git a/intermediate/src/prog8/intermediate/IRFileReader.kt b/intermediate/src/prog8/intermediate/IRFileReader.kt index 872eb6a76..cced0794a 100644 --- a/intermediate/src/prog8/intermediate/IRFileReader.kt +++ b/intermediate/src/prog8/intermediate/IRFileReader.kt @@ -215,6 +215,9 @@ class IRFileReader { else -> throw IRParseException("weird dt") } val dummyNode = PtVariable(name, dt, zp, null, null, Position.DUMMY) + if(arraysize!=null && initArray!=null && initArray.all { it.number==0.0 }) { + initArray=null // arrays with just zeros can be left uninitialized + } variables.add(StStaticVariable(name, dt, initNumeric, null, initArray, arraysize, zp, dummyNode)) } return variables diff --git a/intermediate/test/TestIRFileInOut.kt b/intermediate/test/TestIRFileInOut.kt index 975db62a7..ba3fd5ca6 100644 --- a/intermediate/test/TestIRFileInOut.kt +++ b/intermediate/test/TestIRFileInOut.kt @@ -59,6 +59,7 @@ uword sys.bssvar zp=DONTCARE uword sys.wait.jiffies=10 zp=DONTCARE +ubyte[3] sys.emptystring=0,0,0 zp=DONTCARE @@ -106,10 +107,12 @@ return tempfile.deleteExisting() program.name shouldBe "test-ir-reader" program.blocks.size shouldBe 2 - program.st.allVariables().count() shouldBe 2 + program.st.allVariables().count() shouldBe 3 val var1 = program.st.lookup("sys.wait.jiffies") as StStaticVariable val var2 = program.st.lookup("sys.bssvar") as StStaticVariable + val var3 = program.st.lookup("sys.emptystring") as StStaticVariable var1.uninitialized shouldBe false var2.uninitialized shouldBe true + var3.uninitialized shouldBe true } }) \ No newline at end of file