[squeak-dev] What I learned today.... Parser & Compiler madness..

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

[squeak-dev] What I learned today.... Parser & Compiler madness..

David Goehrig
Squeakers,

Today I learned with Ken Causey's help how to create a SHWorkspace for testing out a custom Parser.  And I have to say, the way in which a typical workspace derives which Parser and Compiler class that it uses is rather confused :)

Typically the ParagraphEditor evalutateSelection method determines which parser to use by sending  'class evaluatorClass' to nil.  This method is defined in the Behavior class, and simply returns ^ Compiler.  The parser is then determined by sending #parserClass to Compiler, which returns ^ Parser.   Parser also has a class side method #evaluatorClass which returns ^ Compiler, which is used to instantiate the actual compiler it seems.

To patch your own workspace, it is necessary to subclass whatever workspace you're using and add an instance side method #doItReceiver which returns an instance of whatever parser you want to use: ^ new MyParser.  This class has to reference your own compiler class say MyCompiler in its #evalutorClass method, which then must have a #parserClass classide method that refers back to MyParser.

After all of that you can open up your new workspace running your own MyParser and MyCompiler, and program in something not totally dissimilar to Smalltalk.

Now #evaluatorClass is implemented in 3 places: Behavior, TPureBehavior, and TraitBehavior.  And all three have the exact same definition:

^ Compiler

The method #parserClass is implemented in 9 places, in a few different ways:

1. Compiler (class side) and MethodNode implement:

^ Parser

2. Behavior, CompiledMethod, TPureBehavior, and TraitBehavior implements:

^ compilerClass parserClass 

3. Compiler instance side:

^parser ifNil: [self class parserClass] ifNotNil: [parser class]

4. UndefinedObject and PseudoClass implement

^ Compiler parserClass

As you can see, most of the time, it does the right thing, except there are instances where you may actually get the wrong information (such as which parser generated a MethodNode), and there are times when you swap out compilers that don't result in the correct behavior. For example Text>>makeSelectorBold explicitly calls Compiler parserClass which necessarily invokes Parser, not necessarily the parser you're using.

Unmuddying these waters is something I'd love to help out with, but I've found poking around in this region is much like performing open heart surgery on yourself.  Sure to kill your image :)

Can anyone shed any light on why the current state of affairs is as it is?  It seems like there have been several attempts to make the underpinnings more flexible, allow for "user space" parsers and compilers, but ultimately, it just feels like a sargasso sea, plagued by dragons...

Dave

-=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] What I learned today.... Parser & Compiler madness..

Igor Stasenko
2009/7/10 David Goehrig <[hidden email]>:

> Squeakers,
> Today I learned with Ken Causey's help how to create a SHWorkspace for
> testing out a custom Parser.  And I have to say, the way in which a typical
> workspace derives which Parser and Compiler class that it uses is rather
> confused :)
> Typically the ParagraphEditor evalutateSelection method determines which
> parser to use by sending  'class evaluatorClass' to nil.  This method is
> defined in the Behavior class, and simply returns ^ Compiler.  The parser is
> then determined by sending #parserClass to Compiler, which returns ^ Parser.
>   Parser also has a class side method #evaluatorClass which returns ^
> Compiler, which is used to instantiate the actual compiler it seems.
> To patch your own workspace, it is necessary to subclass whatever workspace
> you're using and add an instance side method #doItReceiver which returns an
> instance of whatever parser you want to use: ^ new MyParser.  This class has
> to reference your own compiler class say MyCompiler in its #evalutorClass
> method, which then must have a #parserClass classide method that refers back
> to MyParser.
> After all of that you can open up your new workspace running your own
> MyParser and MyCompiler, and program in something not totally dissimilar to
> Smalltalk.
> Now #evaluatorClass is implemented in 3 places: Behavior, TPureBehavior, and
> TraitBehavior.  And all three have the exact same definition:
> ^ Compiler

I think its defined once in TPureBehavior , rest is inherired through traits.
The problem that you can't see it, is browser, which shows trait
method in class(es) which using them.

> The method #parserClass is implemented in 9 places, in a few different ways:
> 1. Compiler (class side) and MethodNode implement:
> ^ Parser
> 2. Behavior, CompiledMethod, TPureBehavior, and TraitBehavior implements:
> ^ compilerClass parserClass
again, blame traits :)

> 3. Compiler instance side:
> ^parser ifNil: [self class parserClass] ifNotNil: [parser class]
> 4. UndefinedObject and PseudoClass implement
> ^ Compiler parserClass
> As you can
> see, most of the time, it does the right thing, except there are instances where you may actually get the wrong information (such as which parser generated a MethodNode), and there are times when you swap out compilers that don't result in the correct behavior. For example Text>>makeSelectorBold explicitly calls Compiler parserClass which necessarily invokes Parser, not necessarily the parser you're using.
> Unmuddying these waters is something I'd love to help out with, but I've
> found poking around in this region is much like performing open heart
> surgery on yourself.  Sure to kill your image :)
> Can anyone shed any light on why the current state of affairs is as it is?
>  It seems like there have been several attempts to make the underpinnings
> more flexible, allow for "user space" parsers and compilers, but ultimately,
> it just feels like a sargasso sea, plagued by dragons...

Being able to plug-in a custom parser/compiler to workspace would be useful.
Because i have parser, which is a heavy refactoring of Squeak one, but
it needs a bit more efforts to get a final shape.

> Dave
> -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] What I learned today.... Parser & Compiler madness..

David Goehrig


On Fri, Jul 10, 2009 at 6:59 PM, Igor Stasenko <[hidden email]> wrote:
2009/7/10 David Goehrig <[hidden email]>:

I think its defined once in TPureBehavior , rest is inherired through traits.
The problem that you can't see it, is browser, which shows trait
method in class(es) which using them.

Hrmmm... that could be interesting to test... That of course begs the question, if that behavior be vectored in TPureBehavior, and then apply traits further throughout the remaining ones... 

Being able to plug-in a custom parser/compiler to workspace would be useful.
Because i have parser, which is a heavy refactoring of Squeak one, but
it needs a bit more efforts to get a final shape.

 Thanks to the old hooks in ParagraphEditor, hooking up a custom parser / compiler to a workspace doesn't require overwriting any existing class.  But it isn't exactly straight forward. :)  And considering the parser get repurposed for pretty printing and other tasks, it would be nice to be certain the right parser is being used.

What I'd like to try is setting up multiple parser/compilers at a top level, where some modules/packages compile against one Compiler, and others compile against others.  

 

--
-=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/