Gwydion Extensions to Dylan
Gwydion Extensions
Copyright (c) 1994, 1995, 1996, 1997 Carnegie Mellon University All rights reserved.
1. Introduction
In the process of working with Dylan, the Gwydion Project has come up with numerous extensions to the Dylan language. Some of them form entire libraries, like the Collection-Extensions and String-Extensions libraries. Others have been added to the Dylan library, in such modules as Extensions and System.
We continue to make no claims about future support for our extensions. However, some extensions are more likely than others to make it into our future compilers. This file documents those extensions which we think will be included in our compilers Dylan library. Extensions which go in separate libraries are documented in their own files; extensions which are part of the Mindy Dylan library but which have a less certain future are documented in the Mindy documentation.
For the remainder of this document, we shall refer to "Gwydion compilers" as a shorthand for "Mindy and other Dylan compilers that the Gwydion Project may write." It is not meant as a guarentee that all future Gwydion releases will support these extensions.
Specific Gwydion compilers may support extensions not listed here; see their documentation for details.
2. Dylan Language Issues
Whenever possible, we have tried to keep the Dylan module pristine and unextended, prefering to add our extensions to separate modules or libraries. However, this is not always possible, particularly when it involves extending the behavior of a function or macro that is exported from the Dylan module. Currently, Gwydion compilers support these extensions to the Dylan module as described below:
- Gwydion compilers support keyed-by clauses in for statements. The format of such a clause is
var KEYED-BY key IN collection
Var is bound to each element in collection, and key is bound to the element's key value.
- Gwydion compilers supports using clauses in for statements. The format of such a clause is
var IN collection USING protocol
protocol will be used instead of forward-iteration-protocol. protocol must be a variable name, not an expression. Using clauses may be used together with keyed-by:
var KEYED-BY key IN collection USING protocol
- Gwydion compilers have an additional type of top level definition, define function, which creates a constant binding in the current module and initializes it to a new function. Define functions usage is similar to define method. The following is an example:
define function cube (x)
x * x * x;
end function cube;
A similar result might be had by writing
define constant cube = method (x)
x * x * x;
end method;
or
define method cube (x)
x * x * x;
end method cube;
- Gwydion compilers supports subclass specializers via the limited function. A subclass specializer causes a method to be invoked whenever the generic function was called on a value that is the specified class or any subclass of the specified class. The method is never invoked on a value that is an instance (direct or indirect) of the specified class, only when the value is a subclass of the specified class. The following is an example:
define method make
(result-class :: limited(<class>, subclass-of: <my-class>));
let x = next-method();
do-special-logging-or-something(x);
x;
end method;
3. Conditional Compilation
Gwydion compilers supports conditional compilation. The syntax is
#if (feature-expression)
dylan-code
#elseif (feature-expression)
dylan-code
#else
dylan-code
#endif
(The #elseif and #else clauses are optional) A feature-expression is composed of features and the ~, &, and | operators, and may be parenthesiszed as usual. Features are not case sensitive. Mindy and d2c use the -D and -U command line switches to define new features. Some features currently supported include:
- mindy
- compiled-for-hppa
- compiled-for-x86
- compiled-for-sparc
- compiled-for-hpux
- compiled-for-win32
- compiled-for-linux
- compiled-for-solaris
- compiled-for-unix
- newlines-are-CRLF
Defined when compiling for a system whose newline representation is two bytes, a carriage return ('\r') followed by a linefeed ('\f'). Examples of such systems include MS-DOS, Windows '95, Windows/NT, and OS/2. It should be kept in mind that not every file on a newlines-are-CRLF system will adhere to this convention; some will adhere to the Unix convention of using a single linefeed as the newline character. For this reason, programs should consider the carriage return an optional part of the newline sequence.
4. Modules of the Dylan Library
In addition to containing the Dylan module, the Dylan library contains a variety of modules which provide extensions. Gwydion compilers export the following modules from the Dylan library:
- Extensions
This module exports useful extensions to the Dylan language (see section The Extensions Module).
Ultimately, there will be several, more logically separate libraries that extend Dylan or provide an
application framework for users. For now, we put any commonly used utilities in the Extensions
module.
- System
- Introspection
- Cheap-io
5. The Extensions Module
Ultimately, there will be several, more logically separate libraries that extend Dylan or provide an application framework for users. For now, we put any commonly used utilities in the Extensions module.
5.1. Generally Useful Definitions
The Extensions module exports the following generally useful functionality:
<byte-vector> [Class]
This class is a subclass of <vector> that can only hold integers between 0 and 255 inclusively.
<byte-character> [Class]
This class is a subclass of <character>. Characters of this type represent the ASCII character set (or extensions to ASCII). Note, in Gwydion compilers the <character> class is equivalent to Unicode characters.
assert [Function]
- Arguments
- Values
- Description
This function signals an error if value is #f. Otherwise, it does nothing. In future Gwydion compilers, assert may be changed to a macro, which may or may not evaluate its argument exactly once.
one-of [Function]
- Arguments
- #rest objects :: <object>
- Values
- Description
This function takes any number of objects, and returns the type that is the type-union of the singletons of those objects. For example, the expression
one-of(#"foo", #"bar", #"baz")
type-union(singleton(#"foo"), singleton(#"bar"), singleton(#"baz"))
false-or [Function]
- Arguments
- Values
- Description
This function is useful in type expressions. It captures the common idiom of returning an instance of a particular type or the value #f. The expression
false-or(<integer>)
is equivalent to the expression
type-union(<integer>, singleton(#f))
5.2. Debugger Customizations
(A note on terminology: We use the term "debugger" here in the loose, Dylan sense of anything that handles an uncaught error. In Mindy, this debugger is indeed a full fledged debugger, but in other Gwydion compilers it may not be)
The debugger uses the function report-condition to print conditions as error messages to users; for example, this is the function that implements the %S format-string directive for conditions. The debugger also uses the format function exported from the Cheap-io module to process format strings, and it prints directly to the Unix stdout. If any library that is used itself uses the Debugger-format library, then the debugger uses format from the Format library, which is shipped with Gwydion compilers. You can extend how the debugger prints conditions, change what formatting function it uses, and direct where debugger output goes with the following:
report-condition [Generic Function]
- Arguments
- Values
- Description
This is the function that is used to print condition variables as error messages to users. The internal format function used by Mindy uses report-condition for condition arguments to the %S format directive. The Format librarys print-message method for conditions calls report-condition.
If you are writing a module that does no output but still provides report-condition methods, you should use condition-format to format output. Using condition-format makes your module more flexible for users of your module. If you call Cheap-IOs format, youll be forced to write to only one destination, stdout, ignoring the stream argument. If you call the Format librarys format function, then your module will require the Format, Print, and Streams libraries; therefore, users of your module may ultimately load these other libraries needlessly. Of course, if you want to make use of the extended functionality of the Format librarys format control strings, then you only have one choice anyway, and theres no reason to use condition-format.
condition-format [Generic Function]
- Arguments
- control-string :: <string>
- Values
- Description
This function serves as a firewall between the condition system and the Streams and Format libraries. Methods on report-condition should use condition-format to do their formatting. Users will generally use *debug-output* or *warning-output* for the stream argument, but this is not required.
Mindy supplies a method for when stream is #"Cheap-IO". The Gwydion Format library supplies a method for when stream is a subclass of <stream>. If you are implementing your own streams or format libraries, you will need to define a method on condition-format for your type of stream.
condition-force-output [Generic Function]
- Arguments
- Values
- Description
Condition-force-output forces any pending output from streams buffer to streams destination. This function is invoked by the debugger after a condition has been reported and before it pauses for user input. Unless you are writing a debugger, you do not need to call condition-force-output yourself.
Mindy supplies a method for when stream is #"Cheap-IO". The Gwydion Format library supplies a method for when stream is a subclass of <stream>. If you are implementing your own streams or format libraries, you will need to define a method on condition-force-output for your type of stream.
*warning-output* [Variable]
Default-handler for <warning> uses *warning-output* to print warning messages. This variable must be either a <stream> from the Streams library, or #"Cheap-IO" (the default). When this variable is#"Cheap-IO", the output goes to stderr.
5.3. Exiting Applications
The Extensions module exports the following functionality for controlling the exiting of applications:
exit [Function]
- Arguments
- #key exit-code :: <integer> = 0
- Description
Causes the process to exit with return code exit-code.
5.4. Collections
The Extensions module exports the following <collection> functionality:
key-exists? [Generic Function]
- Arguments
- collection :: <collection>
- Values
- Description
Return whether key is in collection. If the key is in the collection, then the second value is the element associated with key; otherwise, the second return value is #f.
5.5. Integers
Gwydion compilers have an abstract class <general-integer> which has two concrete subclasses, <integer> and <extended-integer>. <integer>s have a limited range of values, and <integer> arithmetic uses the computers underlying integer facilities. <extended-integer>s can take on any value, and are similar to Common Lisp "big-nums." Expressions involving <extended-integer>s produce <extended-integer> results because <extended-integer>s are contagious. If an expression involving only <integer> values would produce a result that does not fit in an <integer>, then the Gwydion compiler will signal an overflow error. You can use the as function to convert back and forth between <integer>s and <extended-integer>s. As signals an error when converting an <extended-integer> to a <integer>, and the value does not fit in a <integer>.
The Extension module exports the following integer functionality:
<general-integer> [Abstract Class]
<extended-integer> [Class]
<general-integer> is a subclass of <rational>, and is the superclass of <integer> and <extended-integer>.
$maximum-integer [Constant]
$minimum-integer [Constant]
These constants hold the largest positive <integer> and the largest negative <integer>.
5.6. Ratios
The Extensions module exports the following:
<ratio> [Class]
This class is a subclass of <rational>. The ratio is normalized so that it has a positive denominator, and the greatest common divisor of the numerator and the denominator is one. Ratios are never automatically converted to integers. For example, ratio(4,2) would return 2/1.
A numeric operation involving two ratios produces a normalized ratio result. A numeric operation involving a ratio and an integer produced a normalized ratio result. A numeric operation involving a ratio and a float produces a float result.
ratio [Function]
- Arguments
- numerator :: <general-integer>
- denominator :: <general-integer>
- Values
- Description
This function makes a ratio from the two integers.
numerator [Function]
- Arguments
- Values
- the-numerator :: <general-integer>
- Description
This function returns the numerator part of ratio.
denominator [Function]
- Arguments
- Values
- the-numerator :: <general-integer>
- Description
This function returns the denominator part of ratio.
6. The System Module
The System module exports the following:
<buffer> [Class]
This class is a subclass of <vector>. It is the built-in class that the Streams module uses.
copy-bytes [Function]
- Arguments
- dst :: type-union(<buffer>, <byte-vector>, <byte-string>)
- src :: type-union(<buffer>, <byte-vector>, <byte-string>)
- Values
- dst :: type-union(<buffer, <byte-vector>, <byte-string>)
- Description
Copies count bytes from src to dst, starting at src-offset and dst-offset, respectively. This function returns dst. This function does no bounds checking. Dst and src may be the same (\==) object; this function ensures that it copies bytes from to the destination portion correctly, regardless of overlap.
getenv [Function]
- Arguments
- environment-variable-name :: <string>
- Values
- environment-variable-value :: false-or(<string>)
- Description
Returns the value of the environment variable environment-variable-name. If environment-variable-name is undefined, getenv returns #f.
get-time-of-day [Function]
- Arguments
- Values
- time-in-seconds :: <general-integer>
- Description
Returns the number of seconds since midnight, January 1, 1970.
system [Function]
- Arguments
- Values
- Description
System causes command-line to be given to your shell as input as if the string had been typed as a command. If environment variable SHELL is found, its value will be used as the command interpreter (shell); otherwise sh(1) is used.
The parent process will wait until the command terminates. Upon termination of the sub-process, system will return a negative value if the command couldnt be executed, or the commands return code if it was executed.
7. The Introspection Module
The Introspection module exports reflective operations for examining classes, functions, and types.
7.1. Functions
Dylan provides some reflective operations for functions, such as function-specializers and instance?. With the latter, you can determine if a function is a <generic-function> or <method>, but neither Dylan nor Gwydion compilers provide exported class identifiers for other types of functions (such as block exit functions). The Subsection Types describes definitions that are also useful when inspecting methods because you can get detailed information about method specializer types.
The Introspection module exports the following functions:
function-name [Function]
- Arguments
- Values
- result :: false-or(<symbol>)
- Description
Returns the name of function as a <symbol> if function has a name; otherwise function-name returns #f. All functions defined with define generic or define method have names, and some other functions have names.
7.2. Classes
The Introspection module exports the following for class objects:
class-name [Function]
- Arguments
- Values
- result :: false-or(<symbol>)
- Description
Returns the name of class as a <symbol> if class has a name; otherwise, this function returns #f. Mindy can always determine the name of classes defined with define class.
7.3. Types
The Introspection module exports the following for inspecting types (and therefore, method specializers):
singleton-object [Function]
- Arguments
- specializer :: <singleton>
- Values
- Description
This function returns the object of the singleton value type.
<subclass> [Class]
This class is a subclass of <type>. Instances of this class represent subclass specializers. A subclass specializer causes a method to be invoked whenever the generic function was called on a value that is the specified class or any subclass of the specified class (see section Dylan Language Issues for more information). The function subclass-of returns the class specified for the subclass specializer.
subclass-of [Function]
- Arguments
- specializer :: <subclass>
- Values
- Description
Returns the class specified for the subclass specializer.
<limited-integer> [Class]
This class is a subclass of <type>. Instances of this class represent limited integer types. See the functions limited-integer-base-class, limited-integer-minimum, and limited-integer-maximum.
limited-integer-base-class [Function]
- Arguments
- specializer :: <limited-integer>
- Values
- class :: one-of(<integer>, <extended-integer>)
- Description
Returns the class specified for the limited-integer specializer, either <integer> or <extended-integer>.
limited-integer-minimum [Function]
limited-integer-maximum [Function]
- Arguments
- specializer :: <limited-integer>
- Values
- class :: false-or(<integer>)
- Description
Return the inclusive bounds of the limited-integer specializer. If the minimum or maximum is unbounded, then the appropriate function returns #f.
<union> [Class]
This class is a subclass of <type>. Instances of this class represent union types (ie, what type-union returns). The function union-members returns a list of the member types in the union.
union-members [Function]
- Arguments
- Values
- Description
Returns the member types of the union type. The result may contain more than two elements. This function collapses nested union types to a flat list.
7.4. Miscellaneous
The Introspection module exports the following miscellaneous functionality:
object-address [Function]
- Arguments
- Values
- Description
Returns an integer for object. If the object is represented internally represented as immediate data, then the integer returned is only unique to the value of the object. If the object is represented on the dynamic heap, then the integer uniquely identifies the object from all other objects.
8. The Cheap-io Module
The Cheap-io module exports some basic, unextendable I/O functionality. Gwydion compilers use the Cheap-io functions internally. The Gwydion Project also provides the Streams, Print, and Format libraries (see the $INSTALL/doc/libraries/ directory for documentation). It is an error to use both Cheap-IO functions and Streams/Print/Format functions on a single stream. (For example, if you are using the Streams library *standard-input*, do not also use the Cheap-io input functions) For this reason, if any library that you load into Mindy uses the Debugger-format library, the debugger will use format from the Format library.
format [Function]
- Arguments
- control-string :: <byte-string>
- Values
- meaningless :: singleton(#f)
- Description
This format adheres to the format strings described in the Dylan Interim Reference Manual with one exception. Some Gwydion compilers incorrectly prints instances of <condition> supplied to the %S directive. The Format library provides a correct format function that supports an upward-compatible extension to the format control strings described in the DRM.
print [Function]
- Arguments
- Values
- meaningless :: singleton(#f)
- Description
Prints thing to stdout. Print follows thing with a newline. You cannot extend or specialize how objects are printed.
9. Extensions to the Streams Library
The Piped-exec module is a Gwydion extension to the Streams library. It exports the following function:
piped-exec [Function]
- Arguments
- Values
- writeable-stream :: <stream>
- readable-stream :: <stream>
- Description
piped-exec spawns a child process whose standard input and standard output are obtained from the parent process. Specifically, the parents writeable-stream is attached to the childs standard input, and the parents readable-stream is attached to the childs standard output. The readable-stream will be closed when the child closes its standard output, or when the child process terminates. The child process will be spawned by executing the command line command. Unlike the system command, the command line is not passed to a shell, so no wildcard expansion will be done. Like system, however, if the command name is not a fully qualified path, the executable file will be searched for.
Caveat: On Microsoft Windows machines, the command may not be a batch file.
10. Copyright and Terms of Use
Copyright (c) 1994, 1995, 1996, 1997 Carnegie Mellon University All rights reserved.
Use and copying of this software and preparation of derivative works based on this software are permitted, including commercial use, provided that the following conditions are observed:
- This copyright notice must be retained in full on any copies and on appropriate parts of any derivative works.
- Documentation (paper or online) accompanying any system that incorporates this software, or any part of it, must acknowledge the contribution of the Gwydion Project at Carnegie Mellon University.
This software is made available as is. Neither the authors nor Carnegie Mellon University make any warranty about the software, its performance, or its conformity to any specification.
Bug reports, questions, comments, and suggestions should be sent by E-mail to the Internet address gwydion-bugs@cs.cmu.edu.
Copyright 1994, 1995, 1996, 1997 Carnegie Mellon University. All rights reserved.
Send comments and bug reports to gwydion-bugs@cs.cmu.edu