Note: Not all these changes survived after Critical Mass cm3 was open-sourced.
Date: Tue, 08 Apr 1997 10:15:44 -0500
To: farshad@cmass.com
From: Bill Kalsow <kalsow@cmass.com>
Subject: Re: List of changes to the runtime
Cc: kalsow@cmass.com
Here's the list: (as much as I can remember from my notes...)
1) Modules can be added to the system at runtime. From C it looks
like this:
RTLinker__InitRuntime (argc, argv, envp, instance(*Win32 GUI*));
RTLinker__AddUnit (Foo_I3);
"InitRuntime" needs to be called once, before any calls to "AddUnit".
The call to "AddUnit" above adds "Foo.i3" and anything it imports
or that exports it to be added to the running system. That means
their types are registered, brands are checked, main bodies are
called, etc... ("Foo_I3" is a procedure generated by the compiler
when it compiled "Foo.i3".)
Of course, that means its possible to add types on the fly as well.
The details are messier.
2) Exceptions can be marked "implicit" by preceding their declaration
with the <*IMPLICIT*> pragma. An implicit exception can be raised
by a procedure even though it's not named in the procedure's RAISES
clause. ***This changes the language semantics of RAISES clauses.***
Also, the compiler does not warn about unhandled implicit exceptions.
3) Checked runtime errors (NIL fault, array index out of bounds, ...)
are signaled via the implicit exception "RuntimeError.E".
4) NEW() raises RuntimeError.E if it cannot allocate more memory.
5) The RTAllocator.New*() routines raise RTAllocator.OutOfMemory,
a new, non-implicit exception.
6) RTException.SetBackstop() can be used to override the default
handling of "unhandled exceptions". The default is to raise
RuntimeError.E(RuntimeError.T.UnhandledException), and then if
that exception isn't handled, to crash and burn...
7) The layout of OBJECTs is compatible with COM. The first word
of the object is a pointer to its method list (vtable in COM-speak).
The first word of the method table points to the procedure implementing
the first method, and so on ...
8) Unicode support has been added.
There is a new builtin type, WIDECHAR. WIDECHARs occupy 16
bits of storage. Like CHAR, WIDECHAR is an enumeration with
compiler-recognized literals. The new literals are like
CHAR literals, but are preceded by "W". For example, "W'A'"
is the 16-bit WIDECHAR with the ordinal value 65. Octal escape
sequences in WIDECHAR literals must specify 16 bits with 6
octal digits. For example, W'\000101' represents W'A'.
Hex escape sequences are also allowed, they are introduced
with "\x" and must also specify 16-bits with 4 hex digits. So
one more time, W'A' can be specified as W'\x0041'. Hex escape
sequences are also allowed in CHAR literals. There, they must
specify 8 bits with 2 hex digits. The hex version of 'A' is
'\x41'.
TEXT literals preceded by "W" are instantiated by the compiler
with WIDECHAR characters. For example, W"Hello World". TEXTs
are implemented as Modula-3 OBJECTs. So, they can contain
CHARs or WIDECHARs, or even a combination of the above. For
example, "Hello " & W"World" contains both types of character.
The Text interface includes new procedures that allow
clients to deal with CHARs or WIDECHARs as they wish. For
example, "Text.GetWideChar(t: TEXT; i: CARDINAL): WIDECHAR" is
the parallel extension of "Text.GetChar". The Text implementation
automatically converts CHARs to WIDECHARs as needed by zero-extending
the 8-bit values to 16-bit values. It converts WIDECHARs to
CHARs by dropping the high-order 8-bits of the 16-bit value.
"Text.Length" returns the number of characters, not 8-bit bytes
or 16-bit words. "Text.Equal", "Text.Compare", and "Text.Hash"
operate internally by extending all characters to their
corresponding 16-bit values.
Because TEXTs are objects, not REF ARRAY OF CHAR, they can
be implemented in many more exotic forms. For example, in the
new system the concatentation of two texts doesn't copy their
characters, it simply points to the the two texts.
The new TextClass interface specifies what it takes to be a TEXT.
"M3toC.TtoS()" no longer makes sense. In general, it's not possible
to convert an M3 TEXT to a C string without copying the characters.
"TtoS" has been replaced by "SharedTtoS" and the corresponding
"FreeSharedS". If "SharedTtoS" detects a flat C-compatible
literal, it returns the pointer to that string. Otherwise, it
copies the string and returns the address of the new storage.
"FreeSharedS" releases any storage acquired by "SharedTtoS".
The full set of libraries hasn't been converted. Libm3 and m3core
are fixed. Trestle, VBTkit, Obliq, Netobj, ... have not. Because
of the automatic internal 8-bit<->16-bit conversions, these other
libraries will continue to work, they will just ignore the high-order
8 bits of any 16-bit characters in the TEXTs they happen to encounter.
9) "Compiler" is a new built-in interface like "Word".
"Compiler.ThisFile()" returns a TEXT containing the name of the
source file containing the call. "Compiler.ThisPath()" returns a
path from the current directory to the source file containing the
call. "Compiler.ThisLine()" returns the source line number
containing the call. "Compiler.OS" is the enumeration "{POSIX, WIN32}".
"Compiler.ThisOS" is a constant Compiler.OS value indicating
where the source was compiled. "Compiler.Platform" is an
enumeration, "{AIX386, ALPHA_OSF, ...". "Compiler.ThisPlatform"
is a Compiler.Platform constant indicating where the source
was compiled. "Compiler.ThisException()" returns a pointer
to runtime information about the exception current being handled.
Compiler.ThisException can only be called from a TRY-FINALLY
or TRY-EXCEPT handler.
10) The <*ASSERT*> pragma can carry user-defined messages. The new
syntax is:
<*ASSERT condition [ ("," | WITH) msg ] *>
Where "condition" is a BOOLEAN value as before and "msg" is
a TEXT value.
11) There is a <*DEBUG*> pragma with the following syntax:
<*DEBUG condition [ ("," | WITH) msg {, msg} ] *>
<*DEBUG [ msg {, msg } ] *>
<*DEBUG*> pragmas may appear anywhere that statements may appear.
If "condition" is present, it must be a BOOLEAN. If "condition"
is "TRUE" or missing, the "msg"s are printed.
"RTDebug.RegisterHandler()" can be used to override the default
printing of debug messages.
12) The built-in type MUTEX is implemented as an OBJECT with "acquire"
and "release" methods. Clients that override those methods can
change the behavior of LOCK statements.
13) "RTHeapRep.max_heap_size" can be set to limit the size of the
heap. If it is set to a non-negative value and the collector
cannot find enough storage to satisfy an allocation request
and the heap is already at least "max_heap_size" bytes, the
heap will not be extended and the allocation request will
fail. Otherwise, the heap will be extended to satisfy the
allocation request.
- Bill
___________________________________________________________________
Bill Kalsow E-mail: kalsow@cmass.com
Critical Mass, Inc. WWW: http://www.cmass.com/people/kalsow/