494 lines
18 KiB
HTML
494 lines
18 KiB
HTML
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||
|
<HTML>
|
||
|
<HEAD>
|
||
|
<TITLE>Galapagos - Scheme Extensions</TITLE>
|
||
|
<META NAME="Author" CONTENT="">
|
||
|
<META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (Win95; I) [Netscape]">
|
||
|
</HEAD>
|
||
|
<BODY background=stone.jpg>
|
||
|
|
||
|
<CENTER>
|
||
|
<A href="background.html"><IMG border=0 src=prev.gif ALT=" [PREV] "></A>
|
||
|
<A href="gui.html"><IMG border=0 src=next.gif ALT=" [PREV] "></A>
|
||
|
<A href="index.html#toc"><IMG border=0 src=toc.gif ALT=" [PREV] "></A>
|
||
|
</CENTER>
|
||
|
<HR width=80% align=right color=blue>
|
||
|
<P>
|
||
|
|
||
|
<H1 ALIGN=CENTER><A NAME="top"></A>SCHEME EXTENSIONS<BR>
|
||
|
</H1>
|
||
|
|
||
|
<UL>
|
||
|
<LI><A HREF="extensions.html#THE NEW ENVIRONMENT">The New Environment Model</A></LI>
|
||
|
<LI><A HREF="extensions.html#THREADS">Threads</A></LI>
|
||
|
<LI><A HREF="extensions.html#CONSOLES">Consoles</A></LI>
|
||
|
<LI><A HREF="extensions.html#DRAWING">Drawing Boards</A></LI>
|
||
|
<LI><A HREF="extensions.html#TURTLES">Turtles</A></LI>
|
||
|
<LI><A HREF="extensions.html#INTERRUPTS (NOTIFICATIONS) AND MESSAGE">Interrupts
|
||
|
(Notifications) and Message handlers</A></LI>
|
||
|
</UL>
|
||
|
|
||
|
<P>
|
||
|
<HR WIDTH="100%"></P>
|
||
|
|
||
|
<P>We have extended Scheme in two main
|
||
|
directions: Turtle graphics and multithreading:<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>The <I>turtle</I> object lives on a board on which it can move and draw.
|
||
|
A turtle can also communicate with the board and "see" colors
|
||
|
or other turtles. Galapagos Scheme provides a set of primitives to create
|
||
|
and manage such turtles and the boards they live on. <BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A set of additional primitives enable the programmer to create multiple
|
||
|
interpreters that run concurrently. The environment model was extended
|
||
|
to support shared or thread-specific environments, and primitives to handle
|
||
|
multiple environments were also added. <BR>
|
||
|
<BR>
|
||
|
</P>
|
||
|
|
||
|
<H2><A NAME="THE NEW ENVIRONMENT"></A>THE NEW ENVIRONMENT MODEL<BR>
|
||
|
</H2>
|
||
|
|
||
|
<P>A frame is a table which maps (or <I>binds</I>) names to values. An
|
||
|
environment is a chained list of frames in which the interpreter works.
|
||
|
</P>
|
||
|
|
||
|
<P>For example the command: </P>
|
||
|
|
||
|
<P><I>(define x 7)</I> </P>
|
||
|
|
||
|
<P>creates a binding between <I>x</I> and the value <I>7</I>. </P>
|
||
|
|
||
|
<P>A typical environment looks like this:</P>
|
||
|
|
||
|
<P><CENTER>
|
||
|
<IMG border=0 SRC="Envs.gif" HEIGHT=125 WIDTH=459><BR>
|
||
|
</CENTER></P>
|
||
|
<BR>
|
||
|
<BR>
|
||
|
<BR>
|
||
|
Each rectangle denotes a frame and inside it are the bindings it holds.
|
||
|
The rightmost rectangle is the global environment.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>When a variable is evaluated, the interpreter first tries to find it
|
||
|
in the current frame. If a suitable binding can't be found, the interpreter
|
||
|
moves to the next frame in the environment and searched for a binding there.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>In our example if we write <I>x</I> in the command line we'll get <I>12</I>
|
||
|
as the answer because all such computations take place at the global environment.
|
||
|
<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A function application is always evaluated with respect to the environment
|
||
|
the in which it was defined. (A function "holds" its environment,
|
||
|
hence the name "closure") This means that if we write </P>
|
||
|
|
||
|
<P><I>(define (f) x) </I></P>
|
||
|
|
||
|
<P>and then </P>
|
||
|
|
||
|
<P><I>(f)</I> </P>
|
||
|
|
||
|
<P>the result will be </P>
|
||
|
|
||
|
<P><I>12</I>.<BR>
|
||
|
<BR>
|
||
|
<BR>
|
||
|
<BR>
|
||
|
<BR>
|
||
|
<P><CENTER>
|
||
|
<IMG border=0 SRC="Envs2.gif" HEIGHT=140 WIDTH=551><BR>
|
||
|
</CENTER></P>
|
||
|
<BR>
|
||
|
In traditional SCHEME we have only one interpreter running at a time, so
|
||
|
at a given point of calculation there is only one environment. In Galapagos
|
||
|
multiple interpreters can run at the same time, and each of them has its
|
||
|
own environment.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>Under Galapagos's environment model, every interpreter works on its
|
||
|
branch of an "environments tree", but can also evaluate an expression
|
||
|
in any other environment in the tree. If two interpreters have a shared
|
||
|
node on the tree, then from that point up (towards the global environment)
|
||
|
all the bindings are the same for the two interpreters. The global environment
|
||
|
is shared by all interpreters. If an interpreter changes the value of some
|
||
|
variable, the binding is changed in all other interpreters that have access
|
||
|
to the frame where the variable was declared. Obviously, caution should
|
||
|
be taken when writing to a shared variable.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>As an example, if a user created two new threads, called A and B, and
|
||
|
then evaluated: </P>
|
||
|
|
||
|
<P><TT><FONT FACE="Courier New">First thread></FONT></TT> <I>(define
|
||
|
x 7)</I> </P>
|
||
|
|
||
|
<P><I>(define (f) ...)</I> </P>
|
||
|
|
||
|
<P><TT><FONT FACE="Courier New">Thread A></FONT></TT> <I>(define (g)
|
||
|
x)</I> </P>
|
||
|
|
||
|
<P><TT><FONT FACE="Courier New">Thread B></FONT></TT> <I>(define x 4)</I>
|
||
|
</P>
|
||
|
|
||
|
<P>this is how the environment model would look like:<BR>
|
||
|
</P>
|
||
|
|
||
|
<CENTER><P><IMG border=0 SRC="img00001.gif" HEIGHT=407 WIDTH=654><BR>
|
||
|
</P></CENTER>
|
||
|
|
||
|
<P>Now consider what happens when the user evaluates this: </P>
|
||
|
|
||
|
<P><TT><FONT FACE="Courier New">Thread A></FONT></TT> <I>(set! f g)</I>
|
||
|
</P>
|
||
|
|
||
|
<CENTER><P><IMG border=0 SRC="img00002.gif" HEIGHT=431 WIDTH=692><BR>
|
||
|
<BR>
|
||
|
</P></CENTER>
|
||
|
|
||
|
<P>Now, evaluating <I>(f)</I> in thread B will call the function defined
|
||
|
in thread A. It will return 12 which is the value of x in f's environment.
|
||
|
If thread A defines a new x (using <B>define</B>), it will affect the result
|
||
|
of subsequent calls to f.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>Sharing environments and frames are Galapagos's way of allowing shared
|
||
|
data. By default, however, most calculations are done at thread-specific
|
||
|
frames. (More on this subject in the next section). Primitives are supplied
|
||
|
to explicitly reference and manage environments: <B>clone-environment</B>
|
||
|
can create a copy of an environment (so changing a binding in one copy
|
||
|
does not alter the other); <B>extend-environment</B> and <B>pop-environment</B>
|
||
|
can add and remove frames to and from environments. More environment functions
|
||
|
are found in the next section of this document.<BR>
|
||
|
</P>
|
||
|
|
||
|
<H2><A NAME="THREADS"></A>THREADS<BR>
|
||
|
</H2>
|
||
|
|
||
|
<P>A thread is a SCHEME interpreter. The <I>base environment</I> of a thread
|
||
|
is the thread's topmost environment. All forms entered at the thread's
|
||
|
console or as arguments to <B>new-thread</B> are evaluated in the base
|
||
|
environment. In traditional SCHEME there is only one thread of execution.
|
||
|
It is a single thread and its base environment is the global environment.
|
||
|
In Galapagos many interpreters can run concurrently, and each have its
|
||
|
own environment (changing dynamically as computation progresses) and a
|
||
|
base environment (which can be explicitly changed).<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>One thread is created by Galapagos upon startup. It is called the <I>main
|
||
|
thread</I>, and it lasts for the whole Galapagos session. Its base environment
|
||
|
is the global one - much like a traditional Scheme interpreter. Additional
|
||
|
threads can be created using <B>new-thread</B>. These have their base environment
|
||
|
set to a new environment, containing a single fresh frame pointing to the
|
||
|
global environment. Any calculation done at the new thread's console takes
|
||
|
place in this thread-local environment. However, if closure functions are
|
||
|
used, then their evaluation may take place at the global environment or
|
||
|
at some other thread's space, depending on where that function was defined.
|
||
|
<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>When a thread finishes the execution of its commands it terminates.
|
||
|
There are two exceptions to this rule: </P>
|
||
|
|
||
|
<OL>
|
||
|
<LI>The main thread can be only terminated by using <B>quit-program</B>.
|
||
|
</LI>
|
||
|
|
||
|
<LI>A thread that is bound to the console will not terminate at the end
|
||
|
of execution but will wait for the next command input. </LI>
|
||
|
</OL>
|
||
|
|
||
|
<P>Threads can communicate using the predicate <B>tell-thread</B> or by
|
||
|
using the asynchronous message-queues system described later. In addition,
|
||
|
SCM's <B><I>arbiters</I></B> were improved to be multithread safe. An arbiter
|
||
|
object can serve as a guard on a critical section (where only one thread
|
||
|
can work at a given time) of the program. The relevant primitves are <B>make-arbiter</B>,<B>
|
||
|
try-arbiter</B>, and <B>release-arbiter</B>. <BR>
|
||
|
</P>
|
||
|
|
||
|
<P>Note: Galapagos supports Scheme's notation of <B><I>continuations</I></B>.
|
||
|
However, two restrictions apply: </P>
|
||
|
|
||
|
<OL>
|
||
|
<LI>Only "cheap" continuations are supported. That is, a continuation
|
||
|
can only be called when it is still active. This allows for continuations
|
||
|
to be used to implement exception handling, etc. </LI>
|
||
|
|
||
|
<LI>Continuations can not cross thread boundaries. Also continuations,
|
||
|
like any other Scheme object, can be handled by any thread, they can only
|
||
|
be called from within the thread that created them. Trying to call a continuation
|
||
|
from a different thread will cause an error. </LI>
|
||
|
</OL>
|
||
|
|
||
|
<H2><A NAME="CONSOLES"></A>CONSOLES<BR>
|
||
|
</H2>
|
||
|
|
||
|
<P>A <I>console</I> is a text window where the user can type commands (when
|
||
|
the interpreter is idle) and see output. A console has a name which can
|
||
|
be changed dynamically, which appears on its title bar. A thread may or
|
||
|
may not be bound to a console. Information printed by a non-bound thread
|
||
|
is lost; a non-bound thread waiting for input is stuck (unless provisions
|
||
|
were made to allow a new console to be created by means of inter-thread
|
||
|
communications.) If a non-bound thread has nothing to do, instead of waiting
|
||
|
for input like a bound thread, it will terminate.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>The main thread is always bound to a console. To bind a thread to a
|
||
|
console use the command <B>bind-to-console</B> from within the thread.<BR>
|
||
|
</P>
|
||
|
|
||
|
<H2><A NAME="DRAWING"></A>DRAWING BOARDS<BR>
|
||
|
</H2>
|
||
|
|
||
|
<P>A board (window) is the graphical board on which the turtles and the
|
||
|
user draw. It is a bitmap on which the user can draw interactively, by
|
||
|
using the supplied GUI, or by creating turtles and instructing them to
|
||
|
do the drawings.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>The controls of the graphical user interface are located on the toolbar.
|
||
|
The "shapes" of drawing are either a rectangle, a line or free
|
||
|
hand drawing. The user pen can have three widths which are found under
|
||
|
the <B>User Pen</B> menu. The numbers next to the sizes are the widths
|
||
|
in pixels.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>The colors of the user pen can be changes either from the <B>User Pen
|
||
|
</B>menu or from the toolbar's color buttons. When choosing from a toolbar
|
||
|
button, the user can know exactly what color (in RGB format) is used. <BR>
|
||
|
</P>
|
||
|
|
||
|
<P>Each window has a name which is written on its title bar which can be
|
||
|
changed using the <B>rename-window!</B> command. The board can be cleaned
|
||
|
from all drawings using the <B>clear-window </B>command. <BR>
|
||
|
</P>
|
||
|
|
||
|
<P>Since the board is a bitmap it can be saved to a BMP file using the
|
||
|
<B>save-bitmap</B> command. A new background from a bitmap file can be
|
||
|
loaded using the <B>load-bitmap</B> command.<BR>
|
||
|
</P>
|
||
|
|
||
|
<H2><A NAME="TURTLES"></A>TURTLES<BR>
|
||
|
</H2>
|
||
|
|
||
|
<P>A turtle is an object which is connected to a certain board. Each turtle
|
||
|
has a pen with which it can draw on that board. The user can change the
|
||
|
state of the turtle's pen including giving it the color of the board's
|
||
|
background color (using the <B>pen-erase! </B>command). The pen will draw
|
||
|
when it is "down" and will not draw when it is "up".
|
||
|
Turtles can move between boards using the <B>move-turtle-to-window</B>
|
||
|
command.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>Each turtle holds its location as the a pair of coordinates where 0,0
|
||
|
is the upper left corner of the board and 800,600 is the bottom-right corner
|
||
|
of the board. The turtle's location can be changed by giving the turtle
|
||
|
commands such as <B>forward!, backwards!, move-to!</B> or by using the
|
||
|
move button from the toolbar.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A turtle also has a heading which is the direction it will move on the
|
||
|
<B>forward!</B> command. The heading is in degrees, 0 meaning upwards and
|
||
|
increasing clockwise, thus 90 means rightwards and so on. A turtle's heading
|
||
|
can be changed by commands such as <B>right!, left!, </B>and<B> set-heading!</B>
|
||
|
or interactively, by using the move button on the toolbar and pressing
|
||
|
the control key.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A turtle can be visible on the board or be hidden. When it is visible
|
||
|
the user can decide if it wants a "solid" or "hollow"
|
||
|
turtle using the <B>make-hollow! </B>and <B>make-solid!</B> commands.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A turtle is always connected to a certain board, which is the board
|
||
|
it is drawing on. To create a new turtle on a board use the <B>make-turtle</B>
|
||
|
or the <B>clone-turtle</B> commands. A new turtle (created with the <B>make-turtle</B>
|
||
|
command) will be black, solid, heading north and with it's pen down, in
|
||
|
the center of the board. A cloned turtle will have exactly the same inner
|
||
|
state as its parent.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A turtle can also look at the board and see other turtles or colors.
|
||
|
By using the command <B>look</B> the user can tell the turtle the area
|
||
|
in which to look and what to look in this area. </P>
|
||
|
|
||
|
<P>Example: </P>
|
||
|
|
||
|
<P>The command </P>
|
||
|
|
||
|
<P><I>(look t 50 20 '(0 0 0))</I> </P>
|
||
|
|
||
|
<P>will cause the turtle <I>t</I> to look for black pixels in the area
|
||
|
in radius 50 from the turtle and 20 degrees to each side of the heading
|
||
|
line, shown here in blue: </P>
|
||
|
|
||
|
<CENTER><P><IMG border=0 SRC="img00003.gif" HEIGHT=75 WIDTH=48><BR>
|
||
|
</P></CENTER>
|
||
|
|
||
|
<H2><A NAME="INTERRUPTS (NOTIFICATIONS) AND MESSAGE"></A>INTERRUPTS (NOTIFICATIONS)
|
||
|
AND MESSAGE HANDLERS<BR>
|
||
|
</H2>
|
||
|
|
||
|
<P>A turtle can have interrupts. Each interrupt is defined in terms of
|
||
|
turtle's vision. Whenever a turtle starts or stops seeing a given target,
|
||
|
a predefined message is sent to the thread which asked the interrupt. The
|
||
|
user can determine if the interrupt will notify on every change (like a
|
||
|
"can see"- "can't see" toggle) or only when one change
|
||
|
happens (only "can see" or "can't see" toggle). A message
|
||
|
can be any valid SCHEME object.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>Example: </P>
|
||
|
|
||
|
<P>The command </P>
|
||
|
|
||
|
<P><I>(turtle-notify t "I-see" "I-don't-see" 50 20
|
||
|
color-black)</I> </P>
|
||
|
|
||
|
<P>tells the turtle <I>t</I> that every time it sees the color black it
|
||
|
should send the message <I>"I-see"</I> and when it doesn't see
|
||
|
the color black any more it should send the message <I>"I-don't-see"</I>.
|
||
|
</P>
|
||
|
|
||
|
<P>Below is an example of what messages (or no message) <I>t </I>will send
|
||
|
while it is moving forward, encountering two black lines on its way:<BR>
|
||
|
<BR>
|
||
|
<BR>
|
||
|
<IMG border=0 SRC="vision.gif" HEIGHT=183 WIDTH=669></P>
|
||
|
|
||
|
<P><BR>
|
||
|
<BR>
|
||
|
If the interrupt was of kind "can see" (<B>notify-when</B> command)
|
||
|
only the <I>"I-see"</I> messages were sent, and if it was a the
|
||
|
"can't see" interrupt (<B>notify-when-not</B> command) only the
|
||
|
<I>"I-can't-see" </I>style messages were sent.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A special "user interrupt" is invoked when the user right-clicks
|
||
|
the turtle or a window. The <B>notify-on-click</B> command is used to enable
|
||
|
this.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A thread can tell the turtle to delete a certain interrupt using the
|
||
|
<B>turtle-no-notify</B> command. It can also tell the turtle to disable
|
||
|
all interrupts using the <B>stop-notifying</B> command. <BR>
|
||
|
</P>
|
||
|
|
||
|
<P>In order to process the messages sent from a turtle's interrupt (or
|
||
|
from another thread, as presented later) the thread must install a <I>message
|
||
|
handler</I> which is a one argument function. If no handler is installed
|
||
|
the turtle's messages are lost. There can be only one handler per thread.
|
||
|
If the handler is installed then every time an interrupt is invoked, the
|
||
|
handler function in called with the message sent by the interrupt as its
|
||
|
argument. <BR>
|
||
|
<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>Example: </P>
|
||
|
|
||
|
<P>We declare the function: </P>
|
||
|
|
||
|
<P><I>(define (my-print x) (write x) (newline))</I> </P>
|
||
|
|
||
|
<P>and then install <I>my-print</I> as the current handler with: </P>
|
||
|
|
||
|
<P><I>(install-handler my-print)</I> </P>
|
||
|
|
||
|
<P>from now on every message a turtle's interrupt sends will be printed
|
||
|
on screen. If <I>my-print</I> was installed in the previous example then
|
||
|
we would have seen: <BR>
|
||
|
</P>
|
||
|
|
||
|
<P><I>"I-see"</I> </P>
|
||
|
|
||
|
<P><I>"I-don't-see"</I> </P>
|
||
|
|
||
|
<P><I>"I-see"</I><BR>
|
||
|
</P>
|
||
|
|
||
|
<P>on the screen.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A good example to view the interrupts in action is to make a turtle
|
||
|
turn each time it sees a color and then let it wander aimlessly. Then use
|
||
|
the user pen to draw lines the turtle's way and watch it change direction.
|
||
|
See the PINGPONG.SCM file for a demo program. <BR>
|
||
|
</P>
|
||
|
|
||
|
<P>The message-handler concept can be used as a mean of synchronous inter-thread
|
||
|
communications. The tell-thread functions sends a message to a thread,
|
||
|
which will be treated as an interrupt-generated message: It will cause
|
||
|
the thread's message handler function to be called with tell-thread's argument
|
||
|
as its own. This allows one thread to initiate a computation in a different
|
||
|
thread's environment and CPU space synchronously and without sharing environments.
|
||
|
<BR>
|
||
|
</P>
|
||
|
|
||
|
<H2><A NAME="MESSAGE"></A>MESSAGE QUEUES<BR>
|
||
|
</H2>
|
||
|
|
||
|
<P>In order to let threads communicate between themselves asynchronously
|
||
|
a system of message queues was developed. A queue is an object which stores
|
||
|
and relieves messages, stored in FIFO (First In First Out) style, meaning
|
||
|
messages are read in the order of arrival to the queue. Supported messages
|
||
|
are pairs of type and body, both of which can be any valid SCHEME object.
|
||
|
Looking for messages of a certain type is also supported, allowing implementation
|
||
|
of more flexible communication schemes than plain FIFO.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>A thread can check if there are any messages in a given queue, if it
|
||
|
does <B>get-message</B> without checking first if there are messages in
|
||
|
the queue it will wait a given time-out or forever if no time-out is given.
|
||
|
If by the end of the time-out no message were in the queue the result will
|
||
|
be false.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P>Example: </P>
|
||
|
|
||
|
<P>In this example a queue <I>q</I> is created then a message is posted
|
||
|
into the queue and read from it.<BR>
|
||
|
</P>
|
||
|
|
||
|
<P><I>(define q (make-queue))</I> </P>
|
||
|
|
||
|
<P><I>(post-message q (cons 'type-circus 'bozo-the-clown))</I> </P>
|
||
|
|
||
|
<P><I>(define msg (get-message q))</I><BR>
|
||
|
</P>
|
||
|
|
||
|
<P>now the command </P>
|
||
|
|
||
|
<P><I>(car msg) </I></P>
|
||
|
|
||
|
<P>will give </P>
|
||
|
|
||
|
<P><I>type-circus</I> </P>
|
||
|
|
||
|
<P>and the command </P>
|
||
|
|
||
|
<P><I>(cdr msg) </I></P>
|
||
|
|
||
|
<P>will yield </P>
|
||
|
|
||
|
<P><I>bozo-the-clown</I>. </P>
|
||
|
|
||
|
|
||
|
<P>
|
||
|
<HR width=80% align=left color=blue>
|
||
|
<CENTER>
|
||
|
<A href="#top"><IMG border=0 src=back.gif ALT=" [TOP] "></A>
|
||
|
<A href="background.html"><IMG border=0 src=prev.gif ALT=" [PREV] "></A>
|
||
|
<A href="gui.html"><IMG border=0 src=next.gif ALT=" [PREV] "></A>
|
||
|
<A href="index.html#toc"><IMG border=0 src=toc.gif ALT=" [PREV] "></A>
|
||
|
</CENTER>
|
||
|
</BODY>
|
||
|
</HTML>
|
||
|
|
||
|
|
||
|
|
||
|
|