mirror of
https://github.com/irmen/prog8.git
synced 2025-02-23 07:29:12 +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
|
position: Position
|
||||||
) : PtNamedNode(name, position), IPtVariable {
|
) : PtNamedNode(name, position), IPtVariable {
|
||||||
init {
|
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}
|
value?.let {it.parent=this}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -674,28 +674,34 @@ internal class ProgramAndVarsGen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun staticVariable2asm(variable: StStaticVariable) {
|
private fun staticVariable2asm(variable: StStaticVariable) {
|
||||||
val initialValue: Number =
|
if(!variable.dt.isArray && !variable.dt.isString) {
|
||||||
if(variable.initializationNumericValue!=null) {
|
throw AssemblyError("static variables with an initialization value can only be an array or a string, not ${variable.dt} (${variable.name} ${variable.astNode?.position}")
|
||||||
if(variable.dt.isFloat)
|
// because numeric variables are in the BSS section and get initialized via assignment statements
|
||||||
variable.initializationNumericValue!!
|
}
|
||||||
else
|
|
||||||
variable.initializationNumericValue!!.toInt()
|
// val initialValue: Number =
|
||||||
} else 0
|
// if(variable.initializationNumericValue!=null) {
|
||||||
|
// if(variable.dt.isFloat)
|
||||||
|
// variable.initializationNumericValue!!
|
||||||
|
// else
|
||||||
|
// variable.initializationNumericValue!!.toInt()
|
||||||
|
// } else 0
|
||||||
|
//
|
||||||
|
|
||||||
val dt=variable.dt
|
val dt=variable.dt
|
||||||
when {
|
when {
|
||||||
dt.isBool || dt.isUnsignedByte -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}")
|
// dt.isBool || dt.isUnsignedByte -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}")
|
||||||
dt.isSignedByte -> asmgen.out("${variable.name}\t.char $initialValue")
|
// dt.isSignedByte -> asmgen.out("${variable.name}\t.char $initialValue")
|
||||||
dt.isUnsignedWord -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}")
|
// dt.isUnsignedWord -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}")
|
||||||
dt.isSignedWord -> asmgen.out("${variable.name}\t.sint $initialValue")
|
// dt.isSignedWord -> asmgen.out("${variable.name}\t.sint $initialValue")
|
||||||
dt.isFloat -> {
|
// dt.isFloat -> {
|
||||||
if(initialValue==0) {
|
// if(initialValue==0) {
|
||||||
asmgen.out("${variable.name}\t.byte 0,0,0,0,0 ; float")
|
// asmgen.out("${variable.name}\t.byte 0,0,0,0,0 ; float")
|
||||||
} else {
|
// } else {
|
||||||
val floatFill = compTarget.getFloatAsmBytes(initialValue)
|
// val floatFill = compTarget.getFloatAsmBytes(initialValue)
|
||||||
asmgen.out("${variable.name}\t.byte $floatFill ; float $initialValue")
|
// asmgen.out("${variable.name}\t.byte $floatFill ; float $initialValue")
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
dt.isString -> {
|
dt.isString -> {
|
||||||
throw AssemblyError("all string vars should have been interned into prog")
|
throw AssemblyError("all string vars should have been interned into prog")
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ class TestCodegen: FunSpec({
|
|||||||
DataType.forDt(BaseDataType.UBYTE),
|
DataType.forDt(BaseDataType.UBYTE),
|
||||||
ZeropageWish.DONTCARE,
|
ZeropageWish.DONTCARE,
|
||||||
0u,
|
0u,
|
||||||
PtNumber(BaseDataType.UBYTE, 0.0, Position.DUMMY),
|
null,
|
||||||
null,
|
null,
|
||||||
Position.DUMMY
|
Position.DUMMY
|
||||||
))
|
))
|
||||||
@ -81,7 +81,7 @@ class TestCodegen: FunSpec({
|
|||||||
DataType.forDt(BaseDataType.WORD),
|
DataType.forDt(BaseDataType.WORD),
|
||||||
ZeropageWish.DONTCARE,
|
ZeropageWish.DONTCARE,
|
||||||
0u,
|
0u,
|
||||||
PtNumber(BaseDataType.WORD, 1.0, Position.DUMMY),
|
null,
|
||||||
null,
|
null,
|
||||||
Position.DUMMY
|
Position.DUMMY
|
||||||
))
|
))
|
||||||
|
@ -51,7 +51,7 @@ class TestVmCodeGen: FunSpec({
|
|||||||
DataType.forDt(BaseDataType.UBYTE),
|
DataType.forDt(BaseDataType.UBYTE),
|
||||||
ZeropageWish.DONTCARE,
|
ZeropageWish.DONTCARE,
|
||||||
0u,
|
0u,
|
||||||
PtNumber(BaseDataType.UBYTE, 0.0, Position.DUMMY),
|
null,
|
||||||
null,
|
null,
|
||||||
Position.DUMMY
|
Position.DUMMY
|
||||||
))
|
))
|
||||||
@ -78,7 +78,7 @@ class TestVmCodeGen: FunSpec({
|
|||||||
DataType.forDt(BaseDataType.WORD),
|
DataType.forDt(BaseDataType.WORD),
|
||||||
ZeropageWish.DONTCARE,
|
ZeropageWish.DONTCARE,
|
||||||
0u,
|
0u,
|
||||||
PtNumber(BaseDataType.WORD, 1.0, Position.DUMMY),
|
null,
|
||||||
null,
|
null,
|
||||||
Position.DUMMY
|
Position.DUMMY
|
||||||
))
|
))
|
||||||
|
@ -19,6 +19,7 @@ import prog8.code.source.SourceCode
|
|||||||
import prog8.code.target.C64Target
|
import prog8.code.target.C64Target
|
||||||
import prog8.code.target.VMTarget
|
import prog8.code.target.VMTarget
|
||||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||||
|
import prog8.compiler.astprocessing.AstChecker
|
||||||
import prog8.compiler.astprocessing.SimplifiedAstMaker
|
import prog8.compiler.astprocessing.SimplifiedAstMaker
|
||||||
import prog8tests.helpers.*
|
import prog8tests.helpers.*
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ class TestAsmGenSymbols: StringSpec({
|
|||||||
uword var_outside
|
uword var_outside
|
||||||
|
|
||||||
sub start () {
|
sub start () {
|
||||||
uword localvar = 1234
|
uword localvar
|
||||||
uword tgt
|
uword tgt
|
||||||
|
|
||||||
locallabel:
|
locallabel:
|
||||||
@ -48,7 +49,7 @@ class TestAsmGenSymbols: StringSpec({
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
val varInSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE,
|
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,
|
val var2InSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE,
|
||||||
SplitWish.DONTCARE, null, "tgt", emptyList(), null, false, 0u, false, Position.DUMMY)
|
SplitWish.DONTCARE, null, "tgt", emptyList(), null, false, 0u, false, Position.DUMMY)
|
||||||
val labelInSub = Label("locallabel", Position.DUMMY)
|
val labelInSub = Label("locallabel", Position.DUMMY)
|
||||||
@ -79,6 +80,9 @@ class TestAsmGenSymbols: StringSpec({
|
|||||||
fun createTestAsmGen6502(program: Program): AsmGen6502Internal {
|
fun createTestAsmGen6502(program: Program): AsmGen6502Internal {
|
||||||
val errors = ErrorReporterForTests()
|
val errors = ErrorReporterForTests()
|
||||||
val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, true, C64Target(), 999u, 0xffffu)
|
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 ptProgram = SimplifiedAstMaker(program, errors).transform()
|
||||||
val st = SymbolTableMaker(ptProgram, options).make()
|
val st = SymbolTableMaker(ptProgram, options).make()
|
||||||
return AsmGen6502Internal(ptProgram, st, options, errors, 0)
|
return AsmGen6502Internal(ptProgram, st, options, errors, 0)
|
||||||
|
@ -5,12 +5,15 @@
|
|||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
|
ubyte @nozp @shared staticvar=51
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte x = math.rnd()
|
ubyte x = math.rnd()
|
||||||
ubyte a,b = multi1()
|
ubyte a,b = multi1()
|
||||||
ubyte c,d = 99
|
ubyte c,d = multi2()
|
||||||
|
|
||||||
x++
|
x=irmen
|
||||||
txt.print_ub(a)
|
txt.print_ub(a)
|
||||||
txt.spc()
|
txt.spc()
|
||||||
txt.print_ub(b)
|
txt.print_ub(b)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user