On 2 March 2013 09:25, Colin Putney colin@wiresong.com wrote:
Hi all,
So I've been plugging away at Environments, and have a new implementation that supports renaming, but I wanted to get some feedback before figuring out the sequence of commits necessary to update the trunk safely.
The idea is to support this kind of scenario:
seaside := (Environment named: #Seaside) import: Smalltalk globals; importSelf; exportSelf; yourself.
magma := (Environment named: #Magma) import: Smalltalk globals; importSelf; exportSelf; yourself.
app := (Environment named: #AwesomeApp) import: Smalltalk globals; import: seaside; from: seaside import: {#Session -> #SeasideSession}; import: magma; from: magma import: {#Session -> #MagmaSession}; importSelf; exportSelf; yourself.
In order to have the decompiled code use the correct names, I've changed the way lookup works. Instead of moving bindings from one environment to another, we now create a separate set of bindings for each environment, and copy the values (i.e., classes and globals) into a new binding when a binding is imported.
+1 the last time i thought about it, i came to same conclusion.
I had originally thought to use something like #changed:/#update: to keep all the bindings in sync, but then I realized that ClassBuilder does a #becomeForward: updates a class. So it's really only globals that could become out of sync between environments. Since we have very few globals in the image, and they basically never change, an update mechanism may not be necessary in practice.
So, here are some possible ways to proceed:
- Use #changed:/#update: or something similar to keep keep global variables
in sync.
- Idea from Eliot—adopt the same convention as VW, and send #value to the
binding on every access. Then we could have a special Alias bindings that forward the #value message to the original binding.
yeah.. but i would go even further: since you already sending a message, why not using a looked-up name as selector? <obj> Foo -> gives binding of 'Foo' in environment. <obj> Foo: <value> -> sets the new value.
i bet, with some trickery you can almost completely eliminate the overhead of dynamic dispatch (especially while under Cog VM). you can even exploit VM lookup logic to search through hierarchy of environments.
- Share bindings for global variables between environments and disallow
renaming of globals.
Forget it. Message is best. What if you want to delete binding or create new one? If you stick with early binding scheme, you will have a lot of problems with it. Late bound solution is natural , i would go with it first, and then see how to optimize it.. instead of exploiting model which quite inadequate for environments purpose :)
- Special case the traditional globals such as Transcript and Display, and
disallow the creation of new globals.
well, some globals will be still there, like it or not: special objects array ;) as for 'human-recognized' globals , e.g. those who kept in system dictionary.. who cares? you can replace it with bunch of environments at any moment without any harm. yeah.. of course you have to change the tools accordingly, to not rely on capturing association object as a name binding, but instead always send message to environment object.. but that's you have to change anyways.. so what's the deal?
Anyhow, I'd appreciate a code review from anybody who's interested in this stuff. To take a look, file the attached (hand edited) change set into an updated trunk image.
Thanks,
Colin