mirror of
https://github.com/irmen/prog8.git
synced 2025-02-22 01:29:07 +00:00
enforce variable init values are only strings or arrays
This commit is contained in:
parent
0c882836d9
commit
7a13f57ab0
@ -149,6 +149,18 @@ class PtVariable(
|
||||
position: Position
|
||||
) : PtNamedNode(name, position), IPtVariable {
|
||||
init {
|
||||
|
||||
if(value!=null) {
|
||||
require(value is PtArray || value is PtString) { "variable initializer value must only be array or string" }
|
||||
// NOTE: the 6502 code generator expects numerical variables to not have an initialization value,
|
||||
// because that is done via assignment statements. There are no "inline" variables with a given value.
|
||||
// All variables are put into zeropage or into the BSS section and initialized afterwards during program
|
||||
// startup or at the start of the subroutine.
|
||||
// The IR codegen however is different it has a special section <VARIABLESWITHINIT> for all variables
|
||||
// that have a non-zero initialization value, regardless of the datatype. It removes the initialization
|
||||
// assignment and puts the value back into the variable (but only in the symboltable).
|
||||
}
|
||||
|
||||
value?.let {it.parent=this}
|
||||
}
|
||||
}
|
||||
|
@ -674,28 +674,34 @@ internal class ProgramAndVarsGen(
|
||||
}
|
||||
|
||||
private fun staticVariable2asm(variable: StStaticVariable) {
|
||||
val initialValue: Number =
|
||||
if(variable.initializationNumericValue!=null) {
|
||||
if(variable.dt.isFloat)
|
||||
variable.initializationNumericValue!!
|
||||
else
|
||||
variable.initializationNumericValue!!.toInt()
|
||||
} else 0
|
||||
if(!variable.dt.isArray && !variable.dt.isString) {
|
||||
throw AssemblyError("static variables with an initialization value can only be an array or a string, not ${variable.dt} (${variable.name} ${variable.astNode?.position}")
|
||||
// because numeric variables are in the BSS section and get initialized via assignment statements
|
||||
}
|
||||
|
||||
// val initialValue: Number =
|
||||
// if(variable.initializationNumericValue!=null) {
|
||||
// if(variable.dt.isFloat)
|
||||
// variable.initializationNumericValue!!
|
||||
// else
|
||||
// variable.initializationNumericValue!!.toInt()
|
||||
// } else 0
|
||||
//
|
||||
|
||||
val dt=variable.dt
|
||||
when {
|
||||
dt.isBool || dt.isUnsignedByte -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}")
|
||||
dt.isSignedByte -> asmgen.out("${variable.name}\t.char $initialValue")
|
||||
dt.isUnsignedWord -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}")
|
||||
dt.isSignedWord -> asmgen.out("${variable.name}\t.sint $initialValue")
|
||||
dt.isFloat -> {
|
||||
if(initialValue==0) {
|
||||
asmgen.out("${variable.name}\t.byte 0,0,0,0,0 ; float")
|
||||
} else {
|
||||
val floatFill = compTarget.getFloatAsmBytes(initialValue)
|
||||
asmgen.out("${variable.name}\t.byte $floatFill ; float $initialValue")
|
||||
}
|
||||
}
|
||||
// dt.isBool || dt.isUnsignedByte -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}")
|
||||
// dt.isSignedByte -> asmgen.out("${variable.name}\t.char $initialValue")
|
||||
// dt.isUnsignedWord -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}")
|
||||
// dt.isSignedWord -> asmgen.out("${variable.name}\t.sint $initialValue")
|
||||
// dt.isFloat -> {
|
||||
// if(initialValue==0) {
|
||||
// asmgen.out("${variable.name}\t.byte 0,0,0,0,0 ; float")
|
||||
// } else {
|
||||
// val floatFill = compTarget.getFloatAsmBytes(initialValue)
|
||||
// asmgen.out("${variable.name}\t.byte $floatFill ; float $initialValue")
|
||||
// }
|
||||
// }
|
||||
dt.isString -> {
|
||||
throw AssemblyError("all string vars should have been interned into prog")
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ class TestCodegen: FunSpec({
|
||||
DataType.forDt(BaseDataType.UBYTE),
|
||||
ZeropageWish.DONTCARE,
|
||||
0u,
|
||||
PtNumber(BaseDataType.UBYTE, 0.0, Position.DUMMY),
|
||||
null,
|
||||
null,
|
||||
Position.DUMMY
|
||||
))
|
||||
@ -81,7 +81,7 @@ class TestCodegen: FunSpec({
|
||||
DataType.forDt(BaseDataType.WORD),
|
||||
ZeropageWish.DONTCARE,
|
||||
0u,
|
||||
PtNumber(BaseDataType.WORD, 1.0, Position.DUMMY),
|
||||
null,
|
||||
null,
|
||||
Position.DUMMY
|
||||
))
|
||||
|
@ -51,7 +51,7 @@ class TestVmCodeGen: FunSpec({
|
||||
DataType.forDt(BaseDataType.UBYTE),
|
||||
ZeropageWish.DONTCARE,
|
||||
0u,
|
||||
PtNumber(BaseDataType.UBYTE, 0.0, Position.DUMMY),
|
||||
null,
|
||||
null,
|
||||
Position.DUMMY
|
||||
))
|
||||
@ -78,7 +78,7 @@ class TestVmCodeGen: FunSpec({
|
||||
DataType.forDt(BaseDataType.WORD),
|
||||
ZeropageWish.DONTCARE,
|
||||
0u,
|
||||
PtNumber(BaseDataType.WORD, 1.0, Position.DUMMY),
|
||||
null,
|
||||
null,
|
||||
Position.DUMMY
|
||||
))
|
||||
|
@ -19,6 +19,7 @@ import prog8.code.source.SourceCode
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||
import prog8.compiler.astprocessing.AstChecker
|
||||
import prog8.compiler.astprocessing.SimplifiedAstMaker
|
||||
import prog8tests.helpers.*
|
||||
|
||||
@ -31,7 +32,7 @@ class TestAsmGenSymbols: StringSpec({
|
||||
uword var_outside
|
||||
|
||||
sub start () {
|
||||
uword localvar = 1234
|
||||
uword localvar
|
||||
uword tgt
|
||||
|
||||
locallabel:
|
||||
@ -48,7 +49,7 @@ class TestAsmGenSymbols: StringSpec({
|
||||
|
||||
*/
|
||||
val varInSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE,
|
||||
SplitWish.DONTCARE, null, "localvar", emptyList(), NumericLiteral.optimalInteger(1234, Position.DUMMY), false, 0u, false, Position.DUMMY)
|
||||
SplitWish.DONTCARE, null, "localvar", emptyList(), null, false, 0u, false, Position.DUMMY)
|
||||
val var2InSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE,
|
||||
SplitWish.DONTCARE, null, "tgt", emptyList(), null, false, 0u, false, Position.DUMMY)
|
||||
val labelInSub = Label("locallabel", Position.DUMMY)
|
||||
@ -79,6 +80,9 @@ class TestAsmGenSymbols: StringSpec({
|
||||
fun createTestAsmGen6502(program: Program): AsmGen6502Internal {
|
||||
val errors = ErrorReporterForTests()
|
||||
val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, true, C64Target(), 999u, 0xffffu)
|
||||
val astchecker = AstChecker(program, errors, options)
|
||||
astchecker.visit(program)
|
||||
errors.report()
|
||||
val ptProgram = SimplifiedAstMaker(program, errors).transform()
|
||||
val st = SymbolTableMaker(ptProgram, options).make()
|
||||
return AsmGen6502Internal(ptProgram, st, options, errors, 0)
|
||||
|
@ -5,12 +5,15 @@
|
||||
|
||||
|
||||
main {
|
||||
|
||||
ubyte @nozp @shared staticvar=51
|
||||
|
||||
sub start() {
|
||||
ubyte x = math.rnd()
|
||||
ubyte a,b = multi1()
|
||||
ubyte c,d = 99
|
||||
ubyte c,d = multi2()
|
||||
|
||||
x++
|
||||
x=irmen
|
||||
txt.print_ub(a)
|
||||
txt.spc()
|
||||
txt.print_ub(b)
|
||||
|
Loading…
x
Reference in New Issue
Block a user