ifTrue not acting as a polymorphic message?

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

ifTrue not acting as a polymorphic message?

Alan Rodas
First of all, hi to everybody. This is my first time posting to this list, and as the nettiquette rules says I introduce myself.

I'm a student from the Universidad Nacional de Quilmes, in Quilmes, Buenos Aires, Argentina. So I beg for you to apologize my bad English. I'm currently the teachers assistent at Tecnicas Avanzadas de Programacion (Object Oriented Programming)
Well, that's pretty much it.

Second of all I would like to thank and congratulate the team behind Pharo. It's by far my favorite Smalltalk environment, although I miss some features from VisualWorks (Future discussion maybe :-) )

--------------------------------
Now, to my problem.


While I was thinking on an exercise to give to the students I though about developing a three-valued logic, creating the TTrue, TFalse, and TUnknown, whos instances understood some methods such as #ifTrue: #ifFalse: and so on.

My surprise came when I discovered that the ifTrue: method only work for the True and False instances of Smalltalk, being unable to define a method named ifTrue:

For what I saw the problem is that, on non boolean receivers, the method is not even evaluated to see if the receiver can understand it, but it automatically triggers the message #mustBeBoolean

So my question is, why does it do this? Is there a way to use ifTrue: really as a method?
Is there a way that I can make ifTrue: to work with any Class and not just Booleans?



Thanks in advance.

-- 
Alan Rodas Bonjour


_______________________________________________
Pharo-users mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-users
Reply | Threaded
Open this post in threaded view
|

Re: ifTrue not acting as a polymorphic message?

Marcus Denker-4
Hello,

While I was thinking on an exercise to give to the students I though about developing a three-valued logic, creating the TTrue, TFalse, and TUnknown, whos instances understood some methods such as #ifTrue: #ifFalse: and so on.

My surprise came when I discovered that the ifTrue: method only work for the True and False instances of Smalltalk, being unable to define a method named ifTrue:

For what I saw the problem is that, on non boolean receivers, the method is not even evaluated to see if the receiver can understand it, but it automatically triggers the message #mustBeBoolean

So my question is, why does it do this? Is there a way to use ifTrue: really as a method?
Is there a way that I can make ifTrue: to work with any Class and not just Booleans?


The reason is that ifTrue: is compiled by the smalltalk-to-bytecode compiler to a test-and-jump bytecode.

So

^1 + 2 ifTrue: ['true']

is compiled to:

17 <76> pushConstant: 1
18 <77> pushConstant: 2
19 <B0> send: +
20 <99> jumpFalse: 23
21 <20> pushConstant: 'true'
22 <90> jumpTo: 24
23 <73> pushConstant: nil
24 <7C> returnTop


In smalltalk, we do not know at compile time the type of any expression. So we can not build a compiler
that does the jump for the case that the expression is a boolean and send the message else. We know
the class of the result of an expression only at runtime, not at compile time.

So the solution takes was to make some selectors special. ifTrue: is *always* compiled to a jump bytecode.
This in turn means that it can not be used for any other purpose. If you implement it in your own class, it will never
be called. (I alwasy wanted to look into the question if the vm could not just re-send ifTrue: instead of giving the
useless error message...)

One possible way around this (for experiments) is to change the compiler to always send ifTrue: and never do the
jump bytecode. The image gets slow, though (but it can be done). 

Another, more practical solution is to just do the change for the classes you are experimenting with and use a 
hacked second compiler for those (we did this with the NewCompiler in the past when experimenting with different
things). Or you could change the inlining logic of the compiler to not inline ifTrue just for your package, or depending 
on a pragma in the method.

In Opal (the new compiler, sadly not yet a drop-in replacement, but soon), the place to do that is quickly found. 
There is a visitor that translates AST to bytecode. It has a method

acceptMessageNode: aMessageNode
aMessageNode isInlineIf ifTrue: [^ self emitIfNode: aMessageNode].
aMessageNode isInlineIfNil ifTrue: [^ self emitIfNilNode: aMessageNode].
aMessageNode isInlineAndOr ifTrue: [^ self emitAndOrNode: aMessageNode].
aMessageNode isInlineWhile ifTrue: [^ self emitWhileNode: aMessageNode].
aMessageNode isInlineToDo ifTrue: [^ self emitToDoNode: aMessageNode].
aMessageNode isInlineCase ifTrue: [^ self emitCaseNode: aMessageNode].
^ self emitMessageNode: aMessageNode

Easy. 

The old smalltalk compiler, I always get headaches looking at it. I guess #transformIfNil: would be the starting point to look at.

Marcus

--
Marcus Denker  -- http://www.marcusdenker.de
INRIA Lille -- Nord Europe. Team RMoD.


_______________________________________________
Pharo-users mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-users
Reply | Threaded
Open this post in threaded view
|

Re: ifTrue not acting as a polymorphic message?

Marcus Denker-4
In reply to this post by Alan Rodas

On Sep 24, 2010, at 10:17 AM, Marcus Denker wrote:


So the solution takes was to make some selectors special. ifTrue: is *always* compiled to a jump bytecode.
This in turn means that it can not be used for any other purpose. If you implement it in your own class, it will never
be called. (I alwasy wanted to look into the question if the vm could not just re-send ifTrue: instead of giving the
useless error message...)
Which of course would be tricky as there is no block for the parameter... it has been optimized away.

The solution to all these things is of course late-binding optimization to the point when all information is available.

Marcus


--
Marcus Denker  -- http://www.marcusdenker.de
INRIA Lille -- Nord Europe. Team RMoD.


_______________________________________________
Pharo-users mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-users
Reply | Threaded
Open this post in threaded view
|

Re: ifTrue not acting as a polymorphic message?

Alan Rodas
Thanxs Marcus, now its clearer.
Of course my solution was just to rename the method in that class to ifTTrue: ifTFalse: and so on. 
But avoiding the mountain doesn't make it disappear.

Maybe when I get some extra time I will play with the VM to see how it works, and, if possible, find a solution to this problem. 

Thanks again for answering.


See you around the list. Bye.
--
Alan Rodas Bonjour


_______________________________________________
Pharo-users mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-users