mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-03 19:16:13 +00:00 
			
		
		
		
	avoid compiler crash when using char literal in str initialization
fix compiler crash when using str var in an expression without &
This commit is contained in:
		@@ -3,6 +3,7 @@ package prog8.compiler.astprocessing
 | 
				
			|||||||
import prog8.ast.IStatementContainer
 | 
					import prog8.ast.IStatementContainer
 | 
				
			||||||
import prog8.ast.Node
 | 
					import prog8.ast.Node
 | 
				
			||||||
import prog8.ast.Program
 | 
					import prog8.ast.Program
 | 
				
			||||||
 | 
					import prog8.ast.expressions.BinaryExpression
 | 
				
			||||||
import prog8.ast.expressions.CharLiteral
 | 
					import prog8.ast.expressions.CharLiteral
 | 
				
			||||||
import prog8.ast.expressions.IdentifierReference
 | 
					import prog8.ast.expressions.IdentifierReference
 | 
				
			||||||
import prog8.ast.expressions.NumericLiteral
 | 
					import prog8.ast.expressions.NumericLiteral
 | 
				
			||||||
@@ -82,6 +83,18 @@ internal fun Program.charLiteralsToUByteLiterals(target: ICompilationTarget, err
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            return noModifications
 | 
					            return noModifications
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
 | 
				
			||||||
 | 
					            if(decl.datatype.isString) {
 | 
				
			||||||
 | 
					                val initvalue = decl.value
 | 
				
			||||||
 | 
					                if(initvalue!=null && initvalue is BinaryExpression) {
 | 
				
			||||||
 | 
					                    if(initvalue.left is CharLiteral || initvalue.right is CharLiteral) {
 | 
				
			||||||
 | 
					                        errors.err("using a char literal in a string initialization expression, should probably be a string literal with one character in it instead", initvalue.position)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return noModifications
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    walker.visit(this)
 | 
					    walker.visit(this)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -368,4 +368,19 @@ main {
 | 
				
			|||||||
        errors.warnings.size shouldBe 0
 | 
					        errors.warnings.size shouldBe 0
 | 
				
			||||||
        errors.errors[0] shouldContain "requires integer or boolean type"
 | 
					        errors.errors[0] shouldContain "requires integer or boolean type"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test("missing address of in expression operand") {
 | 
				
			||||||
 | 
					        val src="""
 | 
				
			||||||
 | 
					main {
 | 
				
			||||||
 | 
					    sub start() {
 | 
				
			||||||
 | 
					        str name = "foo"
 | 
				
			||||||
 | 
					        cx16.r0 =  name+2
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}"""
 | 
				
			||||||
 | 
					        val errors = ErrorReporterForTests()
 | 
				
			||||||
 | 
					        compileText(C64Target(), false, src, writeAssembly = false, errors = errors) shouldBe null
 | 
				
			||||||
 | 
					        errors.errors.size shouldBe 1
 | 
				
			||||||
 | 
					        errors.warnings.size shouldBe 0
 | 
				
			||||||
 | 
					        errors.errors[0] shouldContain "missing &"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -253,7 +253,7 @@ class BinaryExpression(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // if left or right is a numeric literal, and its value fits in the type of the other operand, use the other's operand type
 | 
					            // if left or right is a numeric literal, and its value fits in the type of the other operand, use the other's operand type
 | 
				
			||||||
            // EXCEPTION: if the numeric value is a word and the other operand is a byte type (to allow   v * $0008  for example)
 | 
					            // EXCEPTION: if the numeric value is a word and the other operand is a byte type (to allow   v * $0008  for example)
 | 
				
			||||||
            if (left is NumericLiteral) {
 | 
					            if (left is NumericLiteral && rightDt.isNumericOrBool) {
 | 
				
			||||||
                if(!(leftDt.isWord && rightDt.isByte)) {
 | 
					                if(!(leftDt.isWord && rightDt.isByte)) {
 | 
				
			||||||
                    val optimal = NumericLiteral.optimalNumeric(rightDt.base, null, left.number, left.position)
 | 
					                    val optimal = NumericLiteral.optimalNumeric(rightDt.base, null, left.number, left.position)
 | 
				
			||||||
                    if (optimal.type != leftDt.base && DataType.forDt(optimal.type) isAssignableTo rightDt) {
 | 
					                    if (optimal.type != leftDt.base && DataType.forDt(optimal.type) isAssignableTo rightDt) {
 | 
				
			||||||
@@ -261,7 +261,7 @@ class BinaryExpression(
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (right is NumericLiteral) {
 | 
					            if (right is NumericLiteral && leftDt.isNumericOrBool) {
 | 
				
			||||||
                if(!(rightDt.isWord && leftDt.isByte)) {
 | 
					                if(!(rightDt.isWord && leftDt.isByte)) {
 | 
				
			||||||
                    val optimal = NumericLiteral.optimalNumeric(leftDt.base, null, right.number, right.position)
 | 
					                    val optimal = NumericLiteral.optimalNumeric(leftDt.base, null, right.number, right.position)
 | 
				
			||||||
                    if (optimal.type != rightDt.base && DataType.forDt(optimal.type) isAssignableTo leftDt) {
 | 
					                    if (optimal.type != rightDt.base && DataType.forDt(optimal.type) isAssignableTo leftDt) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,8 @@ Future Things and Ideas
 | 
				
			|||||||
  Make up our mind! Maybe all setup does need to be put into start() ? because the program cannot function correctly when the variables aren't initialized properly bss is not cleared etc. etc.
 | 
					  Make up our mind! Maybe all setup does need to be put into start() ? because the program cannot function correctly when the variables aren't initialized properly bss is not cleared etc. etc.
 | 
				
			||||||
  Add a -library $xxxx command line option (and/or some directive) to preselect every setting that is required to make a library at $xxxx rather than a normal loadable and runnable program?
 | 
					  Add a -library $xxxx command line option (and/or some directive) to preselect every setting that is required to make a library at $xxxx rather than a normal loadable and runnable program?
 | 
				
			||||||
  Need to add some way to generate a stable jump table at a given address.
 | 
					  Need to add some way to generate a stable jump table at a given address.
 | 
				
			||||||
 | 
					  Need library to not call init_system AND init_system_phase2 not either.
 | 
				
			||||||
 | 
					  Library must not include prog8_program_start stuff either.
 | 
				
			||||||
- Fix missing cases where regular & has to return the start of the split array in memory whatever byte comes first. Search TODO("address of split word array")
 | 
					- Fix missing cases where regular & has to return the start of the split array in memory whatever byte comes first. Search TODO("address of split word array")
 | 
				
			||||||
- Add a syntax to access specific bits in a variable, to avoid manually shifts&ands, something like  variable[4:8] ?  (or something else this may be too similar to regular array indexing)
 | 
					- Add a syntax to access specific bits in a variable, to avoid manually shifts&ands, something like  variable[4:8] ?  (or something else this may be too similar to regular array indexing)
 | 
				
			||||||
- something to reduce the need to use fully qualified names all the time. 'with' ?  Or 'using <prefix>'?
 | 
					- something to reduce the need to use fully qualified names all the time. 'with' ?  Or 'using <prefix>'?
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,7 @@
 | 
				
			|||||||
main {
 | 
					main {
 | 
				
			||||||
    sub start() {
 | 
					    sub start() {
 | 
				
			||||||
        uword[] tasklist = [1111,2222,3333]
 | 
					        ;str test = '?' * 10
 | 
				
			||||||
        uword task_address = tasklist[0]
 | 
					        str name = "foo"
 | 
				
			||||||
        goto task_address
 | 
					        cx16.r0 =  name+2
 | 
				
			||||||
        goto task_address+1
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user