# tadsgen.h | documentation

    #charset "us-ascii"
    #pragma once

    /*
     *   Copyright (c) 1999, 2006 Michael J. Roberts
     *
     *   This file is part of TADS 3
     *
     *   This header defines the tads-gen intrinsic function set.  This function
     *   set provides some miscellaneous functions, including data conversions,
     *   object iteration, regular expressions, and state persistence operations.
     */

    /*
     *   The tads-gen function set.  This set contains basic data manipulation
     *   and miscellaneous utility functions.
     */
    intrinsic 'tads-gen/030008'
    {
        /*
         *   Get the type of the given value.  This returns a TypeXxx value.
         */
        dataType(val);

        /*
         *   Get the given parameter to the current function.  'idx' is 1 for the
         *   first argument in left-to-right order, 2 for the second, and so on.
         */
        getArg(idx);

        /*
         *   Get the first object in memory.  If 'cls' is provided, we return the
         *   first object of the given class; otherwise we return the first
         *   object of any kind.  'flags' is an optional bitwise combination of
         *   ObjXxx values, specifying whether classes, instances, or both are
         *   desired.  If this isn't specified, ObjAll is assumed.  This is used
         *   in conjunction with nextObj() to iterate over all objects in memory,
         *   or all objects of a given class.
         *
         *   Note that firstObj-nextObj loops can retrieve objects that aren't
         *   otherwise reachable, because unreachable objects are only removed
         *   from memory when the garbage collector runs, which happens
         *   intermittently.  If you want to ensure that any currently
         *   unreachable objects are removed from memory just before a
         *   firstObj-nextObj loop, you can do so by calling t3RunGC().
         */
        firstObj(cls?, flags?);

        /*
         *   Get the next object in memory after the given object, optionally of
         *   the given class and optionally limiting to instances, classes, or
         *   both.  This is used to continue an iteration started with
         *   firstObj().
         */
        nextObj(obj, cls?, flags?);

        /*
         *   Random number generator (RNG) initialization.  This selects and
         *   initializes the random number generator algorithm used by rand().
         *   TADS provides several different RNG algorithms; each RNG has
         *   different properties, so some applications might have reasons to
         *   prefer a particular algorithm.  For general purposes, any of them
         *   should produce good results.
         *
         *   The interpreter automatically makes a call to randomize() (the
         *   no-arguments version) when it starts up, unless the user specifies
         *   the "-norand" option when launching the interpreter.  For most
         *   programs, this means that you'll never have to make your own call to
         *   randomize() - you can just call rand() when you need random numbers.
         *
         *   This function performs several tasks, depending on how you invoke
         *   it:
         *
         *.    randomize() - selects the default RNG algorithm (ISAAC), and seeds
         *.          the RNG with truly random data from the operating system.
         *
         *.    randomize(nil) - retrieves the current state of the RNG.  Returns
         *.          a list: [id, state], where 'id' is the ID of the currently
         *.          selected RNG algorithm, and 'state' is a value containing
         *.          its internal state, which can be used in a later call to
         *.          randomize([id, state]) to restore the RNG state.  The 'state'
         *.          value is opaque, meaning that it's not meant to be used
         *.          directly; the only thing you should do with it it save it
         *.          for later if you should want to restore this state later.
         *
         *.    randomize([id, state]) - if you pass in a list that obtained from
         *.          an earlier call to randomize(nil), the RNG will be returned
         *.          to its state at the time of the randomize(nil) call.  This
         *.          selects the same RNG algorithm that was in effect then and
         *.          restores the internal state of the generator.  After calling
         *.          this, a series of calls to rand() will return the same
         *.          sequence of numbers that were returned after the call to
         *.          randomize(nil).
         *
         *.    randomize(id) - selects the RNG algorithm identified by 'id'
         *.          (an RNG_Xxx value).  This doesn't change the state of
         *.          the generator; it simply selects the algorithm.
         *
         *.    randomize(id, nil) - selects the RNG algorithm identified by
         *.          'id' (an RNG_Xxx value), and seeds the generator with
         *.          truly random data obtained from the operating system.
         *
         *.    randomize(id, val) - selects the RNG algorithm identified by
         *.          'id' (an RNG_Xxx value), and seeds the generator with
         *.          the initial value 'val'.  This can be either an integer
         *.          value or a string; the preferred format varies by
         *.          algorithm, but they'll all accept either format.  After
         *.          you set a given seed value, rand() will return a sequence
         *.          of numbers that's repeatable every time you set the same
         *.          seed value.  This can be useful for things like testing,
         *.          where you want a sequence of numbers that's statistically
         *.          random, but which can be reproduced on demand.
         *
         *   Most programs that require random numbers want a truly unpredictable
         *   series of numbers - that is, numbers that have a statistically
         *   random distribution, with no discernible patterns, and which will be
         *   different every time the program is run.  There are two separate
         *   parts to this proposition, and they're handled by separate
         *   functions.  rand() fulfills the first part: it uses a mathematical
         *   formula to generate a series of numbers that are statistically
         *   distributed in a random fashion (for example, so that "1" occurs as
         *   often as "10" or any other number, any given sequence of 2, 3, or
         *   more numbers is equally likely, and so on: mathematicians have many
         *   formal tests that RNGs must satisfy to be considered random.)
         *   randomize() fulfills the second part, which is making sure that the
         *   sequence of numbers is different every time you run the program.
         *   The reason this second part is important is that rand() is by its
         *   nature deterministic: it's defined entirely in terms of a formula,
         *   so given the same initial conditions, it'll always crank out the
         *   same sequence of numbers.  The trick is to randomize its initial
         *   conditions - and what makes it tricky is that we can't just turn to
         *   rand(), since it's the thing we're trying to randomize!
         *
         *   This is where the "seed" values come in.  randomize() and
         *   randomize(id, nil) ask the operating system for truly random data to
         *   use for the initial conditions.  The degree of entropy in this OS
         *   seed data varies by system; some systems have better entropy sources
         *   than others.  But whatever the source, the seed data should be
         *   different each time you run the program.  randomize() feeds this
         *   seed data into the RNG to set its initial conditions, so each time
         *   you run, rand() will be starting from a different initial state.
         *   This makes for a different series of numbers from rand() on each
         *   run.
         *
         *   Note that it's not necessary (or desirable) to call randomize()
         *   every time you want a random number.  Once you seed the RNG, rand()
         *   is all you need to call.  It can be slow to gather the true random
         *   data that randomize() uses, since this sometimes requires
         *   interacting with hardware devices or scanning large amounts of
         *   system data.  rand() is quite fast, since it just calculates a
         *   number using a formula.  Depending on the system, rand() might also
         *   be more reliable at producing high volumes of statistically random
         *   data than the OS sources.  The operating system sources of true
         *   entropy don't always change quickly, so it's better to use them
         *   infrequently, such as just once at the start of program execution,
         *   than to use them as a routine source of random numbers.
         *
         *   The fixed seed values, with randomize(id, val), do something a
         *   little different.  Rather than making the RNG produce different
         *   sequences on each run, a fixed seed makes rand() generate the same
         *   series of numbers every time.  The numbers will still be
         *   statistically random, but each time you run the program, you'll get
         *   the same seaquence.  (The sequence is a function of the seed value.
         *   You'll get a different sequence for each different seed value.)
         *
         *   Why would you want a fixed series of rand() results?  One big reason
         *   is testing.  One popular way to test software is regression testing,
         *   where you run the program and compare its output to a reference
         *   version that you know is correct.  If there are no differences, you
         *   know that changes you've made to the program since haven't broken
         *   anything in the test script.  Randomization interferes with this
         *   kind of testing, because it makes the output different on each run -
         *   it's useless to do a simple mechanical comparison of the new and old
         *   output because they'll always differ.  Fixed seeds to the rescue.
         *   Using a fixed seed, you can still exercise the program's random
         *   behavior, but the sequence of random behavior will repeat on every
         *   run, so you run those regression comparisons after all.  The really
         *   great thing is that you don't have to make big changes to the
         *   program if you want to switch between test mode and real randomness
         *   - all you have to do is change the one call to randomize().
         */
        randomize(...);

        /*
         *   Select a random number or a random value.  This uses the current
         *   random number algorithm as selected via randomize().
         *
         *   If no arguments are supplied, the result is a random integer
         *   distributed evenly over the full range of the 32-bit integer type.
         *   The result can be positive or negative.
         *
         *   If exactly one argument is supplied, the result depends on the type
         *   of the argument:
         *
         *   - Integer: the function returns an integer from 0 to one less than
         *   the argument value.  For example, rand(10) returns a number from 0
         *   to 9 inclusive.
         *
         *   - List: the function randomly selects one of the values from the
         *   list and returns it.
         *
         *   - String: the function generates a random string by replacing each
         *   character of the argument string with a randomly chosen character,
         *   selected from a specific range specified by the argument character.
         *   For example, each 'a' in the input string is replaced by a random
         *   lower-case letter from a to z, each 'A' is replaced by a capital
         *   letter, and each 'd' is replaced by a random digit 0 to 9.  See the
         *   System Manual for the full list of the character codes.
         *
         *   If more than one argument is supplied, the function randomly selects
         *   one of the arguments and returns it.  Note that this is an ordinary
         *   function call, so all of the arguments are evaluated, triggering any
         *   side effects of those evaluations.
         *
         *   In all cases, the random numbers are uniformly distributed, meaning
         *   that each possible return value has equal probability.
         */
        rand(...);

        /*
         *   Convert the given value to a string representation.  'val' can be an
         *   integer, in which case it's converted to a string representation in
         *   the numeric base given by 'radix' (which can be any value from 2 to
         *   36), or base 10 (decimal) if 'radix' is omitted; nil or true, in
         *   which case the string 'nil' or 'true' is returned; a string, which
         *   is returned unchanged; or a BigNumber, in which case the number is
         *   converted to a string representation in the given radix; a list or
         *   vector, in which case the individual elements are converted
         *   recursively, then the results concatenated together into a string
         *   with commas separating elements; or any of the built-in object types
         *   with default string conversions (ByteArray, StringBuffer, FileName,
         *   Date, TimeZone, FileName, etc).
         *
         *   Note that when working with BigNumber values, you might prefer to
         *   use BigNumber.formatString(), as that gives you more control over
         *   the formatting style.
         *
         *   'radix' is only meaningful with numeric values (integers and
         *   BigNumbers).  For BigNumbers, only whole integer values can be
         *   displayed in a non-decimal radix; if the number has a fractional
         *   part, the radix will be ignored and the number will be shown in
         *   decimal.
         *
         *   'isSigned' indicates whether or not the value should be treated as
         *   "signed", meaning that negative values are represented with a "-"
         *   sign followed by the absolute value.  If 'isSigned' is nil, a
         *   negative value won't be converted to its absolute value before being
         *   displayed, but will instead be re-interpreted within its type system
         *   as an unsigned value.  For regular integers, this means that the
         *   result depends on the native hardware storage format for negative
         *   integers.  Most modern hardware uses two's complement notation,
         *   which represents -1 as 0xFFFFFFFF, -2 as 0xFFFFFFFE, etc.  Most
         *   types other than integer don't have distinct signed and unsigned
         *   interpretations, so 'isSigned' isn't meaningful with most other
         *   types.  With BigNumber in particular, the only effect is to omit the
         *   "-" sign for negative values.
         */
        toString(val, radix?, isSigned?);

        /*
         *   Convert the given value to an integer.
         *
         *   If 'val' is a string, the function parses the string's contents as
         *   an integer in the numeric base given by 'radix, which can be any
         *   integer from 2 to 36.  If 'radix' is omitted or nil, the default is
         *   base 10 (decimal).  The value is returned as an integer.  If the
         *   number represented by the string is too large for a 32-bit integer,
         *   a numeric overflow error occurs.
         *
         *   If 'val' is true, or the string 'true', the return value is 1.  If
         *   'val' is nil, or the string 'nil', the return value is 0.  Leading
         *   and trailing spaces are ignored for these strings.
         *
         *   If 'val' is a BigNumber value, the value is rounded to the whole
         *   number, and returned as an integer value.  A numeric overflow error
         *   occurs if the number is out of range for a 32-bit integer.  (If you
         *   want to round a BigNumber to the nearest integer and get the result
         *   as another BigNumber value, use the getWhole() method of the
         *   BigNumber.)
         *
         *   See also toNumber(), which can also parse floating point values and
         *   whole numbers too large for the ordinary integer type.
         */
        toInteger(val, radix?);

        /*
         *   Get the current local time.
         *
         *   If timeType is GetTimeDateAndTime (or is omitted), this returns the
         *   calendar date and wall-clock time, as a list: [year, month,
         *   dayOfMonth, dayOfWeek, dayOfYear, hour, minute, second, timer].
         *   Year is the year AD (for example, 2006); month is the current month,
         *   from 1 (January) to 12 (December); dayOfMonth is the calendar day of
         *   the month, from 1 to 31; dayOfWeek is the day of the week, from 1
         *   (Sunday) to 7 (Saturday); dayOfYear is the current day of the year,
         *   from 1 (January 1) to 366 (December 31 in a leap year); hour is the
         *   hour on a 24-hour clock, ranging from 0 (midnight) to 23 (11pm);
         *   minute is the minute of the hour, from 0 to 59; second is the second
         *   of the minute, from 0 to 59; and timer is the number of seconds
         *   elapsed since the "Epoch," defined as midnight, January 1, 1970,
         *   midnight UTC.  (This is the Epoch that Unix-like systems use, so it
         *   appears frequently in computer timekeeping systems.)  See the Date
         *   class for more comprehensive date/time handling.
         *
         *   If timeType is GetTimeTicks, this return the number of milliseconds
         *   since an arbitrary starting time.  The first call to get this
         *   information sets the starting time, so it will return zero;
         *   subsequent calls will return the amount of time elapsed from that
         *   starting time.  Note that because a signed 32-bit integer can only
         *   hold values up to about 2 billion, the maximum elapsed time that
         *   this value can represent is about 24.8 days; so, if your program
         *   runs continuously for more than this, the timer value will roll
         *   around to zero at each 24.8 day multiple.  So, it's possible for
         *   this function to return a smaller value than on a previous
         *   invocation, if the two invocations straddle a 24.8-day boundary.
         */
        getTime(timeType?);

        /*
         *   Match a string to a regular expression pattern.  'pat' can be either
         *   a string giving the regular expression, or can be a RexPattern
         *   object.  'str' is the string to match, and 'index' is the starting
         *   character index (the first character is at index 1) at which to
         *   start matching.  Returns the length in characters of the match, or
         *   nil if the string doesn't match the pattern.  (Note that a return
         *   value of zero doesn't indicate failure - rather, it indicates a
         *   successful match of the pattern to zero characters.  This is
         *   possible for a pattern with a zero-or-more closure, such as 'x*' or
         *   'x?'.)
         */
        rexMatch(pat, str, index?);

        /*
         *   Search the given string for the given regular expression pattern.
         *   'pat' is a string giving the regular expression to find, or a
         *   RexPattern object.  'str' is the string to search, and 'index' is
         *   the optional starting index (the first character is at index 1;
         *   negative indices are from the end of the string, so -1 is the last
         *   character, -2 is the second to last, and so on).  If a match to the
         *   pattern isn't found, returns nil.  If a match is found, the return
         *   value is a list: [index, length, string], where index is the
         *   starting character index of the match, length is the length in
         *   characters of the match, and string is the text of the match.
         */
        rexSearch(pat, str, index?);

        /*
         *   Get the given regular expression group.  This can be called after a
         *   successful rexMatch() or rexSearch() call to retrieve information on
         *   the substring that matched the given "group" within the regular
         *   expression.  A group is a parenthesized sub-pattern within the
         *   regular expression; groups are numbered left to right by the open
         *   parenthesis, starting at group 1.  If there is no such group in the
         *   last regular expression searched or matched, or the group wasn't
         *   part of the match (for example, because it was part of an
         *   alternation that wasn't matched), the return value is nil.  If the
         *   group is valid and was part of the match, the return value is a
         *   list: [index, length, string], where index is the character index
         *   within the matched or searched string of the start of the group
         *   match, length is the character length of the group match, and string
         *   is the text of the group match.
         */
        rexGroup(groupNum);

        /*
         *   Search for the given regular expression pattern (which can be given
         *   as a regular expression string or as a RexPattern object) within the
         *   given string, and replace one or more occurrences of the pattern
         *   with the given replacement text.
         *
         *   The search pattern can also be given as a *list* of search patterns.
         *   In this case, we'll search for each of the patterns and replace each
         *   one with the corresponding replacement text.  If the replacement is
         *   itself given a list in this case, each element of the pattern list
         *   is replaced by the corresponding element of the replacement list.
         *   If there are more patterns than replacements, the extra patterns are
         *   replaced by empty strings; any extra replacements are simply
         *   ignored.  If the replacement is a single value rather than a list,
         *   each pattern is replaced by that single replacement value.
         *
         *   'flags' is a combination of the ReplaceXxx bit flags, using '|'.  If
         *   the flags include ReplaceAll, all occurrences of the pattern are
         *   replaced; otherwise only the first occurrence is replaced.
         *
         *   ReplaceOnce and ReplaceAll are mutually exclusive; they mean,
         *   respectively, that only the first occurrence of the match should be
         *   replaced, or that every occurrence should be replaced.  ReplaceOnce
         *   and ReplaceAll are ignored if a 'limit' value is specified (this is
         *   true even if 'limit' is nil, which means that all occurrences are
         *   replaced).
         *
         *   If ReplaceIgnoreCase is included, the capitalization of the match
         *   pattern is ignored, so letters in the pattern match both their
         *   upper- and lower-case equivalents.  Otherwise the case will be
         *   matched exactly. If ReplaceFollowCase AND ReplaceIgnoreCase are
         *   included, lower-case letters in the replacement text are capitalized
         *   as needed to follow the capitalization pattern of the actual text
         *   matched: if all the letters in the match are lower-case, the
         *   replacement is lower case; if all are upper-case, the replacement is
         *   changed to all upper-case; if there's a mix of cases in the match,
         *   the first letter of the replacement is capitalized and the rest are
         *   left in lower-case.
         *
         *   The ReplaceSerial flag controls how the search proceeds when
         *   multiple patterns are specified.  By default, we search for each one
         *   of the patterns, and replace the leftmost match.  If ReplaceOnce is
         *   specified, we're done; otherwise we continue by searching again for
         *   all of the patterns, this time in the remainder of the string (after
         *   that first replacement), and again we replace the leftmost match.
         *   This proceeds until we can't find any more matches for any of the
         *   patterns.  If ReplaceSerial is included in the flags, we start by
         *   searching only for the first pattern, replacing one or all
         *   occurrences depending on the ReplaceOnce or ReplaceAll flag.  Next,
         *   if ReplaceAll is specified OR we didn't find any matches for the
         *   first pattern, we start over with the result and search for the
         *   second pattern, replacing one or all occurrences of it.  We repeat
         *   this for each pattern.
         *
         *   If the flags are omitted entirely, the default is ReplaceAll (which
         *   means replace all occurrences, exact case matches only, parallel
         *   searching).
         *
         *   'index', if provided, is the starting character index of the search;
         *   instances of the pattern before this index will be ignored.  Returns
         *   the result string with all of the desired replacements.  When an
         *   instance of the pattern is found and then replaced, the replacement
         *   string is not rescanned for further occurrences of the text, so
         *   there's no danger of infinite recursion; instead, scanning proceeds
         *   from the next character after the replacement text.
         *
         *   'limit', if specified, is an integer indicating the maximum number
         *   of matches to replace, or nil to replace all matches.  If the limit
         *   is reached before all matches have been replaced, no further
         *   replacements are performed.  If this parameter is specified, it
         *   overrides any ReplaceOnce or ReplaceAll flag.
         *
         *   The replacement text can use "%n" sequences to substitute group
         *   matches from the input into the output.  %1 is replaced by the match
         *   to the first group, %2 the second, and so on.  %* is replaced by the
         *   entire matched input.  (Because of the special meaning of "%", you
         *   must use "%%" to include a percent sign in the replacement text.)
         */
        rexReplace(pat, str, replacement, flags?, index?, limit?);

        /*
         *   Create an UNDO savepoint.  This adds a marker to the VM's internal
         *   UNDO log, establishing a point in time for a future UNDO operation.
         */
        savepoint();

        /*
         *   UNDO to the most recent savepoint.  This uses the VM's internal UNDO
         *   log to undo all changes to persistent objects, up to the most recent
         *   savepoint.  Returns true if the operation succeeded, nil if not.  A
         *   nil return means that there's no further UNDO information recorded,
         *   which could be because the program has already undone everything
         *   back to the start of the session, or because the UNDO log was
         *   truncated due to memory size such that no savepoints are recorded.
         *   (The system automatically limits the UNDO log's total memory
         *   consumption, according to local system parameters.  This function
         *   requires at least one savepoint to be present, because otherwise it
         *   could create an inconsistent state.)
         */
        undo();

        /*
         *   Save the current system state into the given file.  This uses the
         *   VM's internal state-save mechanism to store the current state of all
         *   persistent objects in the given file.  Any existing file is
         *   overwritten.
         *
         *   'metatab' is an optional LookupTable containing string key/value
         *   pairs to be saved with the file as descriptive metadata.  The
         *   interpreter and other tools can display this information to the user
         *   when browsing a collection of saved game files, to help the user
         *   remember the details of each saved position.  It's up to the game to
         *   determine what to include; the list can include any information
         *   relevant to the game that would be helpful when reviewing saved
         *   position files, such as the room name, score, turn count, chapter
         *   name, etc.
         */
        saveGame(filename, metatab?);

        /*
         *   Restore a previously saved state file.  This loads the states of all
         *   persistent objects stored in the given file.  The file must have
         *   been saved by the current version of the current running program; if
         *   not, an exception is thrown.
         */
        restoreGame(filename);

        /*
         *   Restart the program from the beginning.  This resets all persistent
         *   objects to their initial state, as they were when the program was
         *   first started.
         */
        restartGame();

        /*
         *   Get the maximum of the given arguments.  The values must be
         *   comparable with the ordinary "<" and ">" operators.  Note that
         *   because this is an ordinary function call, all of the arguments are
         *   evaluated (which means any side effects of these evaluations will be
         *   triggered).
         */
        max(val1, ...);

        /*
         *   Get the minimum of the given arguments.  The values must be
         *   comparable with the ordinary "<" and ">" operators.  Note that
         *   because this is an ordinary function call, all of the arguments are
         *   evaluated (which means any side effects of these evaluations will be
         *   triggered).
         */
        min(val1, ...);

        /*
         *   Create a string by repeating the given value the given number of
         *   times.  If the repeat count isn't specified, the default is 1; a
         *   repeat count less than zero throws an error.  'val' can be a string,
         *   in which case the string is simply repeated the given number of
         *   times; an integer, in which case the given Unicode character is
         *   repeated; or a list of integers, in which case the given Unicode
         *   characters are repeated, in the order of the list.  The list format
         *   can be used to create a string from a list of Unicode characters
         *   that you've been manipulating as a character array, which is
         *   sometimes a more convenient or efficient way to do certain types of
         *   string handling than using the actual string type.
         */
        makeString(val, repeatCount?);

        /*
         *   Get a description of the parameters to the given function.  'func'
         *   is a function pointer.  This function returns a list: [minArgs,
         *   optionalArgs, isVarargs], where minArgs is the minimum number of
         *   arguments required by the function, optionalArgs is the additional
         *   number of arguments that can be optionally provided to the function,
         *   and isVarargs is true if the function takes any number of additional
         *   ("varying") arguments, nil if not.
         */
        getFuncParams(func);

        /*
         *   Convert the given value to a number.  This is similar to
         *   toInteger(), but can parse strings containing floating point numbers
         *   and whole numbers too large for ordinary integers.
         *
         *   If 'val' is an integer or BigNumber value, the return value is
         *   simply 'val'.
         *
         *   If 'val' is a string, the function parses the string's contents as a
         *   number in the given 'radix', which can be any integer from 2 to 36.
         *   If 'radix' is omitted, the default is 10 for decimal.  If the radix
         *   is decimal, and the number contains a decimal point (a period, '.')
         *   or an exponent (which consists of the letter 'e' or 'E', an optional
         *   '+' or '-' sign, and one or more digits), the value is parsed as a
         *   floating point number, and a BigNumber value is returned.  For any
         *   other radix, decimal points and exponents are considered non-number
         *   characters.  For an integral value, the result will be an integer if
         *   the number is within the range that fits in an integer, otherwise
         *   the result is a BigNumber.  The routine will simply stop parsing at
         *   the first non-number character it encounters, so no error will occur
         *   if the string contains text following the number.  If the text
         *   doesn't contain any number characters at all, the result is zero.
         *
         *   If val is true or the string 'true', return 1; if nil or the string
         *   'nil', returns 0.  Leading and trailing spaces are ignored in the
         *   string versions of these values.
         */
        toNumber(val, radix?);

        /*
         *   Format values into a string.  This is similar to the traditional C
         *   language "printf" family of functions: it takes a "format string"
         *   containing a mix of plain text and substitution parameters, and a
         *   set of values to plug in to the substitution parameters, and returns
         *   a new string containing the formatted result.
         *
         *   'format' is the format string.  Most characters of the format string
         *   are simply copied verbatim to the result.  However, each '%' in the
         *   format string begins a substitution parameter; the '%' is followed
         *   by one or more optional qualifiers, then by a type code letter.  The
         *   corresponding value from the argument list is formatted into a
         *   string according to the type code, and then replaces the entire '%'
         *   sequence in the result string.  By default, the first '%' parameter
         *   corresponds to the first additional argument after 'format', the
         *   second '%' corresponds to the second additional argument, and so on.
         *   You can override the default argument position of a '%' using the
         *   '$' qualifier - see below.
         *
         *   The arguments following 'format' are the values to be substituted
         *   for the '%' parameters in the format string.
         *
         *   The return value is a string containing the formatted result.
         *
         *   See the System Manual for the list of '%' codes.
         */
        sprintf(format, ...);

        /*
         *   Create a list by repeating the given value the given number of
         *   times.  If the repeat count isn't specified, the default is 1; a
         *   repeat count less than zero throws an error.  'val' can be any
         *   value; it's simply repeated in each element of the list.
         */
        makeList(val, repeatCount?);

        /*
         *   Get the absolute value of a number.  The argument can be an integer
         *   or a BigNumber; the return value is the absolute value of the
         *   argument, and has the same type as the argument.  (The absolute
         *   value of a positive number X (or zero) is X; the absolute value of a
         *   negative number X is -X.)
         */
        abs(num);

        /*
         *   Get the sign of a number.  The argument can be an integer or a
         *   BigNumber.  The return value is an integer: 1 if the argument is
         *   positive, 0 if the argument is zero, -1 if the argument is negative.
         */
        sgn(num);

        /*
         *   Concatenate the arguments together into a single string.  The
         *   arguments can be strings or any types that can be automatically
         *   converted to string for the regular "+" operator; non-strings are
         *   first converted to strings using the same rules that "+" uses when
         *   combining a string with a non-string.  If there are no arguments,
         *   the result is an empty string.
         *
         *   This function is essentially the same as concatenating a series of
         *   values with the "+" operator, but it's more efficient with three or
         *   more values, since the "+" operator has to be applied successively
         *   in pairs; that creates and copies an extra intermediate result
         *   string at each step.  This function only creates one result string
         *   and only has to copy each input string once.
         */
        concat(...);

        /*
         *   Search backwards in the given string for the given regular
         *   expression pattern.  'pat' is a string giving the regular expression
         *   to find, or a RexPattern object.  'str' is the string to search, and
         *   'index' is the optional starting index (the first character is at
         *   index 1; negative indices are from the end of the string, so -1 is
         *   the last character, -2 is the second to last, and so on; 0 means the
         *   position just after the last character of the string).  If 'index'
         *   is omitted, the default is to search the entire string from the end,
         *   which is equivalent to passing 0 or str.length()+1 for 'index'.
         *
         *   If a match is found, the return value is a list: [index, length,
         *   string], where index is the starting character index of the match,
         *   length is the length in characters of the match, and string is the
         *   text of the match.
         *
         *   This does the same work as rexSearch(), but searches the string
         *   backwards, from the end to the start.  The match must end before the
         *   starting index, which allows for repeated searches: simply pass the
         *   match index from the previous search as the 'index' value for the
         *   next search to find the next earlier match that doesn't overlap the
         *   previous match.
         *
         *   The meanings of the <FirstBegin> and <FirstEnd> flags for a reverse
         *   search are essentially the mirror image of their meanings in a
         *   regular forward search.  This is easiest to understand by thinking
         *   about the flags in the abstract.  <FirstBegin> means that the
         *   winning match is the one whose "near" endpoint is closest to the
         *   starting index; <FirstEnd> means that the winner is the match whose
         *   "far" endpoint is closest to the starting index.  The near endpoint
         *   in a forward search is the start of the match, whereas it's the end
         *   of the match in a reverse search.  Similarly, the far endpoint is
         *   the end of the match in a forward search and the start of the match
         *   in a reverse search.  So in a reverse search, <FirstBegin> means
         *   that the winner is the match whose ending index is highest, and
         *   <FirstEnd> means that the winner is the one whose starting index is
         *   highest.
         */
        rexSearchLast(pat, str, index?);
    }

    /*
     *   flags for firstObj() and nextObj()
     */
    #define ObjInstances  0x0001
    #define ObjClasses    0x0002
    #define ObjAll        (ObjInstances | ObjClasses)

    /*
     *   rexReplace() flags
     */
    #define ReplaceAll         0x0001
    #define ReplaceIgnoreCase  0x0002
    #define ReplaceFollowCase  0x0004
    #define ReplaceSerial      0x0008
    #define ReplaceOnce        0x0010

    /*
     *   getTime() flags
     */
    #define GetTimeDateAndTime  1
    #define GetTimeTicks        2

    /*
     *   Random number generator IDs for randomize().
     */

    /*
     *
     *   RNG_ISAAC - ISAAC is the default generator.  It's designed for both
     *   cryptographic application and more mainstream uses.  Crypto applications
     *   generally have more stringent requirements for an RNG than ordinary
     *   applications.  ISAAC does well with the usual statistical tests for RNGs
     *   and is reasonably fast.
     *
     *   ISAAC's preferred format for a fixed seed is a string value.
     */
    #define RNG_ISAAC    1

    /*
     *   RNG_LCG - LCG stands for Linear Congruential Generator, which generates
     *   numbers using a simple linear formula.  This is the old standby of
     *   computer RNGs; it's the sort that comes standard with C compilers.
     *   These generators have been extensively studied and have reasonably good
     *   statistical properties and a number of known weaknesses.  The TADS LCG
     *   uses the method described in Knuth, The Art of Computer Programming,
     *   volume 2, p170.
     *
     *   The LCG's preferred format for a fixed seed is an integer value.
     */
    #define RNG_LCG      2

    /*
     *   RNG_MT19937 - Mersenne Twister MT19937 algorithm.  This is a widely used
     *   RNG algorithm that's become especially popular for scientific
     *   simulations.  It's relatively new, dating from 1997, and was designed to
     *   remedy most of the known shortcomings of linear congruential generators
     *   and other earlier RNGs.  It's fast and does well on standard statistical
     *   tests.
     *
     *   MT's preferred format for a fixed seed is a string value.
     */
    #define RNG_MT19937  3

TADS 3 Library Manual
Generated on 5/16/2013 from TADS version 3.1.3