improve ast source position tracking

This commit is contained in:
Irmen de Jong committed 2026-03-29 19:49:42 +02:00
1 parent 05093e35c8
commit 331e2b8f2b
12 files changed
+46 -46

No files matched your search

@@ -169,7 +169,7 @@ class AsmGen6502(val prefixSymbols: Boolean, private val lastGeneratedLabelSeque
functionCallsToPrefix.reversed().forEach { (parent, index) ->
val node = parent.children[index]
if(node is PtFunctionCall) {
val prefixedName = PtIdentifier(node.name, DataType.UNDEFINED, Position.DUMMY).prefix(parent, st)
val prefixedName = PtIdentifier(node.name, DataType.UNDEFINED, node.position).prefix(parent, st)
val prefixedNode = node.withNewName(prefixedName.name)
parent.children[index] = prefixedNode
} else {
@@ -333,7 +333,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
// we need to sign extend the source, do this via temporary word variable
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_W1", DataType.UBYTE)
asmgen.signExtendVariableLsb("P8ZP_SCRATCH_W1", value.type.base)
asmgen.assignVariableToRegister("P8ZP_SCRATCH_W1", register, null, Position.DUMMY)
asmgen.assignVariableToRegister("P8ZP_SCRATCH_W1", register, null, value.position)
} else {
val scope = value.definingISub()
val target: AsmAssignTarget =
@@ -344,7 +344,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
}
val src = if(value.type.isPassByRef) {
if(value is PtIdentifier) {
val addr = PtAddressOf(value.type.typeForAddressOf(false), false, Position.DUMMY)
val addr = PtAddressOf(value.type.typeForAddressOf(false), false, value.position)
addr.add(value)
addr.parent = scope as PtNode
AsmAssignSource.fromAstSource(addr, program, asmgen).adjustSignedUnsigned(target)
@@ -742,7 +742,7 @@ internal class ProgramAndVarsGen(
it.initializationStringValue!!.second,
it.initializationStringValue!!.first
)
asmgen.romableError("string (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var
asmgen.romableError("string (${it.dt} ${it.name}) can only be used as read-only in ROMable code", it.astNode?.position ?: Position.DUMMY, false)
}
alignedStrings.sortedBy { it.align }.forEach {
outputStringvar(
@@ -751,22 +751,22 @@ internal class ProgramAndVarsGen(
it.initializationStringValue!!.second,
it.initializationStringValue!!.first
)
asmgen.romableError("string (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var
asmgen.romableError("string (${it.dt} ${it.name}) can only be used as read-only in ROMable code", it.astNode?.position ?: Position.DUMMY, false)
}
notAlignedOther.sortedBy { it.type }.forEach {
staticVariable2asm(it)
if(it.dt.isArray)
asmgen.romableError("array (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var
asmgen.romableError("array (${it.dt} ${it.name}) can only be used as read-only in ROMable code", it.astNode?.position ?: Position.DUMMY, false)
else
asmgen.romableError("inlined variable (${it.dt} ${it.name})", Position.DUMMY) // TODO print warning with position of the var
asmgen.romableError("inlined variable (${it.dt} ${it.name})", it.astNode?.position ?: Position.DUMMY)
}
alignedOther.sortedBy { it.align }.sortedBy { it.type }.forEach {
staticVariable2asm(it)
if(it.dt.isArray)
asmgen.romableError("array (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var
asmgen.romableError("array (${it.dt} ${it.name}) can only be used as read-only in ROMable code", it.astNode?.position ?: Position.DUMMY, false)
else
asmgen.romableError("inlined variable (${it.dt} ${it.name})", Position.DUMMY) // TODO print warning with position of the var
asmgen.romableError("inlined variable (${it.dt} ${it.name})", it.astNode?.position ?: Position.DUMMY)
}
}
}
@@ -5434,7 +5434,7 @@ $endLabel""")
internal fun assignVariableToRegister(asmVarName: String, register: RegisterOrPair, signed: Boolean, scope: IPtSubroutine?, pos: Position) {
val tgt = AsmAssignTarget.fromRegisters(register, signed, pos, null, asmgen)
val src = AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, tgt.datatype, variableAsmName = asmVarName)
val assign = AsmAssignment(src, listOf(tgt), program.memsizer, Position.DUMMY)
val assign = AsmAssignment(src, listOf(tgt), program.memsizer, pos)
translateNormalAssignment(assign, scope)
}
@@ -1193,9 +1193,9 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
val assignValue = AsmAssignment(value,
listOf(
AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, DataType.UBYTE,
address.definingISub(), Position.DUMMY, register = RegisterOrPair.A)
address.definingISub(), address.position, register = RegisterOrPair.A)
),
program.memsizer, Position.DUMMY)
program.memsizer, address.position)
assignmentAsmGen.translateNormalAssignment(assignValue, address.definingISub()) // calculate value into A
}
@@ -60,7 +60,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
// note: multi-value returns are passed throug A or AY (for the first value) then cx16.R15 down to R0
// (this allows unencumbered use of many Rx registers if you don't return that many values)
val returntypes = BuiltinFunctions.getValue(thing.name).returnTypes
val signature = PtSubSignature(returntypes.map { DataType.forDt(it) }, Position.DUMMY)
val signature = PtSubSignature(returntypes.map { DataType.forDt(it) }, values.position)
val returnregs = signature.returnsWhatWhere()
assignmentTargets.zip(returnregs).forEach {
val target = it.first as PtAssignTarget
@@ -1479,4 +1479,4 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
}
return result
}
}
}
@@ -452,7 +452,7 @@ internal class ConstantIdentifierReplacer(
if(targetDatatype.isArray) {
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, targetDatatype.getOrUndef(),
ZeropageWish.DONTCARE, SplitWish.NOSPLIT, null, "dummy", emptyList(),
assignment.value, false, 0u, false, Position.DUMMY)
assignment.value, false, 0u, false, assignment.value.position)
val replaceValue = createConstArrayInitializerValue(decl)
if(replaceValue!=null) {
return listOf(IAstModification.ReplaceNode(assignment.value, replaceValue, assignment))
@@ -56,7 +56,7 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
if(subroutine.returntypes.isNotEmpty())
errors.err("subroutine is missing a return statement with value(s)", subroutine.position)
else {
val returnStmt = Return(arrayOf(), Position.DUMMY)
val returnStmt = Return(arrayOf(), subroutine.position)
mods += IAstModification.InsertLast(returnStmt, subroutine)
}
} else {
@@ -68,7 +68,7 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
// .... we cannot return this as an error, because that also breaks legitimate cases where the return is done from within a nested scope somewhere
// errors.err("subroutine is missing a return statement with value(s)", subroutine.position)
} else {
val returnStmt = Return(arrayOf(), Position.DUMMY)
val returnStmt = Return(arrayOf(), lastStatement?.position ?: subroutine.position)
mods += IAstModification.InsertLast(returnStmt, subroutine)
}
}
@@ -92,7 +92,7 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
if(outerScope.returntypes.size>1 || !(outerScope.returntypes[0].isNumericOrBool || outerScope.returntypes[0].isPointer)) {
errors.err("subroutine is missing a return statement to avoid falling through into nested subroutine", outerStatements[subroutineStmtIdx-1].position)
} else {
val zero = defaultZero(outerScope.returntypes[0].base, Position.DUMMY)
val zero = defaultZero(outerScope.returntypes[0].base, outerStatements[subroutineStmtIdx-1].position)
val returnStmt = Return(arrayOf(zero), outerStatements[subroutineStmtIdx - 1].position)
mods += IAstModification.InsertAfter(outerStatements[subroutineStmtIdx - 1], returnStmt, outerScope)
}
@@ -170,33 +170,33 @@ internal object DeferProcessor {
for( (sub, defers) in subdefers) {
// create the routine that calls the enabled defers in reverse order
val defersRoutine = PtSub(invokeDefersRoutineName, emptyList(), emptyList(), Position.DUMMY)
val defersRoutine = PtSub(invokeDefersRoutineName, emptyList(), emptyList(), sub.position)
defersRoutine.parent=sub
for((idx, defer) in defers.reversed().withIndex()) {
val shift = PtAugmentedAssign(">>=", Position.DUMMY)
shift.add(PtAssignTarget(false, sub.position).also {
it.add(PtIdentifier(sub.scopedName+"."+maskVarName, DataType.UBYTE, sub.position))
val shift = PtAugmentedAssign(">>=", defer.position)
shift.add(PtAssignTarget(false, defer.position).also {
it.add(PtIdentifier(sub.scopedName+"."+maskVarName, DataType.UBYTE, defer.position))
})
shift.add(PtNumber(BaseDataType.UBYTE, 1.0, sub.position))
shift.add(PtNumber(BaseDataType.UBYTE, 1.0, defer.position))
defersRoutine.add(shift)
val skiplabel = "prog8_defer_skip_${idx+1}"
val branchcc = PtConditionalBranch(BranchCondition.CC, Position.DUMMY)
val branchcc = PtConditionalBranch(BranchCondition.CC, defer.position)
branchcc.add(PtNodeGroup().also {
val jump = PtJump(Position.DUMMY)
jump.add(PtIdentifier(defersRoutine.scopedName+"."+skiplabel, DataType.UBYTE, Position.DUMMY))
val jump = PtJump(defer.position)
jump.add(PtIdentifier(defersRoutine.scopedName+"."+skiplabel, DataType.UBYTE, defer.position))
it.add(jump)
})
branchcc.add(PtNodeGroup())
defersRoutine.add(branchcc)
transferChildren(defer, defersRoutine, true)
defersRoutine.add(PtLabel(skiplabel, Position.DUMMY))
defersRoutine.add(PtLabel(skiplabel, defer.position))
}
// val printMask = PtFunctionCall("txt.print_ubbin", true, DataType.UNDEFINED, Position.DUMMY)
// printMask.add(PtIdentifier(sub.scopedName+"."+maskVarName, DataType.UBYTE, Position.DUMMY))
// printMask.add(PtBool(true, Position.DUMMY))
// val printMask = PtFunctionCall("txt.print_ubbin", true, DataType.UNDEFINED, sub.position)
// printMask.add(PtIdentifier(sub.scopedName+"."+maskVarName, DataType.UBYTE, sub.position))
// printMask.add(PtBool(true, sub.position))
// defersRoutine.add(printMask)
defersRoutine.add(PtReturn(Position.DUMMY))
defersRoutine.add(PtReturn(sub.position))
sub.add(defersRoutine)
}
}
+11 -11
View File
@@ -332,17 +332,17 @@ class TestCompilerOnExamplesVirtual: FunSpec({
val onlyVirtual = cartesianProduct(
listOf(
ExampleSizes("bouncegfx", virtualLineCountOptimized=890, virtualLineCountUnoptimized=3552),
ExampleSizes("bsieve", virtualLineCountOptimized=800, virtualLineCountUnoptimized=4486),
ExampleSizes("fountain", virtualLineCountOptimized=720, virtualLineCountUnoptimized=3397),
ExampleSizes("pixelshader", virtualLineCountOptimized=368, virtualLineCountUnoptimized=1216),
ExampleSizes("sincos", virtualLineCountOptimized=1075, virtualLineCountUnoptimized=3600),
ExampleSizes("pointers/animalgame", virtualLineCountOptimized=879, virtualLineCountUnoptimized=8556),
ExampleSizes("pointers/binarytree", virtualLineCountOptimized=1998, virtualLineCountUnoptimized=5657),
ExampleSizes("pointers/hashtable", virtualLineCountOptimized=2232, virtualLineCountUnoptimized=9107),
ExampleSizes("pointers/sortedlist", virtualLineCountOptimized=1102, virtualLineCountUnoptimized=6642),
ExampleSizes("pointers/fountain-virtual", virtualLineCountOptimized=757, virtualLineCountUnoptimized=3436),
ExampleSizes("pointers/sorting", virtualLineCountOptimized=1532, virtualLineCountUnoptimized=9329)
ExampleSizes("bouncegfx", virtualLineCountOptimized=916, virtualLineCountUnoptimized=3604),
ExampleSizes("bsieve", virtualLineCountOptimized=828, virtualLineCountUnoptimized=4546),
ExampleSizes("fountain", virtualLineCountOptimized=746, virtualLineCountUnoptimized=3449),
ExampleSizes("pixelshader", virtualLineCountOptimized=390, virtualLineCountUnoptimized=1260),
ExampleSizes("sincos", virtualLineCountOptimized=1103, virtualLineCountUnoptimized=3654),
ExampleSizes("pointers/animalgame", virtualLineCountOptimized=894, virtualLineCountUnoptimized=8629),
ExampleSizes("pointers/binarytree", virtualLineCountOptimized=2023, virtualLineCountUnoptimized=5732),
ExampleSizes("pointers/hashtable", virtualLineCountOptimized=2267, virtualLineCountUnoptimized=9178),
ExampleSizes("pointers/sortedlist", virtualLineCountOptimized=1117, virtualLineCountUnoptimized=6713),
ExampleSizes("pointers/fountain-virtual", virtualLineCountOptimized=786, virtualLineCountUnoptimized=3491),
ExampleSizes("pointers/sorting", virtualLineCountOptimized=1548, virtualLineCountUnoptimized=9401)
),
listOf(false, true)
)
+3 -3
View File
@@ -229,8 +229,8 @@ interface INameScope: IStatementContainer, INamedStatement {
return null
if (idx == scopedName.size - 1) {
// was last path element
val pointer = IdentifierReference(scopedName, Position.DUMMY)
val ref = StructFieldRef(pointer, struct as StructDecl, fieldDt, field, Position.DUMMY)
val pointer = IdentifierReference(scopedName, localSymbol.position)
val ref = StructFieldRef(pointer, struct as StructDecl, fieldDt, field, localSymbol.position)
ref.linkParents(this as Node)
return ref
}
@@ -451,4 +451,4 @@ fun defaultZero(dt: BaseDataType, position: Position) = when(dt) {
else -> throw FatalAstException("can only determine default zero value for a numeric type, not for $dt at $position")
}
fun defaultZero(idt: InferredTypes.InferredType, position: Position) = defaultZero(idt.getOrUndef().base, position)
fun defaultZero(idt: InferredTypes.InferredType, position: Position) = defaultZero(idt.getOrUndef().base, position)
@@ -798,7 +798,7 @@ class NumericLiteral(val type: BaseDataType, // only numerical types allowed
operator fun compareTo(other: NumericLiteral): Int = number.compareTo(other.number)
class ValueAfterCast(val isValid: Boolean, val whyFailed: String?, private val value: NumericLiteral?) {
fun valueOrZero() = if(isValid) value!! else NumericLiteral(BaseDataType.UBYTE, 0.0, Position.DUMMY)
fun valueOrZero() = if(isValid) value!! else NumericLiteral(BaseDataType.UBYTE, 0.0, value?.position ?: Position.DUMMY)
fun linkParent(parent: Node) {
value?.linkParents(parent)
}