2016-10-23 12:15 GMT+02:00 Peter Uhnak <[email protected]>:

> I was looking at this and ran into some very odd behavior:
>
> imagine we have some method:
>
> ```
> Object subclass: #MyClass.
> MyClass compile: 'method: arg
>     Transcript crShow: ''executed '', arg asString'.
> ```
>
> and a simple metalink
>
> ```
> link := MetaLink new
> metaObject: Halt;
> selector: #now;
> control: #instead.
>
> (MyClass >> #method:) ast link: link.
> ```
>
> Now I can do the following to execute the code:
>
> ```
> c := MyClass new.
> (MyClass>>#method:) valueWithReceiver: c arguments: #(1).
> (MyClass>>#method:) reflectiveMethod valueWithReceiver: c arguments: #(1).
> (MyClass>>#method:) compiledMethod valueWithReceiver: c arguments: #(1).
> MyClass rFwithArgs: #(1) executeMethod: (MyClass>>#method:) compiledMethod.
> ```
>
>
There is only one way to "compile and install" the modified method and
unless this is done, all the above messages are
received on the ReflectiveMethod and delegated to the CompiledMethod (see
ReflectiveMethod>>##doesNotUnderstand:



> All of the statements above will call the method WITHOUT triggering the
> metalink, which is odd.
>
> Now what's even stranger, if I instead do this
>
> ```
> c := MyClass new.
> c method: 1.
> (MyClass>>#method:) valueWithReceiver: c arguments: #(1).
> (MyClass>>#method:) reflectiveMethod valueWithReceiver: c arguments: #(1).
> (MyClass>>#method:) compiledMethod valueWithReceiver: c arguments: #(1).
> MyClass rFwithArgs: #(1) executeMethod: (MyClass>>#method:) compiledMethod.
> ```
>
>
by the first call "c method:1" this is the place where the ReflectiveMethod
actually compiles and installs a modified compiled method.

the magic happens with "objects as methods" and the method run:with:in:
(if the vm looks up a message send, and the object in the method dictionary
is *not* a CompiledMethod, it calls the object with the method
run: aSelector with: anArray in: aReceiver

This is implemented in ReflectiveMethod and will actually compile and
install the new CompiledMethod.


> Then ALL the statements (starting with `c method: 1`) will be suddenly
> halting (triggering the metalinks).
>

Yes because the compiled method to be called is now the new one.

(MyClass>>#method:) class -> " this is now a compiled method again, but the
new, modified one".



>
>
> So my questions are:
>
> 1) why in the first case the following two methods didn't trigger the
> metalink?
>
> (MyClass>>#method:) valueWithReceiver: c arguments: #(1).
> (MyClass>>#method:) reflectiveMethod valueWithReceiver: c arguments: #(1).
>
> 2) why in the second case these two methods did trigger the metalink?
>
> (MyClass>>#method:) compiledMethod valueWithReceiver: c arguments: #(1).
> MyClass rFwithArgs: #(1) executeMethod: (MyClass>>#method:) compiledMethod.
>
> #rFwithArgs:executeMethod: even has comment "This method is used by
> reflectivity internally. All meta-links are ignored".
>
> 3) why the class of (MyClass>>#method:) changed after calling `method:`?
>
> ```
> (MyClass >> #method:) ast link: link.
>
> c := MyClass new.
> (MyClass>>#method:) class. "ReflectiveMethod"
> (MyClass>>#method:) valueWithReceiver: c arguments: #(1).
> (MyClass>>#method:) class. "ReflectiveMethod"
> c method: 1.
> (MyClass>>#method:) class. "CompiledMethod"
> ```
>
> 4) (unrelated to the above) I tried calling `link disable` from within the
> #metaObject, but it was ignored, but maybe I don't understand its purpose.
>


You can enable / disable the condition without actually changing /
reinstalling the link

link condition:[:args | args first isNumber] arguments:#(arguments).

c method:1.   "<- will trigger halt"
c method:'s'.  "<- wont trigger halt"

link disable. "<- disable the condition, like condition never holds"

c method:1.   "<- wont trigger halt"
c method:'s'.  "<- wont trigger halt"



>
>
> Thanks,
> Peter
>
> On Sun, Oct 23, 2016 at 09:21:59AM +0200, Yuriy Tymchuk wrote:
> > I’ve also described the question with examples on SO:
> https://stackoverflow.com/questions/40200546/conditionally-skip-a-method-
> with-matalinks
> >
> > > On 22 Oct 2016, at 23:13, Yuriy Tymchuk <[email protected]> wrote:
> > >
> > > Hi.
> > >
> > > Imagine I have method a: and I want to skip the execution (return self
> or nil or whatever) when a: is evaluated with parameter 0. I have tried to
> add a meta link which will run instead of the method with a condition, but
> the condition did not work… I have tried to implement the metallic method
> to do nothing if the arg is 0 otherwise to perform the method, but I end up
> with an infinite loop…
> > >
> > > Did anybody do something like that already? Any suggestions?
> > >
> > > Uko
> >
>
>

Reply via email to