mirror of
https://github.com/irmen/prog8.git
synced 2024-12-01 15:52:54 +00:00
allow scoped identifiers to reference a subroutine parameter directly.
also for asmsubroutines, but the asm generation for that is not yet done.
This commit is contained in:
parent
0e2e5ffa52
commit
ff715881bc
@ -720,7 +720,6 @@ class AsmGen(private val program: Program,
|
|||||||
internal fun translate(stmt: Statement) {
|
internal fun translate(stmt: Statement) {
|
||||||
outputSourceLine(stmt)
|
outputSourceLine(stmt)
|
||||||
when(stmt) {
|
when(stmt) {
|
||||||
is ParameterVarDecl -> { /* subroutine parameter vardecls don't get any special treatment here */ }
|
|
||||||
is VarDecl -> translate(stmt)
|
is VarDecl -> translate(stmt)
|
||||||
is NopStatement -> {}
|
is NopStatement -> {}
|
||||||
is Directive -> translate(stmt)
|
is Directive -> translate(stmt)
|
||||||
|
@ -62,7 +62,13 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
|||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val dt = idt.getOr(DataType.UNDEFINED)
|
val dt = idt.getOr(DataType.UNDEFINED)
|
||||||
when {
|
when {
|
||||||
identifier != null -> AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, dt, assign.definingSubroutine, variableAsmName = asmgen.asmVariableName(identifier!!), origAstTarget = this)
|
identifier != null -> {
|
||||||
|
val parameter = identifier!!.targetVarDecl(program)?.subroutineParameter
|
||||||
|
if(parameter!=null && parameter.definingSubroutine!!.isAsmSubroutine) {
|
||||||
|
TODO("ASSIGN ASMPARAM $parameter :: $assign")
|
||||||
|
}
|
||||||
|
AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, dt, assign.definingSubroutine, variableAsmName = asmgen.asmVariableName(identifier!!), origAstTarget = this)
|
||||||
|
}
|
||||||
arrayindexed != null -> AsmAssignTarget(TargetStorageKind.ARRAY, program, asmgen, dt, assign.definingSubroutine, array = arrayindexed, origAstTarget = this)
|
arrayindexed != null -> AsmAssignTarget(TargetStorageKind.ARRAY, program, asmgen, dt, assign.definingSubroutine, array = arrayindexed, origAstTarget = this)
|
||||||
memoryAddress != null -> AsmAssignTarget(TargetStorageKind.MEMORY, program, asmgen, dt, assign.definingSubroutine, memory = memoryAddress, origAstTarget = this)
|
memoryAddress != null -> AsmAssignTarget(TargetStorageKind.MEMORY, program, asmgen, dt, assign.definingSubroutine, memory = memoryAddress, origAstTarget = this)
|
||||||
else -> throw AssemblyError("weird target")
|
else -> throw AssemblyError("weird target")
|
||||||
@ -133,6 +139,10 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
|||||||
is StringLiteralValue -> throw AssemblyError("string literal value should not occur anymore for asm generation")
|
is StringLiteralValue -> throw AssemblyError("string literal value should not occur anymore for asm generation")
|
||||||
is ArrayLiteralValue -> throw AssemblyError("array literal value should not occur anymore for asm generation")
|
is ArrayLiteralValue -> throw AssemblyError("array literal value should not occur anymore for asm generation")
|
||||||
is IdentifierReference -> {
|
is IdentifierReference -> {
|
||||||
|
val parameter = value.targetVarDecl(program)?.subroutineParameter
|
||||||
|
if(parameter!=null && parameter.definingSubroutine!!.isAsmSubroutine) {
|
||||||
|
TODO("ASSIGN SOURCE FROM ASMPARAM $parameter :: $value")
|
||||||
|
}
|
||||||
val dt = value.inferType(program).getOr(DataType.UNDEFINED)
|
val dt = value.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
val varName=asmgen.asmVariableName(value)
|
val varName=asmgen.asmVariableName(value)
|
||||||
// special case: "cx16.r[0-15]" are 16-bits virtual registers of the commander X16 system
|
// special case: "cx16.r[0-15]" are 16-bits virtual registers of the commander X16 system
|
||||||
|
@ -46,8 +46,8 @@ class AsmGenSymbolsTests: StringSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
val varInSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "localvar", NumericLiteralValue.optimalInteger(1234, Position.DUMMY), false, false, false, Position.DUMMY)
|
val varInSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "localvar", NumericLiteralValue.optimalInteger(1234, Position.DUMMY), false, false, false, null, Position.DUMMY)
|
||||||
val var2InSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "tgt", null, false, false, false, Position.DUMMY)
|
val var2InSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "tgt", null, false, false, false, null, Position.DUMMY)
|
||||||
val labelInSub = Label("locallabel", Position.DUMMY)
|
val labelInSub = Label("locallabel", Position.DUMMY)
|
||||||
|
|
||||||
val tgt = AssignTarget(IdentifierReference(listOf("tgt"), Position.DUMMY), null, null, Position.DUMMY)
|
val tgt = AssignTarget(IdentifierReference(listOf("tgt"), Position.DUMMY), null, null, Position.DUMMY)
|
||||||
@ -63,7 +63,7 @@ class AsmGenSymbolsTests: StringSpec({
|
|||||||
val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2, assign3, assign4, assign5, assign6, assign7, assign8)
|
val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2, assign3, assign4, assign5, assign6, assign7, assign8)
|
||||||
val subroutine = Subroutine("start", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, statements, Position.DUMMY)
|
val subroutine = Subroutine("start", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, statements, Position.DUMMY)
|
||||||
val labelInBlock = Label("label_outside", Position.DUMMY)
|
val labelInBlock = Label("label_outside", Position.DUMMY)
|
||||||
val varInBlock = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "var_outside", null, false, false, false, Position.DUMMY)
|
val varInBlock = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "var_outside", null, false, false, false, null, Position.DUMMY)
|
||||||
val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY)
|
val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY)
|
||||||
|
|
||||||
val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
|
val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
|
||||||
|
@ -83,14 +83,18 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
|
|||||||
IAstModification.ReplaceNode(it, uwordParam, subroutine)
|
IAstModification.ReplaceNode(it, uwordParam, subroutine)
|
||||||
}
|
}
|
||||||
|
|
||||||
val stringParamNames = stringParams.map { it.name }.toSet()
|
val stringParamsByNames = stringParams.associateBy { it.name }
|
||||||
val varsChanges = subroutine.statements
|
val varsChanges =
|
||||||
|
if(stringParamsByNames.isNotEmpty()) {
|
||||||
|
subroutine.statements
|
||||||
.filterIsInstance<VarDecl>()
|
.filterIsInstance<VarDecl>()
|
||||||
.filter { it.autogeneratedDontRemove && it.name in stringParamNames }
|
.filter { it.subroutineParameter!=null && it.name in stringParamsByNames }
|
||||||
.map {
|
.map {
|
||||||
val newvar = VarDecl(it.type, DataType.UWORD, it.zeropage, null, it.name, null, false, true, it.sharedWithAsm, it.position)
|
val newvar = VarDecl(it.type, DataType.UWORD, it.zeropage, null, it.name, null, false, true, it.sharedWithAsm, stringParamsByNames.getValue(it.name), it.position)
|
||||||
IAstModification.ReplaceNode(it, newvar, subroutine)
|
IAstModification.ReplaceNode(it, newvar, subroutine)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else emptyList()
|
||||||
|
|
||||||
return parameterChanges + varsChanges
|
return parameterChanges + varsChanges
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter, private
|
|||||||
val paramsToCheck = paramNames.intersect(namesInSub)
|
val paramsToCheck = paramNames.intersect(namesInSub)
|
||||||
for(name in paramsToCheck) {
|
for(name in paramsToCheck) {
|
||||||
val symbol = subroutine.searchSymbol(name)
|
val symbol = subroutine.searchSymbol(name)
|
||||||
if(symbol!=null && symbol.position != subroutine.position)
|
if(symbol!=null && (symbol as? VarDecl)?.subroutineParameter==null)
|
||||||
nameError(name, symbol.position, subroutine)
|
nameError(name, symbol.position, subroutine)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,13 +20,13 @@ internal class AstVariousTransforms(private val program: Program) : AstWalker()
|
|||||||
val symbolsInSub = subroutine.allDefinedSymbols
|
val symbolsInSub = subroutine.allDefinedSymbols
|
||||||
val namesInSub = symbolsInSub.map{ it.first }.toSet()
|
val namesInSub = symbolsInSub.map{ it.first }.toSet()
|
||||||
if(subroutine.asmAddress==null) {
|
if(subroutine.asmAddress==null) {
|
||||||
if(subroutine.asmParameterRegisters.isEmpty() && subroutine.parameters.isNotEmpty()) {
|
if(!subroutine.isAsmSubroutine && subroutine.parameters.isNotEmpty()) {
|
||||||
val vars = subroutine.statements.filterIsInstance<VarDecl>().map { it.name }.toSet()
|
val vars = subroutine.statements.filterIsInstance<VarDecl>().map { it.name }.toSet()
|
||||||
if(!vars.containsAll(subroutine.parameters.map{it.name})) {
|
if(!vars.containsAll(subroutine.parameters.map{it.name})) {
|
||||||
return subroutine.parameters
|
return subroutine.parameters
|
||||||
.filter { it.name !in namesInSub }
|
.filter { it.name !in namesInSub }
|
||||||
.map {
|
.map {
|
||||||
val vardecl = ParameterVarDecl(it.name, it.type, subroutine.position)
|
val vardecl = VarDecl.fromParameter(it)
|
||||||
IAstModification.InsertFirst(vardecl, subroutine)
|
IAstModification.InsertFirst(vardecl, subroutine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ class TestMemory: FunSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createTestProgramForMemoryRefViaVar(address: UInt, vartype: VarDeclType): AssignTarget {
|
fun createTestProgramForMemoryRefViaVar(address: UInt, vartype: VarDeclType): AssignTarget {
|
||||||
val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
|
val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY)
|
||||||
val memexpr = IdentifierReference(listOf("address"), Position.DUMMY)
|
val memexpr = IdentifierReference(listOf("address"), Position.DUMMY)
|
||||||
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
@ -149,7 +149,7 @@ class TestMemory: FunSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("regular variable not in mapped IO ram on C64") {
|
test("regular variable not in mapped IO ram on C64") {
|
||||||
val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY)
|
val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, false, null, Position.DUMMY)
|
||||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
||||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
@ -160,8 +160,8 @@ class TestMemory: FunSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("memory mapped variable not in mapped IO ram on C64") {
|
test("memory mapped variable not in mapped IO ram on C64") {
|
||||||
val address = 0x1000
|
val address = 0x1000u
|
||||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
|
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY)
|
||||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
||||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
@ -172,8 +172,8 @@ class TestMemory: FunSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("memory mapped variable in mapped IO ram on C64") {
|
test("memory mapped variable in mapped IO ram on C64") {
|
||||||
val address = 0xd020
|
val address = 0xd020u
|
||||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
|
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY)
|
||||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
||||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
@ -184,7 +184,7 @@ class TestMemory: FunSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("array not in mapped IO ram") {
|
test("array not in mapped IO ram") {
|
||||||
val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY)
|
val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, false, null, Position.DUMMY)
|
||||||
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||||
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
||||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
@ -196,8 +196,8 @@ class TestMemory: FunSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("memory mapped array not in mapped IO ram") {
|
test("memory mapped array not in mapped IO ram") {
|
||||||
val address = 0x1000
|
val address = 0x1000u
|
||||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
|
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY)
|
||||||
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||||
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
||||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
@ -209,8 +209,8 @@ class TestMemory: FunSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("memory mapped array in mapped IO ram") {
|
test("memory mapped array in mapped IO ram") {
|
||||||
val address = 0xd800
|
val address = 0xd800u
|
||||||
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY)
|
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, null, Position.DUMMY)
|
||||||
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||||
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
||||||
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
|
@ -7,7 +7,6 @@ import prog8.ast.statements.*
|
|||||||
import prog8.ast.walk.AstWalker
|
import prog8.ast.walk.AstWalker
|
||||||
import prog8.ast.walk.IAstVisitor
|
import prog8.ast.walk.IAstVisitor
|
||||||
import prog8.parser.SourceCode
|
import prog8.parser.SourceCode
|
||||||
import kotlin.reflect.typeOf
|
|
||||||
|
|
||||||
const val internedStringsModuleName = "prog8_interned_strings"
|
const val internedStringsModuleName = "prog8_interned_strings"
|
||||||
|
|
||||||
@ -69,23 +68,28 @@ interface IStatementContainer {
|
|||||||
fun isNotEmpty(): Boolean = statements.isNotEmpty()
|
fun isNotEmpty(): Boolean = statements.isNotEmpty()
|
||||||
|
|
||||||
fun searchSymbol(name: String): Statement? {
|
fun searchSymbol(name: String): Statement? {
|
||||||
|
if(this is Subroutine && isAsmSubroutine)
|
||||||
|
return searchAsmParameter(name)
|
||||||
|
|
||||||
// this is called quite a lot and could perhaps be optimized a bit more,
|
// this is called quite a lot and could perhaps be optimized a bit more,
|
||||||
// but adding a memoization cache didn't make much of a practical runtime difference...
|
// but adding a memoization cache didn't make much of a practical runtime difference...
|
||||||
for (stmt in statements) {
|
for (stmt in statements) {
|
||||||
when(stmt) {
|
when(stmt) {
|
||||||
// is INamedStatement -> {
|
is INamedStatement -> {
|
||||||
|
if(stmt.name==name) return stmt
|
||||||
|
}
|
||||||
|
// is VarDecl -> {
|
||||||
|
// // a variable was found with this name, which could also be the vardecl
|
||||||
|
// // that is (auto)generated for regular subroutine parameters.
|
||||||
// if(stmt.name==name) return stmt
|
// if(stmt.name==name) return stmt
|
||||||
// }
|
// }
|
||||||
is VarDecl -> {
|
// is Label -> {
|
||||||
if(stmt.name==name) return stmt
|
// if(stmt.name==name) return stmt
|
||||||
}
|
// }
|
||||||
is Label -> {
|
// is Subroutine -> {
|
||||||
if(stmt.name==name) return stmt
|
// if(stmt.name==name)
|
||||||
}
|
// return stmt
|
||||||
is Subroutine -> {
|
// }
|
||||||
if(stmt.name==name)
|
|
||||||
return stmt
|
|
||||||
}
|
|
||||||
is AnonymousScope -> {
|
is AnonymousScope -> {
|
||||||
val found = stmt.searchSymbol(name)
|
val found = stmt.searchSymbol(name)
|
||||||
if(found!=null)
|
if(found!=null)
|
||||||
|
@ -94,7 +94,7 @@ class Program(val name: String,
|
|||||||
val varName = "string_${internedStringsBlock.statements.size}"
|
val varName = "string_${internedStringsBlock.statements.size}"
|
||||||
val decl = VarDecl(
|
val decl = VarDecl(
|
||||||
VarDeclType.VAR, DataType.STR, ZeropageWish.NOT_IN_ZEROPAGE, null, varName, string,
|
VarDeclType.VAR, DataType.STR, ZeropageWish.NOT_IN_ZEROPAGE, null, varName, string,
|
||||||
isArray = false, autogeneratedDontRemove = true, sharedWithAsm = false, position = string.position
|
isArray = false, autogeneratedDontRemove = true, sharedWithAsm = false, subroutineParameter = null, position = string.position
|
||||||
)
|
)
|
||||||
internedStringsBlock.statements.add(decl)
|
internedStringsBlock.statements.add(decl)
|
||||||
decl.linkParents(internedStringsBlock)
|
decl.linkParents(internedStringsBlock)
|
||||||
|
@ -64,6 +64,7 @@ private fun Prog8ANTLRParser.VariabledeclarationContext.toAst() : Statement {
|
|||||||
vd.ARRAYSIG() != null || vd.arrayindex() != null,
|
vd.ARRAYSIG() != null || vd.arrayindex() != null,
|
||||||
false,
|
false,
|
||||||
vd.SHARED()!=null,
|
vd.SHARED()!=null,
|
||||||
|
null,
|
||||||
it.toPosition()
|
it.toPosition()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -81,6 +82,7 @@ private fun Prog8ANTLRParser.VariabledeclarationContext.toAst() : Statement {
|
|||||||
vd.ARRAYSIG() != null || vd.arrayindex() != null,
|
vd.ARRAYSIG() != null || vd.arrayindex() != null,
|
||||||
false,
|
false,
|
||||||
vd.SHARED() != null,
|
vd.SHARED() != null,
|
||||||
|
null,
|
||||||
cvarinit.toPosition()
|
cvarinit.toPosition()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -98,6 +100,7 @@ private fun Prog8ANTLRParser.VariabledeclarationContext.toAst() : Statement {
|
|||||||
vd.ARRAYSIG() != null || vd.arrayindex() != null,
|
vd.ARRAYSIG() != null || vd.arrayindex() != null,
|
||||||
false,
|
false,
|
||||||
vd.SHARED()!=null,
|
vd.SHARED()!=null,
|
||||||
|
null,
|
||||||
mvarinit.toPosition()
|
mvarinit.toPosition()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -600,6 +603,7 @@ private fun Prog8ANTLRParser.VardeclContext.toAst(): VarDecl {
|
|||||||
ARRAYSIG() != null || arrayindex() != null,
|
ARRAYSIG() != null || arrayindex() != null,
|
||||||
false,
|
false,
|
||||||
SHARED()!=null,
|
SHARED()!=null,
|
||||||
|
null,
|
||||||
toPosition()
|
toPosition()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,7 @@ open class VarDecl(val type: VarDeclType,
|
|||||||
val isArray: Boolean,
|
val isArray: Boolean,
|
||||||
val autogeneratedDontRemove: Boolean,
|
val autogeneratedDontRemove: Boolean,
|
||||||
val sharedWithAsm: Boolean,
|
val sharedWithAsm: Boolean,
|
||||||
|
val subroutineParameter: SubroutineParameter?,
|
||||||
final override val position: Position) : Statement(), INamedStatement {
|
final override val position: Position) : Statement(), INamedStatement {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
var allowInitializeWithZero = true
|
var allowInitializeWithZero = true
|
||||||
@ -194,6 +195,16 @@ open class VarDecl(val type: VarDeclType,
|
|||||||
companion object {
|
companion object {
|
||||||
private var autoHeapValueSequenceNumber = 0
|
private var autoHeapValueSequenceNumber = 0
|
||||||
|
|
||||||
|
fun fromParameter(param: SubroutineParameter): VarDecl {
|
||||||
|
return VarDecl(VarDeclType.VAR, param.type, ZeropageWish.DONTCARE, null, param.name, null,
|
||||||
|
isArray = false,
|
||||||
|
autogeneratedDontRemove = true,
|
||||||
|
sharedWithAsm = false,
|
||||||
|
subroutineParameter = param,
|
||||||
|
position = param.position
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun createAuto(array: ArrayLiteralValue): VarDecl {
|
fun createAuto(array: ArrayLiteralValue): VarDecl {
|
||||||
val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}"
|
val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}"
|
||||||
val arrayDt =
|
val arrayDt =
|
||||||
@ -204,7 +215,7 @@ open class VarDecl(val type: VarDeclType,
|
|||||||
val declaredType = ArrayToElementTypes.getValue(arrayDt)
|
val declaredType = ArrayToElementTypes.getValue(arrayDt)
|
||||||
val arraysize = ArrayIndex.forArray(array)
|
val arraysize = ArrayIndex.forArray(array)
|
||||||
return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, array,
|
return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, array,
|
||||||
isArray = true, autogeneratedDontRemove = true, sharedWithAsm = false, position = array.position)
|
isArray = true, autogeneratedDontRemove = true, sharedWithAsm = false, subroutineParameter = null, position = array.position)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun defaultZero(dt: DataType, position: Position) = when(dt) {
|
fun defaultZero(dt: DataType, position: Position) = when(dt) {
|
||||||
@ -258,16 +269,13 @@ open class VarDecl(val type: VarDeclType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun copy(): VarDecl {
|
override fun copy(): VarDecl {
|
||||||
val c = VarDecl(type, declaredDatatype, zeropage, arraysize?.copy(), name, value?.copy(), isArray, autogeneratedDontRemove, sharedWithAsm, position)
|
val c = VarDecl(type, declaredDatatype, zeropage, arraysize?.copy(), name, value?.copy(),
|
||||||
|
isArray, autogeneratedDontRemove, sharedWithAsm, subroutineParameter, position)
|
||||||
c.allowInitializeWithZero = this.allowInitializeWithZero
|
c.allowInitializeWithZero = this.allowInitializeWithZero
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// a vardecl used only for subroutine parameters
|
|
||||||
class ParameterVarDecl(name: String, declaredDatatype: DataType, position: Position)
|
|
||||||
: VarDecl(VarDeclType.VAR, declaredDatatype, ZeropageWish.DONTCARE, null, name, null, false, true, false, position)
|
|
||||||
|
|
||||||
class ArrayIndex(var indexExpr: Expression,
|
class ArrayIndex(var indexExpr: Expression,
|
||||||
override val position: Position) : Node {
|
override val position: Position) : Node {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
@ -709,6 +717,24 @@ class Subroutine(override val name: String,
|
|||||||
.filter { it is InlineAssembly }
|
.filter { it is InlineAssembly }
|
||||||
.map { (it as InlineAssembly).assembly }
|
.map { (it as InlineAssembly).assembly }
|
||||||
.count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it || " bra" in it || "\tbra" in it}
|
.count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it || " bra" in it || "\tbra" in it}
|
||||||
|
|
||||||
|
|
||||||
|
// code to provide the ability to reference asmsub parameters via qualified name:
|
||||||
|
private val asmParamsDecls = mutableMapOf<String, VarDecl>()
|
||||||
|
|
||||||
|
fun searchAsmParameter(name: String): VarDecl? {
|
||||||
|
require(isAsmSubroutine)
|
||||||
|
|
||||||
|
val existingDecl = asmParamsDecls[name]
|
||||||
|
if(existingDecl!=null)
|
||||||
|
return existingDecl
|
||||||
|
|
||||||
|
val param = parameters.firstOrNull {it.name==name} ?: return null
|
||||||
|
val decl = VarDecl.fromParameter(param)
|
||||||
|
decl.linkParents(this)
|
||||||
|
asmParamsDecls[name] = decl
|
||||||
|
return decl
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class SubroutineParameter(val name: String,
|
open class SubroutineParameter(val name: String,
|
||||||
|
@ -3,6 +3,12 @@ TODO
|
|||||||
|
|
||||||
For next compiler release (7.4)
|
For next compiler release (7.4)
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Use GoSub to call subroutines (not in expressions?):
|
||||||
|
- [DONE] allow separate assigns to subroutine's parameter variables / registers
|
||||||
|
- for asmsubs: implement asmgen for assigning to asm parameter (register)
|
||||||
|
- for asmsubs: implement asmgen for reading asm parameter (register)
|
||||||
|
- replace subroutine param load code with just the right order of those assigns
|
||||||
|
- finally replace the actual call with a GoSub
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,22 +1,32 @@
|
|||||||
%import textio
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
ubyte @shared xx
|
||||||
|
main.routine.r1arg = 20
|
||||||
|
; main.routine2.r2arg = 20 ; TODO asmgen
|
||||||
|
|
||||||
ubyte xx = 20
|
xx = main.routine.r1arg
|
||||||
routine(xx)
|
|
||||||
xx++
|
xx++
|
||||||
routine(xx)
|
;xx = main.routine2.r2arg ; TODO asmgen
|
||||||
xx++
|
;xx++
|
||||||
routine(xx)
|
|
||||||
|
|
||||||
|
printstuff("hello")
|
||||||
repeat {
|
repeat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub routine(ubyte x) {
|
sub printstuff(str addr) {
|
||||||
txt.print_ub(x)
|
|
||||||
txt.spc()
|
|
||||||
}
|
}
|
||||||
|
sub routine(ubyte r1arg) {
|
||||||
|
r1arg++
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub routine2(ubyte r2arg @ A) {
|
||||||
|
%asm {{
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user