Consider this method: Object >> m 1 to: 10 do: [:index | self halt. index factorial]. Execute it: Object new m. A debugger appears. Note that the index is shown in the list of variables in the debugger. If you now select the expression (1 to: 10 do: [...]), and try to doIt inside the debugger, a contradiction will happen because index will be recognized as a block argument and also as a local variable (the halt happened inside the block and #to:do: is inlined, i.e., involves no message send.)
The compiler will try to issue a warning about the shadowing problem. However, since the DictionaryScope where index is bounded to 1 has no description, the method that creates the warning string generates an error. In consequence, you are not allowed to evaluate the block inside the debugger.
The fix is simple. Just add a description to the scope as shown below. You might want to look for local senders of #scopeForDictionary: and fix them in the same way. /Leandro
Debugger >> accept: textPane "Private - compile and evaluate the code in textPane. Replace the selected temporary variable with the result of the evaluation."
| aString locals bindings compiler compileResult | aString := textPane contents.
locals := self localVariableList. bindings := Dictionary new: locals size.
1 to: locals size do: [:idx | bindings at: (locals at: idx) put: (self localVariableAt: idx)].
compiler := CompilerInterface new. compiler errorHandler: (TextPaneErrorHandler new pane: textPane).
compiler nameScope: (compiler scopeForReservedSymbolsExcluding: #('super')) ,
(compiler scopeForClass: self doItInstance class) , ((compiler scopeForDictionary: bindings) description: 'local variable') , "<= FIX"
compiler scopeForGlobals. SourceManager current logEvaluate: aString
for: [compileResult := compiler evaluate: aString
withReceiver: self doItInstance. compileResult wasSuccessful ifFalse: [^textPane modified: true]].
instIndex = 1 "same as Inspector..." ifFalse: [self localVariableAt: instIndex put: compileResult value].
self changed: #instance:. textPane modified: false |
Cool. Do you have more of these kinds of debugger fixes? Thanks. -Carl From: Using Visual Smalltalk for Windows/Enterprise [mailto:[hidden email]] On Behalf Of Leandro Caniglia Consider this method: Object >> m 1 to: 10 do: [:index | self halt. index factorial]. Execute it: Object new m. A debugger appears. Note that the index is shown in the list of variables in the debugger. If you now select the expression (1 to: 10 do: [...]), and try to doIt inside the debugger, a contradiction will happen because index will be recognized as a block argument and also as a local variable (the halt happened inside the block and #to:do: is inlined, i.e., involves no message send.) The compiler will try to issue a warning about the shadowing problem. However, since the DictionaryScope where index is bounded to 1 has no description, the method that creates the warning string generates an error. In consequence, you are not allowed to evaluate the block inside the debugger. The fix is simple. Just add a description to the scope as shown below. You might want to look for local senders of #scopeForDictionary: and fix them in the same way. /Leandro Debugger >> accept: textPane "Private - compile and evaluate the code in textPane. Replace the selected temporary variable with the result of the evaluation." | aString locals bindings compiler compileResult | aString := textPane contents. locals := self localVariableList. bindings := Dictionary new: locals size. 1 to: locals size do: [:idx | bindings at: (locals at: idx) put: (self localVariableAt: idx)]. compiler := CompilerInterface new. compiler errorHandler: (TextPaneErrorHandler new pane: textPane). compiler nameScope: (compiler scopeForReservedSymbolsExcluding: #('super')) , (compiler scopeForClass: self doItInstance class) , ((compiler scopeForDictionary: bindings) description: 'local variable') , "<= FIX" compiler scopeForGlobals. SourceManager current logEvaluate: aString for: [compileResult := compiler evaluate: aString withReceiver: self doItInstance. compileResult wasSuccessful ifFalse: [^textPane modified: true]]. instIndex = 1 "same as Inspector..." ifFalse: [self localVariableAt: instIndex put: compileResult value]. self changed: #instance:. textPane modified: false *** this signature added by listserv *** *** Visit http://www.listserv.dfn.de/archives/vswe-l.html *** *** for archive browsing and VSWE-L membership management *** |
Not a fix, but useful when debugging/inspecting and a block defined in another method gets in the way.
BlockClosre >> source | cm source compiler result block node start stop |
cm := self method. cm isNil ifTrue: [^nil]. source := cm source.
source isNil ifTrue: [^nil]. compiler := Compiler forClass: cm classField
errorHandler: SilentErrorHandler new. result := compiler analyze: source withMethodPattern: cm hasMessagePattern.
block := result blockNumbered: self blockNumber. node := block instVarAt: 1.
start := node instVarAt: 3. stop := (node instVarAt: 4) - 1 min: source size.
^source copyFrom: start to: stop
On Tue, Apr 5, 2011 at 5:26 PM, Carl Gundel <[hidden email]> wrote:
|
Free forum by Nabble | Edit this page |