Porting
Chronos... ...To Earlier Versions of VisualWorks
Without any modifications or special procedures, Chronos.st will
file-in successfully to any VW 5.i3 or later VisualWorks image. Even
though the code itself is known to work in even earlier versions of VW
(although it has not been extensively tested in non-VW7x images,) the
file format of Chronos.st cannot be correctly interpreted by
VisualWorks images prior to VW 5i.3. For older versions of VW, it is
necessary to file out Chronos.st using a format that can be consumed by
the target image (or else to backport the ability to consume the modern
VW XML format into the target image.) The optional
“PARC Goodie”
FileOut30.pcl
parcel enables a modern VW image to file out packages or bundles in the
classic pre-5i “chunk format.” It also supports a
variety of non-VisualWorks file-out formats. However,
due to the lack of any meaningful support for “shared pool
Dictionary” file-out/file-in provided by the classic ST80/VW
“chunk” file-out format, it is necessary to define
two “shared pool” globals before filing-in Chronos
to a pre-5i image (or into a post 3x image if the file-in is in the
classic “chunk” file-out format.). This can be done
be evaluating the following “do it” in the target
image before filing-in Chronos:
Smalltalk
at: #Chronos put: Dictionary new;
at:
#ChronosConstants put: Dictionary new.
Note
to those porting into VW 5i.0, 5i.1 and 5i.2: When
filing-in a classic “chunk format” file containing
the Chronos codebase into a post-3x image, #Chronos
and #ChronosConstants must be
predefined as Namespaces (contained by #Smalltalk,) instead
of as Dictionaries. For pre-3x images, there is
insufficient ANSI
Smalltalk compatibility for Chronos to operate without errors. This can
be fixed by backporting ANSI Smalltalk compatibility methods and other
changes into the target image. For example, the following steps were
found to be necessary in order to get Chronos up and running in VW
2.5.1 (in addition to defining the two global shared pool Dictionaries,
as mentioned previously): - Add the
methods #on:do:
and #ensure:
to BlockClosure (behavior as specified by ANSI.)
- Add
the method #return:
to Exception (behavior as specified by ANSI.)
- Add
the methods #message
and #receiver
to Exception (behavior as specified by ANSI for the
MessageNotUnderstood Exception.)
- Define the
global #Error
with the value
“Object errorSignal”.
- Define
the global #MessageNotUnderstood
with the value “Object messageNotUnderstoodSignal”
Installing and using Chronos in pre-3x
VisualWorks
images is not recommended. …To Other
Smalltalk Environments
Chronos was architected and designed to be portable to other Smalltalk
systems. However, the author of Chronos strongly prefers to avoid doing
any
such ports himself (in spite of the fact that he did quite a bit of the
work needed to make the Squeak port fully functional; Squeak, after
all, has a special place in the world, and has no commerical vendor
behind it who is primarily responsible for its care and feeding.)
However, he is willing to serve as a consultant to
anyone who is seriously engaged in porting Chronos to some other
Smalltalk environment. To make a request for such aid, send an e-mail
to the
following address: {porting (at) chronos-st (dot) org}.
Hopefully, the following information will prove to be sufficient:
Firstly, you
may find the optional "contributed component" (a.k.a.
“Goodie”) FileOut30.pcl parcel to be useful. It
enables a modern VW image to file out packages or bundles in the
classic ST80 “chunk format.” It also supports a
variety of non-VisualWorks file-out formats. An even better option
would be the Rosetta Cross-Dialect
Smalltalk Code Interchange Tool. You can find it at
http://rosettast.sourceforge.net/. Secondly,
you will need to follow the procedure as given in the instructions to produce the Chronos Seed. [Link: http://www.chronos-st.org/Chronos-Seed.html]In
the case of
the VisualWorks version of Chronos, the packages <Passport-Kernel-VW>, <Chronos-VW-Extensions>
and <Chronos-ST80 (and VW) Compatibility> are VisualWorks
specific. Similar packages (with different
names) will probably be present in the versions of Chronos specific to
other Smalltalk flavors (assuming some sort of module system is even
supported at all.) Providing classes and methods that are
analagous to those in <Passport-Kernel-VW>
will be absolutely necessary. Providing code that is analagous to
that provided by the other two packages is entirely optional. The <Chronos-VW-Extensions>
package (or its analog) adds convenience methods ("syntactic sugar") to
classes in the Smalltalk base library, such as
Number>>hours, so that users (programmers) can code "-8
hours" instead of "Duration hours: -8." One issue to be
considered is whether any such methods would conflict with methods
already present in the target Smalltalk library (perhaps ones added by
a popular optional module/package.)
Although you won't want to
include the <Chronos-VW-Extensions>
package "as is" in your initial port, you should nevertheless strongly consider providing
analogous extensions in the target Smalltalk environment, unless such
methods would conflict with ones natively present (but on the other
hand, you might do it even then.)
Chronos itself does not need or use any of the extension methods in the
<Chronos-VW-Extensions> package, but applications or other libraries
that rely on Chronos will almost certainly expect them to be present.
The package <Chronos-ST80 (and VW)
Compatibility> is also VisualWorks-specific. It
extends certain Chronos classes with methods to make them type-compatible
with Core.Date, Core.Timestamp and Core.Time. If such
compatibility might be useful, you could include this package in your
port--although some of the implementation-logic assumes that the
classes Date, Timestamp and Time exist, and have the VW API.
Otherwise, you can safely remove this package. Chronos itself
does not depend on any of the extension methods in the <Chronos-ST80 (and VW)
Compatibility> package.
You
might also need or want to add methods to certain Chronos classes to
make them partially or fully type-compatible with whatever date/time
classes are native to the target Smaltlalk environment. One
piece
of advice here: Don't blindly believe the code comments in the host
environment's date/time code. For example, as of Squeak 3.8,
comments in the code of Squeak's Chronology library falsely claim that
the internal variables of a Chronology.DateAndTime instance specify the
date and time relative to Universal Time. The truth is that
those
variables specify local time--probably because the Squeak system clock
reports local time (Chronos can handle system clocks that report either
Universal Time or local time--read the class comments of
ChronosSystemClock and CalendarClock for more information.).
The class ChronosInstaller (in the <Chronos-Installation>
package) should not
be included in the file-in to be ported to the target Smalltalk image
(or library.) The ChronosInstaller class only
exists as a mechanism to launch the final initialization and
configuration of Chronos. It implements just two class-side methods,
#initialize and #postLoad:.
The #postLoad: class method is invoked when a VisualWorks parcel is
loaded. Outside of a VisualWorks environment, it is superfluous and
can be removed.
When ChronosInstaller is filed out of VisualWorks, VW will include a "do
it" that invokes "ChronosInstaller class>>initialize"
when
filed back in. You don't want that to happen pursuant to the very first
file-in of the Chronos code into the Smalltalk platform to which you
are porting. However,
the analogous “final
initialization and configuration” effect needs to be achieved
by the Chronos “file-in” (or whatever the
equivalent “distribution file” may be called) that
you distribute as the ported “load and go” version
of Chronos. How that is best achieved is platform-specific.
What needs to happen once the fully-ported and functional
Chronos
codebase has been "filed in" (or otherwise loaded in) to a new image is
that the message #install must be sent to the canonical instance of
ChronosEnvironment (i.e, the expression "ChronosEnvironment canonical
install" must be evaluated.) That's all that the
ChronosInstaller
class>>initialize method does. The ported distrubution
file you
prepare for Chronos needs to make that happen, but not until the
entire Chronos codebase has been loaded. Use whatever
mechanism
to get that done automatically that is appropriate for the Smalltalk
flavor involved.Thirdly,
it
may be useful (or even absolutely necessary) to port Chronos into a
non-VW Smalltalk environment using a staged approach. For example, it
may be advisable to only file-in/install the contents of the
<Passport-Kernel> package, fixing any problems or issues
encountered during the file-in, then implementing the necessary
platform-specific subclasses before
attempting to do the same with the remainder of the Chronos
codebase.
Fourthly,
it
may be necessary to add some “VisualWorks
Compatibility” and/or “ANSI-Smalltalk
Compatibility” code into the target image (or into the
standard library if the target environment is not image based.) Such
additions would likely include the following methods (probably not an
exhaustive list in some cases): - Object>>isSequenceable
- Obect>>respondsToArithmetic
(answer false, or '^self isNumber', or whatever may be appropriate)
- Number>>respondsToArithmetic
(answer true)
- SequenceableCollection>>readStream
- SequenceableCollection>>writeStream
- SequenceableCollection>>newReadWriteStream
- *>>literalArrayEncoding
- *
class>>decodeFromLiteralArray:
- Array>>decodeAsLiteralArray
The #literalArrayEncoding message needs
to be
understood by the instances of any class whose instances have a literal
representation that can appear in an Array literal (according to the
ANSI-Smalltalk Standard.) The class message #decodeFromLiteralArray:
needs to be understood by any class whose instances respond to
#literalArrayEncoding. An
issue that you hopefully won't have to deal with is the
interpretation of Array literals. Although the Chronos
codebase
includes Array literals that assume the
ANSI-Standard intepretation of Array literals (where #(nil) = (Array
with: nil),) the code that processes any such Arrays ensures that any
#nil, #true or #false values that are the elements of such an Array
literal are converted to the ANSI-mandated value. There are only two
usages of Arrays where this matters: ChronosPrintPolicy specification
Arrays and day-of-week policy Arrays (used by SemanticAnnualDateRule
objects.) Also
see the comments above regarding the necessary
steps and procedures for porting Chronos into ancient versions of
VisualWorks—the same issues may need to be resolved in
similar or analogous ways. Fifthly,
the
flip side of having to remove the platform-specific classes and
packages from the version of Chronos from which you are porting is that
you must then implement analogous classes and packages for your target
Smalltalk platform. At a minimum, you will
have to implement platform-specific subclasses of EnvironmentFacade, ResourcePathFacade, ChronosEnvironment,
ChronosSystemClock, and ChronosSystemFacade in order to get Chronos
working on your target Smalltalk platform. Be
advised that the class comments of
EnvironmentFacade, ResourcePathFacade, ChronosEnvironment,
ChronosSystemClock, and ChronosSystemFacade are essential reading for
anyone who wishes to port Chronos to a non-VisualWorks Smalltalk
environment. Most of the code that needs to be changed and/or
implemented de novo in order to effect a port of Chronos to another
Smalltalk system is specified and documented in those classes.
Sixthly,
for more information about what's involved in discovering what time
zone your code happens to be running in, and how to obtain the time
zone rules used by the host operating system to convert between
Universal Time and local time, you may find the essay
Discovering the Local Time Zone--Why It's a Hard Problem to
be a useful resource. Lastly, be
advised that Chronos is a work in progress. There will be new versions,
perhaps with design and/or API changes. You would be well advised to do
ports to other Smalltalk flavors so that the procedure is
repeatable--with far less work involved when porting subsequent
versions. The VW version is modularized into
StORE
packages so that most (and hopefully all) of the platform-specific code
resides in the packages Chronos-Environment and Chronos-System. The
best approach for porting is to try to limit changes to the Chronos
codebase to the classes in those packages (or to introduce subclasses
of the classes in those packages.) Where possible, any porting issues
that cannot be handled by changes to the Chronos-Environment and
Chronos-System packages should instead be handled by introducing
compatibility classes/methods into the target environment (especially
when the issue is a lack of ANSI compliance.) Modification
of the Chronos codebase for the
purpose
of making Chronos work correctly on the Smalltalk platform to which it
is being ported (other than as herein described,) is strongly not
recommended. Instead, please notify the author of Chronos of the
porting problem {send and e-mail to porting (at) chronos-st (dot) org}
so that a general solution to the problem can be designed and
incorporated into the mainline Chronos codebase. …To
Other Programming Languages
The author of Chronos expects that Chronos will be ported to other
programming languages, but currently has no intention of doing any such
ports himself. However, he may be willing in some cases to offer advice
and/or provide consulting services to anyone who attempts to port
Chronos to another programming language. |