Interception messages in Squeak

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

Interception messages in Squeak

Yann-Gaël Guéhéneuc

        Dear all,

I am trying to understand better reflection in Smalltalk. I am using
the latest version of Squeak (v4.3). I want to intercept every
message sent to instances of one of my classes. I assumed that I
could override the method `ProtoObject>>withArgs:executeMethod` but
Stéphane (Ducasse) explained me that for performance reason, this
method is not used (this is my own summary of his answer). Which
method should I override / how could intercept sent messages?

Here is the code of my attempt:

     Object subclass: #C
      instanceVariableNames: 'i'
      classVariableNames: ''
      poolDictionaries: ''
      category: 'CSE3009'.

     C class compile: 'newWithi: anInt
      ^(self new) i: anInt ; yourself.'.

     C compile: 'withArgs: someArgs executeMethod: aMethod
      Transcript show: ''Caught: ''.
      ^ super withArgs: someArgs executeMethod aMethod.'.

     C compile: 'foo: aText
      Transcript show: aText.
      Transcript show: i.
      Transcript cr.'.

     C compile: 'i: anInt
      i := anInt.'.

     o := C newWithi: 42.
     o foo: 'This is foo: '.

Executing this entire piece of code yields:

     This is foo: 42

When I would like to have:

     Caught: This is foo: 42

        I was told about wrapper objects and MethodWrapper (see
http://stackoverflow.com/questions/15975340/interception-messages-in-squeak)
but in my quest to understand reflection, I would like to know if
there would be something more "reflective", typically overriding a
message :-)

        Thank you very much in advance!
        Yann

--
Yann-Gaël Guéhéneuc
Ph.D. et ing. / Ph.D. and eng.
Professeur titulaire / Full professor
Chaire de recherche du Canada sur les Patrons (de) logiciels /
   Canada Research Chair on Software Patterns and Patterns of Software
DGIGL, École Polytechnique        1-514-340-4711 #7116 (Tél. / Phone)
C.P. 6079, succ. Centre-Ville     1-514-340-5139       (Téléc. / Fax)
Montréal, QC, H3C 3A7, Canada     www.ptidej.net

Reply | Threaded
Open this post in threaded view
|

Re: Interception messages in Squeak

David T. Lewis
On Mon, Apr 15, 2013 at 01:17:40PM +0900, Yann-Ga?l Gu?h?neuc wrote:

>
> Dear all,
>
> I am trying to understand better reflection in Smalltalk. I am using
> the latest version of Squeak (v4.3). I want to intercept every
> message sent to instances of one of my classes. I assumed that I
> could override the method `ProtoObject>>withArgs:executeMethod` but
> St?phane (Ducasse) explained me that for performance reason, this
> method is not used (this is my own summary of his answer). Which
> method should I override / how could intercept sent messages?
>
> Here is the code of my attempt:
>
>     Object subclass: #C
>     instanceVariableNames: 'i'
>     classVariableNames: ''
>     poolDictionaries: ''
>     category: 'CSE3009'.
>
>     C class compile: 'newWithi: anInt
>     ^(self new) i: anInt ; yourself.'.
>
>     C compile: 'withArgs: someArgs executeMethod: aMethod
>     Transcript show: ''Caught: ''.
>     ^ super withArgs: someArgs executeMethod aMethod.'.
>
>     C compile: 'foo: aText
>     Transcript show: aText.
>     Transcript show: i.
>     Transcript cr.'.
>
>     C compile: 'i: anInt
>     i := anInt.'.
>
>     o := C newWithi: 42.
>     o foo: 'This is foo: '.
>
> Executing this entire piece of code yields:
>
>     This is foo: 42
>
> When I would like to have:
>
>     Caught: This is foo: 42
>
> I was told about wrapper objects and MethodWrapper (see
> http://stackoverflow.com/questions/15975340/interception-messages-in-squeak)
> but in my quest to understand reflection, I would like to know if there
> would be something more "reflective", typically overriding a message :-)
>
> Thank you very much in advance!
> Yann

Try this after compiling your code:

  "Ask the class for the compiled method that you want to execute"
  theCompiledMethod := C compiledMethodAt: #foo: .
 
  "Make an array of size one containing the argument, a string"
  theArguments := { 'This is foo: ' } .
 
  "Execute the compiled method as if it was a message send to the object"
  o withArgs: theArguments executeMethod: theCompiledMethod.
 
  ==> Caught: This is foo: 42

Dave


Reply | Threaded
Open this post in threaded view
|

Re: Interception messages in Squeak

Yann-Gaël Guéhéneuc

        Hello Dave,

        Thank you for your answer! But the solution that you suggested does
not show the use of reflection as I would like it to:

        o withArgs: theArguments executeMethod: theCompiledMethod.

I must make an explicit use of "withArgs:executeMethod" while I would
like to make this use "transparent" to illustrate the "overriding" of
the method invocation, any other suggestion?

        My purpose is to illustrate the use of reflection and differences
between C++, Java, and Smalltalk with that respect.  I kind of
remember that in some version/flavor of Smalltalk, you could
"override" the VM mechanism to invoke method, typically by overriding
some "withArgs:executeMethod:" when---and only when---using
reflection so that performance would not be horrible but that you
could still change the behaviour of invocations (at the risk of
breaking the whole image if something silly was done, such as not
"forwarding" the invocation to the VM after interception). Do I
remember wrong?
       
        Yann

On 15/04/2013 13:59, David T. Lewis wrote:

> On Mon, Apr 15, 2013 at 01:17:40PM +0900, Yann-Ga?l Gu?h?neuc wrote:
>>
>> Dear all,
>>
>> I am trying to understand better reflection in Smalltalk. I am using
>> the latest version of Squeak (v4.3). I want to intercept every
>> message sent to instances of one of my classes. I assumed that I
>> could override the method `ProtoObject>>withArgs:executeMethod` but
>> St?phane (Ducasse) explained me that for performance reason, this
>> method is not used (this is my own summary of his answer). Which
>> method should I override / how could intercept sent messages?
>>
>> Here is the code of my attempt:
>>
>>      Object subclass: #C
>>       instanceVariableNames: 'i'
>>       classVariableNames: ''
>>       poolDictionaries: ''
>>       category: 'CSE3009'.
>>
>>      C class compile: 'newWithi: anInt
>>       ^(self new) i: anInt ; yourself.'.
>>
>>      C compile: 'withArgs: someArgs executeMethod: aMethod
>>       Transcript show: ''Caught: ''.
>>       ^ super withArgs: someArgs executeMethod aMethod.'.
>>
>>      C compile: 'foo: aText
>>       Transcript show: aText.
>>       Transcript show: i.
>>       Transcript cr.'.
>>
>>      C compile: 'i: anInt
>>       i := anInt.'.
>>
>>      o := C newWithi: 42.
>>      o foo: 'This is foo: '.
>>
>> Executing this entire piece of code yields:
>>
>>      This is foo: 42
>>
>> When I would like to have:
>>
>>      Caught: This is foo: 42
>>
>> I was told about wrapper objects and MethodWrapper (see
>> http://stackoverflow.com/questions/15975340/interception-messages-in-squeak)
>> but in my quest to understand reflection, I would like to know if there
>> would be something more "reflective", typically overriding a message :-)
>>
>> Thank you very much in advance!
>> Yann
>
> Try this after compiling your code:
>
>    "Ask the class for the compiled method that you want to execute"
>    theCompiledMethod := C compiledMethodAt: #foo: .
>
>    "Make an array of size one containing the argument, a string"
>    theArguments := { 'This is foo: ' } .
>
>    "Execute the compiled method as if it was a message send to the object"
>    o withArgs: theArguments executeMethod: theCompiledMethod.
>
>    ==> Caught: This is foo: 42
>
> Dave
>
>

--
Yann-Gaël Guéhéneuc
Ph.D. et ing. / Ph.D. and eng.
Professeur titulaire / Full professor
Chaire de recherche du Canada sur les Patrons (de) logiciels /
   Canada Research Chair on Software Patterns and Patterns of Software
DGIGL, École Polytechnique        1-514-340-4711 #7116 (Tél. / Phone)
C.P. 6079, succ. Centre-Ville     1-514-340-5139       (Téléc. / Fax)
Montréal, QC, H3C 3A7, Canada     www.ptidej.net

Reply | Threaded
Open this post in threaded view
|

Re: Interception messages in Squeak

Stéphane Rollandin
In reply to this post by Yann-Gaël Guéhéneuc
> I am trying to understand better reflection in Smalltalk. I am using
> the latest version of Squeak (v4.3).

Just a side note: the latest version is 4.4

Stef


Reply | Threaded
Open this post in threaded view
|

Re: Interception messages in Squeak

Yann-Gaël Guéhéneuc
In reply to this post by Yann-Gaël Guéhéneuc
PS. Stéphane also mentioned Reflectivity and Bifröst, I will look at
them.

On 15/04/2013 17:41, Yann-Gaël Guéhéneuc wrote:

>
> Hello Dave,
>
> Thank you for your answer! But the solution that you suggested does
> not show the use of reflection as I would like it to:
>
> o withArgs: theArguments executeMethod: theCompiledMethod.
>
> I must make an explicit use of "withArgs:executeMethod" while I would
> like to make this use "transparent" to illustrate the "overriding" of
> the method invocation, any other suggestion?
>
> My purpose is to illustrate the use of reflection and differences
> between C++, Java, and Smalltalk with that respect.  I kind of
> remember that in some version/flavor of Smalltalk, you could
> "override" the VM mechanism to invoke method, typically by overriding
> some "withArgs:executeMethod:" when---and only when---using
> reflection so that performance would not be horrible but that you
> could still change the behaviour of invocations (at the risk of
> breaking the whole image if something silly was done, such as not
> "forwarding" the invocation to the VM after interception). Do I
> remember wrong?
>
> Yann
>
> On 15/04/2013 13:59, David T. Lewis wrote:
>> On Mon, Apr 15, 2013 at 01:17:40PM +0900, Yann-Ga?l Gu?h?neuc wrote:
>>>
>>> Dear all,
>>>
>>> I am trying to understand better reflection in Smalltalk. I am using
>>> the latest version of Squeak (v4.3). I want to intercept every
>>> message sent to instances of one of my classes. I assumed that I
>>> could override the method `ProtoObject>>withArgs:executeMethod` but
>>> St?phane (Ducasse) explained me that for performance reason, this
>>> method is not used (this is my own summary of his answer). Which
>>> method should I override / how could intercept sent messages?
>>>
>>> Here is the code of my attempt:
>>>
>>>       Object subclass: #C
>>>       instanceVariableNames: 'i'
>>>       classVariableNames: ''
>>>       poolDictionaries: ''
>>>       category: 'CSE3009'.
>>>
>>>       C class compile: 'newWithi: anInt
>>>       ^(self new) i: anInt ; yourself.'.
>>>
>>>       C compile: 'withArgs: someArgs executeMethod: aMethod
>>>       Transcript show: ''Caught: ''.
>>>       ^ super withArgs: someArgs executeMethod aMethod.'.
>>>
>>>       C compile: 'foo: aText
>>>       Transcript show: aText.
>>>       Transcript show: i.
>>>       Transcript cr.'.
>>>
>>>       C compile: 'i: anInt
>>>       i := anInt.'.
>>>
>>>       o := C newWithi: 42.
>>>       o foo: 'This is foo: '.
>>>
>>> Executing this entire piece of code yields:
>>>
>>>       This is foo: 42
>>>
>>> When I would like to have:
>>>
>>>       Caught: This is foo: 42
>>>
>>> I was told about wrapper objects and MethodWrapper (see
>>> http://stackoverflow.com/questions/15975340/interception-messages-in-squeak)
>>> but in my quest to understand reflection, I would like to know if there
>>> would be something more "reflective", typically overriding a message :-)
>>>
>>> Thank you very much in advance!
>>> Yann
>>
>> Try this after compiling your code:
>>
>>     "Ask the class for the compiled method that you want to execute"
>>     theCompiledMethod := C compiledMethodAt: #foo: .
>>
>>     "Make an array of size one containing the argument, a string"
>>     theArguments := { 'This is foo: ' } .
>>
>>     "Execute the compiled method as if it was a message send to the object"
>>     o withArgs: theArguments executeMethod: theCompiledMethod.
>>
>>     ==> Caught: This is foo: 42
>>
>> Dave
>>
>>
>

--
Yann-Gaël Guéhéneuc
Ph.D. et ing. / Ph.D. and eng.
Professeur agrégé / Associate professor
DIRO, Université de Montréal    1-514-343-6111 47497 (Téléphone / Phone)
C.P. 6128, succ. Centre-Ville   1-514-343-5834       (Télécopie / Fax)
Montréal, QC, H3C 3J7, Canada   www.ptidej.net

--
Yann-Gaël Guéhéneuc
Ph.D. et ing. / Ph.D. and eng.
Professeur titulaire / Full professor
Chaire de recherche du Canada sur les Patrons (de) logiciels /
   Canada Research Chair on Software Patterns and Patterns of Software
DGIGL, École Polytechnique        1-514-340-4711 #7116 (Tél. / Phone)
C.P. 6079, succ. Centre-Ville     1-514-340-5139       (Téléc. / Fax)
Montréal, QC, H3C 3A7, Canada     www.ptidej.net

Reply | Threaded
Open this post in threaded view
|

Re: Interception messages in Squeak

Chris Muller-3
In reply to this post by Yann-Gaël Guéhéneuc
I take it you're looking for something lower-level than overriding
doesNotUnderstand:.

I don't know if this meets your qualifications, but one thing Magma
does for its write-barrier is dynamically compile an anonymous
subclass of the classes wanting to be overridden.  Then use
#primitiveChangeClassTo: to change the class of existing instances to
the anonymous class.


On Sun, Apr 14, 2013 at 11:17 PM, Yann-Gaël Guéhéneuc
<[hidden email]> wrote:

>
>         Dear all,
>
> I am trying to understand better reflection in Smalltalk. I am using the
> latest version of Squeak (v4.3). I want to intercept every message sent to
> instances of one of my classes. I assumed that I could override the method
> `ProtoObject>>withArgs:executeMethod` but Stéphane (Ducasse) explained me
> that for performance reason, this method is not used (this is my own summary
> of his answer). Which method should I override / how could intercept sent
> messages?
>
> Here is the code of my attempt:
>
>     Object subclass: #C
>         instanceVariableNames: 'i'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'CSE3009'.
>
>     C class compile: 'newWithi: anInt
>         ^(self new) i: anInt ; yourself.'.
>
>     C compile: 'withArgs: someArgs executeMethod: aMethod
>         Transcript show: ''Caught: ''.
>         ^ super withArgs: someArgs executeMethod aMethod.'.
>
>     C compile: 'foo: aText
>         Transcript show: aText.
>         Transcript show: i.
>         Transcript cr.'.
>
>     C compile: 'i: anInt
>         i := anInt.'.
>
>     o := C newWithi: 42.
>     o foo: 'This is foo: '.
>
> Executing this entire piece of code yields:
>
>     This is foo: 42
>
> When I would like to have:
>
>     Caught: This is foo: 42
>
>         I was told about wrapper objects and MethodWrapper (see
> http://stackoverflow.com/questions/15975340/interception-messages-in-squeak)
> but in my quest to understand reflection, I would like to know if there
> would be something more "reflective", typically overriding a message :-)
>
>         Thank you very much in advance!
>         Yann
>
> --
> Yann-Gaël Guéhéneuc
> Ph.D. et ing. / Ph.D. and eng.
> Professeur titulaire / Full professor
> Chaire de recherche du Canada sur les Patrons (de) logiciels /
>   Canada Research Chair on Software Patterns and Patterns of Software
> DGIGL, École Polytechnique        1-514-340-4711 #7116 (Tél. / Phone)
> C.P. 6079, succ. Centre-Ville     1-514-340-5139       (Téléc. / Fax)
> Montréal, QC, H3C 3A7, Canada     www.ptidej.net
>

Reply | Threaded
Open this post in threaded view
|

Re: Interception messages in Squeak

Stefan Marr-3
In reply to this post by Yann-Gaël Guéhéneuc
Hi Yann:

On 15 Apr 2013, at 10:41, Yann-Gaël Guéhéneuc <[hidden email]> wrote:

> I kind of remember that in some version/flavor of Smalltalk, you could "override" the VM mechanism to invoke method, typically by overriding some "withArgs:executeMethod:" when---and only when---using reflection so that performance would not be horrible but that you could still change the behaviour of invocations (at the risk of breaking the whole image if something silly was done, such as not "forwarding" the invocation to the VM after interception). Do I remember wrong?

Perhaps you remember reading: 'Efficient Method Lookup Customization for Smalltalk'? http://link.springer.com/chapter/10.1007/978-3-642-30561-0_10

There is also PHANtom (http://pleiad.cl/research/software/phantom)
and AspectS that might be more high-level.

Best regards
Stefan

--
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525


Reply | Threaded
Open this post in threaded view
|

Re: Interception messages in Squeak

Yann-Gaël Guéhéneuc

        Hi all!

        Thank Chris and Stefan, I will look at Magma, PHANtom and, indeed,
the paper 'Efficient Method Lookup Customization for Smalltalk' seems
related to what I remember from my school days :-) I will read it,
thanks again!

        Cheers!
        Yann


On 16/04/2013 06:53, Stefan Marr wrote:

> Hi Yann:
>
> On 15 Apr 2013, at 10:41, Yann-Gaël Guéhéneuc <[hidden email]> wrote:
>
>> I kind of remember that in some version/flavor of Smalltalk, you could "override" the VM mechanism to invoke method, typically by overriding some "withArgs:executeMethod:" when---and only when---using reflection so that performance would not be horrible but that you could still change the behaviour of invocations (at the risk of breaking the whole image if something silly was done, such as not "forwarding" the invocation to the VM after interception). Do I remember wrong?
>
> Perhaps you remember reading: 'Efficient Method Lookup Customization for Smalltalk'? http://link.springer.com/chapter/10.1007/978-3-642-30561-0_10
>
> There is also PHANtom (http://pleiad.cl/research/software/phantom)
> and AspectS that might be more high-level.
>
> Best regards
> Stefan
>

--
Yann-Gaël Guéhéneuc
Ph.D. et ing. / Ph.D. and eng.
Professeur titulaire / Full professor
Chaire de recherche du Canada sur les Patrons (de) logiciels /
   Canada Research Chair on Software Patterns and Patterns of Software
DGIGL, École Polytechnique        1-514-340-4711 #7116 (Tél. / Phone)
C.P. 6079, succ. Centre-Ville     1-514-340-5139       (Téléc. / Fax)
Montréal, QC, H3C 3A7, Canada     www.ptidej.net