Hi, I need a short description for what the OCASTTranslator subclasses OCASTTranslatorForEffect OCASTTranslatorForValue are. I don't fully understand the usage. thanks in advance Nicolai |
Translate AST to byte codes? One for the case when we don't care of the result (we will pop it off the stack), we just want the effect.2016-12-05 8:47 GMT+01:00 Nicolai Hess <[hidden email]>:
|
On Mon, Dec 5, 2016 at 8:51 AM, Nicolas Cellier <[hidden email]> wrote:
It translates AST to Opal's IR. And yes one uses one or the other if one wants only the effect and don't care about the result or if one cares about the result and the effect.
|
In reply to this post by Nicolas Cellier
2016-12-05 8:51 GMT+01:00 Nicolas Cellier <[hidden email]>:
(For opal, this first creates the intermediate representation (IR), but yes translating from AST to (finally) byte codes)
Ok.
Who decides which to use, when do I know that I need to use, the effect translator only or the value translator?
|
Both are used for each compilation. They're instance variables of each other.
| Who decides which to use In each AST node translation, you know for each value which one to use. For example, when translating a return, the value to return needs to be pushed on stack, so the valueTranslator is used: visitReturnNode: aReturnNode valueTranslator visitNode: aReturnNode value. methodBuilder returnTop. Yet, in #visitMethodNode:, you can see that the effectTranslator is used, because no value is pushed on stack at the end of the method body: ...effectTranslator visitNode: aMethodNode body... Then some behavior can be conditional, for example, in OCASTTranslator >> #visitArrayNode: ...^ self visitLargeArrayNode: anArrayNode ]... The self here represents either the value or effect translator and dispatches to the correct method using polymorphism. | when do I know that I need to use ? If you need the value on stack, use the valueTranslator. If you need the effect but not the value, use the effectTranslator. If you're implementing something in the valueTranslator, it needs to push something on stack at the end. If you're implementing something in the effectTranslator, it doesn't push anything on stack at the end. | the effect translator only or the value translator? I think you always need both.Let's take this method: MyClass>>return1 ^ 42.0 The method uses the effect translator to translate is body (^ 42.0). The body is a sequence node, with one statement only. A sequence node translates all its statements for effect, except the last one which depends on how it's called (in this case, it's called with the effectTranslator, so it's also for effect). Sequence translated for value are used in inlined control structures. So the first statement is translated for effect. The return node asks first the value translator to push the float (42.0) on stack, generating pushLiteral: 42.0 Then the return node generates the returnTop instruction. ** I don't know how to explain better. I like to think of this problem as the difference between procedures and functions in old programming languages. On Mon, Dec 5, 2016 at 9:36 AM, Nicolai Hess <[hidden email]> wrote:
|
2016-12-05 10:08 GMT+01:00 Clément Bera <[hidden email]>:
Thank you clement, this helped a lot. Some background why I am asking: http://forum.world.st/Stack-underflow-with-meta-links-on-message-nodes-tp4925154.html Adding a "before" metalink to a message node like "1+1" and trying use a the receiver value within the metalink will raise a stack underflow error. This is caused by the RFEReceiverReification, it will pop the arguments of the stack, to access the receiver. It will create temporaries for the popped arguments and expects this temporaries to be pushed on to the stack again, after storing the receiver value. But this does not work (the arguments aren't pushed back). It works if we assign this metalink to a return node *value*, the "1+1" in ^ 1 + 1 Now there is no stack underflow, because the return node value uses the valueTranslator that does do the pushTemp, as expected by the RFEReceiverReification. (Best seen by comparing both IRs. First, link is attached to a message that is not a return statement: label: 1 pushLiteral: '1' pushLiteral: '1' popIntoTemp: #RFArg1RFReification storeTemp: #RFReceiverReificationVar pushLiteralVariable: RFMetaLink pushTemp: #RFReceiverReificationVar pushLiteral: RBMessageNode('1' , '1') send: #value:value: popTop send: #, popTop returnReceiver Next, if the link is attached to the expression of a return statement: label: 1 pushLiteral: '1' pushLiteral: '1' popIntoTemp: #RFArg1RFReification storeTemp: #RFReceiverReificationVar pushTemp: #RFArg1RFReification "<<<- this is missing in the other IR" pushLiteralVariable: RFMetaLink pushTemp: #RFReceiverReificationVar pushLiteral: RBMessageNode('1' , '1') send: #value:value: popTop send: #, returnTop Solution ? @Marcus, can we *always* use the valueTranslator when visiting a link preamble ? (I tried this, the above method now works, and all tests are green, but I am not sure if this is the right solution). nicolai
|
Can we collect this as a nice class comment? On Mon, Dec 5, 2016 at 10:42 AM, Nicolai Hess <[hidden email]> wrote:
|
2016-12-05 10:55 GMT+01:00 Stephane Ducasse <[hidden email]>:
Yes, I 'll try to add this as class comment.
|
In reply to this post by Nicolai Hess-3-2
2016-12-05 10:42 GMT+01:00 Nicolai Hess <[hidden email]>:
using #after-Links with the receiver as argument, doesn't work too. The after link will create a block+ensure call. With this setup, it is even more difficult to access the receiver from the stack.
|
In reply to this post by Nicolai Hess-3-2
Sorry for not answering, I was travelling and now catching up with emails. The decision to visit “for effect only” or “for value” is taken by the visitor depending on what part of the ast it is visiting.
Yes, I think so. The idea is that the preamble is just about stack manipulation, so we actually are not interested in e.g. popping off the result after a send where the value is not needed. I will commit a slide with the fix. Marcus
|
Marcus |
Free forum by Nabble | Edit this page |