> On 18 May 2018, at 10:39, Marcus Denker <[email protected]> wrote:
> 
> Hi,
> 
> the #binding: API until now did not allow to shadow globals. But there is 
> actually no reason to forbid that
> (and it can actually be interesting, e.g. to compile code where one class ref 
> is switched to another).
> 
> The Pull Request does:
> 
> - add comment to OCExtraBindingScope
> - categorize tests
> - change #lookupVar: to allow shadowing of Globals.
> - change test to reflect the new behaviour
> 
> This means you can do:
> 
> result := Smalltalk compiler
>               bindings: {(#Object -> Point)} asDictionary;
>               evaluate: 'Object new’.

So what can we do with this? If you develop a compiler, it is always very 
annoying that any change that you do actually breaks the compiler if you do it 
wrong. Larger changes over multiple methods get quite hard to do.

One thing that we will soon have is the “accept for test” feature that I posted 
recently. 
Another idea is to use the #bindings: feature of the compiler.

I did small experiment, I added this method to the OpalCompiler class on the 
class side:

prepareForDevelopment
        "this method sets up an overlay in the global var CompilerOverlay"
        <script>
        | overlayEnvironment |
        
        overlayEnvironment := Dictionary new.
        Smalltalk globals at: #CompilerOverlay put: overlayEnvironment.
        
        "now we put a copy of all the classes of the compiler package into the 
environment"
        self package definedClasses do: [ :class |
                overlayEnvironment at: class name put: class copy].

        “then we recompile the classes in the environment with itself as an 
overlay"
        overlayEnvironment valuesDo: [ :class | 
                class methods do: [ :method | |newMethod|
                 newMethod := class compiler 
                                bindings: overlayEnvironment;
                                compile: method sourceCode.
                 class addSelectorSilently: method selector withMethod: 
newMethod.      
                ]].

After that is done, we have CompilerOverlay global that contains a copy of all 
the classes of the compiler recompiled so that they use all the classes inside 
this copy.

So we now can set this copy as the main compiler for the image:

SmalltalkImage compilerClass: (CompilerOverlay at: #OpalCompiler) 

And after that, you can put a #halt deep in the compiler (or do some change 
that needs multiple steps), yet compilation will not be affected.
Most tests (not all) are writing in a way that they use classes from the 
package directly (they do not go via the global #compilerClass setting).

So this means that one can now change the compiler as much as one wants, test 
it by running tests and then be quite sure that it will not break anything.

Shortcomings:
        -> extensions are not treated, only the main package
        -> Not used much, for sure needs testing to see if this really works.
        -> Can we get rid of the #CompilerOverlay global?

        Marcus

 




Reply via email to