Packages - basic intro and next step (sorry for long post)

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

Packages - basic intro and next step (sorry for long post)

gokr
Hey again!

Ok, sorry for all these repetitive posts about Packages but I want
everyone to feel that they *did* have a chance to affect the outcome
before it jumped in their face :)

So, we just managed to merge my last low level messing-abouts with
Package, so now packages can have properties and these properties gets
persisted in the MyPackage.js file and the MyPackage.st file too.

Let's rewind a bit so that all follow:

Packages
========

Amber has packages. A package in Amber is a collection of classes +
class extensions. A class extension is a "loose method" for a class in
another package. This mechanism works just like in Monticello.

This means that in Amber we do NOT have "class categories" - what you
see in the left most pane in the browser IS the Package.

On disk a package is represented as three different files, let's say
Kernel package:

        js/Kernel.deploy.js
        js/Kernel.js
        st/Kernel.st

The first one is a javascript file with the compiled Amber classes in
it. It does not contain the original Amber Smalltalk source code.

The second one is the "superset" of all these three - it has the
compiled Amber classes + the Amber Smalltalk source code and other meta
information. You can delete the other two files and still be a happy camper.

The last file is ONLY the Amber Smalltalk source code, in chunk format.
It can be compiled by the command line compiler amberc - to produce the
other two js files. Same goes here, you can delete the other two and
still be a happy camper.


Package properties
==================

First step in creating some loading mechanisms around packages would be
to reify (cool word) packages so that we can work with them in Smalltalk
and then add the ability to attach "meta information" to them.

These two steps have been done. This means that there is a class called
"Package" in the system and you can find instances of Package in various
ways, and ask them stuff etc.

For example, which package does class Number belong to?

        Number package
                ====> Kernel

How many classes is in Kernel package?

        (Smalltalk packageAt: 'Kernel') classes size
                ====> 35

What packages do we have?

        Smalltalk current packages
                ====>
                a Array (Kernel Canvas Compiler IDE SUnit Examples Benchfib Kernel-Tests)


Now, we also would like to attach meta information and have that meta
information persisted in the three files described above. That works
too, so now you can:

        (Smalltalk current packageAt: 'Kernel')
                propertyAt: 'version' put: '1.2

...and after this we can verify what properties we have:
       
        Number package properties
                ====>
                a Dictionary('version' -> '1.2')

...if we now commit the Kernel package, and take a look at Kernel.st we
find first line saying:

Smalltalk current createPackage: 'Kernel' properties: #{'version'->'1.2'}!

Thus, every package file will have such a first line declaring the
package and its properties using the Amber style literal Dictionary.

And in Kernel.js it looks like this:

smalltalk.addPackage('Kernel', {"version":"1.2"});


Now, if you have been following my steps you can reload the IDE and
verify that this did not disappear on us. :)


Next step
=========
So, now we can proceed to the next step, and this is where our code
ends. But I want to describe what I want to build. The idea is that a
given Package can list its dependencies *by name*. We are not going into
versions of packages at this point, and perhaps will never do - not
explicitly at least.

So if MyPackage depends on Foo and Bar I can do:

        (Smalltalk current packageAt: 'MyPackage')
                dependencies: #('Foo' 'Bar')

And checking properties it says:

        (Smalltalk current packageAt: 'MyPackage') properties


Hehe, ok, so obviously there is a bug here - we get the dependencies but
also some other stuff. Let's ignore that.

Now, this is the model I have in mind:

Build a package scanner mechanism that can read only the first line of a
package file so that we can get the properties without actually loading
a package.

Build a Resolver class that can fetch package files from either direct
URIs or simply by package name and then it will "look" in a ordered list
of places (yeah, kinda like CLASSPATH, but for packages).

Then we simply recurse, scan, and load the packages in reverse order. :)

These mechanisms should give us enough "rope" to start publishing
packages (just a URL and we can include it as a property so that we know
where "upstream" is) and we can publish repositories of packages (just a
URL where we can find an Index.html listing them all).

And then using the Resolver we should be able to find and load packages
using simple dependencies.

regards, Göran