From b8b9244ffa71c3ad3b181ec9abe21f6df8b2e2d8 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 6 Apr 2020 14:39:02 +0200 Subject: [PATCH] merged AddressOfInserter into StatementReorderer --- compiler/src/prog8/ast/base/Extensions.kt | 4 - .../prog8/ast/processing/AddressOfInserter.kt | 93 ------------------- .../ast/processing/StatementReorderer.kt | 80 ++++++++++++++-- examples/test.p8 | 29 +----- 4 files changed, 79 insertions(+), 127 deletions(-) delete mode 100644 compiler/src/prog8/ast/processing/AddressOfInserter.kt diff --git a/compiler/src/prog8/ast/base/Extensions.kt b/compiler/src/prog8/ast/base/Extensions.kt index 762ab5564..1d85b77dd 100644 --- a/compiler/src/prog8/ast/base/Extensions.kt +++ b/compiler/src/prog8/ast/base/Extensions.kt @@ -20,10 +20,6 @@ internal fun Program.prepareAsmVariablesAndReturns(errors: ErrorReporter) { } internal fun Program.reorderStatements() { - val initvalueCreator = AddressOfInserter(this) - initvalueCreator.visit(this) - initvalueCreator.applyModifications() - val reorder = StatementReorderer(this) reorder.visit(this) reorder.applyModifications() diff --git a/compiler/src/prog8/ast/processing/AddressOfInserter.kt b/compiler/src/prog8/ast/processing/AddressOfInserter.kt deleted file mode 100644 index 77cf06c7b..000000000 --- a/compiler/src/prog8/ast/processing/AddressOfInserter.kt +++ /dev/null @@ -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 { - // 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 { - // 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, parent: IFunctionCall): Iterable { - // 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() - 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, parent: IFunctionCall): Iterable { - // val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD - val replacements = mutableListOf() - 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 - } -} diff --git a/compiler/src/prog8/ast/processing/StatementReorderer.kt b/compiler/src/prog8/ast/processing/StatementReorderer.kt index 0ec88568c..d4a562de7 100644 --- a/compiler/src/prog8/ast/processing/StatementReorderer.kt +++ b/compiler/src/prog8/ast/processing/StatementReorderer.kt @@ -1,12 +1,12 @@ package prog8.ast.processing import prog8.ast.* -import prog8.ast.base.DataType -import prog8.ast.base.FatalAstException -import prog8.ast.base.NumericDatatypes -import prog8.ast.base.VarDeclType +import prog8.ast.base.* import prog8.ast.expressions.* import prog8.ast.statements.* +import prog8.compiler.CompilerException +import prog8.functions.BuiltinFunctions +import prog8.functions.FSignature 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) struct value assignment is expanded into several struct member assignments. // - 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") @@ -103,8 +104,6 @@ internal class StatementReorderer(val program: Program) : AstWalker() { override fun before(assignment: Assignment, parent: Node): Iterable { 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 = when { assignment.target.register != null -> RegisterExpr(assignment.target.register!!, assignment.target.position) @@ -138,6 +137,75 @@ internal class StatementReorderer(val program: Program) : AstWalker() { return emptyList() } + override fun after(functionCall: FunctionCall, parent: Node): Iterable { + // 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 { + // 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, parent: IFunctionCall): Iterable { + // 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() + 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, parent: IFunctionCall): Iterable { + // val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD + val replacements = mutableListOf() + 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 { val identifier = structAssignment.target.identifier!! val identifierName = identifier.nameInSource.single() diff --git a/examples/test.p8 b/examples/test.p8 index 60f498175..9bc9da346 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,21 +3,6 @@ %import c64flt %zeropage basicsafe -foobar { - %option force_output - - ubyte xx - - sub derp() { - byte yy=cos8(A) - - if A==0 { - ; ubyte qq=cos8(A) - A=54 - } - } - -} main { sub start() { @@ -31,16 +16,12 @@ main { c64flt.print_f(floats[0]) c64flt.print_f(floats[1]) - foobar.derp() - when A { - 100 -> Y=4 - 101 -> Y=5 - 1 -> Y=66 - 10 -> Y=77 - else -> Y=9 - } + derp("hello") - A+=99 + } + + sub derp(uword addr) { + A=lsb(addr) } }