diff --git a/newspeak/ActivationMirrorTesting.ns b/newspeak/ActivationMirrorTesting.ns index a372633..80219ed 100644 --- a/newspeak/ActivationMirrorTesting.ns +++ b/newspeak/ActivationMirrorTesting.ns @@ -250,6 +250,26 @@ public testActivationEvaluateEnclosingLocals = ( assert: eval result reflectee equals: 4. assert: x equals: 4. ) +public testActivationEvaluateEnclosingLocals2 = ( + | x closure thread activation eval | + x:: 0. (* Captured, but only in an enclosing closure *) + closure:: [x:: 3. [nil]] value. + thread:: ActivationMirror invokeSuspended: closure. + + activation:: thread suspendedActivation. + assert: activation receiver equals: (ObjectMirror reflecting: self). + assert: activation closure equals: (ObjectMirror reflecting: closure). + assert: activation method name equals: #testActivationEvaluateEnclosingLocals2. + + eval:: activation evaluate: 'x'. + assert: eval isFulfilled. + assert: eval result reflectee equals: 3. + + eval:: activation evaluate: 'x: 4'. + assert: eval isFulfilled. + assert: eval result reflectee equals: 4. + assert: x equals: 4. +) public testActivationEvaluateWithScope = ( | closure thread activation scope eval | closure:: [add: 3 to: 4]. diff --git a/newspeak/KernelForPrimordialSoup.ns b/newspeak/KernelForPrimordialSoup.ns index fecabd0..b4b826a 100644 --- a/newspeak/KernelForPrimordialSoup.ns +++ b/newspeak/KernelForPrimordialSoup.ns @@ -44,6 +44,11 @@ public closure: value = ( (* :pragma: primitive: 173 *) panic. ) +public enclosingActivation ^ = ( + | c = closure. | + nil = c ifTrue: [^nil]. + ^definingActivationOf: c +) (* Return the next unwind marked above the receiver, returning nil if there is none. Search proceeds up to but not including aContext. *) public findNextUnwindContextUpTo: activation = ( | ctx | @@ -91,12 +96,6 @@ public method: value = ( private nonBooleanReceiver: nonBoolean = ( ^(NonBooleanReceiver receiver: nonBoolean) signal ) -(* Squeak compatibility for DebugMapper. *) -public outerContext ^ = ( - | c = closure. | - nil = c ifTrue: [^nil]. - ^definingActivationOf: c -) public pop = ( | depth = self size. diff --git a/newspeak/Mirrors.ns b/newspeak/Mirrors.ns index 0717bb8..068e2c5 100644 --- a/newspeak/Mirrors.ns +++ b/newspeak/Mirrors.ns @@ -118,7 +118,7 @@ private computeDebugMapper = ( ^computeDebugInfo mapperForContext: reflectee ) public enclosingActivation ^ = ( - | rawEnclosing = reflectee outerContext. | + | rawEnclosing = reflectee enclosingActivation. | nil = rawEnclosing ifTrue: [^nil]. ^ActivationMirror reflecting: rawEnclosing thread: thread ) diff --git a/newspeak/Newspeak2PrimordialSoupCompilation.ns b/newspeak/Newspeak2PrimordialSoupCompilation.ns index 9d4c3d8..a0e59b9 100644 --- a/newspeak/Newspeak2PrimordialSoupCompilation.ns +++ b/newspeak/Newspeak2PrimordialSoupCompilation.ns @@ -593,7 +593,7 @@ public mapperForContext: ctxt = ( ) : ( ) class DebugMapper forContext: ctxt usingDebugInfo: dbgInfo = (| - context = ctxt. + context = ctxt. debugInfo = dbgInfo. myDepth = self depthOfContext: ctxt. |) ( @@ -613,7 +613,7 @@ astForContextAtDepth: targetDepth ^ = ( returnContext:: (UnresolvedSendAST new receiver: returnContext; message: (MessageAST new - selector: #outerContext; + selector: #enclosingActivation; arguments: {}))]. ^returnContext @@ -621,7 +621,7 @@ astForContextAtDepth: targetDepth ^ = ( bci = ( ^context bci ) -contextAtDepth: targetDepth ^ = ( +contextAtDepth: targetDepth ^ = ( | returnContext | @@ -629,13 +629,13 @@ contextAtDepth: targetDepth ^ = ( returnContext: context. (myDepth - targetDepth) - timesRepeat: [returnContext: returnContext outerContext]. + timesRepeat: [returnContext: returnContext enclosingActivation]. ^returnContext ) -depthOfContext: ctxt ^ = ( +depthOfContext: ctxt ^ = ( ^ctxt closure isNil ifTrue: [0 (* method *)] - ifFalse: [1 + (depthOfContext: ctxt outerContext)] + ifFalse: [1 + (depthOfContext: ctxt enclosingActivation)] ) public getValueOf: varName ^ = ( | info ctxt vector | @@ -2079,7 +2079,7 @@ public compileClassSource: src within: enclosingIR ^intermediate ) -public compileExpressionSource: src debugMapper: debugMapper withScope: withScope inMixin: enclosing ^ = ( +public compileExpressionSource: src debugMapper: debugMapper withScope: withScope inMixin: enclosing ^ = ( (* Compile a DoIt method. If aContext is not nil, compile a DoItIn:ctxt method where accesses to names in scope of the context are rewritten to access through the context. Cog closures complicate this rewriting compared to BlockContexts, as access might be rather indirect. Also, in cases where a temp is only a copied value and not in a remote indirection vector, it would be impractical to handle writes such that they actually track down all places where the temp lives and update them. In these cases, we should merely find the most local copy, which I believe is what closure compiled Squeak does. *) | body diff --git a/newspeak/NewspeakCompilation.ns b/newspeak/NewspeakCompilation.ns index 766bf76..13072d1 100644 --- a/newspeak/NewspeakCompilation.ns +++ b/newspeak/NewspeakCompilation.ns @@ -989,7 +989,7 @@ public compileClassHeader: source within: enclosingIR within: enclosingIR ^ = ( subclassResponsibility ) -public compileExpressionSource: src debugMapper: debugMapper withScope: withScope inMixin: enclosing ^ = ( +public compileExpressionSource: src debugMapper: debugMapper withScope: withScope inMixin: enclosing ^ = ( subclassResponsibility ) public compileMethodSource: source within: enclosing ^ = (