new astvisitor tryout

This commit is contained in:
Irmen de Jong 2020-03-18 23:28:56 +01:00
parent 0ee4d420b1
commit 40e6091506
4 changed files with 438 additions and 4 deletions

View File

@ -5,6 +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.statements.*
import prog8.functions.BuiltinFunctions
import java.nio.file.Path
@ -251,6 +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)
}

View File

@ -5,6 +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.statements.*
import prog8.compiler.target.CompilationTarget
import prog8.functions.BuiltinFunctions
@ -21,6 +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 referencesIdentifiers(vararg name: String): Boolean // todo: remove this and add identifier usage tracking into CallGraph instead
abstract fun inferType(program: Program): InferredTypes.InferredType
@ -59,6 +61,8 @@ 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 referencesIdentifiers(vararg name: String) = expression.referencesIdentifiers(*name)
override fun inferType(program: Program): InferredTypes.InferredType {
val inferred = expression.inferType(program)
@ -105,6 +109,8 @@ 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 referencesIdentifiers(vararg name: String) = left.referencesIdentifiers(*name) || right.referencesIdentifiers(*name)
override fun inferType(program: Program): InferredTypes.InferredType {
val leftDt = left.inferType(program)
@ -208,6 +214,8 @@ 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 referencesIdentifiers(vararg name: String) = identifier.referencesIdentifiers(*name)
override fun inferType(program: Program): InferredTypes.InferredType {
@ -237,6 +245,8 @@ 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 referencesIdentifiers(vararg name: String) = expression.referencesIdentifiers(*name)
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(type)
override fun constValue(program: Program): NumericLiteralValue? {
@ -264,6 +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)
}
class DirectMemoryRead(var addressExpression: Expression, override val position: Position) : Expression(), IAssignable {
@ -276,6 +287,8 @@ 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 referencesIdentifiers(vararg name: String) = false
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(DataType.UBYTE)
override fun constValue(program: Program): NumericLiteralValue? = null
@ -330,6 +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 toString(): String = "NumericLiteral(${type.name}:$number)"
@ -416,6 +430,8 @@ 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 referencesIdentifiers(vararg name: String) = values.any { it.referencesIdentifiers(*name) }
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(DataType.STRUCT)
@ -440,6 +456,8 @@ 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 toString(): String = "'${escape(value)}'"
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(DataType.STR)
operator fun compareTo(other: StringLiteralValue): Int = value.compareTo(other.value)
@ -466,6 +484,8 @@ 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 toString(): String = "$value"
override fun inferType(program: Program): InferredTypes.InferredType = if(type.isUnknown) type else guessDatatype(program)
@ -547,6 +567,8 @@ 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 referencesIdentifiers(vararg name: String): Boolean = from.referencesIdentifiers(*name) || to.referencesIdentifiers(*name)
override fun inferType(program: Program): InferredTypes.InferredType {
val fromDt=from.inferType(program)
@ -621,6 +643,8 @@ 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 referencesIdentifiers(vararg name: String): Boolean = register.name in name
override fun toString(): String {
return "RegisterExpr(register=$register, pos=$position)"
@ -663,6 +687,8 @@ 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 referencesIdentifiers(vararg name: String): Boolean = nameInSource.last() in name
override fun inferType(program: Program): InferredTypes.InferredType {
@ -737,6 +763,8 @@ 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 referencesIdentifiers(vararg name: String): Boolean = target.referencesIdentifiers(*name) || args.any{it.referencesIdentifiers(*name)}
override fun inferType(program: Program): InferredTypes.InferredType {

View File

@ -0,0 +1,373 @@
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

@ -5,11 +5,14 @@ import prog8.ast.base.*
import prog8.ast.expressions.*
import prog8.ast.processing.IAstModifyingVisitor
import prog8.ast.processing.IAstVisitor
import prog8.ast.processing.IGenericAstModifyingVisitor
sealed class Statement : Node {
abstract fun accept(visitor: IAstModifyingVisitor) : Statement
abstract fun accept(visitor: IAstVisitor)
abstract fun accept(visitor: IGenericAstModifyingVisitor, parent: Node)
fun makeScopedName(name: String): String {
// easy way out is to always return the full scoped name.
// it would be nicer to find only the minimal prefixed scoped name, but that's too much hassle for now.
@ -37,11 +40,13 @@ sealed class Statement : Node {
}
}
class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position) : Statement() {
override var parent: Node = ParentSentinel
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 definingScope(): INameScope = BuiltinFunctionScopePlaceholder
override val expensiveToInline = false
}
@ -64,6 +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 toString(): String {
return "Block(name=$name, address=$address, ${statements.size} statements)"
@ -83,6 +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)
}
data class DirectiveArg(val str: String?, val name: String?, val int: Int?, override val position: Position) : Node {
@ -103,6 +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 toString(): String {
return "Label(name=$name, pos=$position)"
@ -120,6 +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 toString(): String {
return "Return($value, pos=$position)"
@ -145,6 +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)
}
class Break(override val position: Position) : Statement() {
@ -157,6 +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)
}
@ -234,6 +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)
val scopedname: String by lazy { makeScopedName(name) }
@ -295,10 +307,8 @@ class ArrayIndex(var index: Expression, override val position: Position) : Node
fun accept(visitor: IAstModifyingVisitor) {
index = index.accept(visitor)
}
fun accept(visitor: IAstVisitor) {
index.accept(visitor)
}
fun accept(visitor: IAstVisitor) = index.accept(visitor)
fun accept(visitor: IGenericAstModifyingVisitor, parent: Node) = index.accept(visitor, parent)
override fun toString(): String {
return("ArrayIndex($index, pos=$position)")
@ -320,6 +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 toString(): String {
return("Assignment(augop: $aug_op, target: $target, value: $value, pos=$position)")
@ -347,6 +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)
companion object {
fun fromExpr(expr: Expression): AssignTarget {
@ -445,6 +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 toString(): String {
return "PostIncrDecr(op: $operator, target: $target, pos=$position)"
@ -465,6 +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 toString(): String {
return "Jump(addr: $address, identifier: $identifier, label: $generatedLabel; pos=$position)"
@ -487,6 +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 toString(): String {
return "FunctionCallStatement(target=$target, pos=$position)"
@ -503,6 +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)
}
class AnonymousScope(override var statements: MutableList<Statement>,
@ -528,6 +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)
}
class NopStatement(override val position: Position): Statement() {
@ -540,6 +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)
companion object {
fun insteadOf(stmt: Statement): NopStatement {
@ -582,6 +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 toString(): String {
return "Subroutine(name=$name, parameters=$parameters, returntypes=$returntypes, ${statements.size} statements, address=$asmAddress)"
@ -622,6 +641,8 @@ 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)
}
class BranchStatement(var condition: BranchCondition,
@ -640,6 +661,8 @@ 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)
}
class ForLoop(val loopRegister: Register?,
@ -659,6 +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 toString(): String {
return "ForLoop(loopVar: $loopVar, loopReg: $loopRegister, iterable: $iterable, pos=$position)"
@ -685,6 +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)
}
class ForeverLoop(var body: AnonymousScope, override val position: Position) : Statement() {
@ -698,6 +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)
}
class RepeatLoop(var body: AnonymousScope,
@ -714,6 +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)
}
class WhenStatement(var condition: Expression,
@ -747,6 +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)
}
class WhenChoice(var values: List<Expression>?, // if null, this is the 'else' part
@ -766,6 +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)
}
@ -786,6 +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)
fun nameOfFirstMember() = (statements.first() as VarDecl).name
}
@ -804,4 +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)
}