add more referencesIdentifier() on ast nodes

This commit is contained in:
Irmen de Jong
2023-03-15 20:44:24 +01:00
parent b8113fff1e
commit af1b07ad44
4 changed files with 69 additions and 24 deletions

View File

@@ -21,6 +21,7 @@ object ParentSentinel : Node {
}
override fun copy(): Node = throw FatalAstException("should never duplicate a ParentSentinel")
override fun referencesIdentifier(nameInSource: List<String>): Boolean = false
}
@@ -254,6 +255,7 @@ interface Node {
fun replaceChildNode(node: Node, replacement: Node)
fun copy(): Node
fun referencesIdentifier(nameInSource: List<String>): Boolean
}
@@ -309,6 +311,8 @@ open class Module(final override var statements: MutableList<Statement>,
override fun copy(): Node = throw NotImplementedError("no support for duplicating a Module")
override fun toString() = "Module(name=$name, pos=$position, lib=${isLibrary})"
override fun referencesIdentifier(nameInSource: List<String>): Boolean = statements.any { it.referencesIdentifier(nameInSource) }
fun accept(visitor: IAstVisitor) = visitor.visit(this)
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
@@ -336,6 +340,8 @@ class GlobalNamespace(val modules: Iterable<Module>): Node, INameScope {
override fun replaceChildNode(node: Node, replacement: Node) {
throw FatalAstException("cannot replace anything in the namespace")
}
override fun referencesIdentifier(nameInSource: List<String>): Boolean = modules.any { it.referencesIdentifier(nameInSource) }
}
internal object BuiltinFunctionScopePlaceholder : INameScope {

View File

@@ -21,7 +21,6 @@ sealed class Expression: Node {
abstract fun constValue(program: Program): NumericLiteral?
abstract fun accept(visitor: IAstVisitor)
abstract fun accept(visitor: AstWalker, parent: Node)
abstract fun referencesIdentifier(nameInSource: List<String>): Boolean
abstract fun inferType(program: Program): InferredTypes.InferredType
abstract val isSimple: Boolean
@@ -307,7 +306,7 @@ class ArrayIndexedExpression(var arrayvar: IdentifierReference,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>) = arrayvar.referencesIdentifier(nameInSource)
override fun referencesIdentifier(nameInSource: List<String>) = arrayvar.referencesIdentifier(nameInSource) || indexer.referencesIdentifier(nameInSource)
override fun inferType(program: Program): InferredTypes.InferredType {
val target = arrayvar.targetStatement(program)
@@ -835,7 +834,7 @@ class RangeExpression(var from: Expression,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = from.referencesIdentifier(nameInSource) || to.referencesIdentifier(nameInSource)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = from.referencesIdentifier(nameInSource) || to.referencesIdentifier(nameInSource) || step.referencesIdentifier(nameInSource)
override fun inferType(program: Program): InferredTypes.InferredType {
val fromDt=from.inferType(program)
val toDt=to.inferType(program)
@@ -898,7 +897,6 @@ class RangeExpression(var from: Expression,
}
}
data class IdentifierReference(val nameInSource: List<String>, override val position: Position) : Expression() {
override lateinit var parent: Node
@@ -1062,7 +1060,6 @@ class FunctionCallExpression(override var target: IdentifierReference,
}
}
class ContainmentCheck(var element: Expression,
var iterable: Expression,
override val position: Position): Expression() {
@@ -1114,11 +1111,7 @@ class ContainmentCheck(var element: Expression,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean {
if(element is IdentifierReference)
return element.referencesIdentifier(nameInSource)
return iterable.referencesIdentifier(nameInSource)
}
override fun referencesIdentifier(nameInSource: List<String>): Boolean = element.referencesIdentifier(nameInSource) || iterable.referencesIdentifier(nameInSource)
override fun inferType(program: Program) = InferredTypes.knownFor(DataType.BOOL)
@@ -1134,17 +1127,6 @@ class ContainmentCheck(var element: Expression,
}
}
fun invertCondition(cond: Expression): BinaryExpression? {
if(cond is BinaryExpression) {
val invertedOperator = invertedComparisonOperator(cond.operator)
if (invertedOperator != null)
return BinaryExpression(cond.left, invertedOperator, cond.right, cond.position)
}
return null
}
class BuiltinFunctionCall(override var target: IdentifierReference,
override var args: MutableList<Expression>,
override val position: Position) : Expression(), IFunctionCall {
@@ -1185,3 +1167,12 @@ class BuiltinFunctionCall(override var target: IdentifierReference,
override fun referencesIdentifier(nameInSource: List<String>): Boolean = target.referencesIdentifier(nameInSource) || args.any{it.referencesIdentifier(nameInSource)}
override fun inferType(program: Program) = program.builtinFunctions.returnType(name)
}
fun invertCondition(cond: Expression): BinaryExpression? {
if(cond is BinaryExpression) {
val invertedOperator = invertedComparisonOperator(cond.operator)
if (invertedOperator != null)
return BinaryExpression(cond.left, invertedOperator, cond.right, cond.position)
}
return null
}

View File

@@ -64,6 +64,7 @@ class BuiltinFunctionPlaceholder(override val name: String, override val positio
}
override fun copy() = throw NotImplementedError("no support for duplicating a BuiltinFunctionStatementPlaceholder")
override fun referencesIdentifier(nameInSource: List<String>): Boolean = nameInSource.size==1 && name==nameInSource[0]
}
class Block(override val name: String,
@@ -90,6 +91,7 @@ class Block(override val name: String,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString() = "Block(name=$name, address=$address, ${statements.size} statements)"
override fun referencesIdentifier(nameInSource: List<String>): Boolean = statements.any { it.referencesIdentifier(nameInSource) }
fun options() = statements.filter { it is Directive && it.directive == "%option" }.flatMap { (it as Directive).args }.map {it.name!!}.toSet()
}
@@ -104,6 +106,7 @@ data class Directive(val directive: String, val args: List<DirectiveArg>, overri
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
override fun copy() = Directive(directive, args.map { it.copy() }, position)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = false
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
}
@@ -116,6 +119,7 @@ data class DirectiveArg(val str: String?, val name: String?, val int: UInt?, ove
}
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
override fun copy() = DirectiveArg(str, name, int, position)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = false
}
data class Label(override val name: String, override val position: Position) : Statement(), INamedStatement {
@@ -127,6 +131,7 @@ data class Label(override val name: String, override val position: Position) : S
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
override fun copy() = Label(name, position)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = nameInSource.size==1 && nameInSource[0]==name
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString()= "Label(name=$name, pos=$position)"
@@ -147,6 +152,7 @@ class Return(var value: Expression?, override val position: Position) : Statemen
}
override fun copy() = Return(value?.copy(), position)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = value?.referencesIdentifier(nameInSource)==true
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString() = "Return($value, pos=$position)"
@@ -160,6 +166,7 @@ class Break(override val position: Position) : Statement() {
}
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
override fun referencesIdentifier(nameInSource: List<String>): Boolean = false
override fun copy() = Break(position)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
@@ -277,6 +284,10 @@ class VarDecl(val type: VarDeclType,
.asSequence()
.filterIsInstance<Assignment>()
.singleOrNull { it.origin==AssignmentOrigin.VARINIT && it.target.identifier?.targetVarDecl(program) === this }
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
value?.referencesIdentifier(nameInSource)==true ||
this.arraysize?.referencesIdentifier(nameInSource)==true
}
class ArrayIndex(var indexExpr: Expression,
@@ -309,6 +320,7 @@ class ArrayIndex(var indexExpr: Expression,
infix fun isSameAs(other: ArrayIndex): Boolean = indexExpr isSameAs other.indexExpr
override fun copy() = ArrayIndex(indexExpr.copy(), position)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = indexExpr.referencesIdentifier(nameInSource)
}
enum class AssignmentOrigin {
@@ -340,6 +352,7 @@ class Assignment(var target: AssignTarget, var value: Expression, var origin: As
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString() = "Assignment(target: $target, value: $value, pos=$position)"
override fun referencesIdentifier(nameInSource: List<String>): Boolean = target.referencesIdentifier(nameInSource) || value.referencesIdentifier(nameInSource)
/**
* Is the assigment value an expression that references the assignment target itself?
@@ -429,6 +442,10 @@ data class AssignTarget(var identifier: IdentifierReference?,
fun accept(visitor: IAstVisitor) = visitor.visit(this)
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun copy() = AssignTarget(identifier?.copy(), arrayindexed?.copy(), memoryAddress?.copy(), position)
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
identifier?.referencesIdentifier(nameInSource)==true ||
arrayindexed?.referencesIdentifier(nameInSource)==true ||
memoryAddress?.referencesIdentifier(nameInSource)==true
fun inferType(program: Program): InferredTypes.InferredType {
if (identifier != null) {
@@ -554,6 +571,7 @@ class PostIncrDecr(var target: AssignTarget, val operator: String, override val
replacement.parent = this
}
override fun referencesIdentifier(nameInSource: List<String>): Boolean = target.referencesIdentifier(nameInSource)
override fun copy() = PostIncrDecr(target.copy(), operator, position)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
@@ -581,6 +599,7 @@ class Jump(var address: UInt?,
override fun copy() = Jump(address, identifier?.copy(), generatedLabel, position)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = identifier?.referencesIdentifier(nameInSource)==true
override fun toString() =
"Jump(addr: $address, identifier: $identifier, label: $generatedLabel; pos=$position)"
@@ -613,6 +632,7 @@ class FunctionCallStatement(override var target: IdentifierReference,
replacement.parent = this
}
override fun referencesIdentifier(nameInSource: List<String>): Boolean = target.referencesIdentifier(nameInSource) || args.any { it.referencesIdentifier(nameInSource) }
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString() = "FunctionCallStatement(target=$target, pos=$position)"
@@ -630,6 +650,7 @@ class InlineAssembly(val assembly: String, val isIR: Boolean, override val posit
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = false
fun hasReturnOrRts(): Boolean {
return if(isIR) {
@@ -671,6 +692,7 @@ class AnonymousScope(override var statements: MutableList<Statement>,
replacement.parent = this
}
override fun referencesIdentifier(nameInSource: List<String>): Boolean = statements.any { it.referencesIdentifier(nameInSource) }
override fun copy() = AnonymousScope(statements.map { it.copy() }.toMutableList(), position)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
@@ -717,6 +739,10 @@ class Subroutine(override val name: String,
}
}
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
statements.any { it.referencesIdentifier(nameInSource) } ||
parameters.any { it.referencesIdentifier(nameInSource) }
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString() =
@@ -738,6 +764,7 @@ open class SubroutineParameter(val name: String,
override fun copy() = SubroutineParameter(name, type, position)
override fun toString() = "Param($type:$name)"
override fun referencesIdentifier(nameInSource: List<String>): Boolean = nameInSource.size==1 && name==nameInSource[0]
}
class IfElse(var condition: Expression,
@@ -767,7 +794,10 @@ class IfElse(var condition: Expression,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
condition.referencesIdentifier(nameInSource) ||
truepart.referencesIdentifier(nameInSource) ||
elsepart.referencesIdentifier(nameInSource)
}
class ConditionalBranch(var condition: BranchCondition,
@@ -795,7 +825,8 @@ class ConditionalBranch(var condition: BranchCondition,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
truepart.referencesIdentifier(nameInSource) || elsepart.referencesIdentifier(nameInSource)
}
class ForLoop(var loopVar: IdentifierReference,
@@ -826,6 +857,10 @@ class ForLoop(var loopVar: IdentifierReference,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString() = "ForLoop(loopVar: $loopVar, iterable: $iterable, pos=$position)"
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
loopVar.referencesIdentifier(nameInSource) ||
iterable.referencesIdentifier(nameInSource) ||
body.referencesIdentifier(nameInSource)
fun loopVarDt(program: Program) = loopVar.inferType(program)
}
@@ -854,6 +889,8 @@ class WhileLoop(var condition: Expression,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
condition.referencesIdentifier(nameInSource) || body.referencesIdentifier(nameInSource)
}
class RepeatLoop(var iterations: Expression?, var body: AnonymousScope, override val position: Position) : Statement() {
@@ -878,6 +915,8 @@ class RepeatLoop(var iterations: Expression?, var body: AnonymousScope, override
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
iterations?.referencesIdentifier(nameInSource)==true || body.referencesIdentifier(nameInSource)
}
class UnrollLoop(val iterations: Int, var body: AnonymousScope, override val position: Position) : Statement() {
@@ -898,6 +937,7 @@ class UnrollLoop(val iterations: Int, var body: AnonymousScope, override val pos
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = body.referencesIdentifier(nameInSource)
}
class UntilLoop(var body: AnonymousScope,
@@ -923,6 +963,8 @@ class UntilLoop(var body: AnonymousScope,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
condition.referencesIdentifier(nameInSource) || body.referencesIdentifier(nameInSource)
}
class When(var condition: Expression,
@@ -967,6 +1009,8 @@ class When(var condition: Expression,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
condition.referencesIdentifier(nameInSource) || choices.any { it.referencesIdentifier(nameInSource) }
}
class WhenChoice(var values: MutableList<Expression>?, // if null, this is the 'else' part
@@ -999,6 +1043,8 @@ class WhenChoice(var values: MutableList<Expression>?, // if null, th
fun accept(visitor: IAstVisitor) = visitor.visit(this)
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun referencesIdentifier(nameInSource: List<String>): Boolean =
values?.any { it.referencesIdentifier(nameInSource) }==true || statements.referencesIdentifier(nameInSource)
}
class DirectMemoryWrite(var addressExpression: Expression, override val position: Position) : Node {
@@ -1019,6 +1065,7 @@ class DirectMemoryWrite(var addressExpression: Expression, override val position
fun accept(visitor: IAstVisitor) = visitor.visit(this)
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun copy() = DirectMemoryWrite(addressExpression.copy(), position)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = addressExpression.referencesIdentifier(nameInSource)
}
@@ -1047,6 +1094,7 @@ class BuiltinFunctionCallStatement(override var target: IdentifierReference,
replacement.parent = this
}
override fun referencesIdentifier(nameInSource: List<String>): Boolean = target.referencesIdentifier(nameInSource) || args.any { it.referencesIdentifier(nameInSource) }
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString() = "BuiltinFunctionCallStatement(name=$name, pos=$position)"

View File

@@ -4,7 +4,7 @@ TODO
For next minor release
^^^^^^^^^^^^^^^^^^^^^^
- when a loopvariable of a forloop is *only* referenced in the for loop as loopvariable, and the number of iterations is known, replace the loop by a repeatloop (and remove the vardecl)
but we have no efficient way right now to see if the body references a variable. (what about ReferencesIdentifier? - only on Expressions now)
but we have no efficient way right now to see if the body references a variable. (what about ReferencesIdentifier?)
...