Hi all!
On 06/29/2012 06:48 AM, Chris Cunningham wrote: > Maybe the auto-aliaser would need to detect that the new code > references a dual-defined class, and asks which one it should use? in > other words, 'partially' auto alias. > > -Another Chris Interesting, some of these last ideas would make the end user experience similar to my Namespace implementation (for the insatiably interested: http://swiki.krampe.se/gohu/32) In that solution it works like this: - Classes can optionally be named "Fruit::Orange" instead of just "Orange" - When you look at source code with "Fruit::Orange" in it, it will "render in the browser" as just "Orange" iff there is just one Orange in the image. If there is also a "Colors::Orange" then it will automatically suddenly render in full. - If you try to compile "Orange" (in a Workspace or in a method) the tools will throw up a popup menu asking if you meant "Fruit::Orange" or "Color::Orange". And it will autoexpand it to its full name when you select. - "Prefix" also automatically refers to an instance of Namespace which is a global and acts like a Dictionary. Thus Namespaces are reified. Well, that's about it. Essentially it is prefixes like we have today - but with a clear separator (::), and reification of Namespaces. Being able to "pick another Namespace" when importing code (typically holding a map of these aliases so that code can still find its way) was never implemented but planned. So you end up with two Fruit packages - the idea was that you can import one of them into another Namespace like OldFruit and the image would contain this knowledge so that other packages can still resolve references to OldFruit classes, and ask etc. Anyway, intrigued to see where you end up! :) regards, Göran |
In reply to this post by cbc
On Thu, Jun 28, 2012 at 9:48 PM, Chris Cunningham
<[hidden email]> wrote: > Well, maybe. If I understand this right, then when you alias a class, > you refer to the alias in the code that is loaded later. If, however, > a class was left unaliased originally (in an import) and was then > referenced in the code depending on that import, but later a NEW > environment import was introduced with the same class, then if the new > importer automatically aliased both of these, the code wouldn't know > which one to use. Which would be unfortunate. First and foremost, auto-aliasing would have to be optional. There's always the escape hatch of being able to be explicit about everything, and get exactly what you want. Second, you're talking about two different situations here. One is where you're setting up a new environment before it contains any code. In that case, you have to create the environment that the code expects to see—either code that's already written or the code you're about to write. Auto-aliasing provides an reasonable convention that handles that case well. The other situation is where you add an import to an environment that already has code in it, introducing a name clash. There are three possible options: 1. Create an alias for the binding being imported. We know that the code already in the environment doesn't refer to it, so we just give it a new name and we're in good shape. 2. Create an alias for the existing binding. It requires updating the existing code to use the new name. If we have the RB installed, that's easy; if not, we can at least bring up a browser with all the references to the old name so the user can find them easily. 3. Alias both bindings. This gets us to where we'd have been if we'd done the import before any code was written. Again it requires updating all the existing references. We could use auto-aliasing only with empty environments, or have a (configurable?) policy for handling name clashes, or just ask the user what to do. It doesn't have to be decided now; we'll cross that bridge when we get to it. > In your Seaside / Magma example, could you leave one Session just as > Session, and have the other aliased? Sure. > Maybe the auto-aliaser would need to detect that the new code > references a dual-defined class, and asks which one it should use? in > other words, 'partially' auto alias. No. Auto aliasing would happen a namespace is being imported into an environment, not when code is being loaded. The idea is to resolve all ambiguities when constructing the environment, so that the compiler and dev tools can deal with a simple, one-to-one mapping from names to classes. Colin |
In reply to this post by cbc
> the code wouldn't know which one to use the code would always know which one to use: using the original 'bare' name always resolves to the local (or unique) instance, using the 'alias' is guaranteed by the system to be unambiguous. |
In reply to this post by Colin Putney-3
On 29.06.2012, at 08:57, Colin Putney wrote:
> On Thu, Jun 28, 2012 at 9:48 PM, Chris Cunningham > <[hidden email]> wrote: >> Well, maybe. If I understand this right, then when you alias a class, >> you refer to the alias in the code that is loaded later. If, however, >> a class was left unaliased originally (in an import) and was then >> referenced in the code depending on that import, but later a NEW >> environment import was introduced with the same class, then if the new >> importer automatically aliased both of these, the code wouldn't know >> which one to use. Which would be unfortunate. > > First and foremost, auto-aliasing would have to be optional. There's > always the escape hatch of being able to be explicit about everything, > and get exactly what you want. > > Second, you're talking about two different situations here. One is > where you're setting up a new environment before it contains any code. > In that case, you have to create the environment that the code expects > to see—either code that's already written or the code you're about to > write. Auto-aliasing provides an reasonable convention that handles > that case well. > > The other situation is where you add an import to an environment that > already has code in it, introducing a name clash. There are three > possible options: > > 1. Create an alias for the binding being imported. We know that the > code already in the environment doesn't refer to it, so we just give > it a new name and we're in good shape. > > 2. Create an alias for the existing binding. It requires updating the > existing code to use the new name. If we have the RB installed, that's > easy; if not, we can at least bring up a browser with all the > references to the old name so the user can find them easily. > > 3. Alias both bindings. This gets us to where we'd have been if we'd > done the import before any code was written. Again it requires > updating all the existing references. Or, do nothing at all. The new binding would simply be shadowed. > We could use auto-aliasing only with empty environments, or have a > (configurable?) policy for handling name clashes, or just ask the user > what to do. It doesn't have to be decided now; we'll cross that bridge > when we get to it. > >> In your Seaside / Magma example, could you leave one Session just as >> Session, and have the other aliased? > > Sure. > >> Maybe the auto-aliaser would need to detect that the new code >> references a dual-defined class, and asks which one it should use? in >> other words, 'partially' auto alias. > > No. Auto aliasing would happen a namespace is being imported into an > environment, not when code is being loaded. The idea is to resolve all > ambiguities when constructing the environment, so that the compiler > and dev tools can deal with a simple, one-to-one mapping from names to > classes. > > Colin Maybe aliasing isn't the best solution to resolve ambiguities? What if there was no aliasing, but names would strictly be resolved in order of import? That is exactly as your implementation currently works, right? To refer to a shadowed global, one would have to explicitly request it from its environment, e.g.: self environment: 'Magma' at: #Session I like this better than aliasing because it shows what's happening when actually using it, not somewhere hidden at the import. It's even less magic :) At least that's what I would strive for in an initial implementation. We can add bells and whistles later. - Bert - |
+1. Adding convenience later sounds like a good strategy. It means there is time to find out what the actual patterns are once people start using it. Cheers, - Andreas |
In reply to this post by Bert Freudenberg
On Fri, Jun 29, 2012 at 3:32 AM, Bert Freudenberg <[hidden email]> wrote:
> Or, do nothing at all. The new binding would simply be shadowed. Ah, good point. That's a fourth option. > Maybe aliasing isn't the best solution to resolve ambiguities? > > What if there was no aliasing, but names would strictly be resolved in order of import? That is exactly as your implementation currently works, right? Yes, although so far I've only imported Smalltalk, not other environments. > To refer to a shadowed global, one would have to explicitly request it from its environment, e.g.: > > self environment: 'Magma' at: #Session > > I like this better than aliasing because it shows what's happening when actually using it, not somewhere hidden at the import. It's even less magic :) I don't like this at all. It's equivalent to a fully qualified class reference, ala VisualWorks Magma.Session or Göran's Magma::Session. Avoiding those is the whole point of this design. Environments should be invisible to the code inside them. > At least that's what I would strive for in an initial implementation. We can add bells and whistles later. Yes, autoaliasing should certainly wait. As Andreas said, that'll let us see what aliasing strategies work well in practice. We can even hold off on manual aliasing until compiler and tool support is in place. (Not that aliasing is particularly hard to implement.) That said, I don't want give up the idea of a completely flat namespace from the point of view of application code. That's throwing the baby out with the bathwater. It should appear to Application, that the authors of Seaside and Magma got together and coordinated their class names so that there were no prefixes and no clashes. Colin |
On 29.06.2012, at 16:40, Colin Putney wrote: > On Fri, Jun 29, 2012 at 3:32 AM, Bert Freudenberg <[hidden email]> wrote: > >> Or, do nothing at all. The new binding would simply be shadowed. > > Ah, good point. That's a fourth option. > >> Maybe aliasing isn't the best solution to resolve ambiguities? >> >> What if there was no aliasing, but names would strictly be resolved in order of import? That is exactly as your implementation currently works, right? > > Yes, although so far I've only imported Smalltalk, not other environments. > >> To refer to a shadowed global, one would have to explicitly request it from its environment, e.g.: >> >> self environment: 'Magma' at: #Session >> >> I like this better than aliasing because it shows what's happening when actually using it, not somewhere hidden at the import. It's even less magic :) > > I don't like this at all. It's equivalent to a fully qualified class > reference, ala VisualWorks Magma.Session or Göran's Magma::Session. > Avoiding those is the whole point of this design. Environments should > be invisible to the code inside them. How is this different from having to use "MagmaSession", if the class is actually named "Session", in the Magma environment? The code *has* to differentiate if it needs to use the same global from two different environments. - Bert - >> At least that's what I would strive for in an initial implementation. We can add bells and whistles later. > > Yes, autoaliasing should certainly wait. As Andreas said, that'll let > us see what aliasing strategies work well in practice. We can even > hold off on manual aliasing until compiler and tool support is in > place. (Not that aliasing is particularly hard to implement.) > > That said, I don't want give up the idea of a completely flat > namespace from the point of view of application code. That's throwing > the baby out with the bathwater. It should appear to Application, that > the authors of Seaside and Magma got together and coordinated their > class names so that there were no prefixes and no clashes. > > Colin |
On Fri, Jun 29, 2012 at 7:47 AM, Bert Freudenberg <[hidden email]> wrote:
>> I don't like this at all. It's equivalent to a fully qualified class >> reference, ala VisualWorks Magma.Session or Göran's Magma::Session. >> Avoiding those is the whole point of this design. Environments should >> be invisible to the code inside them. > > How is this different from having to use "MagmaSession", if the class is actually named "Session", in the Magma environment? > > The code *has* to differentiate if it needs to use the same global from two different environments. Yes, the code has to differentiate. But we do it by having two names for the same class, rather than having to classes with the same name. To Seaside it's Session, to Application it's SeasideSession. As far as Application is concerned, it's a happy coincidence that Seaside and Magma don't have any name clashes. Today we achieve that lack of clashes by coordinating with other developers. Chris agrees not to create any classes that start with 'WA' and the Seaside team agrees not to create any classes that start with 'Ma'. With environments, Chris doesn't have to coordinate with the Seaside team and the policy doesn't have to set in advance. The developer of Application gets to set the policy for how his dependencies will be handled. He might decide that he doesn't need to refer to Magma sessions directly and let that class be shadowed, or that Magma sessions are really more like Engagements, or that MagmaSession is nicer or that MaSession is fine. Maybe he wants to use WA and Ma to remind himself where a class comes from, or maybe he would rather names be clean and simple. But whatever he decides, he writes Application code as though the community had conspired to make his particular use case easy. Once Application is written, it depends on certain classes having particular names, but it doesn't have any idea how its environment is organized. Even if Seaside 4.0 is organized differently, we can make a different set of imports and aliases to provide Application with the environment that it needs. Colin |
In reply to this post by Colin Putney-3
On 26 June 2012 03:11, Colin Putney <[hidden email]> wrote:
> Hi all, > > There's an old joke in the Squeak community about how we have a flame > war about namespaces every few years and only newbies bring up the > topic casually. Well, it seems we're overdue, so I'd like to do my bit > for the community by keeping up the tradition. > > I propose that Squeak 4.4, or perhaps 4.5, include support for more > than one class with the same name. This will be a modest proposal, > based on extending Dan's work on environments. The basic idea is this: > an Environment is an object that implements a policy for binding names > to objects during compilation. > > This is in direct contrast to the Namespace implementation that > VisualWorks uses. In VW the global namespace is divided up into a > dot-delimited hierarchy, and there are mechanisms for resolving > unqualified names. Environments, in contrast, are more like Newspeak > modules. There's no universal mapping of names to objects, but rather > different "points of view," where names resolve differently depending > on which environment you're in. > > The simplest and most common use for environments is to allow two > classes with the same name to peacefully co-exist. We currently work > around this problem with classname prefixes - MC in Monticello or WA > in Seaside. With environments, we can do away with prefixes by > creating a separate environment for each prefix that we're currently > using. > > An interesting example of this case that I've run across lately is > Xtreams. In the original VW version, there's only one class that's > publicly visible: the Incomplete exception that gets raised when a > stream operation fails. The rest of the public API to the library is > provided as extensions to classes in the base system. There's actually > no need for code that uses Xtreams to refer to any of the stream > classes. That leaves a lot of room for the implementation of Xtreams > to change while keeping the API stable, and I'd like to be able to > take advantage of this design in Squeak. With Environments, that's > possible: we just create an environment to hold the Xtreams classes, > import the base system, compile Xtreams, export Incomplete, and import > Xtreams into our application's environment. > > I've done a preliminary implementation, which lets me create an empty > environment, file code into it and then browse and modify it with a > standard browser. There's still lots of work to do, but I want to get > a consensus among the core developers before tackling it. That way the > changes can happen in the trunk and we don't have to worry about a > difficult integration later. > > I've attached a couple of screenshots. The first shows two browsers, > one browsing the base image, the other browsing an environment with > Seaside 3.0 loaded. The second is an explorer on the Seaside > environment. The image where they were taken is available for download > here: > > http://www.wiresong.ca/downloads/Environments.zip > > > Flame away! One thing I didn't try when I looked at the above image was run the tests. They mostly fail because setUp uses "env := Environment new" instead of "env := Environment name: 'Some Name'" and so the lookup instvar isn't set. You probably already know this. I'd like to run an experiment with Environments, actually: on binding access, lazily create a subclass of the thing accessed. Initially, that would mean that in an Environment called 'Foo' when you say "Object new" the Environment makes a FooObject in the global space and exposes it as Object to the contained code. When you load a package that contains extensions to Object, they actually appear in FooObject, meaning that code outside the Environment doesn't see the extensions. This doesn't solve the problem of clashing extensions when you import two environments with a common extension, but it does mean that loaded code goes into a sandbox. The code being loaded could still "true become: false" but "Smalltalk at: #Object put: nil" would only affect the loaded code. Is there a place where we can get our hands on Monticello packages? Or does Environments require some bootstrapping? frank |
In reply to this post by Stéphane Rollandin
Back in the Usenet news era it would be You're all a bunch of fags going to hell. No, better: Oo programmers are ... as above. That was when AOL connected to the Internet. Now *those* were flame wars! On Jun 27, 2012 12:39 PM, "Stéphane Rollandin" <[hidden email]> wrote:
Well there's a fine kettle of fish for you. Someone attempts to light up |
In reply to this post by Frank Shearar-3
On Wed, Jul 4, 2012 at 4:41 AM, Frank Shearar <[hidden email]> wrote:
> One thing I didn't try when I looked at the above image was run the > tests. They mostly fail because setUp uses "env := Environment new" > instead of "env := Environment name: 'Some Name'" and so the lookup > instvar isn't set. You probably already know this. Well, I knew it was buggy… :-) > I'd like to run an experiment with Environments, actually: on binding > access, lazily create a subclass of the thing accessed. Initially, > that would mean that in an Environment called 'Foo' when you say > "Object new" the Environment makes a FooObject in the global space and > exposes it as Object to the contained code. When you load a package > that contains extensions to Object, they actually appear in FooObject, > meaning that code outside the Environment doesn't see the extensions. > > This doesn't solve the problem of clashing extensions when you import > two environments with a common extension, but it does mean that loaded > code goes into a sandbox. The code being loaded could still "true > become: false" but "Smalltalk at: #Object put: nil" would only affect > the loaded code. Interesting. I'm not sure if you'd actually have to create FooObject globally. It could call ClassBuilder directly, and bind the resulting class as Object. You might also have to create the alias FooOriginalObject (or something) so that the browse could display a sane class definition. (Otherwise you'd get 'Object subclass: #Object…') > Is there a place where we can get our hands on Monticello packages? Or > does Environments require some bootstrapping? Yeah, Environments requires bootstrapping, but I haven't figured out how to do it yet. The image I posted is the one I did my hacking in, and getting it to that state involved frequent saving and lots of restarts. It's just a proof of concept. That said, the MC packages are here: http://source.wiresong.ca/seed/ Colin |
On 5 July 2012 00:28, Colin Putney <[hidden email]> wrote:
> On Wed, Jul 4, 2012 at 4:41 AM, Frank Shearar <[hidden email]> wrote: > >> One thing I didn't try when I looked at the above image was run the >> tests. They mostly fail because setUp uses "env := Environment new" >> instead of "env := Environment name: 'Some Name'" and so the lookup >> instvar isn't set. You probably already know this. > > Well, I knew it was buggy… :-) > >> I'd like to run an experiment with Environments, actually: on binding >> access, lazily create a subclass of the thing accessed. Initially, >> that would mean that in an Environment called 'Foo' when you say >> "Object new" the Environment makes a FooObject in the global space and >> exposes it as Object to the contained code. When you load a package >> that contains extensions to Object, they actually appear in FooObject, >> meaning that code outside the Environment doesn't see the extensions. >> >> This doesn't solve the problem of clashing extensions when you import >> two environments with a common extension, but it does mean that loaded >> code goes into a sandbox. The code being loaded could still "true >> become: false" but "Smalltalk at: #Object put: nil" would only affect >> the loaded code. > > Interesting. I'm not sure if you'd actually have to create FooObject > globally. It could call ClassBuilder directly, and bind the resulting > class as Object. You might also have to create the alias > FooOriginalObject (or something) so that the browse could display a > sane class definition. (Otherwise you'd get 'Object subclass: > #Object…') Oh, definitely! Right _now_ ClassBuilder uses the SystemChangeNotifier to announce the birth of a new class. If you do the naive thing (as I describe above), even if you try add the new class to your own SystemDictionary, you end up with a reference in Smalltalk globals. That has... interesting effects. That's why I suggest a FooObject _for now_ because while it spams Smalltalk globals, it does so in a reasonably safe manner. Then we can make SystemChangeNotifier work per environment, and THEN we can stop making FooObjects. >> Is there a place where we can get our hands on Monticello packages? Or >> does Environments require some bootstrapping? > > Yeah, Environments requires bootstrapping, but I haven't figured out > how to do it yet. The image I posted is the one I did my hacking in, > and getting it to that state involved frequent saving and lots of > restarts. It's just a proof of concept. Mm, it's a proof of concept on which I want to hack :) > That said, the MC packages are here: http://source.wiresong.ca/seed/ Thanks! frank > Colin > |
In reply to this post by Frank Shearar-3
On Wed, 4 Jul 2012, Frank Shearar wrote:
snip > I'd like to run an experiment with Environments, actually: on binding > access, lazily create a subclass of the thing accessed. Initially, > that would mean that in an Environment called 'Foo' when you say > "Object new" the Environment makes a FooObject in the global space and > exposes it as Object to the contained code. When you load a package > that contains extensions to Object, they actually appear in FooObject, > meaning that code outside the Environment doesn't see the extensions. This wouldn't work, because if you add an extension method to Object, then you have to create a copy of all classes of the global environment which are accessed from your environment (plus their superclasses up to Object). But in practice this doesn't work, because the VM has some expectations about some objects/classes (true, false, nil, LargePositiveInteger, etc). Also you'd have to convert objects which are passed from one environment to another, otherwise code like foo class == bar class would break. Levente > > This doesn't solve the problem of clashing extensions when you import > two environments with a common extension, but it does mean that loaded > code goes into a sandbox. The code being loaded could still "true > become: false" but "Smalltalk at: #Object put: nil" would only affect > the loaded code. > > Is there a place where we can get our hands on Monticello packages? Or > does Environments require some bootstrapping? > > frank > > |
On 5 July 2012 10:30, Levente Uzonyi <[hidden email]> wrote:
> On Wed, 4 Jul 2012, Frank Shearar wrote: > > snip > > >> I'd like to run an experiment with Environments, actually: on binding >> access, lazily create a subclass of the thing accessed. Initially, >> that would mean that in an Environment called 'Foo' when you say >> "Object new" the Environment makes a FooObject in the global space and >> exposes it as Object to the contained code. When you load a package >> that contains extensions to Object, they actually appear in FooObject, >> meaning that code outside the Environment doesn't see the extensions. > > > This wouldn't work, because if you add an extension method to Object, then > you have to create a copy of all classes of the global environment which are > accessed from your environment (plus their superclasses up to Object). In which you just lazily create those, even though my naive idea's now a lot more expensive. You almost might as well just spawn a new image. > But > in practice this doesn't work, because the VM has some expectations about > some objects/classes (true, false, nil, LargePositiveInteger, etc). Right. So what you're saying is that if you want proper modules, you need VM support. > Also > you'd have to convert objects which are passed from one environment to > another, otherwise code like > > foo class == bar class > > would break. How would you pass objects between environments? What does it mean to pass objects between environments? frank > Levente > > >> >> This doesn't solve the problem of clashing extensions when you import >> two environments with a common extension, but it does mean that loaded >> code goes into a sandbox. The code being loaded could still "true >> become: false" but "Smalltalk at: #Object put: nil" would only affect >> the loaded code. >> >> Is there a place where we can get our hands on Monticello packages? Or >> does Environments require some bootstrapping? >> >> frank >> >> > |
On Thu, Jul 5, 2012 at 8:11 AM, Frank Shearar <[hidden email]> wrote:
> Right. So what you're saying is that if you want proper modules, you > need VM support. Not necessarily. For the next experiment, I've been thinking about implementing selector spaces. Here's how it might work: • Each environment has its own Symbol table • The scanner delegates interning of symbols to the environment • When interning a symbol the environment searches its imports • If no imported environment has the symbol, it creates one in its own symbol table This would mean that an environment could add extension methods to classes in other environments, without colliding with other extensions. It would also make it possible to create "private overrides" where only code in that environment would use the override. It might be useful for sandboxing, but might not be sufficient. I want to stress, though, that this is *not* part of the current proposal—it's just some ruminating about what the next experiment might be, someday. Colin |
On 5 July 2012 18:15, Colin Putney <[hidden email]> wrote:
> On Thu, Jul 5, 2012 at 8:11 AM, Frank Shearar <[hidden email]> wrote: > >> Right. So what you're saying is that if you want proper modules, you >> need VM support. > > Not necessarily. For the next experiment, I've been thinking about > implementing selector spaces. Here's how it might work: > > • Each environment has its own Symbol table > • The scanner delegates interning of symbols to the environment > • When interning a symbol the environment searches its imports > • If no imported environment has the symbol, it creates one in its own > symbol table Does that mean that given libraries Foo and Bar that both define Object >> #thing, you provide some conflict resolution (say, {#thing1 -> (Foo at: #Object) >> #thing.}), and then in your Environment you have some method doIt > This would mean that an environment could add extension methods to > classes in other environments, without colliding with other > extensions. It would also make it possible to create "private > overrides" where only code in that environment would use the override. > It might be useful for sandboxing, but might not be sufficient. > > I want to stress, though, that this is *not* part of the current > proposal—it's just some ruminating about what the next experiment > might be, someday. And while I'm drooling about the idea of a modular Squeak environment, what can I/we do to help this first stage? > Colin > |
Sigh. Send accident there.
On 5 July 2012 20:41, Frank Shearar <[hidden email]> wrote: > On 5 July 2012 18:15, Colin Putney <[hidden email]> wrote: >> On Thu, Jul 5, 2012 at 8:11 AM, Frank Shearar <[hidden email]> wrote: >> >>> Right. So what you're saying is that if you want proper modules, you >>> need VM support. >> >> Not necessarily. For the next experiment, I've been thinking about >> implementing selector spaces. Here's how it might work: >> >> • Each environment has its own Symbol table >> • The scanner delegates interning of symbols to the environment >> • When interning a symbol the environment searches its imports >> • If no imported environment has the symbol, it creates one in its own >> symbol table > > Does that mean that given libraries Foo and Bar that both define > Object >> #thing, you provide some conflict resolution (say, {#thing1 > -> (Foo at: #Object) >> #thing.}), and then in your Environment you > have some method > > doIt doIt ^ self thing1 that the scanner turns that into a #thing sent to Foo's Object? frank >> This would mean that an environment could add extension methods to >> classes in other environments, without colliding with other >> extensions. It would also make it possible to create "private >> overrides" where only code in that environment would use the override. >> It might be useful for sandboxing, but might not be sufficient. >> >> I want to stress, though, that this is *not* part of the current >> proposal—it's just some ruminating about what the next experiment >> might be, someday. > > And while I'm drooling about the idea of a modular Squeak environment, > what can I/we do to help this first stage? > >> Colin >> |
In reply to this post by Frank Shearar-3
On Thu, Jul 5, 2012 at 12:41 PM, Frank Shearar <[hidden email]> wrote:
> Does that mean that given libraries Foo and Bar that both define > Object >> #thing, you provide some conflict resolution (say, {#thing1 > -> (Foo at: #Object) >> #thing.}), and then in your Environment you > have some method > > doIt > ^ self thing1 Something like that. You'd do some kind of aliasing, like with globals, but I don't think you'd specify how #thing1 would resolve to a compiled method (that would prevent dynamic message dispatch). Instead you might so something like {#thing1 -> #Foo}. Then the scanner would find Foo's version of #thing when it encountered #thing1. That would make decompilation show #thing instead of #thing1. Or you could do something exotic with name mangling and ObjectsAsMethods, or... well, this is why I don't want to get into it yet. :-) > And while I'm drooling about the idea of a modular Squeak environment, > what can I/we do to help this first stage? I think the first stage is to introduce Environment, and install an instance as "Smalltalk globals" instead of a SystemDictionary. Colin |
In reply to this post by Colin Putney-3
On 2012-07-05, at 19:15, Colin Putney wrote: > On Thu, Jul 5, 2012 at 8:11 AM, Frank Shearar <[hidden email]> wrote: > >> Right. So what you're saying is that if you want proper modules, you >> need VM support. > > Not necessarily. For the next experiment, I've been thinking about > implementing selector spaces. Here's how it might work: > > • Each environment has its own Symbol table > • The scanner delegates interning of symbols to the environment > • When interning a symbol the environment searches its imports > • If no imported environment has the symbol, it creates one in its own > symbol table > > This would mean that an environment could add extension methods to > classes in other environments, without colliding with other > extensions. It would also make it possible to create "private > overrides" where only code in that environment would use the override. > It might be useful for sandboxing, but might not be sufficient. Cool idea. Since the VM just cares about the identity of Symbols, we can have the same selector twice in one method dictionary. Each environment would send only the one from its own Symbol table. > I want to stress, though, that this is *not* part of the current > proposal—it's just some ruminating about what the next experiment > might be, someday. Yep. - Bert - |
On Thu, Jul 5, 2012 at 1:27 PM, Bert Freudenberg <[hidden email]> wrote:
IIRC the implementation of Selector (might be Symbol?) in David Simmons' AOS and S# systems is effectively two-level. A Selector is on object with two inst vars, one being its defining environment and the other being the selector's unique string (Symbol?). The latter is what we think of as a Symbol right now, so any two Selector (Symbol?) objects with the same sequence of characters have the same underlying unique string (Symbol?). Selectors are the keys in method dictionaries and the message selectors in compiled methods (and presumably are used in superclass names, but here I'm not familiar enough). David had some complex mechanism whereby selectors could match based on having the same underlying character sequence and choosing the shortest distances between their environments. This sounds complex, but the idea of boxing a Symbol so that there's a reference to its environment looks to me to be a useful one.
One could imagine using only boxed selectors for messages defined in a particular environment. This makes introspecting easy. A Symbol's environment would be the root environment; a Selector's would be e.g. that of its environment inst var.
Note that the VM doesn't (and shouldn't) care what objects are used for selectors; SmallIntegers can be used e.g. to save space.
Just 2¢
best, Eliot |
Free forum by Nabble | Edit this page |