mirror of
https://github.com/irmen/prog8.git
synced 2024-10-19 07:23:56 +00:00
merged AddressOfInserter into StatementReorderer
This commit is contained in:
parent
3be3989e1c
commit
b8b9244ffa
@ -20,10 +20,6 @@ internal fun Program.prepareAsmVariablesAndReturns(errors: ErrorReporter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun Program.reorderStatements() {
|
internal fun Program.reorderStatements() {
|
||||||
val initvalueCreator = AddressOfInserter(this)
|
|
||||||
initvalueCreator.visit(this)
|
|
||||||
initvalueCreator.applyModifications()
|
|
||||||
|
|
||||||
val reorder = StatementReorderer(this)
|
val reorder = StatementReorderer(this)
|
||||||
reorder.visit(this)
|
reorder.visit(this)
|
||||||
reorder.applyModifications()
|
reorder.applyModifications()
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
package prog8.ast.processing
|
|
||||||
|
|
||||||
import prog8.ast.IFunctionCall
|
|
||||||
import prog8.ast.Node
|
|
||||||
import prog8.ast.Program
|
|
||||||
import prog8.ast.base.DataType
|
|
||||||
import prog8.ast.base.IterableDatatypes
|
|
||||||
import prog8.ast.base.PassByReferenceDatatypes
|
|
||||||
import prog8.ast.expressions.AddressOf
|
|
||||||
import prog8.ast.expressions.Expression
|
|
||||||
import prog8.ast.expressions.FunctionCall
|
|
||||||
import prog8.ast.expressions.IdentifierReference
|
|
||||||
import prog8.ast.statements.FunctionCallStatement
|
|
||||||
import prog8.ast.statements.Statement
|
|
||||||
import prog8.ast.statements.Subroutine
|
|
||||||
import prog8.compiler.CompilerException
|
|
||||||
import prog8.functions.BuiltinFunctions
|
|
||||||
import prog8.functions.FSignature
|
|
||||||
|
|
||||||
|
|
||||||
internal class AddressOfInserter(val program: Program): AstWalker() {
|
|
||||||
// Insert AddressOf (&) expression where required (string params to a UWORD function param etc).
|
|
||||||
// TODO join this into the StatementReorderer?
|
|
||||||
|
|
||||||
override fun after(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> {
|
|
||||||
// insert AddressOf (&) expression where required (string params to a UWORD function param etc).
|
|
||||||
var parentStatement: Node = functionCall
|
|
||||||
while(parentStatement !is Statement)
|
|
||||||
parentStatement = parentStatement.parent
|
|
||||||
val targetStatement = functionCall.target.targetSubroutine(program.namespace)
|
|
||||||
if(targetStatement!=null) {
|
|
||||||
return addAddressOfExprIfNeeded(targetStatement, functionCall.args, functionCall)
|
|
||||||
} else {
|
|
||||||
val builtinFunc = BuiltinFunctions[functionCall.target.nameInSource.joinToString (".")]
|
|
||||||
if(builtinFunc!=null)
|
|
||||||
return addAddressOfExprIfNeededForBuiltinFuncs(builtinFunc, functionCall.args, functionCall)
|
|
||||||
}
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
|
|
||||||
// insert AddressOf (&) expression where required (string params to a UWORD function param etc).
|
|
||||||
val targetStatement = functionCallStatement.target.targetSubroutine(program.namespace)
|
|
||||||
if(targetStatement!=null) {
|
|
||||||
return addAddressOfExprIfNeeded(targetStatement, functionCallStatement.args, functionCallStatement)
|
|
||||||
} else {
|
|
||||||
val builtinFunc = BuiltinFunctions[functionCallStatement.target.nameInSource.joinToString (".")]
|
|
||||||
if(builtinFunc!=null)
|
|
||||||
return addAddressOfExprIfNeededForBuiltinFuncs(builtinFunc, functionCallStatement.args, functionCallStatement)
|
|
||||||
}
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addAddressOfExprIfNeeded(subroutine: Subroutine, args: MutableList<Expression>, parent: IFunctionCall): Iterable<IAstModification> {
|
|
||||||
// functions that accept UWORD and are given an array type, or string, will receive the AddressOf (memory location) of that value instead.
|
|
||||||
val replacements = mutableListOf<IAstModification>()
|
|
||||||
for(argparam in subroutine.parameters.withIndex().zip(args)) {
|
|
||||||
if(argparam.first.value.type==DataType.UWORD || argparam.first.value.type == DataType.STR) {
|
|
||||||
if(argparam.second is AddressOf)
|
|
||||||
continue
|
|
||||||
val idref = argparam.second as? IdentifierReference
|
|
||||||
if(idref!=null) {
|
|
||||||
val variable = idref.targetVarDecl(program.namespace)
|
|
||||||
if(variable!=null && variable.datatype in IterableDatatypes) {
|
|
||||||
replacements += IAstModification.ReplaceNode(
|
|
||||||
args[argparam.first.index],
|
|
||||||
AddressOf(idref, idref.position),
|
|
||||||
parent as Node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return replacements
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addAddressOfExprIfNeededForBuiltinFuncs(signature: FSignature, args: MutableList<Expression>, parent: IFunctionCall): Iterable<IAstModification> {
|
|
||||||
// val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD
|
|
||||||
val replacements = mutableListOf<IAstModification>()
|
|
||||||
for(arg in args.withIndex().zip(signature.parameters)) {
|
|
||||||
val argvalue = arg.first.value
|
|
||||||
val argDt = argvalue.inferType(program)
|
|
||||||
if(argDt.typeOrElse(DataType.UBYTE) in PassByReferenceDatatypes && DataType.UWORD in arg.second.possibleDatatypes) {
|
|
||||||
if(argvalue !is IdentifierReference)
|
|
||||||
throw CompilerException("pass-by-reference parameter isn't an identifier? $argvalue")
|
|
||||||
replacements += IAstModification.ReplaceNode(
|
|
||||||
args[arg.first.index],
|
|
||||||
AddressOf(argvalue, argvalue.position),
|
|
||||||
parent as Node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return replacements
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,12 @@
|
|||||||
package prog8.ast.processing
|
package prog8.ast.processing
|
||||||
|
|
||||||
import prog8.ast.*
|
import prog8.ast.*
|
||||||
import prog8.ast.base.DataType
|
import prog8.ast.base.*
|
||||||
import prog8.ast.base.FatalAstException
|
|
||||||
import prog8.ast.base.NumericDatatypes
|
|
||||||
import prog8.ast.base.VarDeclType
|
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
|
import prog8.compiler.CompilerException
|
||||||
|
import prog8.functions.BuiltinFunctions
|
||||||
|
import prog8.functions.FSignature
|
||||||
|
|
||||||
|
|
||||||
internal class StatementReorderer(val program: Program) : AstWalker() {
|
internal class StatementReorderer(val program: Program) : AstWalker() {
|
||||||
@ -20,6 +20,7 @@ internal class StatementReorderer(val program: Program) : AstWalker() {
|
|||||||
// - (syntax desugaring) augmented assignment is turned into regular assignment.
|
// - (syntax desugaring) augmented assignment is turned into regular assignment.
|
||||||
// - (syntax desugaring) struct value assignment is expanded into several struct member assignments.
|
// - (syntax desugaring) struct value assignment is expanded into several struct member assignments.
|
||||||
// - sorts the choices in when statement.
|
// - sorts the choices in when statement.
|
||||||
|
// - insert AddressOf (&) expression where required (string params to a UWORD function param etc).
|
||||||
|
|
||||||
|
|
||||||
private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address", "%option")
|
private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address", "%option")
|
||||||
@ -103,8 +104,6 @@ internal class StatementReorderer(val program: Program) : AstWalker() {
|
|||||||
|
|
||||||
override fun before(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
override fun before(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
||||||
if(assignment.aug_op!=null) {
|
if(assignment.aug_op!=null) {
|
||||||
// TODO instead of desugaring augmented assignments, instead just keep them and use them for possibly more efficient code generation ?
|
|
||||||
// this also means that we should actually reverse this stuff below: A = A + 5 ---> A += 5
|
|
||||||
val leftOperand: Expression =
|
val leftOperand: Expression =
|
||||||
when {
|
when {
|
||||||
assignment.target.register != null -> RegisterExpr(assignment.target.register!!, assignment.target.position)
|
assignment.target.register != null -> RegisterExpr(assignment.target.register!!, assignment.target.position)
|
||||||
@ -138,6 +137,75 @@ internal class StatementReorderer(val program: Program) : AstWalker() {
|
|||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun after(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> {
|
||||||
|
// insert AddressOf (&) expression where required (string params to a UWORD function param etc).
|
||||||
|
var parentStatement: Node = functionCall
|
||||||
|
while(parentStatement !is Statement)
|
||||||
|
parentStatement = parentStatement.parent
|
||||||
|
val targetStatement = functionCall.target.targetSubroutine(program.namespace)
|
||||||
|
if(targetStatement!=null) {
|
||||||
|
return addAddressOfExprIfNeeded(targetStatement, functionCall.args, functionCall)
|
||||||
|
} else {
|
||||||
|
val builtinFunc = BuiltinFunctions[functionCall.target.nameInSource.joinToString (".")]
|
||||||
|
if(builtinFunc!=null)
|
||||||
|
return addAddressOfExprIfNeededForBuiltinFuncs(builtinFunc, functionCall.args, functionCall)
|
||||||
|
}
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
|
||||||
|
// insert AddressOf (&) expression where required (string params to a UWORD function param etc).
|
||||||
|
val targetStatement = functionCallStatement.target.targetSubroutine(program.namespace)
|
||||||
|
if(targetStatement!=null) {
|
||||||
|
return addAddressOfExprIfNeeded(targetStatement, functionCallStatement.args, functionCallStatement)
|
||||||
|
} else {
|
||||||
|
val builtinFunc = BuiltinFunctions[functionCallStatement.target.nameInSource.joinToString (".")]
|
||||||
|
if(builtinFunc!=null)
|
||||||
|
return addAddressOfExprIfNeededForBuiltinFuncs(builtinFunc, functionCallStatement.args, functionCallStatement)
|
||||||
|
}
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addAddressOfExprIfNeeded(subroutine: Subroutine, args: MutableList<Expression>, parent: IFunctionCall): Iterable<IAstModification> {
|
||||||
|
// functions that accept UWORD and are given an array type, or string, will receive the AddressOf (memory location) of that value instead.
|
||||||
|
val replacements = mutableListOf<IAstModification>()
|
||||||
|
for(argparam in subroutine.parameters.withIndex().zip(args)) {
|
||||||
|
if(argparam.first.value.type==DataType.UWORD || argparam.first.value.type == DataType.STR) {
|
||||||
|
if(argparam.second is AddressOf)
|
||||||
|
continue
|
||||||
|
val idref = argparam.second as? IdentifierReference
|
||||||
|
if(idref!=null) {
|
||||||
|
val variable = idref.targetVarDecl(program.namespace)
|
||||||
|
if(variable!=null && variable.datatype in IterableDatatypes) {
|
||||||
|
replacements += IAstModification.ReplaceNode(
|
||||||
|
args[argparam.first.index],
|
||||||
|
AddressOf(idref, idref.position),
|
||||||
|
parent as Node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return replacements
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addAddressOfExprIfNeededForBuiltinFuncs(signature: FSignature, args: MutableList<Expression>, parent: IFunctionCall): Iterable<IAstModification> {
|
||||||
|
// val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD
|
||||||
|
val replacements = mutableListOf<IAstModification>()
|
||||||
|
for(arg in args.withIndex().zip(signature.parameters)) {
|
||||||
|
val argvalue = arg.first.value
|
||||||
|
val argDt = argvalue.inferType(program)
|
||||||
|
if(argDt.typeOrElse(DataType.UBYTE) in PassByReferenceDatatypes && DataType.UWORD in arg.second.possibleDatatypes) {
|
||||||
|
if(argvalue !is IdentifierReference)
|
||||||
|
throw CompilerException("pass-by-reference parameter isn't an identifier? $argvalue")
|
||||||
|
replacements += IAstModification.ReplaceNode(
|
||||||
|
args[arg.first.index],
|
||||||
|
AddressOf(argvalue, argvalue.position),
|
||||||
|
parent as Node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return replacements
|
||||||
|
}
|
||||||
|
|
||||||
private fun flattenStructAssignmentFromStructLiteral(structAssignment: Assignment, program: Program): List<Assignment> {
|
private fun flattenStructAssignmentFromStructLiteral(structAssignment: Assignment, program: Program): List<Assignment> {
|
||||||
val identifier = structAssignment.target.identifier!!
|
val identifier = structAssignment.target.identifier!!
|
||||||
val identifierName = identifier.nameInSource.single()
|
val identifierName = identifier.nameInSource.single()
|
||||||
|
@ -3,21 +3,6 @@
|
|||||||
%import c64flt
|
%import c64flt
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
foobar {
|
|
||||||
%option force_output
|
|
||||||
|
|
||||||
ubyte xx
|
|
||||||
|
|
||||||
sub derp() {
|
|
||||||
byte yy=cos8(A)
|
|
||||||
|
|
||||||
if A==0 {
|
|
||||||
; ubyte qq=cos8(A)
|
|
||||||
A=54
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
@ -31,16 +16,12 @@ main {
|
|||||||
c64flt.print_f(floats[0])
|
c64flt.print_f(floats[0])
|
||||||
c64flt.print_f(floats[1])
|
c64flt.print_f(floats[1])
|
||||||
|
|
||||||
foobar.derp()
|
derp("hello")
|
||||||
when A {
|
|
||||||
100 -> Y=4
|
|
||||||
101 -> Y=5
|
|
||||||
1 -> Y=66
|
|
||||||
10 -> Y=77
|
|
||||||
else -> Y=9
|
|
||||||
}
|
|
||||||
|
|
||||||
A+=99
|
}
|
||||||
|
|
||||||
|
sub derp(uword addr) {
|
||||||
|
A=lsb(addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user