TADS 3 Change History
For information on changes to the library (adv3), refer to the
Recent Library Changes list.
Changes for 3.0.8 (9/12/2004)
- The compiler now enforces unique naming for all of the modules in
a project. Using the same name for two (or more) modules can cause
problems, mostly because both modules would have the same filename for
their object files and thus one would overwrite the other. In the
past, when a module name conflict caused this kind of problem, the
compiler reported the errors caused by the name collision, but it
wasn't always easy to figure out that the name collision was the root
cause. To avoid this potential source of confusion, the compiler now
checks the entire project for module name collisions, and flags an
error if any collisions are found.
- The "file safety" levels have changed slightly to provide better
security against malicious game programs. First, level 2, which
formerly provided global read access but no write access, now instead
provides read/write access to the current working directory only (the
game isn't allowed any access to files outside of the working
directory). Second, the default safety level is now level 2. In the
past, level 1 (read from any file/write to current directory only) was
the default, which left open the possibility that a game could access
data outside of the working directory. A malicious game could
conceivably have exploited this by, for example, secretly copying
sensitive data to the game directory for later use by a coordinating
network worm, or by encoding the data in a hyperlink (displayed in an
HTML-enabled game) that takes the player to a spyware site when
clicked. The new default setting should effectively eliminate these
risks by barring access to any files outside of the working directory.
- Several of the system headers formerly lacked #include directives
for other headers they depended upon. This didn't cause problems most
of the time, since the necessary headers were usually included from
somewhere else anyway, but it meant that you had to include system
headers in the right order to avoid compiler errors. Each of the
system headers now explicitly includes any other headers it depends
upon, which ensures that each system header can be included in
isolation, and in any order with respect to other headers.
- The saveGame(), restoreGame(), and restartGame() intrinsic
functions can now be called from recursive VM invocations (that is,
from contexts where a call to an intrinsic function or method has
invoked a byte-code callback function, such as an anonymous function
passed to an iteration method on a collection object). This restriction
was needed in the distant past, but it's been vestigial since version
3.0.5a (when the save/restore mechanism was overhauled to exlude the
call stack and execution context from the saved state information).
Since the restriction is no longer necessary, it's now been removed.
- In the intrinsic function getLocalCharSet(), the new constant
CharsetFileCont can be used to retrieve the name of the character set
typically used for the contents of text files on the local system.
(Note that this is only the typical character set for text
files on the local system; there's no guarantee that any particular
file uses this character set. The actual character set of a given
text file is determined by the user and application that created the
file.)
- In tadsio.h, the constant CharsetFile (for use with the
getLocalCharSet() function) has been renamed to CharsetFileName. The
name change is to emphasize that the constnat refers to the character
set used in the local file system for names of files, as
opposed to the contents of text files.
- The compiler sometimes incorrectly complained about a missing
option argument when a "-x" option (with a valid argument supplied)
was used at the very end of a command line. This has been corrected.
- A bug in the compiler occasionally caused floating point constants
that included exponential ("E" suffixes) to be mis-parsed. When this
happened, one or more spurious, random extra digits of precision were
added to the end of the number's mantissa. This has been corrected.
Changes for 3.0.7 (6/12/2004)
There are no changes to the compiler or interpreter core in
this release. The only changes in the adv3 library and the
Windows HTML TADS interpreter.
Changes for 3.0.6q (5/9/2004)
There are no changes to the compiler or interpreter core in this
release. The only changes are in the adv3 library and the Windows
HTML TADS interpreter.
Changes for 3.0.6p (4/25/2004)
Changes for 3.0.6o (3/14/2004)
- The MIME type for saved position files has been changed to
"application/x-t3vm-state". The Windows installers have been updated
to reflect the new MIME type.
Changes for 3.0.6n (3/6/2004)
- The debugger now automatically includes "self" in the local
variable list whenever examining a frame in which "self" is valid.
- On Windows, the installers now add the MIME type for the compiled
game file type (.t3) and the saved position file type (.t3v) to the
system registry. This information can be helpful to applications,
particularly those that perform file transfers. (The MIME type for
a compiled game is "application/x-t3vm-image", and the type for
saved position files is "application/x-t3vm-save".)
- A compiler bug caused the compiler to crash when certain obscure
kinds of syntax errors occurred inside nested object definitions.
This has been corrected.
- A bug in the compiler caused the compiler to crash when it was
attempting to parse a one-line function or method that contained an
unclosed anonymous function. The problem was most likely to be seen
when the errant one-liner was the last thing in a source file. The
compiler now generates appropriate error messages and terminates
normally.
- A bug in the ByteArray class caused the VM to crash when a
ByteArray was used as a key in a LookupTable. This has been
corrected.
- A bug in the BigNumber class caused the VM to crash in some cases
when a string was used as the source value to construct a new
BigNumber. This should now work reliably.
- A bug in the debugger caused a crash when execution stopped
inside an anonymous function with no 'self' context. The most common
place to encounter this problem was at a run-time error in an
anonymous function defined inside a list, such as in an EventList
object. The problem has been corrected.
- On Windows, the Author's Kit installer failed to create the
samples\obj subdirectory. That subdirectory is required to build
the sample game (sample.t3m) included in the kit, so you had to
manually create the directory before you could compile the game.
The installer now automatically creates the directory.
- The BigNumber class incorrectly returned a result of zero when
dividing zero by zero. (This only happened when the dividend was
zero; for other dividend values, a divide-by-zero exception was
correctly thrown.) This now throws a divide-by-zero exception.
Changes for 3.0.6m (11/15/2003)
Note: 3.0.6l was a library-only release, so there was no system
release called 3.0.6l.
- The propNotDefined mechanism is now invoked when 'inherited'
fails to find a base class implementation of the method being
inherited. This works almost exactly the same way it does when
propNotDefined is invoked during a normal method/property call,
with only one difference: when 'inherited' fails to find a base
class property, it searches for a 'propNotDefined' using the
same search pattern it used to seek the original inherited
property. For example, consider this code:
export propNotDefined;
class A: object
propNotDefined(prop, [args]) { "This is A.propNotDefined\n"; }
;
class B: A
propNotDefined(prop, [args]) { "This is B.propNotDefined\n"; }
p1() { inherited(); }
;
main(args)
{
local x = new B();
x.p1();
}
When this program is run, the result displayed will be "This is
A.propNotDefined". B.p1() attempts to inherit the base class
definition of p1(); when it doesn't find an inherited definition, it
searches for propNotDefined() using the same search pattern it used
to find the inherited p1(). That is, the search starts with B's
superclass, because that's where the search for the inherited p1()
started from.
- The t3SetSay() intrinsic function now returns the previous default
output function or method. (The return value corresponds to the
argument value: if the argument sets a new function pointer, the
return value is the old function pointer; if the argument is a new
property ID, the return value is the old property ID.) This allows
code to save the old value for later restoration, if desired. In
addition, the new special argument values T3SetSayNoFunc and
T3SetSayNoMethod can be specified to cancel any existing default
output function or method, respectively, and the function returns
these values when needed to indicate the absence of a previous
setting.
- The t3SetSay() function now accepts an anonymous function as
the default output function. (In the past, only a regular named
function was acceptable.)
- When propNotDefined() is invoked, the interpreter now sets
'targetprop' to &propNotDefined. In the past, the interpreter
incorrectly set 'targetprop' to the property originally invoked.
This was incorrect; one important consequence was that it didn't
allow propNotDefined() itself to use 'inherited' to invoke the base
class's implementation.
- The compiler now automatically adds a property called
'sourceTextOrder' to each non-class object defined in a source file.
The value of the property is an integer giving the object's order in
the source file in which it's defined. This value is defined to
increase monotonically throughout a source file, so you can use it to
sort a collection of objects into the same order in which they appear
in the source text. This property is useful when you want to create
an initialized structure of objects (such as a list or a tree), and
you want objects within the structure to have the same order at
run-time that they have in the source text. In the past, there was
no straightforward way to guarantee source text ordering, because
the compiler and linker assign object ID's in arbitrary order.
This new property is guaranteed to reflect the original source
text order, so you can use it to initialize the run-time order.
Note that a 'modify' statement doesn't assign a new sourceTextOrder
to the underlying object; the original sourceTextOrder is retained
for a modified object. Note also that sourceTextOrder only tells you
the relative order of objects within a single source file; the compiler
resets the counter at the start of each new source file, so it's not
meaningful to compare sourceTextOrder values for objects in different
source modules.
- The toInteger() function now accepts an integer value as its
first argument. If the first argument is an integer, the function
simply returns the same value; the optional second argument (the
radix value) is ignored if present.
- The BigNumber constructor now accepts another BigNumber as the
source value. This creates a new BigNumber with the given source
value at an optional new precision, rounding the original value if
the new precision is less than that of the source value.
- The BigNumber method formatString() incorrectly returned an empty
string when formatting a fractional number if the maximum digit count
for formatting was insufficient to reach the first non-zero digit of
the fractional value. For example, 0.0001.formatString(3) returned
an empty string. The method now returns '0' for these cases.
- In most of the character-mode interpreters, if a line of
highlighted or colored text appeared just before a "MORE" prompt,
subsequent text was incorrectly highlighted or colored like the
line before the "MORE" prompt. This has been fixed.
- The character-mode interpreters very occasionally crashed on exit,
due to a bug in the termination code. This has been corrected.
- In most of the character-mode interpreters that support the
"-plain" mode, the interpreter is now more thorough about flushing
the standard output before stopping to read input. This makes the
plain mode interoperate better with other programs using "pipes"
and similar OS-specific input/output redirection. This change pertains
to the MS-DOS and Unix versions, and to any other platforms based on
the common character-mode layer (known technically as "osgen3").
- The rand() function now accepts a Vector as its argument.
A vector argument behaves the same as a list argument: the function
randomly chooses one of the elements of the vector and returns it.
- A bug in the TadsObject.createInstanceOf() method caused an
incorrect value to be left on the VM stack during creation of the
new object. This showed up as an incorrect argument value if a
method was invoked on the new object as part of the createInstanceOf()
expression. This has been corrected.
- The text-only interpreters incorrectly paid attention to a
<BODY> tag within an <ABOUTBOX> tag, setting any color
scheme specified in the <BODY> tag. This improperly set the
main text window to the color scheme intended only for use inside
the about-box. This no longer occurs.
- The forEachAssoc() method of the List and Vector intrinsic classes
incorrectly passed a zero-based index for the 'key' parameter to the
callback (that is, the first element was identified by index 0, the
second by index 1, etc., C-style). This should have been a one-based
index for consistency with all of the other indexing operations for
List and Vector. This is now fixed.
- Vector.setLength() will now throw an error if the given length
is less than zero. (In the past, it accepted an invalid length,
leading to unpredictable results.)
- Under certain conditions, the debugger didn't stop in response to
a "Break" key (Ctrl-C, Ctrl+Break, or whatever key is appropriate to
local convention). In particular, if a single line of code contained
an infinite loop, and the user ran the program, broke into the loop
once, and then resumed execution, the debugger ignored subsequent
break keys. This has been corrected.
- The compiler incorrectly reported errors in the branches of an
'if' statement at the line of the 'if' itself if the branches were
bare statements (not enclosed in braces). The same applied to
'while', 'for', and 'do while' statements when their bodies were bare
statements. The compiler now reports these errors at the
sub-statement locations.
- The compiler generated an incorrect debugger line number record
under certain obscure circumstances: if the source file contained an
object or class based on multiple superclasses, and the class didn't
define an explicit constructor, then the compiler generated an
incorrect line record for the last executable line of code in the
file. This is now fixed.
- The compiler now shows Unicode escape sequences when displaying an
error message containing characters from the source file that can't be
represented in the compiler console character set. For example, if
you're running the compiler in a terminal window on Unix, and your
terminal window is set up to display Latin-1 (ISO-8859-1) characters,
and you're compiling a source file prepared in Latin-2, your terminal
window would be unable to correctly display some of the characters in
the source file, because Latin-2 has characters that aren't part of
Latin-1. In the past, if any of these "unmappable" characters were
shown as part of a compiler error message, the compiler showed them as
question marks. Now, the compiler shows them as "backslash" escape
sequences. For exampe, Latin-2 character 171, "T with caron," would
be displayed as "\u0164", since its Unicode code is 0x164. This
change doesn't affect the display of compatible characters - all
mappable characters will still be displayed in the local character
set. This only affects characters that were formerly displayed as
question marks.
- The default "file safety level" is now 1, which allows reading
from any file and writing only to the current working directory.
This default setting provides games with reasonable flexibility, but
helps prevent the possibility that a malicious author can modify
important files on your hard disk by limiting writing operations to
the game's working directory only. You can override this using
the "-s" option if you want to set a more permissive or more
restrictive safety level.
- In Workbench for Windows, the "Build for Release" command
didn't properly invoke the "t3res" command for building external
resource files (.3r0, etc). This now works properly.
- A problem in the debugger caused sporadic bad behavior when a
finalizer method threw an exception (out of the finalize() method;
throwing around exceptions within a finalizer was fine, as long as the
exception was caught entirely within the finalizer). This manifested
itself in numerous different ways, ranging from no visible effects
to full Workbench crashes. The problem only occurred in the debugger;
the regular non-debug VM didn't have the problem. This has now
been corrected.
- The VM now recovers more gracefully from stack overflow
exceptions. In the past, stack overflows tended to be unrecoverable
because the VM would usually encounter a second stack overflow in the
course of trying to create an exception object to represent the
original stack overflow, forcing the VM to terminate the game
summarily to avoid an infinite loop of exceptions thrown while
handling exceptions thrown while handling exceptions, ad infinitum.
The VM now keeps a small emergency reserve of stack space for
handling stack overflow errors, which should in most cases allow an
exception object to be created normally, which in turn allows the
game to catch and handle the exception just like any other run-time
error.
- The debugger now gives you more flexibility in recovering from
stack overflow errors. In the past, if your program caused a stack
overflow (due to infinite recursion, for example), the debugger
itself was unable to evaluate expressions without itself encountering
stack overflows, since the debugger shares the stack with the VM.
The debugger now holds some of the stack in reserve specifically for
handling stack overflows; when a stack overflow occurs, the debugger
uses the reserve for its own purposes, allowing you to evaluate
expressions and carry on normally within the debugger. This makes it
easier to figure out why the stack overflow occurred. Note that you
can often use the debugger to recover from a stack overflow by
manually moving the execution pointer to a 'return' statement (or the
end of the method), breaking off the infinite recursion that caused
the overflow.
- The debugger now shows anonymous functions more descriptively in
stack traces. In the past, these showed a string like
"[1234].prop#0(5,6)"; now, the debugger shows "{anonfn:1234}(5,6)"
instead. The "1234" is an internal object identifier for the
anonymous function; this conveys no specific human-readable meaning
other than to distinguish one function from another. The
corresponding change has also been made in reflect.t, in
reflectionServices.formatStackFrame().
Changes for 3.0.6k (8/17/2003)
- The debugger now supports stop-on-change conditional breakpoints.
When you create a breakpoint with a condition expression, the debugger
now offers a choice between stopping when the expression evaluates to
true or stopping when the expression's value changes. In the past,
there was no choice, and only stop-when-true conditions were
supported. Stop-on-change is now the default when creating a new
global breakpoint.
- The system.tl library now includes the default system startup
module, _main.t. In addition, it sets the new library flag, "nodef",
to indicate that the library replaces the default system modules that
the compiler would otherwise include in the build automatically. This
change primarily benefits users of Workbench for Windows, in that it
causes Workbench to include _main.t explicitly in the list of source
files. This makes it more convenient to view the file within
Workbench, set breakpoints inside it, and trace into it. (This change
will have no effect on most existing games. The only games affected
would be those that include system.tl and include a
non-standard startup module, using the "-nodef" compiler flag to
suppress the default inclusion of _main.t. This is an unlikely
scenario, but if it applies, here's what to do: drop the "-nodef"
compiler flag from your project file, and instead add "-x _main"
immediately after the "-lib system" inclusion.)
- The new directive "nodef" can appear within a library (.tl) file.
This instructs the compiler that the library includes the same modules
that the compiler would include by default, or replacements for the
standard modules. If a library includes the "nodef" directive, then
including that library in the build has the same effect as including
the "-nodef" option on the compiler command line or in the project
(.t3m) file.
- In the past, the text-only interpreters didn't properly handle banner
size settings that exceeded the available screen size. The text-only
interpreters will now limit a banner's size to the available space on
the screen when the requested size is too large.
- The AnonFuncPtr intrinsic class now correctly identifies itself as
a subclass of Vector (via ofKind and getSuperclassList).
- The AnonFuncPtr intrinsic class now compares and hashes by
reference, rather than by value as its Vector base class does.
- The banner function bannerSetSize(), when applied to a text window
(BannerTypeText), now takes into account the space used for margins
and borders when sizing in "absolute" units. This ensures that if you
ask for a height of five rows, for example, then the window will
actually be large enough to display five rows in the default font,
without any scrolling. In the past, the margins weren't taken into
account, so the actual capacity of a banner wasn't necessarily
the same as the requested nominal size in absolute units.
- The run-time symbol table now omits "intrinsic class modifier"
objects. These objects have been filtered out of firstObj/nextObj
iterations since 3.0.6c; they're now filtered out of the symbol table
for the same reasons, and for consistency with firstObj/nextObj. (In
the past, these objects appeared as symbols of type object, with names
of the form " 99", and with no superclasses. These are internal
implementation objects that are meaningless to the game program, so
there's no reason for the symbol table to include them.)
- A problem in the List and String classes caused the VM to crash in
certain very rare cases when evaluating properties of constant list or
string values. This has been corrected.
- A bug in the Dictionary intrinsic class's findWord() method
sometimes caused strange behavior, most noticeably as corruptions in
the values of local variables in the invoking code. The problem only
occurred when the method was called in its single-argument form. The
problem has been fixed.
Changes for 3.0.6j (8/2/2003)
- The new TadsObject method setSuperclassList() enables the game
program to change an object's superclass list dynamically. The
method takes a list giving the new superclass list for the object.
- It's now legal to explicitly define a 'location' property in an
object definition that also uses the '+' notation to set the object's
location. The compiler specifically treats an explicit 'location'
property setting as overriding the value set with the '+' notation,
rather than considering the redefinition a conflict as it did in the
past. This allows logically related object definitions to be kept
close together in the source code even when some of the objects are
part of a location tree and others are not; this happens fairly
frequently, because simulation objects sometimes have abstract helper
objects that don't participate in the normal location hierarchy.
- Templates can now include alternative groups that are optional.
If any element of an alternative group is marked as optional, then
the whole group of alternatives is optional.
- The new macro perInstance(expr), defined in the system header
file tads.h, can be used to define a property in a class such that
the property will be set to the value of the expression 'expr'
separately for each instance of the class. For each instance,
the expression is evaluated the first time that instance's value
of the property is accessed, and then stored with that instance.
- The compiler now has the ability to bundle resource files into
the image (.t3) file as part of the main compilation ("t3make") step,
without running the "t3res" utility as a separate step. This lets
you include resource files in your project's makefile (the .t3m
file), which means the makefile can now specify the entire build
procedure for most types of projects. To add resources with t3make,
add the new "-res" option after all of your source and library
modules in the .t3m file, and list your resource files after the "-res"
option. The syntax for the resource list following the "-res" option
is the same as the "t3res" utility, except that the "-add" option is
not allowed (as adding resources is the only possibility).
- Workbench for Windows now allows you to add a resource file to a
project before the resource file exists. To add a resource file that
you haven't yet created, use the usual menu command to add a resource
file, then type the name of the file into the file selector dialog.
The dialog will allow you to type the name of a file that doesn't
yet exist. This is handy when you want to include a resource file
that won't be created until your pre-initialization code runs, such
as the "gameinfo.txt" file.
- The compiler is now able to determine automatically if relinking
is needed due to a change in the set of modules included in the build.
This is accomplished by checking a small bit of additional data in the
.t3 about the set of object modules involved in the build. (The new
information is simply a 32-bit "checksum" of the module source file
list, so it adds only four bytes to the image file. It's not enough
information to allow a user to recover a list of your source files by
reverse-engineering the image file, so you don't have to worry about
any possibility that a user could obtain "hints" this way. Because
only a checksum is stored, there's a very small possibility that a
change to the source file list could result in an identical checksum,
in which case the compiler would not notice that relinking is
required. The probability of this happening is extremely small, but
if you ever suspect it, you can always use the "-al" option to force a
relink.) Note that this doesn't affect the compiler's use of file
timestamps to determine build dependencies; this is simply an
additional check the compiler makes to detect when a new module is
added to the build or an old module is removed.
- The ByteArray intrinsic class has two new methods, readInt() and
writeInt(), that make it easy to translate between integer values and
byte representations of those values. This is especially useful for
reading and writing binary files. The new methods let you read and
write integers in 8-bit, 16-bit, and 32-bit sizes, signed or unsigned,
and in little-endian or big-endian format.
- The File intrinsic class has a new method, getFileSize(), which
returns the size in bytes of the file.
- A bug in the File intrinsic class sometimes caused the VM to
crash when a read operation was attempted after a seek operation.
This has been corrected.
- The starter game templates now include startup handling for
startup-and-restore. When the player launches the interpreter using a
saved-game file, the interpreter invokes the startup-and-restore code,
which the game must provide in a routine called mainRestore(). The
starter templates now include a mainRestore() routine, and handle
main() and mainRestore() using a common subroutine called
mainCommon(). This change will make it much simpler for authors to
include proper startup-and-restore support in their games, by
providing a ready-made framework with the necessary code.
- Fixed a bug in Workbench for Windows: checkboxes in the Project
window didn't work for nested libraries; clicking on the checkbox
for a nested library simply had no effect. These checkboxes now
work properly; clicking on a library checkbox checks or unchecks
the library and all of the files within the library.
- The Win32 character-mode interpreter (t3run.exe) now includes
a desktop icon in the executable file. This allows you to use the
"-icon" option with maketrx32 to add your own custom icons to games
you bundle as executables using the console-mode interpreter.
- A bug in the regular expression matcher failed to handle the
shortest-match closure modifier (specified with a '?' suffix to a
'*' or '?' operator) properly. This bug was introduced in the
regular expression processor rework in 3.0.6h, and has now been
corrected.
- In certain unusual cases, the debugger incorrectly included a
property in property enumerations when the property was actually a
method. This happened when a method overrode a property defined as a
simple data value in a superclass. The debugger isn't meant to show
methods in property enumerations, since invoking a method will
naturally invoke any side effects of the method. This has been
corrected.
- In Workbench for Windows, projects created in the root directory
of a disk (C:\, D:\, etc) caused a number of problems, including
crashes during compilation. These problems have been corrected, so
creating a project in a root directory is now safe.
- In Workbench for Windows, the compiler incorrectly wrote the
object files to the working object directory when compiling for
release, overwriting the object files for the debug build. This
didn't do any harm apart from requiring a full recompile for debugging
after any release build, which the compiler automatically sensed and
performed, but it caused an unnecessary delay. The compiler now
correctly sends release build object files to a temporary directory,
so that the debug build object files are retained through a release
build.
- The new-project wizard in Workbench for Windows will no longer
accept a source filename that ends in an extension reserved for
makefiles or compiler-generated files (.t3m, .t3, .t3o, .t3s). This
makes it more difficult to accidentally create a source file that will
be overwritten by the compiler or by Workbench with generated files.
- The compiler will now recompile an object file if the symbol file
is more recent. Compilations that fail due to a syntax error can
leave a project partially compiled, so that all of the symbol files
but not all of the object files have been recompiled. In the past,
correcting such an error and then recompiling did not always compile
all of the necessary modules. This change ensures that all modules
noted as requiring compilation on the first attempt will be noted
again on subsequent attempts, even if the first attempt fails part-way
through.
- Due to a bug in the VM, throwing exceptions out of a native-code
callback context (such as out of the callback to a Vector or
LookupTable iteration method) sometimes caused the VM to lose track of
the calling exception handlers; this caused symptoms such as sending
the exception to a "catch" block other than the innermost eligible
one. This problem tended to show up when an exception was thrown out
of a callback context, and then the same exception was thrown again on
a later invocation. This has been corrected.
- If a Vector contains a reference to itself, or to a Vector
containing a reference to the first Vector, indirectly to any depth,
then an attempt to compare the Vector to another Vector, or an attempt
to use the Vector as a key in a LookupTable, will fail with a run-time
exception ("maximum equality test/hash recursion depth exceeded").
Since Vector equality comparisons and hash calculations are defined
recursively by value, Vectors with direct or indirect self-references
cause the equality and hash calculations to recurse infinitely; the
Vector class avoids this infinite recursion by throwing the exception
when the recursion becomes too deep. Note that this also effectively
limits the depth of a Vector tree when used in an equality test or
hash value calculation, even if the tree is acyclic; the limit is
256 levels.
- When reading input from a script (using the REPLAY command, for
example), the interpreter now ignores morePrompt() calls. This
allows script replay to proceed unattended, without unnecessary
interactive pauses.
- In the debugger, if the game was interrupted by a real-time event
while the player was editing a command line, and the debugger took
control (via a breakpoint, for example) inside the real-time event,
and the game was then terminated from within the debugger (while
still stepping through the real-time event code) and then later
restarted, a bug in the console manager caused strange behavior,
sometimes including crashing the debugger. This has been corrected.
Changes for 3.0.6i (6/15/2003)
- Due to a compiler bug, when a template was defined using the "|"
symbol to list a set of alternatives for a token position, object
definitions using the template failed to match the last alternative
of a set. All alternatives in a set are now properly recognized.
- The gameinfo.t module has been removed. In its place is a new
mechanism in the library that writes the GameInfo file automatically
during pre-initialization, based on the definitions in the game's
GameID object.
- The Tokenizer class now gives each rule a name, which is simply a
string value by which the rule can be identified. This changes the
format of the rule list entries - each rule list entry has the new
name value as its first element. Any subclasses or modifications
of Tokenizer must use the new rule format.
- The Tokenizer class has some new methods that allow rules to be
added or removed. insertRule(rule, curName, after) inserts the new
rule given by 'rule' before or after the existing rule named
'curName'; the new rule is inserted before the existing rule if
'after' is nil, after the existing rule if 'after' is true.
insertRuleAt(rule, idx) inserts the new rule given by 'rule' at the
index given by 'idx' in the rule list. deleteRule(name) deletes the
existing rule with the given name, and deleteRuleAt(idx) deletes the
existing rule at the given index in the rule list.
Changes for 3.0.6h (6/7/2003)
- The "modify" keyword can now be used to define functions. Modifying
a function works just like replacing a function with the "replace" keyword,
except that the new function can invoke the previous version of the
function by using the "replaced" keyword. Refer to the
Statements section of the
documentation for details.
- Two new TadsObject methods, createInstanceOf() and
createTransientInstanceOf(), enable a program to dynamically
instantiate an object based on multiple superclasses. Refer to the TadsObject reference for
details of the new methods.
- The object template syntax has
been extended to include optional elements and alternative elements.
An element is marked optional by placing a question mark after it;
alternative elements are separated by '|' tokens.
- Several string search and regular expression intrinsics accept a
new optional argument specifying the starting index in the string for
the search. If the index argument is specified, then the search will
start from the given character index; the index value 1 indicates
that the search starts from the first character of the string, which
is the default if the index parameter is omitted. This change allows
algorithms that search for repeated occurrences of a substring or
pattern to be written more efficiently, since they won't have to
split up the source string to continue searching for additional
occurrences.
- String.find(str, index?)
- String.findReplace(origStr, newStr, flags, index?)
- rexMatch(pat, str, index?)
- rexSearch(pat, str, index?)
- rexReplace(pat, str, replacement, flags, index?)
- A new banner style flag, BannerStyleMoreMode, causes a banner
window to use "MORE" mode. This means that any time text displayed to
the banner fills the available vertical space in the banner window,
the interpreter will display some sort of prompt to the user, and then
wait for the user to acknowledge the prompt. The exact nature of the
prompt and acknowledgment varies by platform; usually, the interpreter
displays a prompt like "[MORE]" at the bottom of the overflowing
window, and waits for the user to press a key. The purpose of MORE
mode is to ensure that the user always has a chance to read all of the
displayed text before it scrolls off the screen. Note that
BannerStyleMoreMode implies BannerStyleAutoVScroll, since it only
makes sense to pause for a MORE prompt when new text would cause old
text to scroll away, and this only happens when the auto-vscroll style
is used.
- The forEachInstance() function now allows the callback to break
out of the iteration loop by throwing a BreakLoopSignal exception.
Throwing this exception simply terminates the loop and returns to
the caller of forEachInstance(). You can conveniently throw the
exception using the "breakLoop" macro (defined in tads.h).
- A new utility function has been added to the base library (in
_main.t): instanceWhich(cls, func). This function
iterates over instances of the given class cls, and calling
func on each instance; func is a pointer to a function
taking one parameter, which is the current instance in the iteration.
instanceWhich() returns the first instance for which the callback
function func returns a non-nil and non-zero value. Note that
the function iterates instances in arbitrary order, so if there are
multiple instances of cls for which func returns true,
the return value will simple be the first of these visited in the
arbitrary iteration order. If func doesn't return a
non-nil/non-zero value for any instance of cls, the function
returns nil.
- The setLogFile() function now takes an optional second parameter
specifying the type of log file to open or close. The possible values
are LogTypeTranscript, to create a transcript of all input and output;
and LogTypeCommand, to create a record of only the input commands.
The default, if the parameter is omitted, is LogTypeTranscript.
- The character mapper now accepts the IANA standard names for
the various Unicode encodings supported in TADS 3: "UTF-8", "UTF-16BE"
(for the 16-bit big-endian encoding), and "UTF-16LE" (for the 16-bit
little-endian encoding). These names are case-insensitive, and can
be used anywhere a character encoding name is required (#charset,
new Charset(), etc). The old non-standard names for the same
character sets ("utf8", "unicodeb", and "unicodel") are still accepted
as well.
- The compiler now accepts source files that start with a Unicode
UTF-16 byte-order marker (i.e., the "FF FE" or "FE FF" byte sequences)
and also specify a #charset directive. The #charset directive
in such cases must (1) itself be encoded in the 16-bit Unicode
encoding implied by the byte-order marker, and (2) designate the
character set name that matches the byte-order marker (so a file
encoded in big-endian UTF-16 must have a #charset "utf-16be"
directive, and a file encoded in little-endian UTF-16 must have a
#charset "utf-16le" directive). The #charset directive is optional in
these cases, since the compiler can correctly infer the encoding based
on the byte-order marker alone.
- The compiler now accepts source files that start with a Unicode
UTF-8 byte-order marker. The compiler infers that the file is encoded
in UTF-8 if it sees this sequence. Note that there is only one valid
UTF-8 encoding, so the UTF-8 byte order marker is always the same
(i.e., there is no "big-endian" or "little-endian" flavor of UTF-8;
there's only UTF-8). A #charset "utf-8" directive is allowed but not
required immediately after the UTF-8 three-byte byte-order marker
sequence. This change is required because some text editors that save
in UTF-8 format write the byte-order marker character at the start of
the file.
- A new compiler option, -quotefname, tells the compiler to quote
filenames when reporting the source file location of an error. If
this option is specified, the compiler encloses these filenames in
double quotes, and "stutters" any double-quote characters that are
part of the filenames themselves (that is, each double-quote character
that's actually part of a filename is shown as two double-quote
characters in a row). This change is intended to make it easier
for automated tools to parse the compiler's error message output,
by ensuring that filenames can be predictably parsed regardless of
any special characters that might appear within.
- The compiler now displays an initial status message indicating
the number of files it will need to build. This is designed for
use by automated tools, to give them an estimate of the amount of
work to be done; this can be used, for example, to show a progress
bar indicator as the compilation proceeds.
- In the compiler options file (the .t3m file), certain options (-I,
-o, -Os, -FL, -FI, -Fs, -Fy, -Fo, -source, -lib) can be specified
using URL-style notation, to ensure portability of the .t3m file
across different operating systems. In the past, the compiler didn't
properly translate these options to local conventions when they
contained '/' characters to separate path elements. The compiler
now properly converts URL-style paths to local conventions.
- When an object is defined with an undefined or invalid superclass
name, and the object definition uses a template to define property
values, the compiler now reports an "undefined superclass" error
rather than an error with the template format. In cases where a
superclass name is merely misspelled, the compiler will naturally
fail to find a matching template for the object, since the misspelled
superclass name probably doesn't have any templates associated with
it; thus, the template error is secondary to the true problem, which
is the misspelled superclass name. This change should make the
diagnostics more useful by reporting the true problem rather than the
missing-template side effect.
- Text Grid windows no longer consolidate runs of whitespace;
instead, all whitespace written to a text grid window is treated
literally.
- Text Grid windows incorrectly interpreted HTML markups in the
text-only interpreters. This has been corrected; text displayed to
text grids is now treated literally on all interpreters.
- Workbench now automatically saves the project (.t3m) file settings
upon starting execution of the game in the debugger, and also saves
the recent game order whenever a new game is loaded. These measures
help reduce the chance of data loss in the event that Workbench
crashes while the game is running (which it ideally should
never do at all, but until the glorious day when it's perfectly
bug-free, this extra saving will at least make crashes a little less
painful).
- Due to a bug, Workbench on Windows did not start up correctly
when it was started by double-clicking on a .t3m file from the
Windows desktop. (Workbench started with a blank interpreter
window, but didn't show the main Workbench IDE window at all.)
This has been corrected.
- A bug in the debugger caused the debugger to crash under certain
obscure circumstances. In particular, the crash occurred if the game
caused a stack overflow, and the overflow happened to occur on a
recursive VM invocation from an intrinsic method (such as when an
intrinsic class method invokes an anonymous function callback). This
has been corrected.
- In the past, the compiler generated an output function call for
the intial empty portion of a double-quoted string of the form
"<<expr>>..." (in other words, a string with an embedded
expression immediately after the open quote). The compiler no longer
generates this superfluous empty string output operation, slightly
reducing code size and execution time.
- The String intrinsic class failed to enforce the 64k length limit
for an individual string in some cases; exceeding the limit caused
problems ranging from corrupted string text to crashes. This has
been corrected; the interpreter now throws a run-time exception
("string is too long") if creating a string (via concatenation, for
example) would exceed this limit. The List intrinsic class is
likewise more assertive now about enforcing its 64k limit as well.
- The regular expression functions (rexMatch, rexSearch, rexReplace)
were capable of causing the interpreter to crash (with a system stack
overflow) when asked to match a pattern to an extremely long string.
The exact limits varied by platform according to the amount of system
stack space available; on Windows, the problem started occurring with
strings about 5,000 characters long, although the exact length was
also a function of the complexity of the regular expression pattern.
This has been corrected; the regular expression matcher no longer uses
a recursive algorithm, so its consumption of system stack space is now
fixed and small. The matcher still consumes memory that scales
according to the length of the input string and the complexity of the
regular expression, since such memory consumption is inherent in the
task; but the memory consumed is no longer in the system stack, which
means among other things that the matcher can now recover gracefully
(by throwing an "out of memory" run-time exception) if it should
exhaust available memory while working.
- In the DOS/Windows version, the executable file bundler
(maketrx32) didn't look for the character map library file
(cmaplib.t3r) in the correct location; it looked in the directory
containing the original interpreter executable rather than the
"charmap" subdirectory of the interpreter directory; since the
installer puts cmaplib.t3r in the subdirectory, the bundler failed to
find the file and omitted it from the bundled executable. The program
now looks in the "charmap" subdirectory.
- A bug caused the compiler to crash on certain types of syntax
errors. If a long string (around 1,000 bytes or longer) was
misplaced in a few specific contexts, the error message generator
overflowed an internal buffer trying to include the text of the
string in the error message. This should no longer occur.
- The compiler now flags an error if a grammar production defines
more than 65,535 alternatives. This limit is imposed by the .t3 file
format for grammar rules, but it's undesirable to get anywhere close
to the limit because of performance cost. It's possible to exceed
the limit with relatively concise grammar rule definitions, because
the compiler expands the permutations of rules defined with '|'
alternatives. Grammar rules that contain complex sets of
permutations using '|' alternatives should generally be rewritten
using sub-productions, which will allow equally complex rules without
the overhead of expanding the permutations.
- In reflect.t, reflectionServices.valToSymbol() can now correctly
identify the reflectionServices object itself. (Due to a bug, this
caused a run-time error in the past.)
- In reflect.t, reflectionServices.valToSymbol(), looking up an unnamed
object now returns a string giving the superclass list of the object,
if the superclass names are available. The format of the return value
is now '(obj:sc1,sc2)', where 'sc1' and 'sc2' are the names of the
superclasses (naturally, more or fewer superclass names will appear
according to the actual number of superclasses of the object). The
string 'obj' is literally present. If none of the superclasses have
names, then the traditional result, '(obj)', is returned. If some
superclasses have names but others don't, then the full list will
be returned, with '(anonymous)' used for any unnamed superclass.
Changes for 3.0.6g (4/12/2003)
- The new interpreter option -R lets you specify the root folder
for individual resources. By default, the root resource folder is
the folder that contains the image (.t3) file. If -R is specified,
then the interpreter will look for resources in the given folder when
they can't be found in the image file itself or in a resource bundle
file. Note that this isn't a search list; only one -R option can be
in effect.
- Added a new method, isRoundTripMappable(), to the
CharacterSet intrinsic class. This new
method provides an easy way to determine if a set of characters
has an exact, one-to-one mapping in a given local character set.
- The compiler now warns when a grammar rule ends with an empty
alternative, or is completely empty. Empty rules at the top level of
a grammar rule are uncommon, and it's easy to accidentally leave a '|'
at the end of a rule, especially while actively defining new rules.
To eliminate this new warning, you can use an empty pair of
parentheses, "()", to explicitly indicate an empty rule. This warning
only applies to the outermost grouping level of a rule; empty rules
within parenthesized portions of rules are not flagged.
- Fixed a problem in the console formatter that caused command lines
read from a command input file to be copied into a script output file
twice.
- Fixed a problem in the Dictionary class that caused dynamic
vocabulary to be forgotten if you saved a game to a file, ended the
interpreter session, started a new interpreter session, restored the
file saved earlier, saved again to a second file, and then later
restored the second file. (The problem was that the Dictionary object
was not being marked as being in need of being saved again after it
was restored in the new session, so the second save didn't include the
dynamic vocabulary entries. The Dictionary object is now properly
marked as being in need of saving after being restored.)
- Fixed a problem that caused the Object.propDefined() method
to yield incorrect results when called on an intrinsic class object
to retrieve information on methods added to the intrinsic class
with 'modify'. The information returned was inconsistent with
that returned from getPropList(). This has been corrected;
the returned information should now be fully consistent.
- Fixed a problem that caused sporadic crashes in the Windows
debugger when an expression including the '&' operator applied
to an undefined symbol was evaluated interactively. This crashiness
should no longer occur.
- Fixed two problems in the text-only interpreters relating to
"&" entities. First, a few valid entity names were not
recognized at all, causing the interpreter to show the entity
source text (i.e., the "&" code itself). Second, entities
whose names weren't properly terminated (with a semicolon, ";")
had the last letter of their name incorrectly added to the display
after the entity itself. These problems have been corrected.
- Fixed a couple of bugs that caused interpreter crashes when
running with "unicodeb" or "unicodel" character set mappings.
- The versions of the interpreters that run in a Windows command
prompt window now correctly remove the console window's scrollbars in
all cases on Windows NT, 2000, and XP. In the past, the interpreters
usually did this, but in some cases missed the scrollbars and
left them intact. (Console scrollbars appear when the console
properties are set so that the console has a "screen buffer" larger
than the actual console window. This feature isn't available on the
Windows 9x platforms, only on the NT branch, which includes 2000 and
XP.) Leaving the scrollbars active created the confusing situation
that the area of the console containing the interpreter window could
be scrolled off the screen. The scrollbars are now correctly removed
under all conditions. This affects t3run.exe and tr32.exe.
Changes for 3.0.6f (3/23/2003)
- Fixed a problem in the regular expression parser that misinterpreted
character class expressions involving single Unicode characters outside
of the plain ASCII range (for example: '<\u2019|\u201D>'). The
regular expression compiler treated such expressions as invalid; it
now handles them correctly.
- Added a couple of new compiler options to allow more control over
special system paths:
- -FI path: overrides the standard system include
directory with the given path. The compiler normally uses a path that
depends on the operating system and installation configuration. Note
that this option doesn't set up a search list the way -I does; there's
only a single system include directory in effect at any given time.
- -FL path: overrides the standard system library
source directory with the given path. The standard library path depends
on the operating system and installation configuration. As with -FI,
there's only a single system library directory in effect at one time.
Changes for 3.0.6e (3/16/2003)
- A new HTML tag is now recognized: <NOLOG>. This is a
container tag (so each <NOLOG> must have a corresponding
</NOLOG> tag); it delimits text that is to be displayed only
on the interactive console, not in any log file (transcript) being
made. The tag has no effect on the display.
- The getPropList() method previously only returned static methods
when called on intrinsic class objects (such as TadsObject or
BigNumber). This has been changed so that the method now returns both
static and non-static methods. This change clarifies the meaning of
getPropList() when called on an intrinsic class object: the method
returns the full set of properties that the class defines for
instances of the intrinsic class, which may not necessarily be
methods that are meaningful when called on the intrinsic class object
itself. This change is necessary for consistency throughout the
class hierarchy for the reflection mechanism, so that a program can
traverse a class tree to create an exhaustive list of properties on
a class, including those inherited from intrinsic superclasses.
- In the output formatter, the effects of the "\^" and "\v"
sequences are now limited to the plain text outside of HTML markups.
In the past, if an HTML tag or entity appeared after a "\^" or "\v"
sequence and before any alphabetic character, the case conversion
effect was applied to the first character of the tag or entity name.
Entity names are case-sensitive, so this had the potential to
invalidate an entity name; in addition, whether a tag or entity name
interceded, the case conversion effect was effectively lost, since it
was misapplied to the HTML markup. Now, with this output formatter
change, the case conversion effect of "\^" and "\v" sequences skips
past any HTML markups, so the case conversion is applied to the next
plain text.
- Fixed a problem in the console output formatter that caused
explicit blank line sequences to be ignored in some cases immediately
after reading input.
- Fixed a compiler problem that caused spurious syntax errors in any
object definition that used a template in which a list element
followed a single-quoted string element.
- Fixed a compiler bug that caused spurious syntax error reports
in certain cases involving multi-line strings as macro arguments.
If code involving a macro spanned multiple lines, and the macro
arguments included a string spanning multiple lines, and the string
was part of a larger expression that started with a non-string token,
the compiler sometimes misinterpreted the string as ending before its
actual terminating quote. This resulted in spurious syntax errors,
as the compiler thought some of the string's continuation lines were
non-string tokens. This has been corrected.
- Fixed a bug in the console output formatter that allowed too many
lines to be displayed between "MORE" prompts in some cases, which
caused text to scroll off the top of the screen before the player
could read it. (The problem was introduced with the typographical
spaces in 3.0.6b.)
Changes for 3.0.6d (2/23/2003)
- Fixed a problem that caused the debugger to crash when attempting
to stop a running game when the game was suspended in the debugger at
a run-time exception that was thrown from within a callback invoked
from a system intrinsic method (for example, from a callback
invoked by the List.forEach() method). This has been corrected.
- The inputKey() intrinsic function didn't return the correct
square-bracket code for special keys (arrow keys, function keys, and
so on) due to a bug introduced in an earlier patch release (3.0.6a).
This is now fixed.
- Fixed a problem in several methods of the Dictionary intrinsic
class (addWord, removeWord, forEachWord) that sometimes caused stack
overflows when calling these methods. Fixed the same problem in some
File methods (setCharacterSet, closeFile, setPos, setPosEnd).
Changes for 3.0.6c (2/1/2003)
- Defining a template for an object class no longer creates an
external reference to the object, so it's now legal to define
templates for objects that are never defined in any of the
modules linked into a program. In the past, merely defining a
template for an object created a reference to the object. This
change makes it easier to create more modular subsystems whose
components can be linked a la carte, since templates included in
a header for the subsystem won't by themselves drag in the modules
where the template objects are defined. An object mentioned in
a template will now be required at link time only if the template
is actually used to create instances of the mentioned object.
- The 'modify grammar' statement now accepts an empty grammar rule
list to indicate that the rules defined in the base grammar
definition are to be retained. This change makes it possible to
modify the properties and/or methods of a grammar rule in isolation,
without changing the syntax for the rule. In the past, to modify
only properties or methods of a grammar rule, it was necessary to
repeat the entire rule list from the base grammar definition, since
the rule list in the 'modify grammar' statement always superseded the
base object's rule list.
- The firstObj/nextObj object iteration functions now filter out
"intrinsic class modifier" objects. These are purely internal
implementation objects in the VM; they serve as the repositories of
properties and methods attached via the "modify" keyword to intrinsic
classes, and are for all intents and purposes parts of the intrinsic
classes they modify. There is no benefit in enumerating them as
separate objects, and doing so created some confusing special cases
for code using the reflection mechanisms, so they've been eliminated
from the firstObj/nextObj results.
- The "intrinsic class" declaration syntax now allows the superclass
of the intrinsic class to be specified. This information is largely
for documentary purposes; intrinsic classes are built into the VM, so
the "intrinsic class" syntax doesn't actually define intrinsic classes
but merely tells the compiler about the interfaces of the intrinsic
classes being used. The system header files have been changed to take
advantage of this new feature to provide superclass information for
the intrinsic classes they declare. The one immediate effect of this
change is that the compiler is now able to enforce the rule against
using "modify" with intrinsic methods of intrinsic classes, and can
do so for the entire inheritance tree; in the past, the compiler was
unable to enforce this rule for inherited intrinsic methods, since it
didn't have information on the inheritance relationships among
intrinsic classes.
- Workbench for Windows had a problem that, under certain
circumstances, caused the same directory to be added to the "include"
path in the build settings every time a project was opened. This
happened when a file in the "include files" section of the project
had a parent-relative path (a path starting with ".."). This should
no longer occur.
- Workbench for Windows had a problem that failed to recognize the
library-relative path of a header file associated with a nested
library (that is, a library referenced from within another library;
for example, en_us.tl is nested within adv3.tl in the standard library
configuration). This sometimes caused such header files to be listed
in the "include files" section of the project window with absolute or
parent-relative paths, when they should have been listed without any
path prefix, since Workbench automatically looks for header files in
the directories associated with libraries included in the build.
The unnecessary path prefixes caused other undesirable side effects,
such as including superfluous include paths in the build settings.
Workbench should now correctly identify headers associated with nested
libraries.
- Workbench for Windows did not properly initialize the "recent
projects" menu when configured to load the most recent game at
startup. On the initial load at startup, the list of recent projects
was always shown with full, absolute directory paths, rather than with
paths relative to the initially loaded project's directory. (This was
purely cosmetic, but was inconsistent, since the recent projects were
always shown with paths relative to the active project after opening
another project subsequently.) This has been corrected.
- A problem in the command-line option parser prevented some
combined TADS 2/3 interpreters from accepting the "-cs" (character
set) option for TADS 3 games. This is now fixed.
Changes for 3.0.6b (12/15/2002)
- This version substantially overhauls the output formatter's
word-wrapping rules. The changes are designed to give the game much
greater control over the way that text lines are wrapped to fit the
available horizontal space. The changes should be relatively
transparent to existing code, because the new features mostly add
optional new controls, but use defaults that provide roughly the old
TADS 2 behavior. The changes are implemented in both the text-only
and HTML interpreters. The new text-wrapping rules are described in
detail in the Formatting documentation, but
here's a summary of the changes:
- The game can switch at any between "word-wrap" and "character-wrap"
modes. In word-wrap mode, text can be broken only at word boundaries;
in character-wrap mode, text can be broken between almost any two
characters. The modes are selected with the new tag <WRAP>:
<WRAP WORD> sets word-wrap mode, and <WRAP CHAR>
sets character-wrap mode.
- The formatter recognizes the Unicode character \uFEFF (HTML
entity "&zwnbsp;"), the zero-width non-breaking space. This character
doesn't show up on the display, but it tells the formatter not to break
the line between the two adjacent characters, even if the text-wrapping
rules would otherwise permit it.
- The formatter recognizes the Unicode character \u200B
("&zwsp;"), the zero-width space. This character doesn't show
up on the display, but it tells the formatter that it can break the
line between the two adjacent characters, even if the wrapping rules
wouldn't ordinarily allow a line break there.
- The formatter recognizes several of the Unicode special-width
space characters (en space, em space, etc). All of these are treated
as quoted space, in that they don't combine with adjacent runs of
ordinary whitespace. These spaces allow finer control over visual
spacing, which facilitates a more typographical appearance in the
HTML interpreters.
- The "soft hyphen" character, \u00AD (HTML "­") is now
accepted by the formatter. This is invisible in most cases, but
it tells the formatter that it can break the line by hyphenating.
If the formatter does break a line at a soft hyphen, it displays
the soft hyphen as an ordinary visible hyphen.
- Added the new "log file console." This is a special kind of
console object that has no display, but simply captures all of its
output to a log file. This can be used to capture game output to a
file, using the standard output formatting (including HTML
interpretation and word wrapping), without displaying anything to the
player. Refer to the tads-io function set
documentation for details.
Changes for 3.0.6a (11/23/2002)
- The new #pragma newline_spacing(on|off) directive lets
the program control the treatment of newlines in strings. By default,
newline spacing is set to "on": when a newline character is found within
a string, the compiler converts the newline plus any whitespace that
immediately follows to a single space character. When newline spacing
is set to "off", the compiler instead simply strips out the newline
and any immediately following whitespace. Setting newline spacing
to "off" is desirable in some languages, such as Chinese, where
whitespace is not conventionally used as a token separator in
ordinary text; turning off newline spacing can make it easier to
write code in these cases, because it allows strings to be split over
several lines without introducing unwanted whitespace.
- The compiler now allows macro substitutions in library (.tl) files.
In a library file, the value of a preprocessor symbol defined with the
-D option can be substituted into the text of the library file using
the notation "$(VARNAME)": the variable name is enclosed in parentheses
preceded by a dollar sign. The adv3 library (adv3.tl) uses this
capability to parameterize the language-specific library and message
file selection. See Compiling and Linking
for more information.
- The text-only interpreters now treat " " as a true non-breaking
space. (In the past, " " was treated the same as "\ ", the
quoted space: the formatter did not combine such a space with other
adjacent whitespace, or remove it from the start of a line, but did
allow a line break to occur at an " " character.)
- On Workbench for Windows, the Build Settings dialog has a new page
that lets you set the directory paths to use for object files and symbol
files. This new page's tab is labeled "Temp Files," as the symbol and
object files are intermediate files that the compiler produces and
reads during compilation. (These settings correspond to the -Fy and -Fs
compiler options.)
- When Workbench for Windows creates a new project, it automatically
creates a subfolder (of the folder containing the project file) to
store the project's object and symbol files. The new subfolder is
called "obj". Workbench initializes the new project's object file and
source file path options to the new subfolder. The purpose of using
the subfolder is to keep the compiler-generated intermediate
files separate from the project's source files, to make it easier to
manage the files associated with the project.
- A portability bug that caused interpreter crashes on some platforms
(notably Solaris) has been fixed. (This bug only occurred when the
interpreter was compiled with certain C++ compilers, and prevented
the interpreter from running any games.)
- The 'inherited' operator did not work properly to inherit a
modified intrinsic class method from the intrinsic base class of a
modified intrinsic class. For example, if a method defined with
"modify TadsObject" used 'inherited' to inherit, and a method of the
same name was defined with "modify Object", the Object modifier method
was not properly inherited. This has been corrected.
- The new compiler option "-errnum" causes the compiler to display
the numeric error code for each warning or error message. By default,
the compiler does not display the numeric codes for errors, because
the code is mostly for the compiler's own use; however, the new option
allows the user to show these codes if desired, for purposes such as
cross-referencing with documentation.
- The new compiler option "-w-nnn" causes the compiler to
suppress the warning message identified by nnn, which is the
compiler's internal numeric code for the warning. When this option is
used, the compiler will not display any warnings of the given type,
and will not include any such warnings in its summary error count.
This option can be repeated to suppress multiple types of warning
messages. Only warnings (and pedantic warnings) can be disabled with
this option; specifying codes for errors of severity greater than
warnings will have no effect. The complementary option
"-w+nnn" can be used to explicitly enable a warning; by
default, all warnings are enabled, so the only reason this option
would be needed is to enable a warning previously removed with
"-w-nnn" on the same command line, which might sometimes be
useful with shell aliases or command scripts. Note also that the
"-w+nnn" option cannot be used to selectively enable
certain pedantic warnings without enabling pedantic mode; pedantic
warnings are an entirely separate class of messages from regular
warning, and can only be enabled as a group using the "-w2" option.
Once pedantic warnings are generally enabled, you can use
"-w-nnn" to disable specific pedantic warnings you wish to
suppress. +
- When searching for an external resource file (.3r0,
.3r1, etc.), the interpreter now looks for a file with both a
lower-case and upper-case version of each suffix. This is intended to
make the naming convention more flexible on case-sensitive file
systems, such as Unix; on systems with case-insensitive file naming,
such as Windows or Mac, this change has no effect.
- Added support for mixed multi-byte character sets to the character
mapper; this allows the compiler to read source files encoded in
multi-byte character sets, and allows the interpreters to use local
system character sets with multi-byte encodings, both for displaying
text on the screen and reading text from the keyboard. A number of
widely-used character sets for Asian languages use this type of
character set (Windows systems localized for Chinese and Japanese use
multi-byte character sets, for example). Such character sets have
always been supported in the character map compiler (mkchrtab), but
the character mapper used in the compiler and VM did not implement the
mapping logic for these types of character sets. Double-byte
character sets are now fully supported; the character mapper can now
handle any character set that uses two-byte sequences for all of its
characters (usually called double-byte character sets), or that uses a
mixture of one-byte and two-byte sequences (usually known as
multi-byte or mixed-multi-byte character sets).
- In Workbench for Windows, the Debug Log window displayed its
contents using the same color settings as in the main game window.
The Debug Log window now uses the color settings from the Workbench
"options" dialog, the same as source file windows.
- In the Build Settings dialog in Workbench for Windows, on the
Installer page, a new field allows overriding the default character
mapping library (cmaplib.t3r) with a custom mapping library. This
is especially useful for authors working in Asian languages; the
default character map library includes mappings for the common
character sets for most European languages, but does not include
the Asian character sets because of the large size of these sets.
Authors working in languages which require character sets not included
in the default mapping library can create their own mapping file or
files (see the character mapping documentation),
then bundle the file(s) into a custom library (a .t3r file) using
the t3res tool. Specify this .t3r file in the new
Character Map Library field, and the installer will automatically
bundle this file into your game's executable file when building
the install set.
- Fixed a problem in Workbench for Windows that caused Workbench to
reload a library (.tl) file every time Workbench became the foreground
application (i.e., its main window was activated after another
application had been in the foreground), if the library was ever
modified after being loaded in Workbench in that session.
- Fixed a problem in the UTF-8 character mapper that could have
caused problems in rare cases when reading from a text file encoded
in UTF-8. The mapper did not correctly figure the byte length of the last
character when reading a three-byte character at the end of the buffer and
the first two of the three bytes was read into the buffer. (This problem
was extremely unlikely to actually occur in practice, but in any case it's
now fixed.)
- Fixed a problem in the GrammarProd class that caused interpreter
crashes under certain circumstances. In particular, if a grammar rule
was matched with a '*' element in the rule, and the matched input string
had exactly six tokens, an internal memory corruption led to an interpreter
crash. This has been corrected.
- Fixed the t3make error message "error creating image file" to properly
show the image file name as part of the message. This message incorrectly
showed the filename as "s", regardless of the actual name of the image.
- Fixed a problem in the DOS character-mode interpreters (t3run and
tr32) that caused start-up error messages (in particular, errors
relating to loading the .t3 file, such as a "game file not found"
error) to be cleared from the display before the user had a chance to
see them.
Changes for 3.0.5 (09/22/2002)
- The <BANNER> tag is no longer allowed for T3 HTML programs.
T3 games should use the banner API instead. (The <BANNER>
tag has been removed entirely because it interacts poorly with
the banner API. The adv3 library uses the banner API for the
status line, so this essentially forces programs using the library
to do likewise. To reduce the potential for any confusion that
could result from games inadvertantly mixing banner API calls and
banner tags, we simply disallow banner tags entirely, to ensure
that all T3 programs use the banner API uniformly.) For the moment,
<BANNER> tags are actually disallowed only when the banner API
is supported by an HTML interpreter; for HTML interpreters that don't
yet support the banner API, the tags are still allowed. This support
will be withdrawn soon, though; we're just waiting until we're sure
that banner API support is available on all HTML interpreters.
- The compiler now assumes that each filename and folder name
specified in a ".t3m" file (a compiler makefile) is given relative to
the folder location of the .t3m file itself. This makes the compiler
essentially independent of the working directory when using a .t3m
file, because the location of the .t3m file effectively becomes the
working directory for any file and folder paths specified within.
This treatment naturally does not apply to any filename given in a
.t3m file with an absolute path (for example, a Unix path that starts
with "/", an MS-DOS path that starts with "\" or a drive letter, or a
Macintosh path that starts with a volume name), since an absolute path
is already independent of the working directory.
- The compiler now keeps information on the compiler version that
was used to compile a module. The compiler checks this information
and automatically rebuilds a module that was built by an older version
of the compiler. This ensures that all components of a program are
rebuilt whenever a new version of the compiler is installed. (In the
past, the compiler did not consider itself to be a dependency of the
derived files, which occasionally led to confusing link-time errors
caused by mismatched object file information.)
Changes for 3.0.5h (09/14/2002)
- Some slight additional performance optimizations in the VM should
improve execution speed by another 10% or so (vs. release 3.0.5g).
- Fixed a problem in the Dictionary class that caused spurious
run-time error when restoring games (particularly when restoring
after a RESTART operation had been previously performed).
- Fixed a problem in the regular expression parser: the
counted-repeat operator ({n,m}) did not nest properly with closures.
- Fixed a debugger problem that caused the debugger to fail to
take control (i.e., pause the game program and enter the debugger UI)
when a run-time error occurred under certain conditions when using
the "Step Out" or "Step Over" commands.
- Fixed a problem in the console-based text-only interpreters that
caused the [More] prompt to be displayed at the wrong place (at the
end of a line of text, rather than at the beginning) under certain
rare conditions.
Changes for 3.0.5g (09/08/2002)
- The Dictionary intrinsic class has been
substantially altered. The central change is that the caller can now
specify a "comparator" object that defines how strings in the
dictionary are compared to input strings; this allows the game to
customize the rules for looking up dictionary words. Related to this,
all methods related to truncation length have been removed; instead,
truncation, if desired, is now handled through the comparator.
Finally, the methods that look up words in the dictionary (findWord
and isWordDefined) have changed slightly to provide additional
information from the comparator about how an input word matches a
dictionary word.
- Added the StringComparator intrinsic
class. This class works with the Dictionary
intrinsic class to specify customized rules for matching input words
to dictionary words. StringComparator provides options that specify
whether or not upper- and lower-case letters are distinguished;
whether words can be truncated (abbreviated) on input, and to what
minimum length; and a set of equivalence mappings that allow
alternative spellings on input, such as using unaccented equivalents
of accented characters.
- The GrammarProd intrinsic class method
parseTokens() now uses the supplied Dictionary to perform comparisons
to literal tokens. Each input token is compared to literal tokens in
the grammar rules using the Dictionary's current comparator. Literal
tokens in grammar rules thus are matched using the same rules as
dictionary words. The matchValues() results are stored in the
match tree objects in the new property tokenMatchList: this property
is set in each object in the match tree, and contains a list of
the matchValues() results corresponding to the token list elements.
Changes for 3.0.5f (09/02/2002)
- Added the new method findReplace() to the String intrinsic class. This new method is
similar to the rexReplace()
function, but is slightly more efficient for situations where the text
to be replaced is a simple constant string rather than a regular
expression pattern. It's also slightly simpler to use, since it's not
necessary to worry about any special regular expression interpretation
of the search string.
- Added the new intrinsic class RexPattern. This new class encapsulates a
"compiled" regular expression pattern, which can be used in place of a
pattern string in the regular expression functions. Compiling an
expression converts it from a string into an internal representation.
When a particular pattern is used repeatedly in many searches, it's
much more efficient to use a RexPattern object to conduct searches
with the pattern, because the regular expression functions have to
compile their search patterns internally anyway; by using a
RexPattern, you perform the compilation for a particular pattern only
once, in advance, rather than each time you use the pattern.
Compilation takes a non-trivial amount of time, so if a pattern is
used frequently, pre-compiling it to a RexPattern can make a
difference in execution performance.
Changes for 3.0.5e (08/25/2002)
- This release has a number of VM, compiler, and intrinsic class
changes intended to make programs run faster. The compiler now
generates more optimized code (especially when compiling with no debug
information), and VM executes code faster. The changes should be
entirely transparent in terms of functionality, although a few new
VM instructions have been added, so code compiled with this new
version of the compiler will not run with older VM versions.
- Added two new LookupTable methods:
keysToList(), which returns a list consisting of all of the keys
in the table; and valsToList(), which returns a list consisting of
all of the values in the table. In both cases, the lists are in
arbitrary order.
- The compiler left out a final newline after the error/warning
count summary at the end of a compilation that generated error or
warning messages. This is now fixed.
- Fixed a couple of dialog messages in Workbench for Windows that
referred to ".t3x" files (the old version of the ".t3" extension).
- Fixed a problem in Workbench for Windows that caused an
unparseable compiler command line to be generated if an option
argument (such as an Include path) ended with a backslash. The
problem had to do with DOS's odd command-line quoting rules; the
trailing backslash was treated as "quoting" the quote mark at the end
of the option argument. This has been corrected.
- The compiler's command line error diagnostics are now somewhat
improved, to help pinpoint the source of an error. In the past, the
compiler always simply showed its usage message if the command line had
a problem, which didn't help much in identifying which argument was
causing the problem. The compiler now shows the usage message only
when the command line is empty (or when the argument "-help" is given);
in case of error, the compiler now shows a message explaining the
specific problem, and shows the particular option causing the problem
if appropriate.
- In Workbench for Windows, the folder selector dialog was started
with an empty current folder, which made the entire dialog appear
empty, in some cases (such as when adding a directory to the "Include"
list in the Build Settings dialog). The dialog should now always
start with a valid initial directory.
Changes for 3.0.5d (08/04/2002)
- Workbench for Windows now has a primitive but usable "profiling"
feature. Profiling is a technique in which the programmer collects
data on where the running program is spending its time. The purpose
is to identify any areas where the program spends a disproportionate
amount of time; this sometimes reveals obvious bottlenecks where the
code can be sped up with simple improvements, and in any case usually
reveals the areas where optimization efforts will yield the greatest
results. Workbench collects profiling data with function/method
granularity: each time the program enters or exits a function or
method, Workbench can track the time spent in that code. The user can
turn profiling on and off using the new "Profiler" menu; when
profiling is turned on, Workbench collects profiling data until the
profiler is turned off, at which point the system asks for a file to
which to write the collected data. Workbench writes the data as a
tab-delimited text file: the first column is the name of the function
or method; the second is the number of microseconds spent
directly in that code; the third is the number of microseconds
spent in functions or methods called by that code (which
excludes the time spent directly in the code itself); and the fourth
is the number of times the function or method was invoked. This
format can be easily loaded into an external analysis tool (such as a
spreadsheet application) for inspection. (The profiling facility is
designed mostly for use by library authors, so we probably won't
go to great lengths in the area of ease of use; and we don't expect
to build any integrated analysis tools, as a spreadsheet is more
than adequate to analyze the data.)
- Fixed some problems in the DOS interpreter's display management
(these are generic character-mode interpreter fixes that will also
take care of the same problems on Unix and other character-mode
systems). The problems affected resizing the terminal window,
interaction with "More" prompts in some situations, and cursor
placement under certain conditions. In addition, the "review mode"
status bar is back (it was missing from the first versions with the
banner API); note, though, that the mode bar is now displayed at the
top of the main game window rather than taking over the status line,
which is necessary because of the possibility the banner API creates
of non-standard status line layouts.
- Fixed a problem in the VM that could conceivably have caused
crashes or other misbehavior under certain extremely improbable
conditions involving stack overflows.
Changes for 3.0.5c (07/28/2002)
- The banner creation function bannerCreate() has a slightly modified
interface. The new interface allows the initial size of the banner to
be set in terms of the natural sizing units of the window; in addition,
percentage-based sizing is still possible as well.
- Percentage-based banner sizing now behaves slightly differently
than it used to. In the past, the percentage size was based on the size
of the complete application window. The percentage size is now based
instead on the "remaining space" at the point at which a banner is
laid out during the screen layout process.
- The new banner function bannerSetSize() complements
bannerSizeToContents() by adding the ability to set a banner's
size in terms of the natural sizing units of the window or a new
percentage-based size.
Changes for 3.0.5b (07/20/2002)
- Fixed a bug in the interpreter that caused sporadic crashes in
situations involving adding lots of new properties to an object (of
class TadsObject).
Changes for 3.0.5a (07/14/2002)
- A new set of functions, collectively called the
banner API, provides more direct programmatic
control over the appearance of the user interface than was available
in past versions of TADS. The new API allows the program to divide
the display into multiple "banners," which are non-overlapping windows,
each with its own independent output stream. The banner API provides
functionality based on the HTML TADS <BANNER> tag, but offers
more power, and is also supported on many text-only interpreters.
- Any time a nested object is defined, the compiler now automatically
defines the property lexicalParent in the nested object, setting
the property to a reference to the lexically enclosing object.
- The main text window's output stream is now always in HTML mode.
The "\{" and "\}" sequences have likewise been removed, since these
are no longer useful now that HTML mode cannot be switched on and off.
- The "\H+" and "\H-" output control sequences have been removed.
These are no longer useful now that HTML mode switching has been removed.
- The "\(" and "\)" output control sequences have been removed.
The HTML markups <B> and </B> should be used instead.
The "\(" and "\)" sequences are now redundant with the HTML <B>
markup, since text output streams are now always in HTML mode.
- A new system information code, SysInfoInterpClass, retrieves
information on the broad "class" of the interpreter. This returns
one of the following:
- SysInfoIClassText: a text-only character-mode interpreter, such as
MS-DOS TADS or Unix TADS. This type of interpreter uses a single
fixed-pitch font to show all text, cannot show any graphics, and
uses the text-only HTML subset.
- SysInfoIClassTextGUI: a text-only interpreter running on a graphical
platform, such as MacTADS or WinTADS. This type of interpreter
might use proportionally-spaced fonts, and might use multiple fonts.
These interpreters cannot show graphics using HTML, but they might
use some graphics of their own for things like window borders.
This type of interpreter recognizes the text-only HTML subset.
Note that this code is not indicative of the type of OS, but rather
of the type of interpreter: MS-DOS TADS always returns
SysInfoIClassText, even when it's running in a DOS box under
Windows, because it still acts like a character-mode interpreter
even when running on a Windows machine.
- SysInfoIClassHTML: a full HTML interpreter, such as HTML TADS on
Windows, or HyperTADS on Macintosh.
- The SysInfoHtml and SysInfoHtmlMode system information codes have
been eliminated. The former is superseded by SysInfoInterpClass, and
the latter has been rendered obsolete by the elimination of HTML mode
switching.
- The TADS 3 character-mode interpreters now support the <TAB>
tag, if the underlying OS code allows. This tag is supported on all
full HTML interpreters, plus most character-mode text-only platforms.
The GUI text-only interpreters do not support this currently. The
full complement of <TAB> features is supported; see the HTML TADS
documentation (specifically, the TADS-specific markup extensions) for
details.
- The compiler and VM support "transient" objects, which are objects
that do not participate in any of the VM's built-in persistence
mechanisms (save, restore, undo, restart). A transient object is
not saved to a saved state file, and is not affected by restore, undo,
or restart operations. This is described more fully in the
Object Definitions section of
the documentation.
- The saveGame function works
differently than it used to. The function no longer saves the
execution context, so it no longer has the "setjmp" behavior.
- The restoreGame function
works differently as well. Because saveGame no longer saves the
execution context, restoreGame no longer restores it, so the function
simply returns on successful completion - it doesn't have the
"longjmp" behavior any more. This new design is much more flexible,
because it allows arbitrary session information to be retained
across the Restore operation, via local variables on the stack as
well as with transient objects, and gives the program complete
control over execution flow throughout the operation.
- The restartGame function
also has a new design. The function no longer requires a function
to jump to, but simply resets object state and returns. As with the
restoreGame changes, this allows the program complete control over
execution flow and allows any amount of session information to
be retained across the Restart operation.
- All instances of the File intrinsic
class are now transient. The static creation methods of the File
class always return transient objects.
- It is now possible to open "resources" as though they were files,
and read their data using the File intrinsic
class. Two new static construction methods make this possible:
openTextResource() and openRawResource().
- The option flags for the String.htmlify() method have been renamed,
to make the names of the flags more descriptive of their functions.
The flags formerly were of the form HtmlifyKeepXxx, but now use names
of the form HtmlifyTranslateXxx. The change of terms to "translate"
is a better match for what the flags actually mean, since the flags
specify that certain characters are to be translated into HTML markup
equivalents.
- In Workbench for Windows, when the status line is displayed, the
messages from the compiler showing the build progress are not displayed
to the debug log window, but rather to the status line. This makes it
much easier to read the results in the log window, and especially makes
it easier to see the error messages, since the error messages aren't
mixed in with lots of build progress messages. When the status line
is hidden, build progress messages are still shown in the log window
so that the compiler's progress can be seen.
- The internal character encoding that the T3 software was using
in past versions was not in conformance with the T3 specification, which
calls for the standard UTF-8 encoding. The software was using an older
encoding that had been obsoleted in the spec but was never changed in
the software. This has been corrected; note that this change requires
recompiling any existing games.
- Due to a bug, Workbench for Windows did not properly store directory
paths (such as for the Include path list) in the project file when the
paths included a colon (":") character. This has been fixed.
- A bug in Workbench for Windows caused the Window menu to display
incorrect entries for Windows 95 and NT 4 (actually, this is more due
to a bug in Windows 95 and NT 4, but Workbench didn't work around the
bug, so in a sense it was a Workbench bug). This has been corrected.
- A compiler bug caused the compiler to crash (with an access
violation or equivalent) when given a source file whose very first
object definition started with a template containing a double-quoted
string with an embedded expression. This problem is now fixed.
Changes for version 3.0.4 - 06/01/2002
- Fixed a problem in the Vector intrinsic class that caused interpreter
crashes under certain circumstances. (The exact conditions were not
entirely predictable, because the problem had to do with an interaction
between the Vector class, the garbage collector, and the undo mechanism,
and only occurred when garbage collection was triggered after certain
operations in the Vector class.)
- Added a status line to Workbench for Windows. The status line is
optional; it can be displayed or hidden, as desired, using the "View" menu.
When displayed, the status line shows whether or not the program being
debugged is running, and shows the line and column number of the current
cursor position when a source file window is active.
- Fixed a problem in Workbench that prevented parts of the window
layout from being saved in the project configuration file when the
main Workbench application window was closed while the program being
debugged was still running.
Changes for 05/19/2002
- The DOS text-mode interpreter now supports setting text colors.
Text colors can be set through HTML, as follows:
- The <FONT COLOR=xxx BGCOLOR=yyy> tag can be used to set the
and background colors of the text. The basic set of HTML colors is
recognized, although
the effective set of available colors is limited to the eight ANSI
colors that DOS character mode can display: white, black, red, green,
blue, yellow, cyan, and magenta. Hex RGB values (for example,
<FONT COLOR='#C080E0'> are accepted, but these are simply
mapped to the nearest available color from the ANSI set.
Note that if a FONT tag specifies both COLOR and BGCOLOR, the text
will be displayed exactly as specified; if the FONT tag specifies
only COLOR, then the background color will be inherited from the
enclosing text, and ultimately from the <BODY> color if no
enclosing text has a specific background color.
- The <BODY> tag can be used to set the foreground and background
color of the window. The TEXT attribute sets the foreground text color,
and the BGCOLOR attribute sets the background color of the window.
The background color affects the entire window, just as in the
HTML interpreters, so the entire window will be redisplayed in its
new color whenever a <BODY BGCOLOR=xxx> tag is displayed.
- The parameterized color names (TEXT, BGCOLOR, STATUSTEXT, STATUSBG)
are accepted and map to the current settings of those colors, as set
by the TRCOLOR program.
- The new system information code SysInfoTextColors can be used to
determine the level of color support available on the platform. The
return value is a code indicating the level of support:
- SysInfoTxcNone - no color support
- SysInfoTxcParam - parameterized color names only
- SysInfoTxcAnsiFg - The eight ANSI colors are available for text, but
there is no capability to set the background color
- SysInfoTxcAnsiFgBg - the ANSI colors are available for text and
background colors (this is the code the DOS interpreter returns)
- SysInfoTxcRGB - full RGB text color support is available (this is the
code the Windows HTML interpreter returns)
- The new system information code SysInfoTextHilite can be used to
determine whether or not text highlighting is available. This returns
true if a distinctive appearance for <B> text is available,
nil if not. The HTML interpreters return true for this; the text-only
interpreters generally return true, unless running in "plain" ASCII
mode or with a terminal or display device that cannot render anything
special for highlighted text.
Changes for 05/05/2002
- Fixed a problem in Workbench for Windows with libraries (.tl
files) found via the library search path. In some cases, the files
within a library could not be opened; in addition, the library itself
was not always properly scanned on opening the project, so no files
within the library were visible in the Project window. Libraries
found via the search path should work properly now.
- Workbench for Windows now uses small (8x8-pixel) icons in the left
margin of debugger source windows when the selected source window font
is smaller than the standard (16x16-pixel) icons. (These are the icons
that show the location of the current line, breakpoints, and so on
during a debugging session.) This allows more lines to be displayed
vertically in a source window when a small font is selected.
- When quitting out of Workbench, if a build is still running, the
Workbench displays a dialog indicating that Workbench is waiting for
the build to complete. In the past, there was no way to force
Workbench to exit if the build process had become stuck. Now, the
"waiting for build" dialog offers an "Abort" button; clicking this
button will forcibly terminate the build, allowing Workbench to
terminate immediately. This button is useful when the build process
becomes stuck (which ideally should never happen, but has happened
at times due to compiler bugs). The build process should not normally
be aborted forcibly unless the build appears stuck, because forcibly
terminating a process on Windows can occasionally cause Windows to
become unstable.
- Fixed a compiler bug that made it possible for the linking step
to get stuck in an infinite loop if the data associated with a particular
"grammar" production became too large. This should no longer occur.
- Fixed a debugger bug that caused sporadic crashes when running
games in Workbench.
- Added new systemInfo() codes for MNG display:
- SysInfoMng - can the system display MNG images?
- SysInfoMngTrans - can the system display MNG's with transparency?
- SysInfoMngAlpha - can the system display MNG's with alpha channels
(i.e., partial transparency)?
Changes for 04/28/2002
- Renamed numerous macros in the system and adv3 header files to
achieve more consistency in the naming scheme. Here's a table of
the changes. (Sorry this isn't a Perl script or something.)
Old Name | New Name
|
---|
BIGNUM_SIGN | BignumSign
|
BIGNUM_EXP | BignumExp
|
BIGNUM_EXP_SIGN | BignumExpSign
|
BIGNUM_LEADING_ZERO | BignumLeadingZero
|
BIGNUM_POINT | BignumPoint
|
BIGNUM_COMMAS | BignumCommas
|
BIGNUM_POS_SPACE | BignumPosSpace
|
BIGNUM_EUROSTYLE | BignumEuroStyle
|
TYPE_NIL | TypeNil
|
TYPE_TRUE | TypeTrue
|
TYPE_OBJECT | TypeObject
|
TYPE_PROP | TypeProp
|
TYPE_INT | TypeInt
|
TYPE_SSTRING | TypeSString
|
TYPE_DSTRING | TypeDString
|
TYPE_LIST | TypeList
|
TYPE_CODE | TypeCode
|
TYPE_FUNCPTR | TypeFuncPtr
|
TYPE_NATIVE_CODE | TypeNativeCode
|
TYPE_ENUM | TypeEnum
|
PROPDEF_ANY | PropDefAny
|
PROPDEF_DIRECTLY | PropDefDirectly
|
PROPDEF_INHERITS | PropDefInherits
|
PROPDEF_GET_CLASS | PropDefGetClass
|
STR_HTML_KEEP_SPACES | HtmlifyKeepSpaces
|
STR_HTML_KEEP_NEWLINES | HtmlifyKeepNewlines
|
STR_HTML_KEEP_TABS | HtmlifyKeepTabs
|
STR_HTML_KEEP_WHITESPACE | HtmlifyKeepWhitespace
|
T3DBG_CHECK | T3DebugCheck
|
T3DBG_BREAK | T3DebugBreak
|
OBJ_INSTANCES | ObjInstances
|
OBJ_CLASSES | ObjClasses
|
OBJ_ALL | ObjAll
|
REPLACE_ONCE | ReplaceOnce
|
REPLACE_ALL | ReplaceAll
|
GETTIME_DATE_AND_TIME | GetTimeDateAndTime
|
GETTIME_TICKS | GetTimeTicks
|
INEVT_KEY | InEvtKey
|
INEVT_TIMEOUT | InEvtTimeout
|
INEVT_HREF | InEvtHref
|
INEVT_NOTIMEOUT | InEvtNotimeout
|
INEVT_EOF | InEvtEof
|
INEVT_LINE | InEvtLine
|
INEVT_END_QUIET_SCRIPT | InEvtEndQuietScript
|
INDLG_OK | InDlgOk
|
INDLG_OKCANCEL | InDlgOkcancel
|
INDLG_YESNO | InDlgYesNo
|
INDLG_YESNOCANCEL | InDlgYesNoCancel
|
INDLG_ICON_NONE | InDlgIconNone
|
INDLG_ICON_WARNING | InDlgIconWarning
|
INDLG_ICON_INFO | InDlgIconInfo
|
INDLG_ICON_QUESTION | InDlgIconQuestion
|
INDLG_ICON_ERROR | InDlgIconError
|
INDLG_LBL_OK | InDlgLblOk
|
INDLG_LBL_CANCEL | InDlgLblCancel
|
INDLG_LBL_YES | InDlgLblYes
|
INDLG_LBL_NO | InDlgLblNo
|
INFILE_OPEN | InFileOpen
|
INFILE_SAVE | InFileSave
|
INFILE_SUCCESS | InFileSuccess
|
INFILE_FAILURE | InFileFailure
|
INFILE_CANCEL | InFileCancel
|
FILETYPE_LOG | FileTypeLog
|
FILETYPE_DATA | FileTypeData
|
FILETYPE_CMD | FileTypeCmd
|
FILETYPE_TEXT | FileTypeText
|
FILETYPE_BIN | FileTypeBin
|
FILETYPE_UNKNOWN | FileTypeUnknown
|
FILETYPE_T3IMAGE | FileTypeT3Image
|
FILETYPE_T3SAVE | FileTypeT3Save
|
SYSINFO_VERSION | SysInfoVersion
|
SYSINFO_OS_NAME | SysInfoOsName
|
SYSINFO_HTML | SysInfoHtml
|
SYSINFO_JPEG | SysInfoJpeg
|
SYSINFO_PNG | SysInfoPng
|
SYSINFO_WAV | SysInfoWav
|
SYSINFO_MIDI | SysInfoMidi
|
SYSINFO_WAV_MIDI_OVL | SysInfoWavMidiOvl
|
SYSINFO_WAV_OVL | SysInfoWavOvl
|
SYSINFO_PREF_IMAGES | SysInfoPrefImages
|
SYSINFO_PREF_SOUNDS | SysInfoPrefSounds
|
SYSINFO_PREF_MUSIC | SysInfoPrefMusic
|
SYSINFO_PREF_LINKS | SysInfoPrefLinks
|
SYSINFO_MPEG | SysInfoMpeg
|
SYSINFO_MPEG1 | SysInfoMpeg1
|
SYSINFO_MPEG2 | SysInfoMpeg2
|
SYSINFO_MPEG3 | SysInfoMpeg3
|
SYSINFO_HTML_MODE | SysInfoHtmlMode
|
SYSINFO_LINKS_HTTP | SysInfoLinksHttp
|
SYSINFO_LINKS_FTP | SysInfoLinksFtp
|
SYSINFO_LINKS_NEWS | SysInfoLinksNews
|
SYSINFO_LINKS_MAILTO | SysInfoLinksMailto
|
SYSINFO_LINKS_TELNET | SysInfoLinksTelnet
|
SYSINFO_PNG_TRANS | SysInfoPngTrans
|
SYSINFO_PNG_ALPHA | SysInfoPngAlpha
|
STATMODE_NORMAL | StatModeNormal
|
STATMODE_STATUS | StatModeStatus
|
SCRFILE_QUIET | ScriptFileQuiet
|
SCRFILE_NONSTOP | ScriptFileNonstop
|
CHARSET_DISPLAY | CharsetDisplay
|
CHARSET_FILE | CharsetFile
|
firstPerson | FirstPerson
|
secondPerson | SecondPerson
|
thirdPerson | ThirdPerson
|
spellIntTeenHundreds | SpellIntTeenHundreds
|
spellIntAndTens | SpellIntAndTens
|
spellIntCommas | SpellIntCommas
|
Logical | logical
|
LogicalRank | logicalRank
|
LogicalRankOrd | logicalRankOrd
|
Dangerous | dangerous
|
NonObvious | nonObvious
|
IllogicalNow | illogicalNow
|
Illogical | illogical
|
Inaccessible | inaccessible
|
DefaultReport | defaultReport
|
MainReport | mainReport
|
ReportBefore | reportBefore
|
ReportAfter | reportAfter
|
ReportFailure | reportFailure
|
IsNonDefaultReport | gIsNonDefaultReport
|
SingleDobj | singleDobj
|
SingleIobj | singleIobj
|
DobjList | dobjList
|
IobjList | iobjList
|
NumberPhrase | singleNumber
|
TopicPhrase | singleTopic
|
LiteralPhrase | singleLiteral
|
DirPhrase | singleDir
|
- Added Phil Lewis's new Adv3 Reference Help to Workbench for
Windows. This new Windows Help file is a reference to the classes
in the adv3 library; Phil created it for his own use but has
graciously offered it for inclusion in the Author's Kit distribution.
Phil says the reference isn't complete, but it has a wealth of
information all the same. The Adv3 Help can be reached from the
"TADS 3 Library" item on the Workbench "Help" menu.
- The compiler can now search for source files using a
user-specified list of directories. This allows makefiles (.t3m
files) to specify source files using only relative filename paths,
eliminating any dependency in a makefile on the local system's
directory structure and thus allowing the project to be easily used on
other systems. The compiler searches for its files by looking in the
following locations, in order:
- The current working directory (for Workbench users, this is the
directory containing the .t3m file for the project).
- The directories specified with "-Fs" compiler options, in the
order of the options.
- The directories specified with the new "user library" mechanism.
- The "system library" directory. This is the special directory
containing the compiler's own libraries. This directory varies
by system, but it is normally set up automatically when TADS is
installed and requires no user action to configure.
The "user library" list is specified using a system-dependent
mechanism:
- For the DOS/Windows command-line compiler (i.e., run from a
command prompt), set the environment variable TADSLIB
to a list of directories, separated by semicolons (";").
- For Workbench for Windows, enter the list of directories in
the "Libraries" page of the Workbench preferences dialog,
reachable from the "Options" item on the "View" menu.
- The mechanisms for other systems are yet to be determined,
but in all likelihood Unix will use the same TADSLIB
environment variable as the DOS version.
- Workbench for Windows has a new option to automatically load
the most recent project when Workbench is started. To set the
start-up mode, use the "Start-Up" page of the Workbench preferences
dialog, reachable from the "Options" item on the "View" menu.
- Added the new systemInfo() code SysInfoOgg, which senses whether
or not the interpreter supports Ogg Vorbis audio playback.
- Changed inputEvent() so that it accepts a nil timeout
argument value, for consistency with inputLine(). A nil
value for the timeout is equivalent to omitting the timeout argument
entirely: it indicates that the input should be allowed to proceed
indefinitely.
- The compiler now stores preprocessor symbol (macro) definitions
with the debugger records of the compiled program, when compiling
for source-level debugging (i.e., using the "-d" compiler command-line
option). The debugger uses the preprocessor symbols when parsing
expressions during the debugging session, so it is now possible
to interactively evaluate expressions involving macros. Note that
the compiler keeps debugging records for a macro only if the macro
(1) is never undefined (using #undef) or redefined with a different
expansion within a given module, and (2) has the exact same expansion
in every module in which it is defined; these restrictions mean that
only macros with consistent "global" meanings across the entire
program are visible in the debugger.
- Fixed a problem in Workbench for Windows that caused an incorrect
name to be stored for the game's initial source file when creating a
new project.
- Fixed a compiler problem that caused the compiler to crash when
confronted with a constant index expression where the indexed value
was not a list (e.g., 1[1]).
- Fixed a problem in the Windows HTML interpreter that prevented
interrupted command lines from continuing correctly. When a command
line input was interrupted by a timeout, the command line that was
under construction when the timeout occurred was not properly restored
for further editing. This has been corrected.
- Fixed a problem in the VM that caused the VM to crash under rare
circumstances. The problem was particularly likely to occur when
stepping through large amounts of code with the debugger.
- Fixed a problem in the character map compiler (mkchrtab) that
generated corrupted character map files when the source file had
duplicated display mapping entries.
- The distributions (including the installer kits and the source
code distribution) now include a full set of character mapping files
that should cover most users on most platforms. For a listing of
the included codings, see charmap/README.txt. (The full set adds
only about 25k to the compressed distribution files, which seems a
small cost for the simplicity of having an essentially universal set
of mappings available with the default install.)
- The Windows Author's Kit installer now associates .t3m files with
Workbench, so that double-clicking on a .t3m file from Windows
Explorer will open the file in Workbench. (The 4/7/2002 version still
set the association for .t3c files instead, despite Workbench's switch
to .t3c files for storing project configuration information.)
- Fixed a problem that caused the compiler to display the incorrect
text for invalid tokens in certain error messages related to 'grammar'
statement syntax.
Changes for 04/07/2002
- Workbench for Windows now uses the compiler makefile (.t3m) file
format to store its project information. This means that a Workbench
project file can be used directly as a compiler makefile, using
the compiler's "-f" option. For the moment, Workbench is still capable
of loading
- Workbench on Windows now monitors for Ctrl+Break, and breaks into
the debugger when this key combination is detected. This allows
easily breaking into the debugger if the .t3 program enters an
infinite loop.
- The 'replace' and 'modify' keywords can now be used to change
'grammar' definitions. Refer to the Grammar
Rules documentation for details.
- A grammar production object can now be declared without creating
any rules associated with the production. The new syntax is simply
"grammar production_name;" (that is, a "grammar" statement that
simply ends after the name of the production). This can be useful for
libraries that want to define rules that refer to productions for
which the library itself provides no rules, so that games based on the
library can fill in the grammar definitions for the productions. In
the past, if a production was referenced as a subproduction from one
or more rules but had no rules of its own defined, the linker
generated an error, because it is likely in such cases that the rules
referring to the undeclared production were misspelled and meant to
refer to a declared production; this new syntax gives the author a way
to tell the compiler explicitly that a production name was used
intentionally, even if the production has no rules.
- Added new syntax that allows multiple part-of-speech properties
(such as "noun" or "adjective") to be used as a single token matcher
in a grammar rule. The new syntax uses a list of properties in
angle brackets: <noun adjective plural>. When
this syntax is used, an input token matching any of the part-of-speech
properties in the list matches the rule token position.
- Moved the "build configuration" information that was formerly
stored in object (.t3o) files into the symbol (.t3s) files instead.
The compiler uses the build configuration data stored in these files
to determine if recompilation of a given source file is necessitated
by build configuration changes since the last time the file was
compiled. In the past, when the information was stored in the object
files, the compiler unnecessarily regenerated symbol files repeatedly
when compilations failed due to syntax errors, because compilation
didn't get far enough to store the build data. Moving the information
to the symbol files allows the compiler to skip symbol table
generation when a previous compilation generated a valid symbol file
for a given module. This saves time in the build-edit-build cycle
when a program is initially compiled and contains syntax errors.
- Added two new pseudo-variable keywords: targetobj and
definingobj. These pseudo-variables are similar to
self and targetobj, in that they act like
read-only variables (i.e., you cannot assign values to them), and
they are automatically maintained by the interpreter to keep track
of the current method context. targetobj returns the "original
target object" of the current method; this is the object that was
targeted by the method call that reached the current method. The
target object is set each time a method is called normally or via
delegated, and remains the same as methods are invoked
via inherited. definingobj is the object that
defines the currently executing method; this is normally simply
the object where the method was actually defined in the program's
source code.
- Removed the getMethodDefiner() intrinsic function from
the "tads-gen" function set. This function has been replaced by
the new pseudo-variable definingobj.
- Changed the interface of the Object.propInherited() intrinsic
class method. The method now takes an additional argument (positionally
the second argument in the new interface) giving the original target
object of the call. In cases where the caller wishes to know
if the currently active method can inherit a base class method, the
value for the new argument should simply be targetobj.
- Changed the way inherited behaves after
delegated is used. In the past, the inheritance mechanism
tried to find the defining object of the method with the
inherited operator in the inheritance tree of "self". After
delegated, the defining object is normally not related by
inheritance to "self", so the old search pattern normally failed to
find any inherited instance of the method. Now, the interpreter keeps
track internally of the "original target" object in addition to the
"self" object; the original target is always the target of the last
explicit method call or the target of the most recent
delegated operator. The inherited operator uses the
original target object as the starting point of the inheritance tree
search, rather than "self"; this allows inherited to find
methods inherited from base classes of the delegatee when appropriate.
- Fixed a compiler bug that caused incorrect code to be generated
for statements like this: if (constant_expr &&
non_constant_expr) - that is, an "if" whose condition
expression consists of a constant expression (i.e., an expression
whose value can be determined at compile-time) and a non-constant
expression joined by the "&&" operator. The code that the
compiler generated caused unpredictable results at run-time, and was
able to crash the interpreter in some cases. This has been corrected.
- Increased the standard VM stack size to 4096 stack slots (from 1024).
- Expanded the compiler's maximum symbol length to 80 characters,
to accomodate the longer symbols generated by the new treatment of
production match object tagged names as actual compiler symbols.
- Fixed a problem that caused a sporadic interpreter crash when
using restartGame(). This crash occurred only rarely, and was related
to memory management during program re-initialization. This should no
longer occur.
- Fixed a problem with restoreGame() that caused modifications to
intrinsic classes to be lost in some cases. This problem occurred
rarely, and should no longer occur.
- Changed the character mapping input file format slightly. The
"unicode_to_local" keyword has been renamed to "display_mappings",
and has a slightly different effect: in the "display_mappings"
section, each character mapping gives the Unicode expansion
of a Unicode code point; that is, each mapping specifies a set of
Unicode characters to substitute for the Unicode character being
mapped. The expansion is then further translated automatically by
the character mapper to the local character set. Each expansion
must map to characters defined in the one-to-one mapping
section (i.e., the set of mappings before the "display_mappings"
keyword). Note in particular that an expansion cannot
map to characters that are themselves further expanded. The purpose
of this change is to allow the interpreter to perform expansion
mappings - that is, mappings that can translate one Unicode character
to several display characters - while still in the Unicode domain,
and hence to perform operations such as word-wrapping on the expansions.
The console output formatter uses this to properly word-wrap lines with
expanded display mappings.
Changes for 03/16/2002
- Fixed script-reading mode in the interpreter. Past versions did
not correctly read input scripts (using the command-line interpreter's
"-i" option, for example).
- Added the new input event code INEVT_END_QUIET_SCRIPT, which is
described in the documentation for the
inputLineTimeout
intrinsic function.
- Added a couple of small usabilty enhancements to Workbench for Windows:
- Pushing the Return/Enter key when keyboard focus is in the Project
window opens the selected module in a source file window, if a module
is selected. This allows easier keyboard navigation of the Project
file list.
- Double-clicking on a module in the Project window now moves keyboard
focus to the newly-opened source file window. In the past, focus
stayed on the Project window, so context-sensitive commands (such
as "Find") did not apply to the newly-opened source window until
manually clicking on the window to activate it.
- Fixed a bug in mkchrtab (the character map compiler)
that caused incorrect mappings in some compiled mapping files having
display (from_unicode_to_local) mappings that expanded to more than
one byte.
- Fixed a problem in the Windows interpreter that made it
incompatible with Windows 95. The interpreter should once again be
compatible with Windows 95.
Changes for 03/10/2002
- Added the new method removeElement() to the
Vector intrinsic class. This new method removes an element by
value, modifying the vector in-place.
- Added the new method forEachWord() to the
Dictionary intrinsic class. This new method provides a way of
enumerating all of the entries in a Dictionary object.
- Added information to the LICENSE.TXT file making it clear that
derived versions of the library are permitted with few restrictions.
- The "!" operator can now take an object reference as its operand;
when applied to a non-nil object reference, "!" yields nil. This
means that constructs such as "if (!obj)" are now treated as equivalent
to "if (obj == nil)"; such constructs formerly generated a run-time
error. In addition, property ID's, single-quoted strings, lists,
and function pointers can all be used as operands of "!", and "!"
applied to any of these types yields nil.
- Fixed a compiler bug that caused the compiler to crash in some
cases when confronted with an empty pair of parentheses within a
grammar rule, such as grammar myProd: ('mytoken' ()).
- Fixed a compiler bug that caused the compiler to crash in some
cases when given a method definition with no code body and the end of
the object immediately following.
- Fixed a compiler bug that caused incorrect code generation for
an 'if' with a constant controlling expression that evaluated to
true and no 'else' clause. In such cases, the true branch of the
'if' was not generated; this has been corrected.
- The project file extension for Workbench for Windows is now
".t3c" (it was formerly ".tdc", the same as it was for the TADS 2
Workbench). The extension has been changed to allow the Windows
desktop to launch the appropriate version of Workbench when the user
double-clicks a project file from the desktop and both TADS 2 and
ADS 3 Workbench versions are installed.
- Fixed a problem in the VM that caused repeated "terminate game"
dialogs to appear in Workbench for Windows when the user attempted
to compile the game after the debugger intercepted a run-time error.
- Fixed a problem in the character map compiler (mkchrtab) that
caused invalid map files to be generated if the source file had more
than one symmetric (bidirectional) mapping assigned to the same
Unicode code point. The character map compiler now generates a
warning when these collisions occur, and generates valid map files
even when collisions are present by ignoring redundant mappings.
Changes for 02/17/2002
- The compiler now shows a summary count of warnings and errors at
the end of the compiler console output when either count is non-zero,
to make it more obvious that messages were generated during the
compilation. If many modules are included in a compilation, the
status messages that the compiler generates as it works through the
module list can make it easy to miss an error or warning mixed in
among all the status messages. The new summary at the end of the
compilation should make it easier to notice when something requires
attention. No summary counts are displayed when there are no warnings
or errors; this is intended to make it even easier to notice when
something is wrong, since authors will not be accustomed to seeing
a summary count at all when everything is well.
- The Iterator intrinsic class has the new
methods getCurVal() and getCurKey(), which return the value and key
of the current element of the iteration, respectively. For indexed
collections, the "key" is the index of the current element.
- LookupTable.forEach() no longer passes the key argument to the
callback. If the key is desired, use the new method forEachAssoc()
instead. This allows LookupTable to be used more interchangeably
with other Collection subclasses, since its forEach() method has the
same interface as the corresponding method of other Collection
subclasses.
- LookupTable, List, and Vector now have the additional method
forEachAssoc(func), which calls func(key,val) for each element of
the collection. For List and Vector, the "key" is the index of
the element; for LookupTable, it is the key for the entry.
- The Array intrinsic class has been deleted; Vector should be used
instead. The Array class was too similar to the Vector class to
justify its existence as a separate type, so the functionality of
Array and Vector are now combined into the single Vector class.
- When a Vector is used as the left-hand side of a '+' or '-'
operation, in the past, the VM modified the left-hand side Vector
object directly. This has been changed so that a new Vector is
created, and the original left-hand Vector is left unchanged. The
old behavior was confusing in that it gave the '+' and '-' operators
side effects, which is inconsistent with the behavior of the
operators in other situations.
- A new Vector method, appendAll(), allows appending the individual
elements of a List or Vector to another Vector in-place (i.e., without
creating a new Vector object, as the '+' operator does).
- The Vector methods getUnique() and subset() now return a new
Vector to store the result of the operation. In the past, these
methods modified the original Vector in place.
- In the past, when a Vector was used as the right-hand side of a
'+' operator whose left-hand side was a List or Vector, the List or
Vector on the right was the single new element concatenated to the
left-hand collection. This was inconsistent with the handling of
List values; a List value concatenates its elements individually when
used as the right-hand side of a '+' operator. For consistency,
Vector now concatenates its elements individually when used on the
right side of a '+' operator. Similarly, Vector values now subtract
their elements from the left-hand side collection when used as the
right-hand side of a '-' operator, also for consistency with the List
type's behavior.
- Fixed a problem in the VM that caused the VM to lose track of
intrinsic class modifiers after a RESTORE operation. Intrinsic
class modifiers will now properly survive RESTORE operations.
Changes for 02/09/2002
- Changed inputLineTimeout so that it accepts a nil
timeout argument value. A nil value for the timeout is equivalent to
omitting the timeout argument entirely: it indicates that the input
should be allowed to proceed indefinitely.
- Improved inputLineTimeout's interaction with the OS
layer so that the portable code can handle complete non-implementation
of input-with-timeout by the OS layer.
- Changed getTime(GETTIME_TICKS) so that the function always
chooses the zero point of the system clock as the time of the first
call to the function. This reduces the likelihood that a game will
encounter a roll-over of the system clock, which could lead to confusion
in interpreting time differences and the ordering of events.
- Changed the names of two methods in the LookupTable intrinsic
class. The method formerly called countBuckets() is now
getBucketCount(), and the method formerly called countEntries() is
now getEntryCount(). These names match the names as given in the
documentation, but the header file (lookup.h) had the old names.
- Added the compiler option "-clean", which causes the compiler
to skip ordinary compilation and instead simply remove all derived
files that the compilation would have produced; in particular, this
removes the symbol (.t3s), object (.t3o), and image (.t3) files that
the compilation would have produced.
- Added the compiler option "-Pi", which causes the compiler to
skip ordinary compilation and instead write to the standard output a
list of files included with #include directives throughout
the program. The compiler runs the normal preprocessing, and shows
only files included in conditional compilation sections that are
selected in the compilation (in other words, the list does not
include any files included from within the false branches of
#if or other conditional compilation directives). In the
generated list, the files are listed one file per line, and each line
specifying a file consists of the characters "#include",
followed by a single space, followed by the name of the included
file, followed by a newline sequence. The name of the included file
is not enclosed in any quote marks or other delimiters. This format
is intended to simplify automatic processing of the list by clearly
marking each line in the output that names an included file. Note
that the list of included files might include a given file more than
once, because each file is listed as it's included, and it is possible
to include a given file more than once.
- When the compiler is run with the "-P" option (which writes the
preprocessed version of the source to standard output), the compiler
now prefixes the generated source with the directive #charset
"utf8" to indicate the character set of the preprocessed source.
- Added a compiler warning message when the preprocessor finds a
line that ends with a backslash followed by whitespace. While this
format is legal (because it could be useful in defining a macro that
is later "stringized"), it is highly unusual. Since trailing spaces
are not usually visible in a text editor, the programmer might not
be aware of their presence; and since the presence of the trailing
spaces materially changes the meaning of the program, the compiler
warns about them. Note that the warning can be suppressed by adding
a comment at the end of the line; this doesn't change the meaning
of the program but does make the spaces visually evident in a text
editor, so the compiler recognizes that the warning is not necessary
in this case.
- Fixed a VM problem that caused the garbage collector to
incorrectly delete intrinsic class objects under certain unusual
circumstances. When an intrinsic class is used implicitly but never
specifically declared in the compiled program, the VM creates an
object to represent the intrinsic class during the initial program
load. In the past, it was possible for the garbage collector to
regard such an object as unreachable even though it is always
reachable via the native code implementing its corresponding
intrinsic class. This problem sometimes led to VM crashes. The
problem should no longer occur.
- Fixed a compiler problem that caused incorrect compilation for a
grammar rule specified with an alternation (two or more sub-rules,
each separated by an "|" symbol) and an empty final sub-rule. In
such cases, the compiler incorrectly generated two copies of the
empty sub-rule, leading to two match objects being created at
run-time each time the empty sub-rule was matched. This has been
corrected.
- Changed inherited so that it searches for the next
inherited definition of the property as though the currently active
method (and any overriding definitions) had simply never been
defined. This makes inherited work roughly the same way as
the inheritNext method that was formerly defined in the
MixIn class in the adventure game library (adv3).
- Added a new Object method, propInherited, which
determines if a method is inherited, using the new rules of the
inherited operator. This provides functionality equivalent
to the canInheritNext method formerly defined in the
MixIn class in the adventure game library.
Changes for 01/13/2002
- The compiler can now read "library"
files, which are lists of
source files to be included in the compilation. Library files can be
used to simplify compiler command lines and makefiles when including
sets of source files that usually act as a group, such as the
standard adventure library sources.
- Workbench can now show library files in the project window. You
can add a library file to the project window's source file list in
the same way as you can add a source file; the library shows its
contained source files as a subtree. Each source file within a
library is shown with a checkbox, indicating whether or not the file
is included in compilations; if you want to exclude a file within a
library from compilation, click on the checkbox to remove the
checkmark. The checkbox settings are stored with the project and
don't affect the library itself, so you can use the same library in a
different project, and include and exclude different sets of files.
- The debugger no longer uses a RuntimeError exception to terminate
the program being debugged. In the past, when the user terminated
the running program using the debugger "Stop" button, or by starting
a new compilation of the program while the program was still running,
the debugger attempted to terminate the program by throwing a
RuntimeError with system error code 2390. This approach wasn't
completely reliable, because it allowed the running program to
catch the exception and keep running; programs sometimes inadvertantly
caught the error as part of an inclusive "catch" handler, causing
strange interactions with the debugger user interface. The debugger
now halts the program by telling the VM not to execute any more program
instructions, which guarantees that the program stops immediately.
This new approach should be much more robust and should avoid the
strange effects that sometimes occurred with the old mechanism.
- Fixed a problem in the compiler that caused the compiler to hang
when given a makefile (a .t3m file) that didn't end with a newline
character.
- Fixed a compiler problem that generated an incorrect set of
grammar rule patterns for grammars involving nested alternatives
(i.e., parenthesized "|" expressions). In the past, the compiler
incorrectly generated multiple copies of the top-level expressions
in such rules, leading to run-time generation of multiple redundant
matches for these expressions. This has been corrected; the compiler
now generates only one copy of each top-level rule in an alternation.
- Fixed an interpreter problem that caused the interpreter to crash
when an HTML <TITLE> tag was displayed.
- Fixed a problem in the debugger that caused memory leaks and
other incorrect behavior when the user attempted to run the program,
but the program had not been compiled (or had not been compiled with
debugging information).
- When Workbench needs to find a source file during program tracing
in the debugger, it now scans the project list to find the file. In
the past, the debugger used only the source path to find files,
leading to annoying interactive requests to locate files that were in
plain view in the project window.
Changes for 01/05/2002
- Added the new intrinsic functions
inputLineTimeout(),
which allows reading a line of text with an optional timeout. This
function can be used to combine command-line input with real-time
effects, because it allows a command line to be interrupted if the
command is not completed before a real-time interval elapses.
- Fixed a problem in the Dictionary class: the
isWordDefinedTrunc() method used the wrong truncation length
in its comparison - it required the string to be matched to be at
least one character longer than the dictionary's truncation length.
It now uses the correct truncation length.
Changes for 12/30/2001
- The compiler now parses a delegated expression so that
the object expression is taken to exclude function or method calls.
That is, if parentheses follow the expression giving the target
object of the delegation, these are taken to give the argument list
of the delegation call itself, rather than of the expression giving
the target object value. This change makes delegated
syntactically parallel to inherited in that the target
property can be omitted from the expression, in which case the
delegation target property is the same as the property being
evaluated in the caller. (If a function or method call is desired
in the object expression itself, this can be easily accomplished
by enclosing the entire object expression in parentheses.)
- Workbench now stores its project configuration files so that the
absolute file system path to "system" files is not stored; instead,
system files are flagged as system files, and their locations are
stored relative to the system directory. A "system" file is simply a
file that is stored in the Workbench install directory or any of its
subdirectories; the system directory is the directory containing the
Workbench program executable. This change makes project
configurations more readily moveable from one system to another,
because it eliminates any dependency in the project configuration
on the particular directory in which Workbench is installed.
- The compiler now treats the symbol and object path options as
overriding all module source paths, even when the filenames are given
with "absolute" (as opposed to relative) path names.
Changes for 12/23/2001
- Added a checksum to the saved game format. This allows the
interpreter to validate a saved state file, to ensure the file wasn't
corrupted (such as by a text-mode ftp transfer), before attempting to
load the file.
- Fixed a problem in the Vector intrinsic class that prevented two
equivalent vectors from comparing equal.
- Fixed a compiler problem that caused the compiler to crash in
some cases when a symbol was redefined from function to another type.
- Fixed a compiler problem that caused incorrect initialization
of Dictionary objects in the image file in certain cases when
preinitialization ran (i.e., when compiling with the -d option).
Changes for 12/09/2001
- The compiler now accepts URL-style portable path names in #include
directives, and in fact prefers them. Refer to the
preprocessor chapter for details.
- Added a new method, createClone,
to the TadsObject intrinsic class. This method returns a newly-created
object that is an identical copy of the original object.
Changes for 12/02/2001
- Changed the tokenizer interface (in tok.t) to return a list of
token elements, rather than parallel value/type lists. Each token
element in the token list is a sublist, consisting of the following
values:
- [1] = token value, as set by the matched rule
- [2] = token type enum, as set by the matched rule
- [3] = original source text matched by the rule that matched the token
The tok.h header defines macros that extract these elements of a token;
these should be used rather than direct list elements to make your code
more readable. The macros are getTokVal(tok), getTokType(tok), and
getTokOrig(tok). So, if lst is a variable containing the
result of calling Tokenizer.tokenize(), and you want to retrieve
the type enum for the third token, you'd write getTokType(lst[3]).
- Changed the tokenizer's rule specifications for greater power and
symmetry in creating rules:
- The "flags" entry has been eliminated. The functionality of the
only flag that was defined, TOKFLAG_SKIP, has been replaced with the
improved behavior of the rule processor. Since the processor method's
interface is now powerful enough to subsume the functionality of the
"skip" flag, the special case embodied in the flag is no longer needed.
- The processor method (element [3] in the sublist defining a rule)
has a new interface. In the past, this method took a text match and
returned a token value. This interface meant that a given rule was
limited to generating exactly one token. The new interface takes
three arguments, and returns no value:
self.(processorProp)(txt, typ, toks)
txt is the text that matched the rule (this is the same as the
lone argument to the old interface). typ is the token type from
the rule (i.e., element [2] of the sublist defining the rule).
toks is a Vector containing the token list under construction.
The method must append the appropriate set of tokens to the Vector
in toks. The method is not required to append any tokens; the
rule in the default tokenizer rule set that matches whitespace, for
example, doesn't generate any tokens, since whitespace characters have
no significance other than separating tokens in the default rule set.
The rule is also allowed to generate more than one token; this is useful
for rules that generate certain tokens types only if they immediately
follow particular text patterns. Note that the processor method is
not required to use the typ value given, since each new token
the method adds to the result Vector can be of whatever type is
appropriate; the type information is included so that a single processor
method can be re-used for similar types of processing that produce
different token types.
- Changed the intrinsic GrammarProd.parseTokens() method to accept
tokens in the new format returned by the tokenizer. The method now
takes only two arguments, not three: the second argument that formerly
gave the token type list has been eliminated, since each element of
the token list now includes the type information along with the token
value information.
- Changed the Dictionary and GrammarProd intrinsic classes to use
case-sensitive matching exclusively. Case sensitivity in the past
was inconsistent; all functions are now case-sensitive for
consistency.
- The template inheritance mechanism is somewhat altered from its
first implementation. The 'inherited' keyword can now go anywhere
a template; the inherited token lists are treated as substitutions
for 'inherited' at the point at which it appears in the list.
Furthermore, the compiler now treats each template involving
inheritance as a macro defining all possible inherited templates;
when a template is used, it is matched based on the entire expansion
of the template, not on the partial superclass template. The net
effect is that a template definition involving an 'inherited'
token is identical to the implied set of fully expanded template
definitions.
- The -Fs option can now be used to specify a search path for
source files, rather than a single path for all sources as it did in
the past. Multiple -Fs options can be specified; each one adds one
directory to the source search path. When a source file name is
specified in "relative" form (as defined by local filename
conventions), the compiler first looks for the file in the working
directory, then searches the directories specified with -Fs options,
in the order in which the options were specified. The compiler uses
the first instance of the file it finds.
- The compiler automatically adds the system-dependent default
system library directory to the source search path. This directory
is always searched after all directories specified by
the user with -Fs options. In effect, the compiler adds an
extra -Fs option for the default system library directory after
all user-specified -Fs options. This allows library sources
(such as reflect.t or gameinfo.t) to be included in a build
configuration (in a .t3m file, for example) without any path
information; the compiler will automatically find these system
files using the implied -Fs setting.
- The compiler's default system library and include directories are
now system-dependent. On DOS and Windows systems, the default
system header and library directories are the same as the compiler
executable's directory (this is the main directory where the TADS 3
tools are installed). Check your platform-specific release notes
for details on the locations of these directories on other platforms.
- Fixed a problem that allowed objects to be deleted by the
garbage collector when they were referenced as superclasses of
other objects. This caused unpredictable behavior, including
interpreter crashes.
- Fixed a problem that affected the results of t3GetStackTrace() in
the non-debug interpreter when a run-time error occurred. In such
cases, the stack trace incorrectly omitted the innermost level,
where the error actually occurred. This has been corrected.
- Fixed a compiler problem that sometimes caused the compiler to
crash after attempting a link that involved unresolved external
symbol references.
- Fixed a GrammarProd parsing problem that caused incorrect token
index information to be returned in certain cases involving productions
with no tokens.
Changes for 11/17/2001
- Extended the object template
syntax to allow template inheritance. A template definition can now
include the keyword "inherited" as its final token; this
indicates that the template "inherits" the templates of its
class's superclasses.
- The compiler now detects and reports circular class definitions
(that is, class definitions where the class being defined is a subclass
of one or more its purported superclasses). In the past, the compiler
did not detect such definitions and could get stuck in infinite loops
or unbounded recursion when they were made.
- Fixed a compiler problem that sometimes caused crashes when an
actual parameter list in a macro expansion was not properly terminated
(with a closing parenthesis) in the source file.
- Fixed a problem that affected a few Vector methods by incorrectly
returning an empty vector. This affected the appendUnique, getUnique,
and mapAll methods.
- Fixed a compiler problem that caused a modified intrinsic class
to show a spurious extra property in its getPropList() result list.
This property had an undefined type (type code 16).
- Fixed a problem in the Vector class that caused unpredictable
results, including crashes, when adding a large list to a vector.
- Fixed a problem in the debugger that caused unpredictable
results, including crashes, when interrupting the program in
mid-statement in certain circumstances. The problem occurred
sporadically in such cases when the garbage collector happened to run
while the debugger had control, but didn't appear until after
returning control to the program. This problem only manifested
itself rarely, but could cause crashes when it did appear.
- Fixed a compiler problem that caused incorrect code to be
generated for calls to operator new where the actual
parameters included one or more "..." expressions (i.e., expanded
variable argument lists). This affected the calling end,
not the receiving end. The problem caused the caller to send one
fewer argument than it should have.
- Fixed a problem in the output formatter that caused log files
to be generated without proper line wrapping in the HTML version
of the interpreter.
- Changed the output formatter so that <BANNER> contents
(everything from a <BANNER> tag to the corresponding
</BANNER> close tag) are not included in the output log.
The contents of a banner are not logically part of the main text
stream so are not appropriate for inclusion in a log file. This
ensures that HTML-based status lines and other special display
effects do not interfere with the log file contents.
Changes for 10/21/2001
- Fixed a problem that made it impossible to use anonymous functions
that referenced "self" or properties of "self" within property values
defined as simple value expressions (as opposed to methods).
- Changed the compiler to allow using short-form anonymous functions
(i.e., using the "{args: }" notation, rather than the "new
function" notation) as list elements without enclosing the
functions in parentheses. In the past, the compiler considered an
open brace at the start of a list element expression as an error; this
was an heuristic intended to catch unterminated list expressions, but
its utility as a diagnostic tool was not sufficient to justify the
superfluous syntax requirement it imposed for this case.
Changes for 10/07/2001
- Added special character sequences '\{' and '\}'. These are used
to group a set of output formatter setting changes: any changes to
the formatter settings made after a '\{' sequence are undone at the
corresponding '\}' sequence. In particular, the following state
changes are affected:
These new sequences can be used to isolate a run of text from the
enclosing text's formatter settings, so that the text within the '\{
\}' pair doesn't have to worry about the enclosing settings and has
no effect on the enclosing settings. This can be useful, for
example, if a run of text wants to output an HTML-significant
character, but doesn't know if it will be called with HTML
interpretation turned on or off. In such cases, the text can
turn HTML interpretation off within the brackets without affecting
its caller: "\{\H-&\}" would display an ampersand, regardless
of whether HTML mode was in effect before the text was displayed,
but will have no effect on subsequent text's HTML mode.
- Fixed problems in several intrinsic classes related to saving
and restoring. These bugs caused crashes in some cases when restoring
saved positions.
- Changes the restartGame() behavior slightly. The function invoked
after the restart is now passed the original command line arguments
to the program; the arguments are passed as a list in the second
parameter to the function. This allows the function to invoke
the normal main program entrypoint as though the program were being
started normally.
- If a saved position file is found to be corrupted in the course
of being restored, the interpreter will now force an exit. There is
no way for the program to retain control in such cases. If a saved
position file is corrupted, the partially restored machine state at
the point at which the corruption is detected must be considered
invalid, so the VM cannot safely pass control back to the program.
In such cases, the VM terminates the program to avoid the high
likelihood that the program would crash the VM due to the program's
partially corrupted internal state.
- Fixed some problems in the "undo" mechanism that caused
unpredictable behavior (including VM crashes) under some
circumstances.
- Fixed a problem in the debugger that caused, in some cases, the
incorrect error code to be reported in the RuntimeError object
representing a VM exception. This only occurred when the program
was being run in the debugger, and only then when certain types of
expressions were evaluated. This has been corrected.
Changes for 09/30/2001
- Changed the symbol file format to allow inclusion of intrinsic
function and intrinsic class registration lists. This is an internal
change only; its purpose is to make the compiler more flexible in
correlating the internal linkage identifiers of intrinsics across
object modules to eliminate the possibility of certain confusing
linking errors. In the past, it was necessary to keep intrinsic
definitions in a consistent order across separately compiled modules,
which was problematic for library developers and especially for library
extension developers. Adding the information to the symbol files
allows the compiler to build an intrinsic identifier list globally
across modules to ensure a consistent ordering, even when the
individual modules have conflicting orderings. This change should
not be visible to users except to the extent that it eliminates
certain errors relating to intrinsic class and intrinsic function
inclusion order.
Changes for 09/09/2001
- Added a new function to the "tads-io" function
set: flushOutput(), which immediately flushes text output
to the display and updates the window, if possible.
- Fixed a compiler bug that caused incorrect code to be generated
for implicit constructors for classes with multiple superclasses.
This code generation error did not manifest itself frequently, but
when it did show up caused problems ranging from data value corruption
to interpreter crashes.
- The debugger now includes an ampersand prefix when displaying
property pointer values.
Changes for 08/26/2001
- Added new syntax that provides a short-hand notation for defining
a group of properties with similar names and parameters: the new
"propertyset" syntax.
- Added a new keyword, "targetprop", a pseudo-variable that
evaluates to the current target property pointer. The target
property is the property that was invoked to reach the current
method; this new pseudo-variable complements "self" with information
on the property being evaluated in the current "self" object. The
"targetprop" keyword can only be used in contexts where "self" is
valid.
- The "inherited" and "delegated" keywords can be used with new
syntax that omits the target property. If the target property is
omitted, then the current target property is implied. The target
property can be omitted from any of the previously-allowed forms of
the "inherited" and "delegated" expressions, as shown here ("delegated"
syntax is parallel to "inherited", so only "inherited" is shown):
- inherited is equivalent to inherited.targetprop
- inherited(arguments) is equivalent to
inherited.targetprop(arguments)
- inherited superclass_name is equivalent to
inherited superclass_name.targetprop
- inherited superclass_name(arguments)
is equivalent to
inherited superclass_name.targetprop(arguments)
- Added a new library module, reflect.t, that provides higher-level
reflection services. This module is optional, but if it is included,
the _main.t module uses reflection to show stack trace listings for
unhandled runtime exceptions.
- Added t3GetStackTrace() to
the 't3vm' intrinsic function set. This function returns information
on the call stack.
- The RuntimeException object defined in _main.t now stores a stack
trace (in the form returned by t3GetStackTrace()) in its stack_
property. The VM no longer stores an explicit stringized form of
the stack trace when setting the exception message, since the new
stack trace format is more powerful.
- Fixed a bug in the TadsObject intrinsic class that sometimes
caused a given property to appear more than once in the getPropList()
method's returned list. Any given property now appears at most once
in the result list.
- The TadsObject intrinsic class now supports createInstance() as a
static method on the intrinsic class. The expression
TadsObject.createInstance() returns a new instance of TadsObject,
which is the same as defining an object statically like so: "myobj:
object;" - that is, using the "object" keyword rather than a
superclass list.
- Fixed a bug in the getPropList() method when called on any
intrinsic class object (e.g., Object, TadsObject, BigNumber). In
the past, this method returned a list of all of the methods that
were valid on instances of the intrinsic class, not the
methods that were necessarily valid on the intrinsic class object
itself. This method now returns a list consisting only of the
"static" methods of the intrinsic class, which is to say the methods
that can be called directly on the intrinsic class object itself.
- Fixed a bug in the Object intrinsic class's propType() method.
When the property in question was undefined, the method returned
TYPE_NIL, whereas it should have returned nil. The method now
returns nil for these cases, as documented.
- Fixed a bug in the compiler that caused incorrect code generation
when a variable argument list parameter variable was referenced from
within an anonymous function within the function or method with the
variable argumetn list parameter.
- The compiler now specifially flags code using '=' to define a
method. Since this was valid TADS 2 syntax, and has been
gratuitously changed in TADS 3, users are likely to use the old
syntax accidentally, especially while transitioning to the new
language. The compiler catches these cases so that it can generate
specific and clear error messages; this should help ease the
transition to the new syntax by spelling out plainly the new
syntax requirement.
Changes for 08/12/2001
- Fixed a compiler problem that caused incorrect code to be generated
for expressions of the form obj.(prop)(args), where prop
is a property of self whose value is a property pointer.
An expressions of this form is equivalent to the form
obj.(self.prop)(args), but the compiler in the past incorrectly
interpreted this as equivalent to obj.prop(args) - that is,
rather than evaluating (self.prop) and then calling the
property of obj given by the resulting property pointer value
with the given argument list args,
the compiler generated code that called the property prop
of obj with arguments args. This has been corrected -
the compiler now correctly interprets obj.(prop)(args)
as equivalent to obj.(self.prop)(args).
- Fixed a compiler problem that caused incorrect code to be generated
for delegated expressions involving variable argument lists.
- Fixed a compiler problem that caused a spurious warning under
certain circumstances. If a property was used only in an address
expression ("&prop") in a module, and no object ever defined
a value for the property, a call to the property in a separate
module incorrectly generated a warning indicating a call to a
possibly undefined property name. This warning was spurious because
the use of the property name in an address expression is enough to
definitively establish the symbol as a property.
- Fixed an output formatter problem that caused the text-mode
interpreter to hang (in an infinite loop internally) in response to
certain "&" entities in HTML mode.
- Fixed a problem in the GrammarProd intrinsic class that caused
productions that matched zero tokens to indicate invalid token index
values for firstTokenIndex and lastTokenIndex. These now always
indicate zero in such case, to indicate that the production is
associated with no tokens.
Changes for 08/05/2001
- Added file safety level checking to the File intrinsic class. The
initial implementation of File did not check the safety level set in the
user preferences; the File class now correctly checks to ensure each
open-file operation is allowed by the user's safety level settings.
On a safety level violation, the "open" functions throw the new
exception FileSafetyException.
- Text files can now be opened in FileAccessReadWriteKeep and
FileAccessReadWriteTrunc modes. In the past, only "data" and "raw"
files could be opened in read/write modes, which made it impossible
to append to an existing text file.
Changes for 07/22/2001
- Fixed a problem with using 'modify' with intrinsic classes. In the
past, if more than one 'modify' statement was applied to an intrinsic
class, only the last of the 'modify' statements was actually taken into
account at run-time. This has been corrected.
- Fixed a compiler bug: the compiler did not report an error if a
'replace' statement replaced an object but did not specify a superclass
list for the new object. The compiler misinterpreted such a statement as
a new anonymous object definition. This has been corrected; the compiler
now flags the missing superclass list as an error.
Changes for 07/16/2001
- Fixed a problem in the List class that could cause an object to
be improperly deleted by the garbage collector under certain obscure
circumstances. (In particular, if an object was being assigned to
a list element, and the garbage collector ran in the course of the
creation of the new list for the result of the assignment, the object
on the right-hand side of the assignment was lost if not otherwise
referenced.)
- Fixed a problem that occurred with propDefined(prop,
PROPDEF_GET_CLASS) when the property of interest was an
intrinsic method (i.e., a TYPE_NATIVE_CODE value). In these cases,
the return value of the method was an invalid value, which caused
problems if used, including interpreter crashes. In such cases,
propDefined() now properly returns the intrinsic class
object where the intrinsic method is defined.
- Extended the object template
mechanism to allow class-specific templates to be defined.
- Extended the firstObj() and
nextObj() intrinsic functions to
take a new flags argument, which allows the caller to specify
whether to enumerate instances only, classes only, or both.
- Changed the TadsObject class to allow use of the new
operator with no arguments. In the past, at least one argument
(giving the immediate superclass of the new object) was required;
now a new TadsObject with no arguments is understood to
create a base TadsObject.
- Added the File intrinsic class, which
provides a new interface to external file input/output. This replaces
the file-related functions in the "tads-io"
intrinsic function set, which have been removed. Specifically,
the following functions have been removed:
- fileClose
- fileGetPos
- fileOpen
- fileRead
- fileSeek
- fileSeekEnd
- fileWrite
Important note: This change is not upwardly compatible. All existing
code must be recompiled for this change, and any code using the fileXxx
functions must be modified to use the new File intrinsic class. The
necessary code changes are relatively straightforward, since the names
of the new File methods are similar to those of the old functions.
- The compiler now generates an implicit constructor for each
object or class that inherits from multiple base classes and does
not provide an explicit constructor. The implicit constructor
simply invokes each base class's constructor, in the same order
in which the base classes are listed in the superclass list.
- Added grouped sub-alternatives to rules in the
grammar statement. This allows
portions of an alternative in a rule definition to be grouped for
alternation; for example, a rule can be defined as
"('take' | 'get' | 'pick' 'up') nounList->lst_", which
is more concise than flattening out the grouped alternation manually.
- Added the #ifempty and
#ifnempty variable-arguments expansion operators,
which allow conditional expansion in a varargs macro depending on
whether or not the varargs part is empty.
- Added the -P option to t3make: this preprocesses the source file,
writing the expanded results on standard output. When -P is
specified, no compilation or linking is performed, so no object or
image files are created.
- Added new String intrinsic class
methods: startsWith(), endsWith(), and
mapToByteArray.
- Added a feature to the substr() method of the
String intrinsic class: if the starting
index (the first argument) is negative, it indicates an offset
from the end of the string: -1 is the last character of the string,
-2 the second-to-last, and so on.
- Added a new function to the "tads-io" function
set: getLocalCharSet, which returns the name of one of the
active local character sets on the current system.
- Added new functionality to the "tads-io"
function set for files. Files can now be opened in "raw" mode,
which allows reading and writing byte arrays. Bytes written to and
read from a file in raw mode are not translated or modified in any
way; this mode offers direct access to external files, for purposes
such as manipulating files in formats defined by other applications.
The fileRead() and fileWrite() functions in this
mode take ByteArray arguments.
- Added new functionality to the "tads-io"
function set: the fileOpen() routine can now take an
object of intrinsic class CharacterSet
instead of a character set name. If you've already instantiated
a CharacterSet object for other reasons, it is more efficient to
re-use the same object by reference in this manner than to pass
the name of the character set to fileOpen(), since
fileOpen() has to create another mapping object when
given only a character set name.
- Added the new CharacterSet intrinsic
class.
- Added the new ByteArray intrinsic
class.
- In the Object intrinsic class, method
formerly known as isClass() has been renamed to
ofKind(). x.ofKind(y) returns true if x is an instance or
subclass or y. In addition, this method has been changed so that
x.ofKind(x) returns true for any x.
- Added a built-in character set mapping for ISO 8859-1 (Latin-1).
This character set is in widespread use because of its status as the
default HTTP character set, and has an especially simple mapping to
Unicode, so it seemed worthwhile to add as a built-in set not requiring
an external mapping file. The assigned name of the set is "iso-8859-1".
- Changed the compiler's former -r option to -a,
and the former -rl to -al. (The -a option
forces recompilation of all involved modules even when not out of
date with respect to the source files, and -al forces
relinking even when the image file isn't out of date with respect
to the object files; these options effectively override the compiler's
normal dependency analysis for cases when the automatic analysis is
incorrect for some reason.) This change is gratuitous and cosmetic,
but makes the compiler's option names more closely resemble that of
traditional "make" programs.
- Fixed a compiler bug: the compiler reported a spurious "symbol
already defined" warning when a particular grammar production had
rules defined in multiple modules. This has been corrected.
- Fixed a preprocessor bug: if the argument of a #message was
missing its closing right parenthesis, the preprocessor got stuck
in an infinite loop. This has been corrected.
- Fixed a bug in the Vector intrinsic
class (and, by inheritance, in the Array
intrinsic class): if the insertAt method was called
on an empty vector, a crash occurred. This has been corrected.
- Fixed a compiler bug that caused the compiler to crash if
confronted with a foreach statement in the absence of
the definition of the Collection and Iterator classes. This
has been corrected; the compiler now generates the appropriate
error message and recovers gracefully.
- Fixed a problem with the grammar production object that caused
new match tree objects to bypass constructors on creation. The
match tree constructors are now invoked as for any other object
instantiation.
- Fixed a problem in the debugger that prevented the debugger from
taking control on a run-time exception being thrown when another
run-time exception had previously occurred at the same place twice in
a row with no intervening debugger activity.
- Fixed a problem that caused the debugger to crash under some
unusual conditions when an entry in the local-variables window
was selected and later automatically removed due to an execution
context change.
- Improved the robustness of the debugger when the program
being debugged caused a stack-overflow exception.
- Updated the calc.t example to the new GrammarProd.parseTokens()
interface.
- Fixed a bug that caused comparisons of any two function pointers
to yield unequal, even for equivalent function pointers. This bug
had numerous subtle manifestations; for example, a function pointer
key in a LookupTable could never be found, since a test for equality
to the key would never succeed.
- Fixed a compiler bug that caused the incorrect error message to
be reported when a replace/modify of an extern object was out of order
in a link (the message reported that a function rather than object
was involved).
- Removed a spurious warning that was generated when a dictionary
was imported from multiple symbol files.
- Fixed a bug in the GrammarProd intrinsic class that caused "*"
tokens in subproductions to be misinterpreted. In the past, the "*"
token only worked properly in top-level productions (i.e., a production
on which parseTokens() was called); this has been corrected so that "*"
works properly at any level.
Changes for 05/05/2001
- Incompatible intrinsic class API change: The return value
of the parseTokens() method in the GrammarProd intrinsic class has been changed.
In the past, this method returned a list, each of whose elements was
a sublist of two elements. Each sublist described one successful
match tree; the first element of each sublist was the number of
tokens matched, and the second was the root object of the match tree.
The 4/29/2001 version added the firstTokenIndex and lastTokenIndex
properties to the match objects; since the number of tokens matched
in a tree can be inferred from the firstTokenIndex and lastTokenIndex
values, the token counts in the return sublists were redundant.
Therefore, to simplify the API, the sublists have been eliminated,
and parseTokens() now returns simply a list of match tree
root objects. To obtain the token count for a match, simply calculate
(match.lastTokenIndex - match.firstTokenIndex - 1), where
match is the root object in the match tree. Since the root
object in a tree encompasses the entire match, its token range
necessarily encompasses the range of tokens for the entire match.
- Added variable-argument macros.
- Fixed a problem in the GrammarProd intrinsic
class that prevented a rule from being matched when it ended with
the special '*' token and was used as a subproduction in another rule.
This now works correctly.
- Fixed a problem in the compiler that caused a spurious warning
message indicating that a dictionary symbol had been imported multiple
times. This warning was generated whenever the dictionary was declared
in more than one source file but not in all source files; each
file that did not declare the dictionary displayed the warning.
This has been corrected.
- Added the delegated keyword,
which allows delegating a method call to an unrelated object.
- Added the getMethodDefiner()
intrinsic function, which returns the object that defines the currently
executing method.
- Changed the default name of the ASCII character set mapping to
"us-ascii" for better readability. The old name ("asc7dflt") is still
accepted, but is now obsolescent and should not be used in new code.
All of the #charset directives in the system headers provided with the
compiler have been updated to use the new "us-ascii" name.
Changes for 04/29/2001
- Fixed a problem in the GrammarProd intrinsic
class that caused incorrect results to be returned with
productions that matched exactly zero tokens.
- Extended the grammar syntax to allow the "->"
notation to be used with literal tokens. In the past, the arrow was
only allowed with symbol-match tokens (subproductions and token classes),
but it is often desirable to be able to retrieve the matching token even
for a literal match. There are two cases in particular where a literal's
matching token is needed to reconstruct the original input: when the
literal is matched with truncation; and when a production has several
alternatives with different literals.
- Modified the GrammarProd intrinsic class
so that each match object now includes more direct information on the
tokens involved in the match. The parser now sets the
firstTokenIndex and lastTokenIndex properties of each match object to
indicate the index of the first token and of the last token,
respectively, that are involved in matching the rule corresponding to
the match object. This is a simple range, so all of the tokens from
the first to the last, inclusive, constitute the match's original
text. In addition, the parser sets the tokenList property of each
match tree item to the original token list passed into parseTokens()
(this doesn't take up nearly as much memory as it might at first
appear, since all of the match objects reference a single shared copy
of the token list). The exported properties firstTokenIndex,
lastTokenIndex, and tokenList are defined in gramprod.h.
- The compiler now creates a dictionary entry in the default
dictionary, if one is defined, for each literal string that appears
in a "grammar" statement's rule list. If no
default dictionary is defined when a "grammar" statement is
encountered, the statement's literals are not entered into any
dictionary. Each literal string is associated with the production
object and the property "miscVocab". Since these strings are now
stored in the dictionary, it is simple to determine if a word is
defined in any context; without the grammar literal dictionary
entries, it was not possible to determine if a given string, when
entered by a user at run-time, was known in the context of a grammar
literal.
- The "grammar" syntax has been extended
to allow a "tag" to be associated with each "grammar" statement. To
specify a tag, specify any symbol or number in parentheses after the
production name. For example:
grammar nounPhrase(1): adjective->adj_ : object ;
The tag's only purpose is to provide an identifying name for the
new "grammarInfo" method, described below.
- The compiler now automatically creates a method for each
grammar match object that makes it possible to
traverse match trees without knowing their internal structure in
advance. The new method is called "grammarInfo," and it returns a
list. The list's first element is a string giving the name of the
production, with the optional tag (see above) enclosed in parentheses
after the production's symbolic name. Each subsequent element is the
value of a property appearing after an arrow ("->") in the production's
rule list.
- Modified the grammar production matching
algorithm so that [badness] matches are examined as a group rather
than individually. In particular, when a number of [badness]
alternatives arise simultaneously, the parser had in the past
examined only one such alternative at a time once determining that no
better matches were available. Now, all [badness] alternatives with
the lowest badness value are examined in parallel. This is important
in some cases for the same reasons that parallel consideration of
regular alternatives is necessary.
- Fixed a compiler problem that caused spurious "variable assigned
but not used" warnings in certain situations. In particular, if a
local variable was defined in a nested scope within a method, and the
variable was used only within the lexical confines of an anonymous
function within the nested scope, the compiler did not correctly mark
the variable as having been used and thus incorrectly reported the
warning. This problem did not affect code generation; its only
effect was the unnecessary warning.
- Enhanced the Dictionary intrinsic class's findWord() and
findWordTrunc() methods so that the property argument in each can be
omitted or specified as nil, in which case all objects with vocabulary
matching given text, for any part-of-speech property, will be
returned.
- Fixed a debugger problem that caused a crash in some obscure
cases involving opening a file during a debugger session when the
debugger had never taken control since the beginning of program
execution, and a similar problem that occurred when the VM threw
a run-time error exception under similar circumstances.
Changes for 04/15/2001
- A new mechanism allows capturing calls to undefined methods and
properties. When a call is made to an undefined method, the VM now
calls a new property, propNotDefined(),
on the target object. The new method receives as arguments the
the undefined property ID and the arguments to the original method
call. If propNotDefined is itself not defined, the VM
simply returns nil for the undefined method call, as it did in the
past.
- Added some new regular expression features:
- Character classes can now be combined with '|', as in
<upper|digit> (matches any upper-case letter or any digit).
- Character classes can now be complemented with '^', as in
<^upper> (matches anything except upper-case letters).
- Added some named character
expressions, which look similar to character-class expressions,
and which can be combined with character-class expressions via
'|': <upper|star> matches any upper-case letter or an asterisk.
- Renamed the t23run.exe executable to simply tr32.exe, so the
combined TADS 2+3 interpreter is now the default interpreter. The
separate interpreters are now called t2r32.exe (for TADS 2) and
t3run.exe (for TADS 3). For the most part, users will not need to
run the version-specific interpreters at all; the only time these
should be needed is when bundling a game into an executable, in which
case it is desirable for the sake of minimizing file sizes to include
only the version of the interpreter actually needed.
Changes for 3/28/2001
- The object definition syntax has been extended to allow an object's
property list to be enclosed in braces. Refer to the
Object Definitions documentation for details.
- The object definition syntax now provides "nested" objects. A nested object
is an anonymous object defined in-line within another object, with a
property of the enclosing object initialized with a reference to the
nested object; this syntax is convenient for defining certain types
of small helper objects.
- The language now has a static property
initialization syntax, which allows a property to be initialized with
a non-constant value computed at compile-time.
- Changed the behavior of the '+' property. The new behavior is
much simpler than the previous behavior: if an object is defined
with N plus signs, its '+' property is initialized to the
most recent object defined with N-1 plus signs. Explicitly
setting the '+' property in an object list is now irrelevant.
Refer to the documentation for details.
- Changed the default filename suffix for image files to ".t3" (it
was formerly ".t3x") to make image filenames somewhat more friendly looking.
- Added the new executable "t23run" - this is a 32-bit console-mode
combined TADS 2 and TADS 3 interpreter. You can use this single
application to run games compiled for TADS 2 or TADS 3. This version
of the interpreter is not designed for bundling single-file
games for distribution, since this would unnecessarily increase the
size of bundled games; use the appropriate single-version interpreter
executable for bundling.
- Added the new executable "html23" - this is a combined TADS 2 and
TADS 3 version of the HTML interpreter.
- For anyone interested in porting the combined command-line
interpreter on another platform, the code that implements this should
be easily portable to other command-line operating systems. See
the target 't23run.exe' in win32/makefile.vc5; you can find the source
code for the main program entrypoint in vmcl23.cpp. For systems that
don't use Unix-style command lines, the command line code itself won't
be portable, but portable code for sensing the engine version
needed to run a given game file can be found in vmmain.cpp.
- Fixed a bug that caused problems with certain "reflection"
methods when the program used modify to extend the
TadsObject intrinsic class. If the program modified
TadsObject, then traversed the object tree (using the
getSuperclassList() method), or used the
propDefined() method, the behavior was incorrect, and could
lead to VM crashes. This has been corrected.
- Added documentation on the #charset
directive and using source files encoded in Unicode UCS-2.
- Added a #charset "asc7dflt" directive to each system
source and header file included with the compiler distribution. This
directive ensures that the compiler interprets the contents of the system
files correctly, in case the user wants to specify a default character
set for the compilation with the -cs compiler option.
- The compiler now accepts Unicode character 0x2028 ("line
separator") as equivalent to a newline in source files that use of
the Unicode encodings the compiler accepts (UCS-2 big-endian, UCS-2
little-endian, or UTF-8).
- In text mode, the fileRead() function now properly
translates input characters according to the character set selected
when the file was opened. (In the past, the character set was
ignored, and the characters from the file were not properly
translated to Unicode.) In addition, the fileRead()
function accepts Unicode character 0x2028 (the Unicode line separator
character) as equivalent to a newline (but note that, as always, the
text returned from readLine() represents each end-of-line
with a single '\n' character, regardless of the type of line
termination in the underlying file).
Changes for February 24, 2001
- Added the t3AllocProp()
intrinsic function, which allocates a new property ID.
- Added the
Object.getPropList()
method, which returns a list of properties directly defined by an object.
- Added the
Object.getPropParams(prop) method, which returns
information on the parameters taken by a property or method.
- Added the
getFuncParams(funcptr) intrinsic function, which
returns information ont he parameters taken by a function.
Changes for February 10, 2001
- The new property statement
allows a program to explicitly declare property symbols. This is optional,
but can be useful in certain cases in library code.
- Added the LookupTable intrinsic class,
which implements a general-purpose associative array type. A LookupTable
is similar to a Vector, but whereas a Vector can use only integers as
indices, a Hashtable can use any value as an index.
- Added the new t3GetGlobalSymbols()
intrinsic function, which provides programmatic access to the
compile-time names of objects, properties, functions, intrinsic
classes, and enumerators.
- The preprocessor now treats square brackets ("[ ]") and braces
("{ }") as grouping symbols when parsing macro arguments. In the past,
only parentheses were counted. This allows list constants and anonymous
functions to be used more easily as macro arguments.
- In _main.t, added a new function, initAfterLoad().
The main program entrypoint in _main.t (function _main())
calls this new routine to perform initialization. This routine sets up
the default display function, performs pre-initialization if necessary,
then performs regular load-time initialization. All of these operations
were previously carried out in _main(); the reason they've been
separated into a new function is to allow the same operations to be called
after a restartGame operation. Since a restartGame
effectively re-loads the image file and starts the game over from
scratch, the same initialization that _main()
performs at initial load must be performed immediately after a restart;
this function makes this common code easy to re-use.
- Added a new method to the TadsObject intrinsic class:
createInstance(), which creates an instance of the object. This
method passes its arguments to the new object's constructor, if any,
and returns a reference to the new object.
- Added execAfterMe to ModuleExecObject in
_main.t. User code can initialize this property in a given
ModuleExecObject instance to contain a list of other
ModuleExecObject instances that are to be initialized
after the given instance; this is analogous to the
execBeforeMe list, but allows an object to specify things
that are to come after it. It is sometimes desirable to be able to
specify initialization order dependencies by specifying what must
follow rather than what must precede initialization of a given object,
and this new property provides the flexibility to specify order
dependencies either way.
- A makefile for DJGPP (the definitive port of Gnu C/C++ for MS-DOS)
is now included in the source distribution. This makefile can be used
to create a 32-bit version of the interpreter that will run on MS-DOS
on PC's with 386 or later processors.
- Fixed a VM problem that caused modification of the root intrinsic
object (i.e., modify Object) to fail. In the past, the VM
simply failed to execute code added to the root intrinsic object with
modify. This has been corrected; code added to
Object is now properly inherited from the other intrinsic
classes.
- The String and List intrinsic classes can now be extended with
the modify mechanism. In the past, the VM did not correctly
handle code extensions to the String and List intrinsic classes.
- Fixed a compiler bug that caused incorrect code generation
when adding a constant zero value to a local variable which, at run-time,
ends up containing a vector, list, or other non-integer value.
- The Vector intrinsic class can now be used with the foreach
keyword to loop over the elements in a vector. (In previous versions,
the Vector class incorrectly omitted support for foreach.)
- The "Frames" version of the documentation should now work
correctly with Netscape and other browsers that had trouble with past
versions. (The frames page had some ill-formed HTML, which some
browsers rejected, but this page has now been corrected.)
- Changed the text of the VM error message that results from
applying an index to a type that cannot be indexed (nil[3], for
example). In the past, the message read "invalid type for indexing -
value cannot be index," which incorrectly signified that there was
something wrong with the index value, when in fact the value being
indexed was the problem. The message has been changed to read
"invalid index operation - this type of value cannot be indexed."
- Fixed a problem in the Vector intrinsic class that caused
a vector's data to be corrupted by certain operations that should have,
but did not, increase the internal storage space allocated for the
Vector object.
- Fixed a compiler problem with object templates. The compiler
did not properly parse object templates that included list tokens;
this has been corrected.
- Fixed a bug in the rand() intrinsic function. In the
past, this function crashed the interpreter if the argument was a
list with no elements. This has been corrected; the function now
returns nil when the argument is a list with no elements.
- Fixed a problem with the Vector intrinsic class that
caused pre-initialized data to be loaded incorrectly.
- Corrected the documentation (the expressions
chapter) to reflect the correct precedence of the "[]" and
"." operators, which should be above the unary operators.
- Added four new methods to the List intrinsic
class: prepend(val), which inserts a new value at
the start of a list; insertAt(index, val1, val2, ...),
which inserts one or more values into a list at a given position;
removeElementAt(index), which deletes the element
at the given index; and removeRange(startIndex, endIndex),
which removes the elements in the given range of indices.
- Added a new method to the Vector intrinsic
class: prepend(val), which inserts a new value at
the start of a vector.
- It is no longer legal to apply the unary "&"
operator to an object symbol. In the past,
"&objectName" was the same as simply
"objectName"; this is no longer legal.
"&objectName" was never a meaningful construct,
since an object symbol yields a reference to the object to begin
with, but past versions of the compiler accepted it without complaint
and treated it as equivalent to the unadorned object symbol; the
compiler now rejects this construct.
- It is no longer legal to apply the unary "&"
operator to a function name symbol. In the past,
"&functionName" yielded a reference to the
function. This has been changed so that the function name used
by itself yields a reference to the function, just as an object
name does.
- Because the "&" operator can no longer be used with
any symbol types other than properties, there is no longer a warning
when using the operator with an otherwise undefined symbol name.
"&symbol" now unambiguously defines the symbol
as a property name.
- Fixed a compiler bug that caused a spurious warning message when
compiling certain types of expressions involving property pointers.
The warning did not affect code generation, but it was incorrect and
has been removed.
Changes for version 3.0.2 (September 27, 2000)
- Fixed a compiler problem that caused the compiler to go into an
infinite loop (and therefore freeze up) when confronted with a 'switch'
statement containing code before the first 'case' or 'default' label.
This has been corrected; the compiler now reports an error (such code
is unreachable) and continues with the compilation.
- Fixed a minor compiler problem that generated a spurious warning
message in a certain situation. Specifically, if none of a 'switch'
statement's 'case' labels led to code paths that could reach the next
statement after the 'switch' (for example, if every code path
reachable from a 'case' label led to a 'return' statement), but the
'switch' had no 'default' label, the compiler generated the warning
message "unreachable statement" at the next executable statement
after the 'switch'. This warning was incorrect because, in most
cases, it is not safe to assume that every possible value of a
switch's controlling expression is included in the list of explicit
cases, hence the next statement following a 'switch' with no
'default' is reachable any time the controlling expression's value is
not in the list of explicit 'case' labels. Note that this problem
merely caused the spurious warning and did not affect code
generation.
Changes for June 24, 2000
- Fixed a compiler problem with try/catch statements. The compiler
did not correctly generate handlers for any catch block past the
first for a given try statement; this has been corrected.
Changes for version 3.0.1 (June 17, 2000)
- The meaning of the syntax x.y and &y have
changed slightly, in a way that will be transparent to most code.
In the past, if y was a local variable, then x.y
evaluated the local, then called the method on x specified
by the property pointer value in the local; &y simply
generated a compilation error because a local's address cannot be
evaluated. This behavior has changed. Now, x.y and
&y both ignore the local definition of y and
interpreter y as a property name. This change is important
because it allows code to refer to a property explicitly, even when
a local of the same name has been defined in the code block. For
example:
myObject: object
obj = nil
setObj(obj) { self.obj = obj; }
;
In the past, the code above would have had to use a different name
for the formal parameter variable obj, because it would not
have been able to refer to the property of the same name. With the
new interpretation, the code can distinguish between the local and
the property by referring to the property explicitly using self.obj.
Note that it is still simple to obtain the old behavior of
evaluating the local variable and calling a method via the resulting
property pointer. To do this, simply enclose the local in
parentheses: x.(y).
Changes for 5/21/2000
- Add a new Vector intrinsic class, a subclass
of Array that combines the reference semantics of an Array with the
dynamic sizing capabilities of a List. Vector is substantially more
efficient than List when constructing a collection iteratively.
- Added some new List methods:
sort,
append,
appendUnique.
- Added new Array methods:
sort,
appendUnique.
- Added an error message translation
mechanism, which allows non-English versions of the interpreter's
and compiler's error messages to be substituted at run-time.
Messages can be loaded from an external file, so there is no need to
recompile the system to switch languages. (At the moment, of course,
only an English set of messages actually comes with the system, but
it is hoped that a few translated versions will be contributed so
that more languages will be supported "out of the box" in the future.)
- Fixed a bug that reversed the order of arguments in calls to
anonymous functions while running in the debugger.
Changes for 5/11/2000
- Changed the name of the say function in the "tads-io"
intrinsic function set to tadsSay. This allows the
library to define its own higher-level function called say;
since user code should almost always call the library's function
rather than the low-level direct console output function, it is
desirable to give the library version the shorter, more convenient
name.
- Added the appendUnique() method to the
List and
Array intrinsic classes.
Changes for 4/24/2000
- Fixed a bug in the compiler that caused lost properties on objects
under certain very complicated circumstances (the problem occurred when
dictionaries and other objects were defined in a particular order).
Changes for 4/22/2000
- Added the foreach statement.
- Added the Collection and
Iterator classes. List and
Array are now subclasses of Collection, so these
classes can create Iterator objects to visit their elements.
- The Windows HTML interpreter now supports PNG transparency (this is
a generic change to the Windows HTML renderer that will also be in
HTML TADS 2.5.4). Note that only simple transparency is supported;
full alpha blending is still not supported. PNG transparency now has
its own systemInfo() capability code, SYSINFO_PNG_TRANS.
Changes for 4/16/2000
- Fixed a bug that caused a compiler crash when a source
file was completely empty (or contained only comments).
- Fixed a bug that caused a compiler crash in certain situations
involving multiple initializers in a single 'local' statement.
Changes since 3.0.0
- Added the htmlify() method to the
String class. This method converts any HTML markup-significant characters
in the string to their HTML equivalents; in particular, it converts
an ampersand ("&") to "&" and a less-than sign ("<")
to "<", and can also optionally quote spaces, tabs, and newlines
to ensure display fidelity for these whitespace characters as well.
- Added a
shortest-match modifier to the regular expression closure
operators ("*", "+", and "?"). This feature provides precise control
over how matches are allocated in expressions involving multiple
closures.
- Added the non-capturing
modifier to the regular expression group syntax; this allows a
parenthesized group to be omitted from the counted groups.
- Added look-ahead assertions to
the regular expression syntax.
- Added the regular expression interval operator, which provides a
compact notation for specifying a specific number of repetitions of a
sub-expression.
- Renamed a few list methods and
array methods, and expanded both sets
for greater consistency and more complete functionality:
- indexOf
- indexWhich
- valWhich
- lastIndexOf
- lastIndexWhich
- lastValWhich
- countOf
- countWhich
- mapAll
- applyAll (arrays only)
- forEach
- getUnique
- When the default start-up module (_main.t) is automatically included
in a build, _main.t is linked in first. It was formerly linked in last,
which didn't allow 'modify' or 'replace' to be used with objects defined
in the module.
- When running under the debugger, RuntimeError exceptions now
include stack trace information (with source line information) in the
exceptionMessage string associated with the exception object. This
makes it easier to track down where a run-time error occurred. Note
that this information is available only when running under the debugger,
because this is the only time the system has access to the necessary
source line information.
- Added a "character map library" mechanism to the
stand-alone interpreter. This new feature
allows a set of character map (.tcm) files to be bundled with a
stand-alone game, eliminating the need to distribute separate .tcm files
with a stand-alone game. (Having to distribute .tcm files seemed to
defeat the purpose of building a stand-alone executable. The new
bundling feature still allows users with localizations that aren't
included in the standard character map set to add their own .tcm files,
but it makes character mappings entirely invisible for most users.)
- Added CP1250.TCM (a character set mapping for the Windows
Eastern/Central European code page), CP850.TCM (DOS OEM Latin 1),
and CP852.TCM (DOS OEM Latin 2) to the default character map set
for Windows.
Changes since 03/30/2000
- Slightly changed the InitObject mechanism. The class
formerly known as InitObject is now called
PreinitObject, and a new class InitObject has been
added. The new InitObject does the same thing that
PreinitObject does, but does it at regular program start-up
rather than pre-initialization. This change makes the
pre-initialization and regular initialization mechanisms work the
same way. In addition, to make this mechanism more generic, both
InitObject and PreinitObject now descend from a
base class called ModuleExecObject; this class should be
usable as the base class for other types of modular execution
objects, such as perhaps a post-restore initializer sequence, a
command parsing initializer sequence, and so on. Refer to the
library pre-initialization documentation for
details.
- Added the -r option to the interpreter, allowing games to
be restored directly from the command. The saved state files now include
information on the image file that created them, so if you're restoring
a game, you don't have to specify the image file; this particular feature
also allows double-clicking on a saved state from the desktop to start
the interpreter, load the image file, and restore the saved state.
- The GrammarProd intrinsic class's parseTokens() method now
includes truncated matches to dictionary words (according to the
dictionary's truncation length setting) in its structural analysis.
The method also includes truncated matches (again, using the dictionary
setting) for literal tokens in the grammar. If you don't want to allow
truncated matches, simply change the dictionary's truncation length
setting to zero.
Changes since 03/26/2000
- Added a new library pre-initialization
mechanism based on "initialization objects" rather than a simple
preinit() method. This new mechanism should be especially useful for
library developers, since new initialization objects can be plugged in
without touching any library or user code
- It is now possible to extend
intrinsic classes with user-defined methods.
Changes since 03/21/2000
- The method-based API to certain functions that were formerly
implemented as intrinsics is now official. The trailing underscores
on the interim method names have been removed, and the corresponding
functions have been removed from the intrinsic function sets.
- getSuperclassList() is now Object.getSuperclassList()
- isClass() is now Object.isClass()
- propDefined() is now Object.propDefined()
- propType() is now Object.propType()
- length() is now List.length() and String.length()
- sublist() is now List.sublist()
- intersect() is now List.intersect()
- car() and cdr() are now List.car() and List.cdr()
- substr() is now String.substr()
- toUpper() is now String.toUpper()
- toLower() is now String.toLower()
- find() is now List.find() and String.find()
- toUnicode() is now String.toUnicode()
This change will, of course, necessitate recompiling all code, and will
require changing code that calls any of the functions that have been
migrated to methods. The sample code included in the distribution has
been updated to reflect the changes, and the documentation has also been
updated.
- Renamed the getSize() method in the Array class to
length(), for consistency with List and String.
- Added the 'is in' and 'not in' operators. See
the "is in" and "not in" expressions
section.
- The debugger now has "program arguments" settings. You can
access these settings via a dialog, which you can open using the
"Program Arguments" item on the "Debug" menu. You can use the
program arguments to control script file reading, output logging,
and the argument string that is passed to your program's "_main()"
entrypoint procedure.
- Added several new regular expression features: <Case> and
<NoCase>, <Alpha>, <Upper>, <Lower>, <Digit>,
<AlphaNum>, <Space>, <Punct>. Refer to the new
regular expressions section of the documentation
for details.
- Enhanced the regular expression parser to detect and remove
cycles in compiled patterns. It is possible (pretty easy,
actually) to introduce "infinite loops" into a pattern; the easiest
way to do this is to put a zero-or-more closure inside another closure,
as in "(.*)+" (this has an infinite loop because the expression in
parentheses can match zero characters, and that match can be repeated any
number of times), but much more complex and subtle types of cycles are
possible and can be inadvertantly constructed. Eliminating the
infinitely repeating zero-length matches obviously doesn't change the
meaning of the expression, since one repetition of a zero-length match is
as good as a million, so the regular expression matcher simply detects
and removes these loops and then carries on as normal.
- Updated StartI3.t and StartA3.t (the starter games in the Workbench
kit) to work with _main.t, so you don't have to compile them with -nodef.
(This also has the benefit of making the files a whole lot simpler.)
Also updated them to use method calls rather than intrinsic function
calls where appropriate.
- Updated the sample files to use the standard _main.t startup and
new property functions.
Changes since 03/12/2000
- Added default display methods, which
allow string display to be routed through a method of the active
"self" object in effect each time a string is displayed and each time
an expression embedded in a string via the << >> syntax
is displayed. This powerful new feature allows for per-object output
filtering, and allows for "stateful" filtering (in that the filtering
function is a method of the object that initiated the filtering, and
can therefore look at properties of "self" to perform its work).
- Added the "short form" anonymous
function syntax, which is much
more compact than the long form, but can only be used to define
functions that consist solely of a single expression.
- Added the subset() and applyAll() methods to
the array and list
intrinsic classes.
- Added documentation for the List intrinsic
class.
- Added the -cs interpreter option, which allows the user
to specify a character set to use for the display and keyboard.
Refer to the new interpreter section in
the documentation.
- As mentioned above, there is a new section
on the interpreter in the documentation.
- The TADS 3 HTML interpreter and debugger for Windows now use a
separate registry key for storing their preference settings. In
addition, the TADS 3 debugger's global preferences file is now
called HTMLTDB3.TDC. These changes should allow TADS 2 and TADS 3
installations to co-exist independently on a single system, without
affecting one another's stored configuration settings.
- Anonymous function objects are now represented by their own
intrinsic class. This is a mostly internal change, but does have
the benefit of enabling the debugger to display the type of an
anonymous function object (before, the debugger only knew that they
were objects).
- Made some internal changes to the way anonymous function context
objects are implemented to make them more efficient. (In particular,
context objects are now arrays, not TADS objects; array index lookup
is faster than TADS object property lookup.)
- Moved the code to Visual C++ 6 (which involved no changes, not
surprisingly, although the new C++ compiler caught a few dubious
constructs and generated helpful warnings, all of which have been
cleaned up).