[ANN] Mirrors for GST

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

[ANN] Mirrors for GST

MrGwen
Hello,

I am pleased to announce the initial release of Mirrors for GST.
It is common to use reflection in Smalltalk, for getting the class,
changing an instance variable, ... For instance anObject instVarAt: 1
returns the first instance variable. Reflection is often used for
meta-programming or when we create development tools.

But what will happen if the developer has changed #class or #instVarAt:
methods, unexpected results will occurs. This is one the reasons why
Mirrors are used, the paper explain well why they are useful

Mirrors: Design Principles for Meta-level Facilities of Object-Oriented
Programming Languages <http://bracha.org/mirrors.pdf>

You can try the implementation on my github repository:

https://github.com/MrGwen/gst-mirror (this is under the MIT licence)

First you will need to install a small patch in the VM (a new primitive
for executing
compiled method http://smalltalk.gnu.org/project/issue/643). I've tried
in my implementation
to minimize the VM changes (I didn't want to add tons of new primitives
or to change all the basic primitives).

There are three Mirrors right now:
   - MirrorPrimitive
   - Mirror
   - BehaviorMirror

MirrorPrimitive is a dedicated mirror for breaking all the encapsulation
- and it makes primitive as first class entity by the way - but only do that
  nothing more, that's the link between the others mirrors and the vm.

For instance you could do something like that for getting a class:
   MirrorPrimitive classFor: anObject and as a result you get the class.
   MirrorPrimitive for: anObject slotAt: anIndex

The  implementation is quite trivial since I haven't created new
primitives (i.e. VMpr_Mirror_classFor, ...)
I've redefined the primitives at the class side:

   MirrorPrimitive class >> privateClass [
<primitive: VMpr_Object_class>
   ]

now at the instance side :

   classFor: anObject [
     ^ ##(MirrorPrimitive class >> privateClass) valueWithReceiver:
anObject withArguments: #()
   ]

##() is interesting because the compiled method (thus the primitive call)
will be "injected" as a literal thus I don't need to do a lookup all the
time (for getting the compiled method). Now I can execute the primitive
on the object.

Mirror is the class that you will use, unlike MirrorPrimitive they keep the
  object as a state, and provide all the API for inspecting the objects.
  You can get the class, change the slots, whatever you want. But it will
  return all the time a mirror as a result.

Mirror and MirrorPrimitive don't inherit from Object because I don't want
to allow someone to break the mirror encapsulation (only the mirror should
  be allowed to do that)

The API and the implementation is very a Saturday hacking ^^ Thus it will
be likely changed.

Hope you find them useful

Cheers,
Gwen


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: [ANN] Mirrors for GST

Paolo Bonzini-2
On 02/26/2012 08:07 PM, Gwenaël Casaccio wrote:

>
>   classFor: anObject [
>     ^ ##(MirrorPrimitive class >> privateClass) valueWithReceiver:
> anObject withArguments: #()
>   ]
>
> ##() is interesting because the compiled method (thus the primitive call)
> will be "injected" as a literal thus I don't need to do a lookup all the
> time (for getting the compiled method). Now I can execute the primitive
> on the object.

What about for even faster execution:

    classFor: anObject [
        <primitive VMpr_MirrorPrimitive_executePrimitive>
        ^##(VMpr_Object_class)
    ]

Paolo

_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: [ANN] Mirrors for GST

MrGwen
On 27/02/2012 08:49, Paolo Bonzini wrote:

> On 02/26/2012 08:07 PM, Gwenaël Casaccio wrote:
>>    classFor: anObject [
>>      ^ ##(MirrorPrimitive class>>  privateClass) valueWithReceiver:
>> anObject withArguments: #()
>>    ]
>>
>> ##() is interesting because the compiled method (thus the primitive call)
>> will be "injected" as a literal thus I don't need to do a lookup all the
>> time (for getting the compiled method). Now I can execute the primitive
>> on the object.
> What about for even faster execution:
>
>      classFor: anObject [
>          <primitive VMpr_MirrorPrimitive_executePrimitive>
>          ^##(VMpr_Object_class)
>      ]
>
> Paolo
I've made a MirrorPrimitive and two pragmas; the first pragma calls the
primitive
but the second has an extra argument an error block (i.e. vmPrimitive
for: ... at: ifFailed: [])
Thus no exceptions are raised (and thus no possible leaked vmPrimitves
objects).
The primitive number is added at the end by the pragma. I've added the
compiled
method as an extra parameter to the execute_primitive function.

classFor: anObject [
<mirrorPrimtive: VMpr_Object_Class>
]

for: anObject at: anIndex ifFailed: aBlock [
<mirrorPrimtiveWithBlock: VMpr_Object_basicAt>
     ^aBlock value
]

Cheers,
Gwen


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

mirrorPrimitive.patch (11K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [ANN] Mirrors for GST

Paolo Bonzini-2
Il 28/02/2012 15:00, Gwenaël Casaccio ha scritto:

>>
> I've made a MirrorPrimitive and two pragmas; the first pragma calls the
> primitive
> but the second has an extra argument an error block (i.e. vmPrimitive
> for: ... at: ifFailed: [])
> Thus no exceptions are raised (and thus no possible leaked vmPrimitves
> objects).
> The primitive number is added at the end by the pragma. I've added the
> compiled
> method as an extra parameter to the execute_primitive function.
>
> classFor: anObject [
> <mirrorPrimtive: VMpr_Object_Class>
> ]
>
> for: anObject at: anIndex ifFailed: aBlock [
> <mirrorPrimtiveWithBlock: VMpr_Object_basicAt>
>     ^aBlock value
> ]

Do you need the second?  Perhaps you can just call ^self
primitiveFailed, and catch the exception in the caller.  Mirror
primitives that can fail shouldn't be on a fast path, should they?
Otherwise looks good.

Paolo

_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: [ANN] Mirrors for GST

MrGwen
On 28/02/2012 15:22, Paolo Bonzini wrote:

> Il 28/02/2012 15:00, Gwenaël Casaccio ha scritto:
>> I've made a MirrorPrimitive and two pragmas; the first pragma calls the
>> primitive
>> but the second has an extra argument an error block (i.e. vmPrimitive
>> for: ... at: ifFailed: [])
>> Thus no exceptions are raised (and thus no possible leaked vmPrimitves
>> objects).
>> The primitive number is added at the end by the pragma. I've added the
>> compiled
>> method as an extra parameter to the execute_primitive function.
>>
>> classFor: anObject [
>> <mirrorPrimtive: VMpr_Object_Class>
>> ]
>>
>> for: anObject at: anIndex ifFailed: aBlock [
>> <mirrorPrimtiveWithBlock: VMpr_Object_basicAt>
>>      ^aBlock value
>> ]
> Do you need the second?  Perhaps you can just call ^self
> primitiveFailed, and catch the exception in the caller.  Mirror
> primitives that can fail shouldn't be on a fast path, should they?
> Otherwise looks good.
>
> Paolo

Hello,
about the exceptions. frankly I'm not sure about mirrors errors
handling: I like to force the user to handle errors (for Mirrors) but
there is one exception #dnu: errors (returning ^ self is too "dangerous"
it will be a pain to debug the application). Thus if I raise an
exception specially with a mirror an object could capture exception and
the mirror and you know the next. In fact I would like to understand a
bit more what is the best approach maybe "safer" exceptions are better,
an object could capture them but cannot break the encapsulation of the
exception.

And since I'm talking about exceptions what about a process that handle
exceptions like Erlang : It will capture all the exception of the
running image could handle some cases, and in the worst case could
restart the service (the image with a kind of OSProcess) - just a vague idea

Cheers,
Gwen

_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: [ANN] Mirrors for GST

MrGwen
On 29/02/2012 11:13, Gwenaël Casaccio wrote:

> On 28/02/2012 15:22, Paolo Bonzini wrote:
>> Il 28/02/2012 15:00, Gwenaël Casaccio ha scritto:
>>> I've made a MirrorPrimitive and two pragmas; the first pragma calls the
>>> primitive
>>> but the second has an extra argument an error block (i.e. vmPrimitive
>>> for: ... at: ifFailed: [])
>>> Thus no exceptions are raised (and thus no possible leaked vmPrimitves
>>> objects).
>>> The primitive number is added at the end by the pragma. I've added the
>>> compiled
>>> method as an extra parameter to the execute_primitive function.
>>>
>>> classFor: anObject [
>>> <mirrorPrimtive: VMpr_Object_Class>
>>> ]
>>>
>>> for: anObject at: anIndex ifFailed: aBlock [
>>> <mirrorPrimtiveWithBlock: VMpr_Object_basicAt>
>>>      ^aBlock value
>>> ]
>> Do you need the second?  Perhaps you can just call ^self
>> primitiveFailed, and catch the exception in the caller.  Mirror
>> primitives that can fail shouldn't be on a fast path, should they?
>> Otherwise looks good.
>>
>> Paolo
>
> Hello,
> about the exceptions. frankly I'm not sure about mirrors errors
> handling: I like to force the user to handle errors (for Mirrors) but
> there is one exception #dnu: errors (returning ^ self is too
> "dangerous" it will be a pain to debug the application). Thus if I
> raise an exception specially with a mirror an object could capture
> exception and the mirror and you know the next. In fact I would like
> to understand a bit more what is the best approach maybe "safer"
> exceptions are better, an object could capture them but cannot break
> the encapsulation of the exception.
>
> And since I'm talking about exceptions what about a process that
> handle exceptions like Erlang : It will capture all the exception of
> the running image could handle some cases, and in the worst case could
> restart the service (the image with a kind of OSProcess) - just a
> vague idea
>
> Cheers,
> Gwen
>

Could you remove the second one.

Gwen
_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk