Skip to content

Commit

Permalink
Fixed recursive closure capture, now checks intermediate scopes for v…
Browse files Browse the repository at this point in the history
…ariable declaration
  • Loading branch information
alexnask committed Feb 19, 2013
1 parent cee2f30 commit e7c0599
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 14 deletions.
28 changes: 22 additions & 6 deletions source/rock/middle/FunctionCall.ooc
Original file line number Diff line number Diff line change
Expand Up @@ -360,13 +360,29 @@ FunctionCall: class extends Expression {
while(scopeDepth > 0) {
maybeScope := trail get(scopeDepth, Node)
if(maybeScope instanceOf?(Scope)) {
scope := maybeScope as Scope
maybeClosure := trail get(scopeDepth - 1, Node)
// Make sure the variable we will partial on the top level closure is not one of its arguments
if(maybeClosure instanceOf?(FunctionDecl) && maybeClosure as FunctionDecl isAnon \
&& !maybeClosure as FunctionDecl args contains?(|arg| arg == ref vDecl || arg name == ref vDecl name + "_generic") \
&& !maybeScope as Scope list contains?(|stmt| stmt instanceOf?(VariableDecl) && stmt as VariableDecl name == ref vDecl name)) {
// Mark the variable for partialing in the top level closure
maybeClosure as FunctionDecl markForPartialing(ref vDecl, "v")
if(maybeClosure instanceOf?(FunctionDecl)) {
closure := maybeClosure as FunctionDecl
// Find out if our access is between the kid closure and the parent closure
isDefined? := false
intermediateScopeIndex := closureIndex - 1
while(intermediateScopeIndex > scopeDepth) {
interScope? := trail get(intermediateScopeIndex, Node)
if(interScope? instanceOf?(Scope)) {
interScope := interScope? as Scope
if(interScope list contains?(|stmt| stmt instanceOf?(VariableDecl) && stmt as VariableDecl name == name)) {
isDefined? = true
}
}
intermediateScopeIndex -= 1
}
// Only partial the variable in the top function if it has not be defined by it and it is not one of its arguments
if(closure isAnon && !closure args contains?(|arg| arg name == ref vDecl name || arg name == ref vDecl name + "_generic") \
&& !isDefined?) {
// Mark the variable for partialing to top level closure
closure markForPartialing(ref vDecl, "v")
}
}
}
scopeDepth -= 1
Expand Down
34 changes: 26 additions & 8 deletions source/rock/middle/VariableAccess.ooc
Original file line number Diff line number Diff line change
Expand Up @@ -249,20 +249,38 @@ VariableAccess: class extends Expression {
if (bOp getLeft() == this && bOp isAssign()) mode = "r"
}

// TODO: Abstract this out and use it from FunctionCall.ooc
// Also, try to find some better way to do things, maybe from resolveAccess
// Find the first Scope that is the body of a function declaration in the top of the trail
scopeDepth := closureIndex - 1
while(scopeDepth > 0) {
maybeScope := trail get(scopeDepth, Node)
if(maybeScope instanceOf?(Scope)) {
scope := maybeScope as Scope
maybeClosure := trail get(scopeDepth - 1, Node)
// Only partial the variable in the top function if it has not be defined by it and it is not one of its arguments
if(maybeClosure instanceOf?(FunctionDecl) && maybeClosure as FunctionDecl isAnon \
&& !maybeClosure as FunctionDecl args contains?(|arg| arg name == name || arg name == name + "_generic") \
&& !maybeScope as Scope list contains?(|stmt| stmt instanceOf?(VariableDecl) && stmt as VariableDecl name == name)) {
// Mark the variable for partialing to top level closure
maybeClosure as FunctionDecl markForPartialing(ref as VariableDecl, mode)
if(!maybeClosure as FunctionDecl clsAccesses contains?(this)) {
maybeClosure as FunctionDecl clsAccesses add(this)
if(maybeClosure instanceOf?(FunctionDecl)) {
closure := maybeClosure as FunctionDecl
// Find out if our access is between the kid closure and the parent closure
isDefined? := false
intermediateScopeIndex := closureIndex - 1
while(intermediateScopeIndex > scopeDepth) {
interScope? := trail get(intermediateScopeIndex, Node)
if(interScope? instanceOf?(Scope)) {
interScope := interScope? as Scope
if(interScope list contains?(|stmt| stmt instanceOf?(VariableDecl) && stmt as VariableDecl name == name)) {
isDefined? = true
}
}
intermediateScopeIndex -= 1
}
// Only partial the variable in the top function if it has not be defined by it and it is not one of its arguments
if(closure isAnon && !closure args contains?(|arg| arg name == name || arg name == name + "_generic") \
&& !isDefined?) {
// Mark the variable for partialing to top level closure
closure markForPartialing(ref as VariableDecl, mode)
if(!closure clsAccesses contains?(this)) {
closure clsAccesses add(this)
}
}
}
}
Expand Down

0 comments on commit e7c0599

Please sign in to comment.