-*- Mode: Text, Spell -*- Notes on how the runtime system is going to be setup. ;;;; Static and Dynamic runtimes. A static runtime is one in which definitions cannot change, very similar to what you get out of traditional compilers for static languages like C. Static runtimes support the entire Dylan language, but no incremental redefinition. To change anything, you have to go back and re-run the compiler/linker to produce a new executable. There also exists a ``dynamic runtime'' library that can be linked into a program. The resulting program is still a static runtime, except that it has a dynamic runtime environment embedded within it. The dynamic runtime is really just a set of routines that implement what people normally expect from a dynamic language: an interpreter, facilities for defining (and redefining) new module variables, etc. Definitions in the static runtime can be exposed to the dynamic runtime by invoking routines to make entries in the dynamic runtime's module system. But these definitions are only defined in the dynamic runtime, as the static runtime is just that, static. If one of these definitions is redefined, the redefinition only shows up in the dynamic environment. The class heterarchy is shared between both the dynamic and static runtimes. This is because objects have to be able to be freely passed back and forth, and anyone can call object-class. Therefore, any class in the program has to be valid in both runtimes. The easiest way to deal with this is to just use the same class system everywhere. Note: we are not really loosing anything here, because the static environment has to support ``(make ...)'' anyway, and this is just what the dynamic environment uses to create new class definitions. ### Problem: sharing the class system between the static and dynamic runtimes means that the static runtime also has to support redefinition. We could probably fake it for slots, but not if we want to be able to change the superclasses of a class. ;;;; The compiler's runtime and the compile-time environments. In Common Lisp, there is no difference between the compiler's runtime and the compile-time environments. This leads to lots of problems when trying to compile an incompatible change to the compiler: it is all too easy to break the running compiler by trying to compile the next version of it. To totally bypass this problem in Dylan, the compiler's runtime and the compile-time environments are disjoint. This is accomplished by running the compiler in a static runtime, and using a linked in dynamic runtime to instantiate the compile-time environment. ;;;; The development environment. If the only way to run a program was in a static runtime, we would be giving up a large amount of the advantages of developing in a dynamic language. To retain the advantages of using a dynamic language, it will be possible to run programs in a dynamic environment. This dynamic environment is implemented as a small stub static runtime that consists of nothing more then a dynamic runtime and some bootstrapping code. By loading the code being developed into this dynamic environment, we retain the ability to support incremental redefinition, etc. ;;;; Dynamic runtimes as an extension language. In addition to the two uses outlined above, it is possible to link the dynamic runtime into arbitrary programs. This effectively results in a full-featured extension language. Depending on how tightly integrated the application wants the extension language, it can either ignore the dynamic runtime except for random calls to eval, or it can make detailed queries about the definitions or data structures that have been set up in the dynamic runtime. It can also expose arbitrary amounts of functionality to the dynamic runtime by pre-establishing built-in definitions.