Block and Context cannot return Questions

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

Block and Context cannot return Questions

stéphane ducasse-2
Hi

I would to currify some blocks that I want to use as methods in a  
simple object model.
The currification will allows to capture the class in which the block/
methods is defined in the same way literals hold
this information for compiled methods, and my programmer will not see  
it.

Now I'm stuck.

When I evaluate in a workspace
([:each |
            [ :objself |
                  | class |
                        class := each.
                        class = 2 ifTrue: [ ^ 'zak'].
                        ^ 'zork']] value: 3)
        value: 4

"in my small oo model class will play the role of the class literal  
and I plan to use it to perform super sends"
I get what is expected
        'zak'


Now I want to have a kind of macro system that given a string  
generate blocks
that will act as method bodies for my oo model.

methodFrom: aString myClass: aClass
        "(self new
                        methodFrom: 'class = 2 ifTrue: [ ^ ''zak''].
                                                        ^ ''zork'''
                        myClass: 2) value: 4"

        | block string resBlock |
        string := '[ :each |
                          [ :objself |
                                        | class |
                                        class := each. ', aString ,']]'.
        block := Compiler new
                                evaluate: string
                                in: nil
                                receiver: nil
                                notifying: nil
                                ifFail: [nil].
        resBlock := block value: aClass.
        ^ resBlock


When I execute

        self new
                methodFrom: 'class = 2 ifTrue: [ ^ ''zak''].
                                                        ^ ''zork'''
                myClass: 2) value: 4

I get a context cannot return.
I understand approximately that since I create my blocks on the fly  
they do not have a homeContext.

Now I would like to know how I can get the behavior of the block that  
I manually typed
for the generated ones.
Any nice suggestion? Should I create and how a BlockContext and pass  
it as the in: parameter


Stef





Reply | Threaded
Open this post in threaded view
|

Re: Block and Context cannot return Questions

Nicolas Cellier-3
Le Jeudi 23 Février 2006 21:04, stéphane ducasse a écrit :

> Hi
>
> I would to currify some blocks that I want to use as methods in a
> simple object model.
> The currification will allows to capture the class in which the block/
> methods is defined in the same way literals hold
> this information for compiled methods, and my programmer will not see
> it.
>
> Now I'm stuck.
>
> When I evaluate in a workspace
> ([:each |
>      [ :objself |
>
>      | class |
>
>    class := each.
>    class = 2 ifTrue: [ ^ 'zak'].
>    ^ 'zork']] value: 3)
>  value: 4
>
> "in my small oo model class will play the role of the class literal
> and I plan to use it to perform super sends"
> I get what is expected
>  'zak'
>
>
> Now I want to have a kind of macro system that given a string
> generate blocks
> that will act as method bodies for my oo model.
>
> methodFrom: aString myClass: aClass
>  "(self new
>    methodFrom: 'class = 2 ifTrue: [ ^ ''zak''].
>        ^ ''zork'''
>    myClass: 2) value: 4"
>
>  | block string resBlock |
>
>  string := '[ :each |
>      [ :objself |
>
>      | class |
>
>      class := each. ', aString ,']]'.
>  block := Compiler new
>     evaluate: string
>     in: nil
>     receiver: nil
>     notifying: nil
>     ifFail: [nil].
>  resBlock := block value: aClass.
>  ^ resBlock
>
>
> When I execute
>
>  self new
>   methodFrom: 'class = 2 ifTrue: [ ^ ''zak''].
>        ^ ''zork'''
>   myClass: 2) value: 4
>
> I get a context cannot return.
> I understand approximately that since I create my blocks on the fly
> they do not have a homeContext.

More exactly, your block had a homeContext until #methodFrom:myClass: did
return. Once returned from, the context is no more active, and aClass has
been removed from the execution stack. The inside block created still want to
access aClass as first argument on the stack... And the copy into inside
block temporary does not fix it. Block still keep the link to the stack...

> Now I would like to know how I can get the behavior of the block that
> I manually typed
> for the generated ones.
> Any nice suggestion? Should I create and how a BlockContext and pass
> it as the in: parameter
>
>
> Stef

I suggest you use a dedicated class that will have both a pointer to the
 class and a pointer to the block method as inst vars.

Object subclass: ValuableThing
 instanceVariables: 'targetClass blockMethod'.

This thing will simply implement
value: aClass
 ^(block value: targetClass) value: aClass

Did not browse the system, but such things might already exist in one of
ValueModel subclasses.

Then your #methodFrom:myClass: will compile the outside block and create an
instance of ValuableThing that will be value:-able.

methodFrom: aString myClass: aClass
  "(self new
    methodFrom: 'class = 2 ifTrue: [ ^ ''zak''].
        ^ ''zork'''
    myClass: 2) value: 4"

  | block string resThing |

  string := '[ :each |
      [ :objself |

      | class |

      class := each. ', aString ,']]'.
  block := Compiler new
     evaluate: string
     in: nil
     receiver: nil
     notifying: nil
     ifFail: [nil].

  resThing := ValuableThing new targetClass: aClass blockMethod: block.
  ^ resThing

When you will evaluate resThing, the block context should be OK.

Nicolas

-------------------------------------------------------

Reply | Threaded
Open this post in threaded view
|

Re: Block and Context cannot return Questions

stéphane ducasse-2
In reply to this post by stéphane ducasse-2
Hi

In fact I started with this kind of idea but (I haven't currified the  
block so I could not access the class as I wanted).
Thanks for the suggestion. But I would really like to know why my  
expression in my workspace worked while the
expression generated on the fly did not.
Any idea?

> Object subclass: ObjMethod
>  instanceVariables: 'definingClass blockMethod'.
>
> This thing will simply implement
> value: aClass
>  ^(block value: definingClass) value: aClass
>
> Did not browse the system, but such things might already exist in  
> one of
> ValueModel subclasses.
>
> Then your #methodFrom:myClass: will compile the outside block and  
> create an
> instance of ValuableThing that will be value:-able.
>
> methodFrom: aString myClass: aClass
>   "(self new
>     methodFrom: 'class = 2 ifTrue: [ ^ ''zak''].
>         ^ ''zork'''
>     myClass: 2) value: 4"
>
>   | block string resThing |
>
>   string := '[ :each |
>       [ :objself |
>       | class |
>       class := each. ', aString ,']]'.
>   block := Compiler evaluate: string.
>   resThing := ValuableThing new targetClass: aClass blockMethod:  
> block.
>   ^ resThing
>
> When you will evaluate resThing, the block context should be OK.

Does not work....
Sniff.

Stef

Reply | Threaded
Open this post in threaded view
|

Re: Block and Context cannot return Questions

Nicolas Cellier-3
Le Jeudi 23 Février 2006 22:29, stéphane ducasse a écrit :
> Hi
>
> In fact I started with this kind of idea but (I haven't currified the
> block so I could not access the class as I wanted).
> Thanks for the suggestion. But I would really like to know why my
> expression in my workspace worked while the
> expression generated on the fly did not.
> Any idea?

The inside block refer to its homeContext, that is the Context of method in
which it is compiled.
When you have a DoIt, the insideBlock is evaluated while the homeContext (the
DoIt) is still active. This is why it works.

>
> >
> > When you will evaluate resThing, the block context should be OK.
>
> Does not work....
> Sniff.
>
> Stef

Sorry, i had not any VW image opened when i answered, should have checked...
As i stated above, the homeContext of the insideBlock in my solution is also a
DoIt (Compiler evaluate: etc...). This is why my solution were also bad. The
homeContext is not valid once #evaluate: will return.

If you compile your block on the fly with Compiler evaluate: ..., it's home
context is always dead when you evaluate the block.
You must arrange to have the inside block not refer to its homeContext.

So where is this reference to the homeContext ?
Because the example you use has a return sign ^. That means that the
homeContext should return...
Still your block refer to its homeContext and won't work...

(self new
    methodFrom: 'class = 2 ifTrue: [ ^ ''zak''].
        ^ ''zork'''
    myClass: 2) value: 4

If you try this one:

(self new
    methodFrom: 'class = 2
 ifTrue: [ ''zak'']
        ifFalse: [ ''zork''' ]
    myClass: 2) value: 4

It should work (Sorry, I still did not open the image).
Maybe your first implementation will work too.
But maybe you need these return signs... in which case, i have no easy
solution with blocks.


Reply | Threaded
Open this post in threaded view
|

Re: Block and Context cannot return Questions

stéphane ducasse-2
Yes I need these returns else I cannot represent control flow  
escaping in my model.

>> In fact I started with this kind of idea but (I haven't currified the
>> block so I could not access the class as I wanted).
>> Thanks for the suggestion. But I would really like to know why my
>> expression in my workspace worked while the
>> expression generated on the fly did not.
>> Any idea?
>
> The inside block refer to its homeContext, that is the Context of  
> method in
> which it is compiled.
> When you have a DoIt, the insideBlock is evaluated while the  
> homeContext (the
> DoIt) is still active. This is why it works.
>
>>
>>>
>>> When you will evaluate resThing, the block context should be OK.
>>
>> Does not work....
>> Sniff.
>>
>> Stef
>
> Sorry, i had not any VW image opened when i answered, should have  
> checked...
> As i stated above, the homeContext of the insideBlock in my  
> solution is also a
> DoIt (Compiler evaluate: etc...). This is why my solution were also  
> bad. The
> homeContext is not valid once #evaluate: will return.
>
> If you compile your block on the fly with Compiler evaluate: ...,  
> it's home
> context is always dead when you evaluate the block.
> You must arrange to have the inside block not refer to its  
> homeContext.
>
> So where is this reference to the homeContext ?
> Because the example you use has a return sign ^. That means that the
> homeContext should return...
> Still your block refer to its homeContext and won't work...
>
> (self new
>     methodFrom: 'class = 2 ifTrue: [ ^ ''zak''].
>         ^ ''zork'''
>     myClass: 2) value: 4
>
> If you try this one:
>
> (self new
>     methodFrom: 'class = 2
>  ifTrue: [ ''zak'']
>         ifFalse: [ ''zork''' ]
>     myClass: 2) value: 4
>
> It should work (Sorry, I still did not open the image).
> Maybe your first implementation will work too.
> But maybe you need these return signs... in which case, i have no easy
> solution with blocks.
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Block and Context cannot return Questions

stéphane ducasse-2
In fact thinking about it I'm not sure that these returns have sense  
in my model.
This is interesting to see how an implementation can make you thinking.


> Yes I need these returns else I cannot represent control flow  
> escaping in my model.
>
>>> In fact I started with this kind of idea but (I haven't currified  
>>> the
>>> block so I could not access the class as I wanted).
>>> Thanks for the suggestion. But I would really like to know why my
>>> expression in my workspace worked while the
>>> expression generated on the fly did not.
>>> Any idea?
>>
>> The inside block refer to its homeContext, that is the Context of  
>> method in
>> which it is compiled.
>> When you have a DoIt, the insideBlock is evaluated while the  
>> homeContext (the
>> DoIt) is still active. This is why it works.
>>
>>>
>>>>
>>>> When you will evaluate resThing, the block context should be OK.
>>>
>>> Does not work....
>>> Sniff.
>>>
>>> Stef
>>
>> Sorry, i had not any VW image opened when i answered, should have  
>> checked...
>> As i stated above, the homeContext of the insideBlock in my  
>> solution is also a
>> DoIt (Compiler evaluate: etc...). This is why my solution were  
>> also bad. The
>> homeContext is not valid once #evaluate: will return.
>>
>> If you compile your block on the fly with Compiler evaluate: ...,  
>> it's home
>> context is always dead when you evaluate the block.
>> You must arrange to have the inside block not refer to its  
>> homeContext.
>>
>> So where is this reference to the homeContext ?
>> Because the example you use has a return sign ^. That means that the
>> homeContext should return...
>> Still your block refer to its homeContext and won't work...
>>
>> (self new
>>     methodFrom: 'class = 2 ifTrue: [ ^ ''zak''].
>>         ^ ''zork'''
>>     myClass: 2) value: 4
>>
>> If you try this one:
>>
>> (self new
>>     methodFrom: 'class = 2
>>  ifTrue: [ ''zak'']
>>         ifFalse: [ ''zork''' ]
>>     myClass: 2) value: 4
>>
>> It should work (Sorry, I still did not open the image).
>> Maybe your first implementation will work too.
>> But maybe you need these return signs... in which case, i have no  
>> easy
>> solution with blocks.
>>
>>
>>
>