You are going to implement an embedded domain specific language to describe turtle graphics. The goal of this assignment is to give you a feel for the design issues involved with an embedded language and experience with first-class IO values and graphical user interfaces.
The idea is that there is a turtle that carries a pencil that can draw on a canvas. The turtle is knows just two primitive commands:
right d forward n
That is, it can go forward
for n
units, or it can
turn right
over d
degrees. For example, we can draw a
square using the following commands:
forward 50 right 90 forward 50 right 90 forward 50 right 90 forward 50
You can find more examples and information at the following webpage: http://el.www.media.mit.edu/groups/logo-foundation/logo/turtle.html
It is encouraged to do this assignment with the wxHaskell 0.2 library at http://wxhaskell.sourceforge.net. Unfortunately, this means that you need ghc 6.01 and administrator rights. This implies that only people with access to a computer that they own, can do this assignment with wxHaskell. I can probably provide a few people (up to 4) with a dedicated computer in the ST-lab in the CGN building.
If you really need to work on a standard lab machine, you can also do the assignment using the SOE graphics library for Hugs: http://cvs.haskell.org/Hugs/pages/downloading.htm. See their documentation about how to open windows and do drawing.
Implement the turtle language as an embedded language in Haskell. The language is embedded in Haskell as a single module that exports abstract data types and associated operations. You should consider carefully what operations you want to expose to the user so that programming with turtles becomes convenient. For example, you could start with an interface like this:
data Drawing
forward :: Double -> Drawing right :: Double -> Drawing ...
Of course, this is just an example and you can define another kind of
interface, as long as it has the same basic functionality. In both cases, you
need to be able to defend why you have chosen for a particular approach. Other
turtle commands you should implement are penup
and pendown
,
to either hide or show the trail of the turtle, color
that changes
the color of the pen, and stop
to end a
program.
Other commands are somewhat easier to add: backward
, left
,
and repeat
. Why are these easier to add?
You should also provide an execute
function that takes a turtle
program and runs it. Think about how general your function should be: should it
open its own window and take of everything itself, or should it be parameterised
by a window or drawing functions? Explain why you have chosen a particular
approach. Think also about a coordinate system: do you use pixels as units? what
happens on a resize of the window? Note that your turtle should start in
the center, going upwards.
You implementation doesn't have to show a turtle: it just has to show how the final result looks like. Check your implementation by implementing the spiral example from the http://el.www.media.mit.edu/groups/logo-foundation/logo/turtle.html webpage.
to spiral :size :angle if :size > 100 [stop] forward :size right :angle spiral :size + 2 :angle end
Of course, you would implement your examples in a separate module than the Turtle
module.
Instead of drawing the result of a turtle drawing, show how the drawing is
drawn. You don't have to show a turtle itself, just showing the effect of the
turtle moving around is good enough. You could use a timer
together
with a mutable variable and repaint
to animate the drawing. Look at
the wxHaskell bouncing balls example for an illustration of their usage.
If you use SOE graphics, you can probably use sleep
(or Win32.sleep
)
to achieve the same effect.
Once this works, you can also try to implement the forever
operator.
Implement parallel composition to your interface. One possible interface could be:
(<|>) :: Drawing -> Drawing -> Drawing
When you execute the drawing p <|> q
there will be two
turtles, one drawing p, the other drawing q in parallel.
Think about what happens after a parallel composition finishes? Is the operator commutative? and associative? Why would these laws be important to a programmer?
1. You could add a save construct to the language.
save :: Program -> ProgramThe meaning of the program save p is to recall the current position of the turtle and to continue with the program as if nothing happened. But as soon as we are done, we return to the saved state and execute the program p from that point. When you have several save statements in your program, all of them should be saved and later executed, but you may decide yourself in what order.
2. You could add a pause construct to your language. In this case, you will add a button with the text "Continue" to the graphical interface. This button is normally inactive, but when the turtle program executes the pause command, it halts, and the "Continue" button becomes active. When the user clicks on the "Continue" button, the program continues and the continue button becomes inactive again.
3. Similar to 2., but instead of an explicit pause, you have a combinator called stepping.
stepping :: Program -> ProgramThe meaning of the program stepping p is: execute p as normal, but the user is required to click the "Continue" button at every step during the execution of p.
4. Add the commands showturtle and hideturtle to your language, which toggle between having a turtle picture shown when drawing the pictures or not. A variant of this allows different turtle bitmaps and maybe even a background image. One can then describe simple animations. Also see the section "Up and Away" from the above mentioned turtle web page.
5. Add a way to your language of finding out information about for example, where the turtle currently is, or if the user clicks or drags the mouse. It should of course be possible to then use this information in your turtle programs.
6. Invent your own extension to the turtle language. By extension I mean something that cannot be implemented in terms of the existing language constructs.
Create a cool picture that uses some or all the extensions that you have made. To keep up a long standing tradition, the team with the best demo, subjectively chosen by me :-), wins a bag of M&M's.
Answer and motivate the following questions:
You should send your submission before Sunday, 28 September, 23:59h to daan@cs.uu.nl with the subject afp submission. In the body, you should put the names of your team and the student numbers. You should attach the following (zipped/tarred) files:
Turtle.hs
that contains your embedding of the turtle
language.Main.hs
that contains your examples. If I run main
,
I should see the coolest example you have made.report
that contains the answers to the
questions and comments and motivations about your implementation.Success!