thinman@netcom.com (Lance Norskog) (04/22/91)
- 17 -
( op name=Imag type=Number
( template
ID=output
(type=Complex ID=input)
)
( rewrite
(set (output, input1.im))
)
)
/ arithmetic operators
/ C1 + C2 = C1.re + C2.re, C1.im + C2.im
( op name=+ type=Number
( template
ID=output
(type=Complex ID=input1)
(type=Complex ID=input2)
)
( rewrite
(set(output.re,
(op name=+
(op name=Real(input1))
(op name=Real(input2))
)
))
(set(output.im,
(op name=+
(op name=Imag(input1))
(op name=Imag(input2))
)
))
)
)
/ C1 - C2 = C1.re - C2.re, C1.im - C2.im
/ elided for brevity
- 18 -
/ C1 * C2 = (C1.re * C2.re) - (C1.im * C2.im),
(C1.re * C2.im) + (C2.re * C1.im),
( op name=* type=Number
( template
ID=output
(type=Complex ID=input1)
(type=Complex ID=input2)
)
( rewrite
(set(output.re,
(op name=-
(op name=*
(op name=Real(input1))
(op name=Real(input2))
)
(op name=*
(op name=Imag(input1))
(op name=Imag(input2))
)
)
))
(set(output.im,
(op name=+
(op name=*
(op name=Real(input1))
(op name=Imag(input2))
)
(op name=*
(op name=Imag(input1))
(op name=Real(input2))
)
)
))
)
)
/ Square(Complex input) -> *(input, input)
( op name=Square type=Complex
( template
ID=output
(type=Complex ID=input)
)
( rewrite
(set (output,
(op name=*
(input)
(input)
)
))
)
)
)
- 19 -
The Complex object contains two numbers, and implements
complex arithmetic. Complex subclasses from Number, because
it must be able to rewrite itself into Number objects.
Square rewrites itself into Complex, while all the other
operators rewrite themselves into Complex or Number.
Complex objects must be rewritten into Numbers before their
components may be accessed. Thus, we can be sure that all
invocations of Complex are eventually rewritten into Number,
a primitive class.
Note that the definitions for addition and subtraction are
redundant. The input declaration section says that a
Complex is an aggregation of two Numbers, in order. The
operator inheritance mechanism interacts with this
declaration to automatically derive the addition and
subtraction operators defined above.
The 5D system generates an arithmetic tree of primitive
objects working from the template patterns in user-defined
objects in an iterative algorithm. The program tree
Complex C1, C2, C3
label: Real(plus(C3, plus(C1, C2)))
Imag(label ^)
generates the two Numbers
Real(plus(Real(C3), plus(Real(C1), Real(C2))))
Imag(plus(Imag(C3), plus(Imag(C1), Imag(C2))))
which may be fed into I/O operations at the top of the
lattice.
4.8.7 _D_r_a_w_a_b_l_e__O_b_j_e_c_t_s
The above classes only implement numerical operations. The
Drawable class possesses visual properties such as color and
position. The position property is a Point. The color
property is a Point in RGB color space. A property may be
an object, or a arithmetic tree of objects. Property
objects can have no properties themselves.
The Triangle is a built-in object subclassed off of
Drawable. It consists of three Points. Since a Point is
composed of three Numbers, a Triangle may have nine
arithmetic trees underneath it, and constantly change shape
as those subtrees change value. A 3D modelling program
might use this to rubber-band changes in a 3D shape in
response to numerical input devices, or use feedback to
implement jiggly objects.
- 20 -
4.9 _P_r_o_g_r_a_m__I_D__S_c_o_p_i_n_g
The visibility of IDs is scoped two ways in program trees:
by tree structure, and by program source.
4.9.1 _T_r_e_e_-_s_t_r_u_c_t_u_r_e_d__s_c_o_p_i_n_g
Outside of a class definition, the ID of a node is visible
to a node's siblings and their children. Thus,
Inside a class definition, things are different: the inputs
and outputs of the object have special IDs, and IDs declared
in a method's template are visible within that method's
rewrite rule. This allows the template to describe a
complex tree, and the rewrite rule to tear it apart and
restructure it.
4.9.2 _P_r_o_g_r_a_m_-_s_o_u_r_c_e__s_c_o_p_i_n_g
Different sub-trees in the same scene can be downloaded over
the network from different applications. If there were just
one tree-scoped ID name space, there would be severe
problems with different programs innocently (or maliciously)
affecting each other's scene members. Thus, ID names are
also "sealed off" for each program source. A sub-program
from a different network source may only refer to nodes
downloaded from that network source, and the primitive
objects. A redefinition of a primitive object is also
visible, since it is referred to by the name of a primitive
object.
A parent node may use relative ID addressing to walk a tree
down to a child node received over the network. This is
only a feasible coding technique if the child tree has been
"syntax-checked" against a template.
4.10 _C_l_a_s_s__d_e_f_i_n_i_t_i_o_n__s_c_o_p_i_n_g
A class definition occurs under a program tree node. Thus,
it is only available under that parent node. Two
definitions of the same class may not be siblings. However,
a class may be redefined in a child tree. The class
redefinition may only have one superclass, the parent
definition. The redefinition may add, delete, or change
operators or properties. The parent's version of overridden
operators may be invoked within more elaborate
implementations. For example, the "hinge" operator which
connects polygons may be redefined to draw a line along the
edge of the hinge, by redefining the class Drawable and
overriding the "hinge" definition.
In a class definition the operator and property definition
nodes may use the Type= to select the special IDs Parent or
- 21 -
Self. In an operator definition, Self indicates that the
type of an operation is that of the class or of any derived
subclass. Examination of the Number and Angle classes shows
an example of this. The Number operators are defined as
type Self. Since Angle derives from Number, all the
operators from Number simply appear as "Angle + Angle is
Angle" etc. without being respecified in the Angle class
definition.
Scoping describes which other objects an object definition
may refer to. There are four forms of references: rewrite,
aggregation, data, and property. Here are the scoping rules
for each type of reference:
4.10.1 _R_e_w_r_i_t_e__S_c_o_p_i_n_g
Rewrite reference scoping controls what a method definition
can rewrite itself into. The example class Complex rewrites
itself into Complex or Number. Here are the replacement
scoping rules:
Self An object may replace an operation on
itself with another expression of its
own type. For instance, Complex
replaces the square(Complex) operation
with multiply(input1, input1).
Super An object may also replace an operation
with an expression of its super-class's
type, and on up the line to Object. For
instance, Complex replaces the Real and
Imag operators with expressions of type
Number. Complex cannot replace any
invocations with operators of type
Object, because Object has no operators.
Obviously, if a class can rewrite itself into any other
class, a circular definition would cause an operation to be
rewritten endlessly. While all such errors can be
discovered automatically, it is very difficult to remove
them from a design. This rewrite policy avoids this problem
entirely by making it impossible for circular references to
exist.
Note: inside a rewrite rule, all known classes may be used
for interior operations. [ I think this deserves its own
heading, but I don't know quite where. ]
4.10.2 _A_g_g_r_e_g_a_t_e__S_c_o_p_i_n_g
Aggregation reference scoping controls what objects may be
input to an operator rule. Above, Complex accepts Complex
and Number as input. Here are the aggregation scoping
- 22 -
rules:
Self An object may have objects of its own
type as inputs. For instance, Complex
accepts square(Complex).
Super An object may have objects of its
various superclasses as inputs. For
instance, the Complex object creation
rule accepts two Numbers as inputs and
type-casts them into a Complex.
Sibling An object may accept _s_i_b_l_i_n_g objects
(other objects with the same
superclasses) as inputs.
In rewrite rules, the special type Parent refers to the
parent class from whom an operator was inherited. This is
used in operator re-defines in classes which override a
parent class of the same name. It allows invoking the
parent's operator definition in the middle of the child's
operator definition.
These rules are somewhat arbitrary. They force the class
designer to think through very carefully the objectives of
the project, and to understand more fully the "Buddha
Nature" of the class structure.
4.10.3 _D_a_t_a__S_c_o_p_i_n_g
Each object defined in a Data sections of a class must have
an ID which starts with a $ sign. References to ID's
starting with $ sign are scoped to within the class
definition. [ This is non-orthogonal with the rest of the
scoping rules. Do it some other way. Maybe myclass::ID? ]
4.10.4 _P_r_o_p_e_r_t_y__S_c_o_p_i_n_g
4.10.4.1 _P_r_o_p_e_r_t_y__N_a_m_e_s
Properties are not subject to a unique name space.
Different classes may use the same name to define properties
unique to themselves. If two different classes both define
a property and are combined to derive a subclass, the two
different properties may be disambiguated by the
_s_u_p_e_r=ppppaaaarrrreeeennnntttt keyword. The data section of a class
definition is private; the properties of aggregated data
types are not available.
4.10.4.2 _P_r_o_p_e_r_t_y__T_y_p_e_s
Properties may be of any type which has no properties. The
issue here is that if a property can have a property, then
it can go into a loop attempting to evaluate the original
property. Properties are second class citizens in 5D. They
- 23 -
are intended as simple adornments directing the evaluation
of real tree nodes. If a property has important information
to contribute to the execution of a program, it should be a
real tree node instead.
To enforce language simplicity, types of properties may be
restricted to something. The siblings of a superclass might
work out, as might a special sub-tree of simple types in the
core class hierarchy.
4.10.4.3 _P_r_o_p_e_r_t_y__I_n_h_e_r_i_t_a_n_c_e
Properties are inherited dynamically, not statically. When
trees are executed via pointers, they inherit their
properties from the pointing node, not via their original
parent.
4.10.5 _A_d_d_r_e_s_s_i_n_g__i_s_s_u_e_s
Suppose that sender A creates a tree that accepts data from
sender B. B's data may only appear under A's world according
to A's wishes. A may not remove B's data directly, _s_i_n_c_e _i_t
_c_a_n_n_o_t _a_d_d_r_e_s_s _i_t. However, A must instead remove A's trees
which hold B's data.
This example brings up another point: dynamic references to
a non-existent ID are a run-time error. The Exception class
handles this type of problem. The extant expection handler
receives the code for a non-existent ID reference, and acts
appropriately. Static references are not an error. That
is, the disappearance of a named node does not automatically
cause exceptions for all the nodes pointing to it. A new
version of the node, or another node somewhere else with the
same ID, may be interposed without mishap. A remote
application which performs this sort of skullduggery should
put execution interlocks in place beforehand.
Program references may use IDs with relative indexing: an
ID may be followed by zero or more /_n_u_m_b_e_r strings, each
number an index at successive levels of the tree. Relative
indexing only goes down the tree, and ignores network
scoping rule. Thus, a program may accept a network packet
and peer at its contents. It also allows a complex
polyhedron to avoid giving an ID to each component when
specifying interconnections, thus saving much space in
transmission.
4.10.6 _A_d_d_r_e_s_s_i_n_g__U_s_e_s
The ID space is segmented for various "control" trees. For
example, one small range of IDs is used inside tree
definitions to refer to the inputs of that tree. Another
range of IDs is used to indicate shared-memory bitmaps for
concurrent access by 5D and a 2D imaging system (X,
- 24 -
PostScript, video) on the same machine.
5. _L_a_n_g_u_a_g_e__I_m_p_l_e_m_e_n_t_a_t_i_o_n__A_r_c_h_i_t_e_c_t_u_r_e
5D may be fully interpreted, not that you'd want to. A full
interpreter can not build a sortable polygon database, and
thus cannot implement hidden surfaces. It would also be
very slow. A partial interpreter can build a polygon
database. This technique analyzes the world description tree
and decomposes it into jobs to be done at different times.
The section below describes this technique in more detail.
The language is also intended to be "hot compiled", that is,
the deck software can analyze a tree and generate binary
code to implement that tree. If it creates nothing more
than a string of subroutine calls to the op-code handlers of
the interpreter, it still dissolves away the interpretive
loop. A compiler can optimize different built-in types;
i.e. it can do constant folding for matric operations for
which portions of a matrix are known. 5D is also targeted
for ease of compilation on parallel processors. The
language attempts to minimize interactions between nodes. [
This will require much analysis by experts in parallel
software. ]
5.1 _L_a_n_g_u_a_g_e__d_e_s_i_g_n__i_s_s_u_e_s
5D is intended as a basis for real-time simulation. As
such, the power and elegance of abstract research languages
is unfortunately not available. Languages such as
Smalltalk, Prolog, Actor, etc. are beautifully simple and
dense, but require unpredictable amounts of CPU time to
implement their constructs. 5D's language constructs must
be implementable in a predictable manner. Every operation
must require O(1) amount of time to execute.
5D is designed to be efficient in the amount of space used
to store 5D programs, and thus efficent in network
transmission time. It is also designed to be efficient to
execute compiled or digested 5D code. After the simulation
clock starts, 5D must keep the beat. Slow digestion of 5D
code, and the prodigious use of RAM to store pre-computed
data, is unfortunate but necessary.
Also, real-time predictability outvotes run-time efficiency.
For example, whether it would be more efficient to use
garbage collection rather than freeing memory on the fly is
immaterial. The screen cannot stop updating at random
intervals to do a GC sweep.
- 25 -
5.2 _L_o_w_-_e_n_d__s_y_s_t_e_m__i_m_p_l_e_m_e_n_t_a_t_i_o_n__s_t_r_a_t_e_g_y
5D is targeted initially at low-MIPS desktop computers such
as the 386 PC and the Mac. A single-CPU frame buffer-based
computer will implement 5D as a classic simulation system.
A multi-tasking co-routine package supports a variety of
subsystems which implement different aspects of the deck:
sound I/O, positional input devices, force-feedback events,
network I/O, and last but not least, screen update. These
subsystems sleep on different events: I/O interrupts,
timeouts, and software-defined events. Each subsystem
maintains a task list. It sleeps on one or more events and
does a task list each time that event occurs. The network
I/O system accepts trees from outside and adds them to the
world tree. Each subsystem must be able to insert new tasks
and delete old tasks on the fly, in response to dynamic
editing of the tree.
The polygon database has 2 levels:
+o a list of high-level objects which can change their
relative distances and orientations,
+o where each object is solid and does not change shape.
The high-level list must be sorted for each mono or stereo
screen refresh. Each static object is stored in a Binary
Space Partition database [ ref ]. (The BSP algorithm does a
large majority of the polygon sorting work independent of
the viewpoint. Animating a static object consists of pre-
sorting it, then walking the last mile over and over, thus
considerably speeding up screen refreshes.) Each screen
refresh must sort the list of high-level objects in 3-space
(probably by bounding boxes), and do a fast BSP viewpoint of
the polygons in each static object. Depending on the screen
size and scene complexity, object-first or scan-line-first
rendering may be appropriate, and the renderer may want to
switch between them dynamically. For stereo rendering it
may make sense to walk through the database rendering both
screens, or to walk through it twice doing one screen at a
time.
Practical experience [ref: Graphics Interface '90, "The
DataPaper", Green & Shaw] shows that applying BSP to a
completely static scene winds up fracturing the scene into
an immense number of polygons, and in fact the 2-level
scheme ("clumpy BSP?") is preferable in this case also.
In any event, the Graphics Gems software distribution and
the VOGLE portable 3D library will provide the source code
for the first pass at a renderer.
- 26 -
5.2.1 _S_t_a_t_e__V_e_c_t_o_r_s
For debugging worlds, and doing animation, it is necessary
to maintain a state vector of the execution of a world.
Network control can stop and start execution, and "play" the
sequence of frames forward and back.
Because tree evaluations are triggered by multiple clocks
and asynchronous events, there is not one state vector, but
instead a "time line" of events and state vectors for the
appropriate tree. [This is going to be hairy!] These state
vectors are accessible to 5D and are used by the World
Manager to "swap out" world descriptions as the user wanders
between them.
5.3 _N_e_t_w_o_r_k__C_o_m_m_u_n_i_c_a_t_i_o_n_s
A 5D program is read in from a file or a network connection.
Decks communicate across networks by sending 5D trees.
Communication circuits are point-to-point in 5D terms but
may be multi-drop underneath. That is, it may receive UDP
broadcasts but only receives from host X under host X's
connection object. Thus, it must have a separate UDP
broadcast connection object for each incoming host.
When received, a tree may be examined and then executed or
rejected, or it may just sit in a holding place for
reference. The World Manager needs to accept downloaded
trees and splice them under a "top of world" partition.
MazeWar merely needs to examine the latest status message
from all other players.
Trees are examined with the 5D _t_e_m_p_l_a_t_e facility: a
received tree may be checked against a template as a form of
syntax check. If it passes the check, the receiving parent
tree may choose to execute it. [ We may want to add the
boolean Authenticated as a property of a received program.
The receiver can then take various actions if a program did
not have the right magic encrypted checksum. ]
Groupware and Cyberspace applications are not well served by
the common network protocols; 5D may eventually include a
mutated form of ISIS, IRC, Kerberos, MUD, or all four. MUD
would form a nice permanent object repository for 5D, while
something like the Habitat system could be built running 5D
over IRC.
5.3.1 _R_P_C__c_o_m_p_i_l_e_r
For doing basic application-deck pair applications, a
library-building compiler like the one SUN distributes with
NeWS would be very useful. [ I read about it in a SUN tech
papers book: I haven't actually used it. ]
- 27 -
5.3.2 _C_C_K_:__C_y_b_e_r_s_p_a_c_e__C_o_n_s_t_r_u_c_t_i_o_n__K_i_t
The effort involved in debugging a client-server network
protocol is surprisingly large; we're going to need a
protocol design & debug system for doing many-to-many 5D
network applications. It should have a method for tracing
network messages to & from a deck, and stopping & starting
operations via network control. ESTELLE [ ref ??? ] is a
protocol design language used for describing portions of the
OSI protocol stack. There are ESTELLE simulators; this would
make a handy addition to the CCK.
5.3.3 _N_e_t_w_o_r_k__O_b_j_e_c_t
The Network object is an abstract superclass for defining
network protocols for use with 5D. The object has a channel
number as a property. Each network connection has a unique
number. This number is used to multiplex communications
between multiple endpoints in the deck to the outside world.
Whether a network port initiates or receives connections is
a property, as is whether the protocol uses reliable and
ordered delivery.
A networked deck starts up with various tasks such as
calibrating I/O devices and adjusting speaker volumes. It
then starts a program tree whose sole purpose is to open a
receptive network connection in each protocol the deck
supports.
5.3.3.1 _T_C_P_/_U_D_P__n_e_t_w_o_r_k_i_n_g
5D uses RFC [ XXX ] to dynamically register the well-known
TCP & UDP port numbers for these main ports. It can also
assign channel numbers to subsidiary network sockets
dynamically. Any program when creates subsidiary sockets
with auto-assigned channels must upload the trees with the
sockets, to find out their protocol port numbers. A program
may also pre-assign port numbers and hope it won't clash
with anything else. This technique must be used in UDP
broadcast applications like MazeWar, because every deck must
use the same port number.
[ A reliable broadcast protocol could be done by relying on
a main application to ensure that all other decks got your
message, and simply making sure that the main application
got it. This follows the dictum of philosophy of off-
loading non-interactive work to the application. ]
5.4 _W_o_r_l_d__M_a_n_a_g_e_r
The World Manager is just the main 5D application. It makes
sub-worlds available to the user. A static WM is loaded
from a file and stores one or more sub-worlds in memory.
- 28 -
5.4.1 _H_a_l_l_w_a_y
The prototype implementation of the WM is the _H_a_l_l_w_a_y
(inspired by various "Rooms" systems). The user moves down
a hallway of doors. Each door has some label or icon. The
user selects the doorknob, label, or icon and pops into that
world.
Under file-based 5D, the world is just there in RAM, waiting
to run. Under network-based 5D, there is usually a remote
application program on a computer for each world. This
application handles permanent data storage and complex
calculation work not easily done with 5D. In general, the
application communicates asynchronously with the world,
implementing all synchronous user interface feedback in
downloaded 5D.
5.4.2 _N_e_t_w_o_r_k_e_d__W_M
A dynamic networked WM downloads world trees across the
network from a remote master program for this deck.
In the Hallway, selecting the doorknob causes your WM to
send a message to the master, which then fires up the
program for your selected world. The program contacts your
WM and downloads the world tree. The WM accepts the world,
stuffs it under a "top-of-world" (class Void) node, and
turns it on.
When you exit the world, the WM can destroy it or keep it
around. The WM can manage memory usage by uploading the
current state of a world to its counterpart and deleting it.
When you want to re-enter it, the WM downloads it again.
Before this, the WM may "swap out" your previous world.
You may only traverse worlds by passing through the Hallway.
There's no technical reason for this, it's merely because
the Hallway's worlds are not conceptually connected. A
world may implement its own suite of connected environments
and traverse them in any order. A house may have doors,
windows, ventilator shafts and secret passages for you to
traverse.
6. _T_e_x_t
5D does not contain a textual abstraction, a font database,
or support for typewriter keyboards. There are two possible
uses for text in 5D: 2-dimensional text and 3-dimensional
text, with very different aims. Statistically speaking, 2D
text is rendered, read, and erased. 3D text, on the other
hand, tends to be permanent. It is generally used as a
label in a larger 3D model. The low volatility of 3D text
- 29 -
does not merit devoting scarce permanent deck resources to
fonts. It is better handled as a library tree used by
applications. 2D text is not supported for 2 reasons:
+o 2D textual graphics has been addressed already by many
systems: Tex/Dvi, Postscript, troff, the X Window
System, etc. Many of these systems have freeware
versions which could be easily altered to support 2D
graphics under 5D. In particular, it would be quite
easy to create an X window server which moves flat
bitmaps around in 3-space. This could be connected to
5D via 5D networking or by cohabiting in the same
operating system. A multi-processor Mach system with
one CPU running the X stuff and one running 5D would
make a great hypermedia system. (Throw another CPU on
the fire!)
+o The "official" 5D core language specification only
supports application features which are widely
recognized as the one right way to do things, or as one
of two or three commonly accepted methods. Text is a
mess. There are upwards of 20 European Roman-Arabic
keyboards alone. Japan has 3 alphabets. Some
lettering goes right-to-left, some up-to-down.
Calligraphic lettering apparently requires an iterative
method to match up lines between symbols. We don't
want to keep adding new text "standards" every six
months, duplicating the work that's been done for other
text-processing systems.
If the specified functionality of a low-end deck ends up
including a CD-ROM of library materials, the core library
will include the Hershey fonts, and some basic Adobe-style
outline fonts, and simple 3D CSG-based text construction
operators.
[It might work out for keyboards to just be objects with
many, many switches. Another object might interpret these
into an ASCII dataset, for network communication.]
7. _T_e_r_r_a_F_o_r_m_e_r
The TTTTeeeerrrrrrrraaaaFFFFoooorrrrmmmmeeeerrrr is a visual programming CASE system for 5D
trees. It is a 5D program which presents a tree as a 3D
scene, using translucent structure blocks to display several
levels of structure simultaneously. Someday.
But for now, it's a standard 2D window system application.
You are able to browse and edit the program tree, and browse
the class inheritance lattice. The tree and lattice windows
- 30 -
use a space-efficient method to display these data
structures.
7.1 _T_r_e_e__w_i_n_d_o_w
The tree window show many levels of a tree, starting at a
particular node in the tree. The tree (+ ID=sum (*(1,2),3))
is shown as:
------------------------------------------------------
| + sum |
| -------------------------------------------------- |
| | * | |
| | ---------------------------------------------- | |
| | | 1 | | |
| | ---------------------------------------------- | |
| | ---------------------------------------------- | |
| | | 2 | | |
| | ---------------------------------------------- | |
| -------------------------------------------------- |
| -------------------------------------------------- |
| | 3 | |
| -------------------------------------------------- |
------------------------------------------------------
This format can not show all the nodes in a 5D program.
Grasp the edge of a box with the mouse and move it outwards
to "zoom in" on that box, or move it inwards to move up the
tree.
There are two or more tree windows. You may "cut" or "copy"
a tree in one window, and copy it to the other one.
If a node has off-screen parents or children, its box is
drawn differently, alerting you that there is more.
7.2 _N_o_d_e__W_i_n_d_o_w
When you select a tree node, you may view that node in full
in the node window. This window shows all the keywords
interpreted appropriately, and all extant properties.
7.3 _T_r_e_e__t_y_p_e_s
The 5D text format includes the ability to include files.
These include commands should be preprocessed before a tree
is downloaded, unless the deck possesses access to a
universal file name space.
- 31 -
TF allows you to specify that the contents of a sub-tree
adhere to a given subset of 5D node types, via the template
mechanism. TF saves this non-program information as
comments in the source, via text comments starting with
"_F_o_r_m_a_t:", to remember in a later session how you wish to
view your programs. It can translate other formats into 5D
format, allow you to edit the resulting tree, and save it
out in any format. Also, if configured correctly, TF can
invoke an appropriate editor. You would probably wish to
use a real 3D modeller to edit a 3D model instead of editing
the 5D tree; ordinary differential equations are much more
tractable in the form
xxxx'''' ==== xxxx ++++ yyyy
yyyy'''' ==== ----xxxx ++++ yyyy
than as the equivalent 5D format.
7.4 _C_l_a_s_s__L_a_t_t_i_c_e__B_r_o_w_s_e_r
You may browse the class inheritance lattice via the class
browser window. Of course, you may not edit the class
inheritance lattice directly. The lattice is displayed
using Venn diagram boxes.
A series of class definitions, where abstract superclasses
and type-bearing classes are named appropriately:
(class ID=abstract1)
(class ID=abstract2)
(class ID=atype
super=abstract1
super=abstract2
)
would display in the class lattice browser:
- 32 -
------------------------------------------------------
| ------------------------------ |
| | abstract1 | |
| | | |
| | | |
| | ------------------------------- |
| | | | | |
| | | atype | | |
| | | | | |
| -------------------|---------- | |
| | | |
| | | |
| | abstract2 | |
| ------------------------------- |
------------------------------------------------------
The browser window cannot display the entire class lattice.
It does not attempt to show all possible intersections, nor
even all the intersections of a particular superclass. If a
class has any unseen intersections, the border of its box is
different (monochrome) or its name is in a different color.
Classes with no on-screen children are not drawn with their
own box, but if they have children they are underlined or
drawn in color. This is simply to avoid screen clutter, or
"non-data ink". [ Envisioning Information, Edward Tufte. ]
To look at all intersections of a superclass, select that
class. To select a subset of the intersections of one or
more classes, mouse-down in one intersection box and drag
the mouse through all intersections in which you are
interested. Since this is a Venn diagram, neighboring boxes
form a simplified Boolean expression.
7.5 _O_p_e_r_a_t_o_r_s
The operator menu gives a list of defined operators. It can
give a list of all operators, operators unique to one class,
or multiply defined operators.
7.6 _A_d_d_r_e_s_s__n_o_d_e_s
Address nodes are marked, but automatically are drawn in the
type of the node they point to.