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 |
Hello,
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 |
In reply to this post by Alan Rodas
On Sep 24, 2010, at 10:17 AM, Marcus Denker wrote: 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 |
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 |
Free forum by Nabble | Edit this page |