[PREV]  [PREV]  [PREV]

PROGRAMMER'S MANUAL:
NONSTANDARD PRIMITIVES


Welcome to Galapagos Scheme. This chapter is intended as a quick reference to Galapagos's extensions over traditional Scheme. Knowledge of Scheme is assumed. Galapagos Scheme is compliant with both R4RS and IEEE standard P1178. If you've read the chapter titled "Scheme extensions", you can and should skip the short introduction in each section. This complete chapter appears as on-line help in Galapagos, just a F1 click away.


ENVIRONMENTS

An environment is a list of frames, with the global environment in its tail. A frame is a list of bindings, which map variables to their values. (define...) adds a binding to the frame at the top of the current environment. (set!...) family of commands modify an existing binding, in the frame where it was defined. When a variable is referenced, the current environment is searched from head to tail, and the first binding found dictates the value of the variable.

The first interpreter, which pops up as Galapagos is started, runs at the global environment (the way traditional Scheme works). Additional interpreters (threads) run at distinct environments, which contain a single initially empty frame, and a pointer to the global environment.

(clone-environment env [depth])

Clone-environment will make an exact copy of the environment env, by copying its frames one by one. If depth is specified then the new environment will be the collection of frames which is up to depth frames from the current frame. And the last frame will point to the depth + 1 frames from the current one in env.

This means that if we are now in environment e1 and done (define x 7). Then if we'll write

(define e2 (clone-environment (current-environment))),

the result of

(eval@ e2 x)

will return 7.

But if we are not in a lower frame than the one x was defined in and write

(define e2 (clone-environment (current-environment) 1))

and write the value of x is undefined.

(Unless it was defined in the global environment)

Note: Only the bindings are copied. The bound values are not. Example:

(define x (cons 1 2))

(define e (clone-environment (current-environment)))

(eval@ e (set-cdr! X 6))

will change the 2 into 6 at both environments. However,

(set! x 7)

will only affect one copy.

(pop-environment env)

Returns the current environment without the first frame. This means the first frame on the list of frames is "popped" out.

If env was made from f3->f2->f1->Global, the result will be f2->f1->Global.

(fx means frame number x)

Example:

(define e2 (pop-environment (current-environment)))

(extend-environment env)

Extends env with a new empty frame (where nothing is defined yet).

This means the if env was f2->f1->Global the result will be f3->f2->f1->Global.

(fx means frame number x)

Example:

(define e2 (extend-environment (current-environment)))

(current-environment)

Returns the current environment.

(environment? env)

A predicate that is true if env is an environment.

Example:

(environment? (current-environment))

Will return true.

(parent-environment)

Returns the parent environment. This is the environment where (new-thread) was called to create this thread. The First thread returns the global environment.

Example:

(eval@ (parent-environment) y)

Will return the value of y in the parent environment.

(base-environment)

The environment where the interpreter runs.

(set-base-environment env)

Sets the base environment (where the interpreter runs) to be env

Example:

(set-base-environment (parent-environment))

Will make this thread run in the same environment as its father)

(eval@ env forms...)

Evaluates forms in given environment.

Example:

(define x 7)

(define e2 (clone-environment (current-environment)))

(eval@ e2 x)

The result will be 7

(eval@p forms...)

Evaluates forms in parent environment.

Example:

Say we want to make our turtle walk 30 degrees more than the father's turtle. Then we can write:

(set-heading! T (+ 30 (eval@p (turtle-heading t))))

MESSAGE QUEUES

Message queues are MT-safe mechanisms used to pass messages, possibly between threads. Messages accepted must be cons, its car being the message type and the cdr is the message body. Both can be any kind of Scheme object.

(make-queue)

Creates a new message queue.

Example:

(define q (make-queue))

(message-queue? q)

A predicate that is true if q is a queue.

Example:

(message-queue? q)

Will return true for q from the previous example.

(peek-message q [type])

Return true if there is a message (of given type, or of any type if unspecified) in the queue q.

Example:

(peek-message q)

Will return falsif the queue q is empty.

Note: types are compared using (equals?) .

(post-message q typ_msg)

Posts the message typ_msg to the queue q.

typ_msg must be a cons (type . message).

Example:

(post-message q (cons 'type-welcome 'hello))

(get-message [time-out] q [type])

Get message from queue q , if time-out is defined waits only time-out seconds, and

optionally gets only messages from type type.

Example:

(define msg (get-message 7 q 'type-welcome))

The result will be (if the previous posting was done) ('type-welcome . 'hello)

Note: types are compared using (equals?) .

WINDOW COMMANDS

A window is the graphical board on which the turtles and the user draw. It is a bitmap of size 800x600.

(new-window [name])

Makes a new window, name is a symbol or a string which will also be the window's title. The window's color will be white and it's size 800x600.

Example:

(define w (new-window 'my-window))

Will create a new window with the title my-window.

(rename-window! win [name])

Renames the window win. name is a symbol or a string which will also be the window's title.

Example:

(rename-window! w 'foo)

Will make the title of w to be foo.

(set-background-color! R G B)

Set the background color of the window. All the turtles in the window are notified on the new color (used in pen-erase)

The colors are defined in terms of Red Green Blue (where 0,0,0 is black and 255,255,255 is white).

Example:

(set-background-color! w 255 255 0)

Will turn the background color of w to yellow

(clear-window w)

Clears the screen from all the previous drawings, leaving only the turtles images on it.

Example:

(clear-window w)

(load-bitmap w "filename" [x y])

Loads the bitmap "filename" and makes it the background of w. x y are the coordinates of the upper left corner of the picture. If x y are not given then the picture is centered.

Example:

(load-bitmap w "c:\\windows\\forest.bmp")

This operation can also be done using the Board menu.

(save-bitmap w "filename")

Saves the window into a bitmap file called "filename".

Example:

(save-bitmap w "my_draw.bmp")

This operation can also be done using the Board menu.

(window-alive? win)

True if win is alive, meaning it can get commands.

(window-name w)

Returns the name of w.

Example:

(window-name w)

Will return "foo" on our window.

TURTLE COMMANDS

A turtle is an object which is connected to a certain window. It has inner state variables:

- width: the width of the pen.

- heading: the direction the turtle will go on command forward!. The heading is in degrees where 0 is upwards and adding to the heading means clock wise rotation.

- visibility: if the body of the turtle is visible on the board or not.

- solid: if the turtle is a "solid" turtle (its interior is also drawn) or "hollow" one (only its circumference is drawn).

- position: the location of the turtle on the board, where 0,0 is the upper left corner.

- color: the color of the turtle and it's pen, given in RGB format.

- pen condition: the turtle's pen can be in three states:

- pen width: the width of the pen, the bigger the width the thicker the pen will be.

Turtles can also "see" the board or other turtles (only from the same board) and can handle user interrupts. A turtle is always connected to a certain view, which is the view it is drawing on. Turtles can move between views.

(make-turtle win [name])

Creates and return a new turtle, in window win, optional name (where name can be anything).

The inner state of the new turtle will be:

Example:

(define t (make-turtle 'turty))

(turtle-alive? t)

A predicate that is true if t is alive, meaning t can get commands.

Example:

(turtle-alive? t)

Will return true on our t.

(clone-turtle t [name])

Creates an identical turtle to t (same inner state).

Example:

(define t2 (clone-turtle t))

(rename-turtle t [name])

Renames the turtle, name is a string or a symbol

Example:

(rename-turtle t 'pongy)

(turtle-name t)

Returns the name of t.

Example:

(turtle-name t)

Will return "pongy" on our t.

(forward! t d)

Makes t go forward (in the heading of t) d steps. t will draw while going according to the state of it's pen.

Example:

(forward! t 100)

Will cause t to go forward 100 steps. (In our case since t's heading hasn't changed it will go upwards)

(turtle-width! t n)

Set the width of t's pen to be n. The bigger n is the wider the pen will be.

(backwards! t d)

Same as forward, just in the opposite direction.

Example:

(backwards! t 100)

is the same as

(forward! t -100)

(right! t d)

Will set a new heading to t. The new heading is the old heading plus d, meaning t will rotate clock-wise.

Example:

(right! t 90)

Will make t turn 90 degrees to the

(left! t d)

Same as right, other direction

(set-heading! t val)

Sets the heading of t to be val. 0 is upwards and 90 is to the right.

Example:

(set-heading t 180)

Will cause t to point to the bottom of the screen.

(move-to! t x y)

Makes t move to point x,y without painting. 0,0 is the top-left corner of the window.

Example:

(move-to! T 100 100)

Will cause t to move to point 100,100.

(draw-to! t x y)

Moves t to x,y possibly drawing or erasing according to the state of t's pen.

Example:

(draw-to! t 0 0)

(move-turtle-to-window t win)

Move t to the window win

Example:

(move-turtle-to-window t w)

(pen-up! t)

The pen of t is up, so he won't paint when moving.

Example:

(pen-up! t)

(pen-down! t)

Causes t's pen to be down, meaning he will draw as he is moving.

(pen-erase! t)

Causes t's pen to be in the same color as the background color of the window it is attached to.

(show-turtle! t)

Makes t visible. Meaning he will be seen on the board.

Example:

(show-turtle! t)

(hide-turtle! t)

Makes t invisible. Meaning he will not be seen on the board. (but all the drawing he does will be seen)

Example:

(hide-turtle! t)

(make-turtle-solid! t)

Makes t a solid turtle.

(make-turtle-hollow! t)

Make t a "hollow" turtle.

(kill-turtle! t)

Kills t. Meaning it will be erased from the board and will not accept further commands.

Note: This is the only way to get rid of a turtle.

Example:

(kill-turtle! t)

Will cause when writing t in the command line to the response

#<dead turtle>

(set-color! t R G B) or (set-color! t (list R G B)

Sets t's color (and it's pen), in RGB format.

Example:

(set-color! t 255 0 255)

Will cause t to be pinkish.

Same as:

(define pinkish '(255 0 255))

(set-color! t pinkish)

(turtle-inner-state t)

Returns a list of 6 parameters: color, heading, hidden-flag, pen width, solid flag, location (cons x y))

Example:

(define new-t (make-turtle w))

(turtle-inner-state new-t)

Will return the list

((0 0 0) 0.0 #f 2 #t (400.0 . 300.0))

Below are functions that returns only one of the parameters returned by turtle-inner-state:

(turtle-color t)

(turtle-heading t)

(turtle-visible t)

(turtle-width t)

(turtle-solid? t)

(turtle-position t)

TURTLE VISION

A turtle can interact with the board. It can "see" colors or other turtles.

(look t distance angle '(R G B))

Will return true if there is a point in color (R G B) in distance distance from t and in the area bordered by the angle 2*angle.

Example:

(look t 50 20 '(0 0 0))

Will cause t to search for the color black (RGB 0,0,0) in the area shown here in blue:


(look t distance angle [t1])

Same as if looking for color, just this time it will be true is t1 is in the visible area.

If no target turtle is defined then the function will return true if any turtle from this window is in the visible area.

Example:

(define new-t (clone-turtle t))

(forward! new-t 30)

(look t 50 20 new-t)

And

(look t 50 20)

Will both return true.

INTERRUPTS (NOTIFICATIONS)

A turtle can hold a list of interrupts (or notifications). When an interrupt is invoked it send a given message to the thread that sent the command. Every interrupt is defined by a "look" arguments. An interruptcan be of three kinds:

A "yes" interrupt - The interrupt will happen (message sent) on every "first" time the look returns yes.

Meaning if a turtle is told to invoke an interrupt every time it sees blue on a certain region. Then the first time it sees blue it will invoke the interrupt. From now on if the blue is in view it will not invoke the interrupt. Then if it loses sight of the blue object, the next time it sees blue again it will invoke the interrupt, and so on.

A "no" interrupt - Same as the "yes" interrupt, just this time the interrupt is invoked when the sought object is not seen.

A "both" interrupt - First time the sought object is viewed the "yes" message is sent, then the first time the turtle loses sight of the object the "no" message is sent and so on.

A message can be any SCHEME object.

When the interpreter is installing interrupt to a turtle it need to install a handler, which is a function that takes only one argument and this argument is the messages that comes from the interrupt.

If no handler is installed, the messages will be sent but will have no affect on the thread of execution.

There can be only one handler per thread and a handler can not be a primitive procedure.

(turtle-notify t msg1 msg2 distance angle TARGET)

Instructs a turtle to send msg1 and msg2 upon seeing and not seeing, respectively, the target. The messages can be any Scheme objects, which are sent to the thread as if by (tell-thread). The other parameters - see (look)

Example:

(turtle-notify t 'yes 'no 50 10 new-t)

This is a "both" kind interrupt.

(turtle-no-notify t distance angle TARGET)

Tells the turtle to stop notifying in the given case. Very like deleting the interrupt from the turtle.

(notify-when[-not] t1 msg dist ang TARGET)

Instructs a turtle to send msg upon [stopping] seeing the target. This is a "yes" or "no" interrupt.

Example:

(notify-when t 'gotcha 50 10 new-t)

Will cause t to send the message "gotcha" every "first" time it sees new-t.

(stop-notifying t)

t will temporarily stop notifying on interrupts. Like "clear interrupts".

(continue-notifying t)

t will resume notifying on interrupts.

(no-notifications t)

Deletes all t's interrupts.

(notify-on-click turtle msg)

Instructs turtle to send msg when right-clicked with the mouse (distance of 5 pixels from the turtle location). There can be only one interrupt of this kind per turtle.

Example:

(notify-on-click t 'ouch)

Will case t to send the message "ouch" when the user right-clicks next to it.

(notify-on-click window msg)

Instructs window to send msg when right-clicked with the mouse not close to any turtle.

(clear-notify-click t)

Clears the user right click interrupt

(install-handler func)

Installs a message handler. When a message arrives, func is called with it as a sole argument.

There can be only one handler per thread. func can not be a primitive procedure.

Example:

(define (print x) (write x))

(notify-on-click t 'click-on-t)

(install-handler print)

Will cause that the message "click-on-t" will be printed each time the user right clicked on t.

THREADS

Galapagos supports multiple threads. Every thread is a complete Scheme interpreter, with its own base environment. Every thread has a Thread Object, which uniquely identifies it.

A console is a text window where the user can type commands (when the interpreter is idle) and see output. 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.

(this-thread)

Returns the thread-object of the current thread.

Example:

(this-thread)

Will return something like

#<thread 0x6d1e2c>

(is-first-thread?)

True if the current thread is the first SCM thread.

(thread? t)

True if t is a thread

Example:

(thread? (this-thread))

Will return true

(active-threads)

Returns the number of active threads

(new-thread form+)

Creates a new thread that will calculate the form[s]

Example:

(new-thread (define t (make-turtle w)) (forward! t 200))

Will make a new thread that will create a new turtle and will move it forward 200 steps and then terminates.

(new-thread (bind-to-console))

Will make a new thread that's ready to accept commands form a newly-created window. The same can be achieved by selecting "Fork" from "Scheme" menu.


(break& form+)

Causes the current thread to stop and calculate the form[s]. The current computation is lost.

(bind-to-console)

The thread will get its commands from a console.

Example:

(new-thread (bind-to-console))

Will create a new thread that gets it.

(unbind-console)

Close bound console.

(rename-console name)

New name for the current console

(install-handler func)

Installs a message handler. When a message arrives, func is called with it as a sole argument.

There can be only one handler per thread. func can not be a primitive procedure.

Example:

(define (print x) (write x))

(notify-on-click t 'click-on-t)

(install-handler print)

Will cause that the message "click-on-t" will be printed each time the user right clicked on t.

Note: (new -thread (install-handler f)) is a bad idea, because the fresh thread will terminate immediately.

(tell-thread th x)

Sends message X to thread th. Returns true on success.

If th has no handler installed it will cause nothing.

(quit-thread)

Kills the current thread, does not work on the main thread.

(quit-program)

Quits the program.


These are primitives taken from SCM, which were modifies to be multithread-safe:

An arbiter is a data object the canbe used as a guard for critical sections. It can be either "locked" or "unlocked". It is ideal when a busy/wait mechanism is required, since it is MT-safe.

(sleep n)

Causes the current thread to block for (approximately) n seconds. (sleep 0) is a way to instruct a thread to give up its remaining processor time.

(make-arbiter name)

Makes an arbiter called name.

Example:

(define x-arb (make-arbiter 'x-guard))

(try-arbiter arb)

Checks if the arbiter arb is up. If the arbiter is up returns false, otherwise it sets the arbiter to be "up" and returns true.

Example:

(try-arbiter x-arb)

Will return true and set x-arb to be "up". But trying it for the second time return false since x-arb is "up".

(release-arbiter arb)

Set the arb to be "down". If the arbiter was "up" returns true otherwise returns false.

Example:

(release-arbiter x-arb)

Will return true , but using this function again will return false since x-arb is already down.


 [TOP]  [PREV]  [PREV]  [PREV]