csk@cs.washington.edu
)
Güd is written in Java and requires a Java runtime which supports Java
1.1.1 or higher. The
JavaSoft web site describes how to
download a Java runtime. You must be able to run Java cleanly from the
command line (as the program java
). That may involve setting
the PATH
, CLASSPATH
, and JAVA_HOME
environment variables. See the Java documentation for more details.
Unzip and untar the Güd distribution ("%
" is your command
prompt):
% gunzip gud-0.1.tar.gz
% tar xf gud-0.1.tar
This produces a directory called gud-0.1
which contains all
the files you'll need to run the interpreter.
To use the gud
script, you must set the
GUD_HOME
environment variable to the location of the
gud-0.1
directory. If you unpacked the archive into
/home/fred/gud-0.1
, you would execute something like
% setenv GUD_HOME /home/fred/gud-0.1
Now you are ready to run $GUD_HOME/gud. It will display a
welcome message and a prompt ("-
" is the Güd prompt), like
% $GUD_HOME/gud
This is Güd, version 1.0 (Thu Jul 9 1998)
Reading from "/home/fred/gud-0.1/prelude.gud"...
-
If you have difficulty or questions about installing or running Güd,
please contact the authors and we
will try to assist you.
-
" prompt and should always end with a semicolon
(;
). Additional commentary appears on the right.
Part 1: Some simple values | |
- true; |
true is bound at startup to a unique object in the system.
Like most interpreters, this statement is a request to evaluate
the expression and print the result.
For a complete listing of the built-in objects in the interpreter, see Section 4, Built-in Names. |
- 568; | Every integer literal is like a special predefined identifier bound to a unique object representing that integer value. |
- 5.4; | Floating point values are not currently supported. |
- "Hello, World!"; | String literals are supported. Any special escape sequences inside string literals are not supported. |
Part 2: Variables | |
- it; |
The result of the previous computation is always bound
to the identifier it .
|
- def x = 19; |
Bind the identifier x to the value 19 .
Like ML (and unlike Scheme), this definition hides any previous
bindings to the identifier x , but does not destroy
them. Earlier uses of x still refer to the previous
binding.
A |
Part 3: Method Invocations and Arithmetic | |
- toFormatted( 5 ); |
A simple example of a method invocation. toFormatted is
a built-in function that returns a string representation of any
object.
|
- 4 * 11 - 9 / (7 + 1) >= 99; | The usual arithmetic operators and their precedence relations are supported for integers. But these are all special cases of method invocations... |
- operator "*"( 4, 11 ); |
The operator keyword is special syntax. It
causes the following string literal to be treated as an
identifier. This allows you to refer to operators as
values. You can use this to, e.g., add new cases to an
operator.
|
- "Hello, " + "World!"; |
The operator + is predefined on strings to do concatenation.
|
- toFormatted; | Methods are first-class objects in the system. |
Part 4: Objects and Parents | |
- object; |
The object keyword is an expression that constructs
a fresh object in the system. Think of it as the expression
new Object() in Java.
Because this new object has no specialized printed representation, the default is used, which is the object's hash code. |
- object with parent number; |
x with parent y clones x and adds an
inheritance link from this clone to y . The value of
the expression is the cloned object.
The inheritance links form the basis for predicate overriding. |
- object with parent 6; | Inheritance links can be established between any two non-locked objects (see below). |
- 6 with parent true; |
This expression returns a "new 6" which is also a child of
true . Because with parent is
side-effect free, this does not modify the "canonical" 6.
|
- operator "+" has parent true; |
The has parent syntax is the destructive version of
with parent . x has parent y adds
an inheritance link from x to y
and returns x .
|
- object with parent boolean with parent integer; | Multiple inheritance is supported. |
- def inviolate = const object; |
const creates a "locked" object which cannot be
modified. However, the locked object can be cloned, and
that copy can be modified.
|
- 6 has parent true; | Numbers are locked. |
Part 5: Methods | |
- def f = object with method( b ) when b@true { 165 }; |
with method is like with parent ; it
clones the source object and adds the given method case (or cases).
This example creates a new object, clones it, and adds a new
method case to the clone. The case takes a single argument. When
the argument is equal to or a descendant of true ,
the method is applicable and the body executes, returning
165 .
|
- f( false ); |
f still has no applicable case for the argument
false .
|
- f has method( b ) when b@false { -138 }; |
We can fix the above error by adding a case for false .
The has method syntax is analogous to
has parent . Note that this doesn't affect the
b@true case.
|
- f has method( n@number ) { "number" }; | For convenience, class tests can be embedded inside the formal list of a method declaration. |
- f has method( @150 ) { "special" }; |
For further convenience, the formal name can be omitted. This
new case will dispatch on 150 or its descendants. Note that
the previous case still applies to all other numbers.
For a complete description of the syntax for formals, see the abstract syntax. |
- def op_and = object has method( a@boolean, b@boolean ) |
This method declaration demonstrates several important features
of the language:
|
- defrec fact = object has method( n@number ) |
defrec is just like def , except
that it makes the identifier being defined visible within
(method bodies in) the initializing expression; this makes
it easy to express recursion.
|
- method fact( n@number ) |
The method statement, which can be
used only at the top level, defines an object of a given name
and adds (recursive) method cases.
|
- def thunk7 = [ 3+4 ]; |
This Smalltalk-like block [ expression ] is syntactic sugar for
object with method() { expression } .
|
Part 6: Predicates | |
- method f( a ) |
The two main class test predicates are given by the operators
@ and @= . a@b holds
if a is b or a descendant of b .
a@=b holds only when a and b
are identical.
|
- f has method( n@number ) |
To evaluate an arbitrary program expression, use the test
base predicate. The expression must evaluate to
true or false . All other values produce
a runtime error.
|
- method g( m@number, n@number ) |
A let base predicate binds an identifier to a value
(possibly computed in terms of the method's formals). The bound
identifier acts as a "pseudo-formal": further predicate testing
is possible on it, and the binding is exported into the body of
the method case.
|
- def blah = object; |
Any combination of the connectives and , or
and not (and having higher
precedence than or ) is possible
within a predicate.
|
- predicate even( n@number ) |
The predicate keyword constructs a predicate abstraction.
|
- method f( n ) |
This method uses a call to the even predicate
abstraction defined above. Since the abstraction doesn't return
any values, the call doesn't bind any pseudo-formals.
|
- method f( n ) when n@even { true } | A single value may be tested against a predicate abstraction using a syntax similar to that of class tests. |
- predicate even2(n@number) | A predicate abstraction may return an array-like collection of values; those values may be bound to variables at the abstraction invocation site. |
Built-in to the Interpreter | |
def tao = object;
|
A default object. tao denotes a meaningless
value, like the unit object () in ML.
|
def boolean = object; |
The boolean type and its children (instances)
true and false .
|
def string = object;
| The parent of all string literals. |
def number = object; | The numeric types and integer literals. |
+, -, *, / |
The standard arithmetic and relational operators. The
- operator supports both subtraction and unary
negation.
|
method exit( n@integer ) { | Exit with status n. |
method load( s@string ) { | When the argument is a file name, load that file name and execute it as a sequence of Güd statements. When the argument is a Java class name, load the class and call its initialization method. |
def __name__ = ...; | Some built-in objects that describe the interpreter. |
method printString( s@string ) { |
printString prints an arbitrary string to the console.
newline prints a newline to the console.
|
method toRaw( o ) { |
Build printable representations of objects. toRaw
constructs a representation that it used when printing the result
of a computation. toFormatted is the representation
used when explicitly printing an object. The default behaviour for
toFormatted is to call toRaw .
|
method pp( o ) { | Pretty-print the object o. This method doesn't work particularly well. |
method debugPredicates( b@boolean ) { | Turn the debugging of predicates on or off. When predicate debugging is on, adding a case to a method produces debugging information about static predicate comparison. |
Defined in | |
method eq( a, b ) { |
A function that uses @= style dispatching to
determine whether two objects are identical. This is
pointer/object equivalence, not structural equivalence.
|
&&, ||, !
| Boolean conjunction, disjunction, and negation. Although the syntax for these operators is built-in to the interpreter, their definitions are in the standard prelude. |
method if( b@boolean, thunk1, thunk2 ) { ... }
|
The if method invokes one of the two
thunks, depending on whether the first argument is true. A
two-argument version is also available.
|
method compose( f, g ) { | Compose takes f and g, both methods of a single variable, and returns h such that h(x) = f(g(x)) for all x. |
method print( x ) { |
These methods combine toFormatted and
printString to do formatted output of
arbitrary objects to the console. println is
just like print except that it appends a
newline.
|
list, nil, cons, |
The usual list data definitions and operations. For more information,
look at the comments inside prelude.gud .
|
First, here's the metasyntax, the notation that will be used to present the abstract syntax:
- expr, statement
- Italic text represents non-terminals in the language.
when
,let
- Bold text in code font represents tokens in the language, which must be typed exactly as given.
- []
- Square brackets denote an optional item.
- {}
- Curly braces denote zero or more repetitions of an item.
- ID, STRLIT, INTLIT
- Capitalized words represent general classes of identifiers.
And now, the complete abstract syntax for the language.
program ::= { statement ; }
|
|
|
|
|
|
|
|
|
|
$GUD_HOME/prelude.gud
.
It contains some standard definitions of objects and methods found
in many other programming languages.
stdlib
directory contains examples that are considered
to be "library-like": they provide functionality that is generally
useful but not so important that it be placed in the prelude.
examples
directory contains all other examples.
These are sample client programs that use predicate dispatching.
The examples come in two varieties: Güd input files and Java files.
The Güd files are read directly by the interpreter. Use the
load
method, passing as an argument the path to the file:
% gud
This is Güd, version 1.0 (Thu Jul 9 1998)
Reading from "/home/fred/gud-0.1/prelude.gud"
- load( "/home/fred/gud-0.1/examples/goldbach.gud" );
Loading /home/fred/gud-0.1/examples/goldbach.gud
val it = true
The Java files
can be linked in to the interpreter using an experimental dynamic linking
facility.
To compile the example Java files, make sure that your CLASSPATH
variable contains at least $GUD_HOME
and
$GUD_HOME/gud.jar
:
% cd $GUD_HOME/examples
% setenv CLASSPATH $GUD_HOME/gud.jar:$GUD_HOME
% javac test.java
Then, to install them into a running interpreter, use the
load
method,
passing in the class name:
% $GUD_HOME/gud
This is Güd, version 1.0 (Thu Jul 9 1998)
Reading from "/home/fred/gud-0.1/prelude.gud"
- load( "examples.test" );
val it = true
If you would like more information about linking in native Java code, contact the authors.
Dubious: A Modular, Statically Typed OO Core Language
by Todd
D. Millstein
Ph.D. Qualifying Exam project report, Department of Computer Science and
Engineering, University of
Washington, January 1998.