mirror of
https://github.com/irmen/prog8.git
synced 2025-10-27 05:16:20 +00:00
allow struct initializers to occur in array literals
This commit is contained in:
@@ -5,9 +5,10 @@ import java.nio.file.Path
|
|||||||
import kotlin.io.path.absolute
|
import kotlin.io.path.absolute
|
||||||
|
|
||||||
|
|
||||||
// the automatically generated module where all string literals are interned to:
|
|
||||||
const val INTERNED_STRINGS_MODULENAME = "prog8_interned_strings"
|
const val INTERNED_STRINGS_MODULENAME = "prog8_interned_strings"
|
||||||
|
|
||||||
|
val PROG8_CONTAINER_MODULES = arrayOf(INTERNED_STRINGS_MODULENAME) // option to add more if needed one day
|
||||||
|
|
||||||
// all automatically generated labels everywhere need to have the same label name prefix:
|
// all automatically generated labels everywhere need to have the same label name prefix:
|
||||||
const val GENERATED_LABEL_PREFIX = "p8_label_gen_"
|
const val GENERATED_LABEL_PREFIX = "p8_label_gen_"
|
||||||
|
|
||||||
|
|||||||
@@ -252,6 +252,14 @@ private fun PtVariable.prefix(parent: PtNode, st: SymbolTable): PtVariable {
|
|||||||
newValue.add(newAddr)
|
newValue.add(newAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is PtBuiltinFunctionCall -> {
|
||||||
|
// could be a struct instance or memory slab "allocation"
|
||||||
|
if (elt.name != "prog8_lib_structalloc" && elt.name != "memory")
|
||||||
|
throw AssemblyError("weird array value element $elt")
|
||||||
|
else {
|
||||||
|
newValue.add(elt)
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> throw AssemblyError("weird array value element $elt")
|
else -> throw AssemblyError("weird array value element $elt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package prog8.codegen.cpu6502
|
package prog8.codegen.cpu6502
|
||||||
|
|
||||||
|
import prog8.code.StMemorySlabBlockName
|
||||||
|
import prog8.code.StStructInstanceBlockName
|
||||||
import prog8.code.SymbolTable
|
import prog8.code.SymbolTable
|
||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
@@ -385,7 +387,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
val name = (fcall.args[0] as PtString).value
|
val name = (fcall.args[0] as PtString).value
|
||||||
require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name ${fcall.position}"}
|
require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name ${fcall.position}"}
|
||||||
|
|
||||||
val slabname = PtIdentifier("prog8_slabs.prog8_memoryslab_$name", DataType.UWORD, fcall.position)
|
val slabname = PtIdentifier("$StMemorySlabBlockName.memory_$name", DataType.UWORD, fcall.position)
|
||||||
val addressOf = PtAddressOf(DataType.pointer(BaseDataType.UBYTE), false, fcall.position)
|
val addressOf = PtAddressOf(DataType.pointer(BaseDataType.UBYTE), false, fcall.position)
|
||||||
addressOf.add(slabname)
|
addressOf.add(slabname)
|
||||||
addressOf.parent = fcall
|
addressOf.parent = fcall
|
||||||
@@ -399,9 +401,10 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
if(discardResult)
|
if(discardResult)
|
||||||
throw AssemblyError("should not discard result of struct allocation at $fcall")
|
throw AssemblyError("should not discard result of struct allocation at $fcall")
|
||||||
// ... don't need to pay attention to args here because struct instance is put together elsewhere we just have to get a pointer to it
|
// ... don't need to pay attention to args here because struct instance is put together elsewhere we just have to get a pointer to it
|
||||||
val slabname = SymbolTable.labelnameForStructInstance(fcall)
|
val prefix = if(fcall.args.isEmpty()) "${StStructInstanceBlockName}_bss" else StStructInstanceBlockName
|
||||||
|
val labelname = PtIdentifier("$prefix.${SymbolTable.labelnameForStructInstance(fcall)}", fcall.type, fcall.position)
|
||||||
val addressOf = PtAddressOf(fcall.type, true, fcall.position)
|
val addressOf = PtAddressOf(fcall.type, true, fcall.position)
|
||||||
addressOf.add(PtIdentifier(slabname, fcall.type, fcall.position))
|
addressOf.add(labelname)
|
||||||
addressOf.parent = fcall
|
addressOf.parent = fcall
|
||||||
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, fcall.type, expression = addressOf)
|
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, fcall.type, expression = addressOf)
|
||||||
val target = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, null, asmgen)
|
val target = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, null, asmgen)
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ internal class ProgramAndVarsGen(
|
|||||||
private fun memorySlabs() {
|
private fun memorySlabs() {
|
||||||
if(symboltable.allMemorySlabs.isNotEmpty()) {
|
if(symboltable.allMemorySlabs.isNotEmpty()) {
|
||||||
asmgen.out("; memory slabs\n .section BSS_SLABS")
|
asmgen.out("; memory slabs\n .section BSS_SLABS")
|
||||||
asmgen.out("prog8_slabs\t.block")
|
asmgen.out("$StMemorySlabBlockName\t.block")
|
||||||
for (slab in symboltable.allMemorySlabs) {
|
for (slab in symboltable.allMemorySlabs) {
|
||||||
if (slab.align > 1u)
|
if (slab.align > 1u)
|
||||||
asmgen.out("\t.align ${slab.align.toHex()}")
|
asmgen.out("\t.align ${slab.align.toHex()}")
|
||||||
@@ -434,6 +434,7 @@ internal class ProgramAndVarsGen(
|
|||||||
val (instancesNoInit, instances) = symboltable.allStructInstances.partition { it.initialValues.isEmpty() }
|
val (instancesNoInit, instances) = symboltable.allStructInstances.partition { it.initialValues.isEmpty() }
|
||||||
asmgen.out("; struct instances without initialization values, as BSS zeroed at startup\n")
|
asmgen.out("; struct instances without initialization values, as BSS zeroed at startup\n")
|
||||||
asmgen.out(" .section BSS\n")
|
asmgen.out(" .section BSS\n")
|
||||||
|
asmgen.out("${StStructInstanceBlockName}_bss .block\n")
|
||||||
instancesNoInit.forEach {
|
instancesNoInit.forEach {
|
||||||
val structtype: StStruct = symboltable.lookup(it.structName) as StStruct
|
val structtype: StStruct = symboltable.lookup(it.structName) as StStruct
|
||||||
val zerovalues = structtype.fields.map { field ->
|
val zerovalues = structtype.fields.map { field ->
|
||||||
@@ -445,11 +446,17 @@ internal class ProgramAndVarsGen(
|
|||||||
}
|
}
|
||||||
asmgen.out("${it.name} .dstruct ${it.structName}, ${zerovalues.joinToString(",")}\n")
|
asmgen.out("${it.name} .dstruct ${it.structName}, ${zerovalues.joinToString(",")}\n")
|
||||||
}
|
}
|
||||||
|
asmgen.out(" .endblock\n")
|
||||||
asmgen.out(" .send BSS\n")
|
asmgen.out(" .send BSS\n")
|
||||||
|
|
||||||
asmgen.out("; struct instances with initialization values\n")
|
asmgen.out("; struct instances with initialization values\n")
|
||||||
asmgen.out(" .section STRUCTINSTANCES\n")
|
asmgen.out(" .section STRUCTINSTANCES\n")
|
||||||
instances.forEach { asmgen.out("${it.name} .dstruct ${it.structName}, ${initValues(it).joinToString(",")}\n") }
|
asmgen.out("$StStructInstanceBlockName .block\n")
|
||||||
|
instances.forEach {
|
||||||
|
val instancename = it.name.substringAfter('.')
|
||||||
|
asmgen.out("$instancename .dstruct ${it.structName}, ${initValues(it).joinToString(",")}\n")
|
||||||
|
}
|
||||||
|
asmgen.out(" .endblock\n")
|
||||||
asmgen.out(" .send STRUCTINSTANCES\n")
|
asmgen.out(" .send STRUCTINSTANCES\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -866,7 +873,7 @@ internal class ProgramAndVarsGen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dt.isSplitWordArray -> {
|
dt.isSplitWordArray -> {
|
||||||
if(dt.elementType().isUnsignedWord) {
|
if(dt.elementType().isUnsignedWord || dt.elementType().isPointer) {
|
||||||
val data = makeArrayFillDataUnsigned(dt, value, orNumberOfZeros)
|
val data = makeArrayFillDataUnsigned(dt, value, orNumberOfZeros)
|
||||||
asmgen.out("_array_$varname := ${data.joinToString()}")
|
asmgen.out("_array_$varname := ${data.joinToString()}")
|
||||||
asmgen.out("${varname}_lsb\t.byte <_array_$varname")
|
asmgen.out("${varname}_lsb\t.byte <_array_$varname")
|
||||||
@@ -914,7 +921,7 @@ internal class ProgramAndVarsGen(
|
|||||||
private fun zeroFilledArray(numElts: Int): StArray {
|
private fun zeroFilledArray(numElts: Int): StArray {
|
||||||
val values = mutableListOf<StArrayElement>()
|
val values = mutableListOf<StArrayElement>()
|
||||||
repeat(numElts) {
|
repeat(numElts) {
|
||||||
values.add(StArrayElement(0.0, null, null))
|
values.add(StArrayElement(0.0, null, null,null,null))
|
||||||
}
|
}
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
@@ -972,7 +979,7 @@ internal class ProgramAndVarsGen(
|
|||||||
val number = it.number!!.toInt()
|
val number = it.number!!.toInt()
|
||||||
"$"+number.toString(16).padStart(2, '0')
|
"$"+number.toString(16).padStart(2, '0')
|
||||||
}
|
}
|
||||||
dt.isArray && dt.elementType().isUnsignedWord -> array.map {
|
dt.isArray && (dt.elementType().isUnsignedWord || dt.elementType().isPointer) -> array.map {
|
||||||
if(it.number!=null) {
|
if(it.number!=null) {
|
||||||
"$" + it.number!!.toInt().toString(16).padStart(4, '0')
|
"$" + it.number!!.toInt().toString(16).padStart(4, '0')
|
||||||
}
|
}
|
||||||
@@ -984,9 +991,16 @@ internal class ProgramAndVarsGen(
|
|||||||
else
|
else
|
||||||
asmgen.asmSymbolName(addrOfSymbol)
|
asmgen.asmSymbolName(addrOfSymbol)
|
||||||
}
|
}
|
||||||
else
|
else if(it.structInstance!=null) {
|
||||||
|
asmgen.asmSymbolName("${StStructInstanceBlockName}.${it.structInstance!!}")
|
||||||
|
}
|
||||||
|
else if(it.structInstanceUninitialized!=null) {
|
||||||
|
asmgen.asmSymbolName("${StStructInstanceBlockName}_bss.${it.structInstanceUninitialized!!}")
|
||||||
|
}
|
||||||
|
else {
|
||||||
throw AssemblyError("weird array elt")
|
throw AssemblyError("weird array elt")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else -> throw AssemblyError("invalid dt")
|
else -> throw AssemblyError("invalid dt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package prog8.codegen.intermediate
|
package prog8.codegen.intermediate
|
||||||
|
|
||||||
|
import prog8.code.StMemorySlabBlockName
|
||||||
|
import prog8.code.StStructInstanceBlockName
|
||||||
import prog8.code.SymbolTable
|
import prog8.code.SymbolTable
|
||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.AssemblyError
|
import prog8.code.core.AssemblyError
|
||||||
@@ -500,7 +502,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
val name = (call.args[0] as PtString).value
|
val name = (call.args[0] as PtString).value
|
||||||
val code = IRCodeChunk(null, null)
|
val code = IRCodeChunk(null, null)
|
||||||
val resultReg = codeGen.registers.next(IRDataType.WORD)
|
val resultReg = codeGen.registers.next(IRDataType.WORD)
|
||||||
code += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=resultReg, labelSymbol = "$StMemorySlabPrefix.prog8_memoryslab_$name")
|
code += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=resultReg, labelSymbol = "$StMemorySlabBlockName.memory_$name")
|
||||||
return ExpressionCodeResult(code, IRDataType.WORD, resultReg, -1)
|
return ExpressionCodeResult(code, IRDataType.WORD, resultReg, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +510,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
val code = IRCodeChunk(null, null)
|
val code = IRCodeChunk(null, null)
|
||||||
val resultReg = codeGen.registers.next(IRDataType.WORD)
|
val resultReg = codeGen.registers.next(IRDataType.WORD)
|
||||||
val labelname = SymbolTable.labelnameForStructInstance(call)
|
val labelname = SymbolTable.labelnameForStructInstance(call)
|
||||||
code += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=resultReg, labelSymbol = labelname)
|
code += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=resultReg, labelSymbol = "${StStructInstanceBlockName}.$labelname")
|
||||||
return ExpressionCodeResult(code, IRDataType.WORD, resultReg, -1)
|
return ExpressionCodeResult(code, IRDataType.WORD, resultReg, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ private fun convert(variable: StStaticVariable): IRStStaticVariable {
|
|||||||
val newArray = mutableListOf<IRStArrayElement>()
|
val newArray = mutableListOf<IRStArrayElement>()
|
||||||
array.forEach {
|
array.forEach {
|
||||||
if(it.addressOfSymbol!=null) {
|
if(it.addressOfSymbol!=null) {
|
||||||
val target = variable.lookup(it.addressOfSymbol!!) ?: throw NoSuchElementException("can't find variable ${it.addressOfSymbol}")
|
println("LOOKUP ${it.addressOfSymbol}")
|
||||||
|
val target = variable.lookup(it.addressOfSymbol!!) ?:
|
||||||
|
throw NoSuchElementException("can't find variable ${it.addressOfSymbol}")
|
||||||
newArray.add(IRStArrayElement(null, null, target.scopedNameString))
|
newArray.add(IRStArrayElement(null, null, target.scopedNameString))
|
||||||
} else {
|
} else {
|
||||||
newArray.add(convertArrayElt(it))
|
newArray.add(convertArrayElt(it))
|
||||||
@@ -129,11 +131,11 @@ private fun convert(constant: StConstant): IRStConstant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun convert(variable: StMemorySlab): IRStMemorySlab {
|
private fun convert(mem: StMemorySlab): IRStMemorySlab {
|
||||||
return if('.' in variable.name)
|
return if('.' in mem.name)
|
||||||
IRStMemorySlab(variable.name, variable.size, variable.align)
|
IRStMemorySlab(mem.name, mem.size, mem.align)
|
||||||
else
|
else
|
||||||
IRStMemorySlab("$StMemorySlabPrefix.${variable.name}", variable.size, variable.align)
|
IRStMemorySlab("$StMemorySlabBlockName.${mem.name}", mem.size, mem.align)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,8 +144,8 @@ private fun convert(instance: StStructInstance, fields: Iterable<Pair<DataType,
|
|||||||
val elt = convertArrayElt(value)
|
val elt = convertArrayElt(value)
|
||||||
IRStructInitValue(field.first.base, elt)
|
IRStructInitValue(field.first.base, elt)
|
||||||
}
|
}
|
||||||
return IRStStructInstance(instance.name, instance.structName, values, instance.size)
|
return if('.' in instance.name)
|
||||||
|
IRStStructInstance(instance.name, instance.structName, values, instance.size)
|
||||||
|
else
|
||||||
|
IRStStructInstance("${StStructInstanceBlockName}.${instance.name}", instance.structName, values, instance.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal const val StMemorySlabPrefix = "prog8_slabs" // TODO also add ".prog8_memoryslab_" ?
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import prog8.ast.expressions.TypecastExpression
|
|||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.ast.walk.AstWalker
|
import prog8.ast.walk.AstWalker
|
||||||
import prog8.ast.walk.IAstModification
|
import prog8.ast.walk.IAstModification
|
||||||
import prog8.code.INTERNED_STRINGS_MODULENAME
|
import prog8.code.PROG8_CONTAINER_MODULES
|
||||||
import prog8.code.core.ICompilationTarget
|
import prog8.code.core.ICompilationTarget
|
||||||
import prog8.code.core.IErrorReporter
|
import prog8.code.core.IErrorReporter
|
||||||
import prog8.compiler.CallGraph
|
import prog8.compiler.CallGraph
|
||||||
@@ -93,7 +93,7 @@ class UnusedCodeRemover(private val program: Program,
|
|||||||
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
||||||
if("force_output" !in block.options()) {
|
if("force_output" !in block.options()) {
|
||||||
if (block.containsNoCodeNorVars) {
|
if (block.containsNoCodeNorVars) {
|
||||||
if (block.name != INTERNED_STRINGS_MODULENAME && "ignore_unused" !in block.options()) {
|
if (block.name !in PROG8_CONTAINER_MODULES && "ignore_unused" !in block.options()) {
|
||||||
if (!block.statements.any { it is Subroutine && it.hasBeenInlined })
|
if (!block.statements.any { it is Subroutine && it.hasBeenInlined })
|
||||||
errors.info("removing unused block '${block.name}'", block.position)
|
errors.info("removing unused block '${block.name}'", block.position)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import prog8.ast.*
|
|||||||
import prog8.ast.expressions.Expression
|
import prog8.ast.expressions.Expression
|
||||||
import prog8.ast.expressions.NumericLiteral
|
import prog8.ast.expressions.NumericLiteral
|
||||||
import prog8.ast.statements.Directive
|
import prog8.ast.statements.Directive
|
||||||
|
import prog8.code.SymbolTable
|
||||||
import prog8.code.SymbolTableMaker
|
import prog8.code.SymbolTableMaker
|
||||||
import prog8.code.ast.PtProgram
|
import prog8.code.ast.PtProgram
|
||||||
import prog8.code.ast.printAst
|
import prog8.code.ast.printAst
|
||||||
@@ -176,17 +177,21 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
|||||||
println("*********** COMPILER AST END *************\n")
|
println("*********** COMPILER AST END *************\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var symbolTable: SymbolTable
|
||||||
|
|
||||||
val (intermediateAst, simplifiedAstDuration2) = measureTimedValue {
|
val (intermediateAst, simplifiedAstDuration2) = measureTimedValue {
|
||||||
val intermediateAst = SimplifiedAstMaker(program, args.errors).transform()
|
val intermediateAst = SimplifiedAstMaker(program, args.errors).transform()
|
||||||
val stMaker = SymbolTableMaker(intermediateAst, compilationOptions)
|
val stMaker = SymbolTableMaker(intermediateAst, compilationOptions)
|
||||||
val symbolTable = stMaker.make()
|
symbolTable = stMaker.make()
|
||||||
|
|
||||||
postprocessSimplifiedAst(intermediateAst, symbolTable, compilationOptions, args.errors)
|
postprocessSimplifiedAst(intermediateAst, symbolTable, compilationOptions, args.errors)
|
||||||
args.errors.report()
|
args.errors.report()
|
||||||
|
symbolTable = stMaker.make() // need an updated ST because the postprocessing changes stuff
|
||||||
|
|
||||||
if (compilationOptions.optimize) {
|
if (compilationOptions.optimize) {
|
||||||
optimizeSimplifiedAst(intermediateAst, compilationOptions, symbolTable, args.errors)
|
optimizeSimplifiedAst(intermediateAst, compilationOptions, symbolTable, args.errors)
|
||||||
args.errors.report()
|
args.errors.report()
|
||||||
|
symbolTable = stMaker.make() // need an updated ST because the optimization changes stuff
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.printAst2) {
|
if (args.printAst2) {
|
||||||
@@ -204,6 +209,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
|||||||
createAssemblyDuration = measureTime {
|
createAssemblyDuration = measureTime {
|
||||||
if (!createAssemblyAndAssemble(
|
if (!createAssemblyAndAssemble(
|
||||||
intermediateAst,
|
intermediateAst,
|
||||||
|
symbolTable,
|
||||||
args.errors,
|
args.errors,
|
||||||
compilationOptions,
|
compilationOptions,
|
||||||
program.generatedLabelSequenceNumber
|
program.generatedLabelSequenceNumber
|
||||||
@@ -558,6 +564,7 @@ private fun postprocessAst(program: Program, errors: IErrorReporter, compilerOpt
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createAssemblyAndAssemble(program: PtProgram,
|
private fun createAssemblyAndAssemble(program: PtProgram,
|
||||||
|
symbolTable: SymbolTable,
|
||||||
errors: IErrorReporter,
|
errors: IErrorReporter,
|
||||||
compilerOptions: CompilationOptions,
|
compilerOptions: CompilationOptions,
|
||||||
lastGeneratedLabelSequenceNr: Int
|
lastGeneratedLabelSequenceNr: Int
|
||||||
@@ -572,10 +579,6 @@ private fun createAssemblyAndAssemble(program: PtProgram,
|
|||||||
else
|
else
|
||||||
throw NotImplementedError("no code generator for cpu ${compilerOptions.compTarget.cpu}")
|
throw NotImplementedError("no code generator for cpu ${compilerOptions.compTarget.cpu}")
|
||||||
|
|
||||||
// need to make a new symboltable here to capture possible changes made by optimization steps performed earlier!
|
|
||||||
val stMaker = SymbolTableMaker(program, compilerOptions)
|
|
||||||
val symbolTable = stMaker.make()
|
|
||||||
|
|
||||||
val assembly = asmgen.generate(program, symbolTable, compilerOptions, errors)
|
val assembly = asmgen.generate(program, symbolTable, compilerOptions, errors)
|
||||||
errors.report()
|
errors.report()
|
||||||
|
|
||||||
|
|||||||
@@ -1277,11 +1277,6 @@ internal class AstChecker(private val program: Program,
|
|||||||
errors.err("initialization value contains non-constant elements", array.value[0].position)
|
errors.err("initialization value contains non-constant elements", array.value[0].position)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(array.value.any { it is StaticStructInitializer }) {
|
|
||||||
errors.err("it is not yet possible to use struct initializations in an array, you have to do it one by one for now", array.value[0].position)
|
|
||||||
// TODO this is because later in the simplified AST the allocate struct variable is still missing somehow
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(array.parent is ForLoop) {
|
} else if(array.parent is ForLoop) {
|
||||||
if (!array.value.all { it.constValue(program) != null })
|
if (!array.value.all { it.constValue(program) != null })
|
||||||
errors.err("array literal for iteration must contain constants. Try using a separate array variable instead?", array.position)
|
errors.err("array literal for iteration must contain constants. Try using a separate array variable instead?", array.position)
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ internal fun postprocessSimplifiedAst(
|
|||||||
private fun processSubtypesIntoStReferences(program: PtProgram, st: SymbolTable) {
|
private fun processSubtypesIntoStReferences(program: PtProgram, st: SymbolTable) {
|
||||||
|
|
||||||
fun getStStruct(subType: ISubType): StStruct {
|
fun getStStruct(subType: ISubType): StStruct {
|
||||||
|
if(subType is StStruct)
|
||||||
|
return subType
|
||||||
val stNode = st.lookup(subType.scopedNameString) as? StStruct
|
val stNode = st.lookup(subType.scopedNameString) as? StStruct
|
||||||
if(stNode != null)
|
if(stNode != null)
|
||||||
return stNode
|
return stNode
|
||||||
@@ -28,7 +30,7 @@ private fun processSubtypesIntoStReferences(program: PtProgram, st: SymbolTable)
|
|||||||
throw FatalAstException("cannot find in ST: ${subType.scopedNameString} $subType")
|
throw FatalAstException("cannot find in ST: ${subType.scopedNameString} $subType")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fixSubtype(type: DataType) {
|
fun fixSubtypeIntoStType(type: DataType) {
|
||||||
if(type.subType!=null && type.subType !is StStruct) {
|
if(type.subType!=null && type.subType !is StStruct) {
|
||||||
type.subType = getStStruct(type.subType!!)
|
type.subType = getStStruct(type.subType!!)
|
||||||
}
|
}
|
||||||
@@ -36,13 +38,21 @@ private fun processSubtypesIntoStReferences(program: PtProgram, st: SymbolTable)
|
|||||||
|
|
||||||
fun fixSubtypes(node: PtNode) {
|
fun fixSubtypes(node: PtNode) {
|
||||||
when(node) {
|
when(node) {
|
||||||
is IPtVariable -> fixSubtype(node.type)
|
is IPtVariable -> {
|
||||||
is PtPointerDeref -> fixSubtype(node.type)
|
fixSubtypeIntoStType(node.type)
|
||||||
is PtStructDecl -> node.fields.forEach { fixSubtype(it.first) }
|
// if it's an array, fix the subtypes of its elements as well
|
||||||
is PtAsmSub -> node.returns.forEach { fixSubtype(it.second) }
|
if(node.type.isArray && node is PtVariable) {
|
||||||
is PtExpression -> fixSubtype(node.type)
|
(node.value as? PtArray)?.let {array ->
|
||||||
is PtSubSignature -> node.returns.forEach { fixSubtype(it) }
|
array.children.forEach { fixSubtypes(it) }
|
||||||
is PtSubroutineParameter -> fixSubtype(node.type)
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is PtPointerDeref -> fixSubtypeIntoStType(node.type)
|
||||||
|
is PtStructDecl -> node.fields.forEach { fixSubtypeIntoStType(it.first) }
|
||||||
|
is PtAsmSub -> node.returns.forEach { fixSubtypeIntoStType(it.second) }
|
||||||
|
is PtExpression -> fixSubtypeIntoStType(node.type)
|
||||||
|
is PtSubSignature -> node.returns.forEach { fixSubtypeIntoStType(it) }
|
||||||
|
is PtSubroutineParameter -> fixSubtypeIntoStType(node.type)
|
||||||
else -> { /* has no datatype */ }
|
else -> { /* has no datatype */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import io.kotest.matchers.shouldBe
|
|||||||
import io.kotest.matchers.string.shouldContain
|
import io.kotest.matchers.string.shouldContain
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.code.INTERNED_STRINGS_MODULENAME
|
import prog8.code.INTERNED_STRINGS_MODULENAME
|
||||||
|
import prog8.code.PROG8_CONTAINER_MODULES
|
||||||
import prog8.code.core.IErrorReporter
|
import prog8.code.core.IErrorReporter
|
||||||
import prog8.code.source.SourceCode
|
import prog8.code.source.SourceCode
|
||||||
import prog8.compiler.ModuleImporter
|
import prog8.compiler.ModuleImporter
|
||||||
@@ -49,7 +50,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
withClue(".file should point to specified path") {
|
withClue(".file should point to specified path") {
|
||||||
error1.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
|
error1.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
|
||||||
}
|
}
|
||||||
program.modules.size shouldBe 1
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
val error2 = importer.importMainModule(srcPathAbs).getErrorOrElse { error("should have import error") }
|
val error2 = importer.importMainModule(srcPathAbs).getErrorOrElse { error("should have import error") }
|
||||||
withClue(".file should be normalized") {
|
withClue(".file should be normalized") {
|
||||||
"${error2.file}" shouldBe "${error2.file.normalize()}"
|
"${error2.file}" shouldBe "${error2.file.normalize()}"
|
||||||
@@ -57,7 +58,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
withClue(".file should point to specified path") {
|
withClue(".file should point to specified path") {
|
||||||
error2.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
|
error2.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
|
||||||
}
|
}
|
||||||
program.modules.size shouldBe 1
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
}
|
}
|
||||||
|
|
||||||
test("testDirectory") {
|
test("testDirectory") {
|
||||||
@@ -75,7 +76,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
it.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
|
it.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
program.modules.size shouldBe 1
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
|
|
||||||
shouldThrow<FileSystemException> { importer.importMainModule(srcPathAbs) }
|
shouldThrow<FileSystemException> { importer.importMainModule(srcPathAbs) }
|
||||||
.let {
|
.let {
|
||||||
@@ -86,7 +87,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
it.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
|
it.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
program.modules.size shouldBe 1
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +102,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
val path = assumeReadableFile(searchIn[0], fileName)
|
val path = assumeReadableFile(searchIn[0], fileName)
|
||||||
|
|
||||||
val module = importer.importMainModule(path.absolute()).getOrElse { throw it }
|
val module = importer.importMainModule(path.absolute()).getOrElse { throw it }
|
||||||
program.modules.size shouldBe 2
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size+1
|
||||||
module shouldBeIn program.modules
|
module shouldBeIn program.modules
|
||||||
module.program shouldBe program
|
module.program shouldBe program
|
||||||
}
|
}
|
||||||
@@ -118,7 +119,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
val module = importer.importMainModule(path).getOrElse { throw it }
|
val module = importer.importMainModule(path).getOrElse { throw it }
|
||||||
program.modules.size shouldBe 2
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size+1
|
||||||
module shouldBeIn program.modules
|
module shouldBeIn program.modules
|
||||||
module.program shouldBe program
|
module.program shouldBe program
|
||||||
}
|
}
|
||||||
@@ -131,7 +132,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
assumeReadableFile(searchIn, path)
|
assumeReadableFile(searchIn, path)
|
||||||
|
|
||||||
val module = importer.importMainModule(path).getOrElse { throw it }
|
val module = importer.importMainModule(path).getOrElse { throw it }
|
||||||
program.modules.size shouldBe 2
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size+1
|
||||||
module shouldBeIn program.modules
|
module shouldBeIn program.modules
|
||||||
module.program shouldBe program
|
module.program shouldBe program
|
||||||
}
|
}
|
||||||
@@ -152,7 +153,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
|
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
program.modules.size shouldBe 1
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +173,8 @@ class TestModuleImporter: FunSpec({
|
|||||||
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
|
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
withClue("imported module with error in it should not be present") { program.modules.size shouldBe 1 }
|
withClue("imported module with error in it should not be present") { program.modules.size shouldBe PROG8_CONTAINER_MODULES.size }
|
||||||
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
program.modules[0].name shouldBe INTERNED_STRINGS_MODULENAME
|
program.modules[0].name shouldBe INTERNED_STRINGS_MODULENAME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,14 +205,14 @@ class TestModuleImporter: FunSpec({
|
|||||||
withClue(count[n] + " call / NO .p8 extension") { errors.noErrors() shouldBe false }
|
withClue(count[n] + " call / NO .p8 extension") { errors.noErrors() shouldBe false }
|
||||||
errors.errors.single() shouldContain "0:0: no module found with name i_do_not_exist"
|
errors.errors.single() shouldContain "0:0: no module found with name i_do_not_exist"
|
||||||
errors.report()
|
errors.report()
|
||||||
program.modules.size shouldBe 1
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
|
|
||||||
val result2 = importer.importImplicitLibraryModule(filenameWithExt)
|
val result2 = importer.importImplicitLibraryModule(filenameWithExt)
|
||||||
withClue(count[n] + " call / with .p8 extension") { result2 shouldBe null }
|
withClue(count[n] + " call / with .p8 extension") { result2 shouldBe null }
|
||||||
withClue(count[n] + " call / with .p8 extension") { importer.errors.noErrors() shouldBe false }
|
withClue(count[n] + " call / with .p8 extension") { importer.errors.noErrors() shouldBe false }
|
||||||
errors.errors.single() shouldContain "0:0: no module found with name i_do_not_exist.p8"
|
errors.errors.single() shouldContain "0:0: no module found with name i_do_not_exist.p8"
|
||||||
errors.report()
|
errors.report()
|
||||||
program.modules.size shouldBe 1
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,7 +234,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
|
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
program.modules.size shouldBe 1
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +256,7 @@ class TestModuleImporter: FunSpec({
|
|||||||
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
|
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
withClue("imported module with error in it should not be present") { program.modules.size shouldBe 1 }
|
withClue("imported module with error in it should not be present") { program.modules.size shouldBe PROG8_CONTAINER_MODULES.size }
|
||||||
program.modules[0].name shouldBe INTERNED_STRINGS_MODULENAME
|
program.modules[0].name shouldBe INTERNED_STRINGS_MODULENAME
|
||||||
importer.errors.report()
|
importer.errors.report()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1731,6 +1731,30 @@ main {
|
|||||||
compileText(Cx16Target(), false, src, outputDir) shouldNotBe null
|
compileText(Cx16Target(), false, src, outputDir) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("struct initializers in array") {
|
||||||
|
val src="""
|
||||||
|
main {
|
||||||
|
struct Node {
|
||||||
|
ubyte id
|
||||||
|
str name
|
||||||
|
uword array
|
||||||
|
}
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
^^Node[] @shared nodes = [
|
||||||
|
^^Node:[1,"one", 1000 ],
|
||||||
|
^^Node:[2,"two", 2000 ],
|
||||||
|
^^Node:[3,"three", 3000],
|
||||||
|
^^Node:[],
|
||||||
|
^^Node:[],
|
||||||
|
^^Node:[],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
compileText(C64Target(), false, src, outputDir) shouldNotBe null
|
||||||
|
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
|
||||||
|
}
|
||||||
|
|
||||||
test("type error for invalid bool field initializer") {
|
test("type error for invalid bool field initializer") {
|
||||||
val src="""
|
val src="""
|
||||||
main {
|
main {
|
||||||
|
|||||||
@@ -88,8 +88,8 @@ class TestSymbolTable: FunSpec({
|
|||||||
val stVar1 = StStaticVariable("initialized", DataType.UBYTE, null, null, null, ZeropageWish.DONTCARE, 0u, false,node)
|
val stVar1 = StStaticVariable("initialized", DataType.UBYTE, null, null, null, ZeropageWish.DONTCARE, 0u, false,node)
|
||||||
stVar1.setOnetimeInitNumeric(99.0)
|
stVar1.setOnetimeInitNumeric(99.0)
|
||||||
val stVar2 = StStaticVariable("uninitialized", DataType.UBYTE, null, null, null, ZeropageWish.DONTCARE, 0u, false, node)
|
val stVar2 = StStaticVariable("uninitialized", DataType.UBYTE, null, null, null, ZeropageWish.DONTCARE, 0u, false, node)
|
||||||
val arrayInitNonzero = listOf(StArrayElement(1.1, null, null), StArrayElement(2.2, null, null), StArrayElement(3.3, null, null))
|
val arrayInitNonzero = listOf(StArrayElement(1.1, null, null, null, null), StArrayElement(2.2, null, null, null, null), StArrayElement(3.3, null, null,null, null))
|
||||||
val arrayInitAllzero = listOf(StArrayElement(0.0, null, null), StArrayElement(0.0, null, null), StArrayElement(0.0, null, null))
|
val arrayInitAllzero = listOf(StArrayElement(0.0, null, null, null, null), StArrayElement(0.0, null, null,null, null), StArrayElement(0.0, null, null,null, null))
|
||||||
val stVar3 = StStaticVariable("initialized", DataType.arrayFor(BaseDataType.UWORD), null, arrayInitNonzero, 3u, ZeropageWish.DONTCARE, 0u, false, node)
|
val stVar3 = StStaticVariable("initialized", DataType.arrayFor(BaseDataType.UWORD), null, arrayInitNonzero, 3u, ZeropageWish.DONTCARE, 0u, false, node)
|
||||||
val stVar4 = StStaticVariable("initialized", DataType.arrayFor(BaseDataType.UWORD), null, arrayInitAllzero, 3u, ZeropageWish.DONTCARE, 0u, false, node)
|
val stVar4 = StStaticVariable("initialized", DataType.arrayFor(BaseDataType.UWORD), null, arrayInitAllzero, 3u, ZeropageWish.DONTCARE, 0u, false, node)
|
||||||
val stVar5 = StStaticVariable("uninitialized", DataType.arrayFor(BaseDataType.UWORD), null, null, 3u, ZeropageWish.DONTCARE, 0u, false, node)
|
val stVar5 = StStaticVariable("uninitialized", DataType.arrayFor(BaseDataType.UWORD), null, null, 3u, ZeropageWish.DONTCARE, 0u, false, node)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import io.kotest.matchers.string.shouldContain
|
|||||||
import prog8.ast.AstToSourceTextConverter
|
import prog8.ast.AstToSourceTextConverter
|
||||||
import prog8.ast.Module
|
import prog8.ast.Module
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.code.INTERNED_STRINGS_MODULENAME
|
import prog8.code.PROG8_CONTAINER_MODULES
|
||||||
import prog8.code.source.SourceCode
|
import prog8.code.source.SourceCode
|
||||||
import prog8.parser.ParseError
|
import prog8.parser.ParseError
|
||||||
import prog8.parser.Prog8Parser.parseModule
|
import prog8.parser.Prog8Parser.parseModule
|
||||||
@@ -38,10 +38,12 @@ class TestAstToSourceText: AnnotationSpec() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMentionsInternedStringsModule() {
|
fun testMentionsProg8ContainerModules() {
|
||||||
val orig = SourceCode.Text("\n")
|
val orig = SourceCode.Text("\n")
|
||||||
val (txt, _) = roundTrip(parseModule(orig))
|
val (txt, _) = roundTrip(parseModule(orig))
|
||||||
txt shouldContain Regex(";.*$INTERNED_STRINGS_MODULENAME")
|
PROG8_CONTAINER_MODULES.forEach {
|
||||||
|
txt shouldContain Regex(";.*$it")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ import io.kotest.matchers.types.shouldBeSameInstanceAs
|
|||||||
import prog8.ast.Module
|
import prog8.ast.Module
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.statements.Block
|
import prog8.ast.statements.Block
|
||||||
|
import prog8.code.INTERNED_STRINGS_MODULENAME
|
||||||
|
import prog8.code.PROG8_CONTAINER_MODULES
|
||||||
import prog8.code.ast.PtBlock
|
import prog8.code.ast.PtBlock
|
||||||
import prog8.code.core.Position
|
import prog8.code.core.Position
|
||||||
import prog8.code.source.SourceCode
|
import prog8.code.source.SourceCode
|
||||||
import prog8.code.INTERNED_STRINGS_MODULENAME
|
|
||||||
import prog8.code.target.C64Target
|
import prog8.code.target.C64Target
|
||||||
import prog8tests.helpers.DummyFunctions
|
import prog8tests.helpers.DummyFunctions
|
||||||
import prog8tests.helpers.DummyMemsizer
|
import prog8tests.helpers.DummyMemsizer
|
||||||
@@ -30,7 +31,7 @@ class TestProgram: FunSpec({
|
|||||||
context("Constructor") {
|
context("Constructor") {
|
||||||
test("withNameBuiltinsAndMemsizer") {
|
test("withNameBuiltinsAndMemsizer") {
|
||||||
val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||||
program.modules.size shouldBe 1
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||||
program.modules[0].name shouldBe INTERNED_STRINGS_MODULENAME
|
program.modules[0].name shouldBe INTERNED_STRINGS_MODULENAME
|
||||||
program.modules[0].program shouldBeSameInstanceAs program
|
program.modules[0].program shouldBeSameInstanceAs program
|
||||||
program.modules[0].parent shouldBeSameInstanceAs program.namespace
|
program.modules[0].parent shouldBeSameInstanceAs program.namespace
|
||||||
@@ -45,7 +46,7 @@ class TestProgram: FunSpec({
|
|||||||
val retVal = program.addModule(m1)
|
val retVal = program.addModule(m1)
|
||||||
|
|
||||||
retVal shouldBeSameInstanceAs program
|
retVal shouldBeSameInstanceAs program
|
||||||
program.modules.size shouldBe 2
|
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size + 1
|
||||||
m1 shouldBeIn program.modules
|
m1 shouldBeIn program.modules
|
||||||
m1.program shouldBeSameInstanceAs program
|
m1.program shouldBeSameInstanceAs program
|
||||||
m1.parent shouldBeSameInstanceAs program.namespace
|
m1.parent shouldBeSameInstanceAs program.namespace
|
||||||
@@ -163,7 +164,7 @@ datablock2 ${'$'}8000 {
|
|||||||
|
|
||||||
val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly=true)!!
|
val result = compileText(C64Target(), optimize=false, src, outputDir, writeAssembly=true)!!
|
||||||
result.compilerAst.allBlocks.size shouldBeGreaterThan 5
|
result.compilerAst.allBlocks.size shouldBeGreaterThan 5
|
||||||
result.compilerAst.modules.drop(2).all { it.isLibrary } shouldBe true
|
result.compilerAst.modules.drop(PROG8_CONTAINER_MODULES.size+1).all { it.isLibrary } shouldBe true
|
||||||
val mainMod = result.compilerAst.modules[0]
|
val mainMod = result.compilerAst.modules[0]
|
||||||
mainMod.name shouldStartWith "on_the_fly"
|
mainMod.name shouldStartWith "on_the_fly"
|
||||||
result.compilerAst.modules[1].name shouldBe "prog8_interned_strings"
|
result.compilerAst.modules[1].name shouldBe "prog8_interned_strings"
|
||||||
@@ -183,7 +184,7 @@ datablock2 ${'$'}8000 {
|
|||||||
blocks[1].name shouldBe "p8_sys_startup"
|
blocks[1].name shouldBe "p8_sys_startup"
|
||||||
blocks[2].name shouldBe "p8b_otherblock1"
|
blocks[2].name shouldBe "p8b_otherblock1"
|
||||||
blocks[3].name shouldBe "p8b_otherblock2"
|
blocks[3].name shouldBe "p8b_otherblock2"
|
||||||
blocks[4].name shouldBe "prog8_interned_strings"
|
blocks[4].name shouldBe INTERNED_STRINGS_MODULENAME
|
||||||
blocks[5].name shouldBe "txt"
|
blocks[5].name shouldBe "txt"
|
||||||
blocks[5].library shouldBe true
|
blocks[5].library shouldBe true
|
||||||
blocks[13].name shouldBe "p8b_datablock2"
|
blocks[13].name shouldBe "p8b_datablock2"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import prog8.ast.statements.*
|
|||||||
import prog8.ast.walk.IAstVisitor
|
import prog8.ast.walk.IAstVisitor
|
||||||
import prog8.code.GENERATED_LABEL_PREFIX
|
import prog8.code.GENERATED_LABEL_PREFIX
|
||||||
import prog8.code.INTERNED_STRINGS_MODULENAME
|
import prog8.code.INTERNED_STRINGS_MODULENAME
|
||||||
|
import prog8.code.PROG8_CONTAINER_MODULES
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.code.source.SourceCode
|
import prog8.code.source.SourceCode
|
||||||
|
|
||||||
@@ -22,17 +23,19 @@ class Program(val name: String,
|
|||||||
val namespace: GlobalNamespace = GlobalNamespace(_modules)
|
val namespace: GlobalNamespace = GlobalNamespace(_modules)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// insert a container module for all interned strings later
|
// insert container modules for all interned strings and struct instances
|
||||||
val internedStringsModule = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated(INTERNED_STRINGS_MODULENAME))
|
PROG8_CONTAINER_MODULES.forEach { containername ->
|
||||||
val block = Block(INTERNED_STRINGS_MODULENAME, null, mutableListOf(), true, Position.DUMMY)
|
val module = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated(containername))
|
||||||
|
val block = Block(containername, null, mutableListOf(), true, Position.DUMMY)
|
||||||
val directive = Directive("%option", listOf(DirectiveArg("no_symbol_prefixing", null, Position.DUMMY)), Position.DUMMY)
|
val directive = Directive("%option", listOf(DirectiveArg("no_symbol_prefixing", null, Position.DUMMY)), Position.DUMMY)
|
||||||
block.statements.add(directive)
|
block.statements.add(directive)
|
||||||
directive.linkParents(block)
|
directive.linkParents(block)
|
||||||
internedStringsModule.statements.add(block)
|
module.statements.add(block)
|
||||||
|
|
||||||
_modules.add(0, internedStringsModule)
|
_modules.add(0, module)
|
||||||
internedStringsModule.linkParents(namespace)
|
module.linkParents(namespace)
|
||||||
internedStringsModule.program = this
|
module.program = this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addModule(module: Module): Program {
|
fun addModule(module: Module): Program {
|
||||||
@@ -67,7 +70,7 @@ class Program(val name: String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
val toplevelModule: Module
|
val toplevelModule: Module
|
||||||
get() = modules.first { it.name!= INTERNED_STRINGS_MODULENAME }
|
get() = modules.first { it.name !in PROG8_CONTAINER_MODULES }
|
||||||
|
|
||||||
private val internedStringsReferenceCounts = mutableMapOf<VarDecl, Int>()
|
private val internedStringsReferenceCounts = mutableMapOf<VarDecl, Int>()
|
||||||
|
|
||||||
|
|||||||
@@ -52,10 +52,7 @@ needs_sphinx = '5.3'
|
|||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
# ones.
|
# ones.
|
||||||
extensions = [ 'sphinxcontrib.jquery', 'sphinx_rtd_dark_mode']
|
extensions = [ 'sphinxcontrib.jquery', 'sphinx_rtd_dark_mode', 'sphinx.ext.imgconverter']
|
||||||
|
|
||||||
# user starts in light mode
|
|
||||||
default_dark_mode = False
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['_templates']
|
templates_path = ['_templates']
|
||||||
@@ -177,6 +174,9 @@ texinfo_documents = [
|
|||||||
|
|
||||||
# -- Extension configuration -------------------------------------------------
|
# -- Extension configuration -------------------------------------------------
|
||||||
|
|
||||||
|
# user starts in light mode
|
||||||
|
default_dark_mode = False
|
||||||
|
|
||||||
# -- Options for to do extension ----------------------------------------------
|
# -- Options for to do extension ----------------------------------------------
|
||||||
|
|
||||||
# todo_include_todos = True
|
# todo_include_todos = True
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ and for example the below code omits line 5::
|
|||||||
STRUCTS and TYPED POINTERS
|
STRUCTS and TYPED POINTERS
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
- allow struct initialization syntax in an array such as [ ^^Node:[], ^^Node:[], ^^Node:[] ], update sorting example to use list of countries like that
|
- can we have some syntactic sugar to avoid the struct name pointer prefix for all array elements that are a struct instance?
|
||||||
|
- fix VM so that pointers/sorting.p8 example works again (it worked when adding the struct instances in a loop, no longer now that they're static)
|
||||||
- fix code size regressions (if any left)
|
- fix code size regressions (if any left)
|
||||||
- optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
|
- optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
|
||||||
- update structpointers.rst docs with 6502 specific things?
|
- update structpointers.rst docs with 6502 specific things?
|
||||||
@@ -79,6 +80,7 @@ STRUCTS and TYPED POINTERS
|
|||||||
Future Things and Ideas
|
Future Things and Ideas
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- allow memory() to occur in array initializer
|
||||||
- %breakpoint after an assignment is parsed as part of the expression (x % breakpoint), that should not happen
|
- %breakpoint after an assignment is parsed as part of the expression (x % breakpoint), that should not happen
|
||||||
- when a complete block is removed because unused, suppress all info messages about everything in the block being removed
|
- when a complete block is removed because unused, suppress all info messages about everything in the block being removed
|
||||||
- fix the line, cols in Position, sometimes they count from 0 sometimes from 1
|
- fix the line, cols in Position, sometimes they count from 0 sometimes from 1
|
||||||
|
|||||||
@@ -282,9 +282,10 @@ For instance ``30_000.999_999`` is a valid floating point number 30000.999999.
|
|||||||
|
|
||||||
Arrays
|
Arrays
|
||||||
^^^^^^
|
^^^^^^
|
||||||
Arrays can be created from a list of booleans, bytes, words, floats, or addresses of other variables
|
Arrays can be created from a list of booleans, bytes, words, floats, addresses of other variables
|
||||||
(such as explicit address-of expressions, strings, or other array variables) - values in an array literal
|
(such as explicit address-of expressions, strings, or other array variables), and struct initializers.
|
||||||
always have to be constants. A trailing comma is allowed, sometimes this is easier when copying values
|
The values in an array literal always have to be constants.
|
||||||
|
A trailing comma is allowed, sometimes this is easier when copying values
|
||||||
or when adding more stuff to the array later. Here are some examples of arrays::
|
or when adding more stuff to the array later. Here are some examples of arrays::
|
||||||
|
|
||||||
byte[10] array ; array of 10 bytes, initially set to 0
|
byte[10] array ; array of 10 bytes, initially set to 0
|
||||||
|
|||||||
@@ -11,34 +11,32 @@ main{
|
|||||||
uword area ; 1000 km^2
|
uword area ; 1000 km^2
|
||||||
}
|
}
|
||||||
|
|
||||||
^^Country[100] countries ; won't be fully filled
|
^^Country[] countries = [
|
||||||
ubyte num_countries
|
^^Country:["Indonesia", 285.72, 1904],
|
||||||
|
^^Country:["Congo", 112.83, 2344],
|
||||||
|
^^Country:["Vietnam", 101.60, 331],
|
||||||
|
^^Country:["United States", 347.28, 9372],
|
||||||
|
^^Country:["Iran", 92.42, 1648],
|
||||||
|
^^Country:["Turkey", 87.69, 783],
|
||||||
|
^^Country:["Brazil", 212.81, 8515],
|
||||||
|
^^Country:["Bangladesh", 175.69, 147],
|
||||||
|
^^Country:["Germany", 84.08, 357],
|
||||||
|
^^Country:["Japan", 123.10, 377],
|
||||||
|
^^Country:["India", 1463.87, 3287],
|
||||||
|
^^Country:["China", 1416.10, 9596],
|
||||||
|
^^Country:["Philippines", 116.79, 300],
|
||||||
|
^^Country:["Russia", 143.99, 17098],
|
||||||
|
^^Country:["Pakistan", 255.22, 881],
|
||||||
|
^^Country:["Nigeria", 237.53, 923],
|
||||||
|
^^Country:["Ethiopia", 135.47, 1104],
|
||||||
|
^^Country:["Mexico", 131.95, 1964],
|
||||||
|
^^Country:["Thailand", 71.62, 513],
|
||||||
|
^^Country:["Egypt", 118.37, 1002],
|
||||||
|
]
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
txt.lowercase()
|
txt.lowercase()
|
||||||
|
|
||||||
; because pointer array initialization is not supported yet, we have to add the countries in separate statements for now
|
|
||||||
add(^^Country:["Indonesia", 285.72, 1904])
|
|
||||||
add(^^Country:["Congo", 112.83, 2344])
|
|
||||||
add(^^Country:["Vietnam", 101.60, 331])
|
|
||||||
add(^^Country:["United States", 347.28, 9372])
|
|
||||||
add(^^Country:["Iran", 92.42, 1648])
|
|
||||||
add(^^Country:["Turkey", 87.69, 783])
|
|
||||||
add(^^Country:["Brazil", 212.81, 8515])
|
|
||||||
add(^^Country:["Bangladesh", 175.69, 147])
|
|
||||||
add(^^Country:["Germany", 84.08, 357])
|
|
||||||
add(^^Country:["Japan", 123.10, 377])
|
|
||||||
add(^^Country:["India", 1463.87, 3287])
|
|
||||||
add(^^Country:["China", 1416.10, 9596])
|
|
||||||
add(^^Country:["Philippines", 116.79, 300])
|
|
||||||
add(^^Country:["Russia", 143.99, 17098])
|
|
||||||
add(^^Country:["Pakistan", 255.22, 881])
|
|
||||||
add(^^Country:["Nigeria", 237.53, 923])
|
|
||||||
add(^^Country:["Ethiopia", 135.47, 1104])
|
|
||||||
add(^^Country:["Mexico", 131.95, 1964])
|
|
||||||
add(^^Country:["Thailand", 71.62, 513])
|
|
||||||
add(^^Country:["Egypt", 118.37, 1002])
|
|
||||||
|
|
||||||
txt.print("UNSORTED:\n")
|
txt.print("UNSORTED:\n")
|
||||||
dump()
|
dump()
|
||||||
|
|
||||||
@@ -57,7 +55,7 @@ main{
|
|||||||
|
|
||||||
sub sort_by_name() {
|
sub sort_by_name() {
|
||||||
; stupid slow bubble sort
|
; stupid slow bubble sort
|
||||||
ubyte n = num_countries
|
ubyte n = len(countries)
|
||||||
do {
|
do {
|
||||||
ubyte newn=0
|
ubyte newn=0
|
||||||
ubyte i
|
ubyte i
|
||||||
@@ -73,7 +71,7 @@ main{
|
|||||||
|
|
||||||
sub sort_by_population() {
|
sub sort_by_population() {
|
||||||
; stupid slow bubble sort
|
; stupid slow bubble sort
|
||||||
ubyte n = num_countries
|
ubyte n = len(countries)
|
||||||
do {
|
do {
|
||||||
ubyte newn=0
|
ubyte newn=0
|
||||||
ubyte i
|
ubyte i
|
||||||
@@ -89,7 +87,7 @@ main{
|
|||||||
|
|
||||||
sub sort_by_area() {
|
sub sort_by_area() {
|
||||||
; stupid slow bubble sort
|
; stupid slow bubble sort
|
||||||
ubyte n = num_countries
|
ubyte n = len(countries)
|
||||||
do {
|
do {
|
||||||
ubyte newn=0
|
ubyte newn=0
|
||||||
ubyte i
|
ubyte i
|
||||||
@@ -125,10 +123,5 @@ main{
|
|||||||
txt.nl()
|
txt.nl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub add(^^Country c) {
|
|
||||||
countries[num_countries] = c
|
|
||||||
num_countries++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,19 +8,20 @@ main {
|
|||||||
uword array
|
uword array
|
||||||
}
|
}
|
||||||
|
|
||||||
^^Node @shared @zp node = 2000
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
^^Node[] nodes = [
|
^^Node[] nodes = [
|
||||||
^^Node:[1,"one", 1000 ],
|
^^Node:[1,"one", 1000 ],
|
||||||
^^Node:[2,"two", 2000 ],
|
^^Node:[2,"two", 2000 ],
|
||||||
^^Node:[3,"three", 3000]
|
^^Node:[3,"three", 3000],
|
||||||
|
^^Node:[],
|
||||||
|
^^Node:[],
|
||||||
|
^^Node:[],
|
||||||
]
|
]
|
||||||
txt.print_uw(nodes[0])
|
|
||||||
|
for cx16.r0 in nodes {
|
||||||
|
txt.print_uw(cx16.r0)
|
||||||
txt.spc()
|
txt.spc()
|
||||||
txt.print_uw(nodes[1])
|
}
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(nodes[2])
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package prog8.intermediate
|
package prog8.intermediate
|
||||||
|
|
||||||
import prog8.code.INTERNED_STRINGS_MODULENAME
|
import prog8.code.PROG8_CONTAINER_MODULES
|
||||||
import prog8.code.core.BaseDataType
|
import prog8.code.core.BaseDataType
|
||||||
import prog8.code.core.DataType
|
import prog8.code.core.DataType
|
||||||
import prog8.code.core.Encoding
|
import prog8.code.core.Encoding
|
||||||
@@ -49,12 +49,11 @@ class IRSymbolTable {
|
|||||||
val prefix = "$label."
|
val prefix = "$label."
|
||||||
val vars = table.filter { it.key.startsWith(prefix) }
|
val vars = table.filter { it.key.startsWith(prefix) }
|
||||||
vars.forEach {
|
vars.forEach {
|
||||||
// check if attempt is made to delete interned strings, if so, refuse that.
|
// check if attempt is made to delete fixed modules, if so, refuse that.
|
||||||
if(!it.key.startsWith(INTERNED_STRINGS_MODULENAME)) {
|
if(!PROG8_CONTAINER_MODULES.any { containername -> it.key.startsWith(containername)})
|
||||||
table.remove(it.key)
|
table.remove(it.key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun validate() {
|
fun validate() {
|
||||||
require(table.all { it.key == it.value.name })
|
require(table.all { it.key == it.value.name })
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class SymbolTable(astProgram: PtProgram) : StNode(astProgram.name, StNodeType.GL
|
|||||||
val scopehash = call.parent.hashCode().toUInt().toString(16)
|
val scopehash = call.parent.hashCode().toUInt().toString(16)
|
||||||
val pos = "${call.position.line}_${call.position.startCol}"
|
val pos = "${call.position.line}_${call.position.startCol}"
|
||||||
val hash = call.position.file.hashCode().toUInt().toString(16)
|
val hash = call.position.file.hashCode().toUInt().toString(16)
|
||||||
return "prog8_struct_${structname.replace('.', '_')}_${hash}_${pos}_${scopehash}"
|
return "${structname.replace('.', '_')}_${hash}_${pos}_${scopehash}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,13 +338,18 @@ class StExtSub(name: String,
|
|||||||
|
|
||||||
class StSubroutineParameter(val name: String, val type: DataType, val register: RegisterOrPair?)
|
class StSubroutineParameter(val name: String, val type: DataType, val register: RegisterOrPair?)
|
||||||
class StExtSubParameter(val register: RegisterOrStatusflag, val type: DataType)
|
class StExtSubParameter(val register: RegisterOrStatusflag, val type: DataType)
|
||||||
class StArrayElement(val number: Double?, val addressOfSymbol: String?, val boolean: Boolean?) {
|
class StArrayElement(val number: Double?, val addressOfSymbol: String?, val structInstance: String?, val structInstanceUninitialized: String?, val boolean: Boolean?) {
|
||||||
init {
|
init {
|
||||||
if(number!=null) require(addressOfSymbol==null && boolean==null)
|
if(number!=null) require(addressOfSymbol==null && boolean==null && structInstance==null && structInstanceUninitialized==null)
|
||||||
if(addressOfSymbol!=null) require(number==null && boolean==null)
|
if(addressOfSymbol!=null) require(number==null && boolean==null && structInstance==null && structInstanceUninitialized==null)
|
||||||
if(boolean!=null) require(addressOfSymbol==null && number==null)
|
if(structInstance!=null) require(number==null && boolean==null && addressOfSymbol==null && structInstanceUninitialized==null)
|
||||||
|
if(structInstanceUninitialized!=null) require(number==null && boolean==null && addressOfSymbol==null && structInstance==null)
|
||||||
|
if(boolean!=null) require(addressOfSymbol==null && number==null &&structInstance==null && structInstanceUninitialized==null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias StString = Pair<String, Encoding>
|
typealias StString = Pair<String, Encoding>
|
||||||
typealias StArray = List<StArrayElement>
|
typealias StArray = List<StArrayElement>
|
||||||
|
|
||||||
|
const val StMemorySlabBlockName = "prog8_slabs"
|
||||||
|
const val StStructInstanceBlockName = "prog8_struct_instances"
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
|
|||||||
numElements = (value.value.length + 1).toUInt() // include the terminating 0-byte
|
numElements = (value.value.length + 1).toUInt() // include the terminating 0-byte
|
||||||
}
|
}
|
||||||
is PtArray -> {
|
is PtArray -> {
|
||||||
initialArray = makeInitialArray(value)
|
initialArray = makeInitialArray(value, scope)
|
||||||
initialString = null
|
initialString = null
|
||||||
initialNumeric = null
|
initialNumeric = null
|
||||||
numElements = initialArray.size.toUInt()
|
numElements = initialArray.size.toUInt()
|
||||||
@@ -119,22 +119,12 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
|
|||||||
val size = (node.args[1] as PtNumber).number.toUInt()
|
val size = (node.args[1] as PtNumber).number.toUInt()
|
||||||
val align = (node.args[2] as PtNumber).number.toUInt()
|
val align = (node.args[2] as PtNumber).number.toUInt()
|
||||||
// don't add memory slabs in nested scope, just put them in the top level of the ST
|
// don't add memory slabs in nested scope, just put them in the top level of the ST
|
||||||
scope.first().add(StMemorySlab("prog8_memoryslab_$slabname", size, align, node))
|
scope.first().add(StMemorySlab("memory_$slabname", size, align, node))
|
||||||
}
|
}
|
||||||
else if(node.name=="prog8_lib_structalloc") {
|
else if(node.name=="prog8_lib_structalloc") {
|
||||||
val struct = node.type.subType!!
|
val instance = handleStructAllocation(node)
|
||||||
if(struct is StStruct) {
|
if(instance!=null) {
|
||||||
val label = SymbolTable.labelnameForStructInstance(node)
|
scope.first().add(instance) // don't add struct instances in nested scope, just put them in the top level of the ST
|
||||||
val initialValues = node.args.map {
|
|
||||||
when(it) {
|
|
||||||
is PtAddressOf -> StArrayElement(null, it.identifier!!.name, null)
|
|
||||||
is PtBool -> StArrayElement(null, null, it.value)
|
|
||||||
is PtNumber -> StArrayElement(it.number, null, null)
|
|
||||||
else -> throw AssemblyError("invalid structalloc argument type $it")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val scopedName = if(struct.astNode!=null) (struct.astNode as PtNamedNode).scopedName else struct.scopedNameString
|
|
||||||
scope.first().add(StStructInstance(label, scopedName, initialValues, struct.size, null))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
null
|
null
|
||||||
@@ -153,20 +143,50 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
|
|||||||
scope.removeLast()
|
scope.removeLast()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeInitialArray(value: PtArray): List<StArrayElement> {
|
private fun handleStructAllocation(node: PtBuiltinFunctionCall): StStructInstance? {
|
||||||
|
val struct = node.type.subType as? StStruct ?: return null
|
||||||
|
val initialValues = node.args.map {
|
||||||
|
when(it) {
|
||||||
|
is PtAddressOf -> StArrayElement(null, it.identifier!!.name, null, null,null)
|
||||||
|
is PtBool -> StArrayElement(null, null, null, null, it.value)
|
||||||
|
is PtNumber -> StArrayElement(it.number, null, null, null, null)
|
||||||
|
else -> throw AssemblyError("invalid structalloc argument type $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val label = SymbolTable.labelnameForStructInstance(node)
|
||||||
|
val scopedStructName = if(struct.astNode!=null) (struct.astNode as PtNamedNode).scopedName else struct.scopedNameString
|
||||||
|
return StStructInstance(label, scopedStructName, initialValues, struct.size, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun makeInitialArray(value: PtArray, scope: ArrayDeque<StNode>): List<StArrayElement> {
|
||||||
return value.children.map {
|
return value.children.map {
|
||||||
when(it) {
|
when(it) {
|
||||||
is PtAddressOf -> {
|
is PtAddressOf -> {
|
||||||
when {
|
when {
|
||||||
it.isFromArrayElement -> TODO("address-of array element $it in initial array value")
|
it.isFromArrayElement -> TODO("address-of array element $it in initial array value")
|
||||||
else -> StArrayElement(null, it.identifier!!.name, null)
|
else -> StArrayElement(null, it.identifier!!.name, null, null,null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is PtNumber -> StArrayElement(it.number, null, null)
|
is PtNumber -> StArrayElement(it.number, null, null,null,null)
|
||||||
is PtBool -> StArrayElement(null, null, it.value)
|
is PtBool -> StArrayElement(null, null, null,null,it.value)
|
||||||
is PtBuiltinFunctionCall -> {
|
is PtBuiltinFunctionCall -> {
|
||||||
val labelname = SymbolTable.labelnameForStructInstance(it)
|
if(it.name=="prog8_lib_structalloc") {
|
||||||
StArrayElement(null, labelname, null)
|
val instance = handleStructAllocation(it)
|
||||||
|
if(instance==null) {
|
||||||
|
val label = SymbolTable.labelnameForStructInstance(it)
|
||||||
|
if (it.args.isEmpty())
|
||||||
|
StArrayElement(null, null, null, label, null)
|
||||||
|
else
|
||||||
|
StArrayElement(null, null, label, null, null)
|
||||||
|
} else {
|
||||||
|
scope.first().add(instance) // don't add struct instances in nested scope, just put them in the top level of the ST
|
||||||
|
if (it.args.isEmpty())
|
||||||
|
StArrayElement(null, null, null, instance.name, null)
|
||||||
|
else
|
||||||
|
StArrayElement(null, null, instance.name, null, null)
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
TODO("support for initial array element via ${it.name} ${it.position}")
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("invalid array element $it")
|
else -> throw AssemblyError("invalid array element $it")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user