Skip to content

Commit

Permalink
fix crash when initializing string variable with a non-string value
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Feb 10, 2025
1 parent cd2cc89 commit c7f0ff1
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 59 deletions.
35 changes: 18 additions & 17 deletions compiler/src/prog8/compiler/astprocessing/AstChecker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -820,13 +820,30 @@ internal class AstChecker(private val program: Program,
val eltDt = decl.datatype.elementType()
if(!(iDt istype eltDt))
valueerr("initialisation value has incompatible type ($iDt) for the variable (${decl.datatype})")
} else {
} else if(!decl.datatype.isString) {
if(!(iDt.isBool && decl.datatype.isUnsignedByte || iDt issimpletype BaseDataType.UBYTE && decl.datatype.isBool))
valueerr("initialisation value has incompatible type ($iDt) for the variable (${decl.datatype})")
}
}
}

if(decl.datatype.isString) {
if(decl.value==null) {
// complain about uninitialized str, but only if it's a regular variable
val parameter = (decl.parent as? Subroutine)?.parameters?.singleOrNull{ it.name==decl.name }
if(parameter==null)
err("string var must be initialized with a string literal")
}

if(decl.value !is StringLiteral) {
if(decl.type==VarDeclType.MEMORY)
err("strings can't be memory mapped")
else
valueerr("string var must be initialized with a string literal")
}
return
}

// array length limits and constant lenghts
if(decl.isArray) {

Expand Down Expand Up @@ -883,22 +900,6 @@ internal class AstChecker(private val program: Program,
err("memory mapped word arrays cannot be split, should have @nosplit")
}

if(decl.datatype.isString) {
if(decl.value==null) {
// complain about uninitialized str, but only if it's a regular variable
val parameter = (decl.parent as? Subroutine)?.parameters?.singleOrNull{ it.name==decl.name }
if(parameter==null)
err("string var must be initialized with a string literal")
}

if(decl.value !is StringLiteral) {
if(decl.type==VarDeclType.MEMORY)
err("strings can't be memory mapped")
else
valueerr("string var must be initialized with a string literal")
}
}

if(decl.datatype.isSplitWordArray) {
if (!decl.datatype.isWordArray) {
errors.err("split can only be used on word arrays", decl.position)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
if(decl.isArray) {
if(decl.datatype.isSplitWordArray)
errors.err("value has incompatible type ($valueType) for the variable (${decl.datatype})", decl.value!!.position)
} else {
} else if(!decl.datatype.isString) {
if (valueDt.largerSizeThan(decl.datatype)) {
val constValue = decl.value?.constValue(program)
if (constValue != null)
Expand Down
21 changes: 21 additions & 0 deletions compiler/test/ast/TestAstChecks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -460,4 +460,25 @@ main {
errors.errors[0] shouldContain "too few values: expected 3 got 1"
errors.errors[1] shouldContain "too few values: expected 3 got 1"
}

test("correct errors for wrong string initialization value") {
val src="""
main {
sub start() {
str minString1 = 1234
str minString2 = func()
}
sub func() -> str {
return "zz"
}
}"""
val errors = ErrorReporterForTests()
compileText(Cx16Target(), optimize=false, src, writeAssembly=false, errors = errors) shouldBe null
errors.errors.size shouldBe 3
errors.errors[0] shouldContain "type of value uword doesn't match target str"
errors.errors[1] shouldContain "string var must be initialized with a string literal"
errors.errors[2] shouldContain "string var must be initialized with a string literal"
}
})
9 changes: 0 additions & 9 deletions docs/source/todo.rst
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
TODO
====

- fix string concatenation error
uword totalseconds = 3636
uword minutes
uword seconds
divmod(totalseconds, 60 as uword, minutes, seconds)
str minString = conv.str_uw(minutes)
str secString = conv.str_uw(seconds)
txt.print(minString + ":" + secString)

- Make neo and atari targets external via configs? They are very bare bones atm so easier to contribute to if they're configurable externally? What about the pet32 target

- add paypal donation button as well?
Expand Down
36 changes: 4 additions & 32 deletions examples/test.p8
Original file line number Diff line number Diff line change
@@ -1,39 +1,11 @@
%address $A000
%memtop $C000
%output library

%import textio


main {
; Create a jump table as first thing in the library.
; uword[] @shared @nosplit jumptable = [
; ; NOTE: the compiler has inserted a single JMP instruction at the start of the 'main' block, that jumps to the start() routine.
; ; This is convenient because the rest of the jump table simply follows it,
; ; making the first jump neatly be the required initialization routine for the library (initializing variables and BSS region).
; ; btw, $4c = opcode for JMP.
; $4c00, &library.func1,
; $4c00, &library.func2,
; ]

%jmptable (
library.func1,
library.func2,
)

sub start() {
; has to be here for initialization
txt.print("lib initialized\n")
}
}


library {
sub func1() {
txt.print("lib func 1\n")
str minString1 = 1234
str minString2 = func()
}

sub func2() {
txt.print("lib func 2\n")
sub func() -> str {
return "zz"
}
}

0 comments on commit c7f0ff1

Please sign in to comment.