applying new astwalker for modifications

This commit is contained in:
Irmen de Jong 2020-03-19 21:30:01 +01:00
parent 40e6091506
commit 5e50ea14f8
14 changed files with 590 additions and 546 deletions

View File

@ -5,7 +5,7 @@ import prog8.ast.expressions.Expression
import prog8.ast.expressions.IdentifierReference
import prog8.ast.processing.IAstModifyingVisitor
import prog8.ast.processing.IAstVisitor
import prog8.ast.processing.IGenericAstModifyingVisitor
import prog8.ast.processing.AstWalker
import prog8.ast.statements.*
import prog8.functions.BuiltinFunctions
import java.nio.file.Path
@ -252,7 +252,7 @@ class Module(override val name: String,
fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
fun accept(visitor: IAstVisitor) = visitor.visit(this)
fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}

View File

@ -8,13 +8,7 @@ import prog8.optimizer.FlattenAnonymousScopesAndRemoveNops
// the name of the subroutine that should be called for every block to initialize its variables
internal const val initvarsSubName="prog8_init_vars"
internal fun Program.removeNopsFlattenAnonScopes() {
val flattener = FlattenAnonymousScopesAndRemoveNops()
flattener.visit(this)
}
internal const val initvarsSubName = "prog8_init_vars"
internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: ErrorReporter) {
@ -22,13 +16,11 @@ internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: Err
checker.visit(this)
}
internal fun Program.anonscopeVarsCleanup(errors: ErrorReporter) {
val mover = AnonymousScopeVarsCleanup(errors)
val mover = MoveAnonScopeVarsToSubroutine(errors)
mover.visit(this)
}
internal fun Program.reorderStatements() {
val initvalueCreator = VarInitValueAndAddressOfCreator(this)
initvalueCreator.visit(this)
@ -42,9 +34,10 @@ internal fun Program.addTypecasts(errors: ErrorReporter) {
caster.visit(this)
}
internal fun Module.checkImportedValid(errors: ErrorReporter) {
val checker = ImportedModuleDirectiveRemover(errors)
checker.visit(this)
internal fun Module.checkImportedValid() {
val imr = ImportedModuleDirectiveRemover()
imr.visit(this, this.parent)
imr.applyModifications()
}
internal fun Program.checkRecursion(errors: ErrorReporter) {
@ -53,18 +46,22 @@ internal fun Program.checkRecursion(errors: ErrorReporter) {
checker.processMessages(name)
}
internal fun Program.checkIdentifiers(errors: ErrorReporter) {
val checker = AstIdentifiersChecker(this, errors)
checker.visit(this)
if(modules.map {it.name}.toSet().size != modules.size) {
if (modules.map { it.name }.toSet().size != modules.size) {
throw FatalAstException("modules should all be unique")
}
}
internal fun Program.makeForeverLoops() {
val checker = MakeForeverLoops()
checker.visit(this)
checker.applyModifications()
}
internal fun Program.removeNopsFlattenAnonScopes() {
val flattener = FlattenAnonymousScopesAndRemoveNops()
flattener.visit(this)
}

View File

@ -5,7 +5,7 @@ import prog8.ast.antlr.escape
import prog8.ast.base.*
import prog8.ast.processing.IAstModifyingVisitor
import prog8.ast.processing.IAstVisitor
import prog8.ast.processing.IGenericAstModifyingVisitor
import prog8.ast.processing.AstWalker
import prog8.ast.statements.*
import prog8.compiler.target.CompilationTarget
import prog8.functions.BuiltinFunctions
@ -22,7 +22,7 @@ sealed class Expression: Node {
abstract fun constValue(program: Program): NumericLiteralValue?
abstract fun accept(visitor: IAstModifyingVisitor): Expression
abstract fun accept(visitor: IAstVisitor)
abstract fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)
abstract fun accept(visitor: AstWalker, parent: Node)
abstract fun referencesIdentifiers(vararg name: String): Boolean // todo: remove this and add identifier usage tracking into CallGraph instead
abstract fun inferType(program: Program): InferredTypes.InferredType
@ -61,7 +61,7 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
override fun constValue(program: Program): NumericLiteralValue? = null
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String) = expression.referencesIdentifiers(*name)
override fun inferType(program: Program): InferredTypes.InferredType {
@ -109,7 +109,7 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String) = left.referencesIdentifiers(*name) || right.referencesIdentifiers(*name)
override fun inferType(program: Program): InferredTypes.InferredType {
@ -214,7 +214,7 @@ class ArrayIndexedExpression(var identifier: IdentifierReference,
override fun constValue(program: Program): NumericLiteralValue? = null
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String) = identifier.referencesIdentifiers(*name)
@ -245,7 +245,7 @@ class TypecastExpression(var expression: Expression, var type: DataType, val imp
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String) = expression.referencesIdentifiers(*name)
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(type)
@ -274,7 +274,7 @@ data class AddressOf(var identifier: IdentifierReference, override val position:
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(DataType.UWORD)
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
}
class DirectMemoryRead(var addressExpression: Expression, override val position: Position) : Expression(), IAssignable {
@ -287,7 +287,7 @@ class DirectMemoryRead(var addressExpression: Expression, override val position:
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String) = false
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(DataType.UBYTE)
@ -343,7 +343,7 @@ class NumericLiteralValue(val type: DataType, // only numerical types allowed
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun toString(): String = "NumericLiteral(${type.name}:$number)"
@ -430,7 +430,7 @@ class StructLiteralValue(var values: List<Expression>,
override fun constValue(program: Program): NumericLiteralValue? = null
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String) = values.any { it.referencesIdentifiers(*name) }
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(DataType.STRUCT)
@ -456,7 +456,7 @@ class StringLiteralValue(val value: String,
override fun constValue(program: Program): NumericLiteralValue? = null
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun toString(): String = "'${escape(value)}'"
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(DataType.STR)
@ -484,7 +484,7 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be
override fun constValue(program: Program): NumericLiteralValue? = null
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun toString(): String = "$value"
override fun inferType(program: Program): InferredTypes.InferredType = if(type.isUnknown) type else guessDatatype(program)
@ -567,7 +567,7 @@ class RangeExpr(var from: Expression,
override fun constValue(program: Program): NumericLiteralValue? = null
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String): Boolean = from.referencesIdentifiers(*name) || to.referencesIdentifiers(*name)
override fun inferType(program: Program): InferredTypes.InferredType {
@ -643,7 +643,7 @@ class RegisterExpr(val register: Register, override val position: Position) : Ex
override fun constValue(program: Program): NumericLiteralValue? = null
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String): Boolean = register.name in name
override fun toString(): String {
@ -687,7 +687,7 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String): Boolean = nameInSource.last() in name
@ -763,7 +763,7 @@ class FunctionCall(override var target: IdentifierReference,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)= visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifiers(vararg name: String): Boolean = target.referencesIdentifiers(*name) || args.any{it.referencesIdentifiers(*name)}

View File

@ -0,0 +1,407 @@
package prog8.ast.processing
import prog8.ast.INameScope
import prog8.ast.Module
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.base.FatalAstException
import prog8.ast.expressions.*
import prog8.ast.statements.*
abstract class AstModification(val node: Node) {
abstract fun perform()
class Remove(node: Node, val parent: Node) : AstModification(node) {
override fun perform() {
if(parent is INameScope) {
if (!parent.statements.remove(node))
throw FatalAstException("attempt to remove non-existing node $node")
} else {
throw FatalAstException("parent of a remove modification is not an INameScope")
}
}
}
class Replace(statement: Statement, val replacement: Statement, val parent: Node) : AstModification(statement) {
override fun perform() {
if(parent is INameScope) {
val idx = parent.statements.indexOf(node)
parent.statements[idx] = replacement
replacement.linkParents(parent)
} else {
throw FatalAstException("parent of a replace modification is not an INameScope")
}
}
}
}
abstract class AstWalker {
open fun before(addressOf: AddressOf, parent: Node): Iterable<AstModification> = emptyList()
open fun before(array: ArrayLiteralValue, parent: Node): Iterable<AstModification> = emptyList()
open fun before(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<AstModification> = emptyList()
open fun before(assignTarget: AssignTarget, parent: Node): Iterable<AstModification> = emptyList()
open fun before(assignment: Assignment, parent: Node): Iterable<AstModification> = emptyList()
open fun before(block: Block, parent: Node): Iterable<AstModification> = emptyList()
open fun before(branchStatement: BranchStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun before(breakStmt: Break, parent: Node): Iterable<AstModification> = emptyList()
open fun before(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable<AstModification> = emptyList()
open fun before(contStmt: Continue, parent: Node): Iterable<AstModification> = emptyList()
open fun before(decl: VarDecl, parent: Node): Iterable<AstModification> = emptyList()
open fun before(directive: Directive, parent: Node): Iterable<AstModification> = emptyList()
open fun before(expr: BinaryExpression, parent: Node): Iterable<AstModification> = emptyList()
open fun before(expr: PrefixExpression, parent: Node): Iterable<AstModification> = emptyList()
open fun before(forLoop: ForLoop, parent: Node): Iterable<AstModification> = emptyList()
open fun before(foreverLoop: ForeverLoop, parent: Node): Iterable<AstModification> = emptyList()
open fun before(functionCall: FunctionCall, parent: Node): Iterable<AstModification> = emptyList()
open fun before(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun before(identifier: IdentifierReference, parent: Node): Iterable<AstModification> = emptyList()
open fun before(ifStatement: IfStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun before(inlineAssembly: InlineAssembly, parent: Node): Iterable<AstModification> = emptyList()
open fun before(jump: Jump, parent: Node): Iterable<AstModification> = emptyList()
open fun before(label: Label, parent: Node): Iterable<AstModification> = emptyList()
open fun before(memread: DirectMemoryRead, parent: Node): Iterable<AstModification> = emptyList()
open fun before(memwrite: DirectMemoryWrite, parent: Node): Iterable<AstModification> = emptyList()
open fun before(module: Module, parent: Node): Iterable<AstModification> = emptyList()
open fun before(nopStatement: NopStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun before(numLiteral: NumericLiteralValue, parent: Node): Iterable<AstModification> = emptyList()
open fun before(postIncrDecr: PostIncrDecr, parent: Node): Iterable<AstModification> = emptyList()
open fun before(program: Program, parent: Node): Iterable<AstModification> = emptyList()
open fun before(range: RangeExpr, parent: Node): Iterable<AstModification> = emptyList()
open fun before(registerExpr: RegisterExpr, parent: Node): Iterable<AstModification> = emptyList()
open fun before(repeatLoop: RepeatLoop, parent: Node): Iterable<AstModification> = emptyList()
open fun before(returnStmt: Return, parent: Node): Iterable<AstModification> = emptyList()
open fun before(scope: AnonymousScope, parent: Node): Iterable<AstModification> = emptyList()
open fun before(string: StringLiteralValue, parent: Node): Iterable<AstModification> = emptyList()
open fun before(structDecl: StructDecl, parent: Node): Iterable<AstModification> = emptyList()
open fun before(structLv: StructLiteralValue, parent: Node): Iterable<AstModification> = emptyList()
open fun before(subroutine: Subroutine, parent: Node): Iterable<AstModification> = emptyList()
open fun before(typecast: TypecastExpression, parent: Node): Iterable<AstModification> = emptyList()
open fun before(whenChoice: WhenChoice, parent: Node): Iterable<AstModification> = emptyList()
open fun before(whenStatement: WhenStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun before(whileLoop: WhileLoop, parent: Node): Iterable<AstModification> = emptyList()
open fun after(addressOf: AddressOf, parent: Node): Iterable<AstModification> = emptyList()
open fun after(array: ArrayLiteralValue, parent: Node): Iterable<AstModification> = emptyList()
open fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<AstModification> = emptyList()
open fun after(assignTarget: AssignTarget, parent: Node): Iterable<AstModification> = emptyList()
open fun after(assignment: Assignment, parent: Node): Iterable<AstModification> = emptyList()
open fun after(block: Block, parent: Node): Iterable<AstModification> = emptyList()
open fun after(branchStatement: BranchStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun after(breakStmt: Break, parent: Node): Iterable<AstModification> = emptyList()
open fun after(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable<AstModification> = emptyList()
open fun after(contStmt: Continue, parent: Node): Iterable<AstModification> = emptyList()
open fun after(decl: VarDecl, parent: Node): Iterable<AstModification> = emptyList()
open fun after(directive: Directive, parent: Node): Iterable<AstModification> = emptyList()
open fun after(expr: BinaryExpression, parent: Node): Iterable<AstModification> = emptyList()
open fun after(expr: PrefixExpression, parent: Node): Iterable<AstModification> = emptyList()
open fun after(forLoop: ForLoop, parent: Node): Iterable<AstModification> = emptyList()
open fun after(foreverLoop: ForeverLoop, parent: Node): Iterable<AstModification> = emptyList()
open fun after(functionCall: FunctionCall, parent: Node): Iterable<AstModification> = emptyList()
open fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun after(identifier: IdentifierReference, parent: Node): Iterable<AstModification> = emptyList()
open fun after(ifStatement: IfStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun after(inlineAssembly: InlineAssembly, parent: Node): Iterable<AstModification> = emptyList()
open fun after(jump: Jump, parent: Node): Iterable<AstModification> = emptyList()
open fun after(label: Label, parent: Node): Iterable<AstModification> = emptyList()
open fun after(memread: DirectMemoryRead, parent: Node): Iterable<AstModification> = emptyList()
open fun after(memwrite: DirectMemoryWrite, parent: Node): Iterable<AstModification> = emptyList()
open fun after(module: Module, parent: Node): Iterable<AstModification> = emptyList()
open fun after(nopStatement: NopStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun after(numLiteral: NumericLiteralValue, parent: Node): Iterable<AstModification> = emptyList()
open fun after(postIncrDecr: PostIncrDecr, parent: Node): Iterable<AstModification> = emptyList()
open fun after(program: Program, parent: Node): Iterable<AstModification> = emptyList()
open fun after(range: RangeExpr, parent: Node): Iterable<AstModification> = emptyList()
open fun after(registerExpr: RegisterExpr, parent: Node): Iterable<AstModification> = emptyList()
open fun after(repeatLoop: RepeatLoop, parent: Node): Iterable<AstModification> = emptyList()
open fun after(returnStmt: Return, parent: Node): Iterable<AstModification> = emptyList()
open fun after(scope: AnonymousScope, parent: Node): Iterable<AstModification> = emptyList()
open fun after(string: StringLiteralValue, parent: Node): Iterable<AstModification> = emptyList()
open fun after(structDecl: StructDecl, parent: Node): Iterable<AstModification> = emptyList()
open fun after(structLv: StructLiteralValue, parent: Node): Iterable<AstModification> = emptyList()
open fun after(subroutine: Subroutine, parent: Node): Iterable<AstModification> = emptyList()
open fun after(typecast: TypecastExpression, parent: Node): Iterable<AstModification> = emptyList()
open fun after(whenChoice: WhenChoice, parent: Node): Iterable<AstModification> = emptyList()
open fun after(whenStatement: WhenStatement, parent: Node): Iterable<AstModification> = emptyList()
open fun after(whileLoop: WhileLoop, parent: Node): Iterable<AstModification> = emptyList()
private val modifications = mutableListOf<Triple<AstModification, Node, Node>>()
private fun track(mods: Iterable<AstModification>, node: Node, parent: Node) {
for (it in mods) modifications += Triple(it, node, parent)
}
fun applyModifications() {
modifications.forEach {
it.first.perform()
}
}
fun visit(program: Program) {
track(before(program, program), program, program)
program.modules.forEach { it.accept(this, program) }
track(after(program, program), program, program)
}
fun visit(module: Module, parent: Node) {
track(before(module, parent), module, parent)
module.statements.forEach{ it.accept(this, module) }
track(after(module, parent), module, parent)
}
fun visit(expr: PrefixExpression, parent: Node) {
track(before(expr, parent), expr, parent)
expr.expression.accept(this, expr)
track(after(expr, parent), expr, parent)
}
fun visit(expr: BinaryExpression, parent: Node) {
track(before(expr, parent), expr, parent)
expr.left.accept(this, expr)
expr.right.accept(this, expr)
track(after(expr, parent), expr, parent)
}
fun visit(directive: Directive, parent: Node) {
track(before(directive, parent), directive, parent)
track(after(directive, parent), directive, parent)
}
fun visit(block: Block, parent: Node) {
track(before(block, parent), block, parent)
block.statements.forEach { it.accept(this, block) }
track(after(block, parent), block, parent)
}
fun visit(decl: VarDecl, parent: Node) {
track(before(decl, parent), decl, parent)
decl.value?.accept(this, decl)
decl.arraysize?.accept(this, decl)
track(after(decl, parent), decl, parent)
}
fun visit(subroutine: Subroutine, parent: Node) {
track(before(subroutine, parent), subroutine, parent)
subroutine.statements.forEach { it.accept(this, subroutine) }
track(after(subroutine, parent), subroutine, parent)
}
fun visit(functionCall: FunctionCall, parent: Node) {
track(before(functionCall, parent), functionCall, parent)
functionCall.target.accept(this, functionCall)
functionCall.args.forEach { it.accept(this, functionCall) }
track(after(functionCall, parent), functionCall, parent)
}
fun visit(functionCallStatement: FunctionCallStatement, parent: Node) {
track(before(functionCallStatement, parent), functionCallStatement, parent)
functionCallStatement.target.accept(this, functionCallStatement)
functionCallStatement.args.forEach { it.accept(this, functionCallStatement) }
track(after(functionCallStatement, parent), functionCallStatement, parent)
}
fun visit(identifier: IdentifierReference, parent: Node) {
track(before(identifier, parent), identifier, parent)
track(after(identifier, parent), identifier, parent)
}
fun visit(jump: Jump, parent: Node) {
track(before(jump, parent), jump, parent)
jump.identifier?.accept(this, jump)
track(after(jump, parent), jump, parent)
}
fun visit(ifStatement: IfStatement, parent: Node) {
track(before(ifStatement, parent), ifStatement, parent)
ifStatement.condition.accept(this, ifStatement)
ifStatement.truepart.accept(this, ifStatement)
ifStatement.elsepart.accept(this, ifStatement)
track(after(ifStatement, parent), ifStatement, parent)
}
fun visit(branchStatement: BranchStatement, parent: Node) {
track(before(branchStatement, parent), branchStatement, parent)
branchStatement.truepart.accept(this, branchStatement)
branchStatement.elsepart.accept(this, branchStatement)
track(after(branchStatement, parent), branchStatement, parent)
}
fun visit(range: RangeExpr, parent: Node) {
track(before(range, parent), range, parent)
range.from.accept(this, range)
range.to.accept(this, range)
range.step.accept(this, range)
track(after(range, parent), range, parent)
}
fun visit(label: Label, parent: Node) {
track(before(label, parent), label, parent)
track(after(label, parent), label, parent)
}
fun visit(numLiteral: NumericLiteralValue, parent: Node) {
track(before(numLiteral, parent), numLiteral, parent)
track(after(numLiteral, parent), numLiteral, parent)
}
fun visit(string: StringLiteralValue, parent: Node) {
track(before(string, parent), string, parent)
track(after(string, parent), string, parent)
}
fun visit(array: ArrayLiteralValue, parent: Node) {
track(before(array, parent), array, parent)
array.value.forEach { v->v.accept(this, array) }
track(after(array, parent), array, parent)
}
fun visit(assignment: Assignment, parent: Node) {
track(before(assignment, parent), assignment, parent)
assignment.target.accept(this, assignment)
assignment.value.accept(this, assignment)
track(after(assignment, parent), assignment, parent)
}
fun visit(postIncrDecr: PostIncrDecr, parent: Node) {
track(before(postIncrDecr, parent), postIncrDecr, parent)
postIncrDecr.target.accept(this, postIncrDecr)
track(after(postIncrDecr, parent), postIncrDecr, parent)
}
fun visit(contStmt: Continue, parent: Node) {
track(before(contStmt, parent), contStmt, parent)
track(after(contStmt, parent), contStmt, parent)
}
fun visit(breakStmt: Break, parent: Node) {
track(before(breakStmt, parent), breakStmt, parent)
track(after(breakStmt, parent), breakStmt, parent)
}
fun visit(forLoop: ForLoop, parent: Node) {
track(before(forLoop, parent), forLoop, parent)
forLoop.loopVar?.accept(this, forLoop)
forLoop.iterable.accept(this, forLoop)
forLoop.body.accept(this, forLoop)
track(after(forLoop, parent), forLoop, parent)
}
fun visit(whileLoop: WhileLoop, parent: Node) {
track(before(whileLoop, parent), whileLoop, parent)
whileLoop.condition.accept(this, whileLoop)
whileLoop.body.accept(this, whileLoop)
track(after(whileLoop, parent), whileLoop, parent)
}
fun visit(foreverLoop: ForeverLoop, parent: Node) {
track(before(foreverLoop, parent), foreverLoop, parent)
foreverLoop.body.accept(this, foreverLoop)
track(after(foreverLoop, parent), foreverLoop, parent)
}
fun visit(repeatLoop: RepeatLoop, parent: Node) {
track(before(repeatLoop, parent), repeatLoop, parent)
repeatLoop.untilCondition.accept(this, repeatLoop)
repeatLoop.body.accept(this, repeatLoop)
track(after(repeatLoop, parent), repeatLoop, parent)
}
fun visit(returnStmt: Return, parent: Node) {
track(before(returnStmt, parent), returnStmt, parent)
returnStmt.value?.accept(this, returnStmt)
track(after(returnStmt, parent), returnStmt, parent)
}
fun visit(arrayIndexedExpression: ArrayIndexedExpression, parent: Node) {
track(before(arrayIndexedExpression, parent), arrayIndexedExpression, parent)
arrayIndexedExpression.identifier.accept(this, arrayIndexedExpression)
arrayIndexedExpression.arrayspec.accept(this, arrayIndexedExpression)
track(after(arrayIndexedExpression, parent), arrayIndexedExpression, parent)
}
fun visit(assignTarget: AssignTarget, parent: Node) {
track(before(assignTarget, parent), assignTarget, parent)
assignTarget.arrayindexed?.accept(this, assignTarget)
assignTarget.identifier?.accept(this, assignTarget)
assignTarget.memoryAddress?.accept(this, assignTarget)
track(after(assignTarget, parent), assignTarget, parent)
}
fun visit(scope: AnonymousScope, parent: Node) {
track(before(scope, parent), scope, parent)
scope.statements.forEach { it.accept(this, scope) }
track(after(scope, parent), scope, parent)
}
fun visit(typecast: TypecastExpression, parent: Node) {
track(before(typecast, parent), typecast, parent)
typecast.expression.accept(this, typecast)
track(after(typecast, parent), typecast, parent)
}
fun visit(memread: DirectMemoryRead, parent: Node) {
track(before(memread, parent), memread, parent)
memread.addressExpression.accept(this, memread)
track(after(memread, parent), memread, parent)
}
fun visit(memwrite: DirectMemoryWrite, parent: Node) {
track(before(memwrite, parent), memwrite, parent)
memwrite.addressExpression.accept(this, memwrite)
track(after(memwrite, parent), memwrite, parent)
}
fun visit(addressOf: AddressOf, parent: Node) {
track(before(addressOf, parent), addressOf, parent)
addressOf.identifier.accept(this, addressOf)
track(after(addressOf, parent), addressOf, parent)
}
fun visit(inlineAssembly: InlineAssembly, parent: Node) {
track(before(inlineAssembly, parent), inlineAssembly, parent)
track(after(inlineAssembly, parent), inlineAssembly, parent)
}
fun visit(registerExpr: RegisterExpr, parent: Node) {
track(before(registerExpr, parent), registerExpr, parent)
track(after(registerExpr, parent), registerExpr, parent)
}
fun visit(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node) {
track(before(builtinFunctionStatementPlaceholder, parent), builtinFunctionStatementPlaceholder, parent)
track(after(builtinFunctionStatementPlaceholder, parent), builtinFunctionStatementPlaceholder, parent)
}
fun visit(nopStatement: NopStatement, parent: Node) {
track(before(nopStatement, parent), nopStatement, parent)
track(after(nopStatement, parent), nopStatement, parent)
}
fun visit(whenStatement: WhenStatement, parent: Node) {
track(before(whenStatement, parent), whenStatement, parent)
whenStatement.condition.accept(this, whenStatement)
whenStatement.choices.forEach { it.accept(this, whenStatement) }
track(after(whenStatement, parent), whenStatement, parent)
}
fun visit(whenChoice: WhenChoice, parent: Node) {
track(before(whenChoice, parent), whenChoice, parent)
whenChoice.values?.forEach { it.accept(this, whenChoice) }
whenChoice.statements.accept(this, whenChoice)
track(after(whenChoice, parent), whenChoice, parent)
}
fun visit(structDecl: StructDecl, parent: Node) {
track(before(structDecl, parent), structDecl, parent)
structDecl.statements.forEach { it.accept(this, structDecl) }
track(after(structDecl, parent), structDecl, parent)
}
fun visit(structLv: StructLiteralValue, parent: Node) {
track(before(structLv, parent), structLv, parent)
structLv.values.forEach { it.accept(this, structLv) }
track(after(structLv, parent), structLv, parent)
}
}

View File

@ -1,373 +0,0 @@
package prog8.ast.processing
import prog8.ast.Module
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.expressions.*
import prog8.ast.statements.*
typealias AstModification = (node: Node, parent: Node) -> Unit
interface IGenericAstModifyingVisitor {
fun before(addressOf: AddressOf, parent: Node): List<AstModification> = emptyList()
fun before(array: ArrayLiteralValue, parent: Node): List<AstModification> = emptyList()
fun before(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): List<AstModification> = emptyList()
fun before(assignTarget: AssignTarget, parent: Node): List<AstModification> = emptyList()
fun before(assignment: Assignment, parent: Node): List<AstModification> = emptyList()
fun before(block: Block, parent: Node): List<AstModification> = emptyList()
fun before(branchStatement: BranchStatement, parent: Node): List<AstModification> = emptyList()
fun before(breakStmt: Break, parent: Node): List<AstModification> = emptyList()
fun before(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): List<AstModification> = emptyList()
fun before(contStmt: Continue, parent: Node): List<AstModification> = emptyList()
fun before(decl: VarDecl, parent: Node): List<AstModification> = emptyList()
fun before(directive: Directive, parent: Node): List<AstModification> = emptyList()
fun before(expr: BinaryExpression, parent: Node): List<AstModification> = emptyList()
fun before(expr: PrefixExpression, parent: Node): List<AstModification> = emptyList()
fun before(forLoop: ForLoop, parent: Node): List<AstModification> = emptyList()
fun before(foreverLoop: ForeverLoop, parent: Node): List<AstModification> = emptyList()
fun before(functionCall: FunctionCall, parent: Node): List<AstModification> = emptyList()
fun before(functionCallStatement: FunctionCallStatement, parent: Node): List<AstModification> = emptyList()
fun before(identifier: IdentifierReference, parent: Node): List<AstModification> = emptyList()
fun before(ifStatement: IfStatement, parent: Node): List<AstModification> = emptyList()
fun before(inlineAssembly: InlineAssembly, parent: Node): List<AstModification> = emptyList()
fun before(jump: Jump, parent: Node): List<AstModification> = emptyList()
fun before(label: Label, parent: Node): List<AstModification> = emptyList()
fun before(memread: DirectMemoryRead, parent: Node): List<AstModification> = emptyList()
fun before(memwrite: DirectMemoryWrite, parent: Node): List<AstModification> = emptyList()
fun before(module: Module, parent: Node): List<AstModification> = emptyList()
fun before(nopStatement: NopStatement, parent: Node): List<AstModification> = emptyList()
fun before(numLiteral: NumericLiteralValue, parent: Node): List<AstModification> = emptyList()
fun before(postIncrDecr: PostIncrDecr, parent: Node): List<AstModification> = emptyList()
fun before(program: Program, parent: Node): List<AstModification> = emptyList()
fun before(range: RangeExpr, parent: Node): List<AstModification> = emptyList()
fun before(registerExpr: RegisterExpr, parent: Node): List<AstModification> = emptyList()
fun before(repeatLoop: RepeatLoop, parent: Node): List<AstModification> = emptyList()
fun before(returnStmt: Return, parent: Node): List<AstModification> = emptyList()
fun before(scope: AnonymousScope, parent: Node): List<AstModification> = emptyList()
fun before(string: StringLiteralValue, parent: Node): List<AstModification> = emptyList()
fun before(structDecl: StructDecl, parent: Node): List<AstModification> = emptyList()
fun before(structLv: StructLiteralValue, parent: Node): List<AstModification> = emptyList()
fun before(subroutine: Subroutine, parent: Node): List<AstModification> = emptyList()
fun before(typecast: TypecastExpression, parent: Node): List<AstModification> = emptyList()
fun before(whenChoice: WhenChoice, parent: Node): List<AstModification> = emptyList()
fun before(whenStatement: WhenStatement, parent: Node): List<AstModification> = emptyList()
fun before(whileLoop: WhileLoop, parent: Node): List<AstModification> = emptyList()
fun after(addressOf: AddressOf, parent: Node): List<AstModification> = emptyList()
fun after(array: ArrayLiteralValue, parent: Node): List<AstModification> = emptyList()
fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): List<AstModification> = emptyList()
fun after(assignTarget: AssignTarget, parent: Node): List<AstModification> = emptyList()
fun after(assignment: Assignment, parent: Node): List<AstModification> = emptyList()
fun after(block: Block, parent: Node): List<AstModification> = emptyList()
fun after(branchStatement: BranchStatement, parent: Node): List<AstModification> = emptyList()
fun after(breakStmt: Break, parent: Node): List<AstModification> = emptyList()
fun after(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): List<AstModification> = emptyList()
fun after(contStmt: Continue, parent: Node): List<AstModification> = emptyList()
fun after(decl: VarDecl, parent: Node): List<AstModification> = emptyList()
fun after(directive: Directive, parent: Node): List<AstModification> = emptyList()
fun after(expr: BinaryExpression, parent: Node): List<AstModification> = emptyList()
fun after(expr: PrefixExpression, parent: Node): List<AstModification> = emptyList()
fun after(forLoop: ForLoop, parent: Node): List<AstModification> = emptyList()
fun after(foreverLoop: ForeverLoop, parent: Node): List<AstModification> = emptyList()
fun after(functionCall: FunctionCall, parent: Node): List<AstModification> = emptyList()
fun after(functionCallStatement: FunctionCallStatement, parent: Node): List<AstModification> = emptyList()
fun after(identifier: IdentifierReference, parent: Node): List<AstModification> = emptyList()
fun after(ifStatement: IfStatement, parent: Node): List<AstModification> = emptyList()
fun after(inlineAssembly: InlineAssembly, parent: Node): List<AstModification> = emptyList()
fun after(jump: Jump, parent: Node): List<AstModification> = emptyList()
fun after(label: Label, parent: Node): List<AstModification> = emptyList()
fun after(memread: DirectMemoryRead, parent: Node): List<AstModification> = emptyList()
fun after(memwrite: DirectMemoryWrite, parent: Node): List<AstModification> = emptyList()
fun after(module: Module, parent: Node): List<AstModification> = emptyList()
fun after(nopStatement: NopStatement, parent: Node): List<AstModification> = emptyList()
fun after(numLiteral: NumericLiteralValue, parent: Node): List<AstModification> = emptyList()
fun after(postIncrDecr: PostIncrDecr, parent: Node): List<AstModification> = emptyList()
fun after(program: Program, parent: Node): List<AstModification> = emptyList()
fun after(range: RangeExpr, parent: Node): List<AstModification> = emptyList()
fun after(registerExpr: RegisterExpr, parent: Node): List<AstModification> = emptyList()
fun after(repeatLoop: RepeatLoop, parent: Node): List<AstModification> = emptyList()
fun after(returnStmt: Return, parent: Node): List<AstModification> = emptyList()
fun after(scope: AnonymousScope, parent: Node): List<AstModification> = emptyList()
fun after(string: StringLiteralValue, parent: Node): List<AstModification> = emptyList()
fun after(structDecl: StructDecl, parent: Node): List<AstModification> = emptyList()
fun after(structLv: StructLiteralValue, parent: Node): List<AstModification> = emptyList()
fun after(subroutine: Subroutine, parent: Node): List<AstModification> = emptyList()
fun after(typecast: TypecastExpression, parent: Node): List<AstModification> = emptyList()
fun after(whenChoice: WhenChoice, parent: Node): List<AstModification> = emptyList()
fun after(whenStatement: WhenStatement, parent: Node): List<AstModification> = emptyList()
fun after(whileLoop: WhileLoop, parent: Node): List<AstModification> = emptyList()
private fun applyModifications(mods: List<AstModification>, node: Node, parent: Node) {
mods.forEach { it.invoke(node, parent) }
}
fun visit(program: Program) {
applyModifications(before(program, program), program, program)
program.modules.forEach { it.accept(this, program) }
applyModifications(after(program, program), program, program)
}
fun visit(module: Module, parent: Node) {
applyModifications(before(module, parent), module, parent)
module.statements.forEach{ it.accept(this, module) }
applyModifications(after(module, parent), module, parent)
}
fun visit(expr: PrefixExpression, parent: Node) {
applyModifications(before(expr, parent), expr, parent)
expr.expression.accept(this, expr)
applyModifications(after(expr, parent), expr, parent)
}
fun visit(expr: BinaryExpression, parent: Node) {
applyModifications(before(expr, parent), expr, parent)
expr.left.accept(this, expr)
expr.right.accept(this, expr)
applyModifications(after(expr, parent), expr, parent)
}
fun visit(directive: Directive, parent: Node) {
applyModifications(before(directive, parent), directive, parent)
applyModifications(after(directive, parent), directive, parent)
}
fun visit(block: Block, parent: Node) {
applyModifications(before(block, parent), block, parent)
block.statements.forEach { it.accept(this, block) }
applyModifications(after(block, parent), block, parent)
}
fun visit(decl: VarDecl, parent: Node) {
applyModifications(before(decl, parent), decl, parent)
decl.value?.accept(this, decl)
decl.arraysize?.accept(this, decl)
applyModifications(after(decl, parent), decl, parent)
}
fun visit(subroutine: Subroutine, parent: Node) {
applyModifications(before(subroutine, parent), subroutine, parent)
subroutine.statements.forEach { it.accept(this, subroutine) }
applyModifications(after(subroutine, parent), subroutine, parent)
}
fun visit(functionCall: FunctionCall, parent: Node) {
applyModifications(before(functionCall, parent), functionCall, parent)
functionCall.target.accept(this, functionCall)
functionCall.args.forEach { it.accept(this, functionCall) }
applyModifications(after(functionCall, parent), functionCall, parent)
}
fun visit(functionCallStatement: FunctionCallStatement, parent: Node) {
applyModifications(before(functionCallStatement, parent), functionCallStatement, parent)
functionCallStatement.target.accept(this, functionCallStatement)
functionCallStatement.args.forEach { it.accept(this, functionCallStatement) }
applyModifications(after(functionCallStatement, parent), functionCallStatement, parent)
}
fun visit(identifier: IdentifierReference, parent: Node) {
applyModifications(before(identifier, parent), identifier, parent)
applyModifications(after(identifier, parent), identifier, parent)
}
fun visit(jump: Jump, parent: Node) {
applyModifications(before(jump, parent), jump, parent)
jump.identifier?.accept(this, jump)
applyModifications(after(jump, parent), jump, parent)
}
fun visit(ifStatement: IfStatement, parent: Node) {
applyModifications(before(ifStatement, parent), ifStatement, parent)
ifStatement.condition.accept(this, ifStatement)
ifStatement.truepart.accept(this, ifStatement)
ifStatement.elsepart.accept(this, ifStatement)
applyModifications(after(ifStatement, parent), ifStatement, parent)
}
fun visit(branchStatement: BranchStatement, parent: Node) {
applyModifications(before(branchStatement, parent), branchStatement, parent)
branchStatement.truepart.accept(this, branchStatement)
branchStatement.elsepart.accept(this, branchStatement)
applyModifications(after(branchStatement, parent), branchStatement, parent)
}
fun visit(range: RangeExpr, parent: Node) {
applyModifications(before(range, parent), range, parent)
range.from.accept(this, range)
range.to.accept(this, range)
range.step.accept(this, range)
applyModifications(after(range, parent), range, parent)
}
fun visit(label: Label, parent: Node) {
applyModifications(before(label, parent), label, parent)
applyModifications(after(label, parent), label, parent)
}
fun visit(numLiteral: NumericLiteralValue, parent: Node) {
applyModifications(before(numLiteral, parent), numLiteral, parent)
applyModifications(after(numLiteral, parent), numLiteral, parent)
}
fun visit(string: StringLiteralValue, parent: Node) {
applyModifications(before(string, parent), string, parent)
applyModifications(after(string, parent), string, parent)
}
fun visit(array: ArrayLiteralValue, parent: Node) {
applyModifications(before(array, parent), array, parent)
array.value.forEach { v->v.accept(this, array) }
applyModifications(after(array, parent), array, parent)
}
fun visit(assignment: Assignment, parent: Node) {
applyModifications(before(assignment, parent), assignment, parent)
assignment.target.accept(this, assignment)
assignment.value.accept(this, assignment)
applyModifications(after(assignment, parent), assignment, parent)
}
fun visit(postIncrDecr: PostIncrDecr, parent: Node) {
applyModifications(before(postIncrDecr, parent), postIncrDecr, parent)
postIncrDecr.target.accept(this, postIncrDecr)
applyModifications(after(postIncrDecr, parent), postIncrDecr, parent)
}
fun visit(contStmt: Continue, parent: Node) {
applyModifications(before(contStmt, parent), contStmt, parent)
applyModifications(after(contStmt, parent), contStmt, parent)
}
fun visit(breakStmt: Break, parent: Node) {
applyModifications(before(breakStmt, parent), breakStmt, parent)
applyModifications(after(breakStmt, parent), breakStmt, parent)
}
fun visit(forLoop: ForLoop, parent: Node) {
applyModifications(before(forLoop, parent), forLoop, parent)
forLoop.loopVar?.accept(this, forLoop)
forLoop.iterable.accept(this, forLoop)
forLoop.body.accept(this, forLoop)
applyModifications(after(forLoop, parent), forLoop, parent)
}
fun visit(whileLoop: WhileLoop, parent: Node) {
applyModifications(before(whileLoop, parent), whileLoop, parent)
whileLoop.condition.accept(this, whileLoop)
whileLoop.body.accept(this, whileLoop)
applyModifications(after(whileLoop, parent), whileLoop, parent)
}
fun visit(foreverLoop: ForeverLoop, parent: Node) {
applyModifications(before(foreverLoop, parent), foreverLoop, parent)
foreverLoop.body.accept(this, foreverLoop)
applyModifications(after(foreverLoop, parent), foreverLoop, parent)
}
fun visit(repeatLoop: RepeatLoop, parent: Node) {
applyModifications(before(repeatLoop, parent), repeatLoop, parent)
repeatLoop.untilCondition.accept(this, repeatLoop)
repeatLoop.body.accept(this, repeatLoop)
applyModifications(after(repeatLoop, parent), repeatLoop, parent)
}
fun visit(returnStmt: Return, parent: Node) {
applyModifications(before(returnStmt, parent), returnStmt, parent)
returnStmt.value?.accept(this, returnStmt)
applyModifications(after(returnStmt, parent), returnStmt, parent)
}
fun visit(arrayIndexedExpression: ArrayIndexedExpression, parent: Node) {
applyModifications(before(arrayIndexedExpression, parent), arrayIndexedExpression, parent)
arrayIndexedExpression.identifier.accept(this, arrayIndexedExpression)
arrayIndexedExpression.arrayspec.accept(this, arrayIndexedExpression)
applyModifications(after(arrayIndexedExpression, parent), arrayIndexedExpression, parent)
}
fun visit(assignTarget: AssignTarget, parent: Node) {
applyModifications(before(assignTarget, parent), assignTarget, parent)
assignTarget.arrayindexed?.accept(this, assignTarget)
assignTarget.identifier?.accept(this, assignTarget)
assignTarget.memoryAddress?.accept(this, assignTarget)
applyModifications(after(assignTarget, parent), assignTarget, parent)
}
fun visit(scope: AnonymousScope, parent: Node) {
applyModifications(before(scope, parent), scope, parent)
scope.statements.forEach { it.accept(this, scope) }
applyModifications(after(scope, parent), scope, parent)
}
fun visit(typecast: TypecastExpression, parent: Node) {
applyModifications(before(typecast, parent), typecast, parent)
typecast.expression.accept(this, typecast)
applyModifications(after(typecast, parent), typecast, parent)
}
fun visit(memread: DirectMemoryRead, parent: Node) {
applyModifications(before(memread, parent), memread, parent)
memread.addressExpression.accept(this, memread)
applyModifications(after(memread, parent), memread, parent)
}
fun visit(memwrite: DirectMemoryWrite, parent: Node) {
applyModifications(before(memwrite, parent), memwrite, parent)
memwrite.addressExpression.accept(this, memwrite)
applyModifications(after(memwrite, parent), memwrite, parent)
}
fun visit(addressOf: AddressOf, parent: Node) {
applyModifications(before(addressOf, parent), addressOf, parent)
addressOf.identifier.accept(this, addressOf)
applyModifications(after(addressOf, parent), addressOf, parent)
}
fun visit(inlineAssembly: InlineAssembly, parent: Node) {
applyModifications(before(inlineAssembly, parent), inlineAssembly, parent)
applyModifications(after(inlineAssembly, parent), inlineAssembly, parent)
}
fun visit(registerExpr: RegisterExpr, parent: Node) {
applyModifications(before(registerExpr, parent), registerExpr, parent)
applyModifications(after(registerExpr, parent), registerExpr, parent)
}
fun visit(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node) {
applyModifications(before(builtinFunctionStatementPlaceholder, parent), builtinFunctionStatementPlaceholder, parent)
applyModifications(after(builtinFunctionStatementPlaceholder, parent), builtinFunctionStatementPlaceholder, parent)
}
fun visit(nopStatement: NopStatement, parent: Node) {
applyModifications(before(nopStatement, parent), nopStatement, parent)
applyModifications(after(nopStatement, parent), nopStatement, parent)
}
fun visit(whenStatement: WhenStatement, parent: Node) {
applyModifications(before(whenStatement, parent), whenStatement, parent)
whenStatement.condition.accept(this, whenStatement)
whenStatement.choices.forEach { it.accept(this, whenStatement) }
applyModifications(after(whenStatement, parent), whenStatement, parent)
}
fun visit(whenChoice: WhenChoice, parent: Node) {
applyModifications(before(whenChoice, parent), whenChoice, parent)
whenChoice.values?.forEach { it.accept(this, whenChoice) }
whenChoice.statements.accept(this, whenChoice)
applyModifications(after(whenChoice, parent), whenChoice, parent)
}
fun visit(structDecl: StructDecl, parent: Node) {
applyModifications(before(structDecl, parent), structDecl, parent)
structDecl.statements.forEach { it.accept(this, structDecl) }
applyModifications(after(structDecl, parent), structDecl, parent)
}
fun visit(structLv: StructLiteralValue, parent: Node) {
applyModifications(before(structLv, parent), structLv, parent)
structLv.values.forEach { it.accept(this, structLv) }
applyModifications(after(structLv, parent), structLv, parent)
}
}

View File

@ -1,29 +1,20 @@
package prog8.ast.processing
import prog8.ast.Module
import prog8.ast.base.ErrorReporter
import prog8.ast.Node
import prog8.ast.statements.Directive
import prog8.ast.statements.Statement
internal class ImportedModuleDirectiveRemover(private val errors: ErrorReporter) : IAstModifyingVisitor {
internal class ImportedModuleDirectiveRemover: AstWalker() {
/**
* Most global directives don't apply for imported modules, so remove them
*/
override fun visit(module: Module) {
super.visit(module)
val newStatements : MutableList<Statement> = mutableListOf()
val moduleLevelDirectives = listOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address")
for (sourceStmt in module.statements) {
val stmt = sourceStmt.accept(this)
if(stmt is Directive && stmt.parent is Module) {
if(stmt.directive in moduleLevelDirectives) {
errors.warn("ignoring module directive because it was imported", stmt.position)
continue
}
}
newStatements.add(stmt)
private val moduleLevelDirectives = listOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address")
override fun before(directive: Directive, parent: Node): Iterable<AstModification> {
if(directive.directive in moduleLevelDirectives) {
return listOf(AstModification.Remove(directive, parent))
}
module.statements = newStatements
return emptyList()
}
}

View File

@ -1,24 +1,28 @@
package prog8.ast.processing
import prog8.ast.Node
import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.statements.ForeverLoop
import prog8.ast.statements.RepeatLoop
import prog8.ast.statements.Statement
import prog8.ast.statements.WhileLoop
internal class MakeForeverLoops : IAstModifyingVisitor {
override fun visit(whileLoop: WhileLoop): Statement {
val numeric = whileLoop.condition as? NumericLiteralValue
if(numeric!=null && numeric.number.toInt() != 0) {
return ForeverLoop(whileLoop.body, whileLoop.position)
internal class MakeForeverLoops: AstWalker() {
override fun before(repeatLoop: RepeatLoop, parent: Node): Iterable<AstModification> {
val numeric = repeatLoop.untilCondition as? NumericLiteralValue
if(numeric!=null && numeric.number.toInt() == 0) {
val forever = ForeverLoop(repeatLoop.body, repeatLoop.position)
return listOf(AstModification.Replace(repeatLoop, forever, parent))
}
return super.visit(whileLoop)
return emptyList()
}
override fun visit(repeatLoop: RepeatLoop): Statement {
val numeric = repeatLoop.untilCondition as? NumericLiteralValue
if(numeric!=null && numeric.number.toInt() == 0)
return ForeverLoop(repeatLoop.body, repeatLoop.position)
return super.visit(repeatLoop)
override fun before(whileLoop: WhileLoop, parent: Node): Iterable<AstModification> {
val numeric = whileLoop.condition as? NumericLiteralValue
if(numeric!=null && numeric.number.toInt() != 0) {
val forever = ForeverLoop(whileLoop.body, whileLoop.position)
return listOf(AstModification.Replace(whileLoop, forever, parent))
}
return emptyList()
}
}

View File

@ -6,7 +6,7 @@ import prog8.ast.statements.AnonymousScope
import prog8.ast.statements.Statement
import prog8.ast.statements.VarDecl
class AnonymousScopeVarsCleanup(private val errors: ErrorReporter): IAstModifyingVisitor {
class MoveAnonScopeVarsToSubroutine(private val errors: ErrorReporter): IAstModifyingVisitor {
private val varsToMove: MutableMap<AnonymousScope, List<VarDecl>> = mutableMapOf()
override fun visit(program: Program) {

View File

@ -8,45 +8,6 @@ import prog8.ast.expressions.*
import prog8.ast.statements.*
private fun flattenStructAssignmentFromIdentifier(structAssignment: Assignment, program: Program): List<Assignment> {
val identifier = structAssignment.target.identifier!!
val identifierName = identifier.nameInSource.single()
val targetVar = identifier.targetVarDecl(program.namespace)!!
val struct = targetVar.struct!!
when (structAssignment.value) {
is IdentifierReference -> {
val sourceVar = (structAssignment.value as IdentifierReference).targetVarDecl(program.namespace)!!
if (sourceVar.struct == null)
throw FatalAstException("can only assign arrays or structs to structs")
// struct memberwise copy
val sourceStruct = sourceVar.struct!!
if(sourceStruct!==targetVar.struct) {
// structs are not the same in assignment
return listOf() // error will be printed elsewhere
}
return struct.statements.zip(sourceStruct.statements).map { member ->
val targetDecl = member.first as VarDecl
val sourceDecl = member.second as VarDecl
if(targetDecl.name != sourceDecl.name)
throw FatalAstException("struct member mismatch")
val mangled = mangledStructMemberName(identifierName, targetDecl.name)
val idref = IdentifierReference(listOf(mangled), structAssignment.position)
val sourcemangled = mangledStructMemberName(sourceVar.name, sourceDecl.name)
val sourceIdref = IdentifierReference(listOf(sourcemangled), structAssignment.position)
val assign = Assignment(AssignTarget(null, idref, null, null, structAssignment.position),
null, sourceIdref, member.second.position)
assign.linkParents(structAssignment)
assign
}
}
is StructLiteralValue -> {
throw IllegalArgumentException("not going to flatten a structLv assignment here")
}
else -> throw FatalAstException("strange struct value")
}
}
internal class StatementReorderer(private val program: Program): IAstModifyingVisitor {
// Reorders the statements in a way the compiler needs.
// - 'main' block must be the very first statement UNLESS it has an address set.
@ -254,4 +215,44 @@ internal class StatementReorderer(private val program: Program): IAstModifyingVi
return assg
}
private fun flattenStructAssignmentFromIdentifier(structAssignment: Assignment, program: Program): List<Assignment> {
val identifier = structAssignment.target.identifier!!
val identifierName = identifier.nameInSource.single()
val targetVar = identifier.targetVarDecl(program.namespace)!!
val struct = targetVar.struct!!
when (structAssignment.value) {
is IdentifierReference -> {
val sourceVar = (structAssignment.value as IdentifierReference).targetVarDecl(program.namespace)!!
if (sourceVar.struct == null)
throw FatalAstException("can only assign arrays or structs to structs")
// struct memberwise copy
val sourceStruct = sourceVar.struct!!
if(sourceStruct!==targetVar.struct) {
// structs are not the same in assignment
return listOf() // error will be printed elsewhere
}
return struct.statements.zip(sourceStruct.statements).map { member ->
val targetDecl = member.first as VarDecl
val sourceDecl = member.second as VarDecl
if(targetDecl.name != sourceDecl.name)
throw FatalAstException("struct member mismatch")
val mangled = mangledStructMemberName(identifierName, targetDecl.name)
val idref = IdentifierReference(listOf(mangled), structAssignment.position)
val sourcemangled = mangledStructMemberName(sourceVar.name, sourceDecl.name)
val sourceIdref = IdentifierReference(listOf(sourcemangled), structAssignment.position)
val assign = Assignment(AssignTarget(null, idref, null, null, structAssignment.position),
null, sourceIdref, member.second.position)
assign.linkParents(structAssignment)
assign
}
}
is StructLiteralValue -> {
throw IllegalArgumentException("not going to flatten a structLv assignment here")
}
else -> throw FatalAstException("strange struct value")
}
}
}

View File

@ -5,13 +5,13 @@ import prog8.ast.base.*
import prog8.ast.expressions.*
import prog8.ast.processing.IAstModifyingVisitor
import prog8.ast.processing.IAstVisitor
import prog8.ast.processing.IGenericAstModifyingVisitor
import prog8.ast.processing.AstWalker
sealed class Statement : Node {
abstract fun accept(visitor: IAstModifyingVisitor) : Statement
abstract fun accept(visitor: IAstVisitor)
abstract fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)
abstract fun accept(visitor: AstWalker, parent: Node)
fun makeScopedName(name: String): String {
// easy way out is to always return the full scoped name.
@ -46,7 +46,7 @@ class BuiltinFunctionStatementPlaceholder(val name: String, override val positio
override fun linkParents(parent: Node) {}
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun definingScope(): INameScope = BuiltinFunctionScopePlaceholder
override val expensiveToInline = false
}
@ -69,7 +69,7 @@ class Block(override val name: String,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString(): String {
return "Block(name=$name, address=$address, ${statements.size} statements)"
@ -89,7 +89,7 @@ data class Directive(val directive: String, val args: List<DirectiveArg>, overri
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
data class DirectiveArg(val str: String?, val name: String?, val int: Int?, override val position: Position) : Node {
@ -110,7 +110,7 @@ data class Label(val name: String, override val position: Position) : Statement(
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString(): String {
return "Label(name=$name, pos=$position)"
@ -128,7 +128,7 @@ open class Return(var value: Expression?, override val position: Position) : Sta
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString(): String {
return "Return($value, pos=$position)"
@ -154,7 +154,7 @@ class Continue(override val position: Position) : Statement() {
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
class Break(override val position: Position) : Statement() {
@ -167,7 +167,7 @@ class Break(override val position: Position) : Statement() {
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
@ -245,7 +245,7 @@ class VarDecl(val type: VarDeclType,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
val scopedname: String by lazy { makeScopedName(name) }
@ -308,7 +308,7 @@ class ArrayIndex(var index: Expression, override val position: Position) : Node
index = index.accept(visitor)
}
fun accept(visitor: IAstVisitor) = index.accept(visitor)
fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = index.accept(visitor, parent)
fun accept(visitor: AstWalker, parent: Node) = index.accept(visitor, parent)
override fun toString(): String {
return("ArrayIndex($index, pos=$position)")
@ -330,7 +330,7 @@ open class Assignment(var target: AssignTarget, val aug_op : String?, var value:
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString(): String {
return("Assignment(augop: $aug_op, target: $target, value: $value, pos=$position)")
@ -358,7 +358,7 @@ data class AssignTarget(val register: Register?,
fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
fun accept(visitor: IAstVisitor) = visitor.visit(this)
fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
companion object {
fun fromExpr(expr: Expression): AssignTarget {
@ -457,7 +457,7 @@ class PostIncrDecr(var target: AssignTarget, val operator: String, override val
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString(): String {
return "PostIncrDecr(op: $operator, target: $target, pos=$position)"
@ -478,7 +478,7 @@ class Jump(val address: Int?,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString(): String {
return "Jump(addr: $address, identifier: $identifier, label: $generatedLabel; pos=$position)"
@ -501,7 +501,7 @@ class FunctionCallStatement(override var target: IdentifierReference,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString(): String {
return "FunctionCallStatement(target=$target, pos=$position)"
@ -518,7 +518,7 @@ class InlineAssembly(val assembly: String, override val position: Position) : St
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
class AnonymousScope(override var statements: MutableList<Statement>,
@ -544,7 +544,7 @@ class AnonymousScope(override var statements: MutableList<Statement>,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
class NopStatement(override val position: Position): Statement() {
@ -557,7 +557,7 @@ class NopStatement(override val position: Position): Statement() {
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
companion object {
fun insteadOf(stmt: Statement): NopStatement {
@ -600,7 +600,7 @@ class Subroutine(override val name: String,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString(): String {
return "Subroutine(name=$name, parameters=$parameters, returntypes=$returntypes, ${statements.size} statements, address=$asmAddress)"
@ -641,7 +641,7 @@ class IfStatement(var condition: Expression,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
@ -661,7 +661,7 @@ class BranchStatement(var condition: BranchCondition,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
@ -682,7 +682,7 @@ class ForLoop(val loopRegister: Register?,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString(): String {
return "ForLoop(loopVar: $loopVar, loopReg: $loopRegister, iterable: $iterable, pos=$position)"
@ -709,7 +709,7 @@ class WhileLoop(var condition: Expression,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
class ForeverLoop(var body: AnonymousScope, override val position: Position) : Statement() {
@ -723,7 +723,7 @@ class ForeverLoop(var body: AnonymousScope, override val position: Position) : S
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
class RepeatLoop(var body: AnonymousScope,
@ -740,7 +740,7 @@ class RepeatLoop(var body: AnonymousScope,
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
class WhenStatement(var condition: Expression,
@ -774,7 +774,7 @@ class WhenStatement(var condition: Expression,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
class WhenChoice(var values: List<Expression>?, // if null, this is the 'else' part
@ -794,7 +794,7 @@ class WhenChoice(var values: List<Expression>?, // if null, this is t
fun accept(visitor: IAstVisitor) = visitor.visit(this)
fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
@ -815,7 +815,7 @@ class StructDecl(override val name: String,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
override fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
fun nameOfFirstMember() = (statements.first() as VarDecl).name
}
@ -834,5 +834,5 @@ class DirectMemoryWrite(var addressExpression: Expression, override val position
fun accept(visitor: IAstVisitor) = visitor.visit(this)
fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = visitor.visit(this, parent)
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}

View File

@ -0,0 +1,46 @@
package prog8.optimizer
import prog8.ast.INameScope
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.processing.IAstVisitor
import prog8.ast.statements.AnonymousScope
import prog8.ast.statements.NopStatement
import prog8.ast.statements.Statement
internal class FlattenAnonymousScopesAndRemoveNops: IAstVisitor {
private var scopesToFlatten = mutableListOf<INameScope>()
private val nopStatements = mutableListOf<NopStatement>()
override fun visit(program: Program) {
super.visit(program)
for(scope in scopesToFlatten.reversed()) {
val namescope = scope.parent as INameScope
val idx = namescope.statements.indexOf(scope as Statement)
if(idx>=0) {
val nop = NopStatement.insteadOf(namescope.statements[idx])
nop.parent = namescope as Node
namescope.statements[idx] = nop
namescope.statements.addAll(idx, scope.statements)
scope.statements.forEach { it.parent = namescope }
visit(nop)
}
}
this.nopStatements.forEach {
it.definingScope().remove(it)
}
}
override fun visit(scope: AnonymousScope) {
if(scope.parent is INameScope) {
scopesToFlatten.add(scope) // get rid of the anonymous scope
}
return super.visit(scope)
}
override fun visit(nopStatement: NopStatement) {
nopStatements.add(nopStatement)
}
}

View File

@ -2,12 +2,10 @@ package prog8.optimizer
import prog8.ast.INameScope
import prog8.ast.Module
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.base.*
import prog8.ast.expressions.*
import prog8.ast.processing.IAstModifyingVisitor
import prog8.ast.processing.IAstVisitor
import prog8.ast.statements.*
import prog8.compiler.target.CompilationTarget
import prog8.functions.BuiltinFunctions
@ -582,39 +580,3 @@ internal class StatementOptimizer(private val program: Program,
internal class FlattenAnonymousScopesAndRemoveNops: IAstVisitor {
private var scopesToFlatten = mutableListOf<INameScope>()
private val nopStatements = mutableListOf<NopStatement>()
override fun visit(program: Program) {
super.visit(program)
for(scope in scopesToFlatten.reversed()) {
val namescope = scope.parent as INameScope
val idx = namescope.statements.indexOf(scope as Statement)
if(idx>=0) {
val nop = NopStatement.insteadOf(namescope.statements[idx])
nop.parent = namescope as Node
namescope.statements[idx] = nop
namescope.statements.addAll(idx, scope.statements)
scope.statements.forEach { it.parent = namescope }
visit(nop)
}
}
this.nopStatements.forEach {
it.definingScope().remove(it)
}
}
override fun visit(scope: AnonymousScope) {
if(scope.parent is INameScope) {
scopesToFlatten.add(scope) // get rid of the anonymous scope
}
return super.visit(scope)
}
override fun visit(nopStatement: NopStatement) {
nopStatements.add(nopStatement)
}
}

View File

@ -140,7 +140,7 @@ internal class ModuleImporter(private val errors: ErrorReporter) {
importModule(program, modulePath)
}
importedModule.checkImportedValid(errors)
importedModule.checkImportedValid()
return importedModule
}

View File

@ -5,6 +5,15 @@ main {
sub start() {
while true {
A=99
}
repeat {
A=44
} until false
c64scr.print("spstart:")
print_stackpointer()
sub1()