Renne
Renne

Reputation:

How do I change a method's name dynamically in squeak?

I have a class and I want to change the name of a specific method in run time. I guess there's a method in the 'Behavior' class that does it. But I just can't find it. any help? [in squeak]

Upvotes: 2

Views: 1169

Answers (5)

Frank Shearar
Frank Shearar

Reputation: 17142

You can't change a method's name, really, because it doesn't have one.

An object's method dictionary maps Symbols to CompiledMethods. "Change the name of a method" means "move the CompiledMethod value from this key to that key".

Upvotes: 0

akuhn
akuhn

Reputation: 27813

You best use a refactoring

r := RenameMethodRefactoring 
    renameMethod: #foo:foo: 
    in: Foo
    to: #bar:bar:
    permutation: (1 to: #foo:foo: numArgs). 
r execute.

Upvotes: 1

Alex Jasmin
Alex Jasmin

Reputation: 39516

Avoid voodoo magic in real code when possible.

That being said you can do some very interesting things by manipulating methods dynamically.

For instance the code bricks in Etoys are translated into Smalltalk methods. Other DSL implementations can also benefit from similar metaprogramming tricks.

After experimenting a bit I came up with the following code for renaming unary methods:

renameMethod: oldMethod inClass: class to: newMethod
| oldSelector newSelector source parser |

oldSelector := oldMethod asSymbol.
newSelector := newMethod asSymbol.
oldSelector = newSelector ifTrue: [^self].

"Get method category"
category := (LocatedMethod location: class selector: oldSelector) category.

"Get method source code"
source := class sourceCodeAt: oldSelector.

"Replace selector in method source" 
(parser := class parserClass new) parseSelector: source.
source := (newSelector asString), (source allButFirst: parser endOfLastToken).

"Compile modified source"
class compile: source classified: category.

"Remove old selector"
class removeSelector: oldSelector

You could probably find an easier way to do this if you browse through the Squeak code a bit longer than I did.

Upvotes: 0

Curtis
Curtis

Reputation: 1189

What you are suggesting puts HUGE red flags up for me. What is it you are trying to accomplish with this?

Do you mean you want to change the name of the method you are calling at runtime? If so, that's easy.

do something like:

|methodName|
methodName :=  self useMethod1 ifTrue: [#method1 ] ifFalse:[ #method2 ].
self perform: methodName.

Upvotes: 2

Ken Causey
Ken Causey

Reputation: 31

The normal way a user does this is to modify the method source and 'accept it' then delete the old version. So it's not likely that basic Squeak includes a single method to do this, although I could be wrong.

However if you install, for example, OmniBrowser there is a method refactoring called 'rename' and you could inspect and find code to perform this refactoring. It is fairly complex, firstly because the refactorings are done using the command pattern which involves a little redirection to work out, but secondly because this is a fairly complex refactoring which includes modifying the call sites.

Upvotes: 2

Related Questions