mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
no more duplicate auto heap vars, attempt at automatic insertion of & expression for subroutine params
This commit is contained in:
parent
b200f9945f
commit
87446028e0
@ -814,8 +814,11 @@ private class AstChecker(private val namespace: INameScope,
|
||||
else {
|
||||
for (arg in args.withIndex().zip(target.parameters)) {
|
||||
val argDt = arg.first.value.resultingDatatype(namespace, heap)
|
||||
if(argDt!=null && !argDt.assignableTo(arg.second.type))
|
||||
checkResult.add(ExpressionError("subroutine '${target.name}' argument ${arg.first.index+1} has invalid type $argDt, expected ${arg.second.type}", position))
|
||||
if(argDt!=null && !argDt.assignableTo(arg.second.type)) {
|
||||
// for asm subroutines having STR param it's okay to provide a UWORD too (pointer value)
|
||||
if(!(target.isAsmSubroutine && arg.second.type in StringDatatypes && argDt==DataType.UWORD))
|
||||
checkResult.add(ExpressionError("subroutine '${target.name}' argument ${arg.first.index + 1} has invalid type $argDt, expected ${arg.second.type}", position))
|
||||
}
|
||||
|
||||
if(target.isAsmSubroutine) {
|
||||
if (target.asmParameterRegisters[arg.first.index].registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.XY, RegisterOrPair.X)) {
|
||||
|
@ -14,13 +14,13 @@ fun Module.checkIdentifiers(namespace: INameScope) {
|
||||
|
||||
// add any anonymous variables for heap values that are used,
|
||||
// and replace an iterable literalvalue by identifierref to new local variable
|
||||
for (variable in checker.anonymousVariablesFromHeap) {
|
||||
for (variable in checker.anonymousVariablesFromHeap.values) {
|
||||
val scope = variable.first.definingScope()
|
||||
scope.statements.add(variable.second)
|
||||
val parent = variable.first.parent
|
||||
when {
|
||||
parent is Assignment && parent.value === variable.first -> {
|
||||
val idref = IdentifierReference(listOf("$autoHeapValuePrefix${variable.first.heapId}"), variable.first.position)
|
||||
val idref = IdentifierReference(listOf("$${variable.first.heapId}"), variable.first.position)
|
||||
idref.linkParents(parent)
|
||||
parent.value = idref
|
||||
}
|
||||
@ -217,7 +217,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
|
||||
}
|
||||
|
||||
|
||||
internal val anonymousVariablesFromHeap = mutableSetOf<Pair<LiteralValue, VarDecl>>()
|
||||
internal val anonymousVariablesFromHeap = mutableMapOf<String, Pair<LiteralValue, VarDecl>>()
|
||||
|
||||
|
||||
override fun process(literalValue: LiteralValue): LiteralValue {
|
||||
@ -225,10 +225,10 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
|
||||
// a literal value that's not declared as a variable, which refers to something on the heap.
|
||||
// we need to introduce an auto-generated variable for this to be able to refer to the value!
|
||||
val variable = VarDecl(VarDeclType.VAR, literalValue.type, false, null, "$autoHeapValuePrefix${literalValue.heapId}", literalValue, literalValue.position)
|
||||
anonymousVariablesFromHeap.add(Pair(literalValue, variable))
|
||||
anonymousVariablesFromHeap[variable.name] = Pair(literalValue, variable)
|
||||
}
|
||||
return super.process(literalValue)
|
||||
}
|
||||
}
|
||||
|
||||
private const val autoHeapValuePrefix = "auto_heap_value_"
|
||||
internal const val autoHeapValuePrefix = "auto_heap_value_"
|
||||
|
@ -3,7 +3,7 @@ package prog8.ast
|
||||
import prog8.compiler.HeapValues
|
||||
|
||||
fun Module.reorderStatements(namespace: INameScope, heap: HeapValues) {
|
||||
val initvalueCreator = VarInitValueCreator()
|
||||
val initvalueCreator = VarInitValueAndPointerOfCreator(namespace)
|
||||
this.process(initvalueCreator)
|
||||
|
||||
val checker = StatementReorderer(namespace, heap)
|
||||
@ -203,7 +203,7 @@ private class StatementReorderer(private val namespace: INameScope, private val
|
||||
}
|
||||
|
||||
|
||||
private class VarInitValueCreator: IAstProcessor {
|
||||
private class VarInitValueAndPointerOfCreator(private val namespace: INameScope): IAstProcessor {
|
||||
// Replace the var decl with an assignment and add a new vardecl with the default constant value.
|
||||
// This makes sure the variables get reset to the intended value on a next run of the program.
|
||||
// Variable decls without a value don't get this treatment, which means they retain the last
|
||||
@ -211,6 +211,9 @@ private class VarInitValueCreator: IAstProcessor {
|
||||
// This is done in a separate step because it interferes with the namespace lookup of symbols
|
||||
// in other ast processors.
|
||||
|
||||
// Also takes care to insert PointerOf (&) expression where required (string params to a UWORD function param etc).
|
||||
|
||||
|
||||
private val vardeclsToAdd = mutableMapOf<INameScope, MutableList<VarDecl>>()
|
||||
|
||||
override fun process(module: Module) {
|
||||
@ -252,4 +255,33 @@ private class VarInitValueCreator: IAstProcessor {
|
||||
return decl
|
||||
}
|
||||
|
||||
override fun process(functionCall: FunctionCall): IExpression {
|
||||
val targetStatement = functionCall.target.targetStatement(namespace) as? Subroutine
|
||||
if(targetStatement!=null)
|
||||
addPointerToIfNeeded(targetStatement, functionCall.arglist, functionCall)
|
||||
return functionCall
|
||||
}
|
||||
|
||||
override fun process(functionCallStatement: FunctionCallStatement): IStatement {
|
||||
val targetStatement = functionCallStatement.target.targetStatement(namespace) as? Subroutine
|
||||
if(targetStatement!=null)
|
||||
addPointerToIfNeeded(targetStatement, functionCallStatement.arglist, functionCallStatement)
|
||||
return functionCallStatement
|
||||
}
|
||||
|
||||
private fun addPointerToIfNeeded(subroutine: Subroutine, arglist: MutableList<IExpression>, parent: Node) {
|
||||
// functions that accept UWORD and are given an array type, or string, will receive the Pointer (memory location) of that value instead.
|
||||
for(argparam in subroutine.parameters.withIndex().zip(arglist)) {
|
||||
if(argparam.first.value.type==DataType.UWORD || argparam.first.value.type in StringDatatypes) {
|
||||
val strvalue = argparam.second as? LiteralValue
|
||||
if(strvalue!=null && strvalue.isString) {
|
||||
val idref = IdentifierReference(listOf("$autoHeapValuePrefix${strvalue.heapId}"), strvalue.position) // TODO why does this result later in "pointer-of operand must be the name of a heap variable"
|
||||
val pointerExpr = PointerOf(idref, strvalue.position)
|
||||
pointerExpr.linkParents(arglist[argparam.first.index].parent)
|
||||
arglist[argparam.first.index] = pointerExpr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1089,19 +1089,7 @@ internal class Compiler(private val rootModule: Module,
|
||||
translate(arg.first)
|
||||
prog.instr(Opcode.POP_REGAX_WORD)
|
||||
}
|
||||
// TODO auto-converting str/float/array to their pointer value should be done by explicitly rewriting the Ast into a pointer-of expression, once that is available
|
||||
DataType.STR, DataType.STR_S -> {
|
||||
pushHeapVarAddress(arg.first, false)
|
||||
prog.instr(Opcode.POP_REGAX_WORD)
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
pushFloatAddress(arg.first)
|
||||
prog.instr(Opcode.POP_REGAX_WORD)
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
pushHeapVarAddress(arg.first, false)
|
||||
prog.instr(Opcode.POP_REGAX_WORD)
|
||||
}
|
||||
in StringDatatypes + ArrayDatatypes -> throw CompilerException("string or array arguments should have been converted to their pointer value in the Ast $callPosition")
|
||||
else -> TODO("pass parameter of type $paramDt in registers AX at $callPosition")
|
||||
}
|
||||
}
|
||||
@ -1124,19 +1112,7 @@ internal class Compiler(private val rootModule: Module,
|
||||
translate(arg.first)
|
||||
prog.instr(Opcode.POP_REGAY_WORD)
|
||||
}
|
||||
// TODO auto-converting str/float/array to their pointer value should be done by explicitly rewriting the Ast into a pointer-of expression, once that is available
|
||||
DataType.STR, DataType.STR_S -> {
|
||||
pushHeapVarAddress(arg.first, false)
|
||||
prog.instr(Opcode.POP_REGAY_WORD)
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
pushFloatAddress(arg.first)
|
||||
prog.instr(Opcode.POP_REGAY_WORD)
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
pushHeapVarAddress(arg.first, false)
|
||||
prog.instr(Opcode.POP_REGAY_WORD)
|
||||
}
|
||||
in StringDatatypes + ArrayDatatypes -> throw CompilerException("string or array arguments should have been converted to their pointer value in the Ast $callPosition")
|
||||
else -> TODO("pass parameter of type $paramDt in registers AY at $callPosition")
|
||||
}
|
||||
}
|
||||
@ -1163,19 +1139,7 @@ internal class Compiler(private val rootModule: Module,
|
||||
translate(arg.first)
|
||||
prog.instr(Opcode.POP_REGXY_WORD)
|
||||
}
|
||||
// TODO auto-converting str/float/array to their pointer value should be done by explicitly rewriting the Ast into a pointer-of expression, once that is available
|
||||
DataType.STR, DataType.STR_S -> {
|
||||
pushHeapVarAddress(arg.first, false)
|
||||
prog.instr(Opcode.POP_REGXY_WORD)
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
pushFloatAddress(arg.first)
|
||||
prog.instr(Opcode.POP_REGXY_WORD)
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
pushHeapVarAddress(arg.first, false)
|
||||
prog.instr(Opcode.POP_REGXY_WORD)
|
||||
}
|
||||
in StringDatatypes + ArrayDatatypes -> throw CompilerException("string or array arguments should have been converted to their pointer value in the Ast $callPosition")
|
||||
else -> TODO("pass parameter of type $paramDt in registers XY at $callPosition")
|
||||
}
|
||||
}
|
||||
|
@ -106,9 +106,15 @@
|
||||
|
||||
;uword[4] pointers = [&array1, &array2, &string1, &string2] ; @todo make it possible to initialize array with pointers
|
||||
|
||||
|
||||
;ptrsubasm("moet werken") ; @todo rewrite ast into pointer-of expression (and remove special cases from Compiler)
|
||||
;pointersub("moet werken") ; @todo rewrite ast into pointer-of expression (and remove special cases from Compiler)
|
||||
;myprintasm("moet werken3") ; @todo rewrite ast into pointer-of expression (and remove special cases from Compiler)
|
||||
|
||||
myprintasm("moet werken3")
|
||||
myprintasm("moet werken3")
|
||||
myprintasm("moet werken4")
|
||||
|
||||
c64.CHROUT('\n')
|
||||
|
||||
ptrsubasm(&array1)
|
||||
ptrsubasm(&array2)
|
||||
|
Loading…
Reference in New Issue
Block a user