After much pain mucking about in namespaces, I finally managed to load GemStone code saved in Store using atomic loading.
Atomic loading first loads code into a temporary namespace called the shadow namespace. Once everything is compiled there and it looks good, the system is re-compiled into the real namespace and the shadow namespace disappears.
With GemStone code, I thought I had everything setup to compile the code into the shadow namespace but when I did the actual compile, the code ended up in the real namespace right away. This is bad because in the shadow world, the system would add the compilerClass and classCompilerClass methods to tell the shadow class what the compiler is. You don't want to move these methods into the real namespace because it would cause crashes - which it did.
To allow me to quickly see what was going on, I wrote a tool that simply showed a tree view with a portion of the namespace hierarchy that I was interested in along with the shadow hierarchy. It also showed the identityHashes of the namespaces so I could quickly tell what namespace I was looking at in an inspector. If the namespace contained shared variables or classes, it would show those in the tree and if the classes had methods, it would show those as well. Here's what it looked like.
Now for the problem. When you login to GemStone as a user (for example, David), GemKit creates a namespace for you called Root.GemStone.AllUsers.David. It also aliases this as Root.GemStone.CurrentUser. You can see that in the above image.
When you create the shadow environment, Store creates a mimic of the namespace structure. Since CurrentUser wasn't marked as a namespace link, Store didn't create it in Shadow. Ok, fair enough. I augmented the system to create CurrentUser in the shadow namespace. Sadly, that wasn't enough to fix the problem.
Now when I try to compile, the system locates Root.GemStone in the shadow namespace (so far so good) and asks it to resolve the symbol #UserGlobals. This is where it will put the class it's compiling. UserGlobals isn't in GemStone directly but rather in CurrentUser which is in the imports of GemStone. The problem: The imported namespace CurrentUser is coming from the real environment instead of the shadow environment. It finds UserGlobals in the real world and compiles the class directly there.
Aaarg - ok, I go and smash the imports in the shadow GemStone namespace to point to the CurrentUser in the shadow. Now it complains about a method conflict during the install. When you try to move the shadow classes to the real environment, you must first move the class then move the methods. When you move a GemStone class to the real world, you automatically get a class method called gsst_definition. When we try to move the gsst_definition method from the shadow world to the real world, the system detects that there's a conflict and stops.
As it turns out, you have to change both imported namespaces in the shadow GemStone to point to the shadow and you also need to change the imported namespaces in the shadow GemStone.Globals to point back to the shadow GemStone instead of the real GemStone.
<sigh> After all that, atomic loading works with GemStone code. Yay! I think I'll pop a bottle of bubbly and share it with my wife tonight.
For my next challenge: Cincom switched Store to use Glorp instead of the older direct mechanism. GemKit has tools which are coded for the old mechanism and need to be modified to work with Glorp.
Friday, December 16, 2011
Sunday, December 11, 2011
Space Wars game update
I did some more work on the game I described in my last post. New features:
- Multiple enemy ships
- Ships disappear when hit
- Sound effects on fire
- Planets in the background
- Display of number of ships left
- When all ships are destroyed, a new round starts with 10 more ships
Friday, December 9, 2011
Space Wars game in Smalltalk
My 11 year old son recently asked me to teach him how to program so he can write his own games. Unfortunately, the kind of game he has in mind is a first-person shooter which isn't exactly the easiest way to teach an 11 year old how to program.
We talked about different kinds of games we could write. He had no interest at all in text games like "20 questions" or "guess a number", so I told him about a game I wrote on my old 1802 computer back in the early 1980's. It was based on the Battlestar Galactica TV series that I was watching at the time. You would fly around a star field shooting at Cylon ships. Tyler thought that sounded fun so we started writing it in Smalltalk.
The video below shows our progress so far. I actually wrote most of it and I'm slowly explaining to him how it works. It's piqued his curiosity, however. So far, you can fly around and shoot at ships. The ships don't explode yet, but it still shows some good progress.
We talked about different kinds of games we could write. He had no interest at all in text games like "20 questions" or "guess a number", so I told him about a game I wrote on my old 1802 computer back in the early 1980's. It was based on the Battlestar Galactica TV series that I was watching at the time. You would fly around a star field shooting at Cylon ships. Tyler thought that sounded fun so we started writing it in Smalltalk.
The video below shows our progress so far. I actually wrote most of it and I'm slowly explaining to him how it works. It's piqued his curiosity, however. So far, you can fly around and shoot at ships. The ships don't explode yet, but it still shows some good progress.