compiling methods programatically

VA Smalltalk is a "100% VisualAge compatible" IDE that includes the original VisualAge technology and the popular VA Assist and WidgetKit add-ons.

Moderators: Eric Clayberg, wembley, tc, Diane Engles, solveig

compiling methods programatically

Postby bill.buckley » Thu Sep 17, 2009 8:58 am

Hi,
We have an application which allows users to write "Overlays" to replace the code in a method with thier own version. The program reads in a text associated with the overlaid method and compiles this code to replace the existing method. However when the program is running after a method has overwitten and stopped by the debugger on this method it states that the source code is not available.

Questions is there a way to programatically create a method, and then have the text that was compiled, displayed in the debugger it the debugger stops on this method?

Thanks

Bill B.
bill.buckley
 
Posts: 3
Joined: Thu Sep 17, 2009 8:43 am

Re: compiling methods programatically

Postby TriSebastian » Fri Sep 18, 2009 7:59 am

Hi Bill,

Well, I think you might be able to replace your old implementation with the new compiled method here:

Behavior>>#addSelector: selector withMethod: method

But please take care you might have to implement some more functionality around it. e.g. errorhandling, keeping oldversion,....

But replacing the old coding by the new one in the methodDictionary might enable the Debugger to show the new implementation.

Cheers!
Sebastian
TriSebastian
 
Posts: 76
Joined: Sun Jul 20, 2008 9:40 pm
Location: Nanaimo, BC, Canada

Re: compiling methods programatically

Postby bill.buckley » Fri Sep 18, 2009 10:02 am

Thanks for the suggestion Subastion, however the call that you suggested is already part of the method that progamattically creates the new overlayed method. I did not write the orginal code but basically the present method calls EsCompiler with the name of the class and the new source code to create the compiled method an then uses addSelector:withMethod: to add the method to the class. However, as I've said it does not seem to add the text associated with the method so that if the debugger stops on the new method that it shows the new code and where it broke.

Thanks
Bill
bill.buckley
 
Posts: 3
Joined: Thu Sep 17, 2009 8:43 am

Re: compiling methods programatically

Postby TriSebastian » Fri Sep 18, 2009 11:31 am

Hi Bill,

I guess you are landing here during an error.

ClassDescription classSuppliedSourceFor:

Could you provide a snippet?

Sebastian
TriSebastian
 
Posts: 76
Joined: Sun Jul 20, 2008 9:40 pm
Location: Nanaimo, BC, Canada

Re: compiling methods programatically

Postby marten » Fri Sep 18, 2009 1:30 pm

Reading the methods of CompiledMethod I would assume, that the source code is only held within the ENVY library and not within the image. If you have an end-user application they will normally not have that ENVY library - and also not having methods to handle the source code management within that ENVY library. Otherwise ClassDescription>>install: aCM
asPrivate: makePrivate
withSource: source
ifNewAddTo: newApplication
categorizeIn: newCategories

could help you here ... one the other hand it seems, that special classes would be able to hold their own source code .... look at ClassDescription>>classHasSourceFor: and ClassDescription>>classSuppliedSourceFor:

bill.buckley wrote:Hi,
We have an application which allows users to write "Overlays" to replace the code in a method with thier own version. The program reads in a text associated with the overlaid method and compiles this code to replace the existing method. However when the program is running after a method has overwitten and stopped by the debugger on this method it states that the source code is not available.

Questions is there a way to programatically create a method, and then have the text that was compiled, displayed in the debugger it the debugger stops on this method?

Thanks

Bill B.
Marten Feldtmann, Principal Smalltalk User, Private
SkypeMe callto://marten.feldtmann
marten
[|]
 
Posts: 641
Joined: Sat Oct 14, 2006 7:10 am
Location: Hamburg - Germany

Re: compiling methods programatically

Postby bill.buckley » Mon Sep 21, 2009 5:18 am

Here is a piece of the code from our Overlay Class as requested
Note: affectedClass is the class object that the overlay will be added/modified to
sourceCode is the text that describes this method.

compiledMethod :=
EsCompiler
compile: sourceCode
inClass: affectedClass
ifFail {:error | result := error.
^false].

affectedClass addSelector: (compiledMethod selector) withMethod: compiledMethod.

result := 'Applied'

^true


As stated the reason for wanting the debugger to show the source code is that if the program has an error (which may or may not have come from the added overlay) We may end up stepping through the overlay to fix it. Without the source code it makes this process a little difficult. What is open up the class in the open image (the selector will be listed under the class) select the selector (which then shows there is no source code available and paste a copy of the source code in the open image and save (which essentially overwrites the overlay with code from the overlay source which is then available to look at in the debugger). i'm looking for a little more effecient way of making the source available during debugging

Bill
bill.buckley
 
Posts: 3
Joined: Thu Sep 17, 2009 8:43 am

Re: compiling methods programatically

Postby marten » Mon Sep 21, 2009 9:41 am

Just some code to show how one can do it. Perhaps its not suitable under your circumstances ...

An example application, which shows a possible way ... import the application and execute
"OverlayClass createTempMethod" and look into the debugger ....

Code: Select all
Application create: #MSKTest with:
    (#( Kernel)
        collect: [:each | Smalltalk at: each ifAbsent: [
            Application errorPrerequisite: #MSKTest missing: each]])!

MSKTest becomeDefault!
Object subclass: #OverlayClass
    classInstanceVariableNames: 'sourcesForCompiledMethods '
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''!

MSKTest becomeDefault!
Application subclass: #MSKTest
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''!


MSKTest becomeDefault!

!OverlayClass class publicMethods !

addSource: sourceString for: aCM


   sourcesForCompiledMethods isNil ifTrue:[ sourcesForCompiledMethods := Dictionary new ].
   sourcesForCompiledMethods at: aCM selector put: sourceString.
!

applicationFor: selector

   " ... just a guess how to do it ...."
   ^OverlayClass controller!

classHasSourceFor: aCM

   | source |
   
   sourcesForCompiledMethods isNil ifTrue:[ ^false ].
   (source := sourcesForCompiledMethods at: aCM selector ifAbsent: [ nil ]) isNil ifTrue:[ ^false ].
   ^true!

classSuppliedSourceFor:  aCM

   | source |
   
   sourcesForCompiledMethods isNil ifTrue:[ ^nil ].
   (source := sourcesForCompiledMethods at: aCM selector ifAbsent: [ nil ]) isNil ifTrue:[ ^nil ].
   ^source!

createTempMethod
   "OverlayClass createTempMethod"
   
   | compiledMethod sourceCode affectedClass |
   
   sourceCode :=  'doTempMethod     ^1 / 0'.
   affectedClass := OverlayClass.
   
   compiledMethod :=
      EsCompiler
         compile: sourceCode
         inClass: affectedClass
         ifFail: [:error |  ^false].
      
   affectedClass addSelector: (compiledMethod selector) withMethod: compiledMethod.

   affectedClass addSource: sourceCode for: compiledMethod.
   
   "now execute an erroronous method"
   affectedClass new doTempMethod! !

OverlayClass initializeAfterLoad!
MSKTest initializeAfterLoad!

MSKTest loaded!
Marten Feldtmann, Principal Smalltalk User, Private
SkypeMe callto://marten.feldtmann
marten
[|]
 
Posts: 641
Joined: Sat Oct 14, 2006 7:10 am
Location: Hamburg - Germany


Return to VA Smalltalk 7.0, 7.5 & 8.0

Who is online

Users browsing this forum: Yahoo [Bot] and 1 guest