Mini-fix

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Mini-fix

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 ***
Reply | Threaded
Open this post in threaded view
|

Re: Mini-fix

Carl Gundel-3

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
Sent: Tuesday, April 05, 2011 3:17 PM
To: [hidden email]
Subject: Mini-fix

 

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 ***

*** this signature added by listserv *** *** Visit http://www.listserv.dfn.de/archives/vswe-l.html *** *** for archive browsing and VSWE-L membership management ***
Reply | Threaded
Open this post in threaded view
|

Re: Mini-fix

Leandro Caniglia
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:

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
Sent: Tuesday, April 05, 2011 3:17 PM
To: [hidden email]
Subject: Mini-fix

 

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 ***

*** this signature added by listserv *** *** Visit http://www.listserv.dfn.de/archives/vswe-l.html *** *** for archive browsing and VSWE-L membership management ***

*** this signature added by listserv *** *** Visit http://www.listserv.dfn.de/archives/vswe-l.html *** *** for archive browsing and VSWE-L membership management ***