Squid Environments

Anthony Hannan ajh18 at cornell.edu
Mon May 5 19:12:17 UTC 2003


When importing modules into a module, where do we get the imported
modules from.  In Java, you specify the file path of imported class
modules.  In C, you just declare that certain functions are external but
you don't say where they come from.  The make just specifies a complete
set of modules, and hopefully what each module needs is satisfied by
some other module in the set.  If more than one satisfies the same
function need then the first one seen is used.

I don't like the Java solution because it relies on file structure which
is outside the object model.  And I don't like the C solution because it
requires a make.  Each make represents an isolated application that
don't integrate naturally.

So here is my proposal for Squid.  Modules are imported from
Environments.  An environment contains a set of variables plus inherits
from zero or more other environments, whose variables are also visible
recursively.  A environment may not shadow inherited variables.  If an
environment inherits from two different environment that define the same
variable name, it must alias them, so names are unique.

So for example, the Kernel environment may contain Object, Method, Class
and String, and the Collection environment may contain Array, Set and
String.  I may create my own environment that inherits from both of
these.  I would alias Collection-String as CollectionString and alias
Object-String as String.  When creating a module, I would import the
ones I need from my environment simply by giving their names in my
environment.  For example, "newModule imports: {Object. String}", which
would be executed with respect to my environment.

So a user always operates within some environment where all global vars
he executes are looked up.  The current user environment will be
maintained by development tools and given to the compiler when executing
do-its.

I would like to go one step further.  Instead of modules importing other
modules that are made visible to its methods.  Let methods import what
they need directly, so we don't have to explicitly specify imports.  A
method will import what it needs from the environment it is compiled it.
 To put another way the method just imports the whole compile
environment.  So instead of the compiler looking up global vars in the
module's imports which were given to it by some environment, the
compiler looks them up directly in the compile environment, skipping the
redundant import step.  The method won't need extra import pointers
because each global var and selector it binds to will know which module
and environment it comes from.

>From a source listing point of view (file-out), we group all code by
environment.  An environment specifies inherited environments then lists
all behaviors (modules), classes, and method defined in it.  Each method
specifies which behavior it is defined for and optionally which class. 
The behavior/class could be from an inherited environment as well as the
selectors it calls.  A behavior was a module, but since environments
also look like modules, I will drop the module term and only user
behavior or environment.

Actually, an environment looks a lot like a changeset.  The difference
is inherited environments (dependents) are specified and methods can't
clobber existing methods.  An environment may only rename/alias
inherited methods freeing up the original name for new methods.  Calling
methods compiled in new environment or its sub-environments will bind to
the new method, while calling methods compiled in the original
environment or its other sub-environments will bind to the original
method.  Calling methods in the new environment can bind to the orginal
method by calling the alias.  The new method is new, meaning classes
will have to define new methods if it wants to override it.  Its methods
that override the original will be associated with the alias.

So to summarize, Squid has three code entities: Environments, Methods,
and Classes.  An environment defines new methods and classes and
inherits from zero or more other environments forming layers of code. 
Methods can exist independently or be associated with a class.  Methods
have a two part name, the protocol (previously called behavior) name and
the function name.  When calling a method the protocol name must be
included if the function name by itself is ambiguous.  Methods that are
associated with a class (class methods) can not be called directly. 
Only independent methods (protocol methods) of the same name can
delegate to the class.

Cheers,
Anthony



More information about the Squeak-dev mailing list