Skip to content

Commit

Permalink
Added EOG behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto committed Feb 11, 2025
1 parent 2036659 commit 0779172
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1485,12 +1485,26 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
}

/**
* This adds an extra declaration to the EOG of the [AssignExpression]. This is needed if we somehow
* add the declaration after the pass has initially run.
* This adds an extra declaration (see [AssignExpression.declarations] to the EOG of the
* [AssignExpression]. This is needed if we somehow add the declaration after the pass has initially
* run.
*
* This mimics the behaviour in [EvaluationOrderGraphPass.handleAssignExpression].
*/
fun AssignExpression.addDeclarationToEOG(decl: Declaration): Boolean? {
// We need to insert the declaration before the first lhs ref
return this.lhs.firstOrNull()?.insertNodeBeforeInEOGPath(decl)
}

/**
* This adds an extra local declaration (see [ForEachStatement.locals]) to the EOG of the
* [ForEachStatement]. This is needed if we somehow add the declaration after the pass has initially
* run.
*
* This mimics the behaviour in [EvaluationOrderGraphPass.handleForEachStatement].
*/
fun ForEachStatement.addDeclarationToEOG(decl: Declaration): Boolean? {
// Actually, it seems like we are not adding the declaration of a local variable to the EOG of
// the ForEachStatement at all.
return true
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,45 +159,47 @@ private val Reference.refersToReceiver: Boolean
}

/**
* Generates a new [VariableDeclaration] if [target] is a [Reference] and there is no existing
* Generates a new [VariableDeclaration] if [ref] is a [Reference] and there is no existing
* declaration yet.
*/
internal fun Pass<*>.handleAssignmentToTarget(
internal fun SymbolResolver.provideDeclarationForAssignExpression(
assignExpression: AssignExpression,
target: Node,
ref: Reference,
setAccessValue: Boolean = false,
): Declaration? {
return (target as? Reference)?.let {
if (setAccessValue) it.access = AccessValues.WRITE
val handled = handleWriteToReference(target)
if (handled != null) {
// We cannot assign an initializer here because this will lead to duplicate
// DFG edges, but we need to propagate the type information from our value
// to the declaration. We therefore add the declaration to the observers of
// the value's type, so that it gets informed and can change its own type
// accordingly.
assignExpression
.findValue(target)
?.registerTypeObserver(InitializerTypePropagation(handled))

// Add it to our assign expression, so that we can find it in the AST
assignExpression.declarations += handled

// "Inject" the declaration into the EOG
assignExpression.addDeclarationToEOG(handled)
}
handled
if (setAccessValue) {
ref.access = AccessValues.WRITE
}
val handled = handleWriteToReference(ref)
if (handled != null) {
// We cannot assign an initializer here because this will lead to duplicate
// DFG edges, but we need to propagate the type information from our value
// to the declaration. We therefore add the declaration to the observers of
// the value's type, so that it gets informed and can change its own type
// accordingly.
assignExpression.findValue(ref)?.registerTypeObserver(InitializerTypePropagation(handled))

// Add it to our assign expression, so that we can find it in the AST
assignExpression.declarations += handled

// "Inject" the declaration into the EOG
assignExpression.addDeclarationToEOG(handled)
}

return handled
}

// New variables can also be declared as `variable` in a [ForEachStatement]
private fun Pass<*>.handleForEach(node: ForEachStatement) {
when (val forVar = node.variable) {
is Reference -> {
val handled = handleWriteToReference(forVar)
if (handled is Declaration) {
handled.let { node.addDeclaration(it) }
}
}
internal fun SymbolResolver.provideDeclarationForForEachStatement(
forEachStmt: ForEachStatement,
ref: Reference,
): Declaration? {
val handled = handleWriteToReference(ref)
if (handled != null) {
forEachStmt.addDeclaration(handled)

// "Inject" the declaration into the EOG
forEachStmt.addDeclarationToEOG(handled)
}

return handled
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ class PythonLanguage :
override fun SymbolResolver.provideDeclaration(ref: Reference): Declaration? {
// Completely hacky
return if (ref.astParent is AssignExpression) {
handleAssignmentToTarget(
provideDeclarationForAssignExpression(
ref.astParent!! as AssignExpression,
ref,
setAccessValue = false,
Expand All @@ -242,17 +242,13 @@ class PythonLanguage :
ref.astParent is InitializerListExpression &&
ref.astParent?.astParent is AssignExpression
) {
handleAssignmentToTarget(
provideDeclarationForAssignExpression(
ref.astParent!!.astParent as AssignExpression,
ref,
setAccessValue = true,
)
} else if (ref.astParent is ForEachStatement) {
val handled = handleWriteToReference(ref)
if (handled is Declaration) {
handled.let { (ref.astParent as ForEachStatement).addDeclaration(it) }
}
handled
provideDeclarationForForEachStatement(ref.astParent as ForEachStatement, ref)
} else {
null
}
Expand Down

0 comments on commit 0779172

Please sign in to comment.