summaryrefslogtreecommitdiff
path: root/progs
diff options
context:
space:
mode:
authorYale AI Dept <ai@nebula.cs.yale.edu>1993-07-14 13:08:00 -0500
committerDuncan McGreggor <duncan.mcgreggor@rackspace.com>1993-07-14 13:08:00 -0500
commit4e987026148fe65c323afbc93cd560c07bf06b3f (patch)
tree26ae54177389edcbe453d25a00c38c2774e8b7d4 /progs
Import to github.
Diffstat (limited to 'progs')
-rw-r--r--progs/README9
-rw-r--r--progs/demo/Calendar.hs138
-rw-r--r--progs/demo/README15
-rw-r--r--progs/demo/X11/animation/README22
-rw-r--r--progs/demo/X11/animation/animation.hs16
-rw-r--r--progs/demo/X11/animation/animation.hu6
-rw-r--r--progs/demo/X11/animation/birds.hs28
-rw-r--r--progs/demo/X11/animation/birds.hu3
-rw-r--r--progs/demo/X11/animation/doc.tex578
-rw-r--r--progs/demo/X11/animation/palm.hs47
-rw-r--r--progs/demo/X11/animation/palm.hu3
-rw-r--r--progs/demo/X11/animation/planets.hs30
-rw-r--r--progs/demo/X11/animation/planets.hu3
-rw-r--r--progs/demo/X11/animation/r_behaviour.hs158
-rw-r--r--progs/demo/X11/animation/r_behaviour.hu3
-rw-r--r--progs/demo/X11/animation/r_constants.hs129
-rw-r--r--progs/demo/X11/animation/r_constants.hu3
-rw-r--r--progs/demo/X11/animation/r_curve.hs60
-rw-r--r--progs/demo/X11/animation/r_curve.hu3
-rw-r--r--progs/demo/X11/animation/r_defaults.hs76
-rw-r--r--progs/demo/X11/animation/r_defaults.hu3
-rw-r--r--progs/demo/X11/animation/r_display.hs114
-rw-r--r--progs/demo/X11/animation/r_display.hu6
-rw-r--r--progs/demo/X11/animation/r_inbetween.hs82
-rw-r--r--progs/demo/X11/animation/r_inbetween.hu3
-rw-r--r--progs/demo/X11/animation/r_movie.hs114
-rw-r--r--progs/demo/X11/animation/r_movie.hu3
-rw-r--r--progs/demo/X11/animation/r_picture.hs188
-rw-r--r--progs/demo/X11/animation/r_picture.hu4
-rw-r--r--progs/demo/X11/animation/r_ptypes.hs67
-rw-r--r--progs/demo/X11/animation/r_ptypes.hu2
-rw-r--r--progs/demo/X11/animation/r_shapes.hs38
-rw-r--r--progs/demo/X11/animation/r_shapes.hu3
-rw-r--r--progs/demo/X11/animation/r_utility.hs150
-rw-r--r--progs/demo/X11/animation/r_utility.hu3
-rw-r--r--progs/demo/X11/animation/seafigs.hs158
-rw-r--r--progs/demo/X11/animation/seafigs.hu3
-rw-r--r--progs/demo/X11/animation/seaside.hs25
-rw-r--r--progs/demo/X11/animation/seaside.hu5
-rw-r--r--progs/demo/X11/draw/README1
-rw-r--r--progs/demo/X11/draw/draw.hs41
-rw-r--r--progs/demo/X11/draw/draw.hu2
-rw-r--r--progs/demo/X11/gobang/README66
-rw-r--r--progs/demo/X11/gobang/gobang.hs364
-rw-r--r--progs/demo/X11/gobang/gobang.hu7
-rw-r--r--progs/demo/X11/gobang/misc.hi7
-rw-r--r--progs/demo/X11/gobang/misc.hu2
-rw-r--r--progs/demo/X11/gobang/redraw.hs160
-rw-r--r--progs/demo/X11/gobang/redraw.hu4
-rw-r--r--progs/demo/X11/gobang/utilities.hs305
-rw-r--r--progs/demo/X11/gobang/utilities.hu6
-rw-r--r--progs/demo/X11/gobang/weights.hs323
-rw-r--r--progs/demo/X11/gobang/weights.hu4
-rw-r--r--progs/demo/X11/graphics/README31
-rw-r--r--progs/demo/X11/graphics/henderson.hs465
-rw-r--r--progs/demo/X11/graphics/henderson.hu3
-rw-r--r--progs/demo/X11/graphics/manual454
-rw-r--r--progs/demo/X11/graphics/p.pic1
-rw-r--r--progs/demo/X11/graphics/q.pic2
-rw-r--r--progs/demo/X11/graphics/r.pic2
-rw-r--r--progs/demo/X11/graphics/s.pic1
-rw-r--r--progs/demo/X11/graphics/sqrlmt.hs177
-rw-r--r--progs/demo/X11/graphics/sqrlmt.hu3
-rw-r--r--progs/demo/X11/graphics/stop.pic1
-rw-r--r--progs/demo/X11/graphics/strange.pic2
-rw-r--r--progs/demo/X11/graphics/text.pic1
-rw-r--r--progs/demo/X11/logo/EXAMPLES.LOGO70
-rw-r--r--progs/demo/X11/logo/README104
-rw-r--r--progs/demo/X11/logo/logo.hs1345
-rw-r--r--progs/demo/X11/logo/logo.hu3
-rw-r--r--progs/demo/X11/mdraw/README1
-rw-r--r--progs/demo/X11/mdraw/mdraw.hs83
-rw-r--r--progs/demo/X11/mdraw/mdraw.hu3
-rw-r--r--progs/demo/X11/mdraw/t.hs16
-rw-r--r--progs/demo/X11/mdraw/t.hu3
-rw-r--r--progs/demo/add.hs21
-rw-r--r--progs/demo/eliza.hs267
-rwxr-xr-xprogs/demo/fact.hs14
-rw-r--r--progs/demo/improved-add.hs21
-rwxr-xr-xprogs/demo/merge.hs26
-rw-r--r--progs/demo/pascal.hs24
-rw-r--r--progs/demo/pfac.hs21
-rwxr-xr-xprogs/demo/primes.hs16
-rw-r--r--progs/demo/prolog/Engine.hs61
-rw-r--r--progs/demo/prolog/Engine.hu3
-rw-r--r--progs/demo/prolog/Interact.hs76
-rw-r--r--progs/demo/prolog/Interact.hu2
-rw-r--r--progs/demo/prolog/Main.hs87
-rw-r--r--progs/demo/prolog/Main.hu6
-rw-r--r--progs/demo/prolog/Parse.hs116
-rw-r--r--progs/demo/prolog/Parse.hu1
-rw-r--r--progs/demo/prolog/PrologData.hs121
-rw-r--r--progs/demo/prolog/PrologData.hu2
-rw-r--r--progs/demo/prolog/README3
-rw-r--r--progs/demo/prolog/Subst.hs65
-rw-r--r--progs/demo/prolog/Subst.hu2
-rw-r--r--progs/demo/prolog/Version.hs1
-rw-r--r--progs/demo/prolog/Version.hu1
-rw-r--r--progs/demo/prolog/stdlib38
-rwxr-xr-xprogs/demo/queens.hs40
-rw-r--r--progs/demo/quicksort.hs13
-rw-r--r--progs/lib/README1
-rw-r--r--progs/lib/X11/README11
-rw-r--r--progs/lib/X11/clx-patch.lisp39
-rw-r--r--progs/lib/X11/xlib.hs877
-rw-r--r--progs/lib/X11/xlib.hu5
-rw-r--r--progs/lib/X11/xlibclx.scm1262
-rw-r--r--progs/lib/X11/xlibprims.hi1465
-rw-r--r--progs/lib/X11/xlibprims.hu5
-rw-r--r--progs/lib/cl/README2
-rw-r--r--progs/lib/cl/logop-prims.hi78
-rw-r--r--progs/lib/cl/logop-prims.scm81
-rw-r--r--progs/lib/cl/logop.hs63
-rw-r--r--progs/lib/cl/logop.hu5
-rw-r--r--progs/lib/cl/maybe.hs12
-rw-r--r--progs/lib/cl/maybe.hu3
-rw-r--r--progs/lib/cl/random-prims.hi20
-rw-r--r--progs/lib/cl/random.hs21
-rw-r--r--progs/lib/cl/random.hu4
-rw-r--r--progs/lib/hbc/Either.hs2
-rw-r--r--progs/lib/hbc/Either.hu3
-rw-r--r--progs/lib/hbc/Hash.hs79
-rw-r--r--progs/lib/hbc/Hash.hu3
-rw-r--r--progs/lib/hbc/ListUtil.hs48
-rw-r--r--progs/lib/hbc/ListUtil.hu4
-rw-r--r--progs/lib/hbc/Maybe.hs6
-rw-r--r--progs/lib/hbc/Maybe.hu3
-rw-r--r--progs/lib/hbc/Miranda.hs90
-rw-r--r--progs/lib/hbc/Miranda.hu4
-rw-r--r--progs/lib/hbc/Option.hs3
-rw-r--r--progs/lib/hbc/Option.hu3
-rw-r--r--progs/lib/hbc/Pretty.hs50
-rw-r--r--progs/lib/hbc/Printf.hs150
-rw-r--r--progs/lib/hbc/Printf.hu3
-rw-r--r--progs/lib/hbc/QSort.hs47
-rw-r--r--progs/lib/hbc/QSort.hu3
-rw-r--r--progs/lib/hbc/README97
-rw-r--r--progs/lib/hbc/Random.hs52
-rw-r--r--progs/lib/hbc/Random.hu3
-rw-r--r--progs/lib/hbc/Time.hs51
-rw-r--r--progs/lib/hbc/Time.hu3
-rw-r--r--progs/prelude/Prelude.hs187
-rw-r--r--progs/prelude/Prelude.hu16
-rw-r--r--progs/prelude/PreludeArray.hs201
-rw-r--r--progs/prelude/PreludeArrayPrims.hi37
-rw-r--r--progs/prelude/PreludeArrayPrims.hu4
-rw-r--r--progs/prelude/PreludeComplex.hs94
-rw-r--r--progs/prelude/PreludeCore.hs817
-rw-r--r--progs/prelude/PreludeIO.hs232
-rw-r--r--progs/prelude/PreludeIOMonad.hs60
-rw-r--r--progs/prelude/PreludeIOPrims.hi55
-rw-r--r--progs/prelude/PreludeIOPrims.hu4
-rw-r--r--progs/prelude/PreludeList.hs585
-rw-r--r--progs/prelude/PreludeLocal.hs16
-rw-r--r--progs/prelude/PreludeLocalIO.hs144
-rw-r--r--progs/prelude/PreludePrims.hi252
-rw-r--r--progs/prelude/PreludePrims.hu4
-rw-r--r--progs/prelude/PreludeRatio.hs98
-rw-r--r--progs/prelude/PreludeText.hs260
-rw-r--r--progs/prelude/PreludeTuple.hs213
-rw-r--r--progs/prelude/PreludeTuplePrims.hi48
-rw-r--r--progs/prelude/PreludeTuplePrims.hu4
-rw-r--r--progs/prelude/README12
-rw-r--r--progs/tutorial/README12
-rw-r--r--progs/tutorial/tutorial.hs2143
165 files changed, 17571 insertions, 0 deletions
diff --git a/progs/README b/progs/README
new file mode 100644
index 0000000..8b28d8f
--- /dev/null
+++ b/progs/README
@@ -0,0 +1,9 @@
+This directory contains Haskell source code.
+Subdirectories:
+prelude The prelude used in this system
+tutorial The online supplement to the Hudak & Fasel tutorial
+demo A set of random demo programs
+lib Various random extensions
+
+Other programs can be found in the Haskell program library on the
+official Haskell ftp sites.
diff --git a/progs/demo/Calendar.hs b/progs/demo/Calendar.hs
new file mode 100644
index 0000000..fa2e4a4
--- /dev/null
+++ b/progs/demo/Calendar.hs
@@ -0,0 +1,138 @@
+-- This is a modification of the calendar program described in section 4.5
+-- of Bird and Wadler's ``Introduction to functional programming'', with
+-- two ways of printing the calendar ... as in B+W, or like UNIX `cal':
+--
+-- Use from within Yale Haskell:
+--
+-- Main> :l Calendar
+-- Now in module Calendar.
+-- Calendar> @ do cal 1992
+-- Calendar> :e
+--
+-- ... Unix style calendar ...
+--
+-- Calendar> @ do calendar 1992
+-- Calendar> :e
+--
+-- ... Bird and Wadler style calendar ...
+--
+-- Calendar>
+
+module Calendar(cal,calendar) where
+
+infixr 5 `above`, `beside`
+
+do cal year = appendChan stdout (cal year) exit done
+
+-- Picture handling:
+
+type Picture = [[Char]]
+
+height, width :: Picture -> Int
+height p = length p
+width p = length (head p)
+
+above, beside :: Picture -> Picture -> Picture
+above = (++)
+beside = zipWith (++)
+
+stack, spread :: [Picture] -> Picture
+stack = foldr1 above
+spread = foldr1 beside
+
+empty :: (Int,Int) -> Picture
+empty (h,w) = copy h (copy w ' ')
+
+block, blockT :: Int -> [Picture] -> Picture
+block n = stack . map spread . group n
+blockT n = spread . map stack . group n
+
+group :: Int -> [a] -> [[a]]
+group n [] = []
+group n xs = take n xs : group n (drop n xs)
+
+lframe :: (Int,Int) -> Picture -> Picture
+lframe (m,n) p = (p `beside` empty (h,n-w)) `above` empty (m-h,n)
+ where h = height p
+ w = width p
+
+-- Information about the months in a year:
+
+monthLengths year = [31,feb,31,30,31,30,31,31,30,31,30,31]
+ where feb | leap year = 29
+ | otherwise = 28
+
+leap year = if year`mod`100 == 0 then year`mod`400 == 0
+ else year`mod`4 == 0
+
+monthNames = ["January","February","March","April",
+ "May","June","July","August",
+ "September","October","November","December"]
+
+jan1st year = (year + last`div`4 - last`div`100 + last`div`400) `mod` 7
+ where last = year - 1
+
+firstDays year = take 12
+ (map (`mod`7)
+ (scanl (+) (jan1st year) (monthLengths year)))
+
+-- Producing the information necessary for one month:
+
+dates fd ml = map (date ml) [1-fd..42-fd]
+ where date ml d | d<1 || ml<d = [" "]
+ | otherwise = [rjustify 3 (show d)]
+
+-- The original B+W calendar:
+
+calendar :: Int -> String
+calendar = unlines . block 3 . map picture . months
+ where picture (mn,yr,fd,ml) = title mn yr `above` table fd ml
+ title mn yr = lframe (2,25) [mn ++ " " ++ show yr]
+ table fd ml = lframe (8,25)
+ (daynames `beside` entries fd ml)
+ daynames = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]
+ entries fd ml = blockT 7 (dates fd ml)
+ months year = zip4 monthNames
+ (copy 12 year)
+ (firstDays year)
+ (monthLengths year)
+
+-- In a format somewhat closer to UNIX cal:
+
+cal :: Int -> String
+cal year = unlines (banner year `above` body year)
+ where banner yr = [cjustify 75 (show yr)] `above` empty (1,75)
+ body = block 3 . map (pad . pic) . months
+ pic (mn,fd,ml) = title mn `above` table fd ml
+ pad p = (side`beside`p`beside`side)`above`end
+ side = empty (8,2)
+ end = empty (1,25)
+ title mn = [cjustify 21 mn]
+ table fd ml = daynames `above` entries fd ml
+ daynames = [" Su Mo Tu We Th Fr Sa"]
+ entries fd ml = block 7 (dates fd ml)
+ months year = zip3 monthNames
+ (firstDays year)
+ (monthLengths year)
+
+-- Additional (B+W)-isms: these really ought to go in a separate module,
+-- in a spearate file. But for ease of packaging this simple application,
+-- it doesn't seem worth the trouble!
+
+copy :: Int -> a -> [a]
+copy n x = take n (repeat x)
+
+space :: Int -> String
+space n = copy n ' '
+
+-- Simple string formatting:
+
+cjustify, ljustify, rjustify :: Int -> String -> String
+
+cjustify n s = space halfm ++ s ++ space (m - halfm)
+ where m = n - length s
+ halfm = m `div` 2
+ljustify n s = s ++ space (n - length s)
+rjustify n s = space (n - length s) ++ s
+
+-- End of calendar program
diff --git a/progs/demo/README b/progs/demo/README
new file mode 100644
index 0000000..4a683cd
--- /dev/null
+++ b/progs/demo/README
@@ -0,0 +1,15 @@
+
+This directory contains Haskell demo programs. All of these programs
+compile and execute properly.
+
+This directory contains:
+
+
+fact.hs factorial
+merge.hs merge sort
+pfac.hs parallel factorial
+primes.hs prime number generator
+qs.hs quick sort
+queens.hs N queens
+symalg/ A symbolic algebra program
+prolog/ A prolog interpreter
diff --git a/progs/demo/X11/animation/README b/progs/demo/X11/animation/README
new file mode 100644
index 0000000..c14b867
--- /dev/null
+++ b/progs/demo/X11/animation/README
@@ -0,0 +1,22 @@
+In his paper "A Functional Animation Starter Kit" [ARYA88], Kevi Arya
+proposes an approach to animation that uses functional languages. As
+Arya describes, the cost of computing power is falling. This is making
+the use of computer animation much more prevalent. However, languages
+such as C make it difficult to program animations. What is needed is
+a simpler, faster and more accessible way to program graphics. Functional
+languages are a very effective means for this, due to their higher order
+functions.
+
+ Kevi Arya goes on to provide such a functional animation package in
+the language Miranda. Haskell in particular is good functional language for
+two reasons. It is a completely functional language, doing even I/O in a
+functional manner. Variables are evaluated in a lazy manner allowing infinite
+lists to be manipulated easily, which suits the infinite frames format
+of animation.
+
+The following animations are provided here:
+
+ seaside.hs - a seaside scene
+ planets.hs - planets in orbit
+ palm.hs - another seaside scene
+ birds.hs - flying birds
diff --git a/progs/demo/X11/animation/animation.hs b/progs/demo/X11/animation/animation.hs
new file mode 100644
index 0000000..3c0750c
--- /dev/null
+++ b/progs/demo/X11/animation/animation.hs
@@ -0,0 +1,16 @@
+-- This bundles all the animation stuff into a single module.
+
+module Animation(R_Ptypes..,R_Constants..,R_Utility..,R_Picture..,R_Behaviour..,
+ R_Movie..,R_Shapes..,R_Defaults..,R_Inbetween..,
+ R_Display..) where
+import R_Ptypes
+import R_Constants
+import R_Utility
+import R_Picture
+import R_Behaviour
+import R_Movie
+import R_Shapes
+import R_Defaults
+import R_Inbetween
+import R_Display
+
diff --git a/progs/demo/X11/animation/animation.hu b/progs/demo/X11/animation/animation.hu
new file mode 100644
index 0000000..0dd71ee
--- /dev/null
+++ b/progs/demo/X11/animation/animation.hu
@@ -0,0 +1,6 @@
+animation.hs
+r_movie.hu
+r_defaults.hu
+r_shapes.hu
+r_inbetween.hu
+r_display.hu
diff --git a/progs/demo/X11/animation/birds.hs b/progs/demo/X11/animation/birds.hs
new file mode 100644
index 0000000..daba730
--- /dev/null
+++ b/progs/demo/X11/animation/birds.hs
@@ -0,0 +1,28 @@
+module Birds where
+
+import Animation
+
+bird :: Movie
+--bird = osc [bird1,bird2]
+bird = rOVERLAY
+ [apply (bPar [right,right,right,right]) bm1,
+ apply (bPar [up,right,right,right]) bm2]
+ where bm1 = osc [bird1]
+ bm2 = osc [bird2]
+
+bird1 = [(black,b1)]
+ where b1 = [(0,90),(20,100),(30,110),(40,110),(50,100),(110,120),
+ (130,100),(120,90),(80,90),(0,90),
+ (80,90),(90,70),(140,50),(120,90),(80,90),
+ (80,90),(70,70),(80,60),(90,70)]
+
+bird2 = [(red,b2)]
+ where b2 = [(0,60),(20,70),(30,80),(40,80),(50,70),(110,70),
+ (140,30),(110,35),(100,35),(70,50),(50,60),(0,60),
+ (70,50),(100,90),(150,100),(120,60),(110,35),
+ (70,50),(65,100),(85,115),(97,86)]
+
+main = getEnv "DISPLAY" exit
+ (\ host -> displaym host 30 bird)
+
+
diff --git a/progs/demo/X11/animation/birds.hu b/progs/demo/X11/animation/birds.hu
new file mode 100644
index 0000000..cd94b30
--- /dev/null
+++ b/progs/demo/X11/animation/birds.hu
@@ -0,0 +1,3 @@
+:o= all
+birds.hs
+animation.hu
diff --git a/progs/demo/X11/animation/doc.tex b/progs/demo/X11/animation/doc.tex
new file mode 100644
index 0000000..1b66751
--- /dev/null
+++ b/progs/demo/X11/animation/doc.tex
@@ -0,0 +1,578 @@
+
+% This is obsolete regarding the X system -- jcp
+
+% -*-latex-*-
+% Creator: John Tinmouth
+% Creation Date: Thu May 9 1991
+\documentstyle[11pt]{article}
+\newcommand{\X}[1]{{#1}\index{{#1}}}
+\begin{document}
+
+\title{A Functional Animation Package in Haskell}
+\author{
+ John Tinmouth\\
+ Computer Science Senior Project\\
+ Yale University\\
+ Professor Paul Hudak }
+\date{9 May 1991}
+\maketitle
+
+
+
+\section{Introduction}
+
+ In his paper "A Functional Animation Starter Kit" [ARYA88], Kevi Arya
+proposes an approach to animation that uses functional languages. As
+Arya describes, the cost of computing power is falling. This is making
+the use of computer animation much more prevalent. However, languages
+such as C make it difficult to program animations. What is needed is
+a simpler, faster and more accessible way to program graphics. Functional
+languages are a very effective means for this, due to their higher order
+functions.
+
+ Kevi Arya goes on to provide such a functional animation package in
+the language Miranda. Haskell in particular is good functional language for
+two reasons. It is a completely functional language, doing even I/O in a
+functional manner. Variables are evaluated in a lazy manner allowing infinite
+lists to be manipulated easily, which suits the infinite frames format
+of animation. As it is now possible to complete the implementation of
+this package is Haskell, my work has been converting these Miranda programs
+to Haskell version 1.0-0, Yale Haskell Group.
+
+
+
+\section{How to Use the Graphics: Overview}
+
+ By using higher order functions, it becomes very easy to do rapid
+prototyping of animations. You can quickly throw out an animation of
+simple images manipulated in simple ways. For example, if there was
+an image of a car, and you wanted it to move left, you could almost
+just describe it in english, and that would be the animation.
+\begin{verbatim}
+ movie = apply left car
+\end{verbatim}
+
+ After the simple model is done, converting it to a more complex model
+is simple. Simply make the image, "car" in this case, more complex, and
+then modify the "left" function, and you are done.
+
+ There are three stages in making a movie. First of all, you must
+define your basic images. These will tend to be Pics put into lists, either
+finite or infinite, to be basic Movies. Second, you decide precisely
+what kind of motion you want in animation. These are behaviours. A behaviour
+modifies a movie over time, changing each successive frame. This includes
+motion, changing size, changing from one image to another and so forth. These
+are applied to your basic Movies. Third, you must combine your basic Movies
+into your final Movie. If you want a scene of clouds and a man walking, you
+must overlay your basic Movie of clouds with your Movie of a walking man.
+
+\section {Original Images or Pics}
+
+ A Movie is a list of frames called Pics. Each of these Pics is a list
+of colored polygons. The Pic is a Color followed by a list of Vectors,
+representing the vertices of the Polygon. The original Pic usually must
+be entered by hand, although simple generation routines for boxes,
+triangles and circles are available. You need to produce some of these
+basic images in one way or another, so that you have something to
+manipulate.
+
+ To make a Movie, you need a list of these Pics. With a single Pic, you
+can generate a sequence of that Pic. With several Pics, you can oscillate
+through the Pics in an inifinite list. To generate an infinite list of
+Pics of p1, define a Movie, m1 = i p1.
+ The following datatypes are used in this package:
+
+\begin{verbatim}
+type Vec = (Int,Int)
+type Color = Int
+type Poly = (Color,[Vec])
+type Pic = [Poly]
+type Movie = [Pic]
+type Behaviour = [Pic -> Pic]
+\end{verbatim}
+
+
+\subsection {Modifying Pics}
+
+ Starting with a single Pic, it is possible to create a short list of
+Pics to oscillate on. You can flip it, scale it, or otherwise modify the
+original Pic (p1) in some way to create another Pic (p2). You can either
+keep doing this and produce N images for a Movie of [p1,p2,...,pN], or use
+the interpolation functions available to shift from p1 to p2 in N frames,
+resulting in a Movie [p1,interp1,interp2,...,interpN-2,p2].
+ The list of specific Pic-to-Pic functions is included in the next section,
+along with short explanations of what they do.
+
+\subsection {Pic-to-Pic Functions Available}
+
+\begin{verbatim}
+overlay_Pic Args: Pic Pic
+ This takes 2 Pics and just puts them together into one Pic.
+ module: R_Picture
+
+put_Pic Args: Vec Pic Pic
+ This overlays the two Pics, putting Pic-1's center the Vec
+ distance away from Pic-2's center.
+ module: R_Picture
+
+over_Pic Args: Pic Pic
+ This puts two images on top of one another, explicitly
+ centering the first on top of the second and forms one Pic.
+ module: R_Picture
+
+above_Pic Args: Pic Pic
+ This puts the first Pic above the second Pic, at a distance
+ of half the combined heights of the Pics and overlays them
+ to form one Pic.
+ module: R_Picture
+
+beside_Pic Args: Pic Pic
+ This puts the first Pic to the right of the second Pic, at
+ a distance of half the combined widths of the Pics and
+ overlays them to form one Pic.
+ module: R_Picture
+
+beside2_Pic Args: Pic Pic
+ Withouth analysing the widths of the Pics, it puts the
+ first Pic the width of the second Pic to the right and
+ overlays them to form one Pic.
+ module: R_Picture
+
+scale_Pic Args: Int Pic
+ This scales the picture in elevenths around its own origin
+ and returns that Pic. So if the Int is 22, the Pic will
+ scaled by a factor of 2 (22/11).
+ module: R_Picture
+
+scale_rel_Pic Args: Vev Int Pic
+ This is another scaling function, but it scales the image
+ from the Vec, treating it as the origin.
+ module: R_Picture
+
+mov_Pic Args: Vec Pic
+ This moves the Pic by the amount of the vector.
+ module: R_Picture
+
+movto_Pic Args: Vec Pic
+ This moves the Pic's center to the Vec.
+ module: R_Picture
+
+to_orig Args: Pic
+ This moves the Pic's center to the lower,left side of
+ the Pic.
+ module: R_Picture
+
+rot_Pic Args: Vec Float Pic
+ This rotates the Pic by the Float in radians, using the Vec
+ as the origin of rotation.
+ module: R_Picture
+
+twist_Pic Args: Float Pic
+ This rotates the Pic by the Float amount of radians around
+ its own center.
+ module: R_Picture
+
+rot_Pic' Args: Vec Pic
+ This rotates the Pic by a certain amount (set in R_Constants)
+ using the Vec as the center of rotation. The set amount of
+ rotation makes it faster than rot_Pic.
+ module: R_Picture
+
+twist_Pic' Args: Pic
+ This rotates the Pic by a certain amoutn (set in R_Constants)
+ around the Pic's origin. The set amount of rotation makes
+ it faster than twist_Pic.
+ module: R_Picture
+
+flipx_Pic Args: Int Pic
+ This flips the Pic around the line x=Int, essentially giving
+ a mirror image of the Pic, reversing right and left.
+ module: R_Picture
+
+
+flipy_Pic Args: Int Pic
+ This flips the Pic around the line y=Int, mirror-imaging the
+ Pic, reversing up and down.
+ module: R_Picture
+
+flip_Pic Args: Pic
+ This flips the Pic around its own x-origin, reversing
+ left and right.
+ module: R_Picture
+
+flock_Pic Args: Int Pic
+ This takes the image Pic and copies it out Int*Int times in
+ a Int by Int grid pattern, and returns that as an Pic.
+ module: R_Picture
+
+set_Color Args: Int Pic
+ This takes an Int standing for a color, and changes the
+ color of the Pic to that.
+ module: R_Picture
+\end{verbatim}
+
+\subsection{Other Functions for Manipulating Pics}
+
+\begin{verbatim}
+i Args: Any
+ This will take anything and return an infinite stream of them.
+ module: R_Utility
+
+osc Args: [Any]
+ This will take a Movie, which is a list of Pics and
+ oscillate them.
+ [p1] will give [p1,p1,p1,p1....]
+ [p1,p2,p3,p4] will give [p1,p2,p3,p4,p3,p2,p1,p2...]
+ module: R_Utility
+\end{verbatim}
+
+\section{Behaviours and their Application to Movies}
+
+ A Behaviour is a list of functions that will convert one Pic to
+another Pic. This list then can be applied to any Movie with one
+of the application functions (most often apply). The beauty of the Behaviour
+is that once you have a behaviour for moving left, you can move any
+Movie left without rewriting the routine every time.
+
+ There are specific functions that take a Behaviour and a Movie and
+return a new Movie. These are apply and while. If you had a Movie of a
+man walking in place, and a Behaviour called left that moves Pics ever
+increasing distances left, then you could create a man walking left by:
+\begin{verbatim}
+ apply left man
+\end{verbatim}
+
+ If you want to apply more than one Behaviour to a Movie, you must first
+decide whether to do that in sequence or in parallel, and use bSeq and bPar
+to reduce the list of Behaviours to a single Behaviour, and then apply
+that to a movie. For example:
+\begin{verbatim}
+ apply (bPar left up) gull
+\end{verbatim}
+will take a Movie of a gull and move the Pics up and left.
+
+ Most of the basic Behaviours are defined in R\_Behaviour.
+
+
+\subsection{Defining Customized Packages of Behaviours}
+
+ Often you will have more specialized, or just simpler Behaviours you
+want to use. Using the Behaviours and Pic-to-Pic functions, it is very
+easy to create your own small library of Behaviours. R\_Defaults is a
+module of such Behaviours. For example, to create a Behaviour to move
+a Movie right, you would create a list of mov\_Pic's, each taking a
+everincreasingly large x-coordinate.
+\begin{verbatim}
+ right = [ mov_Pic (x,y) | (x,y) <- zip [0,10,..] [0,..] ]
+\end{verbatim}
+
+ Or if you wanted a behavour to place a Movie at (100,100) twice as
+large as before, you could create a new Behaviour from old ones as:
+ scaleat= bPar [movto (i (100,100)), scale (i 22)]
+
+\subsection{Behaviours Available}
+\begin{verbatim}
+flip Args: none
+ This will flip every Pic around its x-origin, resulting in
+ mirror images reversing left and right.
+ module: R_Behaviour
+
+twist' Args: none
+ This will rotate each Pic by the amount rotunit (see
+ R_Constants) around its origin.
+ module: R_Behaviour
+
+mov Args: [Vec]
+ This will move each Pic by its corresponding vector.
+ module: R_Behaviour
+
+movto Args: [Vec]
+ This will move each Pic's origin to its corresponding vector.
+ module: R_Behaviour
+
+circ_mov Args: Float Float
+ This will move each Pic in a circle, of radius of the first
+ Float and by an increment of the second Float, using (0,0)
+ as the origin of rotation.
+ module: R_Behaviour
+
+scale Args: [Int]
+ Scales every Pic on its origin by the the corresponding Int
+ in the list. These Ints represents elevenths, so that a
+ [2,2,...] will scale every Pic by 2/11 .
+ module: R_Behaviour
+
+scale_rel Args: Vec [Int]
+ Same as scale, except that the Pics are all scaled using the
+ Vec as the point of origin.
+ module: R_Behaviour
+
+twist Args: [Float]
+ This will rotate every Pic by its corresponding Float from
+ the list in radians.
+ module: R_Behaviour
+
+set_color Args: [Int]
+ This sets each Pic to the color indicated by its
+ corresponding int in the list.
+ module: R_Behaviour
+
+rot Args: [Vec] [Float]
+ This will rotate each Pic around its corresponding Vec by
+ its corresponding Float in radians.
+ module: R_Behaviour
+
+big Args: none
+ Scales every Pic up by scaleunit
+ module: R_Defaults
+
+huge Args: none
+ This scales every Pic up by 2*scaleunit
+ module: R_Defaults
+
+small Args: none
+ This scales every Pic down by 10/11
+ module: R_Defaults
+
+tiny Args: none
+ This scale every Pic down by 5/11
+ module: R_Defaults
+
+bigger Args: none
+ This scales every Pic in the list by scaleunit more
+ than the previous Pic, so that the n-th element is
+ scaled up by (n-1)*scaleunit
+ module: R_Defaults
+
+smaller Args: none
+ This scales every Pic down, so that the n-th element
+ is scaled down by (n-1)*(10/11)
+ module: R_Defaults
+
+ccw Args: none
+ This rotates every Pic by one rotunit more than the
+ previous Pic, in a counterclockwise fashion.
+ module: R_Defaults
+
+cw Args: none
+ This rotates every Pic by one rotunit more than the
+ previous Pic, in a clockwise fashion.
+ module: R_Defaults
+
+up Args: none
+ This moves every Pic up by one unit more than the
+ Previous Pic, so that the n-th element is moved up
+ (n-1) units.
+ module: R_Defaults
+
+down Args: none
+ This is same as up, but the Pics move down.
+ module: R_Defaults
+
+right Args: none
+ This is same as up, but the Pics move right.
+ module: R_Defaults
+
+left Args: none
+ This is same as up, but the Pics move left.
+ module: R_Defaults
+\end{verbatim}
+
+\subsection{Functions For Behaviours}
+
+\begin{verbatim}
+do Args: Int Behaviour
+ This takes the first Int elements of the Behaviour and
+ return that.
+ module: R_Behaviour
+
+rpt Args: Int Behaviour
+ This takes an Int and returns a Behaviour of length Int.
+ However, the n-th Pic-to-Pic in the Behaviour returned
+ is made up of the first through (n-1)the Pic-to-Pics of
+ the input list.
+ module: R_Behaviour
+
+forever Args: Behaviour
+ This makes a finite Behaviour list an infinite one by
+ appending the list to itself endlessly.
+ module: R_Behaviour
+
+apply Args: Behaviour Movie
+ This takes a Behaviour and applies it to a Movie
+ module: R_Behaviour
+
+while Args: (Boolean function) Behaviour Movie
+ As long as the Boolean function evaluates true, this
+ takes a Behaviour and applies it to a Movie. When it
+ evaluates to false, no more Pics are produced and
+ the Movie is cut short there.
+ module: R_Behaviour
+
+bseq Args: Behaviour Behaviour
+ This takes two Behaviour and creates one Behaviour made
+ up of the two inputs applies in sequence.
+ module: R_Behaviour
+
+bSeq Args: [Behaviour] Behaviour
+ This takes two Behaviour and creates one Behaviour made
+ up of the two inputs applies in sequence.
+ module: R_Behaviour
+
+bpar Args: Behaviour Behaviour
+ This takes two Behaviour and creates one Behaviour made
+ up of the two inputs applies in parallel.
+ module: R_Behaviour
+
+bPar Args: [Behaviour] Behaviour
+ This takes two Behaviour and creates one Behaviour made
+ up of the two inputs applies in parallel.
+ module: R_Behaviour
+\end{verbatim}
+
+\section{Creating the Final Movie}
+
+ Finally, you have your basic Movies made up of Pictures and Behaviours.
+Now you need to combine them into one Movie. The functions that do this
+are found in the module R\_Movie. These functions will take a list of
+Movies and return a single Movie combining all the Movies in the list.
+How they are combined can be controlled to some extent. Usually they are
+just overlayed, but they can be put beside one another, or on top of
+one another, or put a Vec distance apart.
+
+ It is also possible to use a combination of these forms. If you wanted
+to overaly M1 and M2, and then put that beside M3, you would do:
+\begin{verbatim}
+ rBESIDE [M3, rOVERLAY [M1,M2] ]
+\end{verbatim}
+This is acceptable as rOVERLAY will return a single Movie.
+
+\subsection{Movie Combining Functions}
+
+\begin{verbatim}
+rABOVE Args: [Movie]
+ Puts all the Movies into one movie, all above one another.
+ module: R_Movie
+
+rBESIDE Args: [Movie]
+ Puts all the Movies into one movie, all beside one another.
+ module: R_Movie
+
+rBESIDE2 Args: [Movie]
+ Using their absolute coordinates, puts all the Movies
+ beside one another.
+ module: R_Movie
+
+rOVER Args: [Movie]
+ This lays the Movies on top of one another, centering
+ each Pic so that they share the same origin.
+ module: R_Movie
+
+rOVERLAY Args: [Movie]
+ This lays the Movies on top of one another, centering
+ each Pic so that they share the smae origin.
+ module: R_Movie
+
+pUT Args: [Vec] Movie Movie
+ This takes a list of Vec, and puts each Pic of the
+ first Movie in the location of the corresponding
+ Vec on top of the Pic of the second Movie and
+ returns that list as the new Movie.
+ module: R_Movie
+
+\end{verbatim}
+
+\section{Displaying Your Movie}
+
+ Once you have your function for the Movie defined, you need to output
+it in some way. Currently, this is done by outputting characters to a file and
+running a C Program in X-Windows that displays the contents of the file
+as a graphic in the X system. First of all, you must convert the
+Movie variable to a stream of characters. This is done by running
+"showm" on the Movie. Be carefull you don't try to convert an infinite list
+into characters as the compiler will take awhile to do this. Instead, take
+a certain number of frames and convert them with "showm".
+\begin{verbatim}
+ man\_vm = rOVERLAY [man,vm]
+ man\_vmstring = showm (take 20 man&vm)
+\end{verbatim}
+ Now that you have this string, you need to write it to disk. The
+"writetofile" function does this. It takes a characater string(ie [Char] )
+as an argument, and then prompts you for a filename. It then writes the
+string to the filename. So to put man\_vm string into a file:
+\begin{verbatim}
+ main = writetofile man_vmstring
+\end{verbatim}
+and run the program, where you will prompted for the filename. Or you could:
+\begin{verbatim}
+ main = writetofile (showm (take 20 man_vm))
+\end{verbatim}
+to make it more compact.
+
+
+\subsection{Miscellaneous Usefull Functions}
+
+\begin{verbatim}
+inbetween Args: Int Pic Pic
+ This takes an Int and two Pics and returns a Movie
+ with Int Pics interpolating between the two Pics.
+ module: R_Inbetween
+
+tween Args: Int Movie Movie
+ This takes an Int and two Movies and returns one
+ Movie made up of the first Movie, Int number of
+ frames of Pics interpolating between the last
+ Pic of the first Movie and the first Pic of the
+ second Movie, followed by the second Movie
+ module: R_Inbetween
+
+box Args: Int Int Int
+ This takes 3 Ints, the color, width and height of
+ the box and returns a Pic of a box
+ module: R_Shapes
+
+tri Args: Int Vec Vec Vec
+ This takes a color and three vectors and returns a
+ Pic of a triangle of that colour with those vertices.
+ module: R_Shapes
+
+circ Args: Int Int Int
+ This takes a color, the radius and the number of points
+ around the circle, and returns a circle with origin at
+ (0,0).
+ module: R_Shapes
+\end{verbatim}
+
+\pagebreak
+\large {\bf Appendix: C Programs to Display on X-Windows}
+\\
+\\
+ The program currently used to run these graphics is called "xcshow".
+This takes one argument, the name of the file to be run. When run
+in X-Windows, it will produce a window with the first Pic. To run it, click
+on the left mouse button inside the window. Clicking again will freeze it.
+This will keep cycling through the file, replaying again when it hits the
+end of the file, until the window is killed.
+
+ There is also "xshow" which is used to run the monochrome Movies, as
+"xcshow" is used to run the color Movies. As this animation package
+only produces color Movies, it isn't too usefull.
+
+
+\pagebreak
+\large {\bf References}
+\\
+\\
+\begin{verbatim}
+[ARYA88] "The Formal Analysis of a Functiona Animation System", Kevi Arya,
+ DPhil,Thesis,Oxford University, Programming Research Group,
+ April 1988
+
+[ARYA89] "Processes In A Functional Animation System", Kevi Arya,IBM
+ T.J. Research Center, 1989
+
+[HASK90] "Report On The Programming Language Haskell, Version 1.0",
+ YALEU/DCS/RR-777,Yale University,1990
+\end{verbatim}
+
+\end{document}
diff --git a/progs/demo/X11/animation/palm.hs b/progs/demo/X11/animation/palm.hs
new file mode 100644
index 0000000..9deef12
--- /dev/null
+++ b/progs/demo/X11/animation/palm.hs
@@ -0,0 +1,47 @@
+module Palm (main) where
+
+import Animation
+import SeaFigs
+
+main = getEnv "DISPLAY" exit
+ (\ host -> displaym host 30 trans)
+
+trans :: Movie
+trans = manright++change++gull2
+
+manright::Movie
+manright = mirrorx (take 10 (apply left man))
+
+gull2::Movie
+gull2 = apply (bPar [right,up,huge,huge,huge,(mov (i (275,0)))]) gull
+
+change::Movie
+change = inbetween 5 manf1 gull1
+ where gull1 = head gull2
+ manf1 = last manright
+
+
+
+mirrorx :: Movie -> Movie
+mirrorx m = map (flipx_Pic x) m
+ where (x,_)=orig_Movie m
+
+
+orig_Movie :: Movie -> Vec
+orig_Movie m = ((x2-x1) `div` 2,(y2-y1) `div` 2)
+ where x2 = reduce max (map maxx m)
+ x1 = reduce min (map minx m)
+ y2 = reduce max (map maxy m)
+ y1 = reduce min (map miny m)
+
+maxx :: Pic -> Int
+maxx p = reduce max [x | (c,q) <- p, (x,y) <- q]
+
+minx :: Pic -> Int
+minx p = reduce min [x | (c,q) <- p, (x,y) <- q]
+
+maxy :: Pic -> Int
+maxy p = reduce max [y | (c,q) <- p, (x,y) <- q]
+
+miny :: Pic -> Int
+miny p = reduce min [y | (c,q) <- p, (x,y) <- q]
diff --git a/progs/demo/X11/animation/palm.hu b/progs/demo/X11/animation/palm.hu
new file mode 100644
index 0000000..a86fcb9
--- /dev/null
+++ b/progs/demo/X11/animation/palm.hu
@@ -0,0 +1,3 @@
+:o= all
+palm.hs
+seafigs.hu
diff --git a/progs/demo/X11/animation/planets.hs b/progs/demo/X11/animation/planets.hs
new file mode 100644
index 0000000..38f278a
--- /dev/null
+++ b/progs/demo/X11/animation/planets.hs
@@ -0,0 +1,30 @@
+module Planets (main) where
+
+import Animation
+
+planets:: Float -> Float -> Int -> Int -> Int -> Int -> Movie
+planets i1 i2 r1 r2 c1 c2
+ = rOVERLAY
+ [ apply f1 earth,
+ apply (bpar f1 f2) moon
+ ]
+ where f1 = circ_mov (fromIntegral r1) i1
+ f2 = circ_mov (fromIntegral r2) i2
+ earth = osc [mov_Pic (vplus center (r1,0)) (box c1 30 30)]
+ moon = osc [mov_Pic (vplus center (r1+r2,0)) (box c2 15 15)]
+
+gen a b c d = c :(gen a b (c+b) d)
+
+
+planet_scene:: Movie
+planet_scene = rOVERLAY
+ [apply (bpar (set_color (i yellow)) (movto (i center))) orb,
+ planets (pi/40.0) (pi/10.0) 450 80 darkblue lightblue,
+ planets (pi/20.0) (pi/8.0) 300 50 brown black,
+ planets (pi/10.0) (pi/4.0) 150 40 green red
+ ]
+
+orb = osc [circ red 50 10]
+
+main = getEnv "DISPLAY" exit
+ (\ host -> displaym host 60 planet_scene)
diff --git a/progs/demo/X11/animation/planets.hu b/progs/demo/X11/animation/planets.hu
new file mode 100644
index 0000000..3473372
--- /dev/null
+++ b/progs/demo/X11/animation/planets.hu
@@ -0,0 +1,3 @@
+:o= all
+planets.hs
+animation.hu
diff --git a/progs/demo/X11/animation/r_behaviour.hs b/progs/demo/X11/animation/r_behaviour.hs
new file mode 100644
index 0000000..6f58e3b
--- /dev/null
+++ b/progs/demo/X11/animation/r_behaviour.hs
@@ -0,0 +1,158 @@
+{-**********************************************************************
+ MODULE R_BEHAVIOUR
+
+ This module defines the basic Behaviours available to manipulate
+ Movies. These functions can either be used directly, or used to
+ easily create personnalized Behaviours (see R_Defaults).
+ There are the Behaviours that affect one Movie, which are mov,movto
+ circ_mov,scale,scale_rel,rot,flip and set_color. These change some
+ aspect of the movie over time.
+ There are functions that combine several movies into one, namely
+ bseq,bSeq,bpar and bPar.
+ Some functions modify the Behaviours. These are do, rpt and forever.
+ They put limits on how long the Behaviour is.
+ Finally, there are the functions that apply the Behaviours to a Movie.
+ These are apply and while. Apply applies a Behaviour to a Movie until
+ it runs out of Movie or Behaviour. While takes a conditional and
+ applies the Behaviour to it until that condition is fullfilled.
+
+***********************************************************************-}
+
+module R_Behaviour (mov,movto,circ_mov,scale,scale_rel,rot,flipb,
+ set_color,
+ bseq,bSeq,bpar,bPar,
+ do,rpt,forever,
+ apply,while ) where
+
+import R_Ptypes
+import R_Utility
+import R_Picture
+
+ -- takes a Pic to Pic and makes an infinite list Behaviour out of it
+makeb1 :: (Pic->Pic) -> Behaviour
+makeb1 f = f : makeb1 f
+
+ -- takes a movie and flips it around the x-origin using flip_Pic
+flipb :: Behaviour
+flipb = makeb1 flip_Pic
+
+ -- twist makes twist_Pic into a Behaviour, rotating the image by rotunit
+twist' :: Behaviour
+twist' = makeb1 twist_Pic'
+
+ -- makeb2 makes a Behaviour out of a function that takes a list and a
+ -- function and outputs a Behaviour.
+makeb2 :: (a->Pic->Pic) -> [a] -> Behaviour
+makeb2 f [] = []
+makeb2 f (v:vs) = f v : makeb2 f vs
+
+ -- mov takes a list of Vec's and applies each Pic-to-Pic in the Behaviour
+ -- list to its corresponding Vec, and gives back a new Behaviour
+mov :: [Vec] ->Behaviour
+mov = makeb2 mov_Pic
+
+ -- movto creates a list of Pic-to-Pic Behaviours that move each Pic to its
+ -- corresponding Vec
+movto :: [Vec] -> Behaviour
+movto = makeb2 movto_Pic
+
+ -- produces a Behaviour that produces movement in a circle, taking
+ -- the radius and the increment as arguments.
+circ_mov :: Float -> Float -> Behaviour
+circ_mov r inc = mov (map (vmin' (head vs')) vs')
+ where vs = [ (r*(cos theta),r*(sin theta)) |
+ theta <- gen inc 0.0 ]
+ vmin' x y = vmin y x
+ vs' = map vftov vs
+
+gen :: Float -> Float -> [Float]
+gen b c = c : (gen b (c+b) )
+
+
+ -- scale outputs a list of Pic-to-Pic's that scale according to its
+ -- corresponding Int in the input list
+scale :: [Int] -> Behaviour
+scale = makeb2 scale_Pic
+
+ -- scale_rel does the same thing, but centers on the lower-left corner of
+ -- the image
+scale_rel :: Vec -> [Int] -> Behaviour
+scale_rel v = makeb2 (scale_rel_Pic v)
+
+ -- twist outputs a list of Behaviours that rotate each pick by its
+ -- corresponding Float in the list
+twist :: [Float] -> Behaviour
+twist = makeb2 twist_Pic
+
+ -- set_color takes a list of Colors, and returns a list of Pic-to-Pic's
+ -- that change to the corresponding color in the list
+set_color :: [Color] -> Behaviour
+set_color = makeb2 set_Color_Pic
+
+ -- makeb3 takes a function with two inputs, and two input lists and
+ -- returns a behaviour made up of functions with inputs fromt the lists
+makeb3 :: (a->b->Pic->Pic) -> [a] -> [b] -> Behaviour
+makeb3 f [] (p:ps) = []
+makeb3 f (v:vs) [] = []
+makeb3 f (v:vs) (p:ps) = f v p : makeb3 f vs ps
+
+ -- rot produces behaviours rotating by the Float, around the point
+ -- of the Vec, both provided by lists.
+rot :: [Vec] -> [Float] -> Behaviour
+rot = makeb3 rot_Pic
+
+ -- bseq takes two Behaviours and combines them into one, in sequence.
+ -- It first applies all of the first Behaviour, then all of the second
+bseq :: Behaviour -> Behaviour -> Behaviour
+bseq ps [] = []
+bseq [] qs = []
+bseq ps qs = ps ++ (mapc (last ps) qs)
+
+ -- bSeq takes a list of Behaviour and makes them into one Behaviour, in
+ -- sequence.
+bSeq :: [Behaviour] -> Behaviour
+bSeq = reduce bseq
+
+ -- bpar takes two behaviours and applies them both simultaneously,
+ -- producing a list of Pic-to-Pic's, each one made up of a function
+ -- from the first list combined with a function from the second list
+bpar :: Behaviour -> Behaviour -> Behaviour
+bpar [] (q:qs) = []
+bpar (p:ps) [] = []
+bpar (p:ps) (q:qs) = (p.q):(bpar ps qs)
+
+ -- bPar takes a list of Behaviours and makes them all into one Behaviour,
+ -- in paralell
+bPar :: [Behaviour] -> Behaviour
+bPar = reduce bpar
+
+ -- takes the first n POic-to-Pics in a Behaviour and returns that Behaviour
+do :: Int -> Behaviour -> Behaviour
+do n f = take n f
+
+ -- applies bseq to the list of behaviours, so that the nth element of
+ -- the returned list has n-1 behaviours in it, applied in sequence
+rpt :: Int -> Behaviour -> Behaviour
+rpt n f = replicate n bseq [] f
+
+ -- takes the behaviour and applies all the behaviours up the nth element
+ -- to the nth element, in an infinite list
+forever :: Behaviour -> Behaviour
+forever f = bseq f (forever f)
+
+ -- takes a behaviour, applies each from to a Pic in a Movie and returns
+ -- the new Movie
+apply :: Behaviour -> Movie -> Movie
+apply [] ms = []
+apply fs [] = []
+apply (f:fs) (m:ms) = (f m):(apply fs ms)
+
+ -- applies the Behaviour to the Movie until the condition is fullfilled,
+ -- then returns the movie to that point
+while :: (Pic -> Bool) -> Behaviour -> Movie -> Movie
+while c [] ms = []
+while c fs [] = []
+while c (f:fs) (m:ms) = if (c m) then ( (f m):(while c fs ms))
+ else []
+
+
diff --git a/progs/demo/X11/animation/r_behaviour.hu b/progs/demo/X11/animation/r_behaviour.hu
new file mode 100644
index 0000000..afa52bb
--- /dev/null
+++ b/progs/demo/X11/animation/r_behaviour.hu
@@ -0,0 +1,3 @@
+:o= all
+r_behaviour.hs
+r_picture.hu
diff --git a/progs/demo/X11/animation/r_constants.hs b/progs/demo/X11/animation/r_constants.hs
new file mode 100644
index 0000000..f36e3f2
--- /dev/null
+++ b/progs/demo/X11/animation/r_constants.hs
@@ -0,0 +1,129 @@
+{-****************************************************************
+ MODULE R_CONSTANTS
+
+ This module sets up all the constants used in this functional
+ animation package.
+ Defined here are the basic units of movement, scale and rotation.
+ The screen height and width are set, and the various parts of
+ the screen such as the top-middle, lower-left and center are
+ all set. Finally the color values used by xcshow, the c-program
+ that displays the movies in X, are set.
+
+******************************************************************-}
+
+module R_Constants (fps, unit, hf, qt, scaleunit, rotunit,
+ nullpic, nullseq,
+ sinunit,cosunit,
+ screenwid, screenht, botl, leftm, topl, topm, topr,
+ rightm, botr, botm, center,
+ white,black,red,green,darkblue,lightblue,brown,yellow,
+ colorName, allColors
+ ) where
+
+import R_Ptypes
+
+ -- units are set. The scaleunit is in 11th, so that the 12 is
+ -- actually 12/11'ths
+fps :: Int
+unit :: Int
+hf :: Int
+qt :: Int
+scaleunit :: Int
+fps = 25
+unit = 15
+hf = unit `div` 2
+qt = unit `div`4
+scaleunit = 12
+ --scaleunit is div'ed by 12 later
+
+rotunit :: Float
+rotunit = pi/18
+sinunit = sin rotunit
+cosunit = cos rotunit
+
+
+nullpic :: Pic
+nullpic = []
+nullseq :: Movie
+nullseq= nullpic : [ nullseq2 | nullseq2 <- nullseq]
+
+ -- Screen Parameters
+screenwid :: Int
+screenwid = 800
+screenht :: Int
+screenht = 800
+
+botl :: Vec
+leftm :: Vec
+topl :: Vec
+topm :: Vec
+topr :: Vec
+rightm :: Vec
+botr :: Vec
+botm :: Vec
+center :: Vec
+
+leftmb :: Vec
+leftmt :: Vec
+topml :: Vec
+topmr :: Vec
+rightmt :: Vec
+rightmb :: Vec
+botml :: Vec
+botmr :: Vec
+
+botl = ( 0, 0 )
+leftm = ( 0, screenht `div` 2)
+topl = ( 0, screenht )
+topm = ( screenwid `div` 2, screenht )
+topr = ( screenwid, screenht )
+rightm = ( screenwid, screenht `div` 2 )
+botr = ( screenwid, 0 )
+botm = ( screenwid `div` 2, 0 )
+center = ( screenwid `div` 2, screenht `div` 2 )
+
+leftmb = ( 0, screenht `div` 4 )
+leftmt = ( 0, (screenht*3) `div` 4 )
+topml = ( screenwid `div` 4, screenht )
+topmr = ( (screenwid*3) `div` 4, screenht )
+rightmt = ( screenwid, (screenht*3) `div` 4 )
+rightmb = ( screenwid, screenht `div` 4 )
+botml = ( screenwid `div` 4, 0 )
+botmr = ( (screenwid*3) `div` 4, 0 )
+
+ -- Colors values set to names
+
+white :: Color
+white = 1
+black :: Color
+black = 2
+red :: Color
+red = 4
+green :: Color
+green = 6
+darkblue :: Color
+darkblue = 8
+lightblue :: Color
+lightblue = 10
+yellow :: Color
+yellow = 12
+brown :: Color
+brown = 14
+
+colorName :: Color -> String
+colorName 1 = "white"
+colorName 2 = "black"
+colorName 4 = "red"
+colorName 6 = "green"
+colorName 8 = "blue"
+colorName 10 = "lightblue"
+colorName 12 = "yellow"
+colorName 14 = "brown"
+
+allColors :: [Color]
+allColors = [1,2,4,6,8,10,12,14]
+
+
+
+
+
diff --git a/progs/demo/X11/animation/r_constants.hu b/progs/demo/X11/animation/r_constants.hu
new file mode 100644
index 0000000..d61580f
--- /dev/null
+++ b/progs/demo/X11/animation/r_constants.hu
@@ -0,0 +1,3 @@
+:o= all
+r_constants.hs
+r_ptypes.hu
diff --git a/progs/demo/X11/animation/r_curve.hs b/progs/demo/X11/animation/r_curve.hs
new file mode 100644
index 0000000..14d288c
--- /dev/null
+++ b/progs/demo/X11/animation/r_curve.hs
@@ -0,0 +1,60 @@
+{-**************************************************************
+ MODULE R_CURVE
+
+ This module produces sequences of numbers to be used by
+ Behaviours. The sequences used for moving or scaling can
+ be produced here, in either linear sequences or accelerating
+ and decelerating sequences.
+ The acceleration functions produce floats, so the vftov function
+ would have to be used to convert floating point vectors to integer
+ vectors.
+
+***************************************************************-}
+
+module R_Curve(lnr,hold, acc, dec, accdec, decacc) where
+
+import R_Ptypes
+import R_Constants
+import R_Utility
+import R_Picture
+import R_Behaviour
+
+ -- lnr takes the start, finish and the number of intervals and
+ -- produces a linear list of ints going from the start to finish.
+lnr :: Int -> Int -> Int ->[Int]
+lnr start fin n = take n [start,(start+step)..]
+ where step = ((fin-start)`div`(n-1))
+
+ -- hold produces an infinite number of ints starting at v, modified
+ -- by step every time.
+hold :: Int -> Int -> [Int]
+hold v step = [v,v+step..]
+
+ -- acc accelerates from 0 to the max in n steps.
+acc :: Int -> Int -> Int -> [Int]
+acc min max n = min:acc' min (max-min) n 1
+
+acc' :: Int -> Int -> Int -> Int -> [Int]
+acc' min max n c | (c>n) = []
+acc' min max n c = (min + (((max*c*c) `div` (n*n))))
+ : (acc' min max n (c+1))
+
+
+ -- dec decelerates from the max to 0 in n steps.
+dec :: Int -> Int -> Int -> [Int]
+dec min max n = reverse (acc min max n)
+
+ -- accdec accelerates from start up to max and back to fin, in an steps
+ -- accelerating and dn steps decelerating
+accdec :: Int -> Int -> Int -> Int -> Int -> [Int]
+accdec start max fin an dn = (acc start max an)++(tail (dec fin max dn))
+
+ -- decacc decelerates from start to min in dn steps and then accelerates
+ -- back up to fin in an more steps
+decacc :: Int -> Int -> Int -> Int -> Int -> [Int]
+decacc start min fin dn an = (dec min start dn)++(tail (acc min fin an))
+
+
+
+
+
diff --git a/progs/demo/X11/animation/r_curve.hu b/progs/demo/X11/animation/r_curve.hu
new file mode 100644
index 0000000..9aa9629
--- /dev/null
+++ b/progs/demo/X11/animation/r_curve.hu
@@ -0,0 +1,3 @@
+:o= all
+r_curve.hs
+r_behaviour.hu
diff --git a/progs/demo/X11/animation/r_defaults.hs b/progs/demo/X11/animation/r_defaults.hs
new file mode 100644
index 0000000..1b7070a
--- /dev/null
+++ b/progs/demo/X11/animation/r_defaults.hs
@@ -0,0 +1,76 @@
+{-****************************************************************
+ MODULE R_DEFAULTS
+
+ This module uses the R_Behaviour module to define convient and
+ easy to use behaviours. These aren't very sophistated, but they
+ can be used to quickly animate a movie. For more sophistated
+ animation, a similiar library of sophistocated personnalized
+ functions can be created.
+
+******************************************************************-}
+
+module R_Defaults (big, huge, bigger, smaller, ccw, cw,
+ up, down, left, right,small,tiny)
+where
+
+import R_Ptypes
+import R_Constants
+import R_Utility
+import R_Picture
+import R_Behaviour
+
+
+ -- big scales everything up by the scaleunit (now 12/11ths)
+big :: Behaviour
+big = [scale_Pic x | x <- [scaleunit,scaleunit..]]
+
+ -- huge scales everything up by twice the scaleunit (24/11ths)
+huge :: Behaviour
+huge= [scale_Pic x | x <- [scaleunit*2,(scaleunit*2)..]]
+
+ -- small scales everything down by 10/11ths
+small :: Behaviour
+small = [scale_Pic x | x <- [s,s..]]
+ where s = 10
+
+ -- tiny scales everything down by 5/11ths
+tiny :: Behaviour
+tiny = [scale_Pic x | x <- [s,s..]]
+ where s = 5
+
+ -- bigger causes the Pics to be scaled up by 12/11ths,24/11ths,36/11ths
+ -- and so on, everincreasing.
+bigger :: Behaviour
+bigger = [scale_Pic x | x <- (rept (\x -> div (x*scaleunit) 11) 1)]
+
+ -- smaller causes the Pics to be scaled downwards in ever decreasing
+ -- amounts.
+smaller :: Behaviour
+smaller = [scale_Pic x | x <- (rept (\x -> div (x*10) 11) 1)]
+
+ -- a hardwired version of ccw that rotates the Pics by one rotunit
+ -- more every Pic, counterclockwise.
+ccw :: Behaviour
+ccw = [twist_Pic x | x <- [0.0,rotunit..]]
+
+ -- same as ccw, but rotates the Pics clockwise
+cw :: Behaviour
+cw = [twist_Pic x | x <- [0.0,-rotunit..]]
+
+ -- moves the Pic up by one more unit every Pic.
+up :: Behaviour
+up = [mov_Pic (x,y) | (x,y)<- zip2 [0,0..] [0,unit..]]
+
+ -- moves the Pic down by one more unit every Pic.
+down :: Behaviour
+down = [mov_Pic (x,y) | (x,y)<-zip2 [0,0..] [0,-unit]]
+
+ -- moves the Pic left by one more unit every Pic.
+left :: Behaviour
+left = [mov_Pic (x,y) | (x,y)<- zip2 [0,-unit..] [0,0..]]
+
+ -- moves the Pic right by one more unit every Pic.
+right :: Behaviour
+right = [mov_Pic (x,y) | (x,y)<- zip2 [0,unit..] [0,0..]]
+
+
diff --git a/progs/demo/X11/animation/r_defaults.hu b/progs/demo/X11/animation/r_defaults.hu
new file mode 100644
index 0000000..f945bbc
--- /dev/null
+++ b/progs/demo/X11/animation/r_defaults.hu
@@ -0,0 +1,3 @@
+:o= all
+r_defaults.hs
+r_behaviour.hu
diff --git a/progs/demo/X11/animation/r_display.hs b/progs/demo/X11/animation/r_display.hs
new file mode 100644
index 0000000..19f1d4a
--- /dev/null
+++ b/progs/demo/X11/animation/r_display.hs
@@ -0,0 +1,114 @@
+module R_Display (displaym) where
+
+import R_Ptypes
+import R_Utility
+import Xlib
+import R_Constants
+
+displaym :: String -> Int -> Movie -> IO ()
+
+displaym host n movie =
+ let
+ movie' = cycle (take n (map (map translatePoly) movie))
+ in
+ xOpenDisplay host
+ `thenIO` \ display ->
+ let (screen:_) = xDisplayRoots display
+ fg_color = xScreenBlackPixel screen
+ bg_color = xScreenWhitePixel screen
+ color_map = xScreenDefaultColormap screen
+ getPixels [] = returnIO []
+ getPixels (c:cs) =
+ xLookupColor color_map c `thenIO` \ (xc, _) ->
+ xAllocColor color_map xc `thenIO` \ (p,_,_) ->
+ getPixels cs `thenIO` \ ps ->
+ returnIO (p:ps)
+ in
+ getPixels (map colorName allColors)
+ `thenIO` \ pixels ->
+ let
+ lookupPixel c = lookupPixel1 c allColors pixels
+
+ lookupPixel1 x [] _ = head pixels
+ lookupPixel1 x (c:cs) (p:ps) =
+ if x == c then p
+ else lookupPixel1 x cs ps
+ parent = xScreenRoot screen
+ in
+ xMArrayCreate [lookupPixel i | i <- [0..15]]
+ `thenIO` \ pixelArray ->
+ xCreateGcontext (XDrawWindow parent)
+ [XGCBackground bg_color,
+ XGCForeground fg_color]
+ `thenIO` \ gcontext ->
+ xCreateGcontext (XDrawWindow parent)
+ [XGCBackground bg_color,
+ XGCForeground bg_color]
+ `thenIO` \ blank_gcontext ->
+ xCreateWindow parent
+ (XRect 100 100 500 500)
+ [XWinBackground bg_color,
+ XWinEventMask (XEventMask [XButtonPress])]
+ `thenIO` \window ->
+ let depth = xDrawableDepth (XDrawWindow window)
+ in
+ xCreatePixmap (XSize 500 500) depth (XDrawWindow parent)
+ `thenIO` \ pixmap ->
+ xMapWindow window
+ `thenIO` \() ->
+ let
+ dispFrame m =
+ xDrawRectangle (XDrawPixmap pixmap)
+ blank_gcontext
+ (XRect 0 0 500 500)
+ True
+ `thenIO_`
+ dispPic m
+ `thenIO_`
+ xCopyArea (XDrawPixmap pixmap) gcontext (XRect 0 0 500 500)
+ (XDrawWindow window) (XPoint 0 0)
+ `thenIO_`
+ xDisplayForceOutput display
+
+ dispPic [] = returnIO ()
+ dispPic (p:ps) = dispPoly p `thenIO_` dispPic ps
+
+ dispPoly (c, vec) =
+-- xLookupColor color_map (colorName c) `thenIO` \ ec ->
+-- xAllocColor color_map ec `thenIO` \ p ->
+ xMArrayLookup pixelArray c `thenIO` \p ->
+ xUpdateGcontext gcontext [XGCForeground p] `thenIO` \ () ->
+-- xSetGcontextForeground gcontext (lookupPixel c) `thenIO` \ () ->
+ xDrawLines (XDrawPixmap pixmap) gcontext vec True
+
+ untilButton3 (frame:frames) =
+ let
+ action = dispFrame frame `thenIO_` untilButton3 frames
+ in
+ xEventListen display `thenIO` \count ->
+ if count == 0 then action else
+ xGetEvent display `thenIO` \event ->
+ case (xEventType event) of
+ XButtonPressEvent ->
+ case (xEventCode event) of
+ 3 -> returnIO ()
+ _ -> action
+ _ -> action
+ in
+ printString ("Click right button to end.\n") `thenIO_`
+ untilButton3 movie' `thenIO_`
+ xFreePixmap pixmap `thenIO_`
+ xCloseDisplay display
+
+type Movie' = [Pic']
+type Pic' = [Poly']
+type Poly' = (Int, [XPoint])
+
+translatePoly :: Poly -> Poly'
+translatePoly (c, vs) = (c, flatten_2 vs)
+
+flatten_2 [] = []
+flatten_2 ((a,b):r) = (XPoint (a `div` 2) (b `div` 2)):(flatten_2 r)
+
+printString :: String -> IO ()
+printString s = appendChan "stdout" s abort (returnIO ())
diff --git a/progs/demo/X11/animation/r_display.hu b/progs/demo/X11/animation/r_display.hu
new file mode 100644
index 0000000..23f2c77
--- /dev/null
+++ b/progs/demo/X11/animation/r_display.hu
@@ -0,0 +1,6 @@
+:o= foldr inline constant
+r_constants.hu
+r_utility.hu
+r_ptypes.hu
+r_display.hs
+$HASKELL_LIBRARY/X11/xlib.hu
diff --git a/progs/demo/X11/animation/r_inbetween.hs b/progs/demo/X11/animation/r_inbetween.hs
new file mode 100644
index 0000000..a7fb7d3
--- /dev/null
+++ b/progs/demo/X11/animation/r_inbetween.hs
@@ -0,0 +1,82 @@
+{-******************************************************************
+ MODULE R_INBETWEEN
+
+ This module takes care of interpolation functions. Basically,
+ given two Pics, inbetween will give you a movie gradually
+ converting from one Pic to the other Pic, using linear interpolation.
+ Tween will take two Movies, and append them, interpolating n
+ frames between the last Pic of the first Movie and the first Pic of
+ the last Movie.
+
+******************************************************************-}
+
+module R_Inbetween (inbetween,tween) where
+
+import R_Ptypes
+import R_Utility
+import R_Picture
+import R_Behaviour
+
+ -- inbetween takes an int and two Pics, and interpolates n Pics
+ -- of interpolated Pics.
+inbetween :: Int -> Pic -> Pic -> Movie
+inbetween n p1 p2 | (length p1 == length p2) =
+ ((zip1.(map (inbetweenp n))).zip1) [p1,p2]
+inbetween n p1 p2 = inbetween n [(col,p1')] [(col,p2')]
+ where p1' = concat [ vs | (c,vs) <- p1]
+ p2' = concat [ vs | (c,vs) <- p2]
+ col = head [ c | (c,vs) <- p1 ]
+
+ -- inbetweenp takes a list of 2 Polygons ([[Vec]]) and returns a
+ -- sequence of interpolated Polygons. Should the Number of vertices
+ -- of one Polygon be less than those in the other, it splits it so
+ -- as to have two Polygons of the same length.
+inbetweenp :: Int -> Pic -> Pic
+inbetweenp n [(c1,vs),(c2,ws)] =
+ if ((length vs) < (length ws)) then
+ inbetween1 (split (length ws) (c1,vs)) (c2,ws) 0 n
+ else if ((length vs) > (length ws)) then
+ inbetween1 (c1,vs) (split (length vs) (c2,ws)) 0 n
+ else inbetween1 (c1,vs) (c2,ws) 0 n
+
+
+ -- inbetween1 returns a sequence of interpolated Polygons.
+inbetween1 :: Poly -> Poly -> Int -> Int -> Pic
+inbetween1 p1 p2 m n | m>n || n<=0 = []
+inbetween1 p1 p2 m n = inbetween2 p1 p2 m n
+ :inbetween1 p1 p2 (m+1) n
+
+ -- inbetween2 returns ONE of the required sequence of
+ -- interpolated Polygons.
+inbetween2 :: Poly -> Poly -> Int -> Int -> Poly
+inbetween2 (c1,vs) (c2,ws) p q = (c1, map (partway p q) (zip1 [vs,ws]))
+
+ -- split splits up a Polygon so as to have the given #vertices.
+split :: Int -> Poly -> Poly
+split n (c,vs) = (c, split' n vs)
+
+split' :: Int -> [Vec] -> [Vec]
+split' n vs | n<= (length vs) = vs
+split' n vs = if (n>double) then
+ split' n (split' double vs)
+ else
+ v1:(mid v1 v2):(split' (n-2) (v2:vss))
+ where double = 2*((length vs)) - 1
+ (v1:v2:vss) = vs
+
+
+ -- tween will interpolate n Pics transforming the last Pic of
+ -- the first Movie into the first Pic of the second Movie, and
+ -- then run the second Movie
+tween :: Int -> Movie -> Movie -> Movie
+tween n m1 [] = m1
+tween n m1 m2 = m1 ++ (inbetween n (last m1) (head m2')) ++ (tail m2')
+ where m2' = apply (mov (repeat v)) m2
+ v = vmin (orig_Pic (last m1)) (orig_Pic (head m2))
+
+ -- tweens will take a list of Movies and append them all, interpolating
+ -- n frames between every Movie.
+tweens :: Int -> [Movie] -> Movie
+tweens n = foldr (tween n) []
+
+
diff --git a/progs/demo/X11/animation/r_inbetween.hu b/progs/demo/X11/animation/r_inbetween.hu
new file mode 100644
index 0000000..52771d0
--- /dev/null
+++ b/progs/demo/X11/animation/r_inbetween.hu
@@ -0,0 +1,3 @@
+:o= all
+r_inbetween.hs
+r_behaviour.hu
diff --git a/progs/demo/X11/animation/r_movie.hs b/progs/demo/X11/animation/r_movie.hs
new file mode 100644
index 0000000..a97a452
--- /dev/null
+++ b/progs/demo/X11/animation/r_movie.hs
@@ -0,0 +1,114 @@
+{-*********************************************************************
+ MODULE R_MOVIE
+
+ This module contains necessary functions for editing Movies. There
+ are several that give information on a Movie, such as the heights or
+ wirdths of its Pics. The others all deal with the various ways of
+ combining various Movies into one Movie, a vital set of functions.
+
+*********************************************************************-}
+
+module R_Movie (ht, wid, orig,
+ above, rABOVE, beside, rBESIDE,rBESIDE2, over, rOVER,
+ overlay, rOVERLAY, pUT,
+ uncurry, curry
+ ) where
+
+import R_Ptypes
+import R_Constants
+import R_Utility
+import R_Picture
+
+ -- takes a function and a list and returns a new list of element operated
+ -- on by the function.
+promote:: (a->b)->[a]->[b]
+promote f [] = []
+promote f [p] = f p:promote f [p]
+promote f (p:ps) = f p:promote f ps
+
+ -- promote1 takes a function that analyzes a Pic, and then applies it
+ -- to analyse a movie, returning a list.
+promote1:: (Pic->a) -> Movie -> [a]
+promote1 f ps = [f p | p <- ps]
+
+ -- ht takes a Movie and returns a list of the heights of the Pics
+ht :: Movie -> [Int]
+ht = promote1 ht_Pic
+
+ -- wid takes a Movie and returns a list of the widths of the Pics
+wid :: Movie -> [Int]
+wid = promote1 wid_Pic
+
+ -- orig takes a Movie and returns a list of vectors that are the
+ -- origins of the Pics
+orig:: Movie -> [Vec]
+orig = promote1 orig_Pic
+
+ -- promote2 takes a function accepting an element and a Pic, and
+ -- applies the function to the Movie and list, producing a new Movie
+promote2:: (a->Pic->Pic) -> [a] -> Movie -> Movie
+promote2 f ps qs = [f p q | (p,q) <- zip2 ps qs]
+
+ -- takes two Movies and puts them above one another
+above:: Movie -> Movie -> Movie
+above = promote2 above_Pic
+
+ -- takes a list of Movies and puts them all above one another
+rABOVE:: [Movie] -> Movie
+rABOVE = reduce above
+
+ -- takes two Movies and puts them beside one another
+beside:: Movie -> Movie -> Movie
+beside = promote2 beside_Pic
+
+ -- takes a list of Movies and puts them all beside one another
+rBESIDE:: [Movie] -> Movie
+rBESIDE = reduce beside
+
+ -- same as beside, but with absolute coordinates.
+beside2:: Movie -> Movie -> Movie
+beside2 = promote2 beside2_Pic
+
+ -- same as rBESIDE, but with absolute coordinates.
+rBESIDE2:: [Movie] -> Movie
+rBESIDE2 = reduce beside2
+
+ -- puts one Movie on top of the other Movie
+over:: Movie -> Movie -> Movie
+over = promote2 over_Pic
+
+ -- takes a list of Movies, and puts the n-th on top of the first
+ -- through 9n-1)th.
+rOVER:: [Movie] -> Movie
+rOVER = reduce over
+
+ -- just overlays the two Movies by appending the Pics.
+overlay:: Movie -> Movie -> Movie
+overlay = promote2 overlay_Pic
+
+ -- overlays a list of Movies by appending the Pics
+rOVERLAY:: [Movie] -> Movie
+rOVERLAY = reduce overlay
+
+ -- promote3 takes a function that takes two items and a Pic and
+ -- returns a Pic, and then applies it to two input lists and a Movie,
+ -- producing a new Movie.
+promote3:: (a->b->Pic->Pic) -> [a] -> [b] -> Movie -> Movie
+promote3 f ps qs rs = [f p q r | (p,q,r) <- zip3 ps qs rs]
+
+ -- pUT takes a list of Vectors, and puts each Pic of the first Movie
+ -- in the location of the corresponding vector, on top of the Pic of
+ -- the second Movie, and returns that list as a new Movie.
+pUT:: [Vec] -> Movie -> Movie -> Movie
+pUT = promote3 put_Pic
+
+ -- uncurry takes a function that takes two elements and a list of
+ -- two elements and applies the function to them.
+uncurry:: (a->a->b) -> [a] -> b
+uncurry f [a,b] = f a b
+
+ -- curry takes a function that takes a list, and two elements, and
+ -- then applies the function to the elements in a list.
+curry:: ([a]->b) -> a -> a -> b
+curry f a b = f [a,b]
+
diff --git a/progs/demo/X11/animation/r_movie.hu b/progs/demo/X11/animation/r_movie.hu
new file mode 100644
index 0000000..0023a04
--- /dev/null
+++ b/progs/demo/X11/animation/r_movie.hu
@@ -0,0 +1,3 @@
+:o= all
+r_movie.hs
+r_picture.hu
diff --git a/progs/demo/X11/animation/r_picture.hs b/progs/demo/X11/animation/r_picture.hs
new file mode 100644
index 0000000..ed3a50f
--- /dev/null
+++ b/progs/demo/X11/animation/r_picture.hs
@@ -0,0 +1,188 @@
+{-************************************************************
+ MODULE R_PICTURE
+
+ This module contains all the functions that can be used to manipulate
+ Pic's. The user will probably never use any of these functions. They
+ are used by Behaviours and such higher-order functions, which apply
+ these routines to all the Pic's in the list.
+
+*************************************************************-}
+
+module R_Picture (close_Pic, ht_Pic, wid_Pic, orig_Pic,
+ overlay_Pic, put_Pic, over_Pic, above_Pic, beside_Pic,
+ map_Pic,beside2_Pic,
+ scale_Pic, scale_rel_Pic, mov_Pic, rot_Pic, twist_Pic,
+ twist_Pic', flipx_Pic, flipy_Pic, flip_Pic, {- flock_Pic, -}
+ set_Color_Pic,
+ to_orig_Pic,
+ movto_Pic
+ ) where
+
+import R_Ptypes
+import R_Constants
+import R_Utility
+
+ -- close_Pic makes sure that the polygon is closed
+close_Pic:: Pic -> Pic
+close_Pic p = map close_Poly p
+ where
+ close_Poly (c,ply) | (head ply) == (last ply) = (c,ply)
+ close_Poly (c,ply) = (c,ply++(tail (reverse ply)))
+
+ --these functions find the max and min x and y coordinates of a Pic
+maxx :: Pic -> Int
+maxx p = reduce max [x | (c,q) <- p, (x,y) <- q]
+
+minx :: Pic -> Int
+minx p = reduce min [x | (c,q) <- p, (x,y) <- q]
+
+maxy :: Pic -> Int
+maxy p = reduce max [y | (c,q) <- p, (x,y) <- q]
+
+miny :: Pic -> Int
+miny p = reduce min [y | (c,q) <- p, (x,y) <- q]
+
+ -- these functions find the height, width and origin of a Pic
+ht_Pic :: Pic -> Int
+ht_Pic p = (maxy p) - (miny p)
+
+wid_Pic :: Pic -> Int
+wid_Pic p = (maxx p) - (minx p)
+
+orig_Pic:: Pic -> Vec
+orig_Pic p = ( (maxx p + minx p) `div` 2, (maxy p + miny p) `div` 2 )
+
+-- PICTURE COMBINING OPERATIONS:
+
+ -- overlay_Pic just takes 2 Pics and puts them together into one
+overlay_Pic:: Pic -> Pic -> Pic
+overlay_Pic p q = p ++ q
+
+ -- put_Pic overlays the Pics, offsetting the first Pic by a vector
+ -- amount from the origin of the second
+put_Pic:: Vec -> Pic -> Pic -> Pic
+put_Pic v p q = overlay_Pic
+ (movto_Pic (vplus (orig_Pic q) v) p )
+ q
+
+ -- over_Pic puts one Pic directly on top of the other
+over_Pic:: Pic -> Pic -> Pic
+over_Pic p q = put_Pic (0,0) p q
+
+ -- above_Pic puts the first Pic on top of the second
+above_Pic:: Pic -> Pic -> Pic
+above_Pic p q = put_Pic (0,(((ht_Pic q) + (ht_Pic p)) `div` 2)) p q
+
+ -- beside_Pic puts the first Pic beside the second. The width of
+ -- the Pic is defined as the max x minus the min x, so a moving
+ -- figure will stand still in this implementation
+beside_Pic:: Pic -> Pic -> Pic
+beside_Pic p q = put_Pic (((wid_Pic q)+(wid_Pic p)) `div` 2, 0) p q
+
+ -- beside2_Pic puts the first Pic beside the second, without
+ -- shifting to the width of the Pic. It uses the absolute coordinates.
+beside2_Pic:: Pic -> Pic -> Pic
+beside2_Pic p q = put ((wid_Pic q), 0) p q
+ where put v p q = overlay_Pic (mov_Pic v p) q
+
+
+ -- The following maps a given function over the Vector-list of each Polygon:
+map_Pic:: (Vec -> Vec) -> Pic -> Pic
+map_Pic f p = map f' p
+ where f' (c,vs) = (c, map f vs)
+
+-- THE GEOMETRIC TRANSFORMATIONS:
+
+ -- scales the Pic by r, where r is in units of 11th. ie r=1, the Pic is
+ -- scaled by 1/11 to its origin.
+scale_Pic :: Int -> Pic -> Pic
+scale_Pic r p
+ = map_Pic (scalep r) p
+ where scalep r (v1,v2) = (div ((r*(v1-dx))+dx) 11,div ((r*(v2-dy))+dy) 11)
+ dx = fst (orig_Pic p)
+ dy = snd (orig_Pic p)
+
+ -- this is another scaling function, but it centers the image at the Vec
+scale_rel_Pic :: Vec -> Int -> Pic -> Pic
+scale_rel_Pic v r
+ = map_Pic (scalep r)
+ where scalep r (v1,v2) = (div ((r*(v1-dx))+dx) 11,div ((r*(v2-dy))+dy) 11)
+ dx = fst v
+ dy = snd v
+
+ -- moves a Pic by the vector amount
+mov_Pic:: Vec -> Pic -> Pic
+mov_Pic v = map_Pic (vplus v)
+
+ -- moves a Pic to the vector
+movto_Pic:: Vec -> Pic -> Pic
+movto_Pic v p = mov_Pic (vmin v (orig_Pic p)) p
+
+ -- moves the origin of the Pic to the lower left side of the Pic
+to_orig_Pic:: Pic -> Pic
+to_orig_Pic p = mov_Pic (-mx,-my) p
+ where mx = minx p
+ my = miny p
+
+ -- rotates the Pic about the Vector by theta
+rot_Pic :: Vec -> Float -> Pic -> Pic
+rot_Pic (a,b) theta
+ = map_Pic (rotp (a,b) theta)
+ where rotp (a,b) t (v1,v2)
+ = vftov (a2+ (u * cos theta - v * sin theta),
+ b2+ (u * sin theta + v * cos theta))
+ where u = u1 -a2
+ v = u2 -b2
+ (u1,u2) = vtovf (v1,v2)
+ (a2,b2) = vtovf (a,b)
+
+ -- rotates a Pic about its origin by theta
+twist_Pic :: Float -> Pic -> Pic
+twist_Pic theta p = rot_Pic (orig_Pic p) theta p
+
+
+ -- hardwired version of rot_Pic that runs faster by rotating a set
+ -- unit, the rotunit, every time
+rot_Pic':: Vec -> Pic -> Pic
+rot_Pic' (a,b) = map_Pic (rotp (a,b))
+ where rotp (a,b) (v1,v2)
+ = vftov (a2+ (u * cosunit - v * sinunit),
+ b2+ (u * sinunit + v * cosunit))
+ where u = u1-a2
+ v = u2-b2
+ (u1,u2) = vtovf (v1,v2)
+ (a2,b2) = vtovf (a,b)
+
+ -- hardwired version of twist_Pic that runs faster using rot_Pic'
+twist_Pic':: Pic -> Pic
+twist_Pic' p = rot_Pic' (orig_Pic p) p
+
+ -- flips the Pic about the line x=n (x-coordinates change)
+flipx_Pic :: Int -> Pic -> Pic
+flipx_Pic n = map_Pic (flipvx n)
+ where
+ flipvx n (a,b) = (2*(n-a)+a,b)
+
+ -- flips the Pic about the line y=n (y-coordinates change)
+flipy_Pic :: Int -> Pic -> Pic
+flipy_Pic n = map_Pic (flipvy n)
+ where
+ flipvy n (a,b) = (a, 2*(n-b)+b)
+
+ -- flips the Pic about its own x origin.
+flip_Pic:: Pic -> Pic
+flip_Pic p = map_Pic (flipvx x) p
+ where (x,y) = orig_Pic p
+ flipvx n (a,b) = (2*(n-a)+a,b)
+
+ -- copies the Pic into another Pic n*n times in an n by n array pattern
+flock_Pic :: Int -> Pic -> Pic
+flock_Pic 1 p = p
+flock_Pic (n+2) p = beside_Pic (flock_Pic (n-1) p) (row n p)
+ where row n p = replicate n above_Pic nullpic p
+
+ -- changes the color of the Pic
+set_Color_Pic:: Color -> Pic -> Pic
+set_Color_Pic c p = map f p
+ where f (c',vs) = (c,vs)
+
diff --git a/progs/demo/X11/animation/r_picture.hu b/progs/demo/X11/animation/r_picture.hu
new file mode 100644
index 0000000..932d87c
--- /dev/null
+++ b/progs/demo/X11/animation/r_picture.hu
@@ -0,0 +1,4 @@
+:o= all
+r_picture.hs
+r_constants.hu
+r_utility.hu
diff --git a/progs/demo/X11/animation/r_ptypes.hs b/progs/demo/X11/animation/r_ptypes.hs
new file mode 100644
index 0000000..c020f82
--- /dev/null
+++ b/progs/demo/X11/animation/r_ptypes.hs
@@ -0,0 +1,67 @@
+{-***********************************************************************
+ MODULE PTYPES
+
+ This module contains the definitions for all the basic datatypes used to
+ create functional movies.
+ The basis of all the images is the Poly, which is a tuple of a color
+ and a list of points. This is displayed as a polygon of that color. The
+ form is a line drawn to each of the points, in order.
+ A list of these Poly's is a Pic, or picture. Each picture is a single
+ frame of the movie. A list of Pic's makes up a Movie, which is a series
+ of Pic's displayed in order.
+ Behaviours affect the movies, such as moving them left, or right.
+ PictoPic's affect a single picture.
+ The other functions simply convert regular values such as integers
+ and floats to the datatypes used by the functional programming.
+
+************************************************************************-}
+
+
+module R_Ptypes (Vec(..), Color(..), Pic(..), Poly(..), Movie(..), Behaviour(..), PictoPic(..), Process(..),
+ Vecfloat(..),
+ Msg(..), Chan(..),
+ Val (..),
+ ntov, vtov, nstov, vstov, pstov, bstov
+ ) where
+
+
+ --These are the basic data types for storing and manipulating the movies.
+
+type Vec = (Int,Int)
+type Color = Int
+type Pic = [Poly]
+type Poly = (Color,[Vec])
+type Movie = [Pic]
+type Behaviour = [Pic -> Pic]
+type PictoPic = Pic -> Pic
+
+type Process = [Msg] -> [Msg]
+type Msg = [(Chan,Val)]
+type Chan = [Char]
+
+data Val = N Int | V (Int,Int) | P Pic | B PictoPic
+
+type Vecfloat = (Float,Float)
+
+
+
+--Those convert from the various regular values to Val's.
+
+ntov n = N n
+
+vtov:: Vec -> Val
+vtov v = V v
+
+ptov:: Pic -> Val
+ptov p = P p
+
+nstov ns = [N n|n<-ns]
+
+vstov:: [Vec] -> [Val]
+vstov vs = [V v|v<-vs]
+
+pstov:: [Pic] -> [Val]
+pstov ps = [P p|p<-ps]
+
+bstov:: [PictoPic] -> [Val]
+bstov bs = [B b|b<-bs]
diff --git a/progs/demo/X11/animation/r_ptypes.hu b/progs/demo/X11/animation/r_ptypes.hu
new file mode 100644
index 0000000..8a99f8f
--- /dev/null
+++ b/progs/demo/X11/animation/r_ptypes.hu
@@ -0,0 +1,2 @@
+:o= all
+r_ptypes.hs
diff --git a/progs/demo/X11/animation/r_shapes.hs b/progs/demo/X11/animation/r_shapes.hs
new file mode 100644
index 0000000..aef3362
--- /dev/null
+++ b/progs/demo/X11/animation/r_shapes.hs
@@ -0,0 +1,38 @@
+{-*****************************************************************
+ MODULE R_SHAPES
+
+ This modules produces Pic's of boxes and triangles to help build
+ Pic's to animate.
+
+******************************************************************-}
+
+module R_Shapes (box, tri, circ_mov, circ) where
+
+import R_Ptypes
+import R_Utility
+import R_Picture
+import R_Behaviour
+
+ -- box takes four three ints, the color, width and height of the box and
+ -- returns a Pic of a box
+box :: Int -> Int -> Int -> Pic
+box c width height= [(c,[(0,0),(width,0),(width,height),(0,height),(0,0)])]
+
+ -- tri takes a color and three vectors, and returns a Pic of a triangle
+ -- with the vectors as vertices
+tri:: Color -> Vec -> Vec -> Vec -> Pic
+tri c (x1,y1) (x2,y2) (x3,y3) = [(c,[(x1,y1),(x2,y2),(x3,y3),(x1,y1)])]
+
+
+ -- circ takes a color, the radius
+circ :: Color -> Int -> Int -> Pic
+circ c r inc = [(c,(r+r,r):(circ' r' inc' 1.0))]
+ where r' = (fromIntegral r)
+ inc' = (fromIntegral inc)
+
+circ' :: Float -> Float -> Float -> [Vec]
+circ' r inc c | c>inc = []
+circ' r inc c = vftov (x+r,y+r) : (circ' r inc (c+1.0))
+ where x = r*(cos((2*c*pi)/inc))
+ y = r*(sin((2*c*pi)/inc))
+
diff --git a/progs/demo/X11/animation/r_shapes.hu b/progs/demo/X11/animation/r_shapes.hu
new file mode 100644
index 0000000..ad0bf40
--- /dev/null
+++ b/progs/demo/X11/animation/r_shapes.hu
@@ -0,0 +1,3 @@
+:o= all
+r_shapes.hs
+r_behaviour.hu
diff --git a/progs/demo/X11/animation/r_utility.hs b/progs/demo/X11/animation/r_utility.hs
new file mode 100644
index 0000000..9dfcc65
--- /dev/null
+++ b/progs/demo/X11/animation/r_utility.hs
@@ -0,0 +1,150 @@
+{-*********************************************************************
+ MODULE R_UTILITY
+
+ This module contains all the basic utility functions that the other
+ modules need to have to write their code. These are made generally
+ low level functions, manipulating vectors or defining very
+ general functions
+
+**********************************************************************-}
+
+
+module R_Utility (vtovf,vftov,
+ vplus, vmin, mid, partway,
+ mag,
+ reduce, power, i,
+ member, repeat, zip1, zip2, zip3, rept, replicate,
+ mapc,
+ append, flatten, rptseq, osc
+ ) where
+
+import R_Ptypes
+
+
+-- CONVERSION
+
+ -- vtovf takes a vector of integers, and converts it to a vector of floats
+vtovf :: Vec -> Vecfloat
+vtovf (x,y) = (fromIntegral x,fromIntegral y)
+
+ -- vftov takes a vector of floats and converts it to a vector of integers.
+ -- It rounds the floats off to do this.
+vftov :: Vecfloat -> Vec
+vftov (x,y) = (round x,round y)
+
+
+-- VECTOR OPERATIONS:
+
+ -- vector addition
+vplus:: Vec -> Vec -> Vec
+vplus (a,b) (c,d) = (a+c,b+d)
+
+ -- vector substraction
+vmin:: Vec -> Vec -> Vec
+vmin (a,b) (c,d) = (a-c,b-d)
+
+ -- finds the midpoint between two vectors
+mid:: Vec -> Vec -> Vec
+mid (x1,y1) (x2,y2) = (div (x1+x2) 2,div (y1+y2) 2 )
+
+ -- finds a point p/q along the way between two vectors
+partway :: Int -> Int -> [Vec] -> Vec
+partway p q [(x1,y1),(x2,y2)]
+ = vplus (x1,y1) ( div (p*(x2-x1)) q, div (p*(y2-y1)) q )
+
+ -- finds the magnitude of two vectors
+mag :: Vec -> Int
+mag p = round (magfloat (vtovf p))
+
+magfloat :: Vecfloat -> Float
+magfloat (x,y) = sqrt (x*x + y*y)
+
+ -- returns a vector at right angles to the input vector
+normal:: Vec -> Vec
+normal (x,y) = (-y,x)
+
+ -- returns the first vector projected onto the second
+project:: Vec -> Vec -> Vec
+project (vx,vy) (wx,wy) = partway (vx*wx+vy*wy) (mw*mw) [(0,0),(wx,wy)]
+ where mw = mag (wx,wy)
+
+
+-- HIGHER-ORDER FUNCTIONS:
+
+ -- just foldr1. It applies a function of two inputs to an entire list
+ -- recursively, and displays the single element result
+reduce :: (a->a->a) -> [a] -> a
+reduce = foldr1
+
+ -- power applies a single function n times to a seed
+power :: Int -> (a->a) -> a -> a
+power 0 f seed = seed
+power (n+1) f seed = f (power n f seed)
+
+ -- i takes an element and returns an infinite list of them
+i :: a -> [a]
+i x = x: (i x)
+
+ -- checks to see if x is in the list of xs
+member :: (Eq a) => [a] -> a -> Bool
+member [] x = False
+member (y:ys) x = x == y || member ys x
+
+ -- zip1 takes lists of lists, and rearranges them so that all the first
+ -- elements are in the first list, all the second in the second and so on.
+zip1 :: (Eq a) => [[a]] -> [[a]]
+zip1 xs | member xs [] = []
+zip1 xs = (map head xs):(zip1 (map tail xs))
+
+ -- takes two lists and makes a list of tuples.
+zip2 :: [a] -> [b] -> [(a,b)]
+zip2=zip
+
+ -- rept takes a function and a list of elements, and applies the function
+ -- n-1 times to the n-th element
+rept :: (a->a) -> a -> [a]
+rept f x = x:(rept f (f x))
+
+ -- replicate creates an list n elements long of a, with the function
+ -- applies to the n-th element n-1 times.
+replicate :: Int -> (a->a->a) -> a -> a -> a
+replicate 0 f zero a = zero
+replicate 1 f zero a = a
+replicate (n+2) f zero a = f a (replicate (n+1) f zero a)
+
+ -- mapc is a map function for lists of functions (behaviours)
+mapc :: (a->b) -> [c->a] -> [c->b]
+mapc f as = [f.a | a <- as]
+
+
+-- FUNCTIONS OVER SEQUENCES:
+
+ -- append takes a list of lists, and makes them into one giant happy list.
+append :: [[a]] -> [a]
+append = foldr (++) []
+
+ -- flatten takes a list of lists of tuples and gives one giant happy list
+ -- of single elements back.
+flatten:: [[(a,a)]] -> [a]
+flatten s = foldr f [] (append s)
+ where f (x,y) [] = [x,y]
+ f (x,y) (z:zs) = x:y:(z:zs)
+
+ -- rptseq takes a list of elements and applies a function to them,
+ -- n-1 times for the n-th element, but using map
+rptseq :: (a->a) -> [a] -> [a]
+rptseq f [] = []
+rptseq f (x:xs) = x:rptseq f (map f xs)
+
+ -- osc takes a list, and makes sure it oscillates. If the head is
+ -- equal to the tail, it simply repeats the sequence infinitely. If
+ -- the head is not equal to the tail, it adds the sequence then adds
+ -- the reversed sequence minus the first and last elements, and then repeats
+osc :: [a] -> [a]
+osc s | (length s) == 0 = []
+osc s | (length s) == 1 = head s: osc s
+osc s = (s ++ (((tail.reverse).tail) s)) ++ (osc s)
+
+
+
+
diff --git a/progs/demo/X11/animation/r_utility.hu b/progs/demo/X11/animation/r_utility.hu
new file mode 100644
index 0000000..6fac189
--- /dev/null
+++ b/progs/demo/X11/animation/r_utility.hu
@@ -0,0 +1,3 @@
+:o= all
+r_utility.hs
+r_ptypes.hu
diff --git a/progs/demo/X11/animation/seafigs.hs b/progs/demo/X11/animation/seafigs.hs
new file mode 100644
index 0000000..c216a63
--- /dev/null
+++ b/progs/demo/X11/animation/seafigs.hs
@@ -0,0 +1,158 @@
+module Seafigs (sky,blue_sky,clouds,clouds2,gull,man,sun,vm,windmill,palm) where
+
+import Animation
+
+blue_sky:: Movie
+blue_sky = osc [box lightblue 1000 1000]
+
+sky:: Color -> Movie
+sky c = osc [box c 1000 1000]
+
+clouds2:: Movie
+clouds2 = apply (mov (i (cld_wid,0))) (rBESIDE[cld,cld])
+ where cld_wid = -(wid_Pic (cld!!0))
+ cld= apply (bPar [right,mov (repeat (250,-50))]) cldm1
+ cldm1=osc[cloud1]
+
+clouds:: Movie
+clouds
+ = rOVERLAY
+ [apply (bPar [right,mov (repeat (250,-50))]) cloudm1,
+ apply (bPar [right,mov (repeat (0,-50))]) cloudm2,
+ apply (bPar [right,mov (repeat (250,-75))]) cloudm2,
+ apply (bPar [right,flipb,smaller,mov(repeat (200,-100))]) cloudm2,
+ apply (bPar [right,flipb,smaller,mov(repeat (300,-125))]) cloudm1,
+ apply (bPar [right,right,mov (repeat (-50,50))]) cloudm1]
+ where cloudm1 = osc [cloud1]
+ cloudm2 = osc [cloud2]
+
+
+cloud1 = [(white,ply)]
+ where ply = [(142,301),(169,309),(180,315),(192,312),
+ (196,308),(202,302),(216,300),(224,308),
+ (238,312),(258,311),(274,301),(278,283),
+ (265,279),(246,279),(230,281),(197,286),
+ (185,288),(167,287),(148,287),(136,292),
+ (136,292),(142,301)]
+
+
+cloud2 = [(white,ply)]
+ where ply = [(51,262), (56,266),
+ (66,265), (90,264), (92,266), (98,270),
+ (111,268),(137,268),(155,266),(174,266),
+ (183,262),(183,253),(162,251),(136,254),
+ (132,250),(126,248),(115,252),(109,253),
+ (98,252), (90,253), (88,254), (67,254),
+ (56,252), (49,254), (47,259), (51,262)]
+
+gull :: Movie
+gull = osc [gull1,gull2]
+
+gull1 = [(black,[(2,4),(6,4),(9,2),(10,0),(11,2),
+ (16,4),(20,4)])]
+
+gull2 = [(black,[(0,0),(2,2),(6,3),(9,2),(12,3),
+ (16,2),(18,0)])]
+
+man :: Movie
+man = osc [man1,man2,man3]
+
+
+man1 = [(black,[(0,0),(10,0),(20,40),(30,60),(40,20),
+ (60,0),(50,0)]),
+ (black,[(0,40),(20,60),(30,80),(50,70),(60,60)]),
+ (black,[(30,60),(30,100)]),
+ (black,[(30,100),(25,100),(20,105),(23,112),
+ (20,115),(30,120),(35,120),(40,115),
+ (40,110),(35,105),(30,100)])
+ ]
+
+man2 = [(black,[(20,0),(30,0),(20,40),(30,60),(45,30),
+ (60,20),(50,0)]),
+ (black,[(0,60),(20,60),(20,80),(40,80),(50,60)]),
+ (black,[(30,60),(20,100)]),
+ (black,[(20,100),(15,100),(10,105),(13,112),
+ (10,115),(20,120),(30,120),(30,115),
+ (30,110),(25,105),(20,100)])
+ ]
+
+man3 = [(black,[(0,15),(5,10),(15,45),(30,60),(35,25),
+ (44,10),(35,0)]),
+ (black,[(10,40),(22,60),(20,80),(40,75),(45,44)]),
+ (black,[(30,60),(20,100)]),
+ (black,[(20,100),(19,100),(14,105),(17,112),
+ (14,115),(24,120),(34,120),(34,115),
+ (34,110),(29,105),(200,100)])
+ ]
+
+sun :: Movie
+sun = osc [sun']
+ where
+ sun' = reduce overlay_Pic [sun1,
+ twist_Pic (pi/24.0) sun1,
+ twist_Pic (pi/12.0) sun1]
+
+sun1 = [(yellow,[(43,16),(18,27),(9,51),(20,71),(42,81),
+ (66,73),(76,47),(69,25),(43,15),(43,16)])]
+
+vm :: Movie
+vm = osc[vm1,vm2]
+
+vm1 = beside_Pic (box brown 10 15)
+ (above_Pic light1 (box brown 40 80))
+ where light1 = box yellow 10 10
+
+vm2 = beside_Pic (box brown 10 15)
+ (reduce above_Pic [light,light2,box brown 40 80])
+ where light2 = over_Pic (box red 10 10) (box white 5 5)
+ light = [ (red,[(5,5), (10,2), (0,30),(5,5)]),
+ (red,[(20,2),(25,5),(30,30),(20,2)]),
+ (red,[(15,15),(20,15),(15,50),(10,25)])]
+
+windmill :: Movie
+windmill
+ = apply
+ (bpar (mov (repeat (unit*3,0))) (scale_rel (0,0) (repeat 3)))
+ (overlay body (apply (movto (repeat (100,400))) prop))
+
+blade = osc [tri red (0,0) (100,0) (50,300)]
+prop = apply cw fan
+
+fan = rOVERLAY [fan1,fan2,fan3,fan4]
+fan1 = blade
+fan2 = apply (rot (osc[(50,300)]) (osc[pi/2.0])) fan1
+fan3 = apply (rot (osc[(50,300)]) (osc[pi/2.0])) fan2
+fan4 = apply (rot (osc[(50,300)]) (osc[pi/2.0])) fan3
+
+body = osc [ [(brown,[(0,0),(200,0),(170,300),
+ (100,400),(30,300),(0,0)]) ] ]
+
+
+palm :: Movie
+palm
+ = osc palms
+ where palms = inbetween 3 palm1 (flipx_Pic 100 palm1)
+ palm1 = reduce overlay_Pic [trunk,frond1,frond2,frond3,frond4]
+ where frond1 = [ (green,[(50,60),(60,70),(80,60)]),
+ (green,[(50,70),(60,80),(80,70)]),
+ (green,[(50,80),(55,90),(70,80)]),
+ (green,[(60,70),(55,90),(50,100)]) ]
+
+ frond2 = flipx_Pic 50 frond1
+
+ frond3 = [ (green,[(10,70),(5,80)]),
+ (green,[(10,80),(10,90)]),
+ (green,[(20,90),(20,100)]),
+ (green,[(30,95),(40,104)]),
+ (green,[(5,80),(20,100),(40,104),
+ (50,100)])]
+
+ frond4 = [(green,[(0,100),(5,110)]),
+ (green,[(15,105),(15,115)]),
+ (green,[(25,105),(30,115)]),
+ (green,[(35,105),(40,115)]),
+ (green,[(5,110),(30,115),(50,110),
+ (50,100)])]
+
+ trunk = [(brown,[(100,0),(95,40),(80,80),
+ (70,90),(60,97),(50,100)])]
diff --git a/progs/demo/X11/animation/seafigs.hu b/progs/demo/X11/animation/seafigs.hu
new file mode 100644
index 0000000..83fcfcf
--- /dev/null
+++ b/progs/demo/X11/animation/seafigs.hu
@@ -0,0 +1,3 @@
+:o= all
+animation.hu
+seafigs.hs
diff --git a/progs/demo/X11/animation/seaside.hs b/progs/demo/X11/animation/seaside.hs
new file mode 100644
index 0000000..fe11e12
--- /dev/null
+++ b/progs/demo/X11/animation/seaside.hs
@@ -0,0 +1,25 @@
+module Seaside (main) where
+
+import Animation
+import Seafigs
+
+seaside :: Movie
+seaside = rOVERLAY [blue_sky,
+ apply (bPar [up,cw,movto (repeat botm)]) sun,
+ apply right clouds,
+ apply (bPar [right,bigger]) gull,
+ apply (bPar [right,right,bigger]) gull,
+ apply (bPar [up,up,right,bigger]) gull,
+ apply (bPar [up,right,right,right]) gull,
+ windm,
+ apply (mov (repeat botm)) palm,
+ man_and_vm
+ ]
+ where man_and_vm = rBESIDE2 [manfig, vm]
+ manfig = apply left (apply (mov (i (700,0)))
+ man)
+ windm = apply (mov (i (500,0))) windmill
+
+
+main = getEnv "DISPLAY" exit
+ (\ host -> displaym host 30 (map (flipy_Pic 500) seaside))
diff --git a/progs/demo/X11/animation/seaside.hu b/progs/demo/X11/animation/seaside.hu
new file mode 100644
index 0000000..df2c4b9
--- /dev/null
+++ b/progs/demo/X11/animation/seaside.hu
@@ -0,0 +1,5 @@
+:o= all
+seaside.hs
+seafigs.hu
+
+
diff --git a/progs/demo/X11/draw/README b/progs/demo/X11/draw/README
new file mode 100644
index 0000000..b844d2b
--- /dev/null
+++ b/progs/demo/X11/draw/README
@@ -0,0 +1 @@
+This is the draw program used in the X window documentation
diff --git a/progs/demo/X11/draw/draw.hs b/progs/demo/X11/draw/draw.hs
new file mode 100644
index 0000000..1ba68ce
--- /dev/null
+++ b/progs/demo/X11/draw/draw.hs
@@ -0,0 +1,41 @@
+module Draw where
+
+import Xlib
+
+main = getEnv "DISPLAY" exit (\ host -> draw host)
+
+draw :: String -> IO ()
+draw host =
+ xOpenDisplay host `thenIO` \ display ->
+ let (screen:_) = xDisplayRoots display
+ fg_color = xScreenBlackPixel screen
+ bg_color = xScreenWhitePixel screen
+ root = xScreenRoot screen
+ in
+ xCreateWindow root
+ (XRect 100 100 400 400)
+ [XWinBackground bg_color,
+ XWinEventMask (XEventMask [XButtonMotion,
+ XButtonPress,
+ XKeyPress])]
+ `thenIO` \window ->
+ xMapWindow window `thenIO` \() ->
+ xCreateGcontext (XDrawWindow root)
+ [XGCBackground bg_color,
+ XGCForeground fg_color] `thenIO` \ gcontext ->
+ let
+ handleEvent :: XPoint -> IO ()
+ handleEvent last =
+ xGetEvent display `thenIO` \event ->
+ let pos = xEventPos event
+ in
+ case (xEventType event) of
+ XButtonPressEvent -> handleEvent pos
+ XMotionNotifyEvent ->
+ xDrawLine (XDrawWindow window) gcontext last pos `thenIO` \() ->
+ handleEvent pos
+ XKeyPressEvent -> xCloseDisplay display
+ _ -> handleEvent last
+ in
+ appendChan stdout "Press any key to quit.\n" exit done `thenIO` \ _ ->
+ handleEvent (XPoint 0 0)
diff --git a/progs/demo/X11/draw/draw.hu b/progs/demo/X11/draw/draw.hu
new file mode 100644
index 0000000..f09a72e
--- /dev/null
+++ b/progs/demo/X11/draw/draw.hu
@@ -0,0 +1,2 @@
+$HASKELL_LIBRARY/X11/xlib.hu
+draw.hs
diff --git a/progs/demo/X11/gobang/README b/progs/demo/X11/gobang/README
new file mode 100644
index 0000000..d5634a4
--- /dev/null
+++ b/progs/demo/X11/gobang/README
@@ -0,0 +1,66 @@
+gobang Weiming Wu & Niping Wu
+
+
+Introduction
+
+Our final project is to design and implement a Gobang game under
+X-Window3.2 environment, using the Haskell programming language. Users
+can play the game human-vs-human. The program also provides a robot
+player with whom the user can play the game with. We wrote altogether
+ten modules which were saved in different files to control the whole
+game.
+
+
+About Gobang
+
+The checkerboard of Gobang consists of 19 vertical lines and 19
+horizontal lines. Two players in turn place a unit on the
+checkerboard. Each unit should be put on an unoccupied intersection
+of a vertical and a horizontal line. The winner is the player who
+first makes five consecutive units on either vertical, horizontal or
+diagonal direction.
+
+The program is able to perform the following tasks: 1) Use a new
+window under X-Window interface to display the checkerboard. Players
+will use a mouse to place units onto the chessboard, where a unit is a
+circle with the color black or white. 2) Prompt for the names of both
+players and display them. 3) Calculate the time both players have
+used up. 4) Supervise the progress of the game, declare winner and
+end the game once one player wins. 5) At each point of the game,
+store the progress of the game, so players can review each step during
+the game. 6) There are five buttons on the screen which would provide
+some special services such as starting a new game, quitting the game,
+saving the game, importing the saved game, or reviewing the game as
+soon as the user selects the corresponding buttons. 7) Provide a
+moderately well robot player for that game (using minimum-maximum
+algorithm).
+
+
+Running Gobang
+
+A window titled "gobang" will appear on the screen. On it is a
+checkerboard, clocks and buttons. There will be an instruction saying
+"Please enter the name of player-1". The user can do two things:
+either enter the name of a player or choose the "import" button. Once
+the "import" button is selected, an unfinished game, which was saved
+in the file "###go.bhs###" will be imported. Please notice that the
+character "@" is reserved for the robot player, so if the user types
+in @ as the name of the first player, it is assumed that player-1 is
+the robot player. Then the name of player 2 is prompted. The game
+starts and at each turn an instruction like "Please enter your play."
+would appear on the screen. The user should put a unit onto the
+checkerboard. If the button is clicked on a wrong place or a unit is
+put onto an occupied position, an error message saying "Wrong Point.
+Please reenter." will appear on the screen and the user should reenter
+his play. The marker next to the name of a player indicates whose
+turn it is. At any point of the game the user can choose the other
+four buttons. If the "new" button is selected, the present game will
+be terminated and a new blank checkerboard will be displayed on the
+screen; if the "review" button is selected, one step of the previous
+plays will be displayed each time after the user hits any key; if the
+"save" button is selected, the steps so far will be saved into the
+file "###go.bhs###"; if the "quit" button is selected, the game will
+be terminated.
+
+
+
diff --git a/progs/demo/X11/gobang/gobang.hs b/progs/demo/X11/gobang/gobang.hs
new file mode 100644
index 0000000..f4844dc
--- /dev/null
+++ b/progs/demo/X11/gobang/gobang.hs
@@ -0,0 +1,364 @@
+module Gobang where
+
+import Xlib
+import Utilities
+import Redraw
+import Weights
+
+getXInfo :: String -> IO XInfo
+getXInfo host =
+ xOpenDisplay host `thenIO` \ display ->
+ let (screen:_) = xDisplayRoots display
+ fg_pixel = xScreenBlackPixel screen
+ bg_pixel = xScreenWhitePixel screen
+ root = xScreenRoot screen
+ in
+ xCreateWindow root
+ (XRect 0 0 900 600)
+ [XWinBackground bg_pixel,
+ XWinEventMask (XEventMask [XButtonPress,
+ XKeyPress,
+ XExposure])]
+ `thenIO` \ window ->
+ xSetWmName window "Gobang" `thenIO` \() ->
+ xMapWindow window `thenIO` \() ->
+ xOpenFont display "10x20" `thenIO` \ playerfont ->
+ xOpenFont display "6x13" `thenIO` \ genericfont ->
+ xCreateGcontext (XDrawWindow window)
+ [XGCBackground bg_pixel,
+ XGCForeground fg_pixel] `thenIO` \ gcontext ->
+ xCreateGcontext (XDrawWindow window)
+ [XGCBackground fg_pixel,
+ XGCForeground bg_pixel,
+ XGCFont genericfont] `thenIO` \ gcontext2 ->
+ xCreateGcontext (XDrawWindow window)
+ [XGCBackground bg_pixel,
+ XGCForeground fg_pixel,
+ XGCFont playerfont] `thenIO` \ gcontextp ->
+ returnIO (XInfo display window gcontext gcontext2 gcontextp)
+
+demo = main
+
+main = getEnv "DISPLAY" exit $ \ host ->
+ xHandleError (\(XError msg) -> appendChan stdout msg exit done) $
+ gobang host
+
+gobang :: String -> IO ()
+gobang host =
+ getXInfo host `thenIO` \ xinfo ->
+ xMArrayCreate [1..361] `thenIO` \ board ->
+ xMArrayCreate [1..361] `thenIO` \ weight1 ->
+ xMArrayCreate [1..361] `thenIO` \ weight2 ->
+ xMArrayCreate [1..722] `thenIO` \ steps ->
+ xMArrayCreate [""] `thenIO` \ player1 ->
+ xMArrayCreate [""] `thenIO` \ player2 ->
+ xMArrayCreate [1..4] `thenIO` \ time ->
+ xMArrayCreate [1] `thenIO` \ numbersteps ->
+ xMArrayCreate [""] `thenIO` \ promptString ->
+ xMArrayCreate [1] `thenIO` \ next_player ->
+ let state = GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player
+ in
+ initGame xinfo state `thenIO` \ _ ->
+ promptPlayers xinfo state `thenIO` \ _ ->
+ playGame xinfo state
+
+promptPlayers xinfo state =
+ let (XInfo display window gcontext gcontext2 gcontextp) = xinfo
+ (GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player) = state
+ in
+ promptFor "player 1:" xinfo state `thenIO` \ player1_name ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 710 65) player1_name
+ `thenIO` \ _ ->
+ xMArrayUpdate player1 0 player1_name `thenIO` \ _ ->
+ promptFor "player 2:" xinfo state `thenIO` \ player2_name ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 710 205) player2_name
+ `thenIO` \ _ ->
+ xMArrayUpdate player2 0 player2_name `thenIO` \ _ ->
+ clearCmd xinfo state
+
+initGame :: XInfo -> GameState -> IO ()
+initGame xinfo
+ state@(GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player) =
+ getTime `thenIO` \ curtime ->
+ initArray time 0 2 0 `thenIO` \() ->
+ initArray time 2 4 curtime `thenIO` \() ->
+ initArray numbersteps 0 1 0 `thenIO` \() ->
+ initArray board 0 361 0 `thenIO` \() ->
+ initArray weight1 0 361 0 `thenIO` \() ->
+ initArray weight2 0 361 0 `thenIO` \ () ->
+ initArray next_player 0 1 1 `thenIO` \ () ->
+ clearCmd xinfo state `thenIO` \ () ->
+ redraw xinfo state
+
+
+handleButton :: XPoint -> XInfo -> GameState -> GameCont -> IO ()
+handleButton (XPoint x y)
+ xinfo
+ state@(GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player)
+ cont
+ | buttonPress 700 330 x y = initArray player1 0 1 "" `thenIO` \ _ ->
+ initArray player2 0 1 "" `thenIO` \ _ ->
+ initGame xinfo state `thenIO` \ _ ->
+ promptPlayers xinfo state `thenIO` \ _ ->
+ playGame xinfo state
+ | buttonPress 700 360 x y = initGame xinfo state `thenIO` \ _ ->
+ playGame xinfo state
+ | buttonPress 700 390 x y = undoGame xinfo state cont
+ | buttonPress 700 420 x y = loadGame xinfo state cont
+ | buttonPress 700 450 x y = saveGame xinfo state `thenIO` \ () ->
+ cont xinfo state
+ | buttonPress 700 480 x y = quitGame xinfo state cont
+ | ishelp x y = helpGame xinfo state `thenIO` \ () ->
+ cont xinfo state
+ | otherwise = cont xinfo state
+
+when :: Bool -> IO () -> IO ()
+when cond action = if cond then action else returnIO ()
+
+undoGame xinfo@(XInfo display window gcontext gcontext2 gcontextp)
+ state@(GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player)
+ cont =
+ xMArrayLookup next_player 0 `thenIO` \ next_p ->
+ xMArrayLookup player1 0 `thenIO` \ name1 ->
+ xMArrayLookup player2 0 `thenIO` \ name2 ->
+ let undoStep n =
+ xMArrayLookup steps (2*n) `thenIO` \ x ->
+ xMArrayLookup steps (2*n+1) `thenIO` \ y ->
+ xMArrayUpdate board ((x-1)*19 + y-1) 0 `thenIO` \ _ ->
+ (if (name1 == "computer" || name2 == "computer")
+ then draw_unit board weight1 weight2 x y
+ else returnIO ()) `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext2
+ (XRect (x*30-15) (y*30-15) 30 30) True
+ `thenIO` \() ->
+-- drawBoard xinfo `thenIO` \ _ ->
+-- drawPieces 1 1 board xinfo `thenIO` \ _ ->
+ let x30 = x * 30
+ y30 = y * 30
+ c = XPoint x30 y30
+ w = XPoint (x30-15) y30
+ e = XPoint (x30+15) y30
+ no = XPoint x30 (y30-15)
+ s = XPoint x30 (y30+15)
+ m = XArc (x30-3) (y30-3) 6 6 (-1.0) 6.283
+ in
+ when (x > 1) (xDrawLine (XDrawWindow window) gcontext w c)
+ `thenIO` \ _ ->
+ when (x < 19) (xDrawLine (XDrawWindow window) gcontext c e)
+ `thenIO` \ _ ->
+ when (y > 1) (xDrawLine (XDrawWindow window) gcontext no c)
+ `thenIO` \ _ ->
+ when (y < 19) (xDrawLine (XDrawWindow window) gcontext c s)
+ `thenIO` \ _ ->
+ when ((x `elem` [4,10,16]) && (y `elem` [4,10,16]))
+ (xDrawArc (XDrawWindow window) gcontext m True)
+ `thenIO` \ _ ->
+ xDisplayForceOutput display `thenIO` \ _ ->
+ xMArrayUpdate numbersteps 0 n `thenIO` \ _ ->
+ xMArrayLookup next_player 0 `thenIO` \ next_p ->
+ xMArrayUpdate next_player 0 (if next_p == 1 then 2 else 1)
+
+ cur_name = if next_p == 1 then name1 else name2
+ last_name = if next_p == 1 then name2 else name1
+ in
+ xMArrayLookup numbersteps 0 `thenIO` \ n ->
+ if n==0 then drawCmd "No more steps to undo!" xinfo state `thenIO` \ _ ->
+ cont xinfo state
+ else
+ if cur_name == "computer" then cont xinfo state
+ else
+ (undoStep (n-1) `thenIO` \_ ->
+ if (last_name == "computer" && n /= 1) then undoStep (n-2)
+ else
+ returnIO ()) `thenIO` \ _ ->
+ playGame xinfo state
+
+
+
+
+promptFile xinfo state cont =
+ promptFor "File name:" xinfo state `thenIO` \ name ->
+ readFile name
+ (\ _ -> drawCmd ("Can't read file:" ++ name) xinfo state
+ `thenIO` \ _ ->
+ cont XNull)
+ (\ content -> cont (XSome content))
+
+loadGame xinfo state cont =
+ promptFile xinfo state $ \ file ->
+ case file of
+ XNull -> cont xinfo state
+ XSome file_content ->
+ readGameState file_content `thenIO` \ new_state ->
+ let (GameState _ _ _ _ _ _ time _ _ _) = new_state
+ in
+ getTime `thenIO` \ curtime ->
+ initArray time 2 4 curtime `thenIO` \() ->
+ redraw xinfo new_state `thenIO` \ _ ->
+ playGame xinfo new_state
+
+saveGame :: XInfo -> GameState -> IO ()
+saveGame xinfo state =
+ promptFor "File name:" xinfo state `thenIO` \ name ->
+ showGameState state `thenIO` \ str ->
+ writeFile name str
+ (\ _ -> drawCmd ("Can't write file: " ++ name) xinfo state)
+ done
+
+quitGame :: XInfo -> GameState -> GameCont -> IO ()
+quitGame xinfo state cont =
+ let (XInfo display window gcontext gcontext2 gcontextp) = xinfo
+ in
+ promptFor "Are you sure? (y/n)" xinfo state `thenIO` \ reps ->
+ if (reps == "y" || reps == "Y") then xCloseDisplay display
+ else clearCmd xinfo state `thenIO` \ _ ->
+ cont xinfo state
+
+playGame :: XInfo -> GameState -> IO ()
+playGame xinfo state =
+ let
+ (XInfo display window gcontext gcontext2 gcontextp) = xinfo
+ (GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player) = state
+ in
+ xMArrayLookup numbersteps 0 `thenIO` \ x ->
+ (\cont -> if x == 361
+ then drawCmd "It's a tie!" xinfo state `thenIO` \ _ ->
+ let loop xinfo state = waitButton xinfo state (\ _ -> loop)
+ in loop xinfo state
+ else cont) $
+ xMArrayLookup next_player 0 `thenIO` \ next_player_num ->
+ getTime `thenIO` \ curtime ->
+ xMArrayLookup time 0 `thenIO` \ lstm0 ->
+ xMArrayLookup time 1 `thenIO` \ lstm1 ->
+ xMArrayLookup time 2 `thenIO` \ lstm2 ->
+ xMArrayLookup time 3 `thenIO` \ lstm3 ->
+ drawCmd ("Waiting for player # " ++ (show next_player_num)) xinfo state
+ `thenIO` \() ->
+ if (next_player_num == 1)
+ then xDrawGlyph (XDrawWindow window) gcontextp (XPoint 850 70)
+ '<' `thenIO` \(trash) ->
+ xDrawRectangle (XDrawWindow window) gcontext2
+ (XRect 840 180 40 40) True `thenIO` \() ->
+ xMArrayUpdate time 2 curtime `thenIO` \() ->
+ xMArrayUpdate time 1 (lstm1+curtime-lstm3) `thenIO` \() ->
+ showtime 705 270 (lstm1+curtime-lstm3) xinfo `thenIO` \() ->
+ xMArrayLookup player1 0 `thenIO` \ x ->
+ if (x == "computer")
+ then computerplay xinfo state
+ else humanplay xinfo state
+ else xDrawGlyph (XDrawWindow window) gcontextp (XPoint 850 210)
+ '<' `thenIO` \(trash) ->
+ xDrawRectangle (XDrawWindow window) gcontext2
+ (XRect 840 40 40 40) True `thenIO` \() ->
+ xMArrayUpdate time 3 curtime `thenIO` \() ->
+ xMArrayUpdate time 0 (lstm0+curtime-lstm2) `thenIO` \() ->
+ showtime 705 130 (lstm0+curtime-lstm3) xinfo `thenIO` \() ->
+ xMArrayLookup player2 0 `thenIO` \ x ->
+ if (x == "computer")
+ then computerplay xinfo state
+ else humanplay xinfo state
+
+waitButton xinfo@(XInfo display _ _ _ _) state cont =
+ let
+ loop xinfo state =
+ xGetEvent display `thenIO` \ event ->
+ case (xEventType event) of
+ XExposureEvent -> may_redraw (xEventCount event == 0) xinfo state
+ `thenIO` \ _ ->
+ loop xinfo state
+ XButtonPressEvent ->
+ let pos = xEventPos event
+ in
+ handleButton pos xinfo state (cont pos)
+ _ -> xBell display 0 `thenIO` \ _ ->
+ loop xinfo state
+ in
+ loop xinfo state
+
+updateboard :: XInfo -> GameState -> Int -> Int -> IO ()
+updateboard xinfo state x y =
+ let (GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player) = state
+ (XInfo display window gcontext gcontext2 gcontextp) = xinfo
+ in
+ xMArrayLookup next_player 0 `thenIO` \ next_player_num ->
+ xMArrayUpdate next_player 0 (if next_player_num == 1 then 2 else 1)
+ `thenIO` \ _ ->
+ xMArrayLookup numbersteps 0 `thenIO` \ z ->
+ xMArrayUpdate numbersteps 0 (z+1) `thenIO` \() ->
+ xMArrayUpdate steps (2*z) x `thenIO` \() ->
+ xMArrayUpdate steps (2*z+1) y `thenIO` \() ->
+ xMArrayLookup player1 0 `thenIO` \ name1 ->
+ xMArrayLookup player2 0 `thenIO` \ name2 ->
+ xMArrayUpdate board (19*(x-1)+y-1) next_player_num
+ `thenIO` \() ->
+ human_unit board x y `thenIO` \ win ->
+ if win
+ then drawCmd ("Player " ++ (show next_player_num) ++ " has won!")
+ xinfo state `thenIO` \ _ ->
+ let loop xinfo state = waitButton xinfo state (\ _ -> loop)
+ in loop xinfo state
+ else if (name1 == "computer" || name2 == "computer")
+ then draw_unit board weight1 weight2 x y `thenIO` \() ->
+ xMArrayUpdate weight1 (19*(x-1)+y-1) (-1) `thenIO` \() ->
+ xMArrayUpdate weight2 (19*(x-1)+y-1) (-1) `thenIO` \() ->
+ playGame xinfo state
+ else playGame xinfo state
+
+choice :: XPoint -> XInfo -> GameState -> IO ()
+choice (XPoint x y) xinfo@(XInfo display _ _ _ _) state =
+ let (GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player) = state
+ in
+ case (getposition x y) of
+ XNull -> humanplay xinfo state
+ XSome (x, y) ->
+ xMArrayLookup board (19*(x-1)+y-1) `thenIO` \ z ->
+ if (z>0)
+ then xBell display 0 `thenIO` \ _ ->
+ drawCmd "Wrong point, please re-enter" xinfo state `thenIO` \() ->
+ humanplay xinfo state
+ else xMArrayLookup next_player 0 `thenIO` \ next_player_num ->
+ drawPiece x y xinfo (next_player_num == 1) `thenIO` \() ->
+ updateboard xinfo state x y
+
+humanplay :: XInfo -> GameState -> IO ()
+humanplay xinfo state = waitButton xinfo state choice
+
+computerplay :: XInfo -> GameState -> IO ()
+computerplay xinfo@(XInfo display window gcontext gcontext2 gcontextp)
+ state =
+ let process_events xinfo state cont =
+ xEventListen display `thenIO` \ n_event ->
+ if n_event == 0 then cont xinfo state
+ else xGetEvent display `thenIO` \ event ->
+ case (xEventType event) of
+ XButtonPressEvent ->
+ handleButton (xEventPos event) xinfo state cont
+ XExposureEvent ->
+ may_redraw (xEventCount event == 0)
+ xinfo state
+ `thenIO` \ _ ->
+ process_events xinfo state cont
+ XKeyPressEvent ->
+ process_events xinfo state cont
+ in
+ process_events xinfo state $
+ \ xinfo@(XInfo display window gcontext gcontext2 gcontextp)
+ state@(GameState _ _ _ _ weight1 weight2 _ numbersteps _ next_player) ->
+ robot numbersteps weight1 weight2 `thenIO` \pt ->
+ let (XPoint x y) = pt
+ in
+ xMArrayLookup next_player 0 `thenIO` \ next_player_num ->
+ drawPiece x y xinfo (next_player_num == 1) `thenIO` \() ->
+ updateboard xinfo state x y
+
+
+
+
diff --git a/progs/demo/X11/gobang/gobang.hu b/progs/demo/X11/gobang/gobang.hu
new file mode 100644
index 0000000..d228bb2
--- /dev/null
+++ b/progs/demo/X11/gobang/gobang.hu
@@ -0,0 +1,7 @@
+:o= foldr inline constant
+$HASKELL_LIBRARY/X11/xlib.hu
+gobang.hs
+misc.hi
+utilities.hs
+redraw.hs
+weights.hs
diff --git a/progs/demo/X11/gobang/misc.hi b/progs/demo/X11/gobang/misc.hi
new file mode 100644
index 0000000..29a29be
--- /dev/null
+++ b/progs/demo/X11/gobang/misc.hi
@@ -0,0 +1,7 @@
+interface Misc where
+
+random :: Int -> IO Int
+
+{-#
+random :: LispName("lisp:random")
+#-} \ No newline at end of file
diff --git a/progs/demo/X11/gobang/misc.hu b/progs/demo/X11/gobang/misc.hu
new file mode 100644
index 0000000..42a9c68
--- /dev/null
+++ b/progs/demo/X11/gobang/misc.hu
@@ -0,0 +1,2 @@
+misc.hi
+
diff --git a/progs/demo/X11/gobang/redraw.hs b/progs/demo/X11/gobang/redraw.hs
new file mode 100644
index 0000000..9ec772f
--- /dev/null
+++ b/progs/demo/X11/gobang/redraw.hs
@@ -0,0 +1,160 @@
+module Redraw where
+
+import Xlib
+import Utilities
+
+may_redraw :: Bool -> XInfo -> GameState -> IO ()
+may_redraw ok xinfo state = if ok then redraw xinfo state else returnIO ()
+
+redraw :: XInfo -> GameState -> IO ()
+
+redraw xinfo state =
+ let (XInfo display window gcontext gcontext2 gcontextp) = xinfo
+ in
+ xDrawRectangle (XDrawWindow window) gcontext2 (XRect 0 0 900 600) True
+ `thenIO` \ _ ->
+ drawBoard xinfo `thenIO` \ () ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 610 65) "Player 1"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 620 125) "Clock 1"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 610 205) "Player 2"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 620 265) "Clock 2"
+ `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 700 45 130 30) False
+ `thenIO` \ () ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 700 105 90 30) False
+ `thenIO` \ () ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 700 185 130 30) False
+ `thenIO` \() ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 700 245 90 30) False
+ `thenIO` \() ->
+ button 700 330 "New players" xinfo `thenIO` \() ->
+ button 700 360 "New game" xinfo `thenIO` \() ->
+ button 700 390 "Undo" xinfo `thenIO` \() ->
+ button 700 420 "Load" xinfo `thenIO` \() ->
+ button 700 450 "Save" xinfo `thenIO` \() ->
+ button 700 480 "Quit" xinfo `thenIO` \() ->
+ helpButton xinfo `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 615 535 250 30) False
+ `thenIO` \ _ ->
+ let (GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player) = state
+ in
+ xMArrayLookup time 0 `thenIO` \ lstm0 ->
+ xMArrayLookup time 1 `thenIO` \ lstm1 ->
+ showtime 705 270 (lstm1) xinfo `thenIO` \() ->
+ showtime 705 130 (lstm0) xinfo `thenIO` \() ->
+ xMArrayLookup player1 0 `thenIO` \ player1_name ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 710 65) player1_name
+ `thenIO` \ _ ->
+ xMArrayLookup player2 0 `thenIO` \ player2_name ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 710 205) player2_name
+ `thenIO` \ _ ->
+ xMArrayLookup promptString 0 `thenIO` \ ps ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 620 550) ps
+ `thenIO` \ _ ->
+ xMArrayLookup next_player 0 `thenIO` \ next_player_num ->
+ (if (next_player_num == 1)
+ then xDrawGlyph (XDrawWindow window) gcontextp (XPoint 850 70) '<'
+ else xDrawGlyph (XDrawWindow window) gcontextp (XPoint 850 210) '<')
+ `thenIO` \ _ ->
+ drawPieces 1 1 board xinfo `thenIO` \ _ ->
+ returnIO ()
+
+drawHelp (XInfo display window gcontext gcontext2 gcontextp) =
+ xDrawRectangle (XDrawWindow window) gcontext2 (XRect 100 100 300 200) True
+ `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 100 100 300 200) False
+ `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 102 102 296 196) False
+ `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 200 230 100 60) False
+ `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 202 232 96 56) False
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 240 265) "OK"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 120 120)
+ "Two players in turn place black and white"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 120 135)
+ "pieces on the board. The winner is the"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 120 150)
+ "player who first makes five consecutive"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 120 165)
+ "pieces in either vertical, horizontal or"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 120 180)
+ "diagonal directions."
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 120 200)
+ "To play with a robot, type \"computer\" as"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 120 215)
+ "the name of another player."
+
+
+drawBoard (XInfo display window gcontext gcontext2 gcontextp) =
+ drawvlines 30 30 1 `thenIO` \() ->
+ drawhlines 30 30 1 `thenIO` \() ->
+ drawmarks where
+
+ drawvlines :: Int -> Int -> Int -> IO ()
+ drawvlines x y z
+ | z <= 19
+ = xDrawLine (XDrawWindow window) gcontext
+ (XPoint x y) (XPoint x (y+30*18)) `thenIO` \() ->
+ drawvlines (x+30) y (z+1)
+ | otherwise
+ = returnIO ()
+
+ drawhlines :: Int -> Int -> Int -> IO ()
+ drawhlines x y z
+ | z <= 19
+ = xDrawLine (XDrawWindow window) gcontext
+ (XPoint x y) (XPoint (x+30*18) y) `thenIO` \() ->
+ drawhlines x (y+30) (z+1)
+ | otherwise
+ = returnIO ()
+
+ drawmarks :: IO ()
+ drawmarks =
+ map2IO (\x y ->
+ xDrawArc (XDrawWindow window) gcontext
+ (XArc x y 6 6 (-1.0) 6.283) True)
+ (map (\x -> 30 + x*30-3) [3,9,15,3,9,15,3,9,15])
+ (map (\x -> 30 + x*30-3) [3,3,3,9,9,9,15,15,15])
+ `thenIO` \ _ -> returnIO ()
+
+map2IO :: (a -> b -> IO c) -> [a] -> [b] -> IO [c]
+
+map2IO f [] [] = returnIO []
+map2IO f (x:xs) (z:zs) = f x z `thenIO` \ y ->
+ map2IO f xs zs `thenIO` \ ys ->
+ returnIO (y:ys)
+
+drawPieces 20 _ board xinfo = returnIO ()
+drawPieces x 20 board xinfo = drawPieces (x+1) 1 board xinfo
+drawPieces x y board xinfo =
+ xMArrayLookup board ((x-1)*19 + y-1) `thenIO` \ piece ->
+ (if (piece == 1 || piece == 2)
+ then drawPiece x y xinfo (piece == 1)
+ else returnIO ()) `thenIO` \ _ ->
+ drawPieces x (y+1) board xinfo
+
+drawPiece x y (XInfo display window gcontext gcontext2 _ ) is_black =
+ (if is_black then returnIO ()
+ else xDrawArc (XDrawWindow window) gcontext2
+ (XArc (30*x-10) (30*y-10) 20 20
+ (-1.0) 6.283)
+ True) `thenIO` \ _ ->
+ xDrawArc (XDrawWindow window) gcontext
+ (XArc (30*x-10) (30*y-10) 20 20
+ (-1.0) 6.283)
+ is_black `thenIO` \ _ ->
+ xDisplayForceOutput display
+
diff --git a/progs/demo/X11/gobang/redraw.hu b/progs/demo/X11/gobang/redraw.hu
new file mode 100644
index 0000000..7d5aa14
--- /dev/null
+++ b/progs/demo/X11/gobang/redraw.hu
@@ -0,0 +1,4 @@
+:o= all
+$HASKELL_LIBRARY/X11/xlib.hu
+redraw.hs
+utilities.hs
diff --git a/progs/demo/X11/gobang/utilities.hs b/progs/demo/X11/gobang/utilities.hs
new file mode 100644
index 0000000..fe2483b
--- /dev/null
+++ b/progs/demo/X11/gobang/utilities.hs
@@ -0,0 +1,305 @@
+module Utilities where
+
+import Xlib
+import Weights
+import Redraw
+import Misc
+
+data XInfo = XInfo XDisplay XWindow XGcontext XGcontext XGcontext
+data GameState = GameState (XMArray String) (XMArray String) (XMArray Int)
+ (XMArray Int) (XMArray Int) (XMArray Int)
+ (XMArray Integer) (XMArray Int)
+ (XMArray String) (XMArray Int)
+
+type GameCont = XInfo -> GameState -> IO ()
+
+xMArrayToList :: XMArray a -> IO [a]
+xMArrayToList a =
+ let la = xMArrayLength a
+ loop i a = if i == la then returnIO []
+ else xMArrayLookup a i `thenIO` \ x ->
+ loop (i+1) a `thenIO` \ xs ->
+ returnIO (x:xs)
+ in
+ loop 0 a
+
+
+readGameState str =
+ let
+ [(board_lst, r1)] = reads str
+ [(weight1_lst, r2)] = reads r1
+ [(weight2_lst, r3)] = reads r2
+ [(steps_lst, r4)] = reads r3
+ [(player1_lst, r5)] = reads r4
+ [(player2_lst, r6)] = reads r5
+ [(time_lst, r7)] = reads r6
+ [(numbersteps_lst, r8)] = reads r7
+ [(promptString_lst, r9)] = reads r8
+ [(next_player_lst, [])] = reads r9
+ in
+ xMArrayCreate board_lst `thenIO` \ board ->
+ xMArrayCreate weight1_lst `thenIO` \ weight1 ->
+ xMArrayCreate weight2_lst `thenIO` \ weight2 ->
+ xMArrayCreate steps_lst `thenIO` \ steps ->
+ xMArrayCreate player1_lst `thenIO` \ player1 ->
+ xMArrayCreate player2_lst `thenIO` \ player2 ->
+ xMArrayCreate time_lst `thenIO` \ time ->
+ xMArrayCreate numbersteps_lst `thenIO` \ numbersteps ->
+ xMArrayCreate promptString_lst `thenIO` \ promptString ->
+ xMArrayCreate next_player_lst `thenIO` \ next_player ->
+ returnIO (GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player)
+
+showGameState (GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player) =
+ xMArrayToList board `thenIO` \ board_lst ->
+ xMArrayToList weight1 `thenIO` \ weight1_lst ->
+ xMArrayToList weight2 `thenIO` \ weight2_lst ->
+ xMArrayToList steps `thenIO` \ steps_lst ->
+ xMArrayToList player1 `thenIO` \ player1_lst ->
+ xMArrayToList player2 `thenIO` \ player2_lst ->
+ xMArrayToList time `thenIO` \ time_lst ->
+ xMArrayToList numbersteps `thenIO` \ numbersteps_lst ->
+ xMArrayToList promptString `thenIO` \ promptString_lst ->
+ xMArrayToList next_player `thenIO` \ next_player_lst ->
+ let
+ str =(shows board_lst .
+ shows weight1_lst .
+ shows weight2_lst .
+ shows steps_lst .
+ shows player1_lst .
+ shows player2_lst .
+ shows time_lst .
+ shows numbersteps_lst .
+ shows promptString_lst .
+ shows next_player_lst) []
+ in
+ returnIO str
+
+
+xMod :: Int -> Int -> Int
+xMod x y | x >= y = xMod (x-y) y
+ | otherwise = x
+
+xRes :: Int -> Int -> Int -> Int
+xRes x y z | x >= y = xRes (x-y) y (z+1)
+ | otherwise = z
+
+drawCmd :: String -> XInfo -> GameState -> IO ()
+drawCmd a (XInfo display window gcontext gcontext2 gcontextp)
+ (GameState _ _ _ _ _ _ _ _ str _)
+ = xDrawRectangle (XDrawWindow window) gcontext2
+ (XRect 616 536 248 28) True `thenIO` \ () ->
+ xDrawGlyphs (XDrawWindow window) gcontext
+ (XPoint 620 550) a `thenIO` \ _ ->
+ xMArrayUpdate str 0 a `thenIO` \ _ ->
+ xDisplayForceOutput display
+
+clearCmd :: XInfo -> GameState -> IO ()
+clearCmd (XInfo display window gcontext gcontext2 gcontextp)
+ (GameState _ _ _ _ _ _ _ _ str _)
+ = xDrawRectangle (XDrawWindow window) gcontext2
+ (XRect 616 536 248 28) True `thenIO` \() ->
+ xMArrayUpdate str 0 "" `thenIO` \ _ ->
+ xDisplayForceOutput display
+
+xPosition :: Int -> XPoint
+xPosition a = (XPoint (xRes a 19 1) (1+ (xMod a 19)))
+
+initArray :: XMArray a -> Int -> Int -> a -> IO ()
+initArray mary x y z | x<y = xMArrayUpdate mary x z `thenIO` \() ->
+ initArray mary (x+1) y z
+ | otherwise = returnIO ()
+
+getposition :: Int -> Int -> XMaybe (Int, Int)
+getposition x y = let x1 = round ((fromIntegral x) / 30.0)
+ y1 = round ((fromIntegral y) / 30.0)
+ in
+ if (x1 < 1 || x1 > 19 || y1 < 1 || y1 > 19) then XNull
+ else XSome (x1, y1)
+
+addZero :: Int -> String
+addZero a | a < 10 = "0"
+ | otherwise = ""
+
+printTime :: Int -> Int -> [Int] -> XInfo -> IO()
+printTime x y zs (XInfo display window gcontext gcontext2 gcontextp)
+ = let s = head zs
+ m = head (tail zs)
+ h = head (tail (tail zs))
+ in xDrawRectangle (XDrawWindow window) gcontext2
+ (XRect (x-4) (y-24) 88 28) True `thenIO` \() ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint x y)
+ ((addZero h)++(show h)++":"++(addZero m)++(show m)++
+ ":"++(addZero s)++(show s))
+ `thenIO` \(trash) ->
+ xDisplayForceOutput display
+
+showtime :: Int -> Int -> Integer -> XInfo -> IO()
+showtime x y z a =
+ let (curtm, c) = (decodeTime z (WestOfGMT 0))
+ in printTime x y curtm a
+
+helpButton :: XInfo -> IO ()
+helpButton (XInfo display window gcontext gcontext2 gcontextp) =
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 800 420 70 70)
+ False `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext (XRect 802 422 66 66)
+ False `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontextp (XPoint 810 450) "About"
+ `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 820 470) "Gobang"
+ `thenIO` \ _ ->
+ returnIO ()
+
+ishelp :: Int -> Int -> Bool
+ishelp x y = (x > 800 && x < 870 && y > 420 && y < 490)
+
+button :: Int -> Int -> String -> XInfo -> IO()
+button x y a (XInfo display window gcontext gcontext2 gcontextp) =
+ xDrawArc (XDrawWindow window) gcontext
+ (XArc (x-40) (y-10) 20 20 1.5708 4.7124) True `thenIO` \() ->
+ xDrawRectangle (XDrawWindow window) gcontext
+ (XRect (x-30) (y-10) 60 20) True `thenIO` \() ->
+ xDrawArc (XDrawWindow window) gcontext
+ (XArc (x+20) (y-10) 20 20 (-1.0) 6.283) True `thenIO` \() ->
+ xDrawGlyphs (XDrawWindow window) gcontext2
+ (XPoint (x-(length a * 3)) (y+4)) a `thenIO` \(trash) ->
+ xDisplayForceOutput display
+
+-- a b are the location of the button, c d are the point where we press the
+-- button.
+
+buttonPress :: Int -> Int -> Int -> Int -> Bool
+buttonPress a b c d | (abs (c-a))<=30 && (abs (d-b))<=10 = True
+ | (c-a+30)*(c-a+30)+(d-b)*(d-b)<=100 = True
+ | (c-a-30)*(c-a-30)+(d-b)*(d-b)<=100 = True
+ | otherwise = False
+
+
+
+randmax :: XMArray Int -> Int -> Int -> [Int] -> IO Int
+randmax a ind max mi | ind > 360 =
+ let lmi = length mi
+ in case lmi of
+ 0 -> returnIO (-1)
+ 1 -> returnIO (head mi)
+ _ -> random lmi `thenIO` \ i ->
+ returnIO (mi !! i)
+ | otherwise = xMArrayLookup a ind `thenIO` \ tt3 ->
+ if (tt3 > max)
+ then randmax a (ind+1) tt3 [ind]
+ else if (tt3 == max)
+ then randmax a (ind+1) max (ind:mi)
+ else randmax a (ind+1) max mi
+
+robot :: XMArray Int -> XMArray Int -> XMArray Int -> IO XPoint
+robot numbersteps weight1 weight2
+ = xMArrayLookup numbersteps 0 `thenIO` \(tt5) ->
+ if (tt5 == 0)
+ then returnIO (XPoint 10 10)
+ else
+ randmax weight1 0 0 [] `thenIO` \ tmp1 ->
+ randmax weight2 0 0 [] `thenIO` \ tmp2 ->
+ xMArrayLookup weight1 tmp1 `thenIO` \ tmp3 ->
+ xMArrayLookup weight2 tmp2 `thenIO` \ tmp4 ->
+ if (tmp3 >= 200)
+ then returnIO (xPosition tmp1)
+ else if (tmp3 > tmp4)
+ then returnIO (xPosition tmp1)
+ else returnIO (xPosition tmp2)
+
+
+promptFor prompt xinfo state =
+ let (GameState player1 player2 board steps weight1 weight2 time
+ numbersteps promptString next_player) = state
+ (XInfo display window gcontext gcontext2 gcontextp) = xinfo
+ in
+ xDrawRectangle (XDrawWindow window) gcontext2
+ (XRect 616 536 248 28) True `thenIO` \() ->
+ xMArrayUpdate promptString 0 prompt `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint 620 550) prompt
+ `thenIO` \ _ ->
+ xDisplayForceOutput display `thenIO` \ _ ->
+ let h_base = (length prompt + 1) * 6 + 620
+ getString :: Int -> String -> IO String
+ getString h_pos sofar =
+ xGetEvent display `thenIO` \event ->
+ case (xEventType event) of
+ XButtonPressEvent ->
+ let (XPoint x y) = xEventPos event
+ in
+ (if ishelp x y then helpGame xinfo state
+ else xBell display 0)
+ `thenIO` \ _ ->
+ getString h_pos sofar
+ XExposureEvent ->
+ may_redraw (xEventCount event == 0) xinfo state `thenIO` \ _ ->
+ xDrawGlyphs (XDrawWindow window) gcontext (XPoint h_base 550) sofar
+ `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext
+ (XRect (h_base + 6 * h_pos) (550-10) 6 13) True
+ `thenIO` \ _ -> getString h_pos sofar
+ XKeyPressEvent ->
+ let code = xEventCode event
+ state = xEventState event
+ bs = if (sofar == "") then getString h_pos sofar
+ else xDrawRectangle (XDrawWindow window) gcontext2
+ (XRect (h_base + 6 * h_pos)
+ (550-10) 6 13)
+ True `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext
+ (XRect (h_base + 6 * (h_pos - 1))
+ (550-10) 6 13)
+ True `thenIO` \ _ ->
+ getString (h_pos-1) (take (length sofar - 1) sofar)
+ in
+ xKeycodeCharacter display code state `thenIO` \ char ->
+ case char of
+ (XSome '\r') -> returnIO sofar
+ (XSome '\DEL') -> bs
+ (XSome '\BS') -> bs
+ XNull -> getString h_pos sofar
+ (XSome c) -> xDrawRectangle (XDrawWindow window) gcontext2
+ (XRect (h_base + 6 * h_pos)
+ (550-10) 6 13)
+ True `thenIO` \ _ ->
+ xDrawGlyph (XDrawWindow window) gcontext
+ (XPoint (h_base + 6 * h_pos) 550) c
+ `thenIO` \ _ ->
+ xDrawRectangle (XDrawWindow window) gcontext
+ (XRect (h_base + 6 * (h_pos + 1))
+ (550-10) 6 13)
+ True `thenIO` \ _ ->
+ getString (h_pos + 1) (sofar ++ [c])
+
+ in
+ xDrawRectangle (XDrawWindow window) gcontext
+ (XRect h_base (550-10) 6 13) True
+ `thenIO` \ _ ->
+ getString 0 ""
+
+
+helpGame xinfo@(XInfo display window gcontext gcontext2 gcontextp) state =
+ drawHelp xinfo `thenIO` \ _ ->
+ let
+ loop xinfo state =
+ xGetEvent display `thenIO` \ event ->
+ case (xEventType event) of
+ XExposureEvent -> may_redraw (xEventCount event == 0) xinfo state
+ `thenIO` \ _ ->
+ drawHelp xinfo `thenIO` \ _ ->
+ loop xinfo state
+ XButtonPressEvent ->
+ let (XPoint x y) = xEventPos event
+ in
+ if (x > 200 && x < 300 && y > 230 && y < 290)
+ then redraw xinfo state `thenIO` \ _ ->
+ returnIO ()
+ else loop xinfo state
+ _ -> xBell display 0 `thenIO` \ _ ->
+ loop xinfo state
+ in
+ loop xinfo state
+
+
diff --git a/progs/demo/X11/gobang/utilities.hu b/progs/demo/X11/gobang/utilities.hu
new file mode 100644
index 0000000..bfccbfe
--- /dev/null
+++ b/progs/demo/X11/gobang/utilities.hu
@@ -0,0 +1,6 @@
+:o= all
+$HASKELL_LIBRARY/X11/xlib.hu
+utilities.hs
+weights.hs
+redraw.hs
+misc.hi
diff --git a/progs/demo/X11/gobang/weights.hs b/progs/demo/X11/gobang/weights.hs
new file mode 100644
index 0000000..1b55553
--- /dev/null
+++ b/progs/demo/X11/gobang/weights.hs
@@ -0,0 +1,323 @@
+module Weights where
+
+import Xlib
+import Utilities
+
+xlookup :: XMArray Int -> Int -> Int -> IO Int
+xlookup keyboard x y =
+ if (x < 1 || x > 19 || y < 1 || y > 19)
+ then returnIO (-2)
+ else xMArrayLookup keyboard ((x-1)*19+(y-1))
+
+
+draw_unit :: XMArray Int -> XMArray Int -> XMArray Int -> Int -> Int -> IO()
+draw_unit keyboard weight1 weight2 x y =
+ let
+ update_weight :: XMArray Int->Int->Int->Int->Int->Int->Int->IO()
+ update_weight weight counter player x y incr_x incr_y
+ | x>=1 && x<=19 && y>=1 && y<=19 && counter<=4 =
+ cpt_weight x y player `thenIO` \wt ->
+ xMArrayUpdate weight ((x-1)*19+(y-1)) wt `thenIO` \() ->
+ update_weight weight (counter+1) player (x+incr_x) (y+incr_y)
+ incr_x incr_y
+ | otherwise = returnIO ()
+----------------------------------------------------------------------------
+
+ pattern0 :: Int -> Int -> Int -> Int -> Int -> Int -> Bool
+ pattern0 a b c d e p | a==p && b==p && c==p && d==p && e==p = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern1 :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool
+ pattern1 a b c d e f p | (a==0) && (b==p) && (c==p) && (d==p) && (e==p) &&
+ (f==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern2 :: Int -> Int -> Int -> Int -> Int -> Int -> Bool
+ pattern2 a b c d e p | (a==0 && b==p && c==p && d==p && e==p)||
+ (a==p && b==p && c==p && d==p && e==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern3 :: Int -> Int -> Int -> Int -> Int -> Int -> Bool
+ pattern3 a b c d e p | (a==0 && b==p && c==p && d==p && e==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern4 :: Int -> Int -> Int -> Int -> Int -> Bool
+ pattern4 a b c d p | (a==0 && b==p && c==p && d==p) ||
+ (a==p && b==p && c==p && d==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern5 :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool
+ pattern5 a b c d e f p | (a==0 && b==p && c==p && d==0 && e==p &&
+ f==0) ||
+ (a==0 && b==p && c==0 && d==p && e==p &&
+ f==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern6 :: Int -> Int -> Int -> Int -> Int -> Int -> Bool
+ pattern6 a b c d e p | (a==0 && b==p && c==p && d==0 && e==p) ||
+ (a==0 && b==p && c==0 && d==p && e==p) ||
+ (a==p && b==p && c==0 && d==p && e==0) ||
+ (a==p && b==0 && c==p && d==p && e==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern7 :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int-> Bool
+ pattern7 a b c d e f g p | (a==0 && b==p && c==0 && d==p && e==0 &&
+ f==p && g==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern8 :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Bool
+ pattern8 a b c d e f p | (a==0 && b==p && c==0 && d==p && e==0 &&
+ f==p) ||
+ (a==p && b==0 && c==p && d==0 && e==p &&
+ f==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern9 :: Int -> Int -> Int -> Int -> Int -> Bool
+ pattern9 a b c d p | (a==0 && b==p && c==p && d==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern10 :: Int -> Int -> Int -> Int -> Bool
+ pattern10 a b c p | (a==0 && b==p && c==p) ||
+ (a==p && b==p && c==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern11 :: Int -> Int -> Int -> Int -> Int -> Int -> Bool
+ pattern11 a b c d e p | (a==0 && b==p && c==0 && d==p && e==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ pattern12 :: Int -> Int -> Int -> Int -> Int -> Bool
+ pattern12 a b c d p | (a==0 && b==p && c==0 && d==p) ||
+ (a==p && b==0 && c==p && d==0) = True
+ | otherwise = False
+----------------------------------------------------------------------------
+
+ direct1 :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int ->
+ Int -> Int -> Int -> Int -> Int -> Int
+ direct1 x y pl ptN1 ptN2 ptN3 ptN4 ptN5 pt ptP1 ptP2 ptP3 ptP4 ptP5
+ | (pattern0 ptN4 ptN3 ptN2 ptN1 pt pl) ||
+ (pattern0 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern0 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern0 ptN1 pt ptP1 ptP2 ptP3 pl) ||
+ (pattern0 pt ptP1 ptP2 ptP3 ptP4 pl) = 200
+ | (pattern1 ptN4 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern1 ptN3 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern1 ptN2 ptN1 pt ptP1 ptP2 ptP3 pl) ||
+ (pattern1 ptN1 pt ptP1 ptP2 ptP3 ptP4 pl) = 40
+ | (pattern2 ptN4 ptN3 ptN2 ptN1 pt pl) ||
+ (pattern2 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern2 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern2 ptN1 pt ptP1 ptP2 ptP3 pl) = 13
+ | (pattern3 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern3 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern3 ptN1 pt ptP1 ptP2 ptP3 pl) = 10
+ | (pattern4 ptN3 ptN2 ptN1 pt pl) ||
+ (pattern4 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern4 ptN1 pt ptP1 ptP2 pl) = 8
+ | (pattern5 ptN4 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern5 ptN3 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern5 ptN2 ptN1 pt ptP1 ptP2 ptP3 pl) ||
+ (pattern5 ptN1 pt ptP1 ptP2 ptP3 ptP4 pl) = 9
+ | (pattern6 ptN4 ptN3 ptN2 ptN1 pt pl) ||
+ (pattern6 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern6 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern6 ptN1 pt ptP1 ptP2 ptP3 pl) = 7
+ | (pattern7 ptN5 ptN4 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern7 ptN4 ptN3 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern7 ptN3 ptN2 ptN1 pt ptP1 ptP2 ptP3 pl) ||
+ (pattern7 ptN2 ptN1 pt ptP1 ptP2 ptP3 ptP4 pl) ||
+ (pattern7 ptN1 pt ptP1 ptP2 ptP3 ptP4 ptP5 pl) = 6
+ | (pattern8 ptN5 ptN4 ptN3 ptN2 ptN1 pt pl) ||
+ (pattern8 ptN4 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern8 ptN3 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern8 ptN2 ptN1 pt ptP1 ptP2 ptP3 pl) ||
+ (pattern8 ptN1 pt ptP1 ptP2 ptP3 ptP4 pl) ||
+ (pattern8 pt ptP1 ptP2 ptP3 ptP4 ptP5 pl) = 5
+ | (pattern9 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern9 ptN1 pt ptP1 ptP2 pl) = 4
+ | (pattern10 ptN2 ptN1 pt pl) ||
+ (pattern10 ptN1 pt ptP1 pl) ||
+ (pattern10 pt ptP1 ptP2 pl) = 2
+ | (pattern11 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern11 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern11 ptN1 pt ptP1 ptP2 ptP3 pl) = 3
+ | (pattern12 ptN3 ptN2 ptN1 pt pl) ||
+ (pattern12 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern12 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern12 pt ptP1 ptP2 ptP3 pl) = 1
+ | otherwise = 0
+----------------------------------------------------------------------------
+
+ direct2 :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int ->
+ Int -> Int -> Int -> Int -> Int -> Int
+ direct2 x y pl ptN1 ptN2 ptN3 ptN4 ptN5 pt ptP1 ptP2 ptP3 ptP4 ptP5
+ | (pattern0 ptN4 ptN3 ptN2 ptN1 pt pl) ||
+ (pattern0 ptN3 ptN2 ptN1 pt ptP1 pl) ||
+ (pattern0 ptN2 ptN1 pt ptP1 ptP2 pl) ||
+ (pattern0 ptN1 pt ptP1 ptP2 ptP3 pl) ||
+ (pattern0 pt ptP1 ptP2 ptP3 ptP4 pl) = 200
+ | otherwise = 0
+-----------------------------------------------------------------------------
+
+ cpt_weight :: Int -> Int -> Int -> IO Int
+ cpt_weight x y player =
+ xMArrayLookup keyboard ((x-1)*19+(y-1)) `thenIO` \(unit) ->
+ if (unit /= 0)
+ then returnIO (-1)
+ else xlookup keyboard x (y-1) `thenIO` \(xyN1) ->
+ xlookup keyboard x (y-2) `thenIO` \(xyN2) ->
+ xlookup keyboard x (y-3) `thenIO` \(xyN3) ->
+ xlookup keyboard x (y-4) `thenIO` \(xyN4) ->
+ xlookup keyboard x (y-5) `thenIO` \(xyN5) ->
+ xlookup keyboard x (y+1) `thenIO` \(xyP1) ->
+ xlookup keyboard x (y+2) `thenIO` \(xyP2) ->
+ xlookup keyboard x (y+3) `thenIO` \(xyP3) ->
+ xlookup keyboard x (y+4) `thenIO` \(xyP4) ->
+ xlookup keyboard x (y+5) `thenIO` \(xyP5) ->
+ xlookup keyboard (x-1) y `thenIO` \(xN1y) ->
+ xlookup keyboard (x-2) y `thenIO` \(xN2y) ->
+ xlookup keyboard (x-3) y `thenIO` \(xN3y) ->
+ xlookup keyboard (x-4) y `thenIO` \(xN4y) ->
+ xlookup keyboard (x-5) y `thenIO` \(xN5y) ->
+ xlookup keyboard (x+1) y `thenIO` \(xP1y) ->
+ xlookup keyboard (x+2) y `thenIO` \(xP2y) ->
+ xlookup keyboard (x+3) y `thenIO` \(xP3y) ->
+ xlookup keyboard (x+4) y `thenIO` \(xP4y) ->
+ xlookup keyboard (x+5) y `thenIO` \(xP5y) ->
+ xlookup keyboard (x-1) (y-1) `thenIO` \(xN1yN1)->
+ xlookup keyboard (x-2) (y-2) `thenIO` \(xN2yN2) ->
+ xlookup keyboard (x-3) (y-3) `thenIO` \(xN3yN3) ->
+ xlookup keyboard (x-4) (y-4) `thenIO` \(xN4yN4) ->
+ xlookup keyboard (x-5) (y-5) `thenIO` \(xN5yN5) ->
+ xlookup keyboard (x+1) (y+1) `thenIO` \(xP1yP1) ->
+ xlookup keyboard (x+2) (y+2) `thenIO` \(xP2yP2) ->
+ xlookup keyboard (x+3) (y+3) `thenIO` \(xP3yP3) ->
+ xlookup keyboard (x+4) (y+4) `thenIO` \(xP4yP4) ->
+ xlookup keyboard (x+5) (y+5) `thenIO` \(xP5yP5) ->
+ xlookup keyboard (x-1) (y+1) `thenIO` \(xN1yP1) ->
+ xlookup keyboard (x-2) (y+2) `thenIO` \(xN2yP2) ->
+ xlookup keyboard (x-3) (y+3) `thenIO` \(xN3yP3) ->
+ xlookup keyboard (x-4) (y+4) `thenIO` \(xN4yP4) ->
+ xlookup keyboard (x-5) (y+5) `thenIO` \(xN5yP5) ->
+ xlookup keyboard (x+1) (y-1) `thenIO` \(xP1yN1) ->
+ xlookup keyboard (x+2) (y-2) `thenIO` \(xP2yN2) ->
+ xlookup keyboard (x+3) (y-3) `thenIO` \(xP3yN3) ->
+ xlookup keyboard (x+4) (y-4) `thenIO` \(xP4yN4) ->
+ xlookup keyboard (x+5) (y-5) `thenIO` \(xP5yN5) ->
+ returnIO ( (direct1 x y player xyN1 xyN2 xyN3 xyN4 xyN5 player
+ xyP1 xyP2 xyP3 xyP4 xyP5) +
+ (direct1 x y player xN1y xN2y xN3y xN4y xN5y player
+ xP1y xP2y xP3y xP4y xP5y) +
+ (direct1 x y player xN1yN1 xN2yN2 xN3yN3 xN4yN4
+ xN5yN5 player xP1yP1 xP2yP2 xP3yP3 xP4yP4
+ xP5yP5) +
+ (direct1 x y player xN1yP1 xN2yP2 xN3yP3 xN4yP4
+ xN5yP5 player xP1yN1 xP2yN2 xP3yN3 xP4yN4
+ xP5yN5) )
+-----------------------------------------------------------------------------
+
+-- | 1111 && no_block = 20
+-- | 1111 && one_block = 13
+-- | 111 && no_block = 10
+-- | 111 && one_block = 8
+-- | 11 1 or 1 11 && no_block = 9
+-- | 11 1 or 1 11 && one_block =7
+-- | 1 1 1 && no_block = 6
+-- | 1 1 1 && one_block= 5
+-- | 11 && no_block = 4
+-- | 11 && one_block =2
+-- | 1 1 && no_block =3
+-- | 1 1 && one_block=1
+
+ in
+ update_weight weight1 0 1 x y 1 1 `thenIO` \() ->
+ update_weight weight2 0 2 x y 1 1 `thenIO` \() ->
+ update_weight weight1 0 1 x y 1 (-1) `thenIO` \() ->
+ update_weight weight2 0 2 x y 1 (-1) `thenIO` \() ->
+ update_weight weight1 0 1 x y (-1) (-1) `thenIO` \() ->
+ update_weight weight2 0 2 x y (-1) (-1) `thenIO` \() ->
+ update_weight weight1 0 1 x y (-1) 1 `thenIO` \() ->
+ update_weight weight2 0 2 x y (-1) 1 `thenIO` \() ->
+ update_weight weight1 0 1 x y 0 1 `thenIO` \() ->
+ update_weight weight2 0 2 x y 0 1 `thenIO` \() ->
+ update_weight weight1 0 1 x y 0 (-1) `thenIO` \() ->
+ update_weight weight2 0 2 x y 0 (-1) `thenIO` \() ->
+ update_weight weight1 0 1 x y (-1) 0 `thenIO` \() ->
+ update_weight weight2 0 2 x y (-1) 0 `thenIO` \() ->
+ update_weight weight1 0 1 x y 1 0 `thenIO` \() ->
+ update_weight weight2 0 2 x y 1 0 `thenIO` \() ->
+ returnIO ()
+
+
+human_unit :: XMArray Int -> Int -> Int -> IO(Bool)
+human_unit keyboard x y =
+ let
+ pattern0 :: Int -> Int -> Int -> Int -> Int -> Bool
+ pattern0 a b c d e | a==b && b==c && c==d && d==e = True
+ | otherwise = False
+
+ direct3 :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int ->
+ Int
+ direct3 ptN1 ptN2 ptN3 ptN4 pt ptP1 ptP2 ptP3 ptP4
+ | (pattern0 ptN4 ptN3 ptN2 ptN1 pt) ||
+ (pattern0 ptN3 ptN2 ptN1 pt ptP1) ||
+ (pattern0 ptN2 ptN1 pt ptP1 ptP2) ||
+ (pattern0 ptN1 pt ptP1 ptP2 ptP3) ||
+ (pattern0 pt ptP1 ptP2 ptP3 ptP4) = 200
+ | otherwise = 0
+ in
+ xlookup keyboard x y `thenIO` \(xy) ->
+ xlookup keyboard x (y-1) `thenIO` \(xyN1) ->
+ xlookup keyboard x (y-2) `thenIO` \(xyN2) ->
+ xlookup keyboard x (y-3) `thenIO` \(xyN3) ->
+ xlookup keyboard x (y-4) `thenIO` \(xyN4) ->
+ xlookup keyboard x (y+1) `thenIO` \(xyP1) ->
+ xlookup keyboard x (y+2) `thenIO` \(xyP2) ->
+ xlookup keyboard x (y+3) `thenIO` \(xyP3) ->
+ xlookup keyboard x (y+4) `thenIO` \(xyP4) ->
+ xlookup keyboard (x-1) y `thenIO` \(xN1y) ->
+ xlookup keyboard (x-2) y `thenIO` \(xN2y) ->
+ xlookup keyboard (x-3) y `thenIO` \(xN3y) ->
+ xlookup keyboard (x-4) y `thenIO` \(xN4y) ->
+ xlookup keyboard (x+1) y `thenIO` \(xP1y) ->
+ xlookup keyboard (x+2) y `thenIO` \(xP2y) ->
+ xlookup keyboard (x+3) y `thenIO` \(xP3y) ->
+ xlookup keyboard (x+4) y `thenIO` \(xP4y) ->
+ xlookup keyboard (x-1) (y-1) `thenIO` \(xN1yN1)->
+ xlookup keyboard (x-2) (y-2) `thenIO` \(xN2yN2) ->
+ xlookup keyboard (x-3) (y-3) `thenIO` \(xN3yN3) ->
+ xlookup keyboard (x-4) (y-4) `thenIO` \(xN4yN4) ->
+ xlookup keyboard (x+1) (y+1) `thenIO` \(xP1yP1) ->
+ xlookup keyboard (x+2) (y+2) `thenIO` \(xP2yP2) ->
+ xlookup keyboard (x+3) (y+3) `thenIO` \(xP3yP3) ->
+ xlookup keyboard (x+4) (y+4) `thenIO` \(xP4yP4) ->
+ xlookup keyboard (x-1) (y+1) `thenIO` \(xN1yP1) ->
+ xlookup keyboard (x-2) (y+2) `thenIO` \(xN2yP2) ->
+ xlookup keyboard (x-3) (y+3) `thenIO` \(xN3yP3) ->
+ xlookup keyboard (x-4) (y+4) `thenIO` \(xN4yP4) ->
+ xlookup keyboard (x+1) (y-1) `thenIO` \(xP1yN1) ->
+ xlookup keyboard (x+2) (y-2) `thenIO` \(xP2yN2) ->
+ xlookup keyboard (x+3) (y-3) `thenIO` \(xP3yN3) ->
+ xlookup keyboard (x+4) (y-4) `thenIO` \(xP4yN4) ->
+ xlookup keyboard (x+1) y `thenIO` \(xP1y) ->
+ xlookup keyboard (x+2) y `thenIO` \(xP2y) ->
+ xlookup keyboard (x+3) y `thenIO` \(xP3y) ->
+ xlookup keyboard (x+4) y `thenIO` \(xP4y) ->
+ if ((direct3 xyN1 xyN2 xyN3 xyN4 xy xyP1 xyP2 xyP3 xyP4) +
+ (direct3 xN1y xN2y xN3y xN4y xy xP1y xP2y xP3y xP4y) +
+ (direct3 xN1yN1 xN2yN2 xN3yN3 xN4yN4 xy xP1yP1 xP2yP2 xP3yP3 xP4yP4) +
+ (direct3 xN1yP1 xN2yP2 xN3yP3 xN4yP4 xy xP1yN1 xP2yN2 xP3yN3 xP4yN4))
+ >=200
+ then returnIO (True)
+ else returnIO (False) \ No newline at end of file
diff --git a/progs/demo/X11/gobang/weights.hu b/progs/demo/X11/gobang/weights.hu
new file mode 100644
index 0000000..f13aba0
--- /dev/null
+++ b/progs/demo/X11/gobang/weights.hu
@@ -0,0 +1,4 @@
+:o= all
+$HASKELL_LIBRARY/X11/xlib.hu
+weights.hs
+utilities.hs
diff --git a/progs/demo/X11/graphics/README b/progs/demo/X11/graphics/README
new file mode 100644
index 0000000..77a2d66
--- /dev/null
+++ b/progs/demo/X11/graphics/README
@@ -0,0 +1,31 @@
+HENDERSON GRAPHICS LIBRARY
+by Syam Gadde
+and Bo Whong
+
+-------------------------------------------------
+
+To use the Henderson Library, run emacs with a module that
+imports HendersonLib, such as "sqrlmt.hs". For "sqrlmt.hs",
+run the dialogue "final" or "skewedfinal".
+
+-------------------------------------------------
+
+henderson.hs - Haskell source for the Henderson library.
+henderson.hu
+sqrlmt.hs - Haskell source for dialogue that draws "Square Limit".
+sqrlmt.hu
+p.pic - First of four pictures used to construct "Square Limit".
+q.pic - Second of four pictures used to construct "Square Limit".
+r.pic - Third of four pictures used to construct "Square Limit".
+s.pic - Four of four pictures used to construct "Square Limit".
+new.pic - Hudak's house
+stop.pic - A "hand-drawn" stop sign border
+text.pic - The word "STOP!" (hand-drawn)
+strange.pic - Overlays stop.pic and Flip of text.pic
+squarebox.xwd - A window dump of a box-like structure made of four
+ square limits. Use "xwud -in squarebox.xwd" to view.
+sksl.xwd - A window dump of "squarelimit" in a skewed bounding box.
+ ("skewedfinal" from sqrlmt.hs.)
+sl.xwd - A window dump of Square Limit.
+ ("squarelimit" from sqrlmt.hs.)
+manual - The manual in Island Write format.
diff --git a/progs/demo/X11/graphics/henderson.hs b/progs/demo/X11/graphics/henderson.hs
new file mode 100644
index 0000000..8b7e4ce
--- /dev/null
+++ b/progs/demo/X11/graphics/henderson.hs
@@ -0,0 +1,465 @@
+-- Peter Henderson's Recursive Geometry
+-- Syam Gadde and Bo Whong
+-- full set of modules
+-- CS429 Project
+-- 4/30/93
+
+module HendersonLib (Hostname(..), Filename(..), VTriple(..), HendQuartet(..),
+ Picture(..), sendToDraw, draw, create, modify, plot) where
+import Xlib
+
+-- ADTs and Type Synonyms --------------------------------------------------
+data Picture = Nil
+ | Flip Picture
+ | Beside Float Picture Float Picture
+ | Above Float Picture Float Picture
+ | Rot Picture
+ | File String
+ | Overlay Picture Picture
+ | Grid Int Int SegList
+ deriving Text
+
+data Plot = Plot Picture VTriple
+ | Union Plot Plot
+
+type Hostname = String
+type Filename = String
+type IntPoint = (Int,Int)
+type IntSegment = (IntPoint, IntPoint)
+type IntSegList = [IntSegment]
+type Point = (Float,Float)
+type Segment = (Point, Point)
+type SegList = [Segment]
+type Vector = Point
+type VTriple = (Vector, Vector, Vector)
+type HendQuartet = (Int, Int, Int, Int)
+type PEnv = [(Filename, Picture)]
+
+-- vector Functions --------------------------------------------------------
+-- for adding, negating, multiplying, and dividing vectors
+
+addV :: Vector -> Vector -> Vector
+addV (x1,y1) (x2,y2) = (x1+x2, y1+y2)
+
+negateV :: Vector -> Vector
+negateV (x,y) = (-x,-y)
+
+multV :: Float-> Vector -> Vector
+multV a (x,y) = (a*x, a*y)
+
+divV :: Float -> Vector -> Vector
+divV a (x,y) = (x/a, y/a)
+
+-- plot Function -----------------------------------------------------------
+-- picture manipulation function
+
+plot :: Picture -> VTriple -> PEnv -> ((Plot, PEnv) -> IO()) -> IO()
+
+-- the Nil Picture is just "nothingness" so choose an abritrary representation
+-- of nothingness.
+plot Nil (v1, v2, v3) env cont =
+ plot (Grid 1 1 []) (v1,v2,v3) env cont
+
+-- Flipping a Picture
+plot (Flip p1) (v1, v2, v3) env cont =
+ plot p1 (addV v1 v2, negateV v2, v3) env cont
+
+-- Rotate a Picture 90 degrees counterclockwise
+plot (Rot p1) (v1, v2, v3) env cont =
+ plot p1 (addV v1 v3, negateV v3, v2) env cont
+
+-- Overlay one Picture over another Picture
+plot (Overlay p q) (a,b,c) env cont =
+ plot p (a,b,c) env $ \ (plot1, env1) ->
+ plot q (a,b,c) env1 $ \ (plot2, env2) ->
+ cont ((Union plot1 plot2), env2)
+
+-- Place p1 Beside p2 with width ratio m to n
+plot (Beside m p1 n p2) (v1, v2, v3) env cont =
+ plot p1 (v1, multV (m/(m+n)) v2, v3) env $ \ (plot1, env1) ->
+ plot p2 ((addV (multV (m/(m+n)) v2) v1),
+ (multV (n/(m+n)) v2),
+ v3) env1 $ \ (plot2, env2) ->
+ cont ((Union plot1 plot2), env2)
+
+-- Place p Above q with height ratio m to n
+plot (Above m p n q) (a,b,c) env cont =
+ plot q (addV a (multV (m/(n+m)) c), b, multV (n/(m+n)) c) env
+ $ \ (plot1, env1) ->
+ plot p (a, b, multV (m/(m+n)) c) env1 $ \ (plot2, env2) ->
+ cont ((Union plot1 plot2), env2)
+
+-- the 'real' Picture
+plot (Grid x y s) (a,b,c) env cont =
+ cont ((Plot (Grid x y s) (a,b,c)), env)
+
+-- this picture is located in a File with name name
+-- lookup table: thanks to Sheng
+plot (File name) (a,b,c) env cont =
+ case (lookupEnv env name) of
+ ((_, pic):_) -> plot pic (a,b,c) env cont
+ [] ->
+ readFile name (\s -> appendChan stdout ("File "++name++" not able to be read\n") exit done)
+ $ \s ->
+ let
+ pic = read s
+ newenv = (name,pic):env
+ in
+ plot pic (a,b,c) newenv cont
+
+lookupEnv :: PEnv -> Filename -> PEnv
+lookupEnv [] _ = []
+lookupEnv ((a,b):es) name | a==name = ((a,b):es)
+ | otherwise = lookupEnv es name
+
+-- Draw Function -----------------------------------------------------------
+-- user function to draw pictures
+
+draw :: Hostname -> Picture -> VTriple -> HendQuartet -> IO()
+
+-- opens a display, screen, and window (of size specified in HendQuartet)
+-- and draws Picture in the window
+draw host p (a,b,c) (hm,hn,ho,hp) =
+ xOpenDisplay host `thenIO` \display -> -- opens display
+ let (screen:_) = xDisplayRoots display
+ fg_color = xScreenBlackPixel screen
+ bg_color = xScreenWhitePixel screen
+ root = xScreenRoot screen
+ in
+ xCreateWindow root -- opens window
+ (XRect hm hn ho hp)
+ [XWinBackground bg_color,
+ XWinEventMask (XEventMask [XKeyPress,
+ XExposure,
+ XButtonPress])]
+ `thenIO` \window ->
+ xSetWmName window "Henderson Graphics" `thenIO` \() ->
+ xSetWmIconName window "Henderson Graphics" `thenIO` \() ->
+ xMapWindow window `thenIO` \() -> -- show window
+ xDisplayForceOutput display `thenIO` \ () -> -- show window NOW
+ xCreateGcontext (XDrawWindow (xScreenRoot screen)) -- open a GC
+ [XGCBackground bg_color,
+ XGCForeground fg_color] `thenIO` \ gcontext ->
+ plot p (a,b,c) [] $ \(plt,_) -> -- make pic easier to work with
+ let
+ handleEvent =
+ xGetEvent display `thenIO` \event ->
+ case (xEventType event) of
+ -- Has a part of the window been uncovered?
+ XExposureEvent -> sendToDraw window screen display gcontext plt
+ `thenIO` \() -> handleEvent
+ _ -> xCloseDisplay display
+ in
+ handleEvent
+
+-- SendToDraw Function -----------------------------------------------------
+-- called by draw to actually draw the lines onto the window
+
+sendToDraw :: XWindow -> XScreen -> XDisplay -> XGcontext -> Plot -> IO()
+
+-- have a Union. so do one, and then the other. simple.
+sendToDraw win screen display gcontext (Union p1 p2) =
+ sendToDraw win screen display gcontext p1 `thenIO` \() ->
+ sendToDraw win screen display gcontext p2
+
+-- have just a Plot. have to do some dirty work.
+sendToDraw window screen display gcontext (Plot (Grid x y s) (a,b,c)) =
+ let
+ v2p :: Vector -> XPoint
+ v2p (e,f) = XPoint (round e) (round f) -- convert Vector to an XPoint
+ fx :: Float
+ fx = fromIntegral x
+ fy :: Float
+ fy = fromIntegral y
+ drawit :: SegList -> IO()
+ -- draw the Grid one line at a time
+ drawit [] = done
+ drawit (((x0,y0),(x1,y1)):ss) =
+ xDrawLine (XDrawWindow window)
+ gcontext
+ (v2p (addV (addV a (multV (x0/fx) b))
+ (multV (y0/fy) c)))
+ (v2p (addV (addV a (multV (x1/fx) b))
+ (multV (y1/fy) c))) `thenIO` \() ->
+ drawit ss
+ in
+ drawit s `thenIO` \ () ->
+ xDisplayForceOutput display
+
+-- create function ---------------------------------------------------------
+-- opens up a window to allow the user to create a file
+-- and save it onto a file
+
+create :: Hostname -> Filename -> Int -> Int -> IO()
+
+create host filename x y =
+ xOpenDisplay host `thenIO` \ display ->
+ let
+ (screen:_) = xDisplayRoots display
+ fg_color = xScreenWhitePixel screen
+ bg_color = xScreenBlackPixel screen
+ root = xScreenRoot screen
+ in
+ xCreateWindow root
+ (XRect 0 0 (x+1) (y+1))
+ [XWinBackground bg_color,
+ XWinEventMask (XEventMask [XExposure,
+ XKeyPress,
+ XButtonPress,
+ XPointerMotion])]
+ `thenIO` \window ->
+ xSetWmName window filename `thenIO` \() ->
+ xSetWmIconName window filename `thenIO` \() ->
+ xCreateWindow root
+ (XRect 0 0 100 40)
+ [XWinBackground bg_color] `thenIO` \window2 ->
+ xSetWmName window2 "pos" `thenIO` \() ->
+ xSetWmIconName window2 "pos" `thenIO` \() ->
+ xMapWindow window `thenIO` \() ->
+ xMapWindow window2 `thenIO` \() ->
+ xListFonts display "*times*bold*r*normal*18*" `thenIO` \fontlist ->
+ xCreateGcontext (XDrawWindow root)
+ [XGCBackground bg_color,
+ XGCForeground fg_color,
+ XGCFont (head fontlist)] `thenIO` \gcontext ->
+ let
+ handleEvent :: IntSegList -> IO()
+ handleEvent list =
+ xGetEvent display `thenIO` \event ->
+ let
+ point = xEventPos event
+ XPoint pointx pointy = point
+ handleEvent' :: XPoint -> IO()
+ handleEvent' last =
+ xGetEvent display `thenIO` \event2 ->
+ let
+ pos = xEventPos event2
+ XPoint posx posy = pos
+ in
+ case (xEventType event2) of
+ XKeyPressEvent ->
+ appendChan stdout ((show (tup pos))++ "\n") abort $
+ xDrawLine (XDrawWindow window) gcontext point pos
+ `thenIO` \() -> handleEvent (store list point pos)
+ XExposureEvent ->
+ redraw window gcontext list `thenIO` \() -> handleEvent' last
+ XMotionNotifyEvent ->
+ xDrawImageGlyphs (XDrawWindow window2)
+ gcontext
+ (XPoint 2 18)
+ ((show posx)++", "++(show posy)++" ")
+ `thenIO` \dummy -> handleEvent' last
+ _ ->
+ handleEvent' last
+ in
+ case (xEventType event) of
+ XButtonPressEvent ->
+ putFile display filename list x y "create"
+ XKeyPressEvent ->
+ appendChan stdout (show (tup point)) abort $
+ handleEvent' point
+ XExposureEvent ->
+ redraw window gcontext list `thenIO` \() -> handleEvent list
+ XMotionNotifyEvent ->
+ xDrawImageGlyphs (XDrawWindow window2)
+ gcontext
+ (XPoint 2 18)
+ ((show pointx)++", "++(show pointy)++" ")
+ `thenIO` \dummy -> handleEvent list
+ _ ->
+ handleEvent list
+ in
+ case (checkFile filename) of
+ True -> handleEvent []
+ False -> appendChan stdout picTypeError abort $
+ xCloseDisplay display
+
+-- modify function ---------------------------------------------------------
+-- allows the user to add onto an already existing picture file
+
+modify :: Hostname -> Filename -> IO()
+
+modify host filename =
+ case (checkFile filename) of
+ False -> appendChan stdout picTypeError abort done
+ True ->
+ readFile filename (\s -> appendChan stdout
+ readError abort done) $ \s->
+ let
+ dat = read s
+ origlist = fFloat (getlist dat)
+ x = getx dat
+ y = gety dat
+ in
+ xOpenDisplay host `thenIO` \ display ->
+ let
+ (screen:_) = xDisplayRoots display
+ fg_color = xScreenWhitePixel screen
+ bg_color = xScreenBlackPixel screen
+ root = xScreenRoot screen
+ in
+ xCreateWindow root
+ (XRect 0 0 (x + 1) (y + 1))
+ [XWinBackground bg_color,
+ XWinEventMask (XEventMask [XExposure, XKeyPress,
+ XButtonPress, XPointerMotion])]
+ `thenIO` \window ->
+ xSetWmName window filename `thenIO` \() ->
+ xSetWmIconName window filename `thenIO` \() ->
+ xCreateWindow root (XRect 0 0 100 40)
+ [XWinBackground bg_color] `thenIO` \window2 ->
+ xSetWmName window2 "pos" `thenIO` \() ->
+ xSetWmIconName window2 "pos" `thenIO` \() ->
+ xMapWindow window `thenIO` \() ->
+ xMapWindow window2 `thenIO` \() ->
+ xListFonts display "*times*bold*r*normal*18*" `thenIO` \fontlist ->
+ xCreateGcontext (XDrawWindow root) [XGCBackground bg_color,
+ XGCForeground fg_color,
+ XGCFont (head fontlist)]
+ `thenIO` \ gcontext ->
+ let
+ handleEvent :: IntSegList -> IO()
+ handleEvent list =
+ xGetEvent display `thenIO` \event ->
+ let
+ point = xEventPos event
+ XPoint pointx pointy = point
+ handleEvent' :: XPoint -> IO()
+ handleEvent' last = xGetEvent display `thenIO` \event2 ->
+ let
+ pos = xEventPos event2
+ XPoint posx posy = pos
+ in
+ case (xEventType event2) of
+ XExposureEvent ->
+ redraw window gcontext list `thenIO` \() ->
+ handleEvent' last
+ XKeyPressEvent ->
+ appendChan stdout ((show (tup pos))++ "\n") abort $
+ xDrawLine (XDrawWindow window) gcontext point pos
+ `thenIO` \() -> handleEvent (store list point pos)
+ XMotionNotifyEvent ->
+ xDrawImageGlyphs (XDrawWindow window2) gcontext
+ (XPoint 2 18) ((show posx)++", "++(show posy)++" ")
+ `thenIO` \dummy -> handleEvent' last
+ _ -> handleEvent' last
+ in
+ case (xEventType event) of
+ XButtonPressEvent ->
+ putFile display filename list x y "modify"
+ XKeyPressEvent ->
+ appendChan stdout (show (tup point)) abort $
+ handleEvent' point
+ XExposureEvent ->
+ redraw window gcontext list `thenIO` \() ->
+ handleEvent list
+ XMotionNotifyEvent ->
+ xDrawImageGlyphs (XDrawWindow window2)
+ gcontext (XPoint 2 18)
+ ((show pointx)++", "++(show pointy)++" ")
+ `thenIO` \dummy -> handleEvent list
+ _ ->
+ handleEvent list
+ in
+ redraw window gcontext origlist `thenIO` \() ->
+ handleEvent origlist
+
+-- Miscellaneous functions -------------------------------------------------
+-- shared by the create and modify functions
+
+checkFile :: Filename -> Bool
+checkFile name =
+ case (take 4 (reverse name)) of
+ "cip." -> True
+ _ -> False
+
+store :: IntSegList -> XPoint -> XPoint -> IntSegList
+store l a b = [((xof a,yof a),(xof b,yof b))] ++ l
+
+xof :: XPoint -> Int
+xof (XPoint x y) = x
+
+yof :: XPoint -> Int
+yof (XPoint x y) = y
+
+tup :: XPoint -> IntPoint
+tup (XPoint a b) = (a,b)
+
+ll:: IntSegment -> Int
+ll ((a1,a2),(b1,b2)) = a1
+
+lr:: IntSegment -> Int
+lr ((a1,a2),(b1,b2)) = a2
+
+rl:: IntSegment -> Int
+rl ((a1,a2),(b1,b2)) = b1
+
+rr:: IntSegment -> Int
+rr ((a1,a2),(b1,b2)) = b2
+
+getx :: Picture -> Int
+getx (Grid m n o) = m
+
+gety :: Picture -> Int
+gety(Grid m n o) = n
+
+getlist :: Picture -> SegList
+getlist (Grid m n o) = o
+
+fFloat :: SegList -> IntSegList
+fFloat = map (\ ((ix,iy),(jx,jy)) ->
+ ((round ix,round iy), (round jx,round jy)))
+
+readError :: String
+readError = "Error: reading an invalid file\n"
+
+picTypeError :: String
+picTypeError = "Error: files need to be of .pic type\n"
+
+deleteError :: String
+deleteError = "Error: file can not be deleted\n"
+
+writeError :: String
+writeError = "Error: file can not be written\n"
+
+modError :: String
+modError = "Error: file can not be modified\n"
+
+redraw :: XWindow-> XGcontext -> IntSegList -> IO()
+redraw window gcontext [] = done
+redraw window gcontext (l:ls) =
+ xDrawLine (XDrawWindow window) gcontext (XPoint (ll l) (lr l))
+ (XPoint (rl l) (rr l))
+ `thenIO` \() -> redraw window gcontext ls
+
+changeList :: IntSegList -> SegList
+changeList =
+ map (\ ((ix,iy),(jx,jy)) -> ((fromIntegral ix,fromIntegral iy),
+ (fromIntegral jx,fromIntegral jy)))
+
+putFile :: XDisplay -> Filename -> IntSegList ->
+ Int -> Int -> String -> IO()
+putFile display name list x y flag =
+ let
+ text = show (Grid x y (changeList list))
+ finishMsg = name ++ ": Done...Process completed\n"
+ modMsg = name ++ ": Modifying file\n"
+ createMsg = name ++ ": Creating file\n"
+ continue =
+ deleteFile name (\s -> appendChan stdout deleteError abort done) $
+ writeFile name text (\s -> appendChan stdout writeError abort done) $
+ appendChan stdout finishMsg abort $
+ xCloseDisplay display
+ in
+ case (flag == "create") of
+ False -> appendChan stdout modMsg
+ (\s -> appendChan stdout modError abort done) $
+ continue
+ True -> readFile name (\s -> appendChan stdout createMsg abort $
+ writeFile name text abort
+ (xCloseDisplay display)) $ \s ->
+ continue
+
+
+
+
diff --git a/progs/demo/X11/graphics/henderson.hu b/progs/demo/X11/graphics/henderson.hu
new file mode 100644
index 0000000..e92b66d
--- /dev/null
+++ b/progs/demo/X11/graphics/henderson.hu
@@ -0,0 +1,3 @@
+:o= foldr inline constant
+$HASKELL_LIBRARY/X11/xlib.hu
+henderson.hs
diff --git a/progs/demo/X11/graphics/manual b/progs/demo/X11/graphics/manual
new file mode 100644
index 0000000..17772f1
--- /dev/null
+++ b/progs/demo/X11/graphics/manual
@@ -0,0 +1,454 @@
+104 pgscriptver
+
+100 DefSpaceEx 100 DefCharEx 1 DefNormalHyphenationOn 100
+DefTypeColor (Times-Roman) DefTypeFace ENGLISH DefLanguage 12 DefPointSize
+USE_POINTSIZE DefSetSize (@default) DefTypeResource
+
+LEFT DefJustifyFlags 2 DefBeginParaLeadValue ABSOLUTE DefBeginParaLeadMode 2
+DefEndParaLeadValue ABSOLUTE DefEndParaLeadMode 120 DefLeadValue
+PROPORTIONAL DefLeadMode 1 46 0 TAB_LEFT 720 DefTab 1 46 0
+TAB_LEFT 2160 DefTab 1 46 0 TAB_LEFT 3600 DefTab 1 46 0
+TAB_LEFT 5040 DefTab 1 46 0 TAB_LEFT 6480 DefTab 1 46 0
+TAB_LEFT 7920 DefTab 1 46 0 TAB_LEFT 9360 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 0 46 0 TAB_LEFT 24480 DefTab 0 46 0
+TAB_LEFT 24480 DefTab 80 DefWSMN 100 DefWSNM 150 DefWSMX 110
+DefLSMX 100 DefLeaderEx 46 DefLeaderChar 0 DefFirstIndent 0
+DefLeftIndent 0 DefRightIndent 0 DefNumberingOn 0 DefNumberingType 0
+DefNumberingRestart 1 DefNumberingLevel 0 DefNumberingStyle 0
+DefNumberingTabAfter 1 DefNumberingShowAllLevels 1 DefNumberingStart 1
+DefNumberingIncrement () DefNumberingPrefix () DefNumberingSuffix (.)
+DefNumberingSeparator (*default) DefParaResource
+
+0 DefLineWidth TRANSPARENT DefPenColor TRANSPARENT DefFillColor 1 DefIG 300
+DefResolution 100 DefYScale 100 DefXScale (=default) DefPolyResource
+
+0 DefPageDimensions 12240 DefPageWidth 15840 DefPageHeight 1440
+DefInsideMargin 1080 DefOutsideMargin 1080 DefTopMargin 1080
+DefBottomMargin 0 DefOrientation 0 DefPageStyle 1 DefColumns 360
+DefGutter (%default) DefMasterPage ResDefEnd
+
+0 DefFirstLeft 0 DefDocSetup 1 DefNumPages 1 AutoPage 1
+DefStartPageNum () DefPageNumPrefix 1 DefGraphicLocation document
+
+1 DefAutoPage
+0 (%default) 1 DefPage
+1 DefAutoPage
+0 (%default) 2 DefPage
+
+POLY_OBJECT POLY_EMPTY | DefPolyType
+
+0 DefLineWidth TRANSPARENT DefPenColor TRANSPARENT DefFillColor 1 DefIG 300
+DefResolution 100 DefYScale 100 DefXScale (=default) DefPolyResId 0
+DefMasterRef
+MP_CPSUCC_LINK MP_CPPRED_LINK POLY_COLUMN | | DefSLinksFlags 0 DefStreamSucc 0
+DefStreamPred
+1440 1080 11160 1080 11160 14760 1440 14760 4
+POLY_OBJECT POLY_EMPTY | (%default) 0 1 TextPolygon
+
+POLY_OBJECT POLY_TEXT | DefPolyType
+
+0 DefLineWidth TRANSPARENT DefPenColor TRANSPARENT DefFillColor 1 DefIG 300
+DefResolution 100 DefYScale 100 DefXScale (=default) DefPolyResId 1
+DefMasterRef
+
+MP_CPSUCC_LINK MP_CPPRED_LINK LINK_OVERFLOW MPREF_VALID POLY_COLUMN AUTO_STREAM | | | | |
+DefSLinksFlags 4 DefStreamSucc 0 DefStreamPred 3 DefTextHandle
+1440 1080 11160 1080 11160 14760 1440 14760 4
+POLY_OBJECT POLY_TEXT | (1) 0 2 TextPolygon
+
+3 asciitextstream
+<(Courier) cf ><9 cs>The Henderson Library--<eop>
+by Syam Gadde<eop>
+and Bo Whong<eop>
+<eop>
+The Henderson Library is a toolkit with which one can use Functional Geometry,
+as proposed by Peter Henderson in his paper "Functional Geometry". This is a s
+cheme by which "Picture"s can be described in an abstract data type, and a numb
+er of functions can be applied to it. This results in a very elegant method to
+ produce complex pictures from simple ones. The example Henderson uses is "Squ
+are Limit" by M. C. Escher, which can be constructed with four simple pictures
+.<eop>
+<eop>
+------------------------<eop>
+ADTs and Type Synonyms<eop>
+<eop>
+The Picture data type is composed of eight different types of pictures. They a
+re:<eop>
+<eop>
+data<eop>
+Picture = Nil - empty picture<eop>
+ | Flip Picture - picture flipped on the y-axis<e
+op>
+ | Beside Float Picture Float Picture - two pictures placed side by sid
+e <eop>
+ - in accordance to the ratio of t
+he<eop>
+ - two floats<eop>
+ | Above Float Picture Float Picture - two pictures placed one on top
+of<eop>
+ - another in accordance to the ra
+tio<eop>
+ - of the two floats<eop>
+ | Rot Picture - picture is rotated 90 degrees <
+eop>
+ - counterclockwise<eop>
+ | File String - picture is stored as an externa
+l<eop>
+ - file<eop>
+ | Overlay Picture Picture - two pictures are drawn such tha
+t<eop>
+ - one lays on top of the other<eo
+p>
+ | Grid Int Int SegList - picture type that contains the
+list<eop>
+ - of picture's line segments alon
+g<eop>
+ - with the size of the inital pic
+ture<eop>
+<eop>
+The type synonyms are pretty much self explanatory.<eop>
+<eop>
+ Hostname<tab><tab><tab>- a string of the hostname<eop>
+ Filename <tab>- a string of the filename<e
+op>
+ IntPoint <tab>- a tuple of integers repres
+enting<eop>
+ <tab>- the coordinates of a point
+<eop>
+ IntSegment <tab>- a tuple of Intpoints repre
+senting<eop>
+ <tab>- the endpoints of a line se
+gment<eop>
+ IntSegList <tab>- a list of IntSegments <eop
+>
+ Point <tab>- same as IntPoint except in
+ place of<eop>
+<tab><tab><tab> <tab>- intergers, they are floating points<eop>
+ Segment <tab>- same as IntSegment except
+in place<eop>
+ <tab><tab> <tab>- of intergers, they are floating <eop>
+ <tab><tab><tab>- points<eop>
+ SegList <tab>- same as IntsegList except
+in place<eop>
+ <tab><tab><tab><tab>- of intergers, they are floating <eop>
+ <tab><tab><tab>- points<eop>
+ Vector <tab>- a tuple of floating points
+ to<eop>
+ <tab><tab><tab>- to represent a vector<eop>
+ Vtriple - a 3-tuple of Vectors<eop>
+ HendQuartet - a 4-tuple of Integers for the s
+ize<eop>
+ - of the Henderson window<eop>
+ PEnv - a tuple of a Filename and a Pic
+ture<eop>
+ - for storing already opened file
+s in<eop>
+ - in order to save time and memor
+y<eop>
+ - when a file needs to be opened
+more<eop>
+ - than once<eop>
+<eop>
+-------------------------------------------------------------------------------
+----<eop>
+Function: create (an exported function from the HendersonLib)<eop>
+<eop>
+The purpose of the create function is to provide the user with a function to <e
+op>
+draw a picture from a graphics interface. The user may choose to create a pict
+ure<eop>
+file by inputing the the lines and points manually into a file or (s)he may cho
+ose<eop>
+to use the create function.<eop>
+<eop>
+Functionality of create:<eop>
+ create :: Hostname -<ra> Filaname -<ra> Int -<ra> Int -<ra> IO()<eop
+>
+<eop>
+create takes as input a hostname, a filename, and two integers for the size of
+the <eop>
+window to be opened. Two windows should appear, one for the input of lines and
+<eop>
+another showing the current position of the mouse. These windows will be label
+ed<eop>
+accordingly.<eop>
+To draw a line on the file window, move the cursor to the desired position, the
+n<eop>
+hit any key on the keybroad. This point will be the beginning of the line segme
+nt.<eop>
+Next move the cursor to the position of where the user wants the end of the lin
+e<eop>
+segment to be, then hit any key from the keyboard again. A line should appear.
+<eop>
+The coordinates of the endpoints of each line drawn will also be printed out o
+nto <eop>
+standard output.<eop>
+To signal completion of a file, press any button on the mouse. The user must <
+eop>
+remember though that this is only applicable after a completed drawing of a lin
+e.<eop>
+For example, pressing the mouse button will not work if one of the endpoints of
+ a<eop>
+line is drawn but the other endpoint is not. create will not recognize the mous
+e <eop>
+button press event until a second endpoint is drawn.<eop>
+<eop>
+Advantages of create:<eop>
+ provides a quick and fun way to create a picture file.<eop>
+<eop>
+Disadvantages of create:<eop>
+ If the file does not exist, create will create the file and then store the pic
+ture<eop>
+ to it. However, if the file exists, create will automatically delete the cont
+ents<eop>
+ of that file before storing the new picture.<eop>
+<eop>
+-------------------------------------------------------------------------------
+----<eop>
+Function: modify (an exported function from the HendersonLib)<eop>
+<eop>
+The purpose of the modify function is to provide the user with a function make
+<eop>
+additions to an already existing picture file using a graphics interface. The
+user<eop>
+may choose to modify the picture file by adding the the lines and points manual
+ly <eop>
+into the file or (s)he may choose to use the modify function.<eop>
+<eop>
+Functionality of modify:<eop>
+ modify :: Hostname -<ra> Filaname -<ra> IO()<eop>
+<eop>
+modify takes as input a hostname and a filename. Tow windows should appear. Th
+e <eop>
+size of the draw window will be the same as the x and y coordinates already in
+the<eop>
+file. These windows will be labeled accordingly. The existing picture will app
+ear<eop>
+first before any input is allowed.<eop>
+To draw a line on the file window, move the cursor to the desired position, the
+n<eop>
+hit any key on the keybroad. This point will be the beginning of the line segme
+nt.<eop>
+Next move the cursor to the position of where the user wants the end of the lin
+e<eop>
+segment to be, then hit any key from the keyboard again. A line should appear.
+<eop>
+The coordinates of the endpoints of each line drawn will also be printed out o
+nto <eop>
+standard output.<eop>
+To signal completion of a file, press any button on the mouse. The user must <
+eop>
+remember though that this is only applicable after a completed drawing of a lin
+e.<eop>
+For example, pressing the mouse button will not work if one of the endpoints of
+ a<eop>
+line is drawn but the other endpoint is not. modify will not recognize the mou
+se <eop>
+button press event until a second endpoint is drawn.<eop>
+<eop>
+Advantages of modify:<eop>
+ provides a quick and fun way to modify a picture file without having to go int
+o<eop>
+ the file and manually add on the coordinates of the additional lines<eop>
+<eop>
+Disadvantages of modify:<eop>
+ Existing lines can not be deleted and any additional lines, whether intentiona
+l or<eop>
+ unintentional, will be appended to the picture and stored in the file.<eop>
+<eop>
+--------------------------------------------------------<eop>
+Function: sendToDraw<eop>
+<eop>
+Type of sendToDraw:<eop>
+ sendToDraw :: XWindow -<ra> XScreen -<ra> XDisplay -<ra> <eop>
+ XPixel -<ra> XPixel -<ra> Plot -<ra> IO()<eop>
+<eop>
+Usage:<eop>
+ sendToDraw win scn dis fg_color bg_color plt<eop>
+<eop>
+'sendToDraw' is the most primitive function in the part of the Henderson<eop>
+library that deals with X windows, and therefore, can be used as a very<eop>
+powerful tool. It draws a Plot plt (see 'plot' function) in the given XWindow<
+eop>
+win, and on the given XScreen and XDisplay scn and dis, drawing the lines in<eo
+p>
+the foreground color. This function allows the programmer to draw more than<eo
+p>
+one Picture to the same window.<eop>
+<eop>
+Arguments:<eop>
+ win - the XWindow in which to draw plt<eop>
+ scn - the screen which contains win<eop>
+ dis - the display which contains scn<eop>
+ fg_color - an XPixel the color of which the plt will be drawn in. Note that<
+eop>
+<tab>this allows the programmer to draw different plt's in different colors.<eo
+p>
+ bg_color - unused, but required.<eop>
+--------------------------------------------------------<eop>
+Function: plot<eop>
+<eop>
+Type of 'plot':<eop>
+ plot :: Picture -<ra> VTriple -<ra> PEnv -<ra> ((Plot, PEnv) -<ra> IO()) -<ra
+> IO()<eop>
+<eop>
+Usage:<eop>
+ plot pic (a,b,c) env func<eop>
+<eop>
+The 'plot' function is needed to create a Plot which would be normally sent to<
+eop>
+a function such as sendToDraw. 'plot' converts a Picture pic into a format<eop
+>
+that sendToDraw can deal with.<eop>
+'plot' also takes three vectors which specify the bounding box in which the<eop
+>
+Picture is to be drawn. The first vector (a) specifies the upper left corner<e
+op>
+of the bounding box. The next two vectors specify the bounding box itself,<eop
+>
+with respect to the first vector. This allows for non-rectangular bounding<eop
+>
+boxes. For example, the vector triple ((50,50), (100,0), (0,100)) specifies<eo
+p>
+the following bounding box:<eop>
+<eop>
+ (0,0)----------------------------------<eop>
+ |<eop>
+ | (50,50)<eop>
+ | _______________ (150,0) <eop>
+ | | |<eop>
+ | | |<eop>
+ | | |<eop>
+ | | |<eop>
+ | | |<eop>
+ | |_____________| (150,150)<eop>
+ | (0,150)<eop>
+<eop>
+<eop>
+A vector triple of ((0,0), (100,300), (0,100)) would specify:<eop>
+<eop>
+ (0,0)-------------------------------------<eop>
+ ||\<eop>
+ || \<eop>
+ || \<eop>
+ (0,100)|| \<eop>
+ |\ \<eop>
+ | \ \<eop>
+ | \ \<eop>
+ | \ \ (100,300)<eop>
+ | \ | <eop>
+ | \ |<eop>
+ | \ |<eop>
+ | \| (100,400)<eop>
+<eop>
+Arguments: <eop>
+ pic - the Picture to be converted<eop>
+ a - a vector specifying the upper left corner of the bounding box<eop>
+<tab>of the picture.<eop>
+ b - a vector understood to start at 'a' and specifying the upper edge of<eop>
+
+<tab>the bounding box.<eop>
+ c - a vector understood to start at 'a' and specifying the left edge of<eop>
+<tab>the bounding box.<eop>
+--------------------------------------------------------<eop>
+Function: draw<eop>
+<eop>
+Type of draw:<eop>
+ draw :: Hostname -<ra> Picture -<ra> VTriple -<ra> HendQuartet -<ra> IO()<eop
+>
+<eop>
+Usage:<eop>
+ draw host pic (a,b,c) (m,n,p,q)<eop>
+<eop>
+'draw' is a higher-level function than sendToDraw, and is useful to use when<eo
+p>
+the programmer wishes only to draw one Picture on the screen. This function<eo
+p>
+does most of the work that the programmer would normally have to do when using<
+eop>
+sendToDraw. 'draw' opens a window at host with upper left coordinates m and n<
+eop>
+(on an X server that lets the user position any child window of the root<eop>
+window, these coordinates mean nothing), and with width p and height q.<eop>
+'draw' then calls 'plot' on pic and (a,b,c) and sends the result to sendToDraw,
+<eop>
+which finally draws the picture to the window.<eop>
+<eop>
+Arguments:<eop>
+ host - host on which to open a display, i.e. "tucan:0"<eop>
+ pic - the Picture to be drawn<eop>
+ (a,b,c) - the vector triple specifying the bounding box to be sent to<eop>
+<tab>plot (see 'plot' function)<eop>
+ (m,n,p,q) - upper left corner x (m), upper left corner y (n), width (p),<eop>
+
+<tab>and height (q), of window to be opened.<eop>
+<eop>
+-----------------------------------------------------------<eop>
+<eop>
+Module: SquareLimit<eop>
+<eop>
+This module is a sample user module that can be used to draw Square Limit, a wo
+odcut by M. C. Escher. To draw "SquareLimit" on your host, run the dialogue:<e
+op>
+<tab>final host<eop>
+where 'host' is the host running X, such as "turtle:0".<eop>
+<eop>
+To draw a slightly more interesting picture, tun the dialogue:<eop>
+<tab>skewedfinal host<eop>
+and it will draw "SquareLimit" in a bounding box shaped as a diamond.<eop>
+<eop>
+
+<textstream_end>
+
+POLY_OBJECT POLY_TEXT | DefPolyType
+
+0 DefLineWidth TRANSPARENT DefPenColor TRANSPARENT DefFillColor 1 DefIG 300
+DefResolution 100 DefYScale 100 DefXScale (=default) DefPolyResId 1
+DefMasterRef
+
+MP_CPSUCC_LINK MP_CPPRED_LINK LINK_OVERFLOW MPREF_VALID POLY_COLUMN AUTO_STREAM | | | | |
+DefSLinksFlags 0 DefStreamSucc 2 DefStreamPred 3 DefTextHandle
+1440 1080 11160 1080 11160 14760 1440 14760 4
+POLY_OBJECT POLY_TEXT | (2) 0 4 TextPolygon
+
+BeginProfile
+(Number of Pages) (5) DefProfileString
+(Language) (ENGLISH) DefProfileString
+(Version) (IslandWrite Version 2.3) DefProfileString
+(Creation Date) (gadde May 7, 1993 3:55 PM) DefProfileString
+(Text Formats) (default) DefProfileString
+(Container Formats) (default) DefProfileString
+(Page Formats) (default) DefProfileString
+(Fonts) (Courier) DefProfileString
+(Fonts) (Times-Roman) DefProfileString
+(File Path) () DefProfileString
+(External Contents) () DefProfileString
+(Title) () DefProfileString
+(Status) () DefProfileString
+(Distribution List) () DefProfileString
+(Preparer) () DefProfileString
+(Owner) () DefProfileString
+(Author) () DefProfileString
+(Superseded Documents) () DefProfileString
+EndProfile
+
+pgscriptdone
diff --git a/progs/demo/X11/graphics/p.pic b/progs/demo/X11/graphics/p.pic
new file mode 100644
index 0000000..240b386
--- /dev/null
+++ b/progs/demo/X11/graphics/p.pic
@@ -0,0 +1 @@
+Grid 640 640 [((560.00000000000000,560.00000000000000),(440.00000000000000,640.00000000000000)), ((640.00000000000000,560.00000000000000),(560.00000000000000,560.00000000000000)), ((520.00000000000000,440.00000000000000),(640.00000000000000,480.00000000000000)), ((400.00000000000000,480.00000000000000),(520.00000000000000,440.00000000000000)), ((480.00000000000000,360.00000000000000),(360.00000000000000,400.00000000000000)), ((480.00000000000000,360.00000000000000),(640.00000000000000,400.00000000000000)), ((480.00000000000000,280.00000000000000),(640.00000000000000,320.00000000000000)), ((320.00000000000000,320.00000000000000),(480.00000000000000,280.00000000000000)), ((280.00000000000000,400.00000000000000),(160.00000000000000,440.00000000000000)), ((160.00000000000000,240.00000000000000),(280.00000000000000,400.00000000000000)), ((160.00000000000000,440.00000000000000),(160.00000000000000,240.00000000000000)), ((120.00000000000000,480.00000000000000),(0.0000000000000000,320.00000000000000)), ((0.0000000000000000,320.00000000000000),(0.0000000000000000,520.00000000000000)), ((120.00000000000000,480.00000000000000),(0.0000000000000000,520.00000000000000)), ((240.00000000000000,640.00000000000000),(160.00000000000000,480.00000000000000)), ((400.00000000000000,480.00000000000000),(440.00000000000000,640.00000000000000)), ((320.00000000000000,320.00000000000000),(400.00000000000000,480.00000000000000)), ((160.00000000000000,120.00000000000000),(320.00000000000000,320.00000000000000)), ((0.0000000000000000,0.0000000000000000),(160.00000000000000,120.00000000000000)), ((640.00000000000000,240.00000000000000),(320.00000000000000,160.00000000000000)), ((640.00000000000000,40.000000000000000),(560.00000000000000,0.0000000000000000)), ((520.00000000000000,40.000000000000000),(640.00000000000000,80.000000000000000)), ((480.00000000000000,0.0000000000000000),(520.00000000000000,40.000000000000000)), ((480.00000000000000,80.000000000000000),(400.00000000000000,0.0000000000000000)), ((640.00000000000000,120.00000000000000),(480.00000000000000,80.000000000000000)), ((480.00000000000000,160.00000000000000),(640.00000000000000,160.00000000000000)), ((320.00000000000000,0.0000000000000000),(480.00000000000000,160.00000000000000)), ((240.00000000000000,40.000000000000000),(320.00000000000000,0.0000000000000000)), ((0.0000000000000000,0.0000000000000000),(240.00000000000000,40.000000000000000))] \ No newline at end of file
diff --git a/progs/demo/X11/graphics/q.pic b/progs/demo/X11/graphics/q.pic
new file mode 100644
index 0000000..84e27a4
--- /dev/null
+++ b/progs/demo/X11/graphics/q.pic
@@ -0,0 +1,2 @@
+Grid 16 16
+[((10.000000000000000,6.0000000000000000),(9.0000000000000000,4.0000000000000000)), ((12.000000000000000,4.0000000000000000),(10.000000000000000,6.0000000000000000)), ((9.0000000000000000,4.0000000000000000),(12.000000000000000,4.0000000000000000)), ((0.0000000000000000,6.0000000000000000),(7.0000000000000000,5.0000000000000000)), ((0.0000000000000000,8.0000000000000000),(0.0000000000000000,16.000000000000000)), ((0.0000000000000000,0.0000000000000000),(0.0000000000000000,4.0000000000000000)), ((15.000000000000000,16.000000000000000),(16.000000000000000,14.000000000000000)), ((16.000000000000000,12.000000000000000),(14.000000000000000,16.000000000000000)), ((13.000000000000000,16.000000000000000),(16.000000000000000,10.000000000000000)), ((13.000000000000000,12.000000000000000),(12.000000000000000,16.000000000000000)), ((16.000000000000000,8.0000000000000000),(13.000000000000000,12.000000000000000)), ((15.000000000000000,6.0000000000000000),(16.000000000000000,8.0000000000000000)), ((16.000000000000000,0.0000000000000000),(15.000000000000000,6.0000000000000000)), ((10.000000000000000,16.000000000000000),(14.000000000000000,5.0000000000000000)), ((10.000000000000000,10.000000000000000),(10.000000000000000,7.0000000000000000)), ((8.0000000000000000,16.000000000000000),(10.000000000000000,10.000000000000000)), ((8.0000000000000000,11.000000000000000),(8.0000000000000000,8.0000000000000000)), ((6.0000000000000000,16.000000000000000),(8.0000000000000000,11.000000000000000)), ((6.0000000000000000,11.000000000000000),(4.0000000000000000,16.000000000000000)), ((6.0000000000000000,9.0000000000000000),(6.0000000000000000,11.000000000000000)), ((4.0000000000000000,11.000000000000000),(4.0000000000000000,9.0000000000000000)), ((2.0000000000000000,16.000000000000000),(4.0000000000000000,11.000000000000000)), ((4.0000000000000000,9.0000000000000000),(0.0000000000000000,8.0000000000000000)), ((6.0000000000000000,9.0000000000000000),(4.0000000000000000,9.0000000000000000)), ((12.000000000000000,6.0000000000000000),(6.0000000000000000,9.0000000000000000)), ((16.000000000000000,0.0000000000000000),(12.000000000000000,6.0000000000000000)), ((9.0000000000000000,3.0000000000000000),(8.0000000000000000,1.0000000000000000)), ((11.000000000000000,1.0000000000000000),(9.0000000000000000,3.0000000000000000)), ((8.0000000000000000,1.0000000000000000),(11.000000000000000,1.0000000000000000)), ((8.0000000000000000,0.0000000000000000),(7.0000000000000000,1.0000000000000000)), ((5.0000000000000000,2.0000000000000000),(7.0000000000000000,1.0000000000000000)), ((6.0000000000000000,0.0000000000000000),(7.0000000000000000,1.0000000000000000)), ((5.0000000000000000,2.0000000000000000),(4.0000000000000000,0.0000000000000000)), ((3.0000000000000000,3.0000000000000000),(5.0000000000000000,2.0000000000000000)), ((3.0000000000000000,3.0000000000000000),(0.0000000000000000,4.0000000000000000)), ((2.0000000000000000,0.0000000000000000),(3.0000000000000000,3.0000000000000000))] \ No newline at end of file
diff --git a/progs/demo/X11/graphics/r.pic b/progs/demo/X11/graphics/r.pic
new file mode 100644
index 0000000..6e37979
--- /dev/null
+++ b/progs/demo/X11/graphics/r.pic
@@ -0,0 +1,2 @@
+Grid 32 32
+[((32.000000000000000,0.0000000000000000),(24.000000000000000,8.0000000000000000)), ((32.000000000000000,4.0000000000000000),(30.000000000000000,2.0000000000000000)), ((28.000000000000000,4.0000000000000000),(32.000000000000000,8.0000000000000000)), ((32.000000000000000,12.000000000000000),(26.000000000000000,6.0000000000000000)), ((24.000000000000000,8.0000000000000000),(32.000000000000000,16.000000000000000)), ((22.000000000000000,0.0000000000000000),(24.000000000000000,8.0000000000000000)), ((22.000000000000000,12.000000000000000),(12.000000000000000,0.0000000000000000)), ((32.000000000000000,20.000000000000000),(22.000000000000000,12.000000000000000)), ((24.000000000000000,26.000000000000000),(10.000000000000000,22.000000000000000)), ((32.000000000000000,32.000000000000000),(24.000000000000000,26.000000000000000)), ((16.000000000000000,28.000000000000000),(24.000000000000000,32.000000000000000)), ((6.0000000000000000,26.000000000000000),(16.000000000000000,28.000000000000000)), ((16.000000000000000,32.000000000000000),(4.0000000000000000,28.000000000000000)), ((2.0000000000000000,30.000000000000000),(8.0000000000000000,32.000000000000000)), ((0.0000000000000000,32.000000000000000),(16.000000000000000,16.000000000000000)), ((0.0000000000000000,24.000000000000000),(10.000000000000000,12.000000000000000)), ((4.0000000000000000,8.0000000000000000),(0.0000000000000000,16.000000000000000)), ((28.000000000000000,20.000000000000000),(32.000000000000000,24.000000000000000)), ((16.000000000000000,16.000000000000000),(28.000000000000000,20.000000000000000)), ((4.0000000000000000,8.0000000000000000),(16.000000000000000,16.000000000000000)), ((2.0000000000000000,4.0000000000000000),(4.0000000000000000,8.0000000000000000)), ((2.0000000000000000,4.0000000000000000),(0.0000000000000000,8.0000000000000000)), ((0.0000000000000000,0.0000000000000000),(2.0000000000000000,4.0000000000000000))] \ No newline at end of file
diff --git a/progs/demo/X11/graphics/s.pic b/progs/demo/X11/graphics/s.pic
new file mode 100644
index 0000000..74659b7
--- /dev/null
+++ b/progs/demo/X11/graphics/s.pic
@@ -0,0 +1 @@
+Grid 32 32 [((24.000000000000000,0.0000000000000000),(32.000000000000000,0.0000000000000000)), ((0.0000000000000000,0.0000000000000000),(16.000000000000000,0.0000000000000000)), ((30.000000000000000,14.000000000000000),(32.000000000000000,12.000000000000000)), ((32.000000000000000,8.0000000000000000),(28.000000000000000,10.000000000000000)), ((26.000000000000000,6.0000000000000000),(32.000000000000000,4.0000000000000000)), ((26.000000000000000,6.0000000000000000),(24.000000000000000,0.0000000000000000)), ((30.000000000000000,14.000000000000000),(26.000000000000000,6.0000000000000000)), ((32.000000000000000,16.000000000000000),(30.000000000000000,14.000000000000000)), ((30.000000000000000,16.000000000000000),(26.000000000000000,18.000000000000000)), ((30.000000000000000,22.000000000000000),(30.000000000000000,16.000000000000000)), ((26.000000000000000,18.000000000000000),(30.000000000000000,22.000000000000000)), ((24.000000000000000,24.000000000000000),(20.000000000000000,20.000000000000000)), ((24.000000000000000,18.000000000000000),(24.000000000000000,24.000000000000000)), ((20.000000000000000,20.000000000000000),(24.000000000000000,18.000000000000000)), ((20.000000000000000,0.0000000000000000),(22.000000000000000,12.000000000000000)), ((14.000000000000000,6.0000000000000000),(16.000000000000000,0.0000000000000000)), ((14.000000000000000,16.000000000000000),(16.000000000000000,20.000000000000000)), ((14.000000000000000,6.0000000000000000),(14.000000000000000,16.000000000000000)), ((20.000000000000000,24.000000000000000),(16.000000000000000,20.000000000000000)), ((32.000000000000000,32.000000000000000),(20.000000000000000,24.000000000000000)), ((16.000000000000000,28.000000000000000),(32.000000000000000,32.000000000000000)), ((8.0000000000000000,28.000000000000000),(16.000000000000000,28.000000000000000)), ((0.0000000000000000,32.000000000000000),(8.0000000000000000,28.000000000000000)), ((0.0000000000000000,24.000000000000000),(4.0000000000000000,30.000000000000000)), ((0.0000000000000000,20.000000000000000),(14.000000000000000,24.000000000000000)), ((0.0000000000000000,16.000000000000000),(16.000000000000000,20.000000000000000)), ((0.0000000000000000,12.000000000000000),(14.000000000000000,16.000000000000000)), ((0.0000000000000000,8.0000000000000000),(14.000000000000000,12.000000000000000)), ((0.0000000000000000,4.0000000000000000),(14.000000000000000,6.0000000000000000))] \ No newline at end of file
diff --git a/progs/demo/X11/graphics/sqrlmt.hs b/progs/demo/X11/graphics/sqrlmt.hs
new file mode 100644
index 0000000..662cdfa
--- /dev/null
+++ b/progs/demo/X11/graphics/sqrlmt.hs
@@ -0,0 +1,177 @@
+-- Peter Henderson's Recursive Geometry
+-- Syam Gadde and Bo Whong
+-- CS429 Project
+-- SquareLimit User Program
+
+module SqrLimit where
+import HendersonLib
+import Xlib
+{-
+p = File "p.pic"
+
+q = File "q.pic"
+
+r = File "r.pic"
+
+s = File "s.pic"
+-}
+p = Grid 640 640 [((560.0,560.0),(440.0,640.0)),
+ ((640.0,560.0),(560.0,560.0)),
+ ((520.0,440.0),(640.0,480.0)),
+ ((400.0,480.0),(520.0,440.0)),
+ ((480.0,360.0),(360.0,400.0)),
+ ((480.0,360.0),(640.0,400.0)),
+ ((480.0,280.0),(640.0,320.0)),
+ ((320.0,320.0),(480.0,280.0)),
+ ((280.0,400.0),(160.0,440.0)),
+ ((160.0,240.0),(280.0,400.0)),
+ ((160.0,440.0),(160.0,240.0)),
+ ((120.0,480.0),(0.0,320.0)),
+ ((0.0,320.0),(0.0,520.0)),
+ ((120.0,480.0),(0.0,520.0)),
+ ((240.0,640.0),(160.0,480.0)),
+ ((400.0,480.0),(440.0,640.0)),
+ ((320.0,320.0),(400.0,480.0)),
+ ((160.0,120.0),(320.0,320.0)),
+ ((0.0,0.0),(160.0,120.0)),
+ ((640.0,240.0),(320.0,160.0)),
+ ((640.0,40.0),(560.0,0.0)),
+ ((520.0,40.0),(640.0,80.0)),
+ ((480.0,0.0),(520.0,40.0)),
+ ((480.0,80.0),(400.0,0.0)),
+ ((640.0,120.0),(480.0,80.0)),
+ ((480.0,160.0),(640.0,160.0)),
+ ((320.0,0.0),(480.0,160.0)),
+ ((240.0,40.0),(320.0,0.0)),
+ ((0.0,0.0),(240.0,40.0))]
+
+q = Grid 16 16 [((10.0,6.0),(9.0,4.0)),
+ ((12.0,4.0),(10.0,6.0)),
+ ((9.0,4.0),(12.0,4.0)),
+ ((0.0,6.0),(7.0,5.0)),
+ ((0.0,8.0),(0.0,16.0)),
+ ((0.0,0.0),(0.0,4.0)),
+ ((15.0,16.0),(16.0,14.0)),
+ ((16.0,12.0),(14.0,16.0)),
+ ((13.0,16.0),(16.0,10.0)),
+ ((13.0,12.0),(12.0,16.0)),
+ ((16.0,8.0),(13.0,12.0)),
+ ((15.0,6.0),(16.0,8.0)),
+ ((16.0,0.0),(15.0,6.0)),
+ ((10.0,16.0),(14.0,5.0)),
+ ((10.0,10.0),(10.0,7.0)),
+ ((8.0,16.0),(10.0,10.0)),
+ ((8.0,11.0),(8.0,8.0)),
+ ((6.0,16.0),(8.0,11.0)),
+ ((6.0,11.0),(4.0,16.0)),
+ ((6.0,9.0),(6.0,11.0)),
+ ((4.0,11.0),(4.0,9.0)),
+ ((2.0,16.0),(4.0,11.0)),
+ ((4.0,9.0),(0.0,8.0)),
+ ((6.0,9.0),(4.0,9.0)),
+ ((12.0,6.0),(6.0,9.0)),
+ ((16.0,0.0),(12.0,6.0)),
+ ((9.0,3.0),(8.0,1.0)),
+ ((11.0,1.0),(9.0,3.0)),
+ ((8.0,1.0),(11.0,1.0)),
+ ((8.0,0.0),(7.0,1.0)),
+ ((5.0,2.0),(7.0,1.0)),
+ ((6.0,0.0),(7.0,1.0)),
+ ((5.0,2.0),(4.0,0.0)),
+ ((3.0,3.0),(5.0,2.0)),
+ ((3.0,3.0),(0.0,4.0)),
+ ((2.0,0.0),(3.0,3.0))]
+
+r = Grid 32 32 [((32.0,0.0),(24.0,8.0)),
+ ((32.0,4.0),(30.0,2.0)),
+ ((28.0,4.0),(32.0,8.0)),
+ ((32.0,12.0),(26.0,6.0)),
+ ((24.0,8.0),(32.0,16.0)),
+ ((22.0,0.0),(24.0,8.0)),
+ ((22.0,12.0),(12.0,0.0)),
+ ((32.0,20.0),(22.0,12.0)),
+ ((24.0,26.0),(10.0,22.0)),
+ ((32.0,32.0),(24.0,26.0)),
+ ((16.0,28.0),(24.0,32.0)),
+ ((6.0,26.0),(16.0,28.0)),
+ ((16.0,32.0),(4.0,28.0)),
+ ((2.0,30.0),(8.0,32.0)),
+ ((0.0,32.0),(16.0,16.0)),
+ ((0.0,24.0),(10.0,12.0)),
+ ((4.0,8.0),(0.0,16.0)),
+ ((28.0,20.0),(32.0,24.0)),
+ ((16.0,16.0),(28.0,20.0)),
+ ((4.0,8.0),(16.0,16.0)),
+ ((2.0,4.0),(4.0,8.0)),
+ ((2.0,4.0),(0.0,8.0)),
+ ((0.0,0.0),(2.0,4.0))]
+
+s = Grid 32 32 [((24.0,0.0),(32.0,0.0)),
+ ((0.0,0.0),(16.0,0.0)),
+ ((30.0,14.0),(32.0,12.0)),
+ ((32.0,8.0),(28.0,10.0)),
+ ((26.0,6.0),(32.0,4.0)),
+ ((26.0,6.0),(24.0,0.0)),
+ ((30.0,14.0),(26.0,6.0)),
+ ((32.0,16.0),(30.0,14.0)),
+ ((30.0,16.0),(26.0,18.0)),
+ ((30.0,22.0),(30.0,16.0)),
+ ((26.0,18.0),(30.0,22.0)),
+ ((24.0,24.0),(20.0,20.0)),
+ ((24.0,18.0),(24.0,24.0)),
+ ((20.0,20.0),(24.0,18.0)),
+ ((20.0,0.0),(22.0,12.0)),
+ ((14.0,6.0),(16.0,0.0)),
+ ((14.0,16.0),(16.0,20.0)),
+ ((14.0,6.0),(14.0,16.0)),
+ ((20.0,24.0),(16.0,20.0)),
+ ((32.0,32.0),(20.0,24.0)),
+ ((16.0,28.0),(32.0,32.0)),
+ ((8.0,28.0),(16.0,28.0)),
+ ((0.0,32.0),(8.0,28.0)),
+ ((0.0,24.0),(4.0,30.0)),
+ ((0.0,20.0),(14.0,24.0)),
+ ((0.0,16.0),(16.0,20.0)),
+ ((0.0,12.0),(14.0,16.0)),
+ ((0.0,8.0),(14.0,12.0)),
+ ((0.0,4.0),(14.0,6.0))]
+
+quartet p1 p2 p3 p4 =
+ Above 1 (Beside 1 p1 1 p2) 1 (Beside 1 p3 1 p4)
+
+cyc p1 =
+ quartet p1 (Rot (Rot (Rot p1))) (Rot p1) (Rot (Rot p1))
+
+t = quartet p q r s
+
+u = cyc (Rot q)
+
+side1 = quartet Nil Nil (Rot t) t
+
+side2 = quartet side1 side1 (Rot t) t
+
+corner1 = quartet Nil Nil Nil u
+
+corner2 = quartet corner1 side1 (Rot side1) u
+
+pseudocorner = quartet corner2 side2 (Rot side2) (Rot t)
+
+pseudolimit = cyc pseudocorner
+
+nonet p1 p2 p3 p4 p5 p6 p7 p8 p9 =
+ Above 1 (Beside 1 p1 2 (Beside 1 p2 1 p3))
+ 2 (Above 1 (Beside 1 p4 2 (Beside 1 p5 1 p6))
+ 1 (Beside 1 p7 2 (Beside 1 p8 1 p9)))
+
+corner = nonet corner2 side2 side2
+ (Rot side2) u (Rot t)
+ (Rot side2) (Rot t) (Rot q)
+
+squarelimit = cyc corner
+
+final host = draw host corner ((0,0),(500,0),(0,500)) (0,0,500,500)
+skewedfinal host = draw host squarelimit ((0,0),(600,200),(200,600)) (0,0,800,800)
+
+main = getEnv "DISPLAY" exit $ \ host ->
+ xHandleError ( \ (XError msg) -> appendChan stdout msg exit done) $
+ final host
diff --git a/progs/demo/X11/graphics/sqrlmt.hu b/progs/demo/X11/graphics/sqrlmt.hu
new file mode 100644
index 0000000..7d46b0e
--- /dev/null
+++ b/progs/demo/X11/graphics/sqrlmt.hu
@@ -0,0 +1,3 @@
+:o= foldr inline constant
+henderson.hu
+sqrlmt.hs
diff --git a/progs/demo/X11/graphics/stop.pic b/progs/demo/X11/graphics/stop.pic
new file mode 100644
index 0000000..01ed7d6
--- /dev/null
+++ b/progs/demo/X11/graphics/stop.pic
@@ -0,0 +1 @@
+Grid 200 200 [((110.00000000000000,28.000000000000000),(48.000000000000000,39.000000000000000)), ((143.00000000000000,45.000000000000000),(118.00000000000000,32.000000000000000)), ((165.00000000000000,97.000000000000000),(143.00000000000000,45.000000000000000)), ((149.00000000000000,142.00000000000000),(166.00000000000000,98.000000000000000)), ((80.000000000000000,155.00000000000000),(153.00000000000000,146.00000000000000)), ((31.000000000000000,124.00000000000000),(80.000000000000000,156.00000000000000)), ((24.000000000000000,64.000000000000000),(31.000000000000000,124.00000000000000)), ((52.000000000000000,34.000000000000000),(24.000000000000000,64.000000000000000))] \ No newline at end of file
diff --git a/progs/demo/X11/graphics/strange.pic b/progs/demo/X11/graphics/strange.pic
new file mode 100644
index 0000000..5484b0b
--- /dev/null
+++ b/progs/demo/X11/graphics/strange.pic
@@ -0,0 +1,2 @@
+Overlay (Grid 200 200 [((110.00000000000000,28.000000000000000),(48.000000000000000,39.000000000000000)), ((143.00000000000000,45.000000000000000),(118.00000000000000,32.000000000000000)), ((165.00000000000000,97.000000000000000),(143.00000000000000,45.000000000000000)), ((149.00000000000000,142.00000000000000),(166.00000000000000,98.000000000000000)), ((80.000000000000000,155.00000000000000),(153.00000000000000,146.00000000000000)), ((31.000000000000000,124.00000000000000),(80.000000000000000,156.00000000000000)), ((24.000000000000000,64.000000000000000),(31.000000000000000,124.00000000000000)), ((52.000000000000000,34.000000000000000),(24.000000000000000,64.000000000000000))]) (Flip (File "text.pic"))
+
diff --git a/progs/demo/X11/graphics/text.pic b/progs/demo/X11/graphics/text.pic
new file mode 100644
index 0000000..87fd55c
--- /dev/null
+++ b/progs/demo/X11/graphics/text.pic
@@ -0,0 +1 @@
+Grid 200 200 [((177.00000000000000,91.000000000000000),(177.00000000000000,91.000000000000000)), ((172.00000000000000,63.000000000000000),(175.00000000000000,79.000000000000000)), ((164.00000000000000,73.000000000000000),(148.00000000000000,77.000000000000000)), ((159.00000000000000,63.000000000000000),(164.00000000000000,71.000000000000000)), ((148.00000000000000,63.000000000000000),(159.00000000000000,62.000000000000000)), ((146.00000000000000,61.000000000000000),(149.00000000000000,92.000000000000000)), ((122.00000000000000,61.000000000000000),(115.00000000000000,61.000000000000000)), ((130.00000000000000,62.000000000000000),(122.00000000000000,61.000000000000000)), ((133.00000000000000,75.000000000000000),(130.00000000000000,63.000000000000000)), ((124.00000000000000,89.000000000000000),(131.00000000000000,79.000000000000000)), ((111.00000000000000,81.000000000000000),(124.00000000000000,89.000000000000000)), ((114.00000000000000,61.000000000000000),(108.00000000000000,78.000000000000000)), ((88.000000000000000,64.000000000000000),(91.000000000000000,91.000000000000000)), ((73.000000000000000,62.000000000000000),(96.000000000000000,60.000000000000000)), ((65.000000000000000,97.000000000000000),(49.000000000000000,100.00000000000000)), ((61.000000000000000,80.000000000000000),(65.000000000000000,97.000000000000000)), ((46.000000000000000,79.000000000000000),(61.000000000000000,80.000000000000000)), ((45.000000000000000,61.000000000000000),(46.000000000000000,79.000000000000000)), ((61.000000000000000,63.000000000000000),(41.000000000000000,62.000000000000000))] \ No newline at end of file
diff --git a/progs/demo/X11/logo/EXAMPLES.LOGO b/progs/demo/X11/logo/EXAMPLES.LOGO
new file mode 100644
index 0000000..bb89632
--- /dev/null
+++ b/progs/demo/X11/logo/EXAMPLES.LOGO
@@ -0,0 +1,70 @@
+(to nth :index :lst
+ (if (equal :index 1)
+ then (first :lst)
+ else (nth (difference :index 1) (butfirst :lst))))
+
+(to makelist :begin :end
+ (fput :begin (if (equal :begin :end)
+ then [[]]
+ else (makelist (sum :begin 1) :end))))
+
+(to wheel :centerright
+ [(hideturtle)
+ (pendown)
+ (setangle 90)
+ (setxy :centerright 350)
+ (repeat 72 times
+ [(forward 2)
+ (left 5)])])
+
+(to car
+ [(pendown)
+ (hideturtle)
+ (setxy 400 350)
+ (setangle 90)
+ (forward 70)
+ (left 90)
+ (forward 100)
+ (right 60)
+ (forward 80)
+ (left 60)
+ (forward 100)
+ (left 60)
+ (forward 80)
+ (right 60)
+ (forward 70)
+ (left 90)
+ (forward 70)
+ (left 90)
+ (forward 350)
+ (wheel 350)
+ (wheel 150)])
+
+(to docar?
+ [(local "ans)
+ (print [do you want a car?])
+ (make "ans (read))
+ (if (equal (first ans) "yes)
+ then (car)
+ else [[oh well]])])
+
+(to poly :size :angles
+ [(hideturtle)
+ (pendown)
+ (setangle 90)
+ (repeat :angles times
+ [(forward :size)
+ (right (div 360 :angles))])])
+
+(make "x (makelist 3 12))
+
+(while (less (first x) 12)
+ [(make "x (butfirst x))
+ (print x)])
+
+(clean)
+
+(car)
+
+(poly 100 5)
+
diff --git a/progs/demo/X11/logo/README b/progs/demo/X11/logo/README
new file mode 100644
index 0000000..b483e2a
--- /dev/null
+++ b/progs/demo/X11/logo/README
@@ -0,0 +1,104 @@
+Ki-Wing Ho and Eric Fox
+Computer Science 429b
+Professor Hudak
+Final Project: User Manual
+
+
+Control Commands:
+
+
+(DO <clause> WHILE <cond>)
+
+ Loop, executing a list of commands, then checking a condition and
+looping again if the condition is true.
+
+
+(REPEAT n TIMES)
+ WHILE cn cl
+ IF cn THEN cl1 [ELSE cl2]
+
+Load a file:
+ USE "filename
+
+Environment Commands:
+ MAKE "nm v
+ LOCAL "nm
+ TO :nm1 :nm2 :nm3 ... cl
+
+Text I/O:
+ PRINT v
+ READ
+
+Graphics Commands:
+ FORWARD n
+ BACKWARD n
+ SETXY n1 n2
+ LEFT n
+ RIGHT n
+ PENUP
+ PENDOWN
+ HIDETURTLE
+ SHOWTURTLE
+ CLEARSCREEN
+ CLEAN
+
+Graphics Functions:
+ XCOR
+ YCOR
+ GETANGLE
+ GETPEN
+ GETTURTLE
+
+Mathematical:
+ SUM n1 n2
+ DIFFERENCE n1 n2
+ PRODUCT n1 n2
+ MOD n1 n2
+ DIV n1 n2
+ POWER n1 n2
+
+Boolean:
+ AND b1 b2
+ OR b1 b2
+ NOT b
+
+Predicates:
+ WORDP v
+ LISTP v
+ NUMBERP v
+ GREATER n1 n2
+ LESS n1 n2
+ EQUAL v1 v2
+
+Word/List:
+ FIRST t
+ LAST t
+ FPUT t l
+ BUTFIRST l
+ WORD w1 w2 w3 ...
+ LIST t1 t2 t3 ...
+ CONCAT l1 l2
+ SENTENCE t1 t2 t3 ...
+
+
+Our Logo interpreter will only support one of the three windowing
+modes: window mode, where the turtle, if it walks off the end of the
+screen, just continues going and does not wrap. The two (unsupported)
+modes are fence mode where the turtle cannot walk off the end, and
+wrap mode. The initial turtle state will be with the turtle hidden,
+the pen down, and the turtle in the center of the screen facing
+upwards.
+
+All input (both for commands as well as user-input) will be
+case-insensitive, and the interpreter needs to handle lists, words,
+integers, and boolean values. Also, typing "GoodBye" at the LOGO>
+prompt exits the interpreter.
+
+All commands will be enclosed in parentheses, and all lists of
+commands will be enclosed in square brackets, so that there is no
+longer any need for the keyword "End". Also, all procedures will
+return the value of their last command, so that there are no Stop or
+Output commands. IF statements should return the value of the last
+statement executed, but all looping constructs should return no value.
+
+
diff --git a/progs/demo/X11/logo/logo.hs b/progs/demo/X11/logo/logo.hs
new file mode 100644
index 0000000..458eca1
--- /dev/null
+++ b/progs/demo/X11/logo/logo.hs
@@ -0,0 +1,1345 @@
+{-
+
+Ki-Wing Ho and Eric Fox
+Computer Science 429b
+Professor Hudak
+Final Project: LOGO Interpreter
+
+-}
+
+
+
+-------------------------------------------------------------------------------
+module REPLoop where
+
+{-
+
+REPLoop has two main parts: the first part (function logo) sets up the
+graphics window, prints a welcome message, initializes the variable
+and procedure environments and the turtle, accepts and lines's the
+user input, runs the read-eval-print loop (part two), and then closes
+the graphics window and exists; the second part (function repLoop)
+lexes and parses each command, prints an error message if there was a
+syntax error and evaluates (or tries to) if there wasn't, and then
+either prints the value or an error message or exits if the value
+returnd by the evaluator is "GoodBye".
+
+-}
+
+import Lexer
+import Parser
+import Evaluator
+import Xlib
+
+demo = main
+
+main = getEnv "DISPLAY" exit $ \ host ->
+ xHandleError ( \ (XError msg) -> appendChan stdout msg exit done) $
+ logo host
+
+logo :: String -> IO ()
+
+logo host =
+ xOpenDisplay host `thenIO` \ display ->
+
+ let (screen:_) = xDisplayRoots display
+ fg_color = xScreenWhitePixel screen
+ bg_color = xScreenBlackPixel screen
+ root = xScreenRoot screen
+ in
+ xCreateWindow root
+ (XRect 100 100 500 500)
+ [XWinBackground bg_color,
+ XWinBackingStore XAlwaysBackStore]
+ `thenIO` \ graphWindow ->
+ xSetWmName graphWindow "Logo" `thenIO` \ () ->
+ xSetWmIconName graphWindow "Logo" `thenIO` \ () ->
+ xMapWindow graphWindow `thenIO` \ () ->
+
+ xCreateGcontext (XDrawWindow root)
+ [XGCBackground bg_color,
+ XGCForeground fg_color] `thenIO` \ graphContext ->
+
+ xDisplayForceOutput display `thenIO` \ () ->
+
+ appendChan stdout ("Welcome to LOGO!\n" ++ prompt) exit $
+ readChan stdin exit $ \userInput ->
+ repLoop
+ (varEnvsInit,procEnvsInit,turtleInit)
+ ((lines userInput,Lexer),
+ (graphWindow,display,graphContext,bg_color,fg_color)) $
+ xCloseDisplay display
+
+-- Initial Environments --
+
+varEnvsInit :: VarsType
+varEnvsInit = [[("GOODBYE",GoodBye)]]
+
+-- all user-defined commands must have dummy entries
+procEnvsInit :: ProcsType
+procEnvsInit = (map (makeFakeProc)
+ [("XCOR",0),("YCOR",0),("GETANGLE",0),("GETPEN",0),
+ ("GETTURTLE",0),
+ ("SUM",2),("DIFFERENCE",2),("PRODUCT",2),("MOD",2),
+ ("DIV",2),("POWER",2),
+ ("AND",2),("OR",2),("NOT",1),
+ ("WORDP",1),("LISTP",1),("NUMBERP",1),("GREATER",2),
+ ("EQUAL",2),("LESS",2),
+ ("BUTFIRST",1),("FPUT",2),("CONCAT",2),
+ ("FIRST",1),("LAST",1),("WORD",-2),("LIST",-2),
+ ("SENTENCE",-2), ("USE",1)]):[]
+
+turtleInit :: TurtleType
+turtleInit = (500 `div` 2,500 `div` 2,90,True,False)
+
+-- makes a dummy procedure
+makeFakeProc :: (NameType , Int) -> (NameType , ProcType)
+makeFakeProc (name,num) = (name,(makeArgs num,[]))
+
+makeArgs :: Int -> [NameType]
+makeArgs n | n > 0 = "" : makeArgs (n-1)
+ | otherwise = []
+
+-- keep running Read-Eval-Print Loop until user types GoodBye
+-- repLoop keeps running until user types "GoodBye", alternately
+-- lexing, parsing, and evaluating each command
+-- after a syntax error, the lex state is reset
+repLoop :: EnvsType -> StateType -> IO () -> IO ()
+repLoop e1 (inS1,gs1) end =
+ let fail1 msg (is1,ls1) = errorOutput msg $
+ repLoop e1 ((is1,Lexer),gs1) end
+ -- parser fail continuation doesn't contain graphics state
+ fail2 msg ((is2,ls2),gs2) = errorOutput msg $
+ repLoop e1 ((is2,Lexer),gs1) end
+ -- evaluator fail continuation does contain graphics state
+ in
+ parse [] inS1 fail1 $ \a ts inS2 ->
+ if (null ts)
+ then
+ evaluate e1 a (inS2,gs1) fail2 $ \v e2 ((is3,ls3),gs3) ->
+ output v end $
+ repLoop e2 ((is3,Lexer),gs3) end
+ else
+ fail1 "Syntax error: expected end of line" inS2
+ -- repLoop will still be rerun
+
+-- print error message
+errorOutput :: String -> IO () -> IO ()
+errorOutput error = appendChan stdout (error ++ prompt) abort
+
+-- print expression value, exiting if GoodBye
+output :: Value -> IO () -> IO () -> IO ()
+output GoodBye end succ
+ = appendChan stdout "\nGoodbye!\n"abort end
+output v end succ
+ = appendChan stdout ((valueToString v) ++ prompt) abort succ
+
+prompt :: String
+prompt = "\nLOGO> "
+
+
+
+-------------------------------------------------------------------------------
+module Evaluator where
+
+{-
+
+Evaluator takes an Abstract Syntax Tree and evaluates it in the
+current environment, returning both the resultant value and the new
+environment (as well as the updated state, of which only the user
+input can actually be changed in the evaluator).
+
+A value can be of one of six types: integer, string, list, and
+boolean, as well as null (for commands which don't return anything and
+newly-declared local variables), and goodbye, which allows logo to
+quit.
+
+The environment consists of three parts. The variable environment and
+the procedure environment are separate (so that a name can refer both
+to a variable and a procedure: Logo syntax is such that there is
+never any ambiguity) are both lists of name-value association lists.
+Each association list representes a "local environment", with each
+successive one being more "global", so that the last environment in
+the list is the global environment. Local environments are produced
+by user-function invocations and removed at the end of those
+invocations.
+
+-}
+
+import Lexer
+import Parser
+import Xlib
+
+type NameType = [Char]
+type WordType = [Char]
+type Error = [Char]
+
+type StateType = (InputState , GraphicsState)
+type GraphicsState = (XWindow , XDisplay , XGcontext , XPixel , XPixel)
+type EnvsType = (VarsType,ProcsType,TurtleType)
+type VarsType = [[(NameType , Value)]]
+type ProcsType = [[(NameType , ProcType)]]
+type TurtleType = (Int , Int , Int , Bool , Bool)
+type ProcType = ([NameType] , ClauseType)
+
+data Value = Null
+ | Num Int
+ | Word WordType
+ | List ListType
+ | Boolean Bool
+ | GoodBye
+ deriving Text
+
+data ListType = NullList | Value :* ListType
+ deriving Text
+
+
+type EvalFailType = Error -> StateType -> IO ()
+type EvalSuccType = Value -> EnvsType -> StateType -> IO ()
+type EvalResType = StateType -> EvalFailType -> EvalSuccType -> IO ()
+type EvaluateType = EnvsType -> AST -> EvalResType
+
+
+evaluate :: EvaluateType
+
+evaluate (vs,p:ps,ttl) (To newName newProc) ss fail succ
+ = succ Null (vs,((newName,newProc):p):ps,ttl) ss
+ -- procedures
+
+evaluate e (Read) ((i:is,ls),gs) fail succ
+ = succ (List (makeReadList (lexerReadLine i))) e ((is,ls),gs)
+ -- user input
+
+evaluate e1 (Print [a]) ss fail succ
+ = evaluate e1 a ss fail $ \v e2 ss2 ->
+ appendChan stdout ((valueToString v)++"\n") abort $
+ succ Null e2 ss2
+ -- user output
+
+evaluate e (Argument (Val (Word n))) ss fail succ
+ = lookup e n ss fail $ \v ->
+ succ v e ss
+ -- variable reference
+
+evaluate e (Argument (Val v)) ss fail succ
+ = succ v e ss
+ -- constant
+
+evaluate e (Argument (QuotedWordArg n)) ss fail succ
+ = succ (Word n) e ss
+ -- string constant
+
+evaluate (v:vs,ps,ttl) (Local n) ss fail succ
+ = succ Null (((n,Null):v):vs,ps,ttl) ss
+ -- local variable declaraion
+ -- local returns null, and sets the new local variable to null also
+
+evaluate e (ParseList l) ss fail succ
+ = succ (List l) e ss
+ -- lists (also constant)
+
+evaluate e (Loop l cond insts) ss fail succ
+ = evalLoop l e cond insts ss fail succ
+ -- loops
+
+evaluate e (If cond thens elses) ss fail succ
+ = evalIf e cond thens elses ss fail succ
+ -- if-then[-eles] conditionals
+
+evaluate e1 (Command name as1) ss fail succ
+ | ((na == length as1) || (na == -2))
+ = evalArgs e1 as1 ss fail $ \e2 as2 ss2 ->
+ apply name as2 e2 ss2 fail $ \v e3 ss3 ->
+ succ v e3 ss3
+ | na == -1
+ = fail ("Function does not exist: " ++ name) ss
+ | otherwise
+ = fail ("Wrong number of arguments to " ++ name) ss
+ where na = numArgs e1 name
+ -- function applications
+
+evaluate e1 (Make n a) ss fail succ
+ = evaluate e1 a ss fail $ \v e2 ss2 ->
+ update e2 n v $ \e3 ->
+ succ v e3 ss2
+ -- assignment statements, which return the assigned value
+
+evaluate e1 (Graphics name as1) ss fail succ
+ = evalArgs e1 as1 ss fail $ \e2 as2 ss2 ->
+ doGraphics name as2 e2 ss2 fail $ \e3 ss3 ->
+ succ Null e3 ss3
+ -- side-effecting graphics statements, which all return null
+-- end evaluate
+
+
+-- evaluate a list of actual parameters, returning the corresponding
+-- list of values
+evalArgs :: EnvsType -> ParseArgs -> StateType -> EvalFailType ->
+ (EnvsType -> EvalArgs -> StateType -> IO ()) -> IO ()
+evalArgs e [] ss fail succ
+ = succ e [] ss
+evalArgs e1 (a:as1) ss fail succ
+ = evaluate e1 a ss fail $ \v e2 ss2 ->
+ evalArgs e2 as1 ss2 fail $ \e3 as2 ss3 ->
+ succ e3 (v:as2) ss3
+
+
+-- evaluate a list of commands, returning the value of the last one
+evalClause :: EnvsType -> ClauseType -> EvalResType
+evalClause e [] ss fail succ
+ = succ Null e ss
+evalClause e (a:[]) ss fail succ
+ = evaluate e a ss fail succ
+evalClause e1 (a:as) ss fail succ
+ = evaluate e1 a ss fail $ \v e2 ss2 ->
+ evalClause e2 as ss2 fail succ
+
+-- convert a lexed user-input list to a list constant
+makeReadList :: [WordType] -> ListType
+makeReadList [] = NullList
+makeReadList (w:ws) = (Word w) :* (makeReadList ws)
+
+
+-- Variable routines --
+
+-- look up a variable reference in the variable environment
+-- search the most-local environments first
+-- return an error if not found
+lookup :: EnvsType -> NameType -> StateType -> EvalFailType ->
+ (Value -> IO ()) -> IO ()
+lookup ([],ps,ttl) name ss fail succ
+ = fail ("Unbound variable: " ++ name) ss
+lookup ([]:vss,ps,ttl) name ss fail succ
+ = lookup (vss,ps,ttl) name ss fail succ
+lookup (((n,v):vs):vss,ps,ttl) name ss fail succ
+ | n == name = succ v
+ | otherwise = lookup (vs:vss,ps,ttl) name ss fail succ
+
+-- update the variable environment
+-- replace the most-local occurrance first; if none are found,
+-- create a new variable and place it in the most-global environment
+update :: EnvsType -> NameType -> Value -> (EnvsType -> IO ()) -> IO ()
+update ([]:[],ps,ttl) name value succ
+ = succ (((name,value):[]):[],ps,ttl)
+update ([]:vss,ps,ttl) name value succ
+ = update (vss,ps,ttl) name value $ \(vss2,ps2,ttl2) ->
+ succ ([]:vss2,ps2,ttl2)
+update (((n,v):vs):vss,ps,ttl) name value succ
+ | n == name = succ (((n,value):vs):vss,ps,ttl)
+ | otherwise = update (vs:vss,ps,ttl) name value $ \(vs2:vss2,ps2,ttl2) ->
+ succ (((n,v):vs2):vss2,ps2,ttl2)
+
+
+-- Control structures --
+
+-- evaluate loops
+evalLoop :: LoopType -> EnvsType -> ConditionType -> ClauseType ->
+ EvalResType
+evalLoop Do = evalDo
+evalLoop While = evalWhile
+evalLoop Repeat = evalRepeat
+
+-- evaluate while statements
+-- loop semantics: evaluate condition; if true, evaluate clause, then loop
+-- while returns null
+evalWhile :: EnvsType -> ConditionType -> ClauseType -> EvalResType
+evalWhile e1 cond insts ss fail succ
+ = evalCond e1 cond ss fail $ \b e2 ss2 ->
+ if b
+ then
+ evalClause e2 insts ss2 fail $ \v e3 ss3 ->
+ evalWhile e3 cond insts ss3 fail succ
+ else
+ succ Null e2 ss2
+
+-- evaluate do-while statements
+-- loop semantics: evaluate clause then evaluate condition; if true, loop
+evalDo :: EnvsType -> ConditionType -> ClauseType -> EvalResType
+evalDo e1 cond insts ss fail succ
+ = evalClause e1 insts ss fail $ \v e2 ss2 ->
+ evalCond e2 cond ss2 fail $ \b e3 ss3 ->
+ if b
+ then
+ evalDo e3 cond insts ss3 fail succ
+ else
+ succ Null e3 ss3
+
+-- evaluate repeat statements
+-- loop semantics: evaluate loop number as n; evaluate clause n times
+-- evaluate loop number and print error if it is negative or not an integer
+evalRepeat :: EnvsType -> ConditionType -> ClauseType -> EvalResType
+evalRepeat e1 cond insts ss fail succ
+ = evaluate e1 cond ss fail $ \v e2 ss2 ->
+ case v of
+ Num n -> if (n >= 0)
+ then doIterations e2 n insts ss2 fail succ
+ else fail "Repeat: Iteration count cannot be negative" ss2
+ otherwise -> fail "Repeat: Invalid iteration count" ss2
+
+-- perform loop interations: evaluate "insts" "n" times
+doIterations :: EnvsType -> Int -> ClauseType -> EvalResType
+doIterations e 0 insts ss fail succ
+ = succ Null e ss
+doIterations e1 (n+1) insts ss fail succ
+ = evalClause e1 insts ss fail $ \v e2 ss2 ->
+ doIterations e2 n insts ss2 fail succ
+
+-- evaluates conditions and returns either true, false, or an error
+evalCond :: EnvsType -> ConditionType -> StateType -> EvalFailType ->
+ (Bool -> EnvsType -> StateType -> IO ()) -> IO ()
+evalCond e1 cond ss fail succ
+ = evaluate e1 cond ss fail $ \v e2 ss2 ->
+ case v of
+ Boolean b -> succ b e2 ss2
+ otherwise -> fail "Invalid condition" ss2
+
+-- evaluate if-then[-else] statements
+evalIf :: EnvsType -> ConditionType -> ClauseType -> ClauseType -> EvalResType
+evalIf e1 cond thens elses ss fail succ
+ = evalCond e1 cond ss fail $ \b e2 ss2 ->
+ if b
+ then evalClause e2 thens ss2 fail succ
+ else evalClause e2 elses ss2 fail succ
+
+
+-- Function application --
+
+-- returns the number of arguments to a user-defined or built-in function
+-- -1 means the function wasn't found
+-- -2 means the function can take any number of arguments
+numArgs :: EnvsType -> CommandName -> Int
+numArgs (vs,[],ttl) name
+ = -1
+numArgs (vs,[]:pss,ttl) name
+ = numArgs (vs,pss,ttl) name
+numArgs (vs,((n,(formals,body)):ps):pss,ttl) name
+ | inList ["WORD","SENTENCE","LIST"] name = -2
+ | n == name = length formals
+ | otherwise = numArgs (vs,ps:pss,ttl) name
+
+-- apply a function to its arguments
+-- mostly just decides if it's user-defined or built-in, then dispatches
+apply :: CommandName -> EvalArgs -> EnvsType -> EvalResType
+apply n as e ss fail succ
+ | isBuiltIn n = applyPrimProc n as e ss fail succ
+ | otherwise = applyUserProc (getProc e n) as e ss fail succ
+
+
+
+-- returns procedure "name" from the procedure environment
+-- searches most-local environments first
+-- precondition: procedure does exist somewhere
+getProc :: EnvsType -> CommandName -> ProcType
+getProc (vss,[]:pss,ttl) name
+ = getProc (vss,pss,ttl) name
+getProc (vs,((n,p):ps):pss,ttl) name
+ | n == name = p
+ | otherwise = getProc (vs,ps:pss,ttl) name
+
+-- apply user function:
+-- bind formal parameters
+-- create local enviroments
+-- evaluate body of function
+-- destroy local environments
+-- return value of body
+applyUserProc :: ProcType -> EvalArgs -> EnvsType -> EvalResType
+applyUserProc (formals,body) actuals e1 ss fail succ
+ = bind formals actuals e1 $ \e2 ->
+ evalClause e2 body ss fail $ \v (vs:vss,ps:pss,ts) ss2 ->
+ succ v (vss,pss,ts) ss2
+
+-- bind formal parameters to actuals in local environment
+bind :: [NameType] -> EvalArgs -> EnvsType -> (EnvsType -> IO ()) -> IO ()
+bind formals actuals (vss,pss,ttl) succ
+ = succ ((zip formals actuals):vss,[]:pss,ttl)
+
+
+-- Built-in functions --
+
+-- returns true for built-in functions
+isBuiltIn :: CommandName -> Bool
+isBuiltIn = inList ["XCOR","YCOR","GETANGLE","GETPEN","GETTURTLE",
+ "SUM","DIFFERENCE","PRODUCT","MOD","DIV","POWER",
+ "AND","OR","NOT",
+ "WORDP","LISTP","NUMBERP","GREATER","EQUAL","LESS",
+ "BUTFIRST","FPUT","CONCAT",
+ "FIRST","LAST","WORD","LIST","SENTENCE", "USE"]
+
+
+-- applies a built-in function to its arguments
+applyPrimProc :: CommandName -> [Value] -> EnvsType -> EvalResType
+
+applyPrimProc "XCOR" [] (vs,ps,(x,y,a,p,t)) ss fail succ
+ = succ (Num x) (vs,ps,(x,y,a,p,t)) ss
+applyPrimProc "YCOR" [] (vs,ps,(x,y,a,p,t)) ss fail succ
+ = succ (Num y) (vs,ps,(x,y,a,p,t)) ss
+applyPrimProc "GETANGLE" [] (vs,ps,(x,y,a,p,t)) ss fail succ
+ = succ (Num a) (vs,ps,(x,y,a,p,t)) ss
+applyPrimProc "GETPEN" [] (vs,ps,(x,y,a,p,t)) ss fail succ
+ = succ (Boolean p) (vs,ps,(x,y,a,p,t)) ss
+applyPrimProc "GETTURTLE" [] (vs,ps,(x,y,a,p,t)) ss fail succ
+ = succ (Boolean t) (vs,ps,(x,y,a,p,t)) ss
+
+applyPrimProc "SUM" [Num a , Num b] e ss fail succ
+ = succ (Num (a+b)) e ss
+applyPrimProc "DIFFERENCE" [Num a , Num b] e ss fail succ
+ = succ (Num (a-b)) e ss
+applyPrimProc "PRODUCT" [Num a , Num b] e ss fail succ
+ = succ (Num (a*b)) e ss
+applyPrimProc "MOD" [Num a , Num b] e ss fail succ
+ = succ (Num (a `mod` b)) e ss
+applyPrimProc "DIV" [Num a , Num b] e ss fail succ
+ = succ (Num (a `div` b)) e ss
+applyPrimProc "POWER" [Num a , Num b] e ss fail succ
+ | b >= 0 = succ (Num (a^b)) e ss
+ | otherwise = fail ("Negative exponent: " ++ (show b)) ss
+
+applyPrimProc "AND" [Boolean a , Boolean b] e ss fail succ
+ = succ (Boolean (a && b)) e ss
+applyPrimProc "OR" [Boolean a , Boolean b] e ss fail succ
+ = succ (Boolean (a || b)) e ss
+applyPrimProc "NOT" [Boolean a] e ss fail succ
+ = succ (Boolean (not a)) e ss
+
+applyPrimProc "WORDP" [Word w] e ss fail succ
+ = succ (Boolean True) e ss
+applyPrimProc "WORDP" [v] e ss fail succ
+ = succ (Boolean False) e ss
+applyPrimProc "NUMBERP" [Num n] e ss fail succ
+ = succ (Boolean True) e ss
+applyPrimProc "NUMBERP" [v] e ss fail succ
+ = succ (Boolean False) e ss
+applyPrimProc "LISTP" [List l] e ss fail succ
+ = succ (Boolean True) e ss
+applyPrimProc "LISTP" [v] e ss fail succ
+ = succ (Boolean False) e ss
+applyPrimProc "GREATER" [Num a , Num b] e ss fail succ
+ = succ (Boolean (a > b)) e ss
+applyPrimProc "EQUAL" [Num a , Num b] e ss fail succ
+ = succ (Boolean (a == b)) e ss
+applyPrimProc "EQUAL" [Word a , Word b] e ss fail succ
+ = succ (Boolean (a == b)) e ss
+applyPrimProc "EQUAL" [Boolean a , Boolean b] e ss fail succ
+ = succ (Boolean (a == b)) e ss
+applyPrimProc "LESS" [Num a , Num b] e ss fail succ
+ = succ (Boolean (a < b)) e ss
+
+applyPrimProc "BUTFIRST" [Word ""] e ss fail succ
+ = succ (Word "") e ss
+applyPrimProc "BUTFIRST" [Word (c:cs)] e ss fail succ
+ = succ (Word cs) e ss
+applyPrimProc "BUTFIRST" [List NullList] e ss fail succ
+ = succ (List NullList) e ss
+applyPrimProc "BUTFIRST" [List (v :* vs)] e ss fail succ
+ = succ (List vs) e ss
+applyPrimProc "FPUT" [v , List l] e ss fail succ
+ = succ (List (v :* l)) e ss
+applyPrimProc "CONCAT" [List l1 , List l2] e ss fail succ
+ = succ (List (listConcatenate l1 l2)) e ss
+applyPrimProc "FIRST" [Word (c:cs)] e ss fail succ
+ = succ (Word (c:[])) e ss
+applyPrimProc "FIRST" [List (v :* vs)] e ss fail succ
+ = succ v e ss
+applyPrimProc "LAST" [Word (c:[])] e ss fail succ
+ = succ (Word (c:[])) e ss
+applyPrimProc "LAST" [Word ""] e ss fail succ
+ = succ Null e ss
+applyPrimProc "LAST" [Word (c:cs)] e ss fail succ
+ = applyPrimProc "LAST" [(Word cs)] e ss fail succ
+applyPrimProc "LAST" [List (v :* NullList)] e ss fail succ
+ = succ v e ss
+applyPrimProc "LAST" [List (v :* vs)] e ss fail succ
+ = applyPrimProc "LAST" [(List vs)] e ss fail succ
+applyPrimProc "WORD" [] e ss fail succ
+ = succ (Word "") e ss
+applyPrimProc "WORD" ((Word w):ws) e ss fail succ
+ = applyPrimProc "WORD" ws e ss fail $ \(Word wsc) e2 ss2 ->
+ succ (Word (w ++ wsc)) e2 ss2
+applyPrimProc "LIST" (v:vs) e ss fail succ
+ = applyPrimProc "LIST" vs e ss fail $ \(List l) e2 ss2 ->
+ succ (List (v :* l)) e2 ss2
+applyPrimProc "LIST" [] e ss fail succ
+ = succ (List NullList) e ss
+applyPrimProc "SENTENCE" [] e ss fail succ
+ = succ (List NullList) e ss
+applyPrimProc "SENTENCE" ((List l):[]) e ss fail succ
+ = succ (List l) e ss
+applyPrimProc "SENTENCE" ((List l):vs) e ss fail succ
+ = applyPrimProc "SENTENCE" [List l] e ss fail $ \(List s1) e2 ss2 ->
+ applyPrimProc "SENTENCE" vs e2 ss2 fail $ \(List s2) e3 ss3 ->
+ succ (List (listConcatenate s1 s2)) e3 ss3
+applyPrimProc "SENTENCE" (v:vs) e ss fail succ
+ = applyPrimProc "SENTENCE" vs e ss fail $ \(List ws) e2 ss2 ->
+ succ (List (v :* ws)) e2 ss2
+
+applyPrimProc "USE" [Word filename]
+ e
+ ss@((ins, ls), gs)
+ fail succ
+ = readFile filename (\ _ -> fail ("Can't read file: " ++ filename) ss)
+ $ \filecontents ->
+ useRepLoop e ((lines filecontents, Lexer), gs)
+ (\ msg s -> fail msg ss) $ \ v e s ->
+ succ v e ss
+
+applyPrimProc n _ _ ss fail _
+ = fail ("Incorrect arguments: " ++ n) ss
+
+useRepLoop :: EnvsType -> EvalResType
+useRepLoop e s@(([], ls), gs) fail succ = succ (Word "OK") e s
+useRepLoop e1 s1@(inS1,gs1) fail succ =
+ parse [] inS1 (\ msg ins -> fail msg (ins, gs1)) $ \a ts inS2 ->
+ if (null ts)
+ then
+ evaluate e1 a (inS2,gs1) fail $ \v e2 s3 ->
+ useRepLoop e2 s3 fail succ
+ else
+ fail "Syntax error: expected end of line" (inS2, gs1)
+
+
+
+-- concatenates two lists
+listConcatenate :: ListType -> ListType -> ListType
+listConcatenate NullList l2 = l2
+listConcatenate (v :* l1) l2 = (v :* (listConcatenate l1 l2))
+
+
+-- Graphics --
+
+type EvalArgs = [Value]
+type GraphEnv = (Int,Int,Int,Bool)
+
+-- evaluates side-effecting graphics functions
+-- note: none of them return values
+doGraphics :: CommandName -> EvalArgs -> EnvsType -> StateType ->
+ EvalFailType -> (EnvsType -> StateType -> IO ()) -> IO ()
+
+doGraphics "HIDETURTLE" [] (vs,ps,(x,y,a,p,t)) ss fail succ
+ = hideTurtle x y a ss $
+ succ (vs,ps,(x,y,a,p,False)) ss
+ -- hide turtle, appropriately adjust environment
+
+doGraphics "SHOWTURTLE" [] (vs,ps,(x,y,a,p,t)) ss fail succ
+ = showTurtle x y a ss $
+ succ (vs,ps,(x,y,a,p,True)) ss
+ -- show turtle, appropriately adjust environment
+
+doGraphics name as (vs,ps,(x,y,a,p,True)) ss fail succ
+ = hideTurtle x y a ss $
+ moveTurtle name as (x,y,a,p) ss $ \(x2,y2,a2,p2) ->
+ showTurtle x2 y2 a2 ss $
+ succ (vs,ps,(x2,y2,a2,p2,True)) ss
+ -- executes graphics commands if turtle is shownn
+
+doGraphics name as (vs,ps,(x,y,a,p,False)) ss fail succ
+ = moveTurtle name as (x,y,a,p) ss $ \(x2,y2,a2,p2) ->
+ succ (vs,ps,(x2,y2,a2,p2,False)) ss
+ -- executes graphics commands if turtle is not shown
+
+-- converts an integer to a float
+toFloat :: Int -> Float
+toFloat = fromInteger . toInteger
+
+newmod a b = let c = a `mod` b
+ in if (c < 0) then (c + b) else c
+
+-- shows the turtle, but returns nothing
+showTurtle :: Int -> Int -> Int -> StateType -> IO () -> IO ()
+showTurtle x y a (is,(graphWindow,display,graphContext,bg,fg)) succ
+ = let dx1 = round (12 * cos (toFloat a * pi/180))
+ dx2 = round (4 * sin (toFloat a * pi/180))
+ dy1 = round (12 * sin (toFloat a * pi/180))
+ dy2 = round (4 * cos (toFloat a * pi/180))
+ in
+ xDrawLine (XDrawWindow graphWindow)
+ graphContext
+ (XPoint x y)
+ (XPoint (x-dx1-dx2) (y+dy1-dy2))
+ `thenIO` \ () ->
+ xDrawLine (XDrawWindow graphWindow)
+ graphContext
+ (XPoint x y)
+ (XPoint (x-dx1+dx2) (y+dy1+dy2))
+ `thenIO` \ () ->
+ xDrawLine (XDrawWindow graphWindow)
+ graphContext
+ (XPoint (x-dx1-dx2) (y+dy1-dy2))
+ (XPoint (x-dx1+dx2) (y+dy1+dy2))
+ `thenIO` \ () ->
+ xDisplayForceOutput display
+ `thenIO_`
+ succ
+
+-- hides the turtle, but returns nothing
+hideTurtle :: Int -> Int -> Int -> StateType -> IO () -> IO ()
+hideTurtle x y a (is,(graphWindow,display,graphContext,bg,fg)) succ
+ = xUpdateGcontext graphContext [XGCForeground bg]
+ `thenIO_`
+ (showTurtle x y a (is,(graphWindow,display,graphContext,bg,fg)) $
+ (xUpdateGcontext graphContext [XGCForeground fg]
+ `thenIO_`
+ succ))
+
+-- performs all graphics commands that don't involve hiding/showing
+-- the turtle
+moveTurtle :: CommandName -> EvalArgs -> GraphEnv -> StateType ->
+ (GraphEnv -> IO ()) -> IO ()
+moveTurtle "SETXY" [Num xp,Num yp] (x,y,a,p) ss succ
+ = succ (xp,yp,a,p)
+
+-- move the turtle forward "d" times, drawing a line if pen is down
+moveTurtle "FORWARD" [Num d] (x,y,a,p)
+ (is,(graphWindow,display,graphContext,fg,bg)) succ
+ = let xp = x + round (toFloat d * cos (toFloat a * pi/180))
+ yp = y - round (toFloat d * sin (toFloat a * pi/180)) in
+ (if p
+ then (xDrawLine (XDrawWindow graphWindow)
+ graphContext
+ (XPoint x y)
+ (XPoint xp yp))
+ else returnIO ()) `thenIO` \ () ->
+ xDisplayForceOutput display `thenIO` \ () ->
+ succ (xp,yp,a,p)
+
+-- move the turtle backward "d" pixels, drawing a line if pen is down
+moveTurtle "BACKWARD" [Num d] (x,y,a,p) ss succ
+ = moveTurtle "FORWARD" [Num (-d)] (x,y,a,p) ss succ
+
+-- rotate turtle to "ap" degrees from facing due east
+moveTurtle "SETANGLE" [Num ap] (x,y,a,p) ss succ
+ = succ (x,y,ap,p)
+
+-- rotate turtle counterclockwise "ap" degrees
+moveTurtle "LEFT" [Num ap] (x,y,a,p) ss succ
+ = succ (x,y, (a + ap) `newmod` 360 ,p)
+
+-- rotate turtle clockwise "ap" degrees
+moveTurtle "RIGHT" [Num ap] (x,y,a,p) ss succ
+ = succ (x,y, (a - ap) `newmod` 360 ,p)
+
+-- pick pen up
+moveTurtle "PENUP" [] (x,y,a,p) ss succ
+ = succ (x,y,a,False)
+
+-- put pen down
+moveTurtle "PENDOWN" [] (x,y,a,p) ss succ
+ = succ (x,y,a,True)
+
+-- clear screen but don't otherwise alter turtle state
+moveTurtle "CLEARSCREEN" [] (x,y,a,p)
+ (is,(graphWindow,display,graphContext,bg,fg)) succ
+ = xClearArea graphWindow (XRect 0 0 500 500) True
+ `thenIO` \() ->
+ xDisplayForceOutput display
+ `thenIO` \() ->
+ succ (x,y,a,p)
+
+-- pick pen up and reset turtle
+moveTurtle "CLEAN" [] (x,y,a,p)
+ (is,(graphWindow,display,graphContext,bg,fg)) succ
+ = xClearArea graphWindow (XRect 0 0 500 500) True
+ `thenIO` \() ->
+ xDisplayForceOutput display
+ `thenIO` \() ->
+ succ (500 `div` 2,500 `div` 2,90,True)
+
+-- do nothing if arguments are incorrect
+moveTurtle _ _ e _ succ = succ e
+
+
+-- valueToString, etc. --
+
+-- convert a value to a string
+valueToString :: Value -> String
+valueToString (Word w) = w
+valueToString (Num n) = show n
+valueToString (Boolean True) = "TRUE"
+valueToString (Boolean False) = "FALSE"
+valueToString Null = ""
+valueToString (List l) = "[" ++ (listToString l) ++ "]"
+valueToString GoodBye = "Don't play around with this variable!"
+
+-- convert a list to a string
+listToString :: ListType -> String
+listToString NullList = ""
+listToString (v :* NullList) = valueToString v
+listToString (v :* l) = (valueToString v) ++ " " ++ (listToString l)
+
+
+
+-------------------------------------------------------------------------------
+module Lexer where
+
+{-
+
+Lexer takes as input a line from standard input and returns an ordered
+pair containing the translation of that list into tokens as well as
+the current state of the lexer (how many parentheses and brackets are
+still open). The state is necessary because some commands may take
+multiple lines, so a bracket (say) may be left open on one line to be
+closed later on.
+
+All unmatched close brackets and parentheses are treated as spaces
+(and therefore ignored).
+
+The method for tokenizing commands is:
+
+ All words are delimited by spaces, parenthesis, or brackets.
+
+ All words beginning with a double quote are returned as quoted words
+ rather than normal words.
+
+ Any character preceded by a backslash is taken as is, rather than
+ tokenized normally.
+
+ All words are translated to upper case..
+
+The method for tokenizing user input is:
+
+ All words are delimited by spaces and translated to upper case.
+
+-}
+
+import Parser
+import Evaluator
+
+
+data LexState = Lexer | LexerBracket Int LexState | LexerParen Int LexState
+ deriving Text
+
+type LexerType = [Char] -> ([Token] , LexState)
+
+data Token = OpenBracket
+ | CloseBracket
+ | OpenParen
+ | CloseParen
+ | QuotedWord WordType
+ | Normal WordType deriving (Text,Eq)
+
+
+-- call appropriate lex procedure depending upon the current lex state
+lexDispatch :: LexState -> LexerType
+lexDispatch (Lexer) = lexer
+lexDispatch (LexerBracket n s) = lexerBracket n s
+lexDispatch (LexerParen n s) = lexerParen n s
+
+
+-- handle commands
+lexer :: LexerType
+lexer [] = ([] , Lexer)
+lexer (' ':cs) = lexer cs
+lexer ('[':cs) = let (ts , s) = lexerBracket 1 (Lexer) cs
+ in (OpenBracket : ts , s)
+lexer ('(':cs) = let (ts , s) = lexerParen 1 (Lexer) cs
+ in (OpenParen : ts , s)
+lexer (')':cs) = lexer cs
+lexer (']':cs) = lexer cs
+lexer ('"':cs) = let (t , cs2) = lexerWord (isDelimiter) cs
+ (ts , s) = lexer cs2
+ in ((QuotedWord (upWord t)):ts , s)
+lexer cs = let (t , cs2) = lexerWord (isDelimiter) cs
+ (ts , s) = lexer cs2
+ in ((Normal (upWord t)):ts , s)
+
+lexerWord :: (Char -> Bool) -> [Char] -> (WordType , [Char])
+lexerWord endCond []
+ = ([] , [])
+lexerWord endCond (c:cs)
+ | c == '\\' = if cs == []
+ then ("\\" , cs)
+ else
+ let (t , cs2) = lexerWord endCond (tail cs)
+ in ((head cs):t , cs2)
+ | endCond c = ([] , (c:cs))
+ | otherwise = let (t , cs2) = lexerWord endCond cs
+ in ((toUpper c):t , cs2)
+
+
+-- performs lexing inside brackets
+lexerBracket :: Int -> LexState -> LexerType
+lexerBracket n s []
+ = ([] , LexerBracket n s)
+lexerBracket n s (' ':cs)
+ = lexerBracket n s cs
+lexerBracket 1 s (']':cs)
+ = let (ts , s2) = lexDispatch s cs
+ in (CloseBracket:ts , s2)
+lexerBracket n s (']':cs)
+ = let (ts , s2) = lexerBracket (n-1) s cs
+ in (CloseBracket:ts , s2)
+lexerBracket n s ('[':cs)
+ = let (ts , s2) = lexerBracket (n+1) s cs
+ in (OpenBracket:ts , s2)
+lexerBracket n s ('(':cs)
+ = let (ts , s2) = lexerParen 1 (LexerBracket n s) cs
+ in (OpenParen:ts , s2)
+lexerBracket n s (')':cs)
+ = lexerBracket n s cs
+lexerBracket n s cs
+ = let (t , cs2) = lexerWord (isDelimiter) cs
+ (ts , s2) = lexerBracket n s cs2
+ in ((Normal (upWord t)):ts , s2)
+
+
+-- performs lexing inside parentheses
+lexerParen :: Int -> LexState -> LexerType
+lexerParen n s []
+ = ([] , LexerParen n s)
+lexerParen n s (' ':cs)
+ = lexerParen n s cs
+lexerParen 1 s (')':cs)
+ = let (ts , s2) = lexDispatch s cs
+ in (CloseParen:ts , s2)
+lexerParen n s (')':cs)
+ = let (ts , s2) = lexerParen (n-1) s cs
+ in (CloseParen:ts , s2)
+lexerParen n s ('(':cs)
+ = let (ts , s2) = lexerParen (n+1) s cs
+ in (OpenParen:ts , s2)
+lexerParen n s ('[':cs)
+ = let (ts , s2) = lexerBracket 1 (LexerParen n s) cs
+ in (OpenBracket:ts , s2)
+lexerParen n s (']':cs)
+ = lexerParen n s cs
+lexerParen n s ('"':cs)
+ = let (t , cs2) = lexerWord (isDelimiter) cs
+ (ts , s2) = lexerParen n s cs2
+ in ((QuotedWord (upWord t)):ts , s2)
+lexerParen n s cs
+ = let (t , cs2) = lexerWord (isDelimiter) cs
+ (ts , s2) = lexerParen n s cs2
+ in ((Normal (upWord t)):ts , s2)
+
+
+-- returns true for delimiters
+isDelimiter :: Char -> Bool
+isDelimiter = inList " []()"
+
+-- returns true of p is in cs
+inList :: (Eq a) => [a] -> a -> Bool
+inList [] p = False
+inList (c:cs) p = (c == p) || (inList cs p)
+
+
+-- handle user input
+lexerReadLine :: [Char] -> [WordType]
+lexerReadLine []
+ = []
+lexerReadLine (' ':cs)
+ = lexerReadLine cs
+lexerReadLine cs
+ = let (firstWord,restOfWords) = span (/= ' ') cs
+ in (upWord firstWord) : lexerReadLine restOfWords
+
+-- translate a word to upper case
+upWord :: WordType -> WordType
+upWord = map (toUpper)
+
+
+
+-------------------------------------------------------------------------------
+module Parser where
+
+{-
+
+Parser takes a list of tokens, the input state, and fail and success
+continuations and returns an Abstract Syntax Tree, the remaining
+tokens (hopefully none), and the new input state. The input state
+will be changed every time Parser runs out of tokens: it simply grabs
+(and lexes) the next line of user-input. It therefore doesn't return
+anything until the entire AST has been be read in, even if it spans
+several lines, though parse may catch some errors before all lines
+have been input. In this case, it ceases taking input and returns the
+error.
+
+An Abstract Syntax Tree represents one command, and breaks those
+commands into Ifs, Loops, Tos, Locals, Makes, Reads, Prints,
+Constants, List constants, Graphics commands (which produce
+side-effects), and function applications. All built-in commands that
+don't fit into one of those categories are lumped into function
+applications along with user-defined functions. Each type of AST is
+parsed into subcommands, subclauses (lists of commands), command
+arguments (also subcommands), and any other values that will be
+immediately-evaluatable (such as function names).
+
+-}
+
+
+import Lexer
+import Evaluator
+
+
+type CommandName = [Char]
+type ClauseType = [AST]
+type ConditionType = AST
+
+type ParseArgs = [AST]
+
+data ArgType = Val Value | QuotedWordArg WordType
+ deriving Text
+
+data AST = ParseList ListType
+ | If ConditionType ClauseType ClauseType
+ | Loop LoopType ConditionType ClauseType
+ | To NameType ProcType
+ | Make NameType AST
+ | Local NameType
+ | Read
+ | Print ParseArgs
+ | Argument ArgType
+ | Graphics CommandName ParseArgs
+ | Command CommandName ParseArgs deriving Text
+
+data LoopType = Do | While | Repeat
+ deriving Text
+
+type ParseFailType = Error -> InputState -> IO ()
+type ParseType = [Token] -> InputState -> ParseFailType ->
+ (AST -> [Token] -> InputState -> IO ()) -> IO ()
+type ParseClauseType = [Token] -> InputState -> ParseFailType ->
+ (ClauseType -> [Token] -> InputState -> IO ()) -> IO ()
+
+type InputState = ([[Char]] , LexState)
+
+parse :: ParseType
+
+parse [] (i:is , ls) fail succ
+ = let (ts , ls2) = lexDispatch ls i
+ in parse ts (is , ls2) fail succ
+
+parse ((QuotedWord s) : ts) inS fail succ
+ = succ (Argument (QuotedWordArg s)) ts inS
+
+parse ((Normal s) : ts) inS fail succ
+ = succ (Argument (Val (process s))) ts inS
+
+parse (OpenParen : []) (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in parse (OpenParen:ts) (is,ls2) fail succ
+
+parse (OpenParen : (Normal t) : ts) inS fail succ
+ | t == "TO" = makeProc ts inS fail succ
+ | t == "MAKE" = makeMake ts inS fail succ
+ | t == "LOCAL" = makeLocal ts inS fail succ
+ | t == "READ" = makeRead ts inS fail succ
+ | t == "PRINT" = makePrint ts inS fail succ
+ | t == "IF" = makeIf ts inS fail succ
+ | isLoop t = makeLoop t ts inS fail succ
+ | isGraphics t = makeGraphics t ts inS fail succ
+ | otherwise = makeCommand t ts inS fail succ
+
+parse (OpenBracket : ts) inS fail succ
+ = parseList ts inS fail succ
+
+parse ts inS@([], _) _ succ = succ (Argument (Val (Word "GOODBYE"))) ts inS
+
+parse _ inS fail _
+ = fail "Syntax error" inS
+
+
+-- returns true for all loop names
+isLoop :: CommandName -> Bool
+isLoop = inList ["DO","WHILE","REPEAT"]
+
+-- returns true for all side-effecting graphics command names
+isGraphics :: CommandName -> Bool
+isGraphics = inList ["FORWARD","BACKWARD","LEFT","RIGHT",
+ "SETXY","SETANGLE","PENUP","PENDOWN",
+ "HIDETURTLE","SHOWTURTLE","CLEARSCREEN","CLEAN"]
+
+-- Parse lists --
+
+-- parses a list constant
+parseList :: ParseType
+parseList [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in parseList ts (is,ls2) fail succ
+parseList (CloseBracket:ts) inS fail succ
+ = succ (ParseList NullList) ts inS
+parseList (OpenBracket:ts) inS fail succ
+ = parseList ts inS fail $ \(ParseList l1) ts2 inS2 ->
+ parseList ts2 inS2 fail $ \(ParseList l2) ts3 inS3 ->
+ succ (ParseList ((List l1) :* l2)) ts3 inS3
+parseList ((Normal w):ts) inS fail succ
+ = parseList ts inS fail $ \(ParseList l) ts2 inS2 ->
+ succ (ParseList ((process w) :* l)) ts2 inS2
+parseList (OpenParen:ts) inS fail succ
+ = parseList ts inS fail $ \(ParseList l) ts2 inS2 ->
+ succ (ParseList ((Word "(") :* l)) ts2 inS2
+parseList (CloseParen:ts) inS fail succ
+ = parseList ts inS fail $ \(ParseList l) ts2 inS2 ->
+ succ (ParseList ((Word ")") :* l)) ts2 inS2
+parseList ((QuotedWord w):ts) inS fail succ
+ = parseList ts inS fail $ \(ParseList l) ts2 inS2 ->
+ succ (ParseList ((Word w) :* l)) ts2 inS2
+
+
+-- parses constant values, distinguishing words from integers and booleans
+process :: WordType -> Value
+process "TRUE" = Boolean True
+process "FALSE" = Boolean False
+process ('-':w)
+ | all isDigit w = Num (- (stringToNum (reverse w)))
+ | otherwise = Word ('-':w)
+process w
+ | all isDigit w = Num (stringToNum (reverse w))
+ | otherwise = Word w
+
+-- converts a string to a positive integer
+stringToNum :: String -> Int
+stringToNum (d:[]) = charToDigit d
+stringToNum (d:ds) = (charToDigit d) + 10 * stringToNum ds
+
+-- converts a character to a digit
+charToDigit :: Char -> Int
+charToDigit c = ord c - ord '0'
+
+
+-- Parse command statements --
+
+-- parses commands
+-- format: (<name> <arg1> <arg2> ...)
+makeCommand :: CommandName -> ParseType
+makeCommand n ts inS fail succ
+ = parseArgs CloseParen ts inS fail $ \as ts2 inS2 ->
+ succ (Command n as) ts2 inS2
+
+
+-- parses a list of commands that are terminated by token "term""
+parseArgs :: Token -> ParseClauseType
+parseArgs term [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in parseArgs term ts (is,ls2) fail succ
+parseArgs term (t:ts) inS fail succ
+ | t == term = succ [] ts inS
+ | otherwise = parse (t:ts) inS fail $ \a ts2 inS2 ->
+ parseArgs term ts2 inS2 fail $ \as ts3 inS3 ->
+ succ (a:as) ts3 inS3
+
+
+-- Parse I/O statements --
+
+-- parses read statements
+-- format: (READ)
+makeRead :: ParseType
+makeRead (CloseParen:ts) inS fail succ
+ = succ Read ts inS
+makeRead _ inS fail _
+ = fail "Read: too many arguments" inS
+
+-- parses print statements
+-- format: (PRINT <arg1>)
+makePrint :: ParseType
+makePrint ts inS fail succ
+ = parseArgs CloseParen ts inS fail $ \as ts2 inS2 ->
+ if (length as) == 1
+ then succ (Print as) ts2 inS2
+ else fail "Print: too many arguments" inS
+
+
+
+-- Parse TO statements --
+
+
+-- parses to statements
+-- format: (TO <name> <fpname1> <fpname2> ... <clause>)
+-- note: all formal parameter names must begin with a colon
+makeProc :: ParseType
+makeProc [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in makeProc ts (is,ls2) fail succ
+makeProc ((Normal t):ts) inS fail succ
+ = parseFormals ts inS fail $ \p ts2 inS2 ->
+ getParen ts2 inS2 fail $ \ts3 inS3 ->
+ succ (To t p) ts3 inS3
+makeProc _ inS fail _
+ = fail "Invalid procedure name" inS
+
+-- parses the formal parameters
+-- takes all words beginning with a colon, and assumes everything
+-- after that is part of the body
+parseFormals :: [Token] -> InputState -> ParseFailType ->
+ (([NameType] , ClauseType) -> [Token] -> InputState -> IO ())
+ -> IO ()
+parseFormals [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in parseFormals ts (is,ls2) fail succ
+parseFormals (OpenBracket:ts) inS fail succ
+ = parseClause (OpenBracket:ts) inS fail $ \pb ts2 inS2 ->
+ succ ([],pb) ts2 inS2
+parseFormals ((Normal (':':c:cs)):ts) inS fail succ
+ = parseFormals ts inS fail $ \(formals,pb) ts2 inS2 ->
+ succ ((':':c:cs):formals , pb) ts2 inS2
+parseFormals ts inS fail succ
+ = parseClause ts inS fail $ \pb ts2 inS2 ->
+ succ ([],pb) ts2 inS2
+
+
+-- Parse MAKE statements --
+
+-- parses make statements
+-- format: (MAKE <name> <arg>)
+-- note: <name> must be quoted
+makeMake :: ParseType
+makeMake [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in makeMake ts (is,ls2) fail succ
+makeMake ((QuotedWord s):ts) inS fail succ
+ = parse ts inS fail $ \a ts2 inS2 ->
+ getParen ts2 inS2 fail $ \ts3 inS3 ->
+ succ (Make s a) ts3 inS3
+makeMake _ inS fail _
+ = fail "Make: Improper variable name" inS
+
+
+-- Parse LOCAL statements --
+
+-- parses local statements
+-- format: (LOCAL <name>)
+-- note: <name> must be quoted
+makeLocal :: ParseType
+makeLocal [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in makeLocal ts (is,ls2) fail succ
+makeLocal (t:[]) (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in makeLocal (t:ts) (is,ls2) fail succ
+makeLocal ((QuotedWord s):CloseParen:ts) inS fail succ
+ = succ (Local s) ts inS
+makeLocal _ inS fail _
+ = fail "Local: improper variable name" inS
+
+
+-- Parse IF statements --
+
+-- parses if-then and if-then-else statements
+-- format: (IF <cond> then <clause> [else <clause>])
+makeIf :: ParseType
+makeIf [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in makeIf ts (is,ls2) fail succ
+makeIf ts inS fail succ
+ = parse ts inS fail $ \cond ts2 inS2 ->
+ parseThen ts2 inS2 fail $ \thens elses ts3 inS3 ->
+ getParen ts3 inS3 fail $ \ts4 inS4 ->
+ succ (If cond thens elses) ts4 inS4
+
+
+-- parses then clauses
+parseThen :: [Token] -> InputState -> ParseFailType ->
+ (ClauseType -> ClauseType -> [Token] -> InputState -> IO ()) ->
+ IO ()
+parseThen [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in parseThen ts (is,ls2) fail succ
+parseThen ((Normal "THEN"):ts) inS fail succ
+ = parseClause ts inS fail $ \thens ts2 inS2 ->
+ parseElse ts2 inS2 fail $ \elses ts3 inS3 ->
+ succ thens elses ts3 inS3
+parseThen _ inS fail _
+ = fail "IF: improper THEN clause" inS
+
+-- parses (optional) else clauses
+parseElse :: ParseClauseType
+parseElse [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in parseElse ts (is,ls2) fail succ
+parseElse (CloseParen:ts) inS fail succ
+ = succ [] (CloseParen:ts) inS
+parseElse ((Normal "ELSE"):ts) inS fail succ
+ = parseClause ts inS fail succ
+parseElse _ inS fail _
+ = fail "IF: improper ELSE clause" inS
+
+-- parses clauses
+-- a clause is either a list of commands enclosed in brackets, or a
+-- single command
+parseClause :: ParseClauseType
+parseClause [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in parseClause ts (is,ls2) fail succ
+parseClause (OpenBracket:ts) inS fail succ
+ = parseArgs CloseBracket ts inS fail succ
+parseClause ts inS fail succ
+ = parse ts inS fail $ \a ts2 inS2 ->
+ succ [a] ts2 inS2
+
+
+-- Parse Loop Statements --
+
+-- parses loop statements
+-- basically a dispatcher for other parse functions
+makeLoop :: NameType -> ParseType
+makeLoop "DO" = makeDo
+makeLoop "WHILE" = makeWhile
+makeLoop "REPEAT" = makeRepeat
+
+-- parses do statements
+-- format: (DO <clause> WHILE <cond>)
+makeDo :: ParseType
+makeDo ts inS fail succ
+ = parseClause ts inS fail $ \insts ts2 inS2 ->
+ parseWhileCond ts2 inS2 fail $ \cond ts3 inS3 ->
+ getParen ts3 inS3 fail $ \ts4 inS4 ->
+ succ (Loop Do cond insts) ts4 inS4
+
+-- parses while conditions (both in while and do-while loops)
+-- a condition is simply a command that (hopefully) returns a boolean
+parseWhileCond :: ParseType
+parseWhileCond [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in parseWhileCond ts (is,ls2) fail succ
+parseWhileCond ((Normal "WHILE"):ts) inS fail succ
+ = parse ts inS fail succ
+
+-- parses while statements
+-- format: (WHILE <cond> <clause>)
+makeWhile :: ParseType
+makeWhile ts inS fail succ
+ = parse ts inS fail $ \cond ts2 inS2 ->
+ parseClause ts2 inS fail $ \insts ts3 inS3 ->
+ getParen ts3 inS3 fail $ \ts4 inS4 ->
+ succ (Loop While cond insts) ts4 inS4
+
+-- parses repeat statements
+-- format: (REPEAT <num> TIMES <clause>)
+-- note: <num> is simply a command that (hopefully) returns an integer
+makeRepeat :: ParseType
+makeRepeat ts inS fail succ
+ = parse ts inS fail $ \num ts2 inS2 ->
+ parseRepeatBody ts2 inS fail $ \insts ts3 inS3 ->
+ getParen ts3 inS3 fail $ \ts4 inS4 ->
+ succ (Loop Repeat num insts) ts4 inS4
+
+-- parses repeat body (just a clause)
+parseRepeatBody :: ParseClauseType
+parseRepeatBody [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in parseRepeatBody ts (is,ls2) fail succ
+parseRepeatBody ((Normal "TIMES"):ts) inS fail succ
+ = parseClause ts inS fail succ
+parseRepeatBody _ inS fail _
+ = fail "Repeat: invalid format" inS
+
+
+-- Parse Graphics Statements --
+
+-- parses all side-effecting graphics statements
+makeGraphics :: CommandName -> ParseType
+makeGraphics n ts inS fail succ
+ = parseArgs CloseParen ts inS fail $ \as ts2 inS2 ->
+ succ (Graphics n as) ts2 inS2
+
+-- Parse Trailing Parenthesis --
+
+-- parses the closing paren terminating most commands
+getParen :: [Token] -> InputState -> ParseFailType ->
+ ([Token] -> InputState -> IO ()) -> IO ()
+getParen [] (i:is,ls) fail succ
+ = let (ts,ls2) = lexDispatch ls i
+ in getParen ts (is,ls) fail succ
+getParen (CloseParen:ts) inS fail succ
+ = succ ts inS
+getParen _ inS fail _
+ = fail "Expected )" inS
+
diff --git a/progs/demo/X11/logo/logo.hu b/progs/demo/X11/logo/logo.hu
new file mode 100644
index 0000000..388e926
--- /dev/null
+++ b/progs/demo/X11/logo/logo.hu
@@ -0,0 +1,3 @@
+:o= foldr inline constant
+$HASKELL_LIBRARY/X11/xlib.hu
+logo.hs
diff --git a/progs/demo/X11/mdraw/README b/progs/demo/X11/mdraw/README
new file mode 100644
index 0000000..c78f7d9
--- /dev/null
+++ b/progs/demo/X11/mdraw/README
@@ -0,0 +1 @@
+This is a multiple screen version of the draw program.
diff --git a/progs/demo/X11/mdraw/mdraw.hs b/progs/demo/X11/mdraw/mdraw.hs
new file mode 100644
index 0000000..c4bb508
--- /dev/null
+++ b/progs/demo/X11/mdraw/mdraw.hs
@@ -0,0 +1,83 @@
+module MDraw where
+
+import Xlib
+
+mapIO :: (a -> IO b) -> [a] -> IO [b]
+
+mapIO f [] = returnIO []
+mapIO f (x:xs) = f x `thenIO` \ y ->
+ mapIO f xs `thenIO` \ ys ->
+ returnIO (y:ys)
+
+map2IO :: (a -> b -> IO c) -> [a] -> [b] -> IO [c]
+
+map2IO f [] [] = returnIO []
+map2IO f (x:xs) (z:zs) = f x z `thenIO` \ y ->
+ map2IO f xs zs `thenIO` \ ys ->
+ returnIO (y:ys)
+
+xGetEventMul :: XMArray XDisplay -> IO (Int, XEvent)
+xGetEventMul displays =
+ let n_displays = xMArrayLength displays
+ loop :: Int -> IO (Int, XEvent)
+ loop i = if i == n_displays then loop 0
+ else xMArrayLookup displays i `thenIO` \ display ->
+ xDisplayForceOutput display `thenIO` \ _ ->
+ xEventListen display `thenIO` \ n_events ->
+ if n_events == 0 then loop (i + 1)
+ else xGetEvent display `thenIO` \ event ->
+ returnIO (i, event)
+ in loop 0
+
+-- takes a list of host names
+
+mdraw :: [String] -> IO ()
+mdraw hosts =
+ xHandleError (\ (XError msg) -> appendChan stdout msg exit done) $
+ mapIO xOpenDisplay hosts `thenIO` \ displays ->
+ let screens = map (head . xDisplayRoots) displays
+ fg_colors = map xScreenBlackPixel screens
+ bg_colors = map xScreenWhitePixel screens
+ roots = map xScreenRoot screens
+ in
+ map2IO (\ root color ->
+ xCreateWindow root
+ (XRect 100 100 400 400)
+ [XWinBackground color,
+ XWinEventMask (XEventMask [XButtonMotion,
+ XButtonPress])])
+ roots
+ bg_colors
+ `thenIO` \windows ->
+ mapIO xMapWindow windows `thenIO` \ _ ->
+ map2IO xCreateGcontext
+ (map XDrawWindow roots)
+ (map (\ color -> [XGCForeground color]) fg_colors)
+ `thenIO` \ gcontexts ->
+ xMArrayCreate displays `thenIO` \ displayArr ->
+ let
+ handleEvent lasts =
+ xGetEventMul displayArr `thenIO` \ (idx, event) ->
+ let pos = xEventPos event
+ in
+ case (xEventType event) of
+ XButtonPressEvent ->
+ xMArrayUpdate lasts idx pos `thenIO` \ () ->
+ handleEvent lasts
+ XMotionNotifyEvent ->
+ xMArrayLookup lasts idx `thenIO` \ last ->
+ map2IO (\ window gcontext -> xDrawLine (XDrawWindow window)
+ gcontext
+ last
+ pos)
+ windows
+ gcontexts
+ `thenIO` \ _ ->
+ xMArrayUpdate lasts idx pos `thenIO` \ () ->
+ handleEvent lasts
+ _ -> handleEvent lasts
+ in
+ xMArrayCreate (map (\ _ -> XPoint 0 0) hosts) `thenIO` \ lasts ->
+ handleEvent lasts `thenIO` \ _ ->
+ returnIO ()
+
diff --git a/progs/demo/X11/mdraw/mdraw.hu b/progs/demo/X11/mdraw/mdraw.hu
new file mode 100644
index 0000000..16296d5
--- /dev/null
+++ b/progs/demo/X11/mdraw/mdraw.hu
@@ -0,0 +1,3 @@
+:o= all
+$HASKELL_LIBRARY/X11/xlib.hu
+mdraw.hs
diff --git a/progs/demo/X11/mdraw/t.hs b/progs/demo/X11/mdraw/t.hs
new file mode 100644
index 0000000..77f2baf
--- /dev/null
+++ b/progs/demo/X11/mdraw/t.hs
@@ -0,0 +1,16 @@
+module Test where
+import Xlib
+
+xGetEventMul :: XMArray XDisplay -> IO (Int, XEvent)
+xGetEventMul displays =
+ let n_displays = xMArrayLength displays
+ loop :: Int -> IO (Int, XEvent)
+ loop i = if i == n_displays then loop 0
+ else xMArrayLookup displays i `thenIO` \ display ->
+ xDisplayForceOutput display `thenIO` \ _ ->
+ xEventListen display `thenIO` \ n_events ->
+ if n_events == 0 then loop (i + 1)
+ else xGetEvent display `thenIO` \ event ->
+ returnIO (i, event)
+ in loop 0
+
diff --git a/progs/demo/X11/mdraw/t.hu b/progs/demo/X11/mdraw/t.hu
new file mode 100644
index 0000000..657234c
--- /dev/null
+++ b/progs/demo/X11/mdraw/t.hu
@@ -0,0 +1,3 @@
+:o= all
+$HASKELL_LIBRARY/X11/xlib.hu
+t.hs
diff --git a/progs/demo/add.hs b/progs/demo/add.hs
new file mode 100644
index 0000000..bdfcc2f
--- /dev/null
+++ b/progs/demo/add.hs
@@ -0,0 +1,21 @@
+-- this is an interactive program to read in two numbers and print their sum.
+
+module Main where
+
+main = readChan stdin abort $ \userInput ->
+ let inputLines = lines userInput in
+ readInt "Enter first number: " inputLines $ \num1 inputLines1 ->
+ readInt "Enter second number: " inputLines1 $ \ num2 _ ->
+ appendChan stdout ("Their sum is: " ++ show (num1 + num2)) abort done
+
+readInt :: String -> [String] -> (Integer -> [String] -> Dialogue) -> Dialogue
+
+readInt prompt inputLines succ =
+ appendChan stdout prompt abort $
+ case inputLines of
+ (l1 : rest) -> case (reads l1) of
+ [(x,"")] -> succ x rest
+ _ -> appendChan stdout
+ "Error - retype the number\n" abort $
+ readInt prompt rest succ
+ _ -> appendChan stdout "Early EOF" abort done
diff --git a/progs/demo/eliza.hs b/progs/demo/eliza.hs
new file mode 100644
index 0000000..d7bf975
--- /dev/null
+++ b/progs/demo/eliza.hs
@@ -0,0 +1,267 @@
+-- Eliza: an implementation of the classic pseudo-psychoanalyst ---------------
+--
+-- Gofer version by Mark P. Jones, January 12 1992
+--
+-- Adapted from a pascal implementation provided as part of an experimental
+-- package from James Risner (risner@ms.uky.edu), Univ. of KY. with original
+-- pascal code apparently provided by Robert Migliaccio (mig@ms.uky.edu).
+-------------------------------------------------------------------------------
+
+import Prelude hiding (conjugate)
+
+main :: Dialogue
+main = interact (("\n\
+ \Hi! I'm Eliza. I am your personal therapy computer.\n\
+ \Please tell me your problem.\n\
+ \\n" ++)
+ . session initial []
+ . filter (not.null)
+ . map (words . trim)
+ . lines)
+
+trim :: String -> String -- strip punctuation characters
+trim = foldr cons "" . dropWhile (`elem` punct)
+ where x `cons` xs | x `elem` punct && null xs = []
+ | otherwise = x : xs
+ punct = [' ', '.', '!', '?', ',']
+
+-- Read a line at a time, and produce some kind of response -------------------
+
+session :: State -> Words -> [Words] -> String
+session rs prev [] = []
+session rs prev (l:ls) = response ++ "\n\n" ++ session rs' l ls
+ where (response, rs') | prev == l = repeated rs
+ | otherwise = answer rs l
+
+answer :: State -> Words -> (String, State)
+answer st l = (response, newKeyTab kt st)
+ where (response, kt) = ans (keyTabOf st)
+ e `cons` (r, es) = (r, e:es)
+ ans (e:es) | null rs = e `cons` ans es
+ | otherwise = (makeResponse a (head rs), (key,as):es)
+ where rs = replies key l
+ (key,(a:as)) = e
+
+-- Find all possible replies (without leading string for given key ------------
+
+replies :: Words -> Words -> [String]
+replies key l = ( map (conjugate l . drop (length key))
+ . filter (prefix key . map ucase)
+ . tails) l
+
+prefix :: Eq a => [a] -> [a] -> Bool
+[] `prefix` xs = True
+(x:xs) `prefix` [] = False
+(x:xs) `prefix` (y:ys) = x==y && (xs `prefix` ys)
+
+tails :: [a] -> [[a]] -- non-empty tails of list
+tails [] = []
+tails xs = xs : tails (tail xs)
+
+ucase :: String -> String -- map string to upper case
+ucase = map toUpper
+
+-- Replace keywords in a list of words with appropriate conjugations ----------
+
+conjugate :: Words -> Words -> String
+conjugate d = unwords . trailingI . map conj . maybe d -- d is default input
+ where maybe d xs = if null xs then d else xs
+ conj w = head ([m | (w',m)<-conjugates, uw==w'] ++ [w])
+ where uw = ucase w
+ trailingI = foldr cons []
+ where x `cons` xs | x=="I" && null xs = ["me"]
+ | otherwise = x:xs
+
+conjugates :: [(Word, Word)]
+conjugates = prepare (oneways ++ concat [[(x,y), (y,x)] | (x,y) <- bothways])
+ where oneways = [ ("me", "you") ]
+ bothways = [ ("are", "am"), ("we're", "was"),
+ ("you", "I"), ("your", "my"),
+ ("I've", "you've"), ("I'm", "you're") ]
+ prepare = map (\(w,r) -> (ucase w, r))
+
+-- Response data --------------------------------------------------------------
+
+type Word = String
+type Words = [Word]
+type KeyTable = [(Key, Replies)]
+type Replies = [String]
+type State = (KeyTable, Replies)
+type Key = Words
+
+repeated :: State -> (String, State)
+repeated (kt, (r:rp)) = (r, (kt, rp))
+
+newKeyTab :: KeyTable -> State -> State
+newKeyTab kt' (kt, rp) = (kt', rp)
+
+keyTabOf :: State -> KeyTable
+keyTabOf (kt, rp) = kt
+
+makeResponse :: String -> String -> String
+makeResponse ('?':cs) us = cs ++ " " ++ us ++ "?"
+makeResponse ('.':cs) us = cs ++ " " ++ us ++ "."
+makeResponse cs us = cs
+
+initial :: State
+initial = ([(words k, cycle rs) | (k,rs) <-respMsgs], cycle repeatMsgs)
+
+respMsgs = [ ("CAN YOU", canYou),
+ ("CAN I", canI),
+ ("YOU ARE", youAre),
+ ("YOU'RE", youAre),
+ ("I DON'T", iDont),
+ ("I FEEL", iFeel),
+ ("WHY DON'T YOU", whyDont),
+ ("WHY CAN'T I", whyCant),
+ ("ARE YOU", areYou),
+ ("I CAN'T", iCant),
+ ("I AM", iAm),
+ ("I'M", iAm),
+ ("YOU", you),
+ ("YES", yes),
+ ("NO", no),
+ ("COMPUTER", computer),
+ ("COMPUTERS", computer),
+ ("I WANT", iWant),
+ ("WHAT", question),
+ ("HOW", question),
+ ("WHO", question),
+ ("WHERE", question),
+ ("WHEN", question),
+ ("WHY", question),
+ ("NAME", name),
+ ("BECAUSE", because),
+ ("CAUSE", because),
+ ("SORRY", sorry),
+ ("DREAM", dream),
+ ("DREAMS", dream),
+ ("HI", hello),
+ ("HELLO", hello),
+ ("MAYBE", maybe),
+ ("YOUR", your),
+ ("ALWAYS", always),
+ ("THINK", think),
+ ("ALIKE", alike),
+ ("FRIEND", friend),
+ ("FRIENDS", friend),
+ ("", nokeyMsgs) ]
+
+canYou = [ "?Don't you believe that I can",
+ "?Perhaps you would like to be able to",
+ "?You want me to be able to" ]
+canI = [ "?Perhaps you don't want to",
+ "?Do you want to be able to" ]
+youAre = [ "?What makes you think I am",
+ "?Does it please you to believe I am",
+ "?Perhaps you would like to be",
+ "?Do you sometimes wish you were" ]
+iDont = [ "?Don't you really",
+ "?Why don't you",
+ "?Do you wish to be able to",
+ "Does that trouble you?" ]
+iFeel = [ "Tell me more about such feelings.",
+ "?Do you often feel",
+ "?Do you enjoy feeling" ]
+whyDont = [ "?Do you really believe I don't",
+ ".Perhaps in good time I will",
+ "?Do you want me to" ]
+whyCant = [ "?Do you think you should be able to",
+ "?Why can't you" ]
+areYou = [ "?Why are you interested in whether or not I am",
+ "?Would you prefer if I were not",
+ "?Perhaps in your fantasies I am" ]
+iCant = [ "?How do you know you can't",
+ "Have you tried?",
+ "?Perhaps you can now" ]
+iAm = [ "?Did you come to me because you are",
+ "?How long have you been",
+ "?Do you believe it is normal to be",
+ "?Do you enjoy being" ]
+you = [ "We were discussing you --not me.",
+ "?Oh,",
+ "You're not really talking about me, are you?" ]
+yes = [ "You seem quite positive.",
+ "Are you Sure?",
+ "I see.",
+ "I understand." ]
+no = [ "Are you saying no just to be negative?",
+ "You are being a bit negative.",
+ "Why not?",
+ "Are you sure?",
+ "Why no?" ]
+computer = [ "Do computers worry you?",
+ "Are you talking about me in particular?",
+ "Are you frightened by machines?",
+ "Why do you mention computers?",
+ "What do you think machines have to do with your problems?",
+ "Don't you think computers can help people?",
+ "What is it about machines that worries you?" ]
+iWant = [ "?Why do you want",
+ "?What would it mean to you if you got",
+ "?Suppose you got",
+ "?What if you never got",
+ ".I sometimes also want" ]
+question = [ "Why do you ask?",
+ "Does that question interest you?",
+ "What answer would please you the most?",
+ "What do you think?",
+ "Are such questions on your mind often?",
+ "What is it that you really want to know?",
+ "Have you asked anyone else?",
+ "Have you asked such questions before?",
+ "What else comes to mind when you ask that?" ]
+name = [ "Names don't interest me.",
+ "I don't care about names --please go on." ]
+because = [ "Is that the real reason?",
+ "Don't any other reasons come to mind?",
+ "Does that reason explain anything else?",
+ "What other reasons might there be?" ]
+sorry = [ "Please don't apologise!",
+ "Apologies are not necessary.",
+ "What feelings do you have when you apologise?",
+ "Don't be so defensive!" ]
+dream = [ "What does that dream suggest to you?",
+ "Do you dream often?",
+ "What persons appear in your dreams?",
+ "Are you disturbed by your dreams?" ]
+hello = [ "How do you...please state your problem." ]
+maybe = [ "You don't seem quite certain.",
+ "Why the uncertain tone?",
+ "Can't you be more positive?",
+ "You aren't sure?",
+ "Don't you know?" ]
+your = [ "?Why are you concerned about my",
+ "?What about your own" ]
+always = [ "Can you think of a specific example?",
+ "When?",
+ "What are you thinking of?",
+ "Really, always?" ]
+think = [ "Do you really think so?",
+ "?But you are not sure you",
+ "?Do you doubt you" ]
+alike = [ "In what way?",
+ "What resemblence do you see?",
+ "What does the similarity suggest to you?",
+ "What other connections do you see?",
+ "Cound there really be some connection?",
+ "How?" ]
+friend = [ "Why do you bring up the topic of friends?",
+ "Do your friends worry you?",
+ "Do your friends pick on you?",
+ "Are you sure you have any friends?",
+ "Do you impose on your friends?",
+ "Perhaps your love for friends worries you." ]
+
+repeatMsgs = [ "Why did you repeat yourself?",
+ "Do you expect a different answer by repeating yourself?",
+ "Come, come, elucidate your thoughts.",
+ "Please don't repeat yourself!" ]
+
+nokeyMsgs = [ "I'm not sure I understand you fully.",
+ "What does that suggest to you?",
+ "I see.",
+ "Can you elaborate on that?",
+ "Say, do you have any psychological problems?" ]
+
+-------------------------------------------------------------------------------
diff --git a/progs/demo/fact.hs b/progs/demo/fact.hs
new file mode 100755
index 0000000..054183e
--- /dev/null
+++ b/progs/demo/fact.hs
@@ -0,0 +1,14 @@
+{- This is a simple factorial program which uses the I/O system
+ to read the input and print the result -}
+
+module Main where
+
+fact :: Integer -> Integer
+fact 0 = 1
+fact (n+1) = (n+1)*fact n
+fact _ = error "Negative argument to factorial"
+
+main = appendChan stdout "Type in N: " abort $
+ readChan stdin abort $ \ input ->
+ appendChan stdout (show (fact (read (head (lines input))))) abort done
+
diff --git a/progs/demo/improved-add.hs b/progs/demo/improved-add.hs
new file mode 100644
index 0000000..bdfcc2f
--- /dev/null
+++ b/progs/demo/improved-add.hs
@@ -0,0 +1,21 @@
+-- this is an interactive program to read in two numbers and print their sum.
+
+module Main where
+
+main = readChan stdin abort $ \userInput ->
+ let inputLines = lines userInput in
+ readInt "Enter first number: " inputLines $ \num1 inputLines1 ->
+ readInt "Enter second number: " inputLines1 $ \ num2 _ ->
+ appendChan stdout ("Their sum is: " ++ show (num1 + num2)) abort done
+
+readInt :: String -> [String] -> (Integer -> [String] -> Dialogue) -> Dialogue
+
+readInt prompt inputLines succ =
+ appendChan stdout prompt abort $
+ case inputLines of
+ (l1 : rest) -> case (reads l1) of
+ [(x,"")] -> succ x rest
+ _ -> appendChan stdout
+ "Error - retype the number\n" abort $
+ readInt prompt rest succ
+ _ -> appendChan stdout "Early EOF" abort done
diff --git a/progs/demo/merge.hs b/progs/demo/merge.hs
new file mode 100755
index 0000000..cf61f8f
--- /dev/null
+++ b/progs/demo/merge.hs
@@ -0,0 +1,26 @@
+{- This is a simple merge sort -}
+
+module Merge where
+
+merge :: [Int] -> [Int] -> [Int]
+merge [] x = x
+merge x [] = x
+merge l1@(a:b) l2@(c:d) | a < c = a:(merge b l2)
+ | otherwise = c:(merge l1 d)
+
+half [] = []
+half [x] = [x]
+half (x:y:z) = x:r where r = half z
+
+sort [] = []
+sort [x] = [x]
+sort l = merge (sort odds) (sort evens) where
+ odds = half l
+ evens = half (tail l)
+
+main =
+ appendChan stdout "Enter a list of integers separated by \",\"\n" abort $
+ readChan stdin abort $ \ input ->
+ appendChan stdout
+ (show (sort (read ("[" ++ (head (lines input)) ++ "]"))))
+ abort done
diff --git a/progs/demo/pascal.hs b/progs/demo/pascal.hs
new file mode 100644
index 0000000..a26e9c9
--- /dev/null
+++ b/progs/demo/pascal.hs
@@ -0,0 +1,24 @@
+{- This uses lazy evaluation to define Pascals triangle -}
+
+module Main where
+
+pascal :: [[Int]]
+pascal = [1] : [[x+y | (x,y) <- zip ([0]++r) (r++[0])] | r <- pascal]
+
+tab :: Int -> ShowS
+tab 0 = id
+tab (n+1) = showChar ' ' . tab n
+
+showRow :: [Int] -> ShowS
+showRow [] = showChar '\n'
+showRow (n:ns) = shows n . showChar ' ' . showRow ns
+
+showTriangle 1 (t:_) = showRow t
+showTriangle (n+1) (t:ts) = tab n . showRow t . showTriangle n ts
+
+main = appendChan stdout "Number of rows: " abort $
+ readChan stdin abort $ \input ->
+ appendChan stdout
+ (showTriangle (read (head (lines input))) pascal "")
+ abort done
+
diff --git a/progs/demo/pfac.hs b/progs/demo/pfac.hs
new file mode 100644
index 0000000..516fc85
--- /dev/null
+++ b/progs/demo/pfac.hs
@@ -0,0 +1,21 @@
+
+-- This is a parallel varient of factorial
+
+module Main where
+
+fac :: Int -> Int
+fac 0 = 1
+fac n = pfac 1 n
+
+pfac :: Int -> Int -> Int
+pfac low high | low == high = low
+ | low + 1 == high = (low * high)
+ | otherwise = pfac low mid * pfac (mid + 1) high
+ where
+ mid = (high + low) `div` 2
+
+main = appendChan stdout "Type in N: " abort $
+ readChan stdin abort $ \ input ->
+ appendChan stdout (show (fac (read (head (lines input))))) abort done
+
+
diff --git a/progs/demo/primes.hs b/progs/demo/primes.hs
new file mode 100755
index 0000000..6c8fe79
--- /dev/null
+++ b/progs/demo/primes.hs
@@ -0,0 +1,16 @@
+-- This program implements Eratosthenes Sieve
+-- to generate prime numbers.
+
+module Main where
+
+primes :: [Int]
+primes = map head (iterate sieve [2 ..])
+
+sieve :: [Int] -> [Int]
+sieve (p:ps) = [x | x <- ps, (x `mod` p) /= 0]
+
+main = appendChan stdout "How many primes? " abort $
+ readChan stdin abort $ \ input ->
+ appendChan stdout (show (take (read (head (lines input))) primes))
+ abort done
+
diff --git a/progs/demo/prolog/Engine.hs b/progs/demo/prolog/Engine.hs
new file mode 100644
index 0000000..a269503
--- /dev/null
+++ b/progs/demo/prolog/Engine.hs
@@ -0,0 +1,61 @@
+--
+-- Stack based Prolog inference engine
+-- Mark P. Jones November 1990
+--
+-- uses Haskell B. version 0.99.3
+--
+module Engine(prove) where
+
+import PrologData
+import Subst
+
+--- Calculation of solutions:
+
+-- the stack based engine maintains a stack of triples (s,goal,alts)
+-- corresponding to backtrack points, where s is the substitution at that
+-- point, goal is the outstanding goal and alts is a list of possible ways
+-- of extending the current proof to find a solution. Each member of alts
+-- is a pair (tp,u) where tp is a new subgoal that must be proved and u is
+-- a unifying substitution that must be combined with the substitution s.
+--
+-- the list of relevant clauses at each step in the execution is produced
+-- by attempting to unify the head of the current goal with a suitably
+-- renamed clause from the database.
+
+type Stack = [ (Subst, [Term], [Alt]) ]
+type Alt = ([Term], Subst)
+
+alts :: Database -> Int -> Term -> [Alt]
+alts db n g = [ (tp,u) | (tm:*tp) <- renClauses db n g, u <- unify g tm ]
+
+-- The use of a stack enables backtracking to be described explicitly,
+-- in the following `state-based' definition of prove:
+
+prove :: Database -> [Term] -> [Subst]
+prove db gl = solve 1 nullSubst gl []
+ where
+ solve :: Int -> Subst -> [Term] -> Stack -> [Subst]
+ solve n s [] ow = s : backtrack n ow
+ solve n s (g:gs) ow
+ | g==theCut = solve n s gs (cut ow)
+ | otherwise = choose n s gs (alts db n (apply s g)) ow
+
+ choose :: Int -> Subst -> [Term] -> [Alt] -> Stack -> [Subst]
+ choose n s gs [] ow = backtrack n ow
+ choose n s gs ((tp,u):rs) ow = solve (n+1) (u@@s) (tp++gs) ((s,gs,rs):ow)
+
+ backtrack :: Int -> Stack -> [Subst]
+ backtrack n [] = []
+ backtrack n ((s,gs,rs):ow) = choose (n-1) s gs rs ow
+
+
+--- Special definitions for the cut predicate:
+
+theCut :: Term
+theCut = Struct "!" []
+
+cut :: Stack -> Stack
+cut (top:(s,gl,_):ss) = top:(s,gl,[]):ss
+cut ss = ss
+
+--- End of Engine.hs
diff --git a/progs/demo/prolog/Engine.hu b/progs/demo/prolog/Engine.hu
new file mode 100644
index 0000000..5a64277
--- /dev/null
+++ b/progs/demo/prolog/Engine.hu
@@ -0,0 +1,3 @@
+Engine.hs
+PrologData.hu
+Subst.hu
diff --git a/progs/demo/prolog/Interact.hs b/progs/demo/prolog/Interact.hs
new file mode 100644
index 0000000..c8bf516
--- /dev/null
+++ b/progs/demo/prolog/Interact.hs
@@ -0,0 +1,76 @@
+--
+-- Interactive utility functions
+-- Mark P. Jones November 1990
+--
+-- uses Haskell B. version 0.99.3
+--
+module Interact(Interactive(..), skip, end, readln, writeln, readch) where
+
+-- The functions defined in this module provide basic facilities for
+-- writing line-oriented interactive programs (i.e. a function mapping
+-- an input string to an appropriate output string). These definitions
+-- are an enhancement of thos in B+W 7.8
+--
+-- skip p is an interactive program which consumes no input, produces
+-- no output and then behaves like the interactive program p.
+-- end is an interactive program which ignores the input and
+-- produces no output.
+-- writeln txt p is an interactive program which outputs the message txt
+-- and then behaves like the interactive program p
+-- readch act def is an interactive program which reads the first character c
+-- from the input stream and behaves like the interactive
+-- program act c. If the input character stream is empty,
+-- readch act def prints the default string def and terminates.
+--
+-- readln p g is an interactive program which prints the prompt p and
+-- reads a line (upto the first carriage return, or end of
+-- input) from the input stream. It then behaves like g line.
+-- Backspace characters included in the input stream are
+-- interpretted in the usual way.
+
+type Interactive = String -> String
+
+--- Interactive program combining forms:
+
+skip :: Interactive -> Interactive
+skip p inn = p inn -- a dressed up identity function
+
+end :: Interactive
+end inn = ""
+
+writeln :: String -> Interactive -> Interactive
+writeln txt p inn = txt ++ p inn
+
+readch :: (Char -> Interactive) -> String -> Interactive
+readch act def "" = def
+readch act def (c:cs) = act c cs
+
+readln :: String -> (String -> Interactive) -> Interactive
+readln prompt g inn = prompt ++ lineOut 0 line ++ "\n"
+ ++ g (noBackSpaces line) input'
+ where line = before '\n' inn
+ input' = after '\n' inn
+ after x = tail . dropWhile (x/=)
+ before x = takeWhile (x/=)
+
+--- Filter out backspaces etc:
+
+rubout :: Char -> Bool
+rubout c = (c=='\DEL' || c=='\BS')
+
+lineOut :: Int -> String -> String
+lineOut n "" = ""
+lineOut n (c:cs)
+ | n>0 && rubout c = "\BS \BS" ++ lineOut (n-1) cs
+ | n==0 && rubout c = lineOut 0 cs
+ | otherwise = c:lineOut (n+1) cs
+
+noBackSpaces :: String -> String
+noBackSpaces = reverse . delete 0 . reverse
+ where delete n "" = ""
+ delete n (c:cs)
+ | rubout c = delete (n+1) cs
+ | n>0 = delete (n-1) cs
+ | otherwise = c:delete 0 cs
+
+--- End of Interact.hs
diff --git a/progs/demo/prolog/Interact.hu b/progs/demo/prolog/Interact.hu
new file mode 100644
index 0000000..41ebb9d
--- /dev/null
+++ b/progs/demo/prolog/Interact.hu
@@ -0,0 +1,2 @@
+Interact.hs
+
diff --git a/progs/demo/prolog/Main.hs b/progs/demo/prolog/Main.hs
new file mode 100644
index 0000000..56d83a8
--- /dev/null
+++ b/progs/demo/prolog/Main.hs
@@ -0,0 +1,87 @@
+--
+-- Prolog interpreter top level module
+-- Mark P. Jones November 1990
+--
+-- uses Haskell B. version 0.99.3
+--
+module Main(main) where
+
+import PrologData
+import Parse
+import Interact
+import Subst
+import Engine
+import Version
+
+--- Command structure and parsing:
+
+data Command = Fact Clause | Query [Term] | Show | Error | Quit | NoChange
+
+command :: Parser Command
+command = just (sptok "bye" `orelse` sptok "quit") `do` (\quit->Quit)
+ `orelse`
+ just (okay NoChange)
+ `orelse`
+ just (sptok "??") `do` (\show->Show)
+ `orelse`
+ just clause `do` Fact
+ `orelse`
+ just (sptok "?-" `seq` termlist) `do` (\(q,ts)->Query ts)
+ `orelse`
+ okay Error
+
+--- Main program read-solve-print loop:
+
+signOn :: String
+signOn = "Mini Prolog Version 1.5 (" ++ version ++ ")\n\n"
+
+main :: Dialogue
+main = --echo False abort
+ (appendChan stdout signOn abort
+ (appendChan stdout ("Reading " ++ stdlib ++ "...") abort
+ (readFile stdlib
+ (\fail -> appendChan stdout "not found\n" abort
+ (interpreter ""))
+ (\lib -> appendChan stdout "done\n" abort
+ (interpreter lib))
+ )))
+
+stdlib :: String
+stdlib = "$HASKELL/progs/demo/prolog/stdlib"
+
+interpreter :: String -> Dialogue
+interpreter lib = readChan stdin abort
+ (\inn -> appendChan stdout (loop startDb inn) abort done)
+ where startDb = foldl addClause emptyDb clauses
+ clauses = [r | ((r,""):_)<-map clause (lines lib)]
+
+loop :: Database -> String -> String
+loop db = readln "> " (exec db . fst . head . command)
+
+exec :: Database -> Command -> String -> String
+exec db (Fact r) = skip (loop (addClause db r))
+exec db (Query q) = demonstrate db q
+exec db Show = writeln (show db) (loop db)
+exec db Error = writeln "I don't understand\n" (loop db)
+exec db Quit = writeln "Thank you and goodbye\n" end
+exec db NoChange = skip (loop db)
+
+--- Handle printing of solutions etc...
+
+solution :: [Id] -> Subst -> [String]
+solution vs s = [ show (Var i) ++ " = " ++ show v
+ | (i,v) <- [ (i,s i) | i<-vs ], v /= Var i ]
+
+demonstrate :: Database -> [Term] -> Interactive
+demonstrate db q = printOut (map (solution vs) (prove db q))
+ where vs = (nub . concat . map varsIn) q
+ printOut [] = writeln "no.\n" (loop db)
+ printOut ([]:bs) = writeln "yes.\n" (loop db)
+ printOut (b:bs) = writeln (doLines b) (nextReqd bs)
+ doLines = foldr1 (\xs ys -> xs ++ "\n" ++ ys)
+ nextReqd bs = writeln " "
+ (readch (\c->if c==';'
+ then writeln ";\n" (printOut bs)
+ else writeln "\n" (loop db)) "")
+
+--- End of Main.hs
diff --git a/progs/demo/prolog/Main.hu b/progs/demo/prolog/Main.hu
new file mode 100644
index 0000000..a936ca6
--- /dev/null
+++ b/progs/demo/prolog/Main.hu
@@ -0,0 +1,6 @@
+Main.hs
+Parse.hu
+PrologData.hu
+Interact.hu
+Engine.hu
+Version.hu
diff --git a/progs/demo/prolog/Parse.hs b/progs/demo/prolog/Parse.hs
new file mode 100644
index 0000000..0487432
--- /dev/null
+++ b/progs/demo/prolog/Parse.hs
@@ -0,0 +1,116 @@
+--
+-- General parsing library, based on Richard Bird's parselib.orw for Orwell
+-- (with a number of extensions)
+-- Mark P. Jones November 1990
+--
+-- uses Haskell B. version 0.99.3
+--
+module Parse(Parser(..), fail, okay, tok, sat, orelse, seq, do,
+ sptok, just, listOf, many, sp, many1) where
+
+infixr 6 `seq`
+infixl 5 `do`
+infixr 4 `orelse`
+
+--- Type definition:
+
+type Parser a = [Char] -> [(a,[Char])]
+
+-- A parser is a function which maps an input stream of characters into
+-- a list of pairs each containing a parsed value and the remainder of the
+-- unused input stream. This approach allows us to use the list of
+-- successes technique to detect errors (i.e. empty list ==> syntax error).
+-- it also permits the use of ambiguous grammars in which there may be more
+-- than one valid parse of an input string.
+
+--- Primitive parsers:
+
+-- fail is a parser which always fails.
+-- okay v is a parser which always succeeds without consuming any characters
+-- from the input string, with parsed value v.
+-- tok w is a parser which succeeds if the input stream begins with the
+-- string (token) w, returning the matching string and the following
+-- input. If the input does not begin with w then the parser fails.
+-- sat p is a parser which succeeds with value c if c is the first input
+-- character and c satisfies the predicate p.
+
+fail :: Parser a
+fail inn = []
+
+okay :: a -> Parser a
+okay v inn = [(v,inn)]
+
+tok :: [Char] -> Parser [Char]
+tok w inn = [(w, drop n inn) | w == take n inn]
+ where n = length w
+
+sat :: (Char -> Bool) -> Parser Char
+sat p [] = []
+sat p (c:inn) = [ (c,inn) | p c ]
+
+--- Parser combinators:
+
+-- p1 `orelse` p2 is a parser which returns all possible parses of the input
+-- string, first using the parser p1, then using parser p2.
+-- p1 `seq` p2 is a parser which returns pairs of values (v1,v2) where
+-- v1 is the result of parsing the input string using p1 and
+-- v2 is the result of parsing the remaining input using p2.
+-- p `do` f is a parser which behaves like the parser p, but returns
+-- the value f v wherever p would have returned the value v.
+--
+-- just p is a parser which behaves like the parser p, but rejects any
+-- parses in which the remaining input string is not blank.
+-- sp p behaves like the parser p, but ignores leading spaces.
+-- sptok w behaves like the parser tok w, but ignores leading spaces.
+--
+-- many p returns a list of values, each parsed using the parser p.
+-- many1 p parses a non-empty list of values, each parsed using p.
+-- listOf p s parses a list of input values using the parser p, with
+-- separators parsed using the parser s.
+
+orelse :: Parser a -> Parser a -> Parser a
+p1 `orelse` p2 = \inn->p1 inn ++ p2 inn
+
+seq :: Parser a -> Parser b -> Parser (a,b)
+p1 `seq` p2 = \inn->[((v1,v2),inn2) | (v1,inn1) <- p1 inn, (v2,inn2) <- p2 inn1]
+
+do :: Parser a -> (a -> b) -> Parser b
+p `do` f = \inn->[(f v, inn1) | (v,inn1) <- p inn]
+
+just :: Parser a -> Parser a
+just p inn = [ (v,"") | (v,inn')<- p inn, dropWhile (' '==) inn' == "" ]
+
+sp :: Parser a -> Parser a
+sp p = p . dropWhile (' '==)
+
+sptok :: [Char] -> Parser [Char]
+sptok = sp . tok
+
+many :: Parser a -> Parser [a]
+many p = q
+ where q = ((p `seq` q) `do` makeList) `orelse` (okay [])
+
+many1 :: Parser a -> Parser [a]
+many1 p = p `seq` many p `do` makeList
+
+listOf :: Parser a -> Parser b -> Parser [a]
+listOf p s = p `seq` many (s `seq` p) `do` nonempty
+ `orelse` okay []
+ where nonempty (x,xs) = x:(map snd xs)
+
+--- Internals:
+
+makeList :: (a,[a]) -> [a]
+makeList (x,xs) = x:xs
+
+{-
+-- an attempt to optimise the performance of the standard prelude function
+-- `take' in Haskell B 0.99.3 gives the wrong semantics. The original
+-- definition, given below works correctly and is used in the above.
+
+safetake :: (Integral a) => a -> [b] -> [b]
+safetake _ [] = []
+safetake 0 _ = []
+safetake (n+1) (x:xs) = x : safetake n xs
+-}
+--- End of Parse.hs
diff --git a/progs/demo/prolog/Parse.hu b/progs/demo/prolog/Parse.hu
new file mode 100644
index 0000000..44cc302
--- /dev/null
+++ b/progs/demo/prolog/Parse.hu
@@ -0,0 +1 @@
+Parse.hs
diff --git a/progs/demo/prolog/PrologData.hs b/progs/demo/prolog/PrologData.hs
new file mode 100644
index 0000000..4ff3173
--- /dev/null
+++ b/progs/demo/prolog/PrologData.hs
@@ -0,0 +1,121 @@
+--
+-- Representation of Prolog Terms, Clauses and Databases
+-- Mark P. Jones November 1990
+--
+-- uses Haskell B. version 0.99.3
+--
+module PrologData(Id(..), Atom(..), Term(..), term, termlist, varsIn,
+ Clause((:*)), clause,
+ Database, emptyDb, renClauses, addClause) where
+
+import Parse
+
+infix 6 :*
+
+--- Prolog Terms:
+
+type Id = (Int,String)
+type Atom = String
+data Term = Var Id | Struct Atom [Term]
+ deriving Eq
+data Clause = Term :* [Term]
+data Database = Db [(Atom,[Clause])]
+
+--- Determine the list of variables in a term:
+
+varsIn :: Term -> [Id]
+varsIn (Var i) = [i]
+varsIn (Struct i ts) = (nub . concat . map varsIn) ts
+
+renameVars :: Int -> Term -> Term
+renameVars lev (Var (n,s)) = Var (lev,s)
+renameVars lev (Struct s ts) = Struct s (map (renameVars lev) ts)
+
+--- Functions for manipulating databases (as an abstract datatype)
+
+emptyDb :: Database
+emptyDb = Db []
+
+renClauses :: Database -> Int -> Term -> [Clause]
+renClauses db n (Var _) = []
+renClauses db n (Struct a _) = [ r tm:*map r tp | (tm:*tp)<-clausesFor a db ]
+ where r = renameVars n
+
+clausesFor :: Atom -> Database -> [Clause]
+clausesFor a (Db rss) = case dropWhile (\(n,rs) -> n<a) rss of
+ [] -> []
+ ((n,rs):_) -> if a==n then rs else []
+
+addClause :: Database -> Clause -> Database
+addClause (Db rss) r@(Struct a _ :* _)
+ = Db (initialPart ++
+ case lastPart of
+ [] -> [(a,[r])]
+ ((n,rs):rss') -> if a==n then (n,rs++[r]):rss'
+ else (a,[r]):lastPart)
+ where (initialPart,lastPart) = span (\(n,rs) -> n<a) rss
+
+--- Output functions (defined as instances of Text):
+
+instance Text Term where
+ showsPrec p (Var (n,s))
+ | n==0 = showString s
+ | otherwise = showString s . showChar '_' . shows n
+ showsPrec p (Struct a []) = showString a
+ showsPrec p (Struct a ts) = showString a . showChar '('
+ . showWithSep "," ts
+ . showChar ')'
+
+instance Text Clause where
+ showsPrec p (t:*[]) = shows t . showChar '.'
+ showsPrec p (t:*gs) = shows t . showString ":-"
+ . showWithSep "," gs
+ . showChar '.'
+
+instance Text Database where
+ showsPrec p (Db []) = showString "-- Empty Database --\n"
+ showsPrec p (Db rss) = foldr1 (\u v-> u . showChar '\n' . v)
+ [ showWithTerm "\n" rs | (i,rs)<-rss ]
+
+--- Local functions for use in defining instances of Text:
+
+showWithSep :: Text a => String -> [a] -> ShowS
+showWithSep s [x] = shows x
+showWithSep s (x:xs) = shows x . showString s . showWithSep s xs
+
+showWithTerm :: Text a => String -> [a] -> ShowS
+showWithTerm s xs = foldr1 (.) [shows x . showString s | x<-xs]
+
+--- String parsing functions for Terms and Clauses:
+--- Local definitions:
+
+letter :: Parser Char
+letter = sat (\c -> isAlpha c || isDigit c || c `elem` ":;+=-*&%$#@?/.~!")
+
+variable :: Parser Term
+variable = sat isUpper `seq` many letter `do` makeVar
+ where makeVar (initial,rest) = Var (0,(initial:rest))
+
+struct :: Parser Term
+struct = many letter `seq` (sptok "(" `seq` termlist `seq` sptok ")"
+ `do` (\(o,(ts,c))->ts)
+ `orelse`
+ okay [])
+ `do` (\(name,terms)->Struct name terms)
+
+--- Exports:
+
+term :: Parser Term
+term = sp (variable `orelse` struct)
+
+termlist :: Parser [Term]
+termlist = listOf term (sptok ",")
+
+clause :: Parser Clause
+clause = sp struct `seq` (sptok ":-" `seq` listOf term (sptok ",")
+ `do` (\(from,body)->body)
+ `orelse` okay [])
+ `seq` sptok "."
+ `do` (\(head,(goals,dot))->head:*goals)
+
+--- End of PrologData.hs
diff --git a/progs/demo/prolog/PrologData.hu b/progs/demo/prolog/PrologData.hu
new file mode 100644
index 0000000..362d35f
--- /dev/null
+++ b/progs/demo/prolog/PrologData.hu
@@ -0,0 +1,2 @@
+PrologData.hs
+Parse.hu
diff --git a/progs/demo/prolog/README b/progs/demo/prolog/README
new file mode 100644
index 0000000..73dbc1b
--- /dev/null
+++ b/progs/demo/prolog/README
@@ -0,0 +1,3 @@
+This is a mini prolog interpreter written my Mark Jones. It
+was slightly adapted from version in the hbc release.
+
diff --git a/progs/demo/prolog/Subst.hs b/progs/demo/prolog/Subst.hs
new file mode 100644
index 0000000..f96e462
--- /dev/null
+++ b/progs/demo/prolog/Subst.hs
@@ -0,0 +1,65 @@
+--
+-- Substitutions and Unification of Prolog Terms
+-- Mark P. Jones November 1990
+--
+-- uses Haskell B. version 0.99.3
+--
+module Subst(Subst(..), nullSubst, (>!), (@@), apply, unify) where
+
+import PrologData
+
+infixr 3 @@
+infix 4 >!
+
+--- Substitutions:
+
+type Subst = Id -> Term
+
+-- substitutions are represented by functions mapping identifiers to terms.
+--
+-- apply s extends the substitution s to a function mapping terms to terms
+-- nullSubst is the empty substitution which maps every identifier to the
+-- same identifier (as a term).
+-- i >! t is the substitution which maps the identifier i to the term t,
+-- but otherwise behaves like nullSubst.
+-- s1 @@ s2 is the composition of substitutions s1 and s2
+-- N.B. apply is a monoid homomorphism from (Subst,nullSubst,(@@))
+-- to (Term -> Term, id, (.)) in the sense that:
+-- apply (s1 @@ s2) = apply s1 . apply s2
+-- s @@ nullSubst = s = nullSubst @@ s
+
+apply :: Subst -> Term -> Term
+apply s (Var i) = s i
+apply s (Struct a ts) = Struct a (map (apply s) ts)
+
+nullSubst :: Subst
+nullSubst i = Var i
+
+(>!) :: Id -> Term -> Subst
+(>!) i t j | j==i = t
+ | otherwise = Var j
+
+(@@) :: Subst -> Subst -> Subst
+s1 @@ s2 = apply s1 . s2
+
+--- Unification:
+
+-- unify t1 t2 returns a list containing a single substitution s which is
+-- the most general unifier of terms t1 t2. If no unifier
+-- exists, the list returned is empty.
+
+unify :: Term -> Term -> [Subst]
+unify (Var x) (Var y) = if x==y then [nullSubst] else [x>!Var y]
+unify (Var x) t2 = [ x >! t2 | not (x `elem` varsIn t2) ]
+unify t1 (Var y) = [ y >! t1 | not (y `elem` varsIn t1) ]
+unify (Struct a ts) (Struct b ss) = [ u | a==b, u<-listUnify ts ss ]
+
+listUnify :: [Term] -> [Term] -> [Subst]
+listUnify [] [] = [nullSubst]
+listUnify [] (r:rs) = []
+listUnify (t:ts) [] = []
+listUnify (t:ts) (r:rs) = [ u2 @@ u1 | u1<-unify t r,
+ u2<-listUnify (map (apply u1) ts)
+ (map (apply u1) rs) ]
+
+--- End of Subst.hs
diff --git a/progs/demo/prolog/Subst.hu b/progs/demo/prolog/Subst.hu
new file mode 100644
index 0000000..1bb92fb
--- /dev/null
+++ b/progs/demo/prolog/Subst.hu
@@ -0,0 +1,2 @@
+Subst.hs
+PrologData.hu
diff --git a/progs/demo/prolog/Version.hs b/progs/demo/prolog/Version.hs
new file mode 100644
index 0000000..c580f4b
--- /dev/null
+++ b/progs/demo/prolog/Version.hs
@@ -0,0 +1 @@
+module Version where version="tree based"
diff --git a/progs/demo/prolog/Version.hu b/progs/demo/prolog/Version.hu
new file mode 100644
index 0000000..244a511
--- /dev/null
+++ b/progs/demo/prolog/Version.hu
@@ -0,0 +1 @@
+Version.hs
diff --git a/progs/demo/prolog/stdlib b/progs/demo/prolog/stdlib
new file mode 100644
index 0000000..76d2b8c
--- /dev/null
+++ b/progs/demo/prolog/stdlib
@@ -0,0 +1,38 @@
+This file contains a list of predicate definitions that will automatically
+be read into Mini Prolog at the beginning of a session. Each clause in this
+file must be entered on a single line and lines containing syntax errors are
+always ignored. This includes the first few lines of this file and provides
+a simple way to include comments.
+
+append(nil,X,X).
+append(cons(X,Y),Z,cons(X,W)):-append(Y,Z,W).
+
+equals(X,X).
+
+not(X):-X,!,false.
+not(X).
+
+or(X,Y):-X.
+or(X,Y):-Y.
+
+and(X,Y):-X,Y.
+
+reverse(nil,nil).
+reverse(cons(A,X),Y):-and(reverse(X,Z),append(Z,cons(A,nil),Y)).
+
+palindromes(X):-and(reverse(X,Y),equals(X,Y)).
+
+mul2(A,B):-append(A,A,B).
+mul4(A,B):-and(mul2(A,C),mul2(C,B)).
+mul8(A,B):-and(mul4(A,C),mul2(C,B)).
+mul16(A,B):-and(mul8(A,C),mul2(C,B)).
+mul32(A,B):-and(mul16(A,C),mul2(C,B)).
+mul64(A,B):-and(mul32(A,C),mul2(C,B)).
+mul128(A,B):-and(mul64(A,C),mul2(C,B)).
+mul256(A,B):-and(mul128(A,C),mul2(C,B)).
+mul512(A,B):-and(mul256(A,C),mul2(C,B)).
+mul1024(A,B):-and(mul512(A,C),mul2(C,B)).
+
+true.
+
+End of stdlib
diff --git a/progs/demo/queens.hs b/progs/demo/queens.hs
new file mode 100755
index 0000000..0f8de59
--- /dev/null
+++ b/progs/demo/queens.hs
@@ -0,0 +1,40 @@
+{- This is the n Queens problem. -}
+
+module Main where
+
+queens :: Int -> [[Int]]
+queens size = queens' size size
+
+queens' :: Int -> Int -> [[Int]]
+queens' 0 _ = [[]]
+queens' (n+1) size = [q:qs | qs <- queens' n size, q <- [1..size],
+ not (threatens q qs)]
+
+threatens :: Int -> [Int] -> Bool
+threatens q qs = q `elem` qs || q `elem` (diagonals 1 qs)
+
+diagonals :: Int -> [Int] -> [Int]
+diagonals _ [] = []
+diagonals n (q:qs) = (q+n) : (q-n) : diagonals (n+1) qs
+
+main = appendChan stdout "Enter board size: " abort $
+ readChan stdin abort $ \input ->
+ let line1 : ~(line2 : _) = lines input
+ size = read line1
+ solns = read line2
+ in if size == 0 then done else -- This causes the size to actually read
+ appendChan stdout "Number of solutions: " abort $
+ appendChan stdout (concat (map (\x -> showBoard size x)
+ (take solns (queens size))))
+ abort done
+
+showBoard :: Int -> [Int] -> String
+
+showBoard size pos =
+ concat (map showRow pos) ++ "\n"
+ where
+ showRow n = concat [if i == n then "Q " else ". " | i <- [1..size]]
+ ++ "\n"
+
+
+
diff --git a/progs/demo/quicksort.hs b/progs/demo/quicksort.hs
new file mode 100644
index 0000000..30b4ab4
--- /dev/null
+++ b/progs/demo/quicksort.hs
@@ -0,0 +1,13 @@
+-- Quick sort for Haskell.
+
+module Main where
+
+qs :: [Int] -> [Int]
+qs [] = []
+qs (a:as) = qs [x | x <- as, x <= a] ++ [a] ++ qs [x | x <- as, x > a]
+
+main =
+ appendChan stdout "Enter a list of integers separated by \",\"\n" abort $
+ readChan stdin abort $ \ input ->
+ appendChan stdout (show (qs (read ("[" ++ (head (lines input)) ++ "]"))))
+ abort done
diff --git a/progs/lib/README b/progs/lib/README
new file mode 100644
index 0000000..910be2d
--- /dev/null
+++ b/progs/lib/README
@@ -0,0 +1 @@
+This directory contains supported libraries for Yale Haskell.
diff --git a/progs/lib/X11/README b/progs/lib/X11/README
new file mode 100644
index 0000000..db748e4
--- /dev/null
+++ b/progs/lib/X11/README
@@ -0,0 +1,11 @@
+This directory contains the Haskell->CLX support code.
+
+If you see errors like "ID 42 is a :WM_RESIZE_HINTS, not a window",
+you can get rid of them by loading clx-patch.lisp. This seems to be a
+bug where CLX is not consistent with the protocol in some way; we've
+seen it on some machines and not others. The line
+
+(load "$HASKELL/progs/lib/X11/clx-patch.lisp")
+
+can be placed in your .yhaskell file to load the patch on startup.
+
diff --git a/progs/lib/X11/clx-patch.lisp b/progs/lib/X11/clx-patch.lisp
new file mode 100644
index 0000000..fe2a5e3
--- /dev/null
+++ b/progs/lib/X11/clx-patch.lisp
@@ -0,0 +1,39 @@
+(lisp:in-package 'xlib)
+(defmacro generate-lookup-functions (useless-name &body types)
+ `(within-definition (,useless-name generate-lookup-functions)
+ ,@(mapcar
+ #'(lambda (type)
+ `(defun ,(xintern 'lookup- type)
+ (display id)
+ (declare (type display display)
+ (type resource-id id))
+ (declare (values ,type))
+ ,(if (member type *clx-cached-types*)
+ `(let ((,type (lookup-resource-id display id)))
+ (cond ((null ,type) ;; Not found, create and s
+ave it.
+ (setq ,type (,(xintern 'make- type)
+ :display display :id id))
+ (save-id display id ,type))
+ ;; Found. Check the type
+ ,(cond ((null '()) ;*type-check?*)
+ `(t ,type))
+ ((member type '(window pixmap))
+ `((type? ,type 'drawable) ,type)
+)
+ (t `((type? ,type ',type) ,type))
+)
+ ,@(when '() ;*type-check?*
+ `((t (x-error 'lookup-error
+ :id id
+ :display display
+ :type ',type
+ :object ,type))))))
+ ;; Not being cached. Create a new one each time.
+ `(,(xintern 'make- type)
+ :display display :id id))))
+ types)))
+(macroexpand
+ (generate-lookup-functions ignore
+ window))
+
diff --git a/progs/lib/X11/xlib.hs b/progs/lib/X11/xlib.hs
new file mode 100644
index 0000000..716cc8c
--- /dev/null
+++ b/progs/lib/X11/xlib.hs
@@ -0,0 +1,877 @@
+module Xlib(XLibTypes..,XLibPrims..) where
+import XLibTypes
+import XLibPrims
+
+module XLibTypes(XDisplay, XScreen, XWindow, XGcontext, XPixmap,
+ XColormap, XCursor, XFont, XImage, XMaybe(..), XError(..),
+ XBitmap(..), XKeysymTable(..), XBitVec(..),
+ XPixarray(..), XByteVec(..), XAtom(..), XProperty(..),
+ XPixel(..), XDrawable(..), XTime(..), XSwitch(..),
+ XWindowPlace(..), XEventMode(..), XEventKind(..),
+ XWindowVisibility(..), XWindowStackMode(..),
+ XPropertyState(..), XMapReqType(..), XGraphFun(..),
+ XEvent(..), XEventType(..), XEventSlot(..), XEventMask(..),
+ XEventMaskKey(..), XStateMask(..), XStateMaskKey(..),
+ XWinAttribute(..),XGCAttribute(..), XImAttribute(..),
+ XGrabAttribute(..), XArcMode(..), XCapStyle(..),
+ XClipMask(..), XFillRule(..), XFillStyle(..),
+ XFunction(..), XJoinStyle(..), XLineStyle(..),
+ XSubwindowMode(..), XPoint(..), XSize(..), XRect(..),
+ XArc(..), XBitmapFormat(..), XByteOrder(..),
+ XPixmapFormat(..), XVisualInfo(..), XVisualClass(..),
+ XFillContent(..), XBackingStore(..), XGravity(..),
+ XWindowClass(..), XMapState(..), XImageData(..),
+ XImageFormat(..), XImageType(..), XDrawDirection(..),
+ XColor(..), XInputFocus(..), XGrabStatus(..),
+ XKeysym(..), XCloseDownMode(..), XScreenSaver(..))
+ where
+
+data XMaybe a {-# STRICT #-} = XSome a
+ | XNull
+ --deriving (Printers)
+
+data XDisplay = XDisplay --deriving (Printers)
+data XScreen = XScreen --deriving (Printers)
+data XWindow = XWindow --deriving (Printers)
+data XGcontext = XGcontext --deriving (Printers)
+data XPixmap = XPixmap --deriving (Printers)
+data XColormap = XColormap --deriving (Printers)
+data XCursor = XCursor --deriving (Printers)
+data XFont = XFont --deriving (Printers)
+data XImage = XImage --deriving (Printers)
+
+data XError {-# STRICT #-}
+ = XError String
+ --deriving Printers
+data XBitmap {-# STRICT #-}
+ = XBitmap [[Int]]
+instance Text(XBitmap) where
+ showsPrec p x = showString "<<XBitMap>>"
+
+data XKeysymTable {-# STRICT #-}
+ = XKeysymTable [[Integer]]
+instance Text(XKeysymTable) where
+ showsPrec p x = showString "<<XKeysymTable>>"
+
+data XBitVec {-# STRICT #-}
+ = XBitVec [Int]
+instance Text(XBitVec) where
+ showsPrec p x = showString "<<XBitVec>>"
+
+data XPixarray {-# STRICT #-}
+ = XPixarray [[Integer]]
+instance Text(XPixarray) where
+ showsPrec p x = showString "<<XPixarray>>"
+
+data XByteVec {-# STRICT #-}
+ = XByteVec [Int]
+instance Text(XByteVec) where
+ showsPrec p x = showString "<<XByteVec>>"
+
+
+data XAtom {-# STRICT #-}
+ = XAtom String
+ --deriving (Printers)
+
+data XProperty {-#STRICT #-}
+ = XProperty [Integer] -- data
+ XAtom -- type
+ Int -- format
+ --deriving (Printers)
+
+data XPixel {-# STRICT #-}
+ = XPixel Integer
+ --deriving (Printers)
+
+data XDrawable {-# STRICT #-}
+ = XDrawWindow XWindow
+ | XDrawPixmap XPixmap
+ --deriving (Printers)
+
+data XTime {-# STRICT #-}
+ = XTime Integer
+ --deriving (Printers)
+
+data XSwitch = XOn
+ | XOff
+ --deriving (Printers)
+
+data XWindowPlace = XTopPlace
+ | XBottomPlace
+ --deriving (Printers)
+
+data XEventMode = XNormalMode
+ | XGrabMode
+ | XUngrabMode
+ | XWhileGrabbedMode
+ --deriving (Printers)
+
+data XEventKind = XAncestorKind
+ | XVirtualKind
+ | XInferiorKind
+ | XNonlinearKind
+ | XNonlinearVirtualKind
+ | XPointerKind
+ | XPointerRootKind
+ | XNoneKind
+ --deriving (Printers)
+
+data XWindowVisibility = XUnobscured
+ | XPartiallyObscured
+ | XFullyObscured
+ --deriving (Printers)
+
+data XWindowStackMode = XStackAbove
+ | XStackBelow
+ | XStackTopIf
+ | XStackBottomIf
+ | XStackOpposite
+ --deriving (Printers)
+
+data XPropertyState = XNewValueProperty
+ | XDeletedProperty
+ --deriving (Printers)
+
+data XMapReqType = XModifierMapping
+ | XKeyboardMapping
+ | XPointerMapping
+ --deriving (Printers)
+
+data XGraphFun {-# STRICT #-}
+ = XGraphFun Int -- major opcode
+ Int -- minor opcode
+ --deriving (Printers)
+
+data XEvent {-# STRICT #-}
+ = XEvent XEventType
+ [XEventSlot]
+
+data XEventType = XKeyPressEvent
+ | XKeyReleaseEvent
+ | XButtonPressEvent
+ | XButtonReleaseEvent
+ | XMotionNotifyEvent
+ | XEnterNotifyEvent
+ | XLeaveNotifyEvent
+ | XFocusInEvent
+ | XFocusOutEvent
+ | XKeymapNotifyEvent
+ | XMappingNotifyEvent
+ | XExposureEvent
+ | XGraphicsExposureEvent
+ | XNoExposureEvent
+ | XCirculateNotifyEvent
+ | XConfigureNotifyEvent
+ | XCreateNotifyEvent
+ | XDestroyNotifyEvent
+ | XGravityNotifyEvent
+ | XMapNotifyEvent
+ | XReparentNotifyEvent
+ | XUnmapNotifyEvent
+ | XVisibilityNotifyEvent
+ | XCirculateRequestEvent
+ | XColormapNotifyEvent
+ | XConfigureRequestEvent
+ | XMapRequestEvent
+ | XResizeRequestEvent
+ | XClientMessageEvent
+ | XPropertyNotifyEvent
+ | XSelectionClearEvent
+ | XSelectionNotifyEvent
+ | XSelectionRequestEvent
+ | XOtherEvents
+ --deriving Printers
+
+data XEventSlot {-# STRICT #-}
+ = XEventWindow XWindow
+ | XEventEventWindow XWindow
+ | XEventCode Int
+ | XEventPos XPoint
+ | XEventState XStateMask
+ | XEventTime XTime
+ | XEventRoot XWindow
+ | XEventRootPos XPoint
+ | XEventChild (XMaybe XWindow)
+ | XEventSameScreenP Bool
+ | XEventHintP Bool
+ | XEventMode XEventMode
+ | XEventKind XEventKind
+ | XEventFocusP Bool
+ | XEventKeymap XBitVec
+ | XEventRequest XMapReqType
+ | XEventStart Int
+ | XEventCount Int
+ | XEventRect XRect
+ | XEventDrawable XDrawable
+ | XEventXGraphFun XGraphFun
+ | XEventPlace XWindowPlace
+ | XEventBorderWidth Int
+ | XEventAboveSibling (XMaybe XWindow)
+ | XEventOverrideRedirectP Bool
+ | XEventParent XWindow
+ | XEventConfigureP Bool
+ | XEventVisibility XWindowVisibility
+ | XEventNewP Bool
+ | XEventInstalledP Bool
+ | XEventStackMode XWindowStackMode
+ | XEventValueMask Int
+ | XEventSize XSize
+ | XEventMessage XProperty
+ | XEventPropertyState XPropertyState
+ | XEventAtom XAtom
+ | XEventSelection XAtom
+ | XEventTarget XAtom
+ | XEventProperty (XMaybe XAtom)
+ | XEventRequestor XWindow
+ --deriving Printers
+
+data XEventMask {-# STRICT #-}
+ = XEventMask [XEventMaskKey]
+ --deriving (Printers)
+
+data XEventMaskKey
+ = XButton1Motion
+ | XButton2Motion
+ | XButton3Motion
+ | XButton4Motion
+ | XButton5Motion
+ | XButtonMotion
+ | XButtonPress
+ | XButtonRelease
+ | XColormapChange
+ | XEnterWindow
+ | XExposure
+ | XFocusChange
+ | XKeyPress
+ | XKeyRelease
+ | XKeymapState
+ | XLeaveWindow
+ | XOwnerGrabButton
+ | XPointerMotion
+ | XPointerMotionHint
+ | XPropertyChange
+ | XResizeRedirect
+ | XStructureNotify
+ | XSubstructureRedirect
+ | XVisibilityChange
+ --deriving (Printers)
+
+data XStateMask {-# STRICT #-}
+ = XStateMask [XStateMaskKey]
+ --deriving (Printers)
+
+data XStateMaskKey
+ = XShift
+ | XLock
+ | XControl
+ | XMod1
+ | XMod2
+ | XMod3
+ | XMod4
+ | XMod5
+ | XButton1
+ | XButton2
+ | XButton3
+ | XButton4
+ | XButton5
+ --deriving (Printers)
+
+data XWinAttribute {-# STRICT #-}
+ = XWinBackground XPixel
+ | XWinEventMask XEventMask
+ | XWinDepth Int
+ | XWinBorderWidth Int
+ | XWinClass XWindowClass
+ | XWinVisual Int
+ | XWinBorder XFillContent
+ | XWinBackingStore XBackingStore
+ | XWinBackingPlanes XPixel
+ | XWinBackingPixel XPixel
+ | XWinSaveUnder XSwitch
+ | XWinDoNotPropagateMask XEventMask
+ | XWinOverrideRedirect XSwitch
+ | XWinColormap XColormap
+ | XWinCursor XCursor
+ --deriving (Printers)
+
+data XGCAttribute {-# STRICT #-}
+ = XGCArcMode XArcMode
+ | XGCBackground XPixel
+ | XGCCapStyle XCapStyle
+ | XGCClipMask XClipMask
+ | XGCClipOrigin XPoint
+ | XGCDashOffset Int
+ | XGCDashes [Int]
+ | XGCExposures XSwitch
+ | XGCFillRule XFillRule
+ | XGCFillStyle XFillStyle
+ | XGCFont XFont
+ | XGCForeground XPixel
+ | XGCFunction XFunction
+ | XGCJoinStyle XJoinStyle
+ | XGCLineStyle XLineStyle
+ | XGCLineWidth Int
+ | XGCPlaneMask XPixel
+ | XGCStipple XPixmap
+ | XGCSubwindowMode XSubwindowMode
+ | XGCTile XPixmap
+ | XGCTileOrigin XPoint
+ --deriving (Printers)
+
+data XImAttribute {-# STRICT #-}
+ = XImBitLsbFirstP Bool
+ | XImBitsPerPixel Int
+ | XImBlueMask XPixel
+ | XImByteLsbFirstP Bool
+ | XImBytesPerLine Int
+ | XImData XImageData
+ | XImDepth Int
+ | XImFormat XImageFormat
+ | XImGreenMask XPixel
+ | XImSize XSize
+ | XImName String
+ | XImRedMask XPixel
+ | XImHotSpot XPoint
+ --deriving (Printers)
+
+data XGrabAttribute {-# STRICT #-}
+ = XGrabOwnerP Bool
+ | XGrabSyncPointerP Bool
+ | XGrabSyncKeyboardP Bool
+ | XGrabConfineTo XWindow
+ | XGrabCursor XCursor
+ --deriving (Printers)
+
+data XArcMode = XChord
+ | XPieSlice
+ --deriving (Printers)
+
+data XCapStyle = XButt
+ | XNotLast
+ | XProjecting
+ | XRound
+ --deriving (Printers)
+
+data XClipMask {-# STRICT #-}
+ = XClipMaskPixmap XPixmap
+ | XClipMaskRects [XRect]
+ | XClipMaskNone
+ --deriving (Printers)
+
+data XFillRule = XFillEvenOdd
+ | XFillWinding
+ --deriving (Printers)
+
+data XFillStyle = XFillOpaqueStippled
+ | XFillSolid
+ | XFillStippled
+ | XFillTiled
+ --deriving (Printers)
+
+data XFunction = XBoole1
+ | XBoole2
+ | XBooleAndC1
+ | XBooleAndC2
+ | XBooleAnd
+ | XBooleC1
+ | XBooleC2
+ | XBooleClr
+ | XBooleEqv
+ | XBooleIor
+ | XBooleNand
+ | XBooleNor
+ | XBooleOrc1
+ | XBooleOrc2
+ | XBooleSet
+ | XBooleXor
+ --deriving (Printers)
+
+data XJoinStyle = XJoinBevel
+ | XJoinMiter
+ | XJoinRound
+ --deriving (Printers)
+
+data XLineStyle = XLineSolid
+ | XLineDoubleDash
+ | XLineOnOffDash
+ --deriving (Printers)
+
+data XSubwindowMode = XClipByChildren
+ | XIncludeInferiors
+ --deriving (Printers)
+
+-- BASIC GEOMETRY
+
+data XPoint {-# STRICT #-} = XPoint Int Int -- x,y
+ --deriving (Printers)
+
+data XSize {-# STRICT #-} = XSize Int Int -- width, height
+ --deriving (Printers)
+
+data XRect {-# STRICT #-} = XRect Int Int Int Int -- x, y, width, height
+ --deriving (Printers)
+
+data XArc {-# STRICT #-} = XArc Int Int Int Int Float Float
+ --deriving (Printers) -- x, y, width, height, angle1, angle2
+
+data XBitmapFormat {-# STRICT #-} = XBitmapFormat Int Int Bool
+ --deriving (Printers) -- unit, pad, lsb-first-p
+
+data XByteOrder = XLsbFirst
+ | XMsbFirst
+ --deriving (Printers)
+
+data XPixmapFormat {-# STRICT #-} = XPixmapFormat Int Int Int
+ --deriving (Printers) -- depth, bits-per-pixel, scanline-pad
+
+data XVisualInfo {-# STRICT #-} = XVisualInfo
+ Int -- id
+ XVisualClass -- class
+ XPixel -- red-mask
+ XPixel -- green-mask
+ XPixel -- blue-mask
+ Int -- bits-per-rgb
+ Int -- colormap-entries
+ --deriving (Printers)
+
+data XVisualClass = XDirectColor
+ | XGrayScale
+ | XPseudoColor
+ | XStaticColor
+ | XStaticGray
+ | XTrueColor
+ --deriving (Printers)
+
+data XFillContent {-# STRICT #-}
+ = XFillPixel XPixel
+ | XFillPixmap XPixmap
+ | XFillNone
+ | XFillParentRelative
+ | XFillCopy
+ --deriving (Printers)
+
+data XBackingStore = XAlwaysBackStore
+ | XNeverBackStore
+ | XBackStoreWhenMapped
+ | XBackStoreNotUseful
+ --deriving (Printers)
+
+data XGravity = XForget
+ | XStatic
+ | XCenter
+ | XEast
+ | XNorth
+ | XNorthEast
+ | XNorthWest
+ | XSouth
+ | XSouthEast
+ | XSouthWest
+ | XWest
+ --deriving (Printers)
+
+data XWindowClass = XInputOutput
+ | XInputOnly
+ --deriving (Printers)
+
+data XMapState = XUnmapped
+ | XUnviewable
+ | XViewable
+ --deriving (Printers)
+
+data XImageData {-# STRICT #-}
+ = XBitmapData [XBitmap]
+ | XPixarrayData XPixarray
+ | XByteVecData XByteVec
+ --deriving (Printers)
+
+data XImageFormat = XXyPixmapImage
+ | XZPixmapImage
+ | XBitmapImage
+ --deriving (Printers)
+
+data XImageType = XImageX
+ | XImageXy
+ | XImageZ
+ --deriving (Printers)
+
+data XDrawDirection = XLeftToRight
+ | XRightToLeft
+ --deriving (Printers)
+
+data XColor {-# STRICT #-} = XColor Float Float Float
+ --deriving (Printers)
+
+data XInputFocus {-# STRICT #-}
+ = XFocusWindow XWindow
+ | XFocusNone
+ | XFocusPointerRoot
+ | XFocusParent
+ --deriving (Printers)
+
+data XGrabStatus = XAlreadyGrabbed
+ | XFrozen
+ | XInvalidTime
+ | XNotViewable
+ | XSuccess
+ --deriving (Printers)
+
+
+data XKeysym {-# STRICT #-} = XKeysym Integer
+ --deriving (Printers)
+
+
+data XCloseDownMode = XDestroy
+ | XRetainPermanent
+ | XRetainTemporary
+ --deriving (Printers)
+
+data XScreenSaver {-# STRICT #-} = XScreenSaver Int Int Bool Bool
+ --deriving (Printers)
+
+{-#
+ImportLispType (
+ XMaybe (XSome ("not-null?", "identity", "identity"),
+ XNull ("null?", "'()")),
+ XError (XError ("cons-xerror", "x-error-string")),
+ XBitmap (XBitmap ("mk-bitmap", "sel-bitmap")),
+ XKeysymTable (XKeysymTable ("mk-keysym-table", "sel-keysym-table")),
+ XBitVec (XBitVec ("mk-bitvec", "sel-bitvec")),
+ XPixarray (XPixarray ("mk-pixarray", "sel-pixarray")),
+ XByteVec (XByteVec ("mk-bytevec", "sel-bytevec")),
+ XAtom (XAtom ("mk-atom", "sel-atom")),
+ XProperty (XProperty ("mk-xproperty", "sel-xproperty-data",
+ "sel-xproperty-type", "sel-xproperty-format")),
+ XDrawable (XDrawWindow ("xlib:window-p", "identity", "identity"),
+ XDrawPixmap ("xlib:pixmap-p", "identity", "identity")),
+ XSwitch ( XOn(":on"), XOff(":off")),
+ XWindowPlace (XTopPlace (":top"), XBottomPlace (":bottom")),
+ XEventMode (XNormalMode (":normal"),
+ XGrabMode (":grab"),
+ XUngrabMode (":ungrab"),
+ XWhileGrabbedMode (":while-grabbed")),
+ XEventKind (XAncestorKind (":ancestor"),
+ XVirtualKind (":virtual"),
+ XInferiorKind (":inferior"),
+ XNonlinearKind (":nonlinear"),
+ XNonlinearVirtualKind (":nonlinear-virtual"),
+ XPointerKind (":pointer"),
+ XPointerRootKind (":pointer-root"),
+ XNoneKind (":none")),
+ XWindowVisibility (XUnobscured (":unobscured"),
+ XPartiallyObscured (":partially-obscured"),
+ XFullyObscured (":fully-obscured")),
+ XWindowStackMode (XStackAbove (":above"),
+ XStackBelow (":below"),
+ XStackTopIf (":top-if"),
+ XStackBottomIf (":bottom-if"),
+ XStackOpposite (":opposite")),
+ XPropertyState (XNewValueProperty (":new-value"),
+ XDeletedProperty (":deleted")),
+ XMapReqType (XModifierMapping (":modifier"),
+ XKeyboardMapping (":keyboard"),
+ XPointerMapping (":pointer")),
+ XGraphFun (XGraphFun ("cons", "car", "cdr")),
+ XEvent (XEvent ("mk-event", "sel-event-type", "sel-event-slots")),
+ XEventType (XKeyPressEvent (":key-press"),
+ XKeyReleaseEvent (":key-release"),
+ XButtonPressEvent (":button-press"),
+ XButtonReleaseEvent (":button-release"),
+ XMotionNotifyEvent (":motion-notify"),
+ XEnterNotifyEvent (":enter-notify"),
+ XLeaveNotifyEvent (":leave-notify"),
+ XFocusInEvent (":focus-in"),
+ XFocusOutEvent (":focus-out"),
+ XKeymapNotifyEvent (":keymap-notify"),
+ XMappingNotifyEvent (":mapping-notify"),
+ XExposureEvent (":exposure"),
+ XGraphicsExposureEvent (":graphics-exposure"),
+ XNoExposureEvent (":no-exposure"),
+ XCirculateNotifyEvent (":circulate-notify"),
+ XConfigureNotifyEvent (":configure-notify"),
+ XCreateNotifyEvent (":create-notify"),
+ XDestroyNotifyEvent (":destroy-notify"),
+ XGravityNotifyEvent (":gravity-notify"),
+ XMapNotifyEvent (":map-notify"),
+ XReparentNotifyEvent (":reparent-notify"),
+ XUnmapNotifyEvent (":unmap-notify"),
+ XVisibilityNotifyEvent (":visibility-notify"),
+ XCirculateRequestEvent (":circulate-notify"),
+ XColormapNotifyEvent (":colormap-notify"),
+ XConfigureRequestEvent (":configure-request"),
+ XMapRequestEvent (":map-request"),
+ XResizeRequestEvent (":resize-request"),
+ XClientMessageEvent (":client-message"),
+ XPropertyNotifyEvent (":property-notify"),
+ XSelectionClearEvent (":selection-clear"),
+ XSelectionNotifyEvent (":selection-notify"),
+ XSelectionRequestEvent (":selection-request"),
+ XOtherEvents (":others")),
+ XEventSlot (XEventWindow ("is-window", "mk-window", "keyword-val"),
+ XEventEventWindow
+ ("is-event-window", "mk-event-window", "keyword-val"),
+ XEventCode ("is-code", "mk-code", "keyword-val"),
+ XEventPos ("is-pos", "mk-pos", "keyword-val"),
+ XEventState ("is-state", "mk-state", "keyword-val"),
+ XEventTime ("is-time", "mk-time", "keyword-val"),
+ XEventRoot ("is-root", "mk-root", "keyword-val"),
+ XEventRootPos ("is-root-pos", "mk-root-pos", "keyword-val"),
+ XEventChild ("is-child", "mk-child", "keyword-val"),
+ XEventSameScreenP
+ ("is-same-screen-p", "mk-same-screen-p", "keyword-val"),
+ XEventHintP ("is-hint-p", "mk-hint-p", "keyword-val"),
+ XEventMode ("is-mode", "mk-mode", "keyword-val"),
+ XEventKind ("is-kind", "mk-kind", "keyword-val"),
+ XEventFocusP ("is-focus-p", "mk-focus-p", "keyword-val"),
+ XEventKeymap ("is-keymap", "mk-keymap", "keyword-val"),
+ XEventRequest ("is-request", "mk-request", "keyword-val"),
+ XEventStart ("is-start", "mk-start", "keyword-val"),
+ XEventCount ("is-count", "mk-count", "keyword-val"),
+ XEventRect ("is-rect", "mk-rect", "keyword-val"),
+ XEventDrawable ("is-drawable", "mk-drawable", "keyword-val"),
+ XEventXGraphFun ("is-graph-fun", "mk-graph-fun", "keyword-val"),
+ XEventPlace ("is-place", "mk-place", "keyword-val"),
+ XEventBorderWidth
+ ("is-border-width", "mk-border-width", "keyword-val"),
+ XEventAboveSibling
+ ("is-above-sibling", "mk-above-sibling", "keyword-val"),
+ XEventOverrideRedirectP
+ ("is-override-redirect-p", "mk-override-redirect-p", "keyword-val"),
+ XEventParent ("is-parent", "mk-parent", "keyword-val"),
+ XEventConfigureP ("is-configure-p", "mk-configure-p", "keyword-val"),
+ XEventVisibility ("is-visibility", "mk-visibility", "keyword-val"),
+ XEventNewP ("is-new-p", "mk-new-p", "keyword-val"),
+ XEventInstalledP ("is-installed-p", "mk-installed-p", "keyword-val"),
+ XEventStackMode ("is-stack-mode", "mk-stack-mode", "keyword-val"),
+ XEventValueMask ("is-value-mask", "mk-value-mask", "keyword-val"),
+ XEventSize ("is-size", "mk-size", "keyword-val"),
+ XEventMessage ("is-message", "mk-message", "keyword-val"),
+ XEventPropertyState
+ ("is-property-state", "mk-property-state", "keyword-val"),
+ XEventAtom ("is-atom", "mk-atom", "keyword-val"),
+ XEventSelection ("is-selection", "mk-selection", "keyword-val"),
+ XEventTarget ("is-target", "mk-target", "keyword-val"),
+ XEventProperty ("is-property", "mk-property", "keyword-val"),
+ XEventRequestor ("is-requestor", "mk-requestor", "keyword-val")),
+ XEventMask (XEventMask ("x-make-event-mask", "x-event-mask-key-list")),
+ XEventMaskKey (XButton1Motion (":button-1-motion"),
+ XButton2Motion (":button-2-motion"),
+ XButton3Motion (":button-3-motion"),
+ XButton4Motion (":button-4-motion"),
+ XButton5Motion (":button-5-motion"),
+ XButtonMotion (":button-motion"),
+ XButtonPress (":button-press"),
+ XButtonRelease (":button-release"),
+ XColormapChange (":colormap-change"),
+ XEnterWindow (":enter-window"),
+ XExposure (":exposure"),
+ XFocusChange (":focus-change"),
+ XKeyPress (":key-press"),
+ XKeyRelease (":key-release"),
+ XKeymapState (":keymap-state"),
+ XLeaveWindow (":leave-window"),
+ XOwnerGrabButton (":owner-grab-button"),
+ XPointerMotion (":pointer-motion"),
+ XPointerMotionHint (":pointer-motion-hint"),
+ XPropertyChange (":property-change"),
+ XResizeRedirect (":resize-redirect"),
+ XStructureNotify (":structure-notify"),
+ XSubstructureRedirect (":substructure-notify"),
+ XVisibilityChange (":visibility-change")),
+ XStateMask (XStateMask ("x-make-state-mask", "x-state-mask-key-list")),
+ XStateMaskKey (XShift (":shift"),
+ XLock (":lock"),
+ XControl (":control"),
+ XMod1 (":mod-1"),
+ XMod2 (":mod-2"),
+ XMod3 (":mod-3"),
+ XMod4 (":mod-4"),
+ XMod5 (":mod-5"),
+ XButton1 (":button-1"),
+ XButton2 (":button-2"),
+ XButton3 (":button-3"),
+ XButton4 (":button-4"),
+ XButton5 (":button-5")),
+ XWinAttribute
+ (XWinBackground ("is-background","mk-background","keyword-val"),
+ XWinEventMask ("is-event-mask","mk-event-mask","keyword-val"),
+ XWinDepth ("is-depth","mk-depth","keyword-val"),
+ XWinBorderWidth ("is-border-width","mk-border-width","keyword-val"),
+ XWinClass ("is-class","mk-class","keyword-val"),
+ XWinVisual ("is-visual","mk-visual","keyword-val"),
+ XWinBorder ("is-border","mk-border","keyword-val"),
+ XWinBackingStore ("is-backing-store","mk-backing-store","keyword-val"),
+ XWinBackingPlanes ("is-backing-planes","mk-backing-planes","keyword-val"),
+ XWinBackingPixel ("is-backing-pixel","mk-backing-pixel","keyword-val"),
+ XWinSaveUnder ("is-save-under","mk-save-under","keyword-val"),
+ XWinDoNotPropagateMask ("is-do-not-propagate-mask",
+ "mk-do-not-propagate-mask","keyword-val"),
+ XWinOverrideRedirect("is-override-redirect",
+ "mk-override-redirect","keyword-val"),
+ XWinColormap ("is-colormap","mk-colormap","keyword-val"),
+ XWinCursor ("is-cursor","mk-cursor","keyword-val")),
+ XGCAttribute(
+ XGCArcMode ("is-arc-mode","mk-arc-mode","keyword-val"),
+ XGCBackground ("is-background","mk-background","keyword-val"),
+ XGCCapStyle ("is-cap-style","mk-cap-style","keyword-val"),
+ XGCClipMask ("is-clip-mask","mk-clip-mask","keyword-val"),
+ XGCClipOrigin ("is-clip-origin","mk-clip-origin","keyword-val"),
+ XGCDashOffset ("is-dash-offset","mk-dash-offset","keyword-val"),
+ XGCDashes ("is-dashes","mk-dashes","keyword-val"),
+ XGCExposures ("is-exposures","mk-exposures","keyword-val"),
+ XGCFillRule ("is-fill-rule","mk-fill-rule","keyword-val"),
+ XGCFillStyle ("is-fill-style","mk-fill-style","keyword-val"),
+ XGCFont ("is-font","mk-font","keyword-val"),
+ XGCForeground ("is-foreground","mk-foreground","keyword-val"),
+ XGCFunction ("is-function","mk-function","keyword-val"),
+ XGCJoinStyle ("is-join-style","mk-join-style","keyword-val"),
+ XGCLineStyle ("is-line-style","mk-line-style","keyword-val"),
+ XGCLineWidth ("is-line-width","mk-line-width","keyword-val"),
+ XGCPlaneMask ("is-plane-mask","mk-plane-mask","keyword-val"),
+ XGCStipple ("is-stipple","mk-stipple","keyword-val"),
+ XGCSubwindowMode ("is-subwindow-mode","mk-subwindow-mode","keyword-val"),
+ XGCTile ("is-tile","mk-tile","keyword-val"),
+ XGCTileOrigin ("is-tile-origin","mk-tile-origin","keyword-val")),
+ XImAttribute (
+ XImBitLsbFirstP ("is-bit-lsb-first-p","mk-bit-lsb-first-p","keyword-val"),
+ XImBitsPerPixel ("is-bits-per-pixel","mk-bits-per-pixel","keyword-val"),
+ XImBlueMask ("is-blue-mask","mk-blue-mask","keyword-val"),
+ XImByteLsbFirstP ("is-byte-lsb-first-p","mk-byte-lsb-first-p","keyword-val"),
+ XImBytesPerLine ("is-bytes-per-line","mk-bytes-per-line","keyword-val"),
+ XImData ("is-data","mk-data","keyword-val"),
+ XImDepth ("is-depth","mk-depth","keyword-val"),
+ XImFormat ("is-format","mk-format","keyword-val"),
+ XImGreenMask ("is-green-mask","mk-green-mask","keyword-val"),
+ XImSize ("is-size","mk-size","keyword-val"),
+ XImName ("is-name","mk-name","keyword-val"),
+ XImRedMask ("is-red-mask","mk-red-mask","keyword-val"),
+ XImHotSpot ("is-hot-spot","mk-hot-spot","keyword-val")),
+ XGrabAttribute (
+ XGrabOwnerP ("is-owner-p", "mk-owner-p", "keyword-val"),
+ XGrabSyncPointerP ("is-sync-pointer-p", "mk-sync-pointer-p", "keyword-val"),
+ XGrabSyncKeyboardP ("is-sync-keyboard-p", "mk-sync-keyboard-p", "keyword-val"),
+ XGrabConfineTo ("is-confine-to", "mk-confine-to", "keyword-val"),
+ XGrabCursor ("is-cursor", "mk-cursor", "keyword-val")),
+ XArcMode (XChord (":chord"),
+ XPieSlice (":pie-slice")),
+ XCapStyle (XButt (":butt"),
+ XNotLast (":not-last"),
+ XProjecting (":projecting"),
+ XRound (":round")),
+ XClipMask (XClipMaskPixmap ("xlib:pixmap-p","identity","identity"),
+ XClipMaskRects ("not-pixmap-and-list-p","mk-clip-mask-rects",
+ "sel-clip-mask-rects"),
+ XClipMaskNone ("null?", "()")),
+ XFillRule (XFillEvenOdd (":even-odd"),
+ XFillWinding (":winding")),
+ XFillStyle (XFillOpaqueStippled (":opaque-stippled"),
+ XFillSolid (":solid"),
+ XFillStippled (":stippled"),
+ XFillTiled (":tiled")),
+ XFunction (XBoole1 ("xlib::boole-1"),
+ XBoole2 ("xlib::boole-2"),
+ XBooleAndC1 ("xlib::boole-andc1"),
+ XBooleAndC2 ("xlib::boole-andc2"),
+ XBooleAnd ("xlib::boole-and"),
+ XBooleC1 ("xlib::boole-c1"),
+ XBooleC2 ("xlib::boole-c2"),
+ XBooleClr ("xlib::boole-clr"),
+ XBooleEqv ("xlib::boole-eqv"),
+ XBooleIor ("xlib::boole-ior"),
+ XBooleNand ("xlib::boole-nand"),
+ XBooleNor ("xlib::boole-nor"),
+ XBooleOrc1 ("xlib::boole-orc1"),
+ XBooleOrc2 ("xlib::boole-orc2"),
+ XBooleSet ("xlib::boole-set"),
+ XBooleXor ("xlib::boole-xor")),
+ XJoinStyle (XJoinBevel (":bevel"),
+ XJoinMiter (":miter"),
+ XJoinRound (":round")),
+ XLineStyle (XLineSolid (":solid"),
+ XLineDoubleDash (":double-dash"),
+ XLineOnOffDash (":on-off-dash")),
+ XSubwindowMode (XClipByChildren (":clip-by-children"),
+ XIncludeInferiors (":include-inferiors")),
+ XPoint(XPoint("mk-xpoint", "xpoint-x", "xpoint-y")),
+ XSize (XSize ("mk-xsize", "xsize-w", "xsize-h")),
+ XRect (XRect ("mk-xrect", "xrect-x", "xrect-y", "xrect-w", "xrect-h")),
+ XArc (XArc ("mk-xarc", "xarc-x", "xarc-y", "xarc-w", "xarc-h",
+ "xarc-a1", "xarc-a2")),
+ XBitmapFormat
+ (XBitmapFormat ("bitmap-format-p", "mk-bitmap-format",
+ "xlib:bitmap-format-unit",
+ "xlib:bitmap-format-pad",
+ "xlib:bitmap-format-lsb-first-p")),
+ XByteOrder (XLsbFirst (":lsbfirst"),
+ XMsbFirst (":msbfirst")),
+ XPixmapFormat (XPixmapFormat ("pixmap-format-p", "mk-pixmap-format",
+ "xlib:pixmap-format-depth",
+ "xlib:pixmap-format-bits-per-pixel",
+ "xlib:pixmap-format-scanline-pad")),
+ XVisualInfo
+ (XVisualInfo ( "visual-info-p", "mk-xvisual-info",
+ "xlib:visual-info-id",
+ "xlib:visual-info-class",
+ "xlib:visual-info-red-mask",
+ "xlib:visual-info-green-mask",
+ "xlib:visual-info-blue-mask",
+ "xlib:visual-info-bits-per-rgb",
+ "xlib:visual-info-colormap-entries")),
+ XVisualClass (XDirectColor (":direct-color"),
+ XGrayScale (":gray-scale"),
+ XPseudoColor (":pseudo-color"),
+ XStaticColor (":static-color"),
+ XStaticGray (":static-gray"),
+ XTrueColor (":true-color")),
+ XFillContent (XFillPixel ("is-fill-pixel", "identity","identity"),
+ XFillPixmap ("xlib:pixmap-p", "identity","identity"),
+ XFillNone (":none"),
+ XFillParentRelative (":parent-relative"),
+ XFillCopy (":copy")),
+ XBackingStore (XAlwaysBackStore (":always"),
+ XNeverBackStore (":never"),
+ XBackStoreWhenMapped (":when-mapped"),
+ XBackStoreNotUseful (":not-useful")),
+ XGravity (XForget (":forget"),
+ XStatic (":static"),
+ XCenter (":center"),
+ XEast (":east"),
+ XNorth (":north"),
+ XNorthEast (":north-east"),
+ XNorthWest (":north-west"),
+ XSouth (":south"),
+ XSouthEast (":south-east"),
+ XSouthWest (":south-west"),
+ XWest ("west")),
+ XWindowClass (XInputOutput (":input-output"),
+ XInputOnly (":input-only")),
+ XMapState (XUnmapped (":unmapped"),
+ XUnviewable (":unviewable"),
+ XViewable (":viewable")),
+ XImageData (XBitmapData ("bitmap-list-p", "haskell-list->list/identity", "list->haskell-list/identity"),
+ XPixarrayData ("pixarray-p", "identity", "identity"),
+ XByteVecData ("bytevec-p", "identity", "identity")),
+ XImageFormat (XXyPixmapImage (":xy-pixmap"),
+ XZPixmapImage (":z-pixmap"),
+ XBitmapImage (":bitmap")),
+ XImageType (XImageX ("'xlib:image-x"),
+ XImageXy ("'xlib:image-xy"),
+ XImageZ ("'xlib:image-z")),
+ XDrawDirection (XLeftToRight (":left-to-right"),
+ XRightToLeft (":right-to-left")),
+ XColor (XColor ("xlib:color-p", "mk-color",
+ "xlib:color-red", "xlib:color-green", "xlib:color-blue")),
+ XInputFocus (XFocusWindow ("xlib:window-p", "identity", "identity"),
+ XFocusNone (":none"),
+ XFocusPointerRoot (":pointer-root"),
+ XFocusParent (":parent")),
+ XGrabStatus (XAlreadyGrabbed (":already-grabbed"),
+ XFrozen (":frozen"),
+ XInvalidTime (":invalid-time"),
+ XSuccess (":success")),
+ XCloseDownMode (XDestroy (":destroy"),
+ XRetainPermanent (":retain-permanent"),
+ XRetainTemporary (":retain-temporary")),
+ XScreenSaver (XScreenSaver ("list", "car", "cadr", "caddr", "cadddr")))
+
+#-}
+
diff --git a/progs/lib/X11/xlib.hu b/progs/lib/X11/xlib.hu
new file mode 100644
index 0000000..b86b2ac
--- /dev/null
+++ b/progs/lib/X11/xlib.hu
@@ -0,0 +1,5 @@
+:output $LIBRARYBIN/
+:stable
+:o= all
+xlib.hs
+xlibprims.hu
diff --git a/progs/lib/X11/xlibclx.scm b/progs/lib/X11/xlibclx.scm
new file mode 100644
index 0000000..1f1fd6a
--- /dev/null
+++ b/progs/lib/X11/xlibclx.scm
@@ -0,0 +1,1262 @@
+;;; xlibclx.scm -- Lisp support for Haskell/CLX interface
+
+;; general
+
+(define-syntax (nth-value n form)
+ (cond ((eqv? n 0)
+ `(values ,form))
+ ((number? n)
+ (let ((temps '()))
+ (dotimes (i n)
+ (declare (ignorable i))
+ (push (gensym) temps))
+ `(multiple-value-bind ,(reverse temps) ,form
+ (declare (ignore ,@(reverse (cdr temps))))
+ ,(car temps))))
+ (else
+ `(lisp:nth ,n (lisp:multiple-value-list ,form)))
+ ))
+
+
+(define-local-syntax (keywordify string)
+ `(lisp:intern ,string (lisp:find-package "KEYWORD")))
+
+(define-local-syntax (xlibify string)
+ `(lisp:intern ,string (lisp:find-package "XLIB")))
+
+
+
+;;; This is stuff to support slots that consist of a keyword/value
+;;; pair. Note that the value is always unboxed.
+
+(define-syntax (make-keyword key value)
+ `(cons ,key ,value))
+
+(define-syntax (is-keyword? x key)
+ `(eq? (car ,x) ,key))
+
+(define-syntax (keyword-key x) `(car ,x))
+(define-syntax (keyword-val x) `(cdr ,x))
+
+(define-syntax (define-keyword-constructor name)
+ (let* ((name-str (symbol->string name))
+ (key (keywordify name-str))
+ (is-name (string->symbol (string-append "IS-" name-str)))
+ (mk-name (string->symbol (string-append "MK-" name-str))))
+ `(begin
+ (define (,mk-name x) (make-keyword ,key x))
+ (define (,is-name x) (is-keyword? x ,key)))
+ ))
+
+(define-syntax (define-event-slot-finder slot)
+ (let* ((slot-str (symbol->string slot))
+ (slot-key (keywordify slot-str))
+ (fun (string->symbol (string-append "X-EVENT-" slot-str))))
+ `(define (,fun event) (lookup-event-slot (cdr event) ,slot-key))))
+
+(define (lookup-event-slot event key)
+ (if (null? event)
+ (error "non-existent event slot: ~A" key)
+ (if (eq? key (car event))
+ (cadr event)
+ (lookup-event-slot (cddr event) key))))
+
+
+(define-syntax (define-attribute-setter entity attribute)
+ (let* ((entity-attr (string-append (symbol->string entity)
+ "-"
+ (symbol->string attribute)))
+ (fun-name (string->symbol (string-append "X-SET-" entity-attr)))
+ (xfun-name (xlibify entity-attr)))
+ `(define (,fun-name ,entity ,attribute)
+ (setf (,xfun-name ,entity) ,attribute))))
+
+(define-syntax (make-h-tuple . args)
+ (let ((nargs (map (lambda (arg) `(box ,arg)) args)))
+ `(make-tuple ,@nargs)))
+
+;; type XError
+
+(define (cons-xerror x)
+ (declare (ignore x))
+ (error "can't construct XError"))
+
+(define (x-error-string c)
+ (make-haskell-string (format '#f "~A" c)))
+
+
+;;; The forces here are necessary because the thing being funcalled
+;;; returns a data structure of type (IO a), and we need to do
+;;; an IO a -> a transformation.
+
+#+lucid
+(define (x-handle-error handler body)
+ (lisp:catch 'x-error-handle
+ (lcl:handler-bind ((lisp:error (mk-handler handler)))
+ (force (funcall body (box 'state))))))
+
+#+(or cmu allegro lispworks)
+(define (x-handle-error handler body)
+ (lisp:catch 'x-error-handle
+ (lisp:handler-bind ((lisp:error (mk-handler handler)))
+ (force (funcall body (box 'state))))))
+
+#+akcl
+(define (x-handle-error handler body)
+ (error "AKCL does not support HANDLER-BIND!"))
+
+(define (mk-handler handler)
+ (lambda (c)
+ (lisp:throw 'x-error-handle
+ (force (funcall handler
+ (box c)
+ (box 'state))))))
+
+;; for type XMaybe
+
+(define (not-null? x) (not (null? x)))
+
+
+;; For Bitmap, Pixarray, KeysymTable
+
+(define (array2->haskell-list a)
+ (let* ((dims (lisp:array-dimensions a))
+ (i1max (car dims))
+ (i2max (cadr dims)))
+ (declare (type fixnum i1max i2max))
+ (do ((i1 (the fixnum (1- i1max)) (the fixnum (1- i1)))
+ (outer '()))
+ ((< i1 0) outer)
+ (declare (type fixnum i1))
+ (setf outer
+ (cons
+ (box
+ (do ((i2 (the fixnum (1- i2max)) (the fixnum (1- i2)))
+ (inner '()))
+ ((< i2 0) inner)
+ (declare (type fixnum i2))
+ (setf inner
+ (cons (box (lisp:aref a i1 i2))
+ (box inner)))))
+ (box outer))))
+ ))
+
+
+;; Bitmap
+
+(define (mk-bitmap ll)
+ (let ((l (haskell-list->list #'haskell-list->list/identity ll)))
+ (lisp:make-array `(,(length l) , (length (car l)))
+ :element-type 'lisp:bit
+ :initial-contents l)))
+
+(define (sel-bitmap l)
+ (array2->haskell-list l))
+
+
+;; XKeysymTable
+
+(define (mk-keysym-table ll)
+ (let ((l (haskell-list->list #'haskell-list->list/identity ll)))
+ (lisp:make-array `(,(length l) , (length (car l)))
+ :element-type 'xlib:card32
+ :initial-contents l)))
+
+(define (sel-keysym-table l)
+ (array2->haskell-list l))
+
+;; XPixarray
+
+(define (mk-pixarray ll)
+ (let ((l (haskell-list->list #'haskell-list->list/identity ll)))
+ (let* ((max-num (find-max l))
+ (pix-type (cond ((<= max-num 1) 'lisp:bit)
+ ((<= max-num 15) '(lisp:unsigned-byte 4))
+ ((<= max-num 255) 'xlib:card8)
+ ((<= max-num 65535) 'xlib:card16)
+ (else 'xlib:card32))))
+ (declare (type integer max-num))
+ (lisp:make-array `(,(length l) , (length (car l)))
+ :element-type pix-type
+ :initial-contents l))))
+
+(define (find-max l)
+ (let ((max 0))
+ (dolist (ll l)
+ (dolist (lll ll)
+ (when (> (the integer lll) (the integer max))
+ (setf max lll))))
+ max))
+
+(define (sel-pixarray l)
+ (array2->haskell-list l))
+
+
+
+
+;;; Can't use mumble vector primitives on arrays of specialized types!
+
+(define (array1->haskell-list a)
+ (declare (type lisp:vector a))
+ (let ((imax (lisp:length a)))
+ (declare (type fixnum imax))
+ (do ((i (the fixnum (1- imax)) (the fixnum (1- i)))
+ (result '()))
+ ((< i 0) result)
+ (declare (type fixnum i))
+ (setf result
+ (cons (box (lisp:aref a i))
+ (box result))))))
+
+;; BitVec
+
+(define (mk-bitvec ll)
+ (let ((l (haskell-list->list/identity ll)))
+ (lisp:make-array `(,(length l)) :element-type 'lisp:bit
+ :initial-contents l)))
+
+(define (sel-bitvec l)
+ (array1->haskell-list l))
+
+;; ByteVec
+
+(define (mk-bytevec ll)
+ (let ((l (haskell-list->list/identity ll)))
+ (lisp:make-array `(,(length l)) :element-type 'xlib:card8
+ :initial-contents l)))
+
+(define (sel-bytevec l)
+ (array1->haskell-list l))
+
+
+;; XAtom
+(define (mk-atom name)
+ (keywordify (haskell-string->string name)))
+
+(define (sel-atom atom)
+ (make-haskell-string (symbol->string atom)))
+
+;; XProperty
+;;; watch out for name conflict with :property keyword stuff
+(define (mk-xproperty d ty f) (list (haskell-list->list/identity d) ty f))
+(define (sel-xproperty-data p) (list->haskell-list/identity (car p)))
+(define (sel-xproperty-type p) (cadr p))
+(define (sel-xproperty-format p) (caddr p))
+
+(define (mk-event type slots)
+ (cons type (slots->keywords (haskell-list->list/identity slots))))
+
+(define (sel-event-type event) (car event))
+
+(define (sel-event-slots event)
+ (list->haskell-list/identity (keywords->slots (car event) (cdr event) event)))
+
+;; XEventSlot
+
+(define-keyword-constructor window)
+(define-keyword-constructor event-window)
+(define-keyword-constructor code)
+(define-keyword-constructor pos)
+(define-keyword-constructor state)
+(define-keyword-constructor time)
+(define-keyword-constructor root)
+(define-keyword-constructor root-pos)
+(define-keyword-constructor child)
+(define-keyword-constructor same-screen-p)
+(define-keyword-constructor hint-p)
+(define-keyword-constructor mode)
+(define-keyword-constructor kind)
+(define-keyword-constructor focus-p)
+(define-keyword-constructor keymap)
+(define-keyword-constructor request)
+(define-keyword-constructor start)
+(define-keyword-constructor count)
+(define-keyword-constructor rect)
+(define-keyword-constructor drawable)
+(define-keyword-constructor graph-fun)
+(define-keyword-constructor place)
+(define-keyword-constructor border-width)
+(define-keyword-constructor above-sibling)
+(define-keyword-constructor override-redirect-p)
+(define-keyword-constructor parent)
+(define-keyword-constructor configure-p)
+(define-keyword-constructor visibility)
+(define-keyword-constructor new-p)
+(define-keyword-constructor installed-p)
+(define-keyword-constructor stack-mode)
+(define-keyword-constructor value-mask)
+(define-keyword-constructor size)
+(define-keyword-constructor message)
+(define-keyword-constructor property-state)
+(define-keyword-constructor atom)
+(define-keyword-constructor selection)
+(define-keyword-constructor target)
+(define-keyword-constructor property)
+(define-keyword-constructor requestor)
+
+(define-event-slot-finder window)
+(define-event-slot-finder event-window)
+(define-event-slot-finder code)
+(define-event-slot-finder x)
+(define-event-slot-finder y)
+(define-event-slot-finder state)
+(define-event-slot-finder time)
+(define-event-slot-finder root)
+(define-event-slot-finder root-x)
+(define-event-slot-finder root-y)
+(define-event-slot-finder child)
+(define-event-slot-finder same-screen-p)
+(define-event-slot-finder hint-p)
+(define-event-slot-finder mode)
+(define-event-slot-finder kind)
+(define-event-slot-finder focus-p)
+(define-event-slot-finder keymap)
+(define-event-slot-finder request)
+(define-event-slot-finder start)
+(define-event-slot-finder count)
+(define-event-slot-finder width)
+(define-event-slot-finder height)
+(define-event-slot-finder drawable)
+(define-event-slot-finder major)
+(define-event-slot-finder minor)
+(define-event-slot-finder place)
+(define-event-slot-finder border-width)
+(define-event-slot-finder above-sibling)
+(define-event-slot-finder override-redirect-p)
+(define-event-slot-finder parent)
+(define-event-slot-finder configure-p)
+(define-event-slot-finder new-p)
+(define-event-slot-finder installed-p)
+(define-event-slot-finder stack-mode)
+(define-event-slot-finder value-mask)
+(define-event-slot-finder data)
+(define-event-slot-finder type)
+(define-event-slot-finder format)
+(define-event-slot-finder atom)
+(define-event-slot-finder selection)
+(define-event-slot-finder target)
+(define-event-slot-finder property)
+(define-event-slot-finder requestor)
+
+(define (x-event-pos event) (mk-xpoint (x-event-x event) (x-event-y event)))
+
+(define (x-event-root-pos event)
+ (mk-xpoint (x-event-root-x event) (x-event-root-y event)))
+
+(define (x-event-size event)
+ (mk-xsize (x-event-width event) (x-event-height event)))
+
+(define (x-event-rect event)
+ (mk-xrect (x-event-x event) (x-event-y event)
+ (x-event-width event) (x-event-height event)))
+
+(define (x-event-graph-fun event)
+ (cons (x-event-major event) (x-event-minor event)))
+
+(define (x-event-message event)
+ (list (sequence->list (x-event-data event))
+ (x-event-type event)
+ (x-event-format event)))
+
+
+;; XEventMask
+
+(define (x-make-event-mask keys)
+ (apply (function xlib:make-event-mask) (haskell-list->list/identity keys)))
+
+(define (x-event-mask-key-list mask)
+ (list->haskell-list/identity (xlib:make-event-keys mask)))
+
+;; XStateMask
+
+(define (x-make-state-mask keys)
+ (apply (function xlib:make-state-mask) (haskell-list->list/identity keys)))
+
+(define (x-state-mask-key-list mask)
+ (list->haskell-list/identity (xlib:make-state-keys mask)))
+
+
+(define-keyword-constructor background)
+(define-keyword-constructor foreground)
+(define-keyword-constructor event-mask)
+(define-keyword-constructor depth)
+(define-keyword-constructor border-width)
+(define-keyword-constructor class)
+(define-keyword-constructor visual)
+(define-keyword-constructor border)
+(define-keyword-constructor backing-store)
+(define-keyword-constructor backing-planes)
+(define-keyword-constructor backing-pixel)
+(define-keyword-constructor save-under)
+(define-keyword-constructor do-not-propagate-mask)
+(define-keyword-constructor override-redirect)
+(define-keyword-constructor colormap)
+(define-keyword-constructor cursor)
+
+(define-keyword-constructor arc-mode)
+(define-keyword-constructor cap-style)
+(define-keyword-constructor clip-mask)
+(define-keyword-constructor clip-origin)
+(define-keyword-constructor dash-offset)
+(define-keyword-constructor dashes)
+(define-keyword-constructor exposures)
+(define-keyword-constructor fill-rule)
+(define-keyword-constructor fill-style)
+(define-keyword-constructor font)
+(define-keyword-constructor function)
+(define-keyword-constructor join-style)
+(define-keyword-constructor line-style)
+(define-keyword-constructor line-width)
+(define-keyword-constructor plane-mask)
+(define-keyword-constructor stipple)
+(define-keyword-constructor subwindow-mode)
+(define-keyword-constructor tile)
+(define-keyword-constructor tile-origin)
+
+(define-keyword-constructor bit-lsb-first-p)
+(define-keyword-constructor bits-per-pixel)
+(define-keyword-constructor blue-mask)
+(define-keyword-constructor byte-lsb-first-p)
+(define-keyword-constructor bytes-per-line)
+(define-keyword-constructor data)
+(define-keyword-constructor format)
+(define-keyword-constructor green-mask)
+(define-keyword-constructor size)
+(define-keyword-constructor name)
+(define-keyword-constructor red-mask)
+(define-keyword-constructor hot-spot)
+
+
+(define-keyword-constructor owner-p)
+(define-keyword-constructor sync-pointer-p)
+(define-keyword-constructor sync-keyboard-p)
+(define-keyword-constructor confine-to)
+
+
+;; XClipMask
+
+(define (not-pixmap-and-list-p x)
+ (and (pair? x) (not (xlib:pixmap-p x))))
+(define (mk-clip-mask-rects rects)
+ (rects->point-seq (haskell-list->list/identity rects)))
+(define (sel-clip-mask-rects point-seq)
+ (list->haskell-list/identity (point-seq->rects point-seq)))
+
+;; XPoint
+
+(define (mk-xpoint x y) (cons x y))
+(define (xpoint-x x) (car x))
+(define (xpoint-y x) (cdr x))
+
+;; XSize
+
+(define (mk-xsize x y) (cons x y))
+(define (xsize-w x) (car x))
+(define (xsize-h x) (cdr x))
+
+;; XRect
+(define (mk-xrect x y w h) (vector x y w h))
+(define (xrect-x x) (vector-ref x 0))
+(define (xrect-y x) (vector-ref x 1))
+(define (xrect-w x) (vector-ref x 2))
+(define (xrect-h x) (vector-ref x 3))
+
+;; XArc
+
+(define (mk-xarc x y w h a1 a2) (vector x y w h a1 a2))
+
+(define (xarc-x x) (vector-ref x 0))
+(define (xarc-y x) (vector-ref x 1))
+(define (xarc-w x) (vector-ref x 2))
+(define (xarc-h x) (vector-ref x 3))
+(define (xarc-a1 x) (vector-ref x 4))
+(define (xarc-a2 x) (vector-ref x 5))
+
+;; BitmapFormat
+
+(define (mk-bitmap-format u p l)
+ (xlib::make-bitmap-format :unit u :pad p :lsb-first-p l))
+
+;; PixmapFormat
+
+(define (mk-pixmap-format u p l)
+ (xlib::make-pixmap-format :depth u :bits-per-pixel p :scanline-pad l))
+
+;; XVisualInfo
+
+(define (mk-xvisual-info id cl rm gm bm bs es)
+ (xlib::make-visual-info :id id :class cl :red-mask rm :green-mask gm
+ :blue-mask bm :bits-per-rgb bs :colormap-entries es))
+
+;; XFillContent
+
+(define (is-fill-pixel x) (not (or (xlib:pixmap-p x) (symbol? x))))
+
+;; XBackingStore
+
+;; XImageData
+
+(define (bitmap-list-p x) (pair? x))
+(define (pixarray-p x) (and (not (pair? x)) (eq? (lisp:array-rank x) 2)))
+(define (bytevec-p x) (and (not (pair? x)) (eq? (lisp:array-rank x) 1)))
+
+;; XColor
+(define (mk-color r g b)
+ (xlib:make-color :red r :green g :blue b))
+
+
+(define (x-print x)
+ (print x))
+
+(define (x-set-event-mask-key mask key-sym)
+ (lisp:logior mask (xlib:make-event-mask key-sym)))
+
+(define (x-clear-event-mask-key mask key-sym)
+ (lisp:logand mask (lisp:lognot (xlib:make-event-mask key-sym))))
+
+
+(define (x-test-event-mask-key mask key-sym)
+ (if (eqv? 0 (lisp:logand mask (xlib:make-event-mask key-sym))) '#f '#t))
+
+(define (x-set-state-mask-key mask key-sym)
+ (lisp:logior mask (xlib:make-state-mask key-sym)))
+
+(define (x-clear-state-mask-key mask key-sym)
+ (lisp:logand mask (lisp:lognot (xlib:make-state-mask key-sym))))
+
+(define (x-test-state-mask-key mask key-sym)
+ (if (eqv? 0 (lisp:logand mask (xlib:make-state-mask key-sym))) '#f '#t))
+
+
+;;; Display is a string of the format name:d.s
+;;; ignore s; if d is omitted, default it to zero.
+
+(define (x-open-display display)
+ (let* ((end (string-length display))
+ (colon (or (string-position #\: display 0 end) end))
+ (dot (or (string-position #\. display colon end) end)))
+ (declare (type fixnum end colon dot))
+ (xlib:open-display
+ (substring display 0 colon)
+ :display (if (eqv? colon dot)
+ 0
+ (string->number (substring display (1+ colon) dot))))))
+
+(define (x-set-display-error-handler display error-fun)
+ (declare (ignore display error-fun))
+ (error "not implemented"))
+
+(define (x-set-display-after-function display after-fun)
+ (declare (ignore display after-fun))
+ (error "not implemented"))
+
+(define (x-screen-depths screen)
+ (let ((depths (xlib:screen-depths screen)))
+ (map (lambda (l) (make-h-tuple (car l) (list->haskell-list/identity (cdr l))))
+ depths)))
+
+(define (x-screen-size screen)
+ (mk-xsize (xlib:screen-width screen) (xlib:screen-height screen)))
+
+(define (x-screen-mmsize screen)
+ (mk-xsize (xlib:screen-width-in-millimeters screen)
+ (xlib:screen-height-in-millimeters screen)))
+
+(define (x-create-window parent rect attrs)
+ (apply (function XLIB:CREATE-WINDOW)
+ `(:parent ,parent :x ,(xrect-x rect) :y ,(xrect-y rect)
+ :width ,(xrect-w rect) :height ,(xrect-h rect)
+ ,@(attrs->keywords attrs))))
+
+(define-attribute-setter drawable border-width)
+
+(define (x-drawable-size drawable)
+ (mk-xsize (xlib:drawable-width drawable) (xlib:drawable-height drawable)))
+
+(define (x-drawable-resize drawable size)
+ (setf (xlib:drawable-width drawable) (xsize-w size))
+ (setf (xlib:drawable-height drawable) (xsize-h size)))
+
+(define (x-window-pos window)
+ (mk-xpoint (xlib:drawable-x window) (xlib:drawable-y window)))
+
+(define (x-window-move window point)
+ (setf (xlib:drawable-x window) (xpoint-x point))
+ (setf (xlib:drawable-y window) (xpoint-y point)))
+
+(define-attribute-setter window background)
+(define-attribute-setter window backing-pixel)
+(define-attribute-setter window backing-planes)
+(define-attribute-setter window backing-store)
+(define-attribute-setter window bit-gravity)
+(define-attribute-setter window border)
+(define-attribute-setter window colormap)
+
+(define (x-set-window-cursor window cursor)
+ (let ((val (if (null? cursor) :none cursor)))
+ (setf (xlib:window-cursor window) val)))
+
+(define-attribute-setter window do-not-propagate-mask)
+(define-attribute-setter window event-mask)
+(define-attribute-setter window gravity)
+(define-attribute-setter window override-redirect)
+(define-attribute-setter window priority)
+(define-attribute-setter window save-under)
+
+(define (x-query-tree window)
+ (multiple-value-bind (children parent root)
+ (xlib:query-tree window)
+ (make-h-tuple (list->haskell-list/identity children) parent root)))
+
+(define (x-reparent-window window parent point)
+ (xlib:reparent-window window parent (xpoint-x point) (xpoint-y point)))
+
+(define (x-translate-coordinates source point dest)
+ (xlib:translate-coordinates source (xpoint-x point) (xpoint-y point) dest))
+
+(define (x-create-pixmap size depth drawable)
+ (xlib:create-pixmap :width (xsize-w size)
+ :height (xsize-h size)
+ :depth depth
+ :drawable drawable))
+
+(define (x-create-gcontext drawable attrs)
+ (apply (function XLIB:CREATE-GCONTEXT)
+ `(:drawable ,drawable ,@(attrs->keywords attrs))))
+
+(define (x-update-gcontext gcontext attrs)
+ (do ((keys (attrs->keywords attrs) (cddr keys)))
+ ((null? keys))
+ (x-update-gcontext-attr gcontext (car keys) (cadr keys))))
+
+(define (x-update-gcontext-attr gcontext key attr)
+ (case key
+ (:arc-mode (setf (xlib:gcontext-arc-mode gcontext) attr))
+ (:background (setf (xlib:gcontext-background gcontext) attr))
+ (:cap-style (setf (xlib:gcontext-cap-style gcontext) attr))
+ (:fill-style (setf (xlib:gcontext-fill-style gcontext) attr))
+ (:clip-mask (setf (xlib:gcontext-clip-mask gcontext) attr))
+ (:clip-x (setf (xlib:gcontext-clip-x gcontext) attr))
+ (:clip-y (setf (xlib:gcontext-clip-y gcontext) attr))
+ (:dash-offset (setf (xlib:gcontext-dash-offset gcontext) attr))
+ (:dashes (setf (xlib:gcontext-dashes gcontext) attr))
+ (:exposures (setf (xlib:gcontext-exposures gcontext) attr))
+ (:fill-rule (setf (xlib:gcontext-fill-rule gcontext) attr))
+ (:font (setf (xlib:gcontext-font gcontext) attr))
+ (:foreground (setf (xlib:gcontext-foreground gcontext) attr))
+; (:function (setf (xlib:gcontext-function gcontext) attr))
+ (:join-style (setf (xlib:gcontext-join-style gcontext) attr))
+ (:line-style (setf (xlib:gcontext-line-style gcontext) attr))
+; (:line-width (setf (xlib:gcontext-line-width gcontext) attr))
+; (:plane-mask (setf (xlib:gcontext-plane-mask gcontext) attr))
+; (:stipple (setf (xlib:gcontext-stipple gcontext) attr))
+ (:subwindow-mode (setf (xlib:gcontext-subwindow-mode gcontext) attr))
+; (:tile (setf (xlib:gcontext-tile gcontext) attr))
+; (:ts-x (setf (xlib:gcontext-ts-x gcontext) attr))
+; (:ts-y (setf (xlib:gcontext-ts-y gcontext) attr))
+ (else (format '#t "Graphics context attribute ~A is not settable.~%"
+ key))))
+
+(define (x-query-best-stipple dsize drawable)
+ (multiple-value-bind (w h)
+ (xlib:query-best-stipple (xsize-w dsize) (xsize-h dsize) drawable)
+ (mk-xsize w h)))
+
+(define (x-query-best-tile dsize drawable)
+ (multiple-value-bind (w h)
+ (xlib:query-best-tile (xsize-w dsize) (xsize-h dsize) drawable)
+ (mk-xsize w h)))
+
+(define (x-clear-area window rect exposures-p)
+ (xlib:clear-area window
+ :x (xrect-x rect)
+ :y (xrect-y rect)
+ :width (xrect-w rect)
+ :height (xrect-h rect)
+ :exposures-p exposures-p))
+
+(define (x-copy-area src gcontext rect dest point)
+ (xlib:copy-area src
+ gcontext
+ (xrect-x rect) (xrect-y rect)
+ (xrect-w rect) (xrect-h rect)
+ dest
+ (xpoint-x point) (xpoint-y point)))
+
+(define (x-copy-plane src gcontext plane rect dest point)
+ (xlib:copy-plane src
+ gcontext
+ plane
+ (xrect-x rect) (xrect-y rect)
+ (xrect-w rect) (xrect-h rect)
+ dest
+ (xpoint-x point) (xpoint-y point)))
+
+(define (x-draw-point drawable gcontext point)
+ (xlib:draw-point drawable gcontext (xpoint-x point) (xpoint-y point)))
+
+(define (x-draw-points drawable gcontext points)
+ (xlib:draw-points drawable gcontext (points->point-seq points)))
+
+(define (points->point-seq points)
+ (if (null? points)
+ '()
+ (let ((point (car points)))
+ (lisp:list* (xpoint-x point)
+ (xpoint-y point)
+ (points->point-seq (cdr points))))))
+
+(define (segments->point-seq segments)
+ (if (null? segments)
+ '()
+ (let* ((first-pair (car segments))
+ (point-1 (force (tuple-select 2 0 first-pair)))
+ (point-2 (force (tuple-select 2 1 first-pair))))
+ (lisp:list* (xpoint-x point-1)
+ (xpoint-y point-1)
+ (xpoint-x point-2)
+ (xpoint-y point-2)
+ (segments->point-seq (cdr segments))))))
+
+(define (rects->point-seq rects)
+ (if (null? rects)
+ '()
+ (let ((rect (car rects)))
+ (lisp:list* (xrect-x rect)
+ (xrect-y rect)
+ (xrect-w rect)
+ (xrect-h rect)
+ (rects->point-seq (cdr rects))))))
+
+(define (point-seq->rects point-seq)
+ (if (null? point-seq)
+ '()
+ (cons (mk-xrect (car point-seq) (cadr point-seq)
+ (caddr point-seq) (cadddr point-seq))
+ (point-seq->rects (cddddr point-seq)))))
+
+(define (arcs->point-seq arcs)
+ (if (null? arcs)
+ '()
+ (let ((arc (car arcs)))
+ (lisp:list* (xarc-x arc)
+ (xarc-y arc)
+ (xarc-w arc)
+ (xarc-h arc)
+ (xarc-a1 arc)
+ (xarc-a2 arc)
+ (arcs->point-seq (cdr arcs))))))
+
+(define (x-draw-line drawable gcontext point-1 point-2)
+ (xlib:draw-line drawable gcontext (xpoint-x point-1) (xpoint-y point-1)
+ (xpoint-x point-2) (xpoint-y point-2)))
+
+(define (x-draw-lines drawable gcontext points fill-p)
+ (xlib:draw-lines drawable gcontext
+ (points->point-seq points) :fill-p fill-p))
+
+(define (x-draw-segments drawable gcontext segments)
+ (xlib:draw-segments drawable gcontext (segments->point-seq segments)))
+
+(define (x-draw-rectangle drawable gcontext rect fill-p)
+ (xlib:draw-rectangle drawable gcontext
+ (xrect-x rect) (xrect-y rect)
+ (xrect-w rect) (xrect-h rect)
+ fill-p))
+
+(define (x-draw-rectangles drawable gcontext rects fill-p)
+ (xlib:draw-rectangles drawable gcontext
+ (rects->point-seq rects)
+ fill-p))
+
+(define (x-draw-arc drawable gcontext arc fill-p)
+ (xlib:draw-arc drawable gcontext
+ (xarc-x arc) (xarc-y arc)
+ (xarc-w arc) (xarc-h arc)
+ (xarc-a1 arc) (xarc-a2 arc)
+ fill-p))
+
+(define (x-draw-arcs drawable gcontext arcs fill-p)
+ (xlib:draw-arcs drawable gcontext
+ (arcs->point-seq arcs)
+ fill-p))
+
+(define (x-draw-glyph drawable gcontext point element)
+ (nth-value 1
+ (xlib:draw-glyph drawable gcontext (xpoint-x point)
+ (xpoint-y point) element)))
+
+(define (x-draw-glyphs drawable gcontext point element)
+ (nth-value 1 (xlib:draw-glyphs drawable gcontext (xpoint-x point)
+ (xpoint-y point) element)))
+
+(define (x-draw-image-glyph drawable gcontext point element)
+ (nth-value 1 (xlib:draw-image-glyph drawable gcontext (xpoint-x point)
+ (xpoint-y point) element)))
+
+(define (x-draw-image-glyphs drawable gcontext point element)
+ (nth-value 1 (xlib:draw-image-glyphs drawable gcontext (xpoint-x point)
+ (xpoint-y point) element)))
+
+(define (x-image-size image)
+ (mk-xsize (xlib:image-width image) (xlib:image-height image)))
+
+(define (x-image-name image)
+ (let ((lisp-name (xlib:image-name image)))
+ (cond ((null? lisp-name) "")
+ ((symbol? lisp-name) (symbol->string lisp-name))
+ (else lisp-name))))
+
+(define-attribute-setter image name)
+
+(define (x-image-hot-spot image)
+ (mk-xpoint (xlib:image-x-hot image) (xlib:image-y-hot image)))
+
+(define (x-set-image-hot-spot image point)
+ (setf (xlib:image-x-hot image) (xpoint-x point))
+ (setf (xlib:image-y-hot image) (xpoint-y point)))
+
+(define-attribute-setter image xy-bitmap-list)
+(define-attribute-setter image z-bits-per-pixel)
+(define-attribute-setter image z-pixarray)
+
+(define (x-create-image attrs)
+ (apply (function xlib:create-image) (attrs->keywords attrs)))
+
+(define (x-copy-image image rect type)
+ (xlib:copy-image image :x (xrect-x rect) :y (xrect-y rect)
+ :width (xrect-w rect) :height (xrect-h rect)
+ :result-type type))
+
+(define (x-get-image drawable rect pmask format type)
+ (xlib:get-image drawable :x (xrect-x rect) :y (xrect-y rect)
+ :width (xrect-w rect) :height (xrect-h rect)
+ :plane-mask pmask :format format :result-type type))
+
+(define (x-put-image drawable gcontext image point rect)
+ (xlib:put-image drawable gcontext image
+ :src-x (xpoint-x point) :src-y (xpoint-y point)
+ :x (xrect-x rect) :y (xrect-y rect)
+ :width (xrect-w rect) :height (xrect-h rect)))
+
+(define (x-get-raw-image drawable rect pmask format)
+ (xlib:get-raw-image drawable
+ :x (xrect-x rect) :y (xrect-y rect)
+ :width (xrect-w rect) :height (xrect-h rect)
+ :plane-mask pmask :format format))
+
+(define (x-put-raw-image drawable gcontext data depth rect left-pad format)
+ (xlib:put-raw-image drawable gcontext data
+ :depth depth
+ :x (xrect-x rect) :y (xrect-y rect)
+ :width (xrect-w rect) :height (xrect-h rect)
+ :left-pad left-pad :format format))
+
+(define (x-font-name font)
+ (let ((lisp-name (xlib:font-name font)))
+ (cond ((null? lisp-name) "")
+ ((symbol? lisp-name) (symbol->string lisp-name))
+ (else lisp-name))))
+
+(define (x-alloc-color colormap color)
+ (multiple-value-bind (pixel screen-color exact-color)
+ (xlib:alloc-color colormap color)
+ (make-h-tuple pixel screen-color exact-color)))
+
+(define (x-alloc-color-cells colormap colors planes contiguous-p)
+ (multiple-value-bind (pixels mask)
+ (xlib:alloc-color-cells colormap colors :planes planes
+ :contiguous-p contiguous-p)
+ (make-h-tuple (list->haskell-list/identity pixels) (list->haskell-list/identity mask))))
+
+(define (x-alloc-color-planes colormap colors reds greens blues contiguous-p)
+ (multiple-value-bind (pixels red-mask green-mask blue-mask)
+ (xlib:alloc-color-planes colormap colors :reds reds :greens greens
+ :blues blues :contiguous-p contiguous-p)
+ (make-h-tuple (list->haskell-list/identity pixels)
+ red-mask
+ green-mask
+ blue-mask)))
+
+(define (x-lookup-color colormap name)
+ (multiple-value-bind (screen-color exact-color)
+ (xlib:lookup-color colormap name)
+ (make-h-tuple screen-color exact-color)))
+
+(define (unzip l)
+ (if (null? l)
+ '()
+ (let ((h (car l)))
+ (lisp:list* (force (tuple-select 2 0 h))
+ (force (tuple-select 2 1 h))
+ (unzip (cdr l))))))
+
+(define (x-store-colors colormap pixel-colors)
+ (xlib:store-colors colormap (unzip pixel-colors)))
+
+(define (x-create-cursor source mask point foreground background)
+ (apply (function xlib:create-cursor)
+ `(:source ,source
+ ,@(if mask `(:mask ,mask) '())
+ :x ,(xpoint-x point) :y ,(xpoint-y point)
+ :foreground ,foreground :background ,background)))
+
+(define (x-create-glyph-cursor src mask foreground background)
+ (apply (function xlib:create-glyph-cursor)
+ `(:source-font ,(force (tuple-select 2 0 src))
+ :source-char ,(integer->char (force (tuple-select 2 1 src)))
+ ,@(if mask
+ `(:mask-font ,(force (tuple-select 2 0 mask))
+ :mask-char ,(integer->char (force (tuple-select 2 1 mask))))
+ '())
+ :foreground ,foreground :background ,background)))
+
+(define (x-query-best-cursor size display)
+ (multiple-value-bind (w h)
+ (xlib:query-best-cursor (xsize-w size) (xsize-h size) display)
+ (mk-xsize w h)))
+
+(define (x-change-property window property content)
+ (xlib:change-property window property
+ (car content) (cadr content)
+ (caddr content)))
+
+(define (x-get-property window property)
+ (lisp:multiple-value-bind (data type format)
+ (xlib:get-property window property)
+ (list (sequence->list data) type format)))
+
+(define (x-convert-selection selection type requestor property time)
+ (apply (function xlib:convert-selection)
+ `(,selection ,type ,requestor ,property ,@(if time `(,time) '()))))
+
+(define (x-set-selection-owner display selection time owner)
+ (if time
+ (setf (xlib:selection-owner display selection time) owner)
+ (setf (xlib:selection-owner display selection) owner)))
+
+(define (sequence->list seq)
+ (if (list? seq) seq
+ (do ((i (1- (lisp:length seq)) (1- i))
+ (res '() (cons (lisp:elt seq i) res)))
+ ((< i 0) res))))
+
+(define *this-event* '())
+
+(define (translate-event lisp:&rest event-slots lisp:&key event-key
+ lisp:&allow-other-keys)
+ (setf *this-event* (cons event-key event-slots))
+ '#t)
+
+
+(define (x-get-event display)
+ (xlib:process-event display :handler #'translate-event :force-output-p '#t)
+ *this-event*)
+
+(define (x-queue-event display event append-p)
+ (apply (function xlib:queue-event)
+ `(,display ,(car event) ,@(cdr event) :append-p ,append-p)))
+
+(define (x-event-listen display)
+ (let ((res (xlib:event-listen display)))
+ (if (null? res) 0 res)))
+
+(define (x-send-event window event mask)
+ (apply (function xlib:send-event)
+ `(,window ,(car event) ,mask ,@(cdr event))))
+
+(define (x-global-pointer-position display)
+ (multiple-value-bind (x y) (xlib:global-pointer-position display)
+ (mk-xpoint x y)))
+
+(define (x-pointer-position window)
+ (multiple-value-bind (x y same) (xlib:pointer-position window)
+ (if same (mk-xpoint x y) '())))
+
+(define (x-motion-events window start stop)
+ (do ((npos '() (cons (mk-xpoint (car pos) (cadr pos)) npos))
+ (pos (xlib:motion-events window :start start :stop stop)
+ (cdddr pos)))
+ ((null? pos) (nreverse npos))))
+
+(define (x-warp-pointer dest-win point)
+ (xlib:warp-pointer dest-win (xpoint-x point) (xpoint-y point)))
+
+(define (x-set-input-focus display focus revert-to time)
+ (apply (function xlib:set-input-focus)
+ `(,display ,focus ,revert-to ,@(if time `(,time) '()))))
+
+(define (x-input-focus display)
+ (multiple-value-bind (focus revert-to) (xlib:input-focus display)
+ (make-h-tuple focus revert-to)))
+
+(define (x-grab-pointer window event-mask attrs time)
+ (apply (function xlib:grab-pointer)
+ `(,window ,event-mask
+ ,@(attrs->keywords attrs)
+ ,@(if time `(:time ,time) '()))))
+
+(define (x-ungrab-pointer display time)
+ (if time
+ (xlib:ungrab-pointer display :time time)
+ (xlib:ungrab-pointer display)))
+
+(define (x-change-active-pointer-grab display event-mask attrs time)
+ (apply (function xlib:change-active-pointer-grab)
+ `(,display ,event-mask
+ ,@(attrs->keywords attrs)
+ ,@(if time `(,time) '()))))
+
+(define (x-grab-button window button event-mask state-mask attrs)
+ (apply (function xlib:grab-button)
+ `(,window ,button ,event-mask :modifiers ,state-mask
+ ,@(attrs->keywords attrs))))
+
+(define (x-ungrab-button window button modifiers)
+ (xlib:ungrab-button window button :modifiers modifiers))
+
+(define (x-grab-keyboard window attrs time)
+ (apply (function xlib:grab-keyboard)
+ `(,window ,@(attrs->keywords attrs)
+ ,@(if time `(:time ,time) '()))))
+
+(define (x-ungrab-keyboard display time)
+ (if time
+ (xlib:ungrab-keyboard display :time time)
+ (xlib:ungrab-keyboard display)))
+
+(define (x-grab-key window key state-mask attrs)
+ (apply (function xlib:grab-key)
+ `(,window ,key :modifiers ,state-mask ,@(attrs->keywords attrs))))
+
+(define (x-ungrab-key window key modifiers)
+ (xlib:ungrab-button window key :modifiers modifiers))
+
+(define (x-set-pointer-acceleration display val)
+ (xlib:change-pointer-control display :acceleration val))
+
+(define (x-set-pointer-threshold display val)
+ (xlib:change-pointer-control display :threshold val))
+
+(define (x-pointer-acceleration display)
+ (lisp:coerce (nth-value 0 (xlib:pointer-control display))
+ 'lisp:single-float))
+
+(define (x-pointer-threshold display)
+ (lisp:coerce (nth-value 1 (xlib:pointer-control display))
+ 'lisp:single-float))
+
+(define-attribute-setter pointer mapping)
+
+(define (x-set-keyboard-key-click-percent display v)
+ (xlib:change-keyboard-control display :key-click-percent v))
+
+(define (x-set-keyboard-bell-percent display v)
+ (xlib:change-keyboard-control display :bell-percent v))
+
+(define (x-set-keyboard-bell-pitch display v)
+ (xlib:change-keyboard-control display :bell-pitch v))
+
+(define (x-set-keyboard-bell-duration display v)
+ (xlib:change-keyboard-control display :bell-duration v))
+
+
+;;; Yes, leds are really counted from 1 rather than 0.
+
+(define (x-set-keyboard-led display v)
+ (declare (type integer v))
+ (do ((led 1 (1+ led))
+ (vv v (lisp:ash vv -1)))
+ ((> led 32))
+ (declare (type fixnum led) (type integer vv))
+ (xlib:change-keyboard-control display
+ :led led
+ :led-mode (if (lisp:logand vv 1) :on :off))))
+
+(define (x-set-keyboard-auto-repeat-mode display v)
+ (do ((key 0 (1+ key)))
+ ((>= key (lisp:length v)))
+ (declare (type fixnum key))
+ (xlib:change-keyboard-control display
+ :key key
+ :auto-repeat-mode (if (eqv? (the fixnum (lisp:aref v key)) 1) :on :off)
+ )))
+
+(define (x-keyboard-key-click-percent display)
+ (nth-value 0 (xlib:keyboard-control display)))
+
+(define (x-keyboard-bell-percent display)
+ (nth-value 1 (xlib:keyboard-control display)))
+
+(define (x-keyboard-bell-pitch display)
+ (nth-value 2 (xlib:keyboard-control display)))
+
+(define (x-keyboard-bell-duration display)
+ (nth-value 3 (xlib:keyboard-control display)))
+
+(define (x-keyboard-led display)
+ (nth-value 4 (xlib:keyboard-control display)))
+
+(define (x-keyboard-auto-repeat-mode display)
+ (nth-value 6 (xlib:keyboard-control display)))
+
+(define (x-modifier-mapping display)
+ (lisp:multiple-value-list (xlib:modifier-mapping display)))
+
+(define (x-set-modifier-mapping display l)
+ (let ((l1 (cddddr l)))
+ (xlib:set-modifier-mapping display
+ :shift (car l)
+ :lock (cadr l)
+ :control (caddr l)
+ :mod1 (cadddr l)
+ :mod2 (car l1)
+ :mod3 (cadr l1)
+ :mod4 (caddr l1)
+ :mod5 (cadddr l1))))
+
+(define (x-keysym-character display keysym state)
+ (let ((res (xlib:keysym->character display keysym state)))
+ (if (char? res) (char->integer res) '())))
+
+(define (x-keycode-character display keycode state)
+ (let ((res (xlib:keycode->character display keycode state)))
+ (if (char? res) (char->integer res) '())))
+
+(define-attribute-setter close-down mode)
+
+(define-attribute-setter access control)
+
+(define (x-screen-saver display)
+ (lisp:multiple-value-list (xlib:screen-saver display)))
+
+(define (x-set-screen-saver display ss)
+ (xlib:set-screen-saver display (car ss) (cadr ss) (caddr ss) (cadddr ss)))
+
+(define (slots->keywords slots)
+ (if (null slots) '()
+ `(,@(slot->keyword (car slots)) ,@(slots->keywords (cdr slots)))))
+
+(define (slot->keyword slot)
+ (let* ((tag (keyword-key slot))
+ (val (keyword-val slot)))
+ (case tag
+ (:pos `(:x ,(xpoint-x val) :y ,(xpoint-y val)))
+ (:root-pos `(:root-x ,(xpoint-x val) :root-y ,(xpoint-y val)))
+ (:size `(:width ,(xsize-w val) :height ,(xsize-h val)))
+ (:rect `(:x ,(xrect-x val) :y ,(xrect-y val)
+ :width ,(xrect-w val) :height ,(xrect-h val)))
+ (:graph-fun `(:major ,(car val) :minor ,(cdr val)))
+ (:visibility `(:state ,val))
+ (:property-state `(:state ,val))
+ (:message `(:data ,(car val) :type ,(cadr val) :format ,(caddr val)))
+ (else `(,tag ,val)))))
+
+(define (keywords->slots type keywords event)
+ (let* ((slots (keywords->slots1 type keywords))
+ (has-root-xy (memq type '(:key-press :key-release :button-press
+ :button-release :motion-notify
+ :enter-notify :leave-notify)))
+ (has-xy (or has-root-xy
+ (memq type '(:gravity-notify :reparent-notify))))
+ (has-graph-fun (memq type '(:graphics-exposure :no-exposure)))
+ (has-rect (memq type '(:exposure :graphics-exposure
+ :configure-notify
+ :create-notify :configure-request)))
+ (has-size (memq type '(:resize-request)))
+ (has-message (memq type '(:client-message))))
+ (when has-xy
+ (push (make-keyword :pos (x-event-pos event)) slots))
+ (when has-root-xy
+ (push (make-keyword :root-pos (x-event-root-pos event)) slots))
+ (when has-graph-fun
+ (push (make-keyword :graph-fun (x-event-graph-fun event)) slots))
+ (when has-rect
+ (push (make-keyword :rect (x-event-rect event)) slots))
+ (when has-size
+ (push (make-keyword :size (x-event-size event)) slots))
+ (when has-message
+ (push (make-keyword :message (x-event-message event)) slots))
+ slots))
+
+(define (keywords->slots1 type keywords)
+ (if (null? keywords)
+ '()
+ (if (memq (car keywords)
+ '(:x :y :width :height :root-x :root-y
+ :major :minor :type :data :format))
+ (keywords->slots1 type (cddr keywords))
+ (cons (keyword->slot type (car keywords) (cadr keywords))
+ (keywords->slots1 type (cddr keywords))))))
+
+(define (keyword->slot type slot val)
+ (if (eq? slot :state)
+ (case type
+ (:property-state (make-keyword :property-state val))
+ (:visibility (make-keyword :visibility val))
+ (else (make-keyword :state val)))
+ (make-keyword slot val)))
+
+(define (attrs->keywords attrs)
+ (if (null attrs)
+ '()
+ (nconc (attr->keyword (car attrs))
+ (attrs->keywords (cdr attrs)))))
+
+(define (attr->keyword attr)
+ (let* ((tag (keyword-key attr))
+ (val (keyword-val attr)))
+ (case tag
+ (:clip-origin `(:clip-x ,(xpoint-x val) :clip-y ,(xpoint-y val)))
+ (:dashes `(,tag ,(haskell-list->list/identity val)))
+ (:tile-origin `(:ts-x ,(xpoint-x val) :ts-y ,(xpoint-y val)))
+ (:size `(:width ,(xsize-w val) :height ,(xsize-h val)))
+ (:name `(:name ,(haskell-string->string val)))
+ (:hot-spot `(:x-hot ,(xpoint-x val) :y-hot ,(xpoint-y val)))
+ (else `(,tag ,val)))))
+
+(define (x-mutable-array-create inits)
+ (list->vector inits))
+
+(define (x-mutable-array-lookup a i)
+ (vector-ref a i))
+
+(define (x-mutable-array-update a i x)
+ (setf (vector-ref a i) x))
+
+(define (x-mutable-array-length a)
+ (vector-length a))
+
+(define (get-time-zone)
+ (nth-value 8 (lisp:get-decoded-time)))
+
+(define (decode-time time zone)
+ (multiple-value-bind (sec min hour date mon year week ds-p)
+ (if zone
+ (lisp:decode-universal-time time zone)
+ (lisp:decode-universal-time time))
+ (make-h-tuple
+ (list->haskell-list/identity (list sec min hour date mon year week))
+ ds-p)))
+
+(define (encode-time time zone)
+ (apply (function lisp:encode-universal-time)
+ (if (null? zone) time (append time (list zone)))))
+
+(define (get-run-time)
+ (/ (lisp:coerce (lisp:get-internal-run-time) 'lisp:single-float)
+ (lisp:coerce lisp:internal-time-units-per-second 'lisp:single-float)))
+
+(define (get-elapsed-time)
+ (/ (lisp:coerce (lisp:get-internal-real-time) 'lisp:single-float)
+ (lisp:coerce lisp:internal-time-units-per-second 'lisp:single-float)))
+
+(define (prim.thenio---1 x fn)
+ (lambda (state)
+ (declare (ignore state))
+ (let ((res (funcall x (box 'state))))
+ (format '#t "~A~%" res)
+ (funcall fn res (box 'state)))))
+
+(define-attribute-setter wm name)
+(define-attribute-setter wm icon-name)
diff --git a/progs/lib/X11/xlibprims.hi b/progs/lib/X11/xlibprims.hi
new file mode 100644
index 0000000..02d4163
--- /dev/null
+++ b/progs/lib/X11/xlibprims.hi
@@ -0,0 +1,1465 @@
+-- 4/13/93 add xTestEventMask, xTestStateMask
+-- 4/14/93 add xMArrayLength,
+-- xGetEventN
+-- 4/15/93 change xKeycodeCharacter
+-- add xKeysymCharacter
+-- add xHandleError
+-- add xError
+-- 4/27/93 Change Bool to XSwitch in XWinAttribute, XGCAttribute
+
+interface XLibPrims where
+
+import XLibTypes(
+ XDisplay, XScreen, XWindow, XGcontext, XPixmap,
+ XColormap, XCursor, XFont, XImage, XMaybe, XError,
+ XBitmap, XKeysymTable, XBitVec,
+ XPixarray, XByteVec, XAtom, XProperty,
+ XPixel, XDrawable, XTime, XSwitch,
+ XWindowPlace, XEventMode, XEventKind,
+ XWindowVisibility, XWindowStackMode,
+ XPropertyState, XMapReqType, XGraphFun,
+ XEvent, XEventType, XEventSlot, XEventMask,
+ XEventMaskKey, XStateMask, XStateMaskKey,
+ XWinAttribute,XGCAttribute, XImAttribute,
+ XGrabAttribute, XArcMode, XCapStyle,
+ XClipMask, XFillRule, XFillStyle,
+ XFunction, XJoinStyle, XLineStyle,
+ XSubwindowMode, XPoint, XSize, XRect,
+ XArc, XBitmapFormat, XByteOrder,
+ XPixmapFormat, XVisualInfo, XVisualClass,
+ XFillContent, XBackingStore, XGravity,
+ XWindowClass, XMapState, XImageData,
+ XImageFormat, XImageType, XDrawDirection,
+ XColor, XInputFocus, XGrabStatus,
+ XKeysym, XCloseDownMode, XScreenSaver)
+
+xHandleError :: (XError -> IO a) -> IO a -> IO a
+xError :: String -> IO a
+
+xEventType :: XEvent -> XEventType
+xEventWindow :: XEvent -> XWindow
+xEventEventWindow :: XEvent -> XWindow
+xEventCode :: XEvent -> Int
+xEventPos :: XEvent -> XPoint
+xEventState :: XEvent -> XStateMask
+xEventTime :: XEvent -> XTime
+xEventRoot :: XEvent -> XWindow
+xEventRootPos :: XEvent -> XPoint
+xEventChild :: XEvent -> (XMaybe XWindow)
+xEventSameScreenP :: XEvent -> Bool
+xEventHintP :: XEvent -> Bool
+xEventMode :: XEvent -> XEventMode
+xEventKind :: XEvent -> XEventKind
+xEventFocusP :: XEvent -> Bool
+xEventKeymap :: XEvent -> XBitVec
+xEventRequest :: XEvent -> XMapReqType
+xEventStart :: XEvent -> Int
+xEventCount :: XEvent -> Int
+xEventRect :: XEvent -> XRect
+xEventDrawable :: XEvent -> XDrawable
+xEventXGraphFun :: XEvent -> XGraphFun
+xEventPlace :: XEvent -> XWindowPlace
+xEventBorderWidth :: XEvent -> Int
+xEventAboveSibling :: XEvent -> (XMaybe XWindow)
+xEventOverrideRedirectP :: XEvent -> Bool
+xEventParent :: XEvent -> XWindow
+xEventConfigureP :: XEvent -> Bool
+xEventVisibility :: XEvent -> XWindowVisibility
+xEventNewP :: XEvent -> Bool
+xEventInstalledP :: XEvent -> Bool
+xEventStackMode :: XEvent -> XWindowStackMode
+xEventValueMask :: XEvent -> Int
+xEventSize :: XEvent -> XSize
+xEventMessage :: XEvent -> XProperty
+xEventPropertyState :: XEvent -> XPropertyState
+xEventAtom :: XEvent -> XAtom
+xEventSelection :: XEvent -> XAtom
+xEventTarget :: XEvent -> XAtom
+xEventProperty :: XEvent -> (XMaybe XAtom)
+xEventRequestor :: XEvent -> XWindow
+
+xSetEventMaskKey :: XEventMask -> XEventMaskKey -> XEventMask
+xClearEventMaskKey :: XEventMask -> XEventMaskKey -> XEventMask
+xTestEventMaskKey :: XEventMask -> XEventMaskKey -> Bool
+
+xSetStateMaskKey :: XStateMask -> XStateMaskKey -> XStateMask
+xClearStateMaskKey :: XStateMask -> XStateMaskKey -> XStateMask
+xTestStateMaskKey :: XStateMask -> XStateMaskKey -> Bool
+
+
+-- DISPLAYS
+
+-- open
+
+xOpenDisplay :: String -- host:display
+ -> IO XDisplay
+
+-- display attributes
+
+xDisplayAuthorizationData :: XDisplay -> String
+xDisplayAuthorizationName :: XDisplay -> String
+xDisplayBitmapFormat :: XDisplay -> XBitmapFormat
+xDisplayByteOrder :: XDisplay -> XByteOrder
+xDisplayDisplay :: XDisplay -> Int
+xSetDisplayErrorHandler :: XDisplay -> (XError -> IO ()) -> IO ()
+xDisplayImageLsbFirstP :: XDisplay -> Bool
+xDisplayMaxKeycode :: XDisplay -> Int
+xDisplayMaxRequestLength :: XDisplay -> Int
+xDisplayMinKeycode :: XDisplay -> Int
+xDisplayMotionBufferSize :: XDisplay -> Int
+xDisplayPixmapFormats :: XDisplay -> [XPixmapFormat]
+xDisplayProtocolMajorVersion :: XDisplay -> Int
+xDisplayProtocolMinorVersion :: XDisplay -> Int
+xDisplayResourceIdBase :: XDisplay -> Int
+xDisplayResourceIdMask :: XDisplay -> Int
+xDisplayRoots :: XDisplay -> [XScreen]
+xDisplayVendorName :: XDisplay -> String
+xDisplayReleaseNumber :: XDisplay -> Int
+
+-- output buffer
+
+xDisplayAfterFunction :: XDisplay -> XMaybe (IO ())
+xSetDisplayAfterFunction :: XDisplay -> XMaybe (IO ()) -> IO ()
+xDisplayForceOutput :: XDisplay -> IO ()
+xDisplayFinishOutput :: XDisplay -> IO ()
+
+-- close
+
+xCloseDisplay :: XDisplay -> IO ()
+
+-- SCREENS
+
+xScreenBackingStores :: XScreen -> XBackingStore
+xScreenBlackPixel :: XScreen -> XPixel
+xScreenDefaultColormap :: XScreen -> XColormap
+xScreenDepths :: XScreen -> [(Int, [XVisualInfo])]
+xScreenEventMaskAtOpen :: XScreen -> XEventMask
+xScreenSize :: XScreen -> XSize
+xScreenMMSize :: XScreen -> XSize
+xScreenMaxInstalledMaps :: XScreen -> Int
+xScreenMinInstalledMaps :: XScreen -> Int
+xScreenRoot :: XScreen -> XWindow
+xScreenRootDepth :: XScreen -> Int
+xScreenRootVisual :: XScreen -> Int
+xScreenSaveUndersP :: XScreen -> Bool
+xScreenWhitePixel :: XScreen -> XPixel
+
+-- WINDOWS AND PIXMAPS
+
+-- drawables
+
+xDrawableDisplay :: XDrawable -> XDisplay
+xDrawableEqual :: XDrawable -> XDrawable -> Bool
+xDrawableId :: XDrawable -> Int
+
+-- creating windows
+
+xCreateWindow :: XWindow -- parent
+ -> XRect -- (x,y,width,height)
+ -> [XWinAttribute] -- optional arguments
+ -> IO XWindow
+
+-- window attributes
+
+xWindowBorderWidth :: XWindow -> IO Int
+xSetWindowBorderWidth :: XWindow -> Int -> IO ()
+
+xDrawableDepth :: XDrawable -> Int
+
+xDrawableSize :: XDrawable -> IO XSize
+xDrawableResize :: XDrawable -> XSize -> IO ()
+
+xWindowPos :: XWindow -> IO XPoint
+xWindowMove :: XWindow -> XPoint -> IO ()
+
+xWindowAllEventMasks :: XWindow -> IO XEventMask
+xSetWindowBackground :: XWindow -> XFillContent -> IO ()
+
+xWindowBackingPixel :: XWindow -> IO XPixel
+xSetWindowBackingPixel :: XWindow -> XPixel -> IO ()
+
+xWindowBackingPlanes :: XWindow -> IO XPixel
+xSetWindowBackingPlanes :: XWindow -> XPixel -> IO ()
+
+xWindowBackingStore :: XWindow -> IO XBackingStore
+xSetWindowBackingStore :: XWindow -> XBackingStore -> IO ()
+
+xWindowBitGravity :: XWindow -> IO XGravity
+xSetWindowBitGravity :: XWindow -> XGravity -> IO ()
+
+xSetWindowBorder :: XWindow -> XFillContent -> IO ()
+
+xWindowClass :: XWindow -> XWindowClass
+
+xWindowColorMap :: XWindow -> IO (XMaybe XColormap)
+xSetWindowColorMap :: XWindow -> XColormap -> IO ()
+xWindowColormapInstalledP :: XWindow -> IO Bool
+
+xSetWindowCursor :: XWindow -> (XMaybe XCursor) -> IO ()
+
+xWindowDisplay :: XWindow -> XDisplay
+
+xWindowDoNotPropagateMask :: XWindow -> IO XEventMask
+xSetWindowDoNotPropagateMask :: XWindow -> XEventMask -> IO ()
+
+xWindowEqual :: XWindow -> XWindow -> Bool
+
+xWindowEventMask :: XWindow -> IO XEventMask
+xSetWindowEventMask :: XWindow -> XEventMask -> IO ()
+
+xWindowGravity :: XWindow -> IO XGravity
+xSetWindowGravity :: XWindow -> XGravity -> IO ()
+
+xWindowId :: XWindow -> Int
+
+xWindowMapState :: XWindow -> IO XMapState
+
+xWindowOverrideRedirect :: XWindow -> IO XSwitch
+xSetWindowOverrideRedirect :: XWindow -> XSwitch -> IO ()
+
+xSetWindowPriority :: XWindow -> XWindowStackMode -> IO ()
+
+xWindowSaveUnder :: XWindow -> IO XSwitch
+xSetWindowSaveUnder :: XWindow -> XSwitch -> IO ()
+
+xWindowVisual :: XWindow -> Int
+
+-- stacking order
+
+xCirculateWindowDown :: XWindow -> IO ()
+xCirculateWindowUp :: XWindow -> IO ()
+
+-- window hierarchy
+
+xDrawableRoot :: XDrawable -> IO XWindow
+xQueryTree :: XWindow -> IO ([XWindow], -- children
+ XMaybe XWindow,-- parent
+ XWindow) -- root
+
+xReparentWindow :: XWindow -- window
+ -> XWindow -- parent
+ -> XPoint -- (x,y)
+ -> IO ()
+
+xTranslateCoordinates :: XWindow -- source
+ -> XPoint -- (source-x,source-y)
+ -> XWindow -- destination
+ -> IO (XMaybe XPoint) -- (dest-x,dest-y)
+
+-- mapping windows
+
+xMapWindow :: XWindow -> IO ()
+xMapSubwindows :: XWindow -> IO ()
+xUnmapWindow :: XWindow -> IO ()
+xUnmapSubwindows :: XWindow -> IO ()
+
+-- destroying windows
+
+xDestroyWindow :: XWindow -> IO ()
+xDestroySubwindows :: XWindow -> IO ()
+
+-- pixmaps
+
+xCreatePixmap :: XSize -- (width,height)
+ -> Int -- depth
+ -> XDrawable -- drawable
+ -> IO XPixmap
+
+xFreePixmap :: XPixmap -> IO ()
+
+xPixmapDisplay :: XPixmap -> XDisplay
+xPixmapEqual :: XPixmap -> XPixmap -> Bool
+
+-- GRAPHICS CONTEXTS
+
+xCreateGcontext :: XDrawable -- drawable
+ -> [XGCAttribute] -- optional arguments
+ -> IO XGcontext
+
+xUpdateGcontext :: XGcontext -- old gcontext
+ -> [XGCAttribute] -- changes
+ -> IO () -- new gcontext
+
+xFreeGcontext :: XGcontext -> IO ()
+
+xGcontextDisplay :: XGcontext -> XDisplay
+xGcontextEqual :: XGcontext -> XGcontext -> Bool
+
+xGcontextId :: XGcontext -> Int
+
+xQueryBestStipple :: XSize -> XDrawable -> XSize
+xQueryBestTile :: XSize -> XDrawable -> XSize
+
+xCopyGcontext :: XGcontext -- source
+ -> XGcontext -- destination
+ -> IO ()
+
+-- GRAPHICS OPERATIONS
+
+xClearArea :: XWindow -- window
+ -> XRect -- (x,y,width,height)
+ -> Bool -- exposure-p
+ -> IO ()
+
+xCopyArea :: XDrawable -- source
+ -> XGcontext -- gcontext
+ -> XRect -- (src-x,src-y,w,h)
+ -> XDrawable -- destination
+ -> XPoint -- (dest-x,dest-y)
+ -> IO ()
+
+xCopyPlane :: XDrawable -- source
+ -> XGcontext -- gcontext
+ -> XPixel -- plane
+ -> XRect -- (src-x,src-y,w,h)
+ -> XDrawable -- destination
+ -> XPoint -- (dest-x,dest-y)
+ -> IO ()
+
+xDrawPoint :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XPoint -- (x,y)
+ -> IO ()
+
+xDrawPoints :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> [XPoint] -- points
+ -> IO ()
+
+xDrawLine :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XPoint -- (x1,y1)
+ -> XPoint -- (x2,y2)
+ -> IO ()
+
+xDrawLines :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> [XPoint] -- points
+ -> Bool -- fill-p
+ -> IO ()
+
+xDrawSegments :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> [(XPoint,XPoint)] -- segments
+ -> IO ()
+
+xDrawRectangle :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XRect -- (x,y,width,height)
+ -> Bool -- fill-p
+ -> IO ()
+
+xDrawRectangles :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> [XRect] -- rectangles
+ -> Bool -- fill-p
+ -> IO ()
+
+xDrawArc :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XArc -- (x,y,w,h,a1,a2)
+ -> Bool -- fill-p
+ -> IO ()
+
+xDrawArcs :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> [XArc] -- arcs
+ -> Bool -- fill-p
+ -> IO ()
+
+xDrawGlyph :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XPoint -- (x,y)
+ -> Char -- element
+ -> IO (XMaybe Int) -- width
+
+xDrawGlyphs :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XPoint -- (x,y)
+ -> String -- sequence
+ -> IO (XMaybe Int) -- width
+
+xDrawImageGlyph :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XPoint -- (x,y)
+ -> Char -- element
+ -> IO (XMaybe Int) -- width
+
+xDrawImageGlyphs :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XPoint -- (x,y)
+ -> String -- sequence
+ -> IO (XMaybe Int) -- width
+
+-- IMAGES
+
+xImageBlueMask :: XImage -> XMaybe XPixel
+xImageDepth :: XImage -> Int
+xImageGreenMask :: XImage -> XMaybe XPixel
+xImageSize :: XImage -> XSize
+xImageName :: XImage -> String
+xSetImageName :: XImage -> String -> IO ()
+xImageRedMask :: XImage -> XMaybe XPixel
+xImageHotSpot :: XImage -> XMaybe XPoint
+xSetImageHotSpot :: XImage -> XPoint -> IO ()
+
+-- XY-format images
+
+xImageXYBitmaps :: XImage -> IO [XBitmap]
+xSetImageXYBitmaps :: XImage -> [XBitmap] -> IO ()
+
+-- Z-format images
+
+xImageZBitsPerPixel :: XImage -> IO Int
+xsetImageZBitsPerPixel :: XImage -> Int -> IO ()
+xImageZPixarray :: XImage -> IO XPixarray
+xSetImageZPixarray :: XImage -> XPixarray -> IO ()
+
+-- image functions
+
+xCreateImage :: [XImAttribute] -> IO XImage
+xCopyImage :: XImage -- image
+ -> XRect -- (x,y,width,height)
+ -> XImageType -- result-type
+ -> XImage -- new-image
+
+xGetImage :: XDrawable -- drawable
+ -> XRect -- (x,y,width,height)
+ -> XPixel -- plane-mask
+ -> XImageFormat -- format
+ -> XImageType -- result-type
+ -> IO XImage -- image
+
+xPutImage :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XImage -- ximage
+ -> XPoint -- (src-x,src-y)
+ -> XRect -- (x,y,width,height)
+ -> IO ()
+
+-- image files
+
+xReadBitmapFile :: String -- pathname
+ -> IO XImage
+
+xWriteBitmapFile :: String -- pathname
+ -> XImage -> IO ()
+
+-- direct image transfer
+
+xGetRawImage :: XDrawable -- drawable
+ -> XRect -- (x,y,width,height)
+ -> XPixel -- plane-mask
+ -> XImageFormat -- format
+ -> IO XImageData -- data
+
+xPutRawImage :: XDrawable -- drawable
+ -> XGcontext -- gcontext
+ -> XImageData -- data
+ -> Int -- depth
+ -> XRect -- (x,y,width,height)
+ -> Int -- left-pad
+ -> XImageFormat -- format
+ -> IO ()
+
+-- FONTS
+
+-- opening fonts
+
+xOpenFont :: XDisplay -> String -> IO XFont
+xCloseFont :: XFont -> IO ()
+xDiscardFontInfo :: XFont -> IO ()
+
+-- listing fonts
+
+xFontPath :: XDisplay -> IO [String]
+xListFontNames :: XDisplay -> String -- pattern
+ -> IO [String]
+xListFonts :: XDisplay -> String -- pattern
+ -> IO [XFont]
+
+-- font attriburtes
+
+xFontAllCharExistsP :: XFont -> Bool
+xFontAscent :: XFont -> Int
+xFontDefaultChar :: XFont -> Int
+xFontDescent :: XFont -> Int
+xFontDirection :: XFont -> XDrawDirection
+xFontDisplay :: XFont -> XDisplay
+xFontEqual :: XFont -> XFont -> Int
+xFontId :: XFont -> Int
+
+xFontMaxByte1 :: XFont -> Int
+xFontMaxByte2 :: XFont -> Int
+xFontMaxChar :: XFont -> Int
+xFontMinByte1 :: XFont -> Int
+xFontMinByte2 :: XFont -> Int
+xFontMinChar :: XFont -> Int
+
+xFontName :: XFont -> String
+
+xFontMaxCharAscent :: XFont -> Int
+xFontMaxCharAttributes :: XFont -> Int
+xFontMaxCharDescent :: XFont -> Int
+xFontMaxCharLeftBearing :: XFont -> Int
+xFontMaxCharRightBearing :: XFont -> Int
+xFontMaxCharWidth :: XFont -> Int
+xFontMinCharAscent :: XFont -> Int
+xFontMinCharAttributes :: XFont -> Int
+xFontMinCharDescent :: XFont -> Int
+xFontMinCharLeftBearing :: XFont -> Int
+xFontMinCharRightBearing :: XFont -> Int
+xFontMinCharWidth :: XFont -> Int
+
+-- char attributes
+
+xCharAscent :: XFont -> Int -> XMaybe Int
+xCharAttributes :: XFont -> Int -> XMaybe Int
+xCharDescent :: XFont -> Int -> XMaybe Int
+xCharLeftBearing :: XFont -> Int -> XMaybe Int
+xCharRightBearing :: XFont -> Int -> XMaybe Int
+xCharWidth :: XFont -> Int -> XMaybe Int
+
+-- querying text size
+
+xTextWidth :: XFont -- font
+ -> String -- sequence
+ -> Int -- width
+
+-- COLORS
+
+-- creating colormaps
+
+xCreateColormap :: XVisualInfo -- visual
+ -> XWindow -- window
+ -> Bool -- alloc-p
+ -> IO XColormap
+
+xCopyColormapAndFree :: XColormap -> IO XColormap
+xFreeColormap :: XColormap -> IO ()
+
+-- installing colormaps
+
+xInstallColormap :: XColormap -> IO ()
+xInstalledColormaps :: XWindow -> IO [XColormap]
+xUnInstallColormap :: XColormap -> IO ()
+
+-- allocating colors
+
+xAllocColor :: XColormap -> XColor
+ -> IO (XPixel, -- pixel
+ XColor, -- screen-color
+ XColor) -- exact-color
+
+xAllocColorCells :: XColormap -- pixel
+ -> Int -- colors
+ -> Int -- planes
+ -> Bool -- contiguous
+ -> IO ([XPixel], -- pixels
+ [XPixel]) -- mask
+
+xAllocColorPlanes :: XColormap -- colormap
+ -> Int -- colors
+ -> Int -- reds
+ -> Int -- greens
+ -> Int -- blues
+ -> Bool -- contiguous-p
+ -> IO ([XPixel], -- pixel
+ XPixel, -- red-mask
+ XPixel, -- green-mask
+ XPixel) -- blue-mask
+
+xFreeColors :: XColormap -> [XPixel] -- pixels
+ -> XPixel -- plane-mask
+ -> IO ()
+
+-- finding colors
+
+xLookupColor :: XColormap -> String -- name
+ -> IO (XColor, -- screen-color
+ XColor) -- exact-color
+
+xQueryColors :: XColormap -> [XPixel] -- pixels
+ -> IO [XColor]
+
+-- changing colors
+
+xStoreColor :: XColormap -> XPixel -- pixel
+ -> XColor -- color
+ -> IO ()
+
+xStoreColors :: XColormap -- colormap
+ -> [(XPixel, XColor)] -- pixel-colors
+ -> IO ()
+
+-- colormap attributes
+
+xColormapDisplay :: XColormap -> XDisplay
+xColormapEqual :: XColormap -> XColormap -> Bool
+
+-- CURSORS
+
+xCreateCursor :: XPixmap -- source
+ -> (XMaybe XPixmap) -- mask
+ -> XPoint -- (x,y)
+ -> XColor -- foreground
+ -> XColor -- background
+ -> IO XCursor
+
+xCreateGlyphCursor :: (XFont, char) -- (src-font,src-char)
+ -> (XMaybe (XFont, Char)) -- (mask-font,mask-char)
+ -> XColor -- foreground
+ -> XColor -- background
+ -> IO XCursor
+
+xFreeCursor :: XCursor -> IO ()
+
+xQueryBestCursor :: XSize -- (width,height)
+ -> XDisplay -> IO XSize
+
+xRecolorCursor :: XCursor -> XColor -- foreground
+ -> XColor -- background
+ -> IO ()
+
+xCursorDisplay :: XCursor -> XDisplay
+xCursorEqual :: XCursor -> XCursor -> Bool
+
+-- ATOMS, PROPERTIES, AND SELECTIONS
+
+-- atoms
+
+xAtomName :: XDisplay -> Int -- atom-id
+ -> XAtom
+
+xFindAtom :: XDisplay -> XAtom -- atom-name
+ -> IO (XMaybe Int)
+
+xInternAtom :: XDisplay -> XAtom -- atom-name
+ -> IO (XMaybe Int)
+
+-- properties
+
+xChangeProperty :: XWindow -- window
+ -> XAtom -- property
+ -> XProperty -- (data,type,format)
+ -> IO ()
+
+xDeleteProperty :: XWindow -> XAtom -> IO ()
+xGetProperty :: XWindow -- window
+ -> XAtom -- property
+ -> IO XProperty -- (data,type,format)
+
+xListProperties :: XWindow -> IO [XAtom]
+xRotateProperties :: XWindow -- window
+ -> [XAtom] -- properties
+ -> Int -- delta
+ -> IO ()
+
+-- selections
+
+xConvertSelection :: XAtom -- selection
+ -> XAtom -- type
+ -> XWindow -- requester
+ -> XAtom -- property
+ -> (XMaybe XTime) -- time
+ -> IO ()
+
+xSelectionOwner :: XDisplay -- display
+ -> XAtom -- selection
+ -> IO (XMaybe XWindow)
+
+xSetSelectionOwner :: XDisplay -- display
+ -> XAtom -- selection
+ -> (XMaybe XTime) -- time
+ -> XWindow -- owner
+ -> IO ()
+
+-- EVENT
+
+-- Wait for the next event
+
+xGetEvent :: XDisplay -> IO XEvent
+
+-- managing the event queue
+
+xQueueEvent :: XDisplay -> XEvent -> Bool -- append-p
+ -> IO ()
+
+xEventListen :: XDisplay -> IO Int -- # of events in queue
+
+-- sending events
+
+xSendEvent :: XWindow -- window
+ -> XEvent -- event key and slots
+ -> XEventMask -- event-mask
+ -> IO ()
+
+-- pointer position
+
+xGlobalPointerPosition :: XDisplay -> IO XPoint
+xPointerPosition :: XWindow -> IO (XMaybe XPoint)
+xMotionEvents :: XWindow -> XTime -> XTime -> IO [XPoint]
+xWarpPointer :: XWindow -> XPoint -> IO ()
+
+-- keyboard input focus
+
+xSetInputFocus :: XDisplay -- display
+ -> XInputFocus -- focus
+ -> XInputFocus -- revert-to
+ -> (XMaybe XTime) -- time
+ -> IO ()
+
+xInputFucus :: XDisplay -> IO (XInputFocus, -- focus
+ XInputFocus) -- revert-to
+
+-- grabbing the pointer
+
+xGrabPointer :: XWindow -- window
+ -> XEventMask -- event-mask
+ -> [XGrabAttribute] -- optional attributes
+ -> XMaybe XTime -- time
+ -> IO XGrabStatus
+
+xUngrabPointer :: XDisplay -> XMaybe XTime -> IO ()
+
+xChangeActivePointerGrab :: XDisplay -> XEventMask -- event-mask
+ -> [XGrabAttribute] -- cursor
+ -> XMaybe XTime -> IO ()
+
+-- grabbing a button
+
+xGrabButton :: XWindow -- window
+ -> Int -- button
+ -> XEventMask -- event-mask
+ -> XStateMask -- modifiers
+ -> [XGrabAttribute] -- optional attributes
+ -> IO ()
+
+xUngrabButton :: XWindow -> Int -- button
+ -> XStateMask -- modifiers
+ -> IO ()
+
+-- grabbing the keyboard
+
+xGrabKeyboard :: XWindow -- window
+ -> [XGrabAttribute] -- optional attributes
+ -> XMaybe XTime -- time
+ -> IO XGrabStatus
+
+xUngrabkeyboard :: XDisplay -> XMaybe XTime -> IO ()
+
+-- grabbing a key
+
+xGrabKey :: XWindow -- window
+ -> Int -- key
+ -> XStateMask -- modifiers
+ -> [XGrabAttribute] -- optional attributes
+ -> IO ()
+
+xUngrabKey :: XWindow -> Int -> XStateMask -- modifiers
+ -> IO ()
+
+-- CONTROL FUNCTIONS
+
+-- grabbing the server
+
+xGrabServer :: XDisplay -> IO ()
+xUngrabServer :: XDisplay -> IO ()
+
+-- pointer control
+
+xSetPointerAcceleration :: XDisplay -> Float -> IO ()
+xSetPointerThreshold :: XDisplay -> Float -> IO ()
+xPointerAcceleration :: XDisplay -> IO Float
+xPointerThreshold :: XDisplay -> IO Float
+xSetPointerMapping :: XDisplay -> [Int] -> IO ()
+xPointerMapping :: XDisplay -> IO [Int]
+
+-- keyboard control
+
+xBell :: XDisplay -> Int -> IO ()
+
+xSetKeyboardKeyClickPercent :: XDisplay -> Int -> IO ()
+xSetKeyboardBellPercent :: XDisplay -> Int -> IO ()
+xSetKeyboardBellPitch :: XDisplay -> Int -> IO ()
+xSetKeyboardBellDuration :: XDisplay -> Int -> IO ()
+xSetKeyboardLed :: XDisplay -> Integer -> IO ()
+xSetKeyboardAutoRepeatMode :: XDisplay -> XBitVec -> IO ()
+
+xKeyboardKeyClickPercent :: XDisplay -> IO Int
+xKeyboardBellPercent :: XDisplay -> IO Int
+xKeyboardBellPitch :: XDisplay -> IO Int
+xKeyboardBellDuration :: XDisplay -> IO Int
+
+xKeyboardLed :: XDisplay -> IO Integer
+xKeyboardAutoRepeatMode :: XDisplay -> IO XBitVec
+
+xModifierMapping :: XDisplay -> IO [[Int]]
+xSetModifierMapping :: XDisplay -> [[Int]] -> IO (XMaybe ())
+xQueryKeymap :: XDisplay -> IO XBitVec
+
+-- keyboard mapping
+
+xChangeKeyboardMapping :: XDisplay -- display
+ -> XKeysymTable -- keysyms
+ -> IO ()
+
+xKeyboardMapping :: XDisplay -- display
+ -> IO XKeysymTable -- mappings
+
+xKeycodeKeysym :: XDisplay -- display
+ -> Int -- keycode
+ -> Int -- keysym-index
+ -> IO XKeysym
+
+xKeysymCharacter :: XDisplay -- display
+ -> XKeysym -- keysym
+ -> XStateMask -- state
+ -> IO (XMaybe Char)
+
+xKeycodeCharacter :: XDisplay -- display
+ -> Int -- keycode
+ -> XStateMask -- state
+ -> IO (XMaybe Char)
+
+-- client termination
+
+xAddToSaveSet :: XWindow -> IO ()
+xCloseDownMode :: XDisplay -> IO XCloseDownMode
+xSetCloseDownMode :: XDisplay -> XCloseDownMode -> IO ()
+xKillClient :: XDisplay -> Int -> IO ()
+xKillTemporaryClients :: XDisplay -> IO ()
+xRemoveFromSaveSet :: XWindow -> IO ()
+
+-- managing host access
+
+xAccessControl :: XDisplay -> IO Bool
+xSetAccessControl :: XDisplay -> Bool -> IO ()
+xAccessHosts :: XDisplay -> IO [String]
+xAddAccessHost :: XDisplay -> String -> IO ()
+xRemoveAccessHost :: XDisplay -> String -> IO ()
+
+-- screen saver
+
+xActivateScreenSaver :: XDisplay -> IO ()
+xResetScreenSaver :: XDisplay -> IO ()
+
+xScreenSaver :: XDisplay -> IO XScreenSaver
+xSetScreenSaver :: XDisplay -> XScreenSaver -> IO ()
+
+{-#
+
+
+xHandleError :: LispName("x-handle-error")
+xError :: LispName("xlib::x-error")
+
+xEventType :: LispName("sel-event-type")
+
+xEventWindow :: LispName ("x-event-window")
+xEventEventWindow :: LispName ("x-event-event-window")
+xEventCode :: LispName ("x-event-code")
+xEventPos :: LispName ("x-event-pos")
+xEventState :: LispName ("x-event-state")
+xEventTime :: LispName ("x-event-time")
+xEventRoot :: LispName ("x-event-root")
+xEventRootPos :: LispName ("x-event-root-pos")
+xEventChild :: LispName ("x-event-child")
+xEventSameScreenP :: LispName ("x-event-same-screen-p")
+xEventHintP :: LispName ("x-event-hint-p")
+xEventMode :: LispName ("x-event-mode")
+xEventKind :: LispName ("x-event-kind")
+xEventFocusP :: LispName ("x-event-focus-p")
+xEventKeymap :: LispName ("x-event-keymap")
+xEventRequest :: LispName ("x-event-request")
+xEventStart :: LispName ("x-event-start")
+xEventCount :: LispName ("x-event-count")
+xEventRect :: LispName ("x-event-rect")
+xEventDrawable :: LispName ("x-event-drawable")
+xEventXGraphFun :: LispName ("x-event-graph-fun")
+xEventPlace :: LispName ("x-event-place")
+xEventBorderWidth :: LispName ("x-event-border-width")
+xEventAboveSibling :: LispName ("x-event-above-sibling")
+xEventOverrideRedirectP :: LispName ("x-event-override-redirect-p")
+xEventParent :: LispName ("x-event-parent")
+xEventConfigureP :: LispName ("x-event-configure-p")
+xEventVisibility :: LispName ("x-event-state")
+xEventNewP :: LispName ("x-event-new-p")
+xEventInstalledP :: LispName ("x-event-installed-p")
+xEventStackMode :: LispName ("x-event-stack-mode")
+xEventValueMask :: LispName ("x-event-value-mask")
+xEventSize :: LispName ("x-event-size")
+xEventMessage :: LispName ("x-event-message")
+xEventPropertyState :: LispName ("x-event-state")
+xEventAtom :: LispName ("x-event-atom")
+xEventSelection :: LispName ("x-event-selection")
+xEventTarget :: LispName ("x-event-target")
+xEventProperty :: LispName ("x-event-property")
+xEventRequestor :: LispName ("x-event-requestor")
+
+
+xSetEventMaskKey :: LispName ("x-set-event-mask-key")
+xClearEventMaskKey :: LispName ("x-clear-event-mask-key")
+xTestEventMaskKey :: LispName ("x-test-event-mask-key")
+
+xSetStateMaskKey :: LispName ("x-set-state-mask-key")
+xClearStateMaskKey :: LispName ("x-clear-state-mask-key")
+xTestStateMaskKey :: LispName ("x-test-state-mask-key")
+
+-- DISPLAYS
+
+-- open
+
+xOpenDisplay :: LispName("x-open-display")
+
+-- display attributes
+
+xDisplayAuthorizationData :: LispName("xlib:display-authorization-data")
+xDisplayAuthorizationName :: LispName("xlib:display-authorization-name")
+xDisplayBitmapFormat :: LispName("xlib:display-bitmap-format")
+xDisplayByteOrder :: LispName("xlib:display-byte-order")
+xDisplayDisplay :: LispName("xlib:display-display")
+xSetDisplayErrorHandler :: LispName("x-set-display-error-handler")
+xDisplayImageLsbFirstP :: LispName("xlib:display-image-lsb-first-p")
+xDisplayMaxKeycode :: LispName("xlib:display-max-keycode")
+xDisplayMaxRequestLength :: LispName("xlib:display-max-request-length")
+xDisplayMinKeycode :: LispName("xlib:display-min-keycode")
+xDisplayMotionBufferSize :: LispName("xlib:display-motion-buffer-size")
+xDisplayPixmapFormats :: LispName("xlib:display-pixmap-formats")
+xDisplayProtocolMajorVersion :: LispName("xlib:display-protocol-major-version")
+xDisplayProtocolMinorVersion :: LispName("xlib:display-protocol-minor-version")
+xDisplayResourceIdBase :: LispName("xlib:display-resource-id-base")
+xDisplayResourceIdMask :: LispName("xlib:display-resource-id-mask")
+xDisplayRoots :: LispName("xlib:display-roots")
+xDisplayVendorName :: LispName("xlib:display-vendor-name")
+xDisplayReleaseNumber :: LispName("xlib:display-release-number")
+
+-- output buffer
+
+xDisplayAfterFunction :: LispName("xlib:display-after-function")
+xSetDisplayAfterFunction :: LispName("x-set-display-after-function")
+xDisplayForceOutput :: LispName("xlib:display-force-output")
+xDisplayFinishOutput :: LispName("xlib:display-finish-output")
+
+-- close
+
+xCloseDisplay :: LispName("xlib:close-display")
+
+-- SCREENS
+
+xScreenBackingStores :: LispName("xlib:screen-backing-stores")
+xScreenBlackPixel :: LispName("xlib:screen-black-pixel")
+xScreenDefaultColormap :: LispName("xlib:screen-default-colormap")
+xScreenDepths :: LispName("x-screen-depths")
+xScreenEventMaskAtOpen :: LispName("xlib:screen-event-mask-at-open")
+xScreenSize :: LispName("x-screen-size")
+xScreenMMSize :: LispName("x-screen-mmsize")
+xScreenMaxInstalledMaps :: LispName("xlib:screen-max-installed-maps")
+xScreenMinInstalledMaps :: LispName("xlib:screen-min-installed-maps")
+xScreenRoot :: LispName("xlib:screen-root")
+xScreenRootDepth :: LispName("xlib:screen-root-depth")
+xScreenRootVisual :: LispName("xlib:screen-root-visual")
+xScreenSaveUndersP :: LispName("xlib:screen-save-unders-p")
+xScreenWhitePixel :: LispName("xlib:screen-white-pixel")
+
+-- WINDOWS AND PIXMAPS
+
+-- drawables
+
+xDrawableDisplay :: LispName("xlib:drawable-display")
+xDrawableEqual :: LispName("xlib:drawable-equal")
+xDrawableId :: LispName("xlib:drawable-id")
+
+-- creating windows
+
+xCreateWindow :: LispName("x-create-window")
+
+-- window attributes
+
+xWindowBorderWidth :: LispName("xlib:drawable-border-width")
+xSetWindowBorderWidth :: LispName("x-set-drawable-border-width")
+
+xDrawableDepth :: LispName("xlib:drawable-depth")
+
+xDrawableSize :: LispName("x-drawable-size")
+xDrawableResize :: LispName("x-drawable-resize")
+
+xWindowPos :: LispName("x-window-pos")
+xWindowMove :: LispName("x-window-move")
+
+xWindowAllEventMasks :: LispName("xlib:window-all-event-masks")
+
+xSetWindowBackground :: LispName("x-set-window-background")
+
+xWindowBackingPixel :: LispName("xlib:window-backing-pixel")
+xSetWindowBackingPixel :: LispName("x-set-window-backing-pixel")
+
+xWindowBackingPlanes :: LispName("xlib:window-backing-planes")
+xSetWindowBackingPlanes :: LispName("x-set-window-backing-planes")
+
+xWindowBackingStore :: LispName("xlib:window-backing-store")
+xSetWindowBackingStore :: LispName("x-set-window-backing-store")
+
+xWindowBitGravity :: LispName("xlib:window-bit-gravity")
+xSetWindowBitGravity :: LispName("x-set-window-bit-gravity")
+
+xSetWindowBorder :: LispName("x-set-window-border")
+
+xWindowClass :: LispName("xlib:window-class")
+
+xWindowColorMap :: LispName("xlib:window-colormap")
+xSetWindowColorMap :: LispName("x-set-window-colormap")
+xWindowColormapInstalledP :: LispName("xlib:window-colormap-installed-p")
+
+xSetWindowCursor :: LispName("x-set-window-cursor")
+
+xWindowDisplay :: LispName("xlib:window-display")
+
+xWindowDoNotPropagateMask :: LispName("xlib:window-do-not-propagate-mask")
+xSetWindowDoNotPropagateMask :: LispName("x-set-window-do-not-propagate-mask")
+
+xWindowEqual :: LispName("xlib:window-equal")
+
+xWindowEventMask :: LispName("xlib:window-event-mask")
+xSetWindowEventMask :: LispName("x-set-window-event-mask")
+
+xWindowGravity :: LispName("xlib:window-gravity")
+xSetWindowGravity :: LispName("x-set-window-gravity")
+
+xWindowId :: LispName("xlib:window-id")
+
+xWindowMapState :: LispName("xlib:window-map-state")
+
+xWindowOverrideRedirect :: LispName("xlib:window-override-redirect")
+xSetWindowOverrideRedirect :: LispName("x-set-window-override-redirect")
+
+xSetWindowPriority :: LispName("x-set-window-priority")
+
+xWindowSaveUnder :: LispName("xlib:window-save-under")
+xSetWindowSaveUnder :: LispName("x-set-window-save-under")
+xWindowVisual :: LispName("xlib:window-visual")
+
+-- stacking order
+
+xCirculateWindowDown :: LispName("xlib:circulate-window-down")
+xCirculateWindowUp :: LispName("xlib:circulate-window-up")
+
+-- window hierarchy
+
+xDrawableRoot :: LispName("xlib:drawable-root")
+xQueryTree :: LispName("x-query-tree")
+
+xReparentWindow :: LispName("x-reparent-window")
+
+xTranslateCoordinates :: LispName("x-translate-coordinates")
+
+-- mapping windows
+
+xMapWindow :: LispName("xlib:map-window")
+xMapSubwindows :: LispName("xlib:map-subwindows")
+xUnmapWindow :: LispName("xlib:unmap-window")
+xUnmapSubwindows :: LispName("xlib:unmap-subwindows")
+
+-- destroying windows
+
+xDestroyWindow :: LispName("xlib:destroy-window")
+xDestroySubwindows :: LispName("xlib:destroy-subwindows")
+
+-- pixmaps
+
+xCreatePixmap :: LispName("x-create-pixmap")
+xFreePixmap :: LispName("xlib:free-pixmap")
+xPixmapDisplay :: LispName("xlib:pixmap-display")
+xPixmapEqual :: LispName("xlib:pixmap-equal")
+
+-- GRAPHICS CONTEXTS
+
+xCreateGcontext :: LispName("x-create-gcontext")
+xUpdateGcontext :: LispName("x-update-gcontext")
+xFreeGcontext :: LispName("xlib:free-gcontext")
+
+xGcontextDisplay :: LispName("xlib:gcontext-display")
+xGcontextEqual :: LispName("xlib:gcontext-equal")
+
+xGcontextId :: LispName("xlib:gcontext-id")
+
+xQueryBestStipple :: LispName("x-query-best-stipple")
+xQueryBestTile :: LispName("x-query-best-tile")
+
+xCopyGcontext :: LispName("xlib:copy-gcontext")
+
+-- GRAPHICS OPERATIONS
+
+xClearArea :: LispName("x-clear-area")
+xCopyArea :: LispName("x-copy-area")
+xCopyPlane :: LispName("x-copy-plane")
+xDrawPoint :: LispName("x-draw-point")
+xDrawPoints :: LispName("x-draw-points")
+xDrawLine :: LispName("x-draw-line")
+xDrawLines :: LispName("x-draw-lines")
+xDrawSegments :: LispName("x-draw-segments")
+xDrawRectangle :: LispName("x-draw-rectangle")
+xDrawRectangles :: LispName("x-draw-rectangles")
+xDrawArc :: LispName("x-draw-arc")
+xDrawArcs :: LispName("x-draw-arcs")
+xDrawGlyph :: LispName("x-draw-glyph")
+xDrawGlyphs :: LispName("x-draw-glyphs")
+xDrawImageGlyph :: LispName("x-draw-image-glyph")
+xDrawImageGlyphs :: LispName("x-draw-image-glyphs")
+
+-- IMAGES
+
+xImageBlueMask :: LispName("xlib:image-blue-mask")
+xImageDepth :: LispName("xlib:image-depth")
+xImageGreenMask :: LispName("xlib:image-green-mask")
+xImageSize :: LispName("x-image-size")
+xImageName :: LispName("x-image-name")
+xSetImageName :: LispName("x-set-image-name")
+xImageRedMask :: LispName("xlib:image-red-mask")
+xImageHotSpot :: LispName("x-image-hot-spot")
+xSetImageHotSpot :: LispName("x-set-image-hot-spot")
+
+-- XY-format images
+
+xImageXYBitmaps :: LispName("xlib:image-xy-bitmap-list")
+xSetImageXYBitmaps :: LispName("x-set-image-xy-bitmap-list")
+
+-- Z-format images
+
+xImageZBitsPerPixel :: LispName("xlib:image-z-bits-per-pixel")
+xsetImageZBitsPerPixel :: LispName("x-set-image-z-bits-per-pixel")
+xImageZPixarray :: LispName("xlib:image-z-pixarray")
+xSetImageZPixarray :: LispName("x-set-image-z-pixarray")
+
+-- image functions
+
+xCreateImage :: LispName("x-create-image")
+xCopyImage :: LispName("x-copy-image")
+xGetImage :: LispName("x-get-image")
+xPutImage :: LispName("x-put-image")
+
+-- image files
+
+xReadBitmapFile :: LispName("xlib:read-bitmap-file")
+xWriteBitmapFile :: LispName("xlib:write-bitmap-file")
+
+-- direct image transfer
+
+xGetRawImage :: LispName("x-get-raw-image")
+xPutRawImage :: LispName("x-put-raw-image")
+
+-- FONTS
+
+-- opening fonts
+
+xOpenFont :: LispName ("xlib:open-font")
+xCloseFont :: LispName ("xlib:close-font")
+xDiscardFontInfo :: LispName ("xlib:discard-font-info")
+
+-- listing fonts
+
+xFontPath :: LispName ("xlib:font-path")
+xListFontNames :: LispName ("xlib:list-font-names")
+xListFonts :: LispName ("xlib:list-fonts")
+
+-- font attriburtes
+
+xFontAllCharExistsP :: LispName ("xlib:font-all-chars-exist-p")
+xFontAscent :: LispName ("xlib:font-ascent")
+xFontDefaultChar :: LispName ("xlib:font-default-char")
+xFontDescent :: LispName ("xlib:font-descent")
+xFontDirection :: LispName ("xlib:font-direction")
+xFontDisplay :: LispName ("xlib:font-display")
+xFontEqual :: LispName ("xlib:font-equal")
+xFontId :: LispName ("xlib:font-id")
+
+xFontMaxByte1 :: LispName ("xlib:font-max-byte1")
+xFontMaxByte2 :: LispName ("xlib:font-max-byte2")
+xFontMaxChar :: LispName ("xlib:font-max-char")
+xFontMinByte1 :: LispName ("xlib:font-min-byte1")
+xFontMinByte2 :: LispName ("xlib:font-min-byte2")
+xFontMinChar :: LispName ("xlib:font-min-char")
+
+xFontName :: LispName ("x-font-name")
+
+xFontMaxCharAscent :: LispName ("xlib:max-char-ascent")
+xFontMaxCharAttributes :: LispName ("xlib:max-char-attributes")
+xFontMaxCharDescent :: LispName ("xlib:max-char-descent")
+xFontMaxCharLeftBearing :: LispName ("xlib:max-char-left-bearing")
+xFontMaxCharRightBearing :: LispName ("xlib:max-char-right-bearing")
+xFontMaxCharWidth :: LispName ("xlib:max-char-width")
+xFontMinCharAscent :: LispName ("xlib:min-char-ascent")
+xFontMinCharAttributes :: LispName ("xlib:min-char-attributes")
+xFontMinCharDescent :: LispName ("xlib:min-char-descent")
+xFontMinCharLeftBearing :: LispName ("xlib:min-char-left-bearing")
+xFontMinCharRightBearing :: LispName ("xlib:min-char-right-bearing")
+xFontMinCharWidth :: LispName ("xlib:min-char-width")
+
+-- char attributes
+
+xCharAscent :: LispName ("xlib:char-ascent")
+xCharAttributes :: LispName ("xlib:char-attributes")
+xCharDescent :: LispName ("xlib:char-descent")
+xCharLeftBearing :: LispName ("xlib:char-left-bearing")
+xCharRightBearing :: LispName ("xlib:char-right-bearing")
+xCharWidth :: LispName ("xlib:char-width")
+
+-- querying text size
+
+xTextWidth :: LispName ("xlib:text-width")
+
+-- COLORS
+
+-- creating colormaps
+
+xCreateColormap :: LispName ("xlib:create-colormap")
+xCopyColormapAndFree :: LispName ("xlib:copy-colormap-and-free")
+xFreeColormap :: LispName ("xlib:free-colormap")
+
+-- installing colormaps
+
+xInstallColormap :: LispName ("xlib:install-colormap")
+xInstalledColormaps :: LispName ("xlib:installed-colormaps")
+xUnInstallColormap :: LispName ("xlib:uninstall-colormap")
+
+-- allocating colors
+
+xAllocColor :: LispName ("x-alloc-color")
+xAllocColorCells :: LispName ("x-alloc-color-cells")
+xAllocColorPlanes :: LispName ("x-alloc-color-planes")
+
+xFreeColors :: LispName ("xlib:free-colors")
+
+-- finding colors
+
+xLookupColor :: LispName ("x-lookup-color")
+xQueryColors :: LispName ("xlib:query-colors")
+
+-- changing colors
+
+xStoreColor :: LispName ("xlib:store-color")
+xStoreColors :: LispName ("x-store-colors")
+
+-- colormap attributes
+
+xColormapDisplay :: LispName ("xlib:colormap-display")
+xColormapEqual :: LispName ("xlib:colormap-equal")
+
+-- CURSORS
+
+xCreateCursor :: LispName ("x-create-cursor")
+xCreateGlyphCursor :: LispName ("x-create-glyph-cursor")
+xFreeCursor :: LispName ("xlib:free-cursor")
+
+xQueryBestCursor :: LispName ("x-query-best-cursor")
+xRecolorCursor :: LispName ("xlib:recolor-cursor")
+
+xCursorDisplay :: LispName ("xlib:cursor-display")
+xCursorEqual :: LispName ("xlib:cursor-equal")
+
+-- ATOMS, PROPERTIES, AND SELECTIONS
+
+-- atoms
+
+xAtomName :: LispName ("xlib:atom-name")
+xFindAtom :: LispName ("xlib:find-atom")
+xInternAtom :: LispName ("xlib:intern-atom")
+
+-- properties
+
+xChangeProperty :: LispName ("x-change-property")
+xDeleteProperty :: LispName ("xlib:delete-property")
+xGetProperty :: LispName ("x-get-property")
+xListProperties :: LispName ("xlib:list-properties")
+xRotateProperties :: LispName ("xlib:rotate-properties")
+
+-- selections
+
+xConvertSelection :: LispName ("x-convert-selection")
+xSelectionOwner :: LispName ("xlib:selection-owner")
+xSetSelectionOwner :: LispName ("x-set-selection-owner")
+
+-- EVENT
+
+-- Wait for the next event
+
+xGetEvent :: LispName ("x-get-event")
+
+-- managing the event queue
+
+xQueueEvent :: LispName ("x-queue-event")
+xEventListen :: LispName ("x-event-listen")
+
+-- sending events
+
+xSendEvent :: LispName ("x-send-event")
+
+-- pointer position
+
+xGlobalPointerPosition :: LispName ("x-global-pointer-position")
+xPointerPosition :: LispName ("x-pointer-position")
+xMotionEvents :: LispName ("x-motion-events")
+xWarpPointer :: LispName ("x-warp-pointer")
+
+-- keyboard input focus
+
+xSetInputFocus :: LispName ("x-set-input-focus")
+xInputFucus :: LispName ("x-input-focus")
+
+-- grabbing the pointer
+
+xGrabPointer :: LispName ("x-grab-pointer")
+xUngrabPointer :: LispName ("x-ungrab-pointer")
+xChangeActivePointerGrab :: LispName ("x-change-active-pointer-grab")
+
+-- grabbing a button
+
+xGrabButton :: LispName ("x-grab-button")
+xUngrabButton :: LispName ("x-ungrab-button")
+
+-- grabbing the keyboard
+
+xGrabKeyboard :: LispName ("x-grab-keyboard")
+xUngrabkeyboard :: LispName ("x-ungrab-keyboard")
+
+-- grabbing a key
+
+xGrabKey :: LispName ("x-grab-key")
+xUngrabKey :: LispName ("x-ungrab-key")
+
+-- CONTROL FUNCTIONS
+
+-- grabbing the server
+
+xGrabServer :: LispName ("xlib:grab-server")
+xUngrabServer :: LispName ("xlib:ungrab-server")
+
+-- pointer control
+
+xSetPointerAcceleration :: LispName ("x-set-pointer-acceleration")
+xSetPointerThreshold :: LispName ("x-set-pointer-threshold")
+xPointerAcceleration :: LispName ("x-pointer-acceleration")
+xPointerThreshold :: LispName ("x-pointer-threshold")
+xSetPointerMapping :: LispName ("x-set-pointer-mapping")
+xPointerMapping :: LispName ("xlib:pointer-mapping")
+
+-- keyboard control
+
+xBell :: LispName ("xlib:bell")
+
+xSetKeyboardKeyClickPercent :: LispName ("x-set-keyboard-key-click-percent")
+xSetKeyboardBellPercent :: LispName ("x-set-keyboard-bell-percent")
+xSetKeyboardBellPitch :: LispName ("x-set-keyboard-bell-pitch")
+xSetKeyboardBellDuration :: LispName ("x-set-keyboard-bell-duration")
+xSetKeyboardLed :: LispName ("x-set-keyboard-led")
+xSetKeyboardAutoRepeatMode :: LispName ("x-set-keyboard-auto-repeat-mode")
+
+xKeyboardKeyClickPercent :: LispName ("x-keyboard-key-click-percent")
+xKeyboardBellPercent :: LispName ("x-keyboard-bell-percent")
+xKeyboardBellPitch :: LispName ("x-keyboard-bell-pitch")
+xKeyboardBellDuration :: LispName ("x-keyboard-bell-duration")
+xKeyboardLed :: LispName ("x-keyboard-led")
+xKeyboardAutoRepeatMode :: LispName ("x-keyboard-auto-repeat-mode")
+
+xModifierMapping :: LispName ("x-modifier-mapping")
+xSetModifierMapping :: LispName ("x-set-modifier-mapping")
+xQueryKeymap :: LispName ("xlib:query-keymap")
+
+-- keyboard mapping
+
+xChangeKeyboardMapping :: LispName ("xlib:change-keyboard-mapping")
+xKeyboardMapping :: LispName ("xlib:keyboard-mapping")
+
+xKeycodeKeysym :: LispName ("xlib:keycode->keysym")
+xKeysymCharacter :: LispName ("x-keysym-character")
+xKeycodeCharacter :: LispName ("x-keycode-character")
+
+-- client termination
+
+xAddToSaveSet :: LispName ("xlib:add-to-save-set")
+xCloseDownMode :: LispName ("xlib:close-down-mode")
+xSetCloseDownMode :: LispName ("x-set-close-down-mode")
+xKillClient :: LispName ("xlib:kill-client")
+xKillTemporaryClients :: LispName ("xlib:kill-temporary-clients")
+xRemoveFromSaveSet :: LispName ("xlib:remove-from-save-set")
+
+-- managing host access
+
+xAccessControl :: LispName ("xlib:access-control")
+xSetAccessControl :: LispName ("x-set-access-control")
+xAccessHosts :: LispName ("xlib:access-hosts")
+xAddAccessHost :: LispName ("xlib:add-access-host")
+xRemoveAccessHost :: LispName ("xlib:remove-access-host")
+
+-- screen saver
+
+xActivateScreenSaver :: LispName ("xlib:activate-screen-saver")
+xResetScreenSaver :: LispName ("xlib:reset-screen-saver")
+xScreenSaver :: LispName ("x-screen-saver")
+xSetScreenSaver :: LispName ("x-set-screen-saver")
+
+#-}
+
+data XMArray a
+
+xMArrayCreate :: [a] -> IO (XMArray a)
+xMArrayLookup :: XMArray a -> Int -> IO a
+xMArrayUpdate :: XMArray a -> Int -> a -> IO ()
+xMArrayLength :: XMArray a -> Int
+
+{-#
+xMArrayCreate :: LispName("x-mutable-array-create")
+xMArrayLookup :: LispName("x-mutable-array-lookup")
+xMArrayUpdate :: LispName("x-mutable-array-update")
+xMArrayLength :: LispName("x-mutable-array-length")
+#-}
+
+
+xprint :: a -> IO ()
+{-#
+xprint :: LispName ("x-print")
+#-}
+
+-- decoded time format:
+-- ([second, minute, hour, date, month, year, day-of-week],
+-- daylight-saving-time-p)
+-- time format to encode:
+-- [second, minute, hour, date, month, year]
+
+data TimeZone = WestOfGMT Int {-# STRICT #-}
+ | CurrentZone
+
+getTime :: IO Integer
+getTimeZone :: IO Int
+decodeTime :: Integer -> TimeZone -> ([Int], Bool)
+encodeTime :: [Int] -> TimeZone -> Integer
+getRunTime :: IO Float
+getElapsedTime :: IO Float
+sleep :: Int -> IO ()
+
+{-#
+ImportLispType (TimeZone (WestOfGMT ("number?", "identity", "identity")))
+ImportLispType (TimeZone (CurrentZone ("null?", "'()")))
+
+getTime :: LispName("lisp:get-universal-time")
+getTimeZone :: LispName("get-time-zone")
+decodeTime :: LispName("decode-time")
+encodeTime :: LispName("encode-time")
+getRunTime :: LispName("get-run-time")
+getElapsedTime :: LispName("get-elapsed-time")
+sleep :: LispName("lisp:sleep")
+
+#-}
+
+xWmName :: XWindow -> IO String
+xSetWmName :: XWindow -> String -> IO ()
+
+xWmIconName :: XWindow -> IO String
+xSetWmIconName :: XWindow -> String -> IO ()
+
+{-#
+xWmName :: LispName ("xlib:wm-name")
+xSetWmName :: LispName ("x-set-wm-name")
+
+xWmIconName :: LispName ("xlib:wm-icon-name")
+xSetWmIconName :: LispName ("x-set-wm-icon-name")
+#-}
diff --git a/progs/lib/X11/xlibprims.hu b/progs/lib/X11/xlibprims.hu
new file mode 100644
index 0000000..38138d4
--- /dev/null
+++ b/progs/lib/X11/xlibprims.hu
@@ -0,0 +1,5 @@
+:output $LIBRARYBIN/
+:stable
+:o= all
+xlibclx.scm
+xlibprims.hi
diff --git a/progs/lib/cl/README b/progs/lib/cl/README
new file mode 100644
index 0000000..8164257
--- /dev/null
+++ b/progs/lib/cl/README
@@ -0,0 +1,2 @@
+This directory contains some libraries which allow you to use various
+Common Lisp primitives from Haskell.
diff --git a/progs/lib/cl/logop-prims.hi b/progs/lib/cl/logop-prims.hi
new file mode 100644
index 0000000..2b120bb
--- /dev/null
+++ b/progs/lib/cl/logop-prims.hi
@@ -0,0 +1,78 @@
+-- logop-prims.hi -- interface to logical operations on numbers
+--
+-- author : Sandra Loosemore
+-- date : 19 June 1993
+--
+
+interface LogOpPrims where
+
+logiorInteger :: Integer -> Integer -> Integer
+logxorInteger :: Integer -> Integer -> Integer
+logandInteger :: Integer -> Integer -> Integer
+logeqvInteger :: Integer -> Integer -> Integer
+lognandInteger :: Integer -> Integer -> Integer
+lognorInteger :: Integer -> Integer -> Integer
+logandc1Integer :: Integer -> Integer -> Integer
+logandc2Integer :: Integer -> Integer -> Integer
+logorc1Integer :: Integer -> Integer -> Integer
+logorc2Integer :: Integer -> Integer -> Integer
+lognotInteger :: Integer -> Integer
+logtestInteger :: Integer -> Integer -> Integer
+logbitpInteger :: Int -> Integer -> Integer
+ashInteger :: Integer -> Int -> Integer
+logcountInteger :: Integer -> Int
+integerLengthInteger :: Integer -> Int
+
+logiorInt :: Int -> Int -> Int
+logxorInt :: Int -> Int -> Int
+logandInt :: Int -> Int -> Int
+logeqvInt :: Int -> Int -> Int
+lognandInt :: Int -> Int -> Int
+lognorInt :: Int -> Int -> Int
+logandc1Int :: Int -> Int -> Int
+logandc2Int :: Int -> Int -> Int
+logorc1Int :: Int -> Int -> Int
+logorc2Int :: Int -> Int -> Int
+lognotInt :: Int -> Int
+logtestInt :: Int -> Int -> Int
+logbitpInt :: Int -> Int -> Int
+ashInt :: Int -> Int -> Int
+logcountInt :: Int -> Int
+integerLengthInt :: Int -> Int
+
+{-#
+logiorInteger :: LispName("logop.logior-integer"), Complexity(4)
+logxorInteger :: LispName("logop.logxor-integer"), Complexity(4)
+logandInteger :: LispName("logop.logand-integer"), Complexity(4)
+logeqvInteger :: LispName("logop.logeqv-integer"), Complexity(4)
+lognandInteger :: LispName("logop.lognand-integer"), Complexity(4)
+lognorInteger :: LispName("logop.lognor-integer"), Complexity(4)
+logandc1Integer :: LispName("logop.logandc1-integer"), Complexity(4)
+logandc2Integer :: LispName("logop.logandc2-integer"), Complexity(4)
+logorc1Integer :: LispName("logop.logorc1-integer"), Complexity(4)
+logorc2Integer :: LispName("logop.logorc2-integer"), Complexity(4)
+lognotInteger :: LispName("logop.lognot-integer"), Complexity(4)
+logtestInteger :: LispName("logop.logtest-integer"), Complexity(4)
+logbitpInteger :: LispName("logop.logbitp-integer"), Complexity(4)
+ashInteger :: LispName("logop.ash-integer"), Complexity(4)
+logcountInteger :: LispName("logop.logcount-integer"), Complexity(4)
+integerLengthInteger :: LispName("logop.integer-length-integer"), Complexity(4)
+
+logiorInt :: LispName("logop.logior-int"), Complexity(2)
+logxorInt :: LispName("logop.logxor-int"), Complexity(2)
+logandInt :: LispName("logop.logand-int"), Complexity(2)
+logeqvInt :: LispName("logop.logeqv-int"), Complexity(2)
+lognandInt :: LispName("logop.lognand-int"), Complexity(2)
+lognorInt :: LispName("logop.lognor-int"), Complexity(2)
+logandc1Int :: LispName("logop.logandc1-int"), Complexity(2)
+logandc2Int :: LispName("logop.logandc2-int"), Complexity(2)
+logorc1Int :: LispName("logop.logorc1-int"), Complexity(2)
+logorc2Int :: LispName("logop.logorc2-int"), Complexity(2)
+lognotInt :: LispName("logop.lognot-int"), Complexity(2)
+logtestInt :: LispName("logop.logtest-int"), Complexity(2)
+logbitpInt :: LispName("logop.logbitp-int"), Complexity(2)
+ashInt :: LispName("logop.ash-int"), Complexity(2)
+logcountInt :: LispName("logop.logcount-int"), Complexity(2)
+integerLengthInt :: LispName("logop.integer-length-int"), Complexity(2)
+#-}
+
diff --git a/progs/lib/cl/logop-prims.scm b/progs/lib/cl/logop-prims.scm
new file mode 100644
index 0000000..b846836
--- /dev/null
+++ b/progs/lib/cl/logop-prims.scm
@@ -0,0 +1,81 @@
+;;; logop-prims.scm -- primitives for logical operations on numbers
+;;;
+;;; author : Sandra Loosemore
+;;; date : 19 Jun 1993
+;;;
+
+
+;;; Integer operations
+;;; Note that bit counts are still guaranteed to be fixnums....
+
+(define-syntax (logop.logior-integer i1 i2)
+ `(the integer (lisp:logior (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.logxor-integer i1 i2)
+ `(the integer (lisp:logxor (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.logand-integer i1 i2)
+ `(the integer (lisp:logand (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.logeqv-integer i1 i2)
+ `(the integer (lisp:logeqv (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.lognand-integer i1 i2)
+ `(the integer (lisp:lognand (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.lognor-integer i1 i2)
+ `(the integer (lisp:lognor (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.logandc1-integer i1 i2)
+ `(the integer (lisp:logandc1 (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.logandc2-integer i1 i2)
+ `(the integer (lisp:logandc2 (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.logorc1-integer i1 i2)
+ `(the integer (lisp:logorc1 (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.logorc2-integer i1 i2)
+ `(the integer (lisp:logorc2 (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.lognot-integer i1)
+ `(the integer (lisp:lognot (the integer ,i1))))
+(define-syntax (logop.logtest-integer i1 i2)
+ `(the integer (lisp:logtest (the integer ,i1) (the integer ,i2))))
+(define-syntax (logop.logbitp-integer i1 i2)
+ `(the integer (lisp:logbitp (the fixnum ,i1) (the integer ,i2))))
+(define-syntax (logop.ash-integer i1 i2)
+ `(the integer (lisp:ash (the integer ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logcount-integer i1)
+ `(the fixnum (lisp:logcount (the integer ,i1))))
+(define-syntax (logop.integer-length-integer i1)
+ `(the fixnum (lisp:integer-length (the integer ,i1))))
+
+
+;;; Fixnum operations
+
+(define-syntax (logop.logior-int i1 i2)
+ `(the fixnum (lisp:logior (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logxor-int i1 i2)
+ `(the fixnum (lisp:logxor (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logand-int i1 i2)
+ `(the fixnum (lisp:logand (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logeqv-int i1 i2)
+ `(the fixnum (lisp:logeqv (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.lognand-int i1 i2)
+ `(the fixnum (lisp:lognand (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.lognor-int i1 i2)
+ `(the fixnum (lisp:lognor (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logandc1-int i1 i2)
+ `(the fixnum (lisp:logandc1 (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logandc2-int i1 i2)
+ `(the fixnum (lisp:logandc2 (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logorc1-int i1 i2)
+ `(the fixnum (lisp:logorc1 (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logorc2-int i1 i2)
+ `(the fixnum (lisp:logorc2 (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.lognot-int i1)
+ `(the fixnum (lisp:lognot (the fixnum ,i1))))
+(define-syntax (logop.logtest-int i1 i2)
+ `(the fixnum (lisp:logtest (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logbitp-int i1 i2)
+ `(the fixnum (lisp:logbitp (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.ash-int i1 i2)
+ `(the fixnum (lisp:ash (the fixnum ,i1) (the fixnum ,i2))))
+(define-syntax (logop.logcount-int i1)
+ `(the fixnum (lisp:logcount (the fixnum ,i1))))
+(define-syntax (logop.integer-length-int i1)
+ `(the fixnum (lisp:integer-length (the fixnum ,i1))))
+
+
+
diff --git a/progs/lib/cl/logop.hs b/progs/lib/cl/logop.hs
new file mode 100644
index 0000000..1d0f9ba
--- /dev/null
+++ b/progs/lib/cl/logop.hs
@@ -0,0 +1,63 @@
+-- logop.hs -- logical operations on numbers
+--
+-- author : Sandra Loosemore
+-- date : 19 June 1993
+--
+
+module LogOp where
+
+import LogOpPrims -- from logop-prims.hi
+
+class LogOperand a where
+ logior :: a -> a -> a
+ logxor :: a -> a -> a
+ logand :: a -> a -> a
+ logeqv :: a -> a -> a
+ lognand :: a -> a -> a
+ lognor :: a -> a -> a
+ logandc1 :: a -> a -> a
+ logandc2 :: a -> a -> a
+ logorc1 :: a -> a -> a
+ logorc2 :: a -> a -> a
+ lognot :: a -> a
+ logtest :: a -> a -> a
+ logbitp :: Int -> a -> a
+ ash :: a -> Int -> a
+ logcount :: a -> Int
+ integerLength :: a -> Int
+
+instance LogOperand Integer where
+ logior = logiorInteger
+ logxor = logxorInteger
+ logand = logandInteger
+ logeqv = logeqvInteger
+ lognand = lognandInteger
+ lognor = lognorInteger
+ logandc1 = logandc1Integer
+ logandc2 = logandc2Integer
+ logorc1 = logorc1Integer
+ logorc2 = logorc2Integer
+ lognot = lognotInteger
+ logtest = logtestInteger
+ logbitp = logbitpInteger
+ ash = ashInteger
+ logcount = logcountInteger
+ integerLength = integerLengthInteger
+
+instance LogOperand Int where
+ logior = logiorInt
+ logxor = logxorInt
+ logand = logandInt
+ logeqv = logeqvInt
+ lognand = lognandInt
+ lognor = lognorInt
+ logandc1 = logandc1Int
+ logandc2 = logandc2Int
+ logorc1 = logorc1Int
+ logorc2 = logorc2Int
+ lognot = lognotInt
+ logtest = logtestInt
+ logbitp = logbitpInt
+ ash = ashInt
+ logcount = logcountInt
+ integerLength = integerLengthInt
diff --git a/progs/lib/cl/logop.hu b/progs/lib/cl/logop.hu
new file mode 100644
index 0000000..cfe8209
--- /dev/null
+++ b/progs/lib/cl/logop.hu
@@ -0,0 +1,5 @@
+:output $LIBRARYBIN/
+:o= all
+logop.hs
+logop-prims.scm
+logop-prims.hi
diff --git a/progs/lib/cl/maybe.hs b/progs/lib/cl/maybe.hs
new file mode 100644
index 0000000..8ce01e5
--- /dev/null
+++ b/progs/lib/cl/maybe.hs
@@ -0,0 +1,12 @@
+-- maybe.hs -- "maybe" type
+--
+-- author : Sandra Loosemore
+-- date : 22 June 1993
+--
+
+module Maybe where
+
+data Maybe a = Some a | Null
+
+{-# ImportLispType (Maybe(Some("identity", "identity", "identity"),
+ Null("not", "'#f"))) #-}
diff --git a/progs/lib/cl/maybe.hu b/progs/lib/cl/maybe.hu
new file mode 100644
index 0000000..2115c71
--- /dev/null
+++ b/progs/lib/cl/maybe.hu
@@ -0,0 +1,3 @@
+:output $LIBRARYBIN/
+:o= all
+maybe.hs
diff --git a/progs/lib/cl/random-prims.hi b/progs/lib/cl/random-prims.hi
new file mode 100644
index 0000000..e66d802
--- /dev/null
+++ b/progs/lib/cl/random-prims.hi
@@ -0,0 +1,20 @@
+-- random-prims.hi -- interface file to random number primitives
+--
+-- author : Sandra Loosemore
+-- date : 22 June 1993
+--
+
+
+interface RandomPrims where
+
+randomInt :: Int -> IO Int
+randomInteger :: Integer -> IO Integer
+randomFloat :: Float -> IO Float
+randomDouble :: Double -> IO Double
+
+{-#
+randomInt :: LispName("lisp:random"), Complexity(5)
+randomInteger :: LispName("lisp:random"), Complexity(5)
+randomFloat :: LispName("lisp:random"), Complexity(5)
+randomDouble :: LispName("lisp:random"), Complexity(5)
+#-}
diff --git a/progs/lib/cl/random.hs b/progs/lib/cl/random.hs
new file mode 100644
index 0000000..93d26e4
--- /dev/null
+++ b/progs/lib/cl/random.hs
@@ -0,0 +1,21 @@
+-- random.hs -- random number functions
+--
+-- author : Sandra Loosemore
+-- date : 22 June 1993
+--
+
+module Random where
+
+import RandomPrims -- from random-prims.hi
+
+class RandomOperand a where
+ random :: a -> IO a
+
+instance RandomOperand Int where
+ random = randomInt
+instance RandomOperand Integer where
+ random = randomInteger
+instance RandomOperand Float where
+ random = randomFloat
+instance RandomOperand Double where
+ random = randomDouble
diff --git a/progs/lib/cl/random.hu b/progs/lib/cl/random.hu
new file mode 100644
index 0000000..4b8e286
--- /dev/null
+++ b/progs/lib/cl/random.hu
@@ -0,0 +1,4 @@
+:output $LIBRARYBIN/
+:o= all
+random.hs
+random-prims.hi
diff --git a/progs/lib/hbc/Either.hs b/progs/lib/hbc/Either.hs
new file mode 100644
index 0000000..fad5af8
--- /dev/null
+++ b/progs/lib/hbc/Either.hs
@@ -0,0 +1,2 @@
+module Either(Either(..)) where
+data Either a b = Left a | Right b deriving (Eq, Ord, Text, Binary)
diff --git a/progs/lib/hbc/Either.hu b/progs/lib/hbc/Either.hu
new file mode 100644
index 0000000..3313235
--- /dev/null
+++ b/progs/lib/hbc/Either.hu
@@ -0,0 +1,3 @@
+:output $LIBRARYBIN/
+:o= all
+Either.hs
diff --git a/progs/lib/hbc/Hash.hs b/progs/lib/hbc/Hash.hs
new file mode 100644
index 0000000..1f14c6f
--- /dev/null
+++ b/progs/lib/hbc/Hash.hs
@@ -0,0 +1,79 @@
+module Hash where
+--
+-- Hash a value. Hashing produces an Int of
+-- unspecified range.
+--
+
+class Hashable a where
+ hash :: a -> Int
+
+instance Hashable Char where
+ hash x = ord x
+
+instance Hashable Int where
+ hash x = x
+
+instance Hashable Integer where
+ hash x = fromInteger x
+
+instance Hashable Float where
+ hash x = truncate x
+
+instance Hashable Double where
+ hash x = truncate x
+
+instance Hashable Bin where
+ hash x = 0
+
+{-instance Hashable File where
+ hash x = 0 -}
+
+instance Hashable () where
+ hash x = 0
+
+instance Hashable (a -> b) where
+ hash x = 0
+
+instance Hashable a => Hashable [a] where
+ hash x = sum (map hash x)
+
+instance (Hashable a, Hashable b) => Hashable (a,b) where
+ hash (a,b) = hash a + 3 * hash b
+
+instance (Hashable a, Hashable b, Hashable c) => Hashable (a,b,c) where
+ hash (a,b,c) = hash a + 3 * hash b + 5 * hash c
+
+instance (Hashable a, Hashable b, Hashable c, Hashable d) => Hashable (a,b,c,d) where
+ hash (a,b,c,d) = hash a + 3 * hash b + 5 * hash c + 7 * hash d
+
+instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e) => Hashable (a,b,c,d,e) where
+ hash (a,b,c,d,e) = hash a + hash b + hash c + hash d + hash e
+
+instance Hashable Bool where
+ hash False = 0
+ hash True = 1
+
+instance (Integral a, Hashable a) => Hashable (Ratio a) where
+ hash x = hash (denominator x) + hash (numerator x)
+
+instance (RealFloat a, Hashable a) => Hashable (Complex a) where
+ hash (x :+ y) = hash x + hash y
+
+instance (Hashable a, Hashable b) => Hashable (Assoc a b) where
+ hash (x := y) = hash x + hash y
+
+instance (Ix a) => Hashable (Array a b) where
+ hash x = 0 -- !!!
+
+instance Hashable Request where
+ hash x = 0 -- !!
+
+instance Hashable Response where
+ hash x = 0 -- !!
+
+instance Hashable IOError where
+ hash x = 0 -- !!
+
+hashToMax maxhash x =
+ let h = abs (hash x)
+ in if h < 0 then 0 else h `rem` maxhash
diff --git a/progs/lib/hbc/Hash.hu b/progs/lib/hbc/Hash.hu
new file mode 100644
index 0000000..2c23c72
--- /dev/null
+++ b/progs/lib/hbc/Hash.hu
@@ -0,0 +1,3 @@
+:output $LIBRARYBIN/
+:o= all
+Hash.hs
diff --git a/progs/lib/hbc/ListUtil.hs b/progs/lib/hbc/ListUtil.hs
new file mode 100644
index 0000000..560920e
--- /dev/null
+++ b/progs/lib/hbc/ListUtil.hs
@@ -0,0 +1,48 @@
+module ListUtil(assoc, concatMap, unfoldr, mapAccuml, union, intersection, chopList, assocDef, lookup, Maybe..) where
+import Maybe
+
+-- Lookup an item in an association list. Apply a function to it if it is found, otherwise return a default value.
+assoc :: (Eq c) => (a -> b) -> b -> [(c, a)] -> c -> b
+assoc f d [] x = d
+assoc f d ((x',y):xys) x | x' == x = f y
+ | otherwise = assoc f d xys x
+
+-- Map and concatename results.
+concatMap :: (a -> [b]) -> [a] -> [b]
+concatMap f [] = []
+concatMap f (x:xs) =
+ case f x of
+ [] -> concatMap f xs
+ ys -> ys ++ concatMap f xs
+
+-- Repeatedly extract (and transform) values until a predicate hold. Return the list of values.
+unfoldr :: (a -> (b, a)) -> (a -> Bool) -> a -> [b]
+unfoldr f p x | p x = []
+ | otherwise = y:unfoldr f p x'
+ where (y, x') = f x
+
+-- Map, but plumb a state through the map operation.
+mapAccuml :: (a -> b -> (a, c)) -> a -> [b] -> (a, [c])
+mapAccuml f s [] = (s, [])
+mapAccuml f s (x:xs) = (s'', y:ys)
+ where (s', y) = f s x
+ (s'', ys) = mapAccuml f s' xs
+
+-- Union of sets as lists.
+union :: (Eq a) => [a] -> [a] -> [a]
+union xs ys = xs ++ (ys \\ xs)
+
+-- Intersection of sets as lists.
+intersection :: (Eq a) => [a] -> [a] -> [a]
+intersection xs ys = [x | x<-xs, x `elem` ys]
+
+--- Functions derived from those above
+
+chopList :: ([a] -> (b, [a])) -> [a] -> [b]
+chopList f l = unfoldr f null l
+
+assocDef :: (Eq a) => [(a, b)] -> b -> a -> b
+assocDef l d x = assoc id d l x
+
+lookup :: (Eq a) => [(a, b)] -> a -> Maybe b
+lookup l x = assoc Just Nothing l x
diff --git a/progs/lib/hbc/ListUtil.hu b/progs/lib/hbc/ListUtil.hu
new file mode 100644
index 0000000..7402cb7
--- /dev/null
+++ b/progs/lib/hbc/ListUtil.hu
@@ -0,0 +1,4 @@
+:output $LIBRARYBIN/
+:o= all
+ListUtil.hs
+Maybe.hu
diff --git a/progs/lib/hbc/Maybe.hs b/progs/lib/hbc/Maybe.hs
new file mode 100644
index 0000000..f0ada70
--- /dev/null
+++ b/progs/lib/hbc/Maybe.hs
@@ -0,0 +1,6 @@
+module Maybe(Maybe(..), thenM) where
+-- Maybe together with Just and thenM forms a monad, but is more
+-- by accident than by design.
+data Maybe a = Nothing | Just a deriving (Eq, Ord, Text, Binary)
+Nothing `thenM` _ = Nothing
+Just a `thenM` f = f a
diff --git a/progs/lib/hbc/Maybe.hu b/progs/lib/hbc/Maybe.hu
new file mode 100644
index 0000000..a55b652
--- /dev/null
+++ b/progs/lib/hbc/Maybe.hu
@@ -0,0 +1,3 @@
+:output $LIBRARYBIN/
+:o= all
+Maybe.hs
diff --git a/progs/lib/hbc/Miranda.hs b/progs/lib/hbc/Miranda.hs
new file mode 100644
index 0000000..2d863ce
--- /dev/null
+++ b/progs/lib/hbc/Miranda.hs
@@ -0,0 +1,90 @@
+module Miranda(cjustify, lay, layn, limit, ljustify, merge, rep, rjustify, spaces,
+ {-force,seq,-}sort) where
+--import UnsafeDirty
+import QSort
+
+cjustify :: Int -> String -> String
+cjustify n s = spaces l ++ s ++ spaces r
+ where
+ m = n - length s
+ l = m `div` 2
+ r = m - l
+
+{-
+index :: [a] -> [Int]
+index xs = f xs 0
+ where f [] n = []
+ f (_:xs) n = n : f xs (n+1)
+-}
+
+lay :: [String] -> String
+lay = concat . map (++"\n")
+
+layn :: [String] -> String
+layn = concat . zipWith f [1..]
+ where
+ f :: Int -> String -> String
+ f n x = rjustify 4 (show n) ++ ") " ++ x ++ "\n"
+
+limit :: (Eq a) => [a] -> a
+limit (x:y:ys) | x == y = x
+ | otherwise = limit (y:ys)
+limit _ = error "Miranda.limit: bad use"
+
+ljustify :: Int -> String -> String
+ljustify n s = s ++ spaces (n - length s)
+
+merge :: (Ord a) => [a] -> [a] -> [a]
+merge [] ys = ys
+merge xs [] = xs
+merge xxs@(x:xs) yys@(y:ys) | x <= y = x : merge xs yys
+ | otherwise = y : merge xxs ys
+
+rep :: Int -> b -> [b]
+rep n x = take n (repeat x)
+
+rjustify :: Int -> String -> String
+rjustify n s = spaces (n - length s) ++ s
+
+spaces :: Int -> String
+spaces 0 = ""
+spaces n = ' ' : spaces (n-1)
+
+-------------
+
+arctan x = atan x
+code c = ord c
+converse f a b = flip f a b
+decode n = chr n
+digit c = isDigit c
+e :: (Floating a) => a
+e = exp 1
+entier x = floor x
+filemode f = error "Miranda.filemode"
+--getenv
+hd xs = head xs
+hugenum :: (Floating a) => a
+hugenum = error "hugenum" --!!!
+integer x = x == truncate x
+letter c = isAlpha c
+map2 f xs ys = zipWith f xs ys
+--max
+max2 x y = max x y
+member xs x = x `elem` xs
+--min
+min2 x y = min x y
+mkset xs = nub xs
+neg x = negate x
+numval :: (Num a) => String -> a
+numval cs = read cs
+postfix xs x = xs ++ [x]
+--read
+scan f z l = scanl f z l
+--shownum !!!
+--showfloat !!!
+--showscaled !!!
+tinynum :: (Floating a) => a
+tinynum = error "tinynum"
+undef = error "undefined"
+zip2 xs ys = zip xs ys
+--zip
diff --git a/progs/lib/hbc/Miranda.hu b/progs/lib/hbc/Miranda.hu
new file mode 100644
index 0000000..cfa86ed
--- /dev/null
+++ b/progs/lib/hbc/Miranda.hu
@@ -0,0 +1,4 @@
+:output $LIBRARYBIN/
+:o= all
+Miranda.hs
+QSort.hu
diff --git a/progs/lib/hbc/Option.hs b/progs/lib/hbc/Option.hs
new file mode 100644
index 0000000..a4b2423
--- /dev/null
+++ b/progs/lib/hbc/Option.hs
@@ -0,0 +1,3 @@
+module Option(Option(..), thenO) where
+import Maybe renaming (Maybe to Option, Nothing to None, Just to Some, thenM to thenO)
+
diff --git a/progs/lib/hbc/Option.hu b/progs/lib/hbc/Option.hu
new file mode 100644
index 0000000..592a0cd
--- /dev/null
+++ b/progs/lib/hbc/Option.hu
@@ -0,0 +1,3 @@
+:output $LIBRARYBIN/
+:o= all
+Option.hs
diff --git a/progs/lib/hbc/Pretty.hs b/progs/lib/hbc/Pretty.hs
new file mode 100644
index 0000000..ad63dbe
--- /dev/null
+++ b/progs/lib/hbc/Pretty.hs
@@ -0,0 +1,50 @@
+module Pretty(text, separate, nest, pretty, (~.), (^.), IText(..), Context(..)) where
+infixr 8 ~.
+infixr 8 ^.
+
+type IText = Context -> [String]
+type Context = (Bool,Int,Int,Int)
+
+text :: String -> IText
+text s (v,w,m,m') = [s]
+
+(~.) :: IText -> IText -> IText
+(~.) d1 d2 (v,w,m,m') =
+ let t = d1 (False,w,m,m')
+ tn = last t
+ indent = length tn
+ sig = if length t == 1
+ then m' + indent
+ else length (dropWhile (==' ') tn)
+ (l:ls) = d2 (False,w-indent,m,sig)
+ in init t ++
+ [tn ++ l] ++
+ map (space indent++) ls
+
+space :: Int -> String
+space n = [' ' | i<-[1..n]]
+
+(^.) :: IText -> IText -> IText
+(^.) d1 d2 (v,w,m,m') = d1 (True,w,m,m') ++ d2 (True,w,m,0)
+
+separate :: [IText] -> IText
+separate [] _ = [""]
+separate ds (v,w,m,m') =
+ let hor = foldr1 (\d1 d2 -> d1 ~. text " " ~. d2) ds
+ ver = foldr1 (^.) ds
+ t = hor (v,w,m,m')
+ in if fits 1 t && fits (w `min` m-m') (head t)
+ then t
+ else ver (v,w,m,m')
+
+fits n xs = length xs <= n `max` 0 --null (drop n xs)
+
+nest :: Int -> IText -> IText
+nest n d (v,w,m,m') =
+ if v then
+ map (space n++) (d (v,w-n,m,if m'==0 then 0 else m'+n))
+ else
+ d (v,w,m,m')
+
+pretty :: Int->Int->IText->String
+pretty w m d = concat (map (++"\n") (d (False,w,m,0)))
diff --git a/progs/lib/hbc/Printf.hs b/progs/lib/hbc/Printf.hs
new file mode 100644
index 0000000..c8291bd
--- /dev/null
+++ b/progs/lib/hbc/Printf.hs
@@ -0,0 +1,150 @@
+-- This code used a function in the lml library (fmtf) that I don't have.
+-- If someone makes this work for floats let me know -- jcp
+--
+-- A C printf like formatter.
+-- Conversion specs:
+-- - left adjust
+-- num field width
+-- . separates width from precision
+-- Formatting characters:
+-- c Char, Int, Integer
+-- d Char, Int, Integer
+-- o Char, Int, Integer
+-- x Char, Int, Integer
+-- u Char, Int, Integer
+-- f Float, Double
+-- g Float, Double
+-- e Float, Double
+-- s String
+--
+module Printf(UPrintf(..), printf) where
+
+-- import LMLfmtf
+
+data UPrintf = UChar Char |
+ UString String |
+ UInt Int |
+ UInteger Integer |
+ UFloat Float |
+ UDouble Double
+
+printf :: String -> [UPrintf] -> String
+printf "" [] = ""
+printf "" (_:_) = fmterr
+printf ('%':_) [] = argerr
+printf ('%':cs) us@(_:_) = fmt cs us
+printf (c:cs) us = c:printf cs us
+
+fmt :: String -> [UPrintf] -> String
+fmt cs us =
+ let (width, prec, ladj, zero, cs', us') = getSpecs False False cs us
+ adjust (pre, str) =
+ let lstr = length str
+ lpre = length pre
+ fill = if lstr+lpre < width then take (width-(lstr+lpre)) (repeat (if zero then '0' else ' ')) else ""
+ in if ladj then pre ++ str ++ fill else pre ++ fill ++ str
+ in
+ case cs' of
+ [] -> fmterr
+ c:cs'' ->
+ case us' of
+ [] -> argerr
+ u:us'' ->
+ (case c of
+ 'c' -> adjust ("", [chr (toint u)])
+ 'd' -> adjust (fmti u)
+ 'x' -> adjust ("", fmtu 16 u)
+ 'o' -> adjust ("", fmtu 8 u)
+ 'u' -> adjust ("", fmtu 10 u)
+ '%' -> "%"
+ 'e' -> adjust (dfmt c prec (todbl u))
+ 'f' -> adjust (dfmt c prec (todbl u))
+ 'g' -> adjust (dfmt c prec (todbl u))
+ 's' -> adjust ("", tostr u)
+ c -> perror ("bad formatting char " ++ [c])
+ ) ++ printf cs'' us''
+unimpl = perror "unimplemented"
+
+fmti (UInt i) = if i < 0 then
+ if i == -i then fmti (UInteger (toInteger i)) else ("-", itos (-i))
+ else
+ ("", itos i)
+fmti (UInteger i) = if i < 0 then ("-", itos (-i)) else ("", itos i)
+fmti (UChar c) = fmti (UInt (ord c))
+fmti u = baderr
+
+fmtu b (UInt i) = if i < 0 then
+ if i == -i then itosb b (maxi - toInteger (i+1) - 1) else itosb b (maxi - toInteger (-i))
+ else
+ itosb b (toInteger i)
+fmtu b (UInteger i) = itosb b i
+fmtu b (UChar c) = itosb b (toInteger (ord c))
+fmtu b u = baderr
+
+maxi :: Integer
+maxi = (toInteger maxInt + 1) * 2
+
+toint (UInt i) = i
+toint (UInteger i) = toInt i
+toint (UChar c) = ord c
+toint u = baderr
+
+tostr (UString s) = s
+tostr u = baderr
+
+todbl (UDouble d) = d
+todbl (UFloat f) = fromRational (toRational f)
+todbl u = baderr
+
+itos n =
+ if n < 10 then
+ [chr (ord '0' + toInt n)]
+ else
+ let (q, r) = quotRem n 10 in
+ itos q ++ [chr (ord '0' + toInt r)]
+
+chars = array (0,15) (zipWith (:=) [0..] "0123456789abcdef")
+itosb :: Integer -> Integer -> String
+itosb b n =
+ if n < b then
+ [chars!n]
+ else
+ let (q, r) = quotRem n b in
+ itosb b q ++ [chars!r]
+
+stoi :: Int -> String -> (Int, String)
+stoi a (c:cs) | isDigit c = stoi (a*10 + ord c - ord '0') cs
+stoi a cs = (a, cs)
+
+getSpecs :: Bool -> Bool -> String -> [UPrintf] -> (Int, Int, Bool, Bool, String, [UPrintf])
+getSpecs l z ('-':cs) us = getSpecs True z cs us
+getSpecs l z ('0':cs) us = getSpecs l True cs us
+getSpecs l z ('*':cs) us = unimpl
+getSpecs l z cs@(c:_) us | isDigit c =
+ let (n, cs') = stoi 0 cs
+ (p, cs'') = case cs' of
+ '.':r -> stoi 0 r
+ _ -> (-1, cs')
+ in (n, p, l, z, cs'', us)
+getSpecs l z cs us = (0, -1, l, z, cs, us)
+
+-- jcp: I don't know what the lml function fmtf does. Someone needs to
+-- rewrite this.
+
+{-
+dfmt c p d =
+ case fmtf ("1" ++ (if p < 0 then "" else '.':itos p) ++ [c]) d of
+ '-':cs -> ("-", cs)
+ cs -> ("" , cs)
+-}
+dfmt = error "fmtf not implemented"
+
+perror s = error ("Printf.printf: "++s)
+fmterr = perror "formatting string ended prematurely"
+argerr = perror "argument list ended prematurely"
+baderr = perror "bad argument"
+
+-- This is needed because standard Haskell does not have toInt
+
+toInt :: Integral a => a -> Int
+toInt x = fromIntegral x
diff --git a/progs/lib/hbc/Printf.hu b/progs/lib/hbc/Printf.hu
new file mode 100644
index 0000000..d94f5b1
--- /dev/null
+++ b/progs/lib/hbc/Printf.hu
@@ -0,0 +1,3 @@
+:output $LIBRARYBIN/
+:o= all
+Printf.hs
diff --git a/progs/lib/hbc/QSort.hs b/progs/lib/hbc/QSort.hs
new file mode 100644
index 0000000..f19eb43
--- /dev/null
+++ b/progs/lib/hbc/QSort.hs
@@ -0,0 +1,47 @@
+{-
+ This module implements a sort function using a variation on
+ quicksort. It is stable, uses no concatenation and compares
+ only with <=.
+
+ sortLe sorts with a given predicate
+ sort uses the <= method
+
+ Author: Lennart Augustsson
+-}
+
+module QSort(sortLe, sort) where
+sortLe :: (a -> a -> Bool) -> [a] -> [a]
+sortLe le l = qsort le l []
+
+sort :: (Ord a) => [a] -> [a]
+sort l = qsort (<=) l []
+
+-- qsort is stable and does not concatenate.
+qsort le [] r = r
+qsort le [x] r = x:r
+qsort le (x:xs) r = qpart le x xs [] [] r
+
+-- qpart partitions and sorts the sublists
+qpart le x [] rlt rge r =
+ -- rlt and rge are in reverse order and must be sorted with an
+ -- anti-stable sorting
+ rqsort le rlt (x:rqsort le rge r)
+qpart le x (y:ys) rlt rge r =
+ if le x y then
+ qpart le x ys rlt (y:rge) r
+ else
+ qpart le x ys (y:rlt) rge r
+
+-- rqsort is as qsort but anti-stable, i.e. reverses equal elements
+rqsort le [] r = r
+rqsort le [x] r = x:r
+rqsort le (x:xs) r = rqpart le x xs [] [] r
+
+rqpart le x [] rle rgt r =
+ qsort le rle (x:qsort le rgt r)
+rqpart le x (y:ys) rle rgt r =
+ if le y x then
+ rqpart le x ys (y:rle) rgt r
+ else
+ rqpart le x ys rle (y:rgt) r
+
diff --git a/progs/lib/hbc/QSort.hu b/progs/lib/hbc/QSort.hu
new file mode 100644
index 0000000..9a07dd1
--- /dev/null
+++ b/progs/lib/hbc/QSort.hu
@@ -0,0 +1,3 @@
+:output $LIBRARYBIN/
+:o= all
+QSort.hs
diff --git a/progs/lib/hbc/README b/progs/lib/hbc/README
new file mode 100644
index 0000000..c51452a
--- /dev/null
+++ b/progs/lib/hbc/README
@@ -0,0 +1,97 @@
+These libraries are adapted from the lml library. Also included are a number
+of Common Lisp functions.
+
+The hbc library contains the following modules and functions:
+
+* module Either
+ binary sum data type
+ data Either a b = Left a | Right b
+ constructor Left typically used for errors
+
+* module Option
+ type for success or failure
+ data Option a = None | Some a
+ thenO :: Option a -> (a -> Option b) -> Option b apply a function that may fail
+
+
+* module ListUtil
+ Various useful functions involving lists that are missing from the Prelude
+ assoc :: (Eq c) => (a -> b) -> b -> [(c, a)] -> c -> b
+ assoc f d l k looks for k in the association list l, if it is found f is applied to the value, otherwise d is returned
+ concatMap :: (a -> [b]) -> [a] -> [b]
+ flattening map (LMLs concmap)
+ unfoldr :: (a -> (b, a)) -> (a -> Bool) -> a -> [b]
+ unfoldr f p x repeatedly applies f to x until (p x) holds. (f x) should give a list element and a new x
+ mapAccuml :: (a -> b -> (a, c)) -> a -> [b] -> (a, [c])
+ mapAccuml f s l maps f over l, but also threads the state s though (LMLs mapstate)
+ union :: (Eq a) => [a] -> [a] -> [a]
+ unions of two lists
+ intersection :: (Eq a) => [a] -> [a] -> [a]
+ intersection of two lists
+ chopList :: ([a] -> (b, [a])) -> [a] -> [b]
+ LMLs choplist
+ assocDef :: (Eq a) => [(a, b)] -> b -> a -> b
+ LMLs assocdef
+ lookup :: (Eq a) => [(a, b)] -> a -> Option b
+ lookup l k looks for the key k in the association list l and returns an optional value
+
+* module Pretty
+ John Hughes pretty printing library.
+ type Context = (Bool, Int, Int, Int)
+ type IText = Context -> [String]
+ text :: String -> IText just text
+ (~.) :: IText -> IText -> IText horizontal composition
+ (^.) :: IText -> IText -> IText vertical composition
+ separate :: [IText] -> IText separate by spaces
+ nest :: Int -> IText -> IText indent
+ pretty :: Int -> Int -> IText -> String format it
+
+* module QSort
+ Sort function using quicksort.
+ sortLe :: (a -> a -> Bool) -> [a] -> [a] sort le l sorts l with le as less than predicate
+ sort :: (Ord a) => [a] -> [a] sort l sorts l using the Ord class
+
+* module Random
+ Random numbers.
+ randomInts :: Int -> Int -> [Int] given two seeds gives a list of random Int
+ randomDoubles :: Int -> Int -> [Double] given two seeds gives a list of random Double
+
+* module RunDialogue
+ Test run programs of type Dialogue.
+ Only a few Requests are implemented, unfortunately not ReadChannel.
+ run :: Dialogue -> String just run the program, showing the output
+ runTrace :: Dialogue -> String run the program, showing each Request and Response
+
+* module Miranda
+ Functions found in the Miranda(tm) library.
+
+* module Printf
+ C printf style formatting. Handles same types as printf in C, but requires the arguments
+ to be tagged. Useful for formatting of floating point values.
+ data UPrintf = UChar Char | UString String | UInt Int | UInteger Integer | UFloat Float | UDouble Double
+ printf :: String -> [UPrintf] -> String convert arguments in the list according to the formatting string
+
+
+* module Time
+ Manipulate time values (a Double with seconds since 1970).
+ -- year mon day hour min sec dec-sec weekday
+ data Time = Time Int Int Int Int Int Int Double Int
+ dblToTime :: Double -> Time convert a Double to a Time
+ timeToDbl :: Time -> Double convert a Time to a Double
+ timeToString :: Time -> String convert a Time to a readable String
+
+----- To add:
+
+Bytes
+IO Library
+Word oprtations
+Time clock stuff
+Lisp stuff: symbols
+ hashtables
+ strings
+
+
+
+
+
+
diff --git a/progs/lib/hbc/Random.hs b/progs/lib/hbc/Random.hs
new file mode 100644
index 0000000..269d6af
--- /dev/null
+++ b/progs/lib/hbc/Random.hs
@@ -0,0 +1,52 @@
+{-
+ This module implements a (good) random number generator.
+
+ The June 1988 (v31 #6) issue of the Communications of the ACM has an
+ article by Pierre L'Ecuyer called, "Efficient and Portable Combined
+ Random Number Generators". Here is the Portable Combined Generator of
+ L'Ecuyer for 32-bit computers. It has a period of roughly 2.30584e18.
+
+ Transliterator: Lennart Augustsson
+-}
+
+module Random(randomInts, randomDoubles) where
+-- Use seeds s1 in 1..2147483562 and s2 in 1..2147483398 to generate
+-- an infinite list of random Ints.
+randomInts :: Int -> Int -> [Int]
+randomInts s1 s2 =
+ if 1 <= s1 && s1 <= 2147483562 then
+ if 1 <= s2 && s2 <= 2147483398 then
+ rands s1 s2
+ else
+ error "randomInts: Bad second seed."
+ else
+ error "randomInts: Bad first seed."
+
+rands :: Int -> Int -> [Int]
+rands s1 s2 =
+ let
+ k = s1 `div` 53668
+ s1' = 40014 * (s1 - k * 53668) - k * 12211
+ s1'' = if s1' < 0 then s1' + 2147483563 else s1'
+
+ k' = s2 `div` 52774
+ s2' = 40692 * (s2 - k' * 52774) - k' * 3791
+ s2'' = if s2' < 0 then s2' + 2147483399 else s2'
+
+ z = s1'' - s2''
+{-
+ z' = if z < 1 then z + 2147483562 else z
+
+ in z' : rands s1'' s2''
+-}
+-- Use this instead; it is a little stricter and generates much better code
+ in if z < 1 then z + 2147483562 : rands s1'' s2''
+ else z : rands s1'' s2''
+
+-- For those of you who don't have fromInt
+fromInt = fromInteger . toInteger
+
+-- Same values for s1 and s2 as above, generates an infinite
+-- list of Doubles uniformly distibuted in (0,1).
+randomDoubles :: Int -> Int -> [Double]
+randomDoubles s1 s2 = map (\x -> fromInt x * 4.6566130638969828e-10) (randomInts s1 s2)
diff --git a/progs/lib/hbc/Random.hu b/progs/lib/hbc/Random.hu
new file mode 100644
index 0000000..9fff34e
--- /dev/null
+++ b/progs/lib/hbc/Random.hu
@@ -0,0 +1,3 @@
+:output $LIBRARYBIN/
+:o= all
+Random.hs
diff --git a/progs/lib/hbc/Time.hs b/progs/lib/hbc/Time.hs
new file mode 100644
index 0000000..29f3441
--- /dev/null
+++ b/progs/lib/hbc/Time.hs
@@ -0,0 +1,51 @@
+module Time(Time(..), dblToTime, timeToDbl, timeToString) where
+-- year mon day hour min sec ... wday
+data Time = Time Int Int Int Int Int Int Double Int deriving (Eq, Ord, Text)
+
+isleap :: Int -> Bool
+isleap n = n `rem` 4 == 0 -- good enough for the UNIX time span
+
+daysin :: Int -> Int
+daysin n = if isleap n then 366 else 365
+
+monthlen :: Array (Bool, Int) Int
+monthlen = array ((False, 1), (True, 12)) (zipWith3 (\ a b c -> (a,b):=c) (repeat False) [1..] [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] ++
+ zipWith3 (\ a b c -> (a,b):=c) (repeat True) [1..] [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31])
+
+-- Time zone offset in minutes
+tzOffset = 120 -- Swedish DST
+
+dblToTime :: Double -> Time
+dblToTime d =
+ let t = truncate d :: Int
+ offset = tzOffset -- timezone
+ (days, rem) = (t+offset*60) `quotRem` (60*60*24)
+ (hour, rem') = rem `quotRem` (60*60)
+ (min, sec) = rem' `quotRem` 60
+ wday = (days+3) `mod` 7
+ (year, days')= until (\ (y, d) -> d < daysin y) (\ (y, d) -> (y+1, d - daysin y)) (1970, days)
+ (mon, day) = until (\ (m, d) -> d <= monthlen!(isleap year, m)) (\ (m, d) -> (m+1, d - monthlen!(isleap year, m))) (1, days')
+ in Time year mon (day+1) hour min sec (d - fromInt t) wday
+
+timeToDbl :: Time -> Double
+timeToDbl (Time year mon day hour min sec sdec _) =
+ let year' = year - 1970
+ offset = tzOffset -- timezone
+ days = year' * 365 + (year'+1) `div` 4 +
+ sum [monthlen!(isleap year, m) | m<-[1..mon-1]] + day - 1
+ secs = ((days*24 + hour) * 60 + min - offset) * 60 + sec
+ in fromInt secs + sdec
+
+show2 :: Int -> String
+show2 x = [chr (x `quot` 10 + ord '0'), chr (x `rem` 10 + ord '0')]
+
+weekdays = ["Mon","Tue","Wen","Thu","Fri","Sat","Sun"]
+
+timeToString :: Time -> String
+timeToString (Time year mon day hour min sec sdec wday) =
+ show year ++ "-" ++ show2 mon ++ "-" ++ show2 day ++ " " ++
+ show2 hour ++ ":" ++ show2 min ++ ":" ++ show2 sec ++
+ tail (take 5 (show sdec)) ++ " " ++ weekdays!!wday
+
+-- For those of you who don't have fromInt
+fromInt = fromInteger . toInteger
diff --git a/progs/lib/hbc/Time.hu b/progs/lib/hbc/Time.hu
new file mode 100644
index 0000000..01c8f64
--- /dev/null
+++ b/progs/lib/hbc/Time.hu
@@ -0,0 +1,3 @@
+:output $LIBRARYBIN/
+:o= all
+Time.hs
diff --git a/progs/prelude/Prelude.hs b/progs/prelude/Prelude.hs
new file mode 100644
index 0000000..bf20849
--- /dev/null
+++ b/progs/prelude/Prelude.hs
@@ -0,0 +1,187 @@
+-- Standard value bindings
+
+module Prelude (
+ PreludeCore.., PreludeRatio.., PreludeComplex.., PreludeList..,
+ PreludeArray.., PreludeText.., PreludeIO..,
+ nullBin, isNullBin, appendBin,
+ (&&), (||), not, otherwise,
+ minChar, maxChar, ord, chr,
+ isAscii, isControl, isPrint, isSpace,
+ isUpper, isLower, isAlpha, isDigit, isAlphanum,
+ toUpper, toLower,
+ minInt, maxInt, subtract, gcd, lcm, (^), (^^),
+ fromIntegral, fromRealFrac, atan2,
+ fst, snd, id, const, (.), flip, ($), until, asTypeOf, error ) where
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+import PreludePrims
+
+import PreludeCore
+import PreludeList
+import PreludeArray
+import PreludeRatio
+import PreludeComplex
+import PreludeText
+import PreludeIO
+
+infixr 9 .
+infixr 8 ^, ^^
+infixr 3 &&
+infixr 2 ||
+infixr 0 $
+
+
+-- Binary functions
+
+nullBin :: Bin
+nullBin = primNullBin
+
+isNullBin :: Bin -> Bool
+isNullBin = primIsNullBin
+
+appendBin :: Bin -> Bin -> Bin
+appendBin = primAppendBin
+
+-- Boolean functions
+
+(&&), (||) :: Bool -> Bool -> Bool
+True && x = x
+False && _ = False
+True || _ = True
+False || x = x
+
+not :: Bool -> Bool
+not True = False
+not False = True
+
+{-# (&&) :: Inline #-}
+{-# (||) :: Inline #-}
+{-# not :: Inline #-}
+
+
+otherwise :: Bool
+otherwise = True
+
+-- Character functions
+
+minChar, maxChar :: Char
+minChar = '\0'
+maxChar = '\255'
+
+ord :: Char -> Int
+ord = primCharToInt
+
+chr :: Int -> Char
+chr = primIntToChar
+
+isAscii, isControl, isPrint, isSpace :: Char -> Bool
+isUpper, isLower, isAlpha, isDigit, isAlphanum :: Char -> Bool
+
+isAscii c = ord c < 128
+isControl c = c < ' ' || c == '\DEL'
+isPrint c = c >= ' ' && c <= '~'
+isSpace c = c == ' ' || c == '\t' || c == '\n' ||
+ c == '\r' || c == '\f' || c == '\v'
+isUpper c = c >= 'A' && c <= 'Z'
+isLower c = c >= 'a' && c <= 'z'
+isAlpha c = isUpper c || isLower c
+isDigit c = c >= '0' && c <= '9'
+isAlphanum c = isAlpha c || isDigit c
+
+
+toUpper, toLower :: Char -> Char
+toUpper c | isLower c = chr ((ord c - ord 'a') + ord 'A')
+ | otherwise = c
+
+toLower c | isUpper c = chr ((ord c - ord 'A') + ord 'a')
+ | otherwise = c
+
+-- Numeric functions
+
+minInt, maxInt :: Int
+minInt = primMinInt
+maxInt = primMaxInt
+
+subtract :: (Num a) => a -> a -> a
+subtract = flip (-)
+
+gcd :: (Integral a) => a -> a -> a
+gcd 0 0 = error "gcd{Prelude}: gcd 0 0 is undefined"
+gcd x y = gcd' (abs x) (abs y)
+ where gcd' x 0 = x
+ gcd' x y = gcd' y (x `rem` y)
+
+lcm :: (Integral a) => a -> a -> a
+lcm _ 0 = 0
+lcm 0 _ = 0
+lcm x y = abs ((x `quot` (gcd x y)) * y)
+
+(^) :: (Num a, Integral b) => a -> b -> a
+x ^ 0 = 1
+x ^ (n+1) = f x n x
+ where f _ 0 y = y
+ f x n y = g x n where
+ g x n | even n = g (x*x) (n `quot` 2)
+ | otherwise = f x (n-1) (x*y)
+_ ^ _ = error "(^){Prelude}: negative exponent"
+
+(^^) :: (Fractional a, Integral b) => a -> b -> a
+x ^^ n = if n >= 0 then x^n else recip (x^(-n))
+
+fromIntegral :: (Integral a, Num b) => a -> b
+fromIntegral = fromInteger . toInteger
+
+fromRealFrac :: (RealFrac a, Fractional b) => a -> b
+fromRealFrac = fromRational . toRational
+
+atan2 :: (RealFloat a) => a -> a -> a
+atan2 y x = case (signum y, signum x) of
+ ( 0, 1) -> 0
+ ( 1, 0) -> pi/2
+ ( 0,-1) -> pi
+ (-1, 0) -> -pi/2
+ ( _, 1) -> atan (y/x)
+ ( _,-1) -> atan (y/x) + pi
+ ( 0, 0) -> error "atan2{Prelude}: atan2 of origin"
+
+
+-- Some standard functions:
+-- component projections for pairs:
+fst :: (a,b) -> a
+fst (x,y) = x
+
+snd :: (a,b) -> b
+snd (x,y) = y
+
+-- identity function
+id :: a -> a
+id x = x
+
+-- constant function
+const :: a -> b -> a
+const x _ = x
+
+-- function composition
+(.) :: (b -> c) -> (a -> b) -> a -> c
+f . g = \ x -> f (g x)
+
+-- flip f takes its (first) two arguments in the reverse order of f.
+flip :: (a -> b -> c) -> b -> a -> c
+flip f x y = f y x
+
+-- right-associating infix application operator (useful in continuation-
+-- passing style)
+($) :: (a -> b) -> a -> b
+f $ x = f x
+
+-- until p f yields the result of applying f until p holds.
+until :: (a -> Bool) -> (a -> a) -> a -> a
+until p f x | p x = x
+ | otherwise = until p f (f x)
+
+-- asTypeOf is a type-restricted version of const. It is usually used
+-- as an infix operator, and its typing forces its first argument
+-- (which is usually overloaded) to have the same type as the second.
+asTypeOf :: a -> a -> a
+asTypeOf = const
diff --git a/progs/prelude/Prelude.hu b/progs/prelude/Prelude.hu
new file mode 100644
index 0000000..1ee32ca
--- /dev/null
+++ b/progs/prelude/Prelude.hu
@@ -0,0 +1,16 @@
+:output $PRELUDEBIN/Prelude
+:stable
+:prelude
+PreludePrims.hu
+PreludeArrayPrims.hu
+PreludeTuplePrims.hu
+PreludeIOPrims.hu
+Prelude.hs
+PreludeArray.hs
+PreludeComplex.hs
+PreludeCore.hs
+PreludeIO.hs
+PreludeList.hs
+PreludeRatio.hs
+PreludeText.hs
+PreludeTuple.hs
diff --git a/progs/prelude/PreludeArray.hs b/progs/prelude/PreludeArray.hs
new file mode 100644
index 0000000..a501631
--- /dev/null
+++ b/progs/prelude/PreludeArray.hs
@@ -0,0 +1,201 @@
+module PreludeArray ( Array, Assoc((:=)), array, listArray, (!), bounds,
+ indices, elems, assocs, accumArray, (//), accum, amap,
+ ixmap
+ ) where
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+-- This module uses some simple techniques with updatable vectors to
+-- avoid vector copying in loops where single threading is obvious.
+-- This is rather fragile and depends on the way the compiler handles
+-- strictness.
+
+import PreludeBltinArray
+
+infixl 9 !
+infixl 9 //
+infix 1 :=
+
+data Assoc a b = a := b deriving (Eq, Ord, Ix, Text, Binary)
+data (Ix a) => Array a b = MkArray (a,a) {-#STRICT#-}
+ (Vector (Box b)) {-#STRICT#-}
+ deriving ()
+
+array :: (Ix a) => (a,a) -> [Assoc a b] -> Array a b
+listArray :: (Ix a) => (a,a) -> [b] -> Array a b
+(!) :: (Ix a) => Array a b -> a -> b
+bounds :: (Ix a) => Array a b -> (a,a)
+indices :: (Ix a) => Array a b -> [a]
+elems :: (Ix a) => Array a b -> [b]
+assocs :: (Ix a) => Array a b -> [Assoc a b]
+accumArray :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [Assoc a c]
+ -> Array a b
+(//) :: (Ix a) => Array a b -> [Assoc a b] -> Array a b
+accum :: (Ix a) => (b -> c -> b) -> Array a b -> [Assoc a c]
+ -> Array a b
+amap :: (Ix a) => (b -> c) -> Array a b -> Array a c
+ixmap :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c
+ -> Array a c
+
+-- Arrays are a datatype containing a bounds pair and a vector of values.
+-- Uninitialized array elements contain an error value.
+
+-- Primitive vectors now contain only unboxed values. This permits us to
+-- treat array indexing as an atomic operation without forcing the element
+-- being accessed. The boxing and unboxing of array elements happens
+-- explicitly using these operations:
+
+data Box a = MkBox a
+unBox (MkBox x) = x
+{-# unBox :: Inline #-}
+
+
+-- Array construction and update using index/value associations share
+-- the same helper function.
+
+array b@(bmin, bmax) ivs =
+ let size = (index b bmax) + 1
+ v = primMakeVector size uninitializedArrayError
+ in (MkArray b (updateArrayIvs b v ivs))
+{-# array :: Inline #-}
+
+a@(MkArray b v) // ivs =
+ let v' = primCopyVector v
+ in (MkArray b (updateArrayIvs b v' ivs))
+{-# (//) :: Inline #-}
+
+updateArrayIvs b v ivs =
+ let g (i := x) next = strict1 (primVectorUpdate v (index b i) (MkBox x))
+ next
+ in foldr g v ivs
+{-# updateArrayIvs :: Inline #-}
+
+uninitializedArrayError =
+ MkBox (error "(!){PreludeArray}: uninitialized array element.")
+
+
+-- when mapping a list onto an array, be smart and don't do full index
+-- computation
+
+listArray b@(bmin, bmax) vs =
+ let size = (index b bmax) + 1
+ v = primMakeVector size uninitializedArrayError
+ in (MkArray b (updateArrayVs size v vs))
+{-# listArray :: Inline #-}
+
+updateArrayVs size v vs =
+ let g x next j = if (j == size)
+ then v
+ else strict1 (primVectorUpdate v j (MkBox x))
+ (next (j + 1))
+ in foldr g (\ _ -> v) vs 0
+{-# updateArrayVs :: Inline #-}
+
+
+-- Array access
+
+a@(MkArray b v) ! i = unBox (primVectorSel v (index b i))
+{-# (!) :: Inline #-}
+
+bounds (MkArray b _) = b
+
+indices = range . bounds
+
+
+-- Again, when mapping array elements into a list, be smart and don't do
+-- the full index computation for every element.
+
+elems a@(MkArray b@(bmin, bmax) v) =
+ build (\ c n ->
+ let size = (index b bmax) + 1
+ g j = if (j == size)
+ then n
+ else c (unBox (primVectorSel v j)) (g (j + 1))
+ -- This strict1 is so size doesn't get inlined and recomputed
+ -- at every iteration. It should also force the array argument
+ -- to be strict.
+ in strict1 size (g 0))
+{-# elems :: Inline #-}
+
+assocs a@(MkArray b@(bmin, bmax) v) =
+ build (\ c n ->
+ let g i next j = let y = unBox (primVectorSel v j)
+ in c (i := y) (next (j + 1))
+ in foldr g (\ _ -> n) (range b) 0)
+{-# assocs :: Inline #-}
+
+
+-- accum and accumArray share the same helper function. The difference is
+-- that accum makes a copy of an existing array and accumArray creates
+-- a new one with all elements initialized to the given value.
+
+accum f a@(MkArray b v) ivs =
+ let v' = primCopyVector v
+ in (MkArray b (accumArrayIvs f b v' ivs))
+{-# accum :: Inline #-}
+
+accumArray f z b@(bmin, bmax) ivs =
+ let size = (index b bmax) + 1
+ v = primMakeVector size (MkBox z)
+ in (MkArray b (accumArrayIvs f b v ivs))
+{-# accumArray :: Inline #-}
+
+
+-- This is a bit tricky. We need to force the access to the array element
+-- before the update, but not force the thunk that is the value of the
+-- array element unless f is strict.
+
+accumArrayIvs f b v ivs =
+ let g (i := x) next =
+ let j = index b i
+ y = primVectorSel v j
+ in strict1
+ y
+ (strict1 (primVectorUpdate v j (MkBox (f (unBox y) x)))
+ next)
+ in foldr g v ivs
+{-# accumArrayIvs :: Inline #-}
+
+
+-- again, be smart and bypass full array indexing on array mapping
+
+amap f a@(MkArray b@(bmin, bmax) v) =
+ let size = (index b bmax) + 1
+ v' = primMakeVector size uninitializedArrayError
+ g j = if (j == size)
+ then v'
+ else let y = primVectorSel v j
+ in strict1 (primVectorUpdate v' j (MkBox (f (unBox y))))
+ (g (j + 1))
+ in (MkArray b (g 0))
+{-# amap :: Inline #-}
+
+
+-- can't bypass the index computation here since f needs it as an argument
+
+ixmap b f a = array b [i := a ! f i | i <- range b]
+{-# ixmap :: Inline #-}
+
+
+-- random other stuff
+
+instance (Ix a, Eq b) => Eq (Array a b) where
+ a == a' = assocs a == assocs a'
+
+instance (Ix a, Ord b) => Ord (Array a b) where
+ a <= a' = assocs a <= assocs a'
+
+instance (Ix a, Text a, Text b) => Text (Array a b) where
+ showsPrec p a = showParen (p > 9) (
+ showString "array " .
+ shows (bounds a) . showChar ' ' .
+ shows (assocs a) )
+
+ readsPrec p = readParen (p > 9)
+ (\r -> [(array b as, u) | ("array",s) <- lex r,
+ (b,t) <- reads s,
+ (as,u) <- reads t ]
+ ++
+ [(listArray b xs, u) | ("listArray",s) <- lex r,
+ (b,t) <- reads s,
+ (xs,u) <- reads t ])
diff --git a/progs/prelude/PreludeArrayPrims.hi b/progs/prelude/PreludeArrayPrims.hi
new file mode 100644
index 0000000..a8529c0
--- /dev/null
+++ b/progs/prelude/PreludeArrayPrims.hi
@@ -0,0 +1,37 @@
+-- These primitives are used to implement arrays with constant time
+-- access. There are destructive update routines for arrays for use
+-- internally in functions such as array. These are impure but are
+-- marked as pure to keep them out of the top level monad. This should
+-- be redone using lambda-var someday.
+
+interface PreludeBltinArray where
+
+
+data Vector a -- Used to represent vectors with delayed components
+data Delay a -- An explicit represenation of a delayed object
+
+
+-- Primitive vectors now always have strict components. This permits us
+-- to treat array indexing as an atomic operation without the explicit
+-- force on access.
+
+primVectorSel :: Vector a -> Int -> a
+primVectorUpdate :: Vector a -> Int -> a -> a
+primMakeVector :: Int -> a -> Vector a
+primCopyVector :: Vector a -> Vector a
+
+-- These functions are used for explicit sequencing of destructive ops
+
+strict1 :: a -> b -> b
+primForce :: Delay a -> a
+
+{-#
+primVectorSel :: LispName("prim.vector-sel"), Complexity(1)
+primVectorUpdate :: LispName("prim.vector-update"), Complexity(1)
+primMakeVector :: LispName("prim.make-vector"), Complexity(4)
+primCopyVector :: LispName("prim.copy-vector"), Complexity(5)
+strict1 :: Strictness("S,N"),
+ LispName("prim.strict1")
+primForce :: LispName("prim.force")
+#-}
+
diff --git a/progs/prelude/PreludeArrayPrims.hu b/progs/prelude/PreludeArrayPrims.hu
new file mode 100644
index 0000000..62ea8ac
--- /dev/null
+++ b/progs/prelude/PreludeArrayPrims.hu
@@ -0,0 +1,4 @@
+:output $PRELUDEBIN/PreludeArrayPrims
+:stable
+:prelude
+PreludeArrayPrims.hi
diff --git a/progs/prelude/PreludeComplex.hs b/progs/prelude/PreludeComplex.hs
new file mode 100644
index 0000000..2044129
--- /dev/null
+++ b/progs/prelude/PreludeComplex.hs
@@ -0,0 +1,94 @@
+-- Complex Numbers
+
+module PreludeComplex where
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+infixl 6 :+
+
+data (RealFloat a) => Complex a = a {-#STRICT#-} :+ a {-#STRICT #-}
+ deriving (Eq,Binary,Text)
+
+instance (RealFloat a) => Num (Complex a) where
+ (x:+y) + (x':+y') = (x+x') :+ (y+y')
+ (x:+y) - (x':+y') = (x-x') :+ (y-y')
+ (x:+y) * (x':+y') = (x*x'-y*y') :+ (x*y'+y*x')
+ negate (x:+y) = negate x :+ negate y
+ abs z = magnitude z :+ 0
+ signum 0 = 0
+ signum z@(x:+y) = x/r :+ y/r where r = magnitude z
+ fromInteger n = fromInteger n :+ 0
+
+instance (RealFloat a) => Fractional (Complex a) where
+ (x:+y) / (x':+y') = (x*x''+y*y'') / d :+ (y*x''-x*y'') / d
+ where x'' = scaleFloat k x'
+ y'' = scaleFloat k y'
+ k = - max (exponent x') (exponent y')
+ d = x'*x'' + y'*y''
+
+ fromRational a = fromRational a :+ 0
+
+instance (RealFloat a) => Floating (Complex a) where
+ pi = pi :+ 0
+ exp (x:+y) = expx * cos y :+ expx * sin y
+ where expx = exp x
+ log z = log (magnitude z) :+ phase z
+
+ sqrt 0 = 0
+ sqrt z@(x:+y) = u :+ (if y < 0 then -v else v)
+ where (u,v) = if x < 0 then (v',u') else (u',v')
+ v' = abs y / (u'*2)
+ u' = sqrt ((magnitude z + abs x) / 2)
+
+ sin (x:+y) = sin x * cosh y :+ cos x * sinh y
+ cos (x:+y) = cos x * cosh y :+ (- sin x * sinh y)
+ tan (x:+y) = (sinx*coshy:+cosx*sinhy)/(cosx*coshy:+(-sinx*sinhy))
+ where sinx = sin x
+ cosx = cos x
+ sinhy = sinh y
+ coshy = cosh y
+
+ sinh (x:+y) = cos y * sinh x :+ sin y * cosh x
+ cosh (x:+y) = cos y * cosh x :+ sin y * sinh x
+ tanh (x:+y) = (cosy*sinhx:+siny*coshx)/(cosy*coshx:+siny*sinhx)
+ where siny = sin y
+ cosy = cos y
+ sinhx = sinh x
+ coshx = cosh x
+
+ asin z@(x:+y) = y':+(-x')
+ where (x':+y') = log (((-y):+x) + sqrt (1 - z*z))
+ acos z@(x:+y) = y'':+(-x'')
+ where (x'':+y'') = log (z + ((-y'):+x'))
+ (x':+y') = sqrt (1 - z*z)
+ atan z@(x:+y) = y':+(-x')
+ where (x':+y') = log (((1-y):+x) / sqrt (1+z*z))
+
+ asinh z = log (z + sqrt (1+z*z))
+ acosh z = log (z + (z+1) * sqrt ((z-1)/(z+1)))
+ atanh z = log ((1+z) / sqrt (1-z*z))
+
+
+realPart, imagPart :: (RealFloat a) => Complex a -> a
+realPart (x:+y) = x
+imagPart (x:+y) = y
+
+conjugate :: (RealFloat a) => Complex a -> Complex a
+conjugate (x:+y) = x :+ (-y)
+
+mkPolar :: (RealFloat a) => a -> a -> Complex a
+mkPolar r theta = r * cos theta :+ r * sin theta
+
+cis :: (RealFloat a) => a -> Complex a
+cis theta = cos theta :+ sin theta
+
+polar :: (RealFloat a) => Complex a -> (a,a)
+polar z = (magnitude z, phase z)
+
+magnitude, phase :: (RealFloat a) => Complex a -> a
+magnitude (x:+y) = scaleFloat k
+ (sqrt ((scaleFloat mk x)^2 + (scaleFloat mk y)^2))
+ where k = max (exponent x) (exponent y)
+ mk = - k
+
+phase (x:+y) = atan2 y x
diff --git a/progs/prelude/PreludeCore.hs b/progs/prelude/PreludeCore.hs
new file mode 100644
index 0000000..f8a7be2
--- /dev/null
+++ b/progs/prelude/PreludeCore.hs
@@ -0,0 +1,817 @@
+-- Standard types, classes, and instances
+
+module PreludeCore (
+ Eq((==), (/=)),
+ Ord((<), (<=), (>=), (>), max, min),
+ Num((+), (-), (*), negate, abs, signum, fromInteger),
+ Integral(quot, rem, div, mod, quotRem, divMod, even, odd, toInteger),
+ Fractional((/), recip, fromRational),
+ Floating(pi, exp, log, sqrt, (**), logBase,
+ sin, cos, tan, asin, acos, atan,
+ sinh, cosh, tanh, asinh, acosh, atanh),
+ Real(toRational),
+ RealFrac(properFraction, truncate, round, ceiling, floor),
+ RealFloat(floatRadix, floatDigits, floatRange,
+ encodeFloat, decodeFloat, exponent, significand, scaleFloat),
+ Ix(range, index, inRange),
+ Enum(enumFrom, enumFromThen, enumFromTo, enumFromThenTo),
+ Text(readsPrec, showsPrec, readList, showList), ReadS(..), ShowS(..),
+ Binary(readBin, showBin),
+-- List type: [_]((:), [])
+-- Tuple types: (_,_), (_,_,_), etc.
+-- Trivial type: ()
+ Bool(True, False),
+ Char, Int, Integer, Float, Double, Bin,
+ Ratio, Complex((:+)), Assoc((:=)), Array,
+ String(..), Rational(..) ) where
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+import PreludePrims
+import PreludeText
+import PreludeRatio(Ratio, Rational(..))
+import PreludeComplex(Complex((:+)))
+import PreludeArray(Assoc((:=)), Array)
+import PreludeIO({-Request, Response,-} IOError,
+ Dialogue(..), SuccCont(..), StrCont(..),
+ StrListCont(..), BinCont(..), FailCont(..))
+
+infixr 8 **
+infixl 7 *, /, `quot`, `rem`, `div`, `mod`
+infixl 6 +, -
+infix 4 ==, /=, <, <=, >=, >
+
+
+infixr 5 :
+
+data Int = MkInt
+data Integer = MkInteger
+data Float = MkFloat
+data Double = MkDouble
+data Char = MkChar
+data Bin = MkBin
+data List a = a : (List a) | Nil deriving (Eq, Ord)
+data Arrow a b = MkArrow a b
+data UnitType = UnitConstructor deriving (Eq, Ord, Ix, Enum, Binary)
+
+-- Equality and Ordered classes
+
+class Eq a where
+ (==), (/=) :: a -> a -> Bool
+
+ x /= y = not (x == y)
+
+class (Eq a) => Ord a where
+ (<), (<=), (>=), (>):: a -> a -> Bool
+ max, min :: a -> a -> a
+
+ x < y = x <= y && x /= y
+ x >= y = y <= x
+ x > y = y < x
+
+ -- The following default methods are appropriate for partial orders.
+ -- Note that the second guards in each function can be replaced
+ -- by "otherwise" and the error cases, eliminated for total orders.
+ max x y | x >= y = x
+ | y >= x = y
+ |otherwise = error "max{PreludeCore}: no ordering relation"
+ min x y | x <= y = x
+ | y <= x = y
+ |otherwise = error "min{PreludeCore}: no ordering relation"
+
+
+-- Numeric classes
+
+class (Eq a, Text a) => Num a where
+ (+), (-), (*) :: a -> a -> a
+ negate :: a -> a
+ abs, signum :: a -> a
+ fromInteger :: Integer -> a
+
+ x - y = x + negate y
+
+class (Num a, Enum a) => Real a where
+ toRational :: a -> Rational
+
+class (Real a, Ix a) => Integral a where
+ quot, rem, div, mod :: a -> a -> a
+ quotRem, divMod :: a -> a -> (a,a)
+ even, odd :: a -> Bool
+ toInteger :: a -> Integer
+
+ n `quot` d = q where (q,r) = quotRem n d
+ n `rem` d = r where (q,r) = quotRem n d
+ n `div` d = q where (q,r) = divMod n d
+ n `mod` d = r where (q,r) = divMod n d
+ divMod n d = if signum r == - signum d then (q-1, r+d) else qr
+ where qr@(q,r) = quotRem n d
+ even n = n `rem` 2 == 0
+ odd = not . even
+
+class (Num a) => Fractional a where
+ (/) :: a -> a -> a
+ recip :: a -> a
+ fromRational :: Rational -> a
+
+ recip x = 1 / x
+
+class (Fractional a) => Floating a where
+ pi :: a
+ exp, log, sqrt :: a -> a
+ (**), logBase :: a -> a -> a
+ sin, cos, tan :: a -> a
+ asin, acos, atan :: a -> a
+ sinh, cosh, tanh :: a -> a
+ asinh, acosh, atanh :: a -> a
+
+ x ** y = exp (log x * y)
+ logBase x y = log y / log x
+ sqrt x = x ** 0.5
+ tan x = sin x / cos x
+ tanh x = sinh x / cosh x
+
+class (Real a, Fractional a) => RealFrac a where
+ properFraction :: (Integral b) => a -> (b,a)
+ truncate, round :: (Integral b) => a -> b
+ ceiling, floor :: (Integral b) => a -> b
+
+ truncate x = m where (m,_) = properFraction x
+
+ round x = let (n,r) = properFraction x
+ m = if r < 0 then n - 1 else n + 1
+ in case signum (abs r - 0.5) of
+ -1 -> n
+ 0 -> if even n then n else m
+ 1 -> m
+
+ ceiling x = if r > 0 then n + 1 else n
+ where (n,r) = properFraction x
+
+ floor x = if r < 0 then n - 1 else n
+ where (n,r) = properFraction x
+
+class (RealFrac a, Floating a) => RealFloat a where
+ floatRadix :: a -> Integer
+ floatDigits :: a -> Int
+ floatRange :: a -> (Int,Int)
+ decodeFloat :: a -> (Integer,Int)
+ encodeFloat :: Integer -> Int -> a
+ exponent :: a -> Int
+ significand :: a -> a
+ scaleFloat :: Int -> a -> a
+
+ exponent x = if m == 0 then 0 else n + floatDigits x
+ where (m,n) = decodeFloat x
+
+ significand x = encodeFloat m (- floatDigits x)
+ where (m,_) = decodeFloat x
+
+ scaleFloat k x = encodeFloat m (n+k)
+ where (m,n) = decodeFloat x
+
+
+-- Index and Enumeration classes
+
+class (Ord a, Text a) => Ix a where -- This is a Yale modification
+ range :: (a,a) -> [a]
+ index :: (a,a) -> a -> Int
+ inRange :: (a,a) -> a -> Bool
+
+class (Ord a) => Enum a where
+ enumFrom :: a -> [a] -- [n..]
+ enumFromThen :: a -> a -> [a] -- [n,n'..]
+ enumFromTo :: a -> a -> [a] -- [n..m]
+ enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m]
+
+ enumFromTo = defaultEnumFromTo
+ enumFromThenTo = defaultEnumFromThenTo
+
+defaultEnumFromTo n m = takeWhile (<= m) (enumFrom n)
+defaultEnumFromThenTo n n' m
+ = takeWhile (if n' >= n then (<= m) else (>= m))
+ (enumFromThen n n')
+{-# defaultEnumFromTo :: Inline #-}
+{-# defaultEnumFromThenTo :: Inline #-}
+
+-- Text class
+
+type ReadS a = String -> [(a,String)]
+type ShowS = String -> String
+
+class Text a where
+ readsPrec :: Int -> ReadS a
+ showsPrec :: Int -> a -> ShowS
+ readList :: ReadS [a]
+ showList :: [a] -> ShowS
+
+ readList = readParen False (\r -> [pr | ("[",s) <- lex r,
+ pr <- readl s])
+ where readl s = [([],t) | ("]",t) <- lex s] ++
+ [(x:xs,u) | (x,t) <- reads s,
+ (xs,u) <- readl' t]
+ readl' s = [([],t) | ("]",t) <- lex s] ++
+ [(x:xs,v) | (",",t) <- lex s,
+ (x,u) <- reads t,
+ (xs,v) <- readl' u]
+ showList [] = showString "[]"
+ showList (x:xs)
+ = showChar '[' . shows x . showl xs
+ where showl [] = showChar ']'
+ showl (x:xs) = showString ", " . shows x . showl xs
+
+
+
+-- Binary class
+
+class Binary a where
+ readBin :: Bin -> (a,Bin)
+ showBin :: a -> Bin -> Bin
+
+
+-- Trivial type
+
+-- data () = () deriving (Eq, Ord, Ix, Enum, Binary)
+
+instance Text () where
+ readsPrec p = readParen False
+ (\r -> [((),t) | ("(",s) <- lex r,
+ (")",t) <- lex s ] )
+ showsPrec p () = showString "()"
+
+
+-- Binary type
+
+instance Text Bin where
+ readsPrec p s = error "readsPrec{PreludeText}: Cannot read Bin."
+ showsPrec p b = showString "<<Bin>>"
+
+
+-- Boolean type
+
+data Bool = False | True deriving (Eq, Ord, Ix, Enum, Text, Binary)
+
+
+-- Character type
+
+instance Eq Char where
+ (==) = primEqChar
+ (/=) = primNeqChar
+
+instance Ord Char where
+ (<) = primLsChar
+ (<=) = primLeChar
+ (>) = primGtChar
+ (>=) = primGeChar
+
+instance Ix Char where
+ range (c,c') = [c..c']
+ index b@(c,c') ci
+ | inRange b ci = ord ci - ord c
+ | otherwise = error "index{PreludeCore}: Index out of range."
+ inRange (c,c') ci = ord c <= i && i <= ord c'
+ where i = ord ci
+ {-# range :: Inline #-}
+
+instance Enum Char where
+ enumFrom = charEnumFrom
+ enumFromThen = charEnumFromThen
+ enumFromTo = defaultEnumFromTo
+ enumFromThenTo = defaultEnumFromThenTo
+ {-# enumFrom :: Inline #-}
+ {-# enumFromThen :: Inline #-}
+ {-# enumFromTo :: Inline #-}
+ {-# enumFromThenTo :: Inline #-}
+
+charEnumFrom c = map chr [ord c .. ord maxChar]
+charEnumFromThen c c' = map chr [ord c, ord c' .. ord lastChar]
+ where lastChar = if c' < c then minChar else maxChar
+{-# charEnumFrom :: Inline #-}
+{-# charEnumFromThen :: Inline #-}
+
+instance Text Char where
+ readsPrec p = readParen False
+ (\r -> [(c,t) | ('\'':s,t)<- lex r,
+ (c,_) <- readLitChar s])
+
+ showsPrec p '\'' = showString "'\\''"
+ showsPrec p c = showChar '\'' . showLitChar c . showChar '\''
+
+ readList = readParen False (\r -> [(l,t) | ('"':s, t) <- lex r,
+ (l,_) <- readl s ])
+ where readl ('"':s) = [("",s)]
+ readl ('\\':'&':s) = readl s
+ readl s = [(c:cs,u) | (c ,t) <- readLitChar s,
+ (cs,u) <- readl t ]
+
+ showList cs = showChar '"' . showl cs
+ where showl "" = showChar '"'
+ showl ('"':cs) = showString "\\\"" . showl cs
+ showl (c:cs) = showLitChar c . showl cs
+
+type String = [Char]
+
+
+-- Standard Integral types
+
+instance Eq Int where
+ (==) = primEqInt
+ (/=) = primNeqInt
+
+instance Eq Integer where
+ (==) = primEqInteger
+ (/=) = primNeqInteger
+
+instance Ord Int where
+ (<) = primLsInt
+ (<=) = primLeInt
+ (>) = primGtInt
+ (>=) = primGeInt
+ max = primIntMax
+ min = primIntMin
+
+instance Ord Integer where
+ (<) = primLsInteger
+ (<=) = primLeInteger
+ (>) = primGtInteger
+ (>=) = primGeInteger
+ max = primIntegerMax
+ min = primIntegerMin
+
+instance Num Int where
+ (+) = primPlusInt
+ (-) = primMinusInt
+ negate = primNegInt
+ (*) = primMulInt
+ abs = primAbsInt
+ signum = signumReal
+ fromInteger = primIntegerToInt
+
+instance Num Integer where
+ (+) = primPlusInteger
+ (-) = primMinusInteger
+ negate = primNegInteger
+ (*) = primMulInteger
+ abs = primAbsInteger
+ signum = signumReal
+ fromInteger x = x
+
+signumReal x | x == 0 = 0
+ | x > 0 = 1
+ | otherwise = -1
+
+instance Real Int where
+ toRational x = toInteger x % 1
+
+instance Real Integer where
+ toRational x = x % 1
+
+instance Integral Int where
+ quotRem = primQuotRemInt
+ toInteger = primIntToInteger
+
+instance Integral Integer where
+ quotRem = primQuotRemInteger
+ toInteger x = x
+
+instance Ix Int where
+ range (m,n) = [m..n]
+ index b@(m,n) i
+ | inRange b i = i - m
+ | otherwise = error "index{PreludeCore}: Index out of range."
+ inRange (m,n) i = m <= i && i <= n
+ {-# range :: Inline #-}
+
+instance Ix Integer where
+ range (m,n) = [m..n]
+ index b@(m,n) i
+ | inRange b i = fromInteger (i - m)
+ | otherwise = error "index{PreludeCore}: Index out of range."
+ inRange (m,n) i = m <= i && i <= n
+ {-# range :: Inline #-}
+
+instance Enum Int where
+ enumFrom = numericEnumFrom
+ enumFromThen = numericEnumFromThen
+ enumFromTo = defaultEnumFromTo
+ enumFromThenTo = defaultEnumFromThenTo
+ {-# enumFrom :: Inline #-}
+ {-# enumFromThen :: Inline #-}
+ {-# enumFromTo :: Inline #-}
+ {-# enumFromThenTo :: Inline #-}
+
+instance Enum Integer where
+ enumFrom = numericEnumFrom
+ enumFromThen = numericEnumFromThen
+ enumFromTo = defaultEnumFromTo
+ enumFromThenTo = defaultEnumFromThenTo
+ {-# enumFrom :: Inline #-}
+ {-# enumFromThen :: Inline #-}
+ {-# enumFromTo :: Inline #-}
+ {-# enumFromThenTo :: Inline #-}
+
+numericEnumFrom :: (Real a) => a -> [a]
+numericEnumFromThen :: (Real a) => a -> a -> [a]
+numericEnumFrom = iterate (+1)
+numericEnumFromThen n m = iterate (+(m-n)) n
+
+{-# numericEnumFrom :: Inline #-}
+{-# numericEnumFromThen :: Inline #-}
+
+
+instance Text Int where
+ readsPrec p = readSigned readDec
+ showsPrec = showSigned showInt
+
+instance Text Integer where
+ readsPrec p = readSigned readDec
+ showsPrec = showSigned showInt
+
+
+-- Standard Floating types
+
+instance Eq Float where
+ (==) = primEqFloat
+ (/=) = primNeqFloat
+
+instance Eq Double where
+ (==) = primEqDouble
+ (/=) = primNeqDouble
+
+instance Ord Float where
+ (<) = primLsFloat
+ (<=) = primLeFloat
+ (>) = primGtFloat
+ (>=) = primGeFloat
+ max = primFloatMax
+ min = primFloatMin
+
+instance Ord Double where
+ (<) = primLsDouble
+ (<=) = primLeDouble
+ (>) = primGtDouble
+ (>=) = primGeDouble
+ max = primDoubleMax
+ min = primDoubleMax
+
+instance Num Float where
+ (+) = primPlusFloat
+ (-) = primMinusFloat
+ negate = primNegFloat
+ (*) = primMulFloat
+ abs = primAbsFloat
+ signum = signumReal
+ fromInteger n = encodeFloat n 0
+
+instance Num Double where
+ (+) = primPlusDouble
+ (-) = primMinusDouble
+ negate = primNegDouble
+ (*) = primMulDouble
+ abs = primAbsDouble
+ signum = signumReal
+ fromInteger n = encodeFloat n 0
+
+instance Real Float where
+ toRational = primFloatToRational
+
+instance Real Double where
+ toRational = primDoubleToRational
+
+-- realFloatToRational x = (m%1)*(b%1)^^n
+-- where (m,n) = decodeFloat x
+-- b = floatRadix x
+
+instance Fractional Float where
+ (/) = primDivFloat
+ fromRational = primRationalToFloat
+-- fromRational = rationalToRealFloat
+
+instance Fractional Double where
+ (/) = primDivDouble
+ fromRational = primRationalToDouble
+-- fromRational = rationalToRealFloat
+
+-- rationalToRealFloat x = x'
+-- where x' = f e
+-- f e = if e' == e then y else f e'
+-- where y = encodeFloat (round (x * (1%b)^^e)) e
+-- (_,e') = decodeFloat y
+-- (_,e) = decodeFloat (fromInteger (numerator x) `asTypeOf` x'
+-- / fromInteger (denominator x))
+-- b = floatRadix x'
+
+instance Floating Float where
+ pi = primPiFloat
+ exp = primExpFloat
+ log = primLogFloat
+ sqrt = primSqrtFloat
+ sin = primSinFloat
+ cos = primCosFloat
+ tan = primTanFloat
+ asin = primAsinFloat
+ acos = primAcosFloat
+ atan = primAtanFloat
+ sinh = primSinhFloat
+ cosh = primCoshFloat
+ tanh = primTanhFloat
+ asinh = primAsinhFloat
+ acosh = primAcoshFloat
+ atanh = primAtanhFloat
+
+instance Floating Double where
+ pi = primPiDouble
+ exp = primExpDouble
+ log = primLogDouble
+ sqrt = primSqrtDouble
+ sin = primSinDouble
+ cos = primCosDouble
+ tan = primTanDouble
+ asin = primAsinDouble
+ acos = primAcosDouble
+ atan = primAtanDouble
+ sinh = primSinhDouble
+ cosh = primCoshDouble
+ tanh = primTanhDouble
+ asinh = primAsinhDouble
+ acosh = primAcoshDouble
+ atanh = primAtanhDouble
+
+
+instance RealFrac Float where
+ properFraction = floatProperFraction
+
+instance RealFrac Double where
+ properFraction = floatProperFraction
+
+floatProperFraction x
+ | n >= 0 = (fromInteger m * fromInteger b ^ n, 0)
+ | otherwise = (fromInteger w, encodeFloat r n)
+ where (m,n) = decodeFloat x
+ b = floatRadix x
+ (w,r) = quotRem m (b^(-n))
+
+instance RealFloat Float where
+ floatRadix _ = primFloatRadix
+ floatDigits _ = primFloatDigits
+ floatRange _ = (primFloatMinExp,primFloatMaxExp)
+ decodeFloat = primDecodeFloat
+ encodeFloat = primEncodeFloat
+
+instance RealFloat Double where
+ floatRadix _ = primDoubleRadix
+ floatDigits _ = primDoubleDigits
+ floatRange _ = (primDoubleMinExp,primDoubleMaxExp)
+ decodeFloat = primDecodeDouble
+ encodeFloat = primEncodeDouble
+
+instance Enum Float where
+ enumFrom = numericEnumFrom
+ enumFromThen = numericEnumFromThen
+ enumFromTo = defaultEnumFromTo
+ enumFromThenTo = defaultEnumFromThenTo
+ {-# enumFrom :: Inline #-}
+ {-# enumFromThen :: Inline #-}
+ {-# enumFromTo :: Inline #-}
+ {-# enumFromThenTo :: Inline #-}
+
+instance Enum Double where
+ enumFrom = numericEnumFrom
+ enumFromThen = numericEnumFromThen
+ enumFromTo = defaultEnumFromTo
+ enumFromThenTo = defaultEnumFromThenTo
+ {-# enumFrom :: Inline #-}
+ {-# enumFromThen :: Inline #-}
+ {-# enumFromTo :: Inline #-}
+ {-# enumFromThenTo :: Inline #-}
+
+instance Text Float where
+ readsPrec p = readSigned readFloat
+ showsPrec = showSigned showFloat
+
+instance Text Double where
+ readsPrec p = readSigned readFloat
+ showsPrec = showSigned showFloat
+
+
+-- Lists
+
+-- data [a] = [] | a : [a] deriving (Eq, Ord, Binary)
+
+instance (Text a) => Text [a] where
+ readsPrec p = readList
+ showsPrec p = showList
+
+
+-- Tuples
+
+-- data (a,b) = (a,b) deriving (Eq, Ord, Ix, Binary)
+{-
+instance (Text a, Text b) => Text (a,b) where
+ readsPrec p = readParen False
+ (\r -> [((x,y), w) | ("(",s) <- lex r,
+ (x,t) <- reads s,
+ (",",u) <- lex t,
+ (y,v) <- reads u,
+ (")",w) <- lex v ] )
+
+ showsPrec p (x,y) = showChar '(' . shows x . showChar ',' .
+ shows y . showChar ')'
+-- et cetera
+-}
+
+-- Functions
+
+instance Text (a -> b) where
+ readsPrec p s = error "readsPrec{PreludeCore}: Cannot read functions."
+ showsPrec p f = showString "<<function>>"
+
+-- Support for class Bin
+
+instance Binary Int where
+ showBin i b = primShowBinInt i b
+ readBin b = primReadBinInt b
+
+instance Binary Integer where
+ showBin i b = primShowBinInteger i b
+ readBin b = primReadBinInteger b
+
+instance Binary Float where
+ showBin f b = primShowBinFloat f b
+ readBin b = primReadBinFloat b
+
+instance Binary Double where
+ showBin d b = primShowBinDouble d b
+ readBin b = primReadBinDouble b
+
+instance Binary Char where
+ showBin c b = primShowBinInt (ord c) b
+ readBin b = (chr i,b') where
+ (i,b') = primReadBinSmallInt b primMaxChar
+
+instance (Binary a) => Binary [a] where
+ showBin l b = showBin (length l :: Int) (sb1 l b) where
+ sb1 [] b = b
+ sb1 (h:t) b = showBin h (sb1 t b)
+ readBin bin = rbl len bin' where
+ len :: Int
+ (len,bin') = readBin bin
+ rbl 0 b = ([],b)
+ rbl n b = (h:t,b'') where
+ (h,b') = readBin b
+ (t,b'') = rbl (n-1) b'
+
+instance (Ix a, Binary a, Binary b) => Binary (Array a b) where
+ showBin a = showBin (bounds a) . showBin (elems a)
+ readBin bin = (listArray b vs, bin'')
+ where (b,bin') = readBin bin
+ (vs,bin'') = readBin bin'
+
+{-
+instance (Binary a, Binary b) => Binary (a,b) where
+ showBin (x,y) = (showBin x) . (showBin y)
+ readBin b = ((x,y),b'') where
+ (x,b') = readBin b
+ (y,b'') = readBin b'
+
+instance (Binary a, Binary b, Binary c) => Binary (a,b,c) where
+ showBin (x,y,z) = (showBin x) . (showBin y) . (showBin z)
+ readBin b = ((x,y,z),b3) where
+ (x,b1) = readBin b
+ (y,b2) = readBin b1
+ (z,b3) = readBin b2
+
+instance (Binary a, Binary b, Binary c, Binary d) => Binary (a,b,c,d) where
+ showBin (a,b,c,d) = (showBin a) . (showBin b) . (showBin c) . (showBin d)
+ readBin b = ((a1,a2,a3,a4),b4) where
+ (a1,b1) = readBin b
+ (a2,b2) = readBin b1
+ (a3,b3) = readBin b2
+ (a4,b4) = readBin b3
+-}
+-- Instances for tuples
+
+-- This whole section should be handled in the support code. For now,
+-- only tuple instances expliticly provided here are available.
+-- Currently provided:
+
+-- 2,3 tuples: all classes (Eq, Ord, Ix, Bin, Text)
+-- 4 tuples: Eq, Bin, Text
+-- 5, 6 tuples: Text (printing only)
+
+{-
+rangeSize :: (Ix a) => (a,a) -> Int
+rangeSize (l,u) = index (l,u) u + 1
+
+instance (Eq a1, Eq a2) => Eq (a1,a2) where
+ (a1,a2) == (z1,z2) = a1==z1 && a2==z2
+
+instance (Ord a1, Ord a2) => Ord (a1,a2) where
+ (a1,a2) <= (z1,z2) = a1<=z1 || a1==z1 && a2<=z2
+ (a1,a2) < (z1,z2) = a1<z1 || a1==z1 && a2<z2
+
+instance (Ix a1, Ix a2) => Ix (a1,a2) where
+ range ((l1,l2),(u1,u2)) = [(i1,i2) | i1 <- range(l1,u1),
+ i2 <- range(l2,u2)]
+ index ((l1,l2),(u1,u2)) (i1,i2) =
+ index (l1,u1) i1 * rangeSize (l2,u2)
+ + index (l2,u2) i2
+ inRange ((l1,l2),(u1,u2)) (i1,i2) =
+ inRange (l1,u1) i1 && inRange (l2,u2) i2
+
+{- Apprears in Joe's code.
+instance (Text a1, Text a2) => Text (a1,a2) where
+ readsPrec p = readParen False
+ (\r0 -> [((a1,a2), w) | ("(",r1) <- lex r0,
+ (a1,r2) <- reads r1,
+ (",",r3) <- lex r2,
+ (a2,r4) <- reads r3,
+ (")",w) <- lex r4 ])
+
+ showsPrec p (a1,a2) = showChar '(' . shows a1 . showChar ',' .
+ shows a2 . showChar ')'
+-}
+
+instance (Eq a1, Eq a2, Eq a3) => Eq (a1,a2,a3) where
+ (a1,a2,a3) == (z1,z2,z3) = a1==z1 && a2==z2 && a3==z3
+
+instance (Ord a1, Ord a2, Ord a3) => Ord (a1,a2,a3) where
+ (a1,a2,a3) <= (z1,z2,z3) = a1<=z1 || a1==z1 &&
+ (a2<=z2 || a2==z2 &&
+ a3<=z3)
+ (a1,a2,a3) < (z1,z2,z3) = a1<z1 || a1==z1 &&
+ (a2<z2 || a2==z2 &&
+ a3<z3)
+
+
+instance (Ix a1, Ix a2, Ix a3) => Ix (a1,a2,a3) where
+ range ((l1,l2,l3),(u1,u2,u3)) =
+ [(i1,i2,i3) | i1 <- range(l1,u1),
+ i2 <- range(l2,u2),
+ i3 <- range(l3,u3)]
+ index ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
+ (index (l1,u1) i1 * rangeSize (l2,u2)
+ + index (l2,u2) i2 ) * rangeSize (l3,u3)
+ + index (l3,u3) i3
+ inRange ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
+ inRange (l1,u1) i1 && inRange (l2,u2) i2 && inRange (l3,u3) i3
+
+
+instance (Text a1, Text a2, Text a3) => Text (a1,a2,a3) where
+ readsPrec p = readParen False
+ (\r0 -> [((a1,a2,a3), w) |
+ ("(",r1) <- lex r0,
+ (a1,r2) <- reads r1,
+ (",",r3) <- lex r2,
+ (a2,r4) <- reads r3,
+ (",",r5) <- lex r4,
+ (a3,r6) <- reads r5,
+ (")",w) <- lex r6 ])
+ showsPrec p (a1,a2,a3) =
+ showChar '(' . shows a1 . showChar ',' .
+ shows a2 . showChar ',' .
+ shows a3 . showChar ')'
+
+instance (Eq a1, Eq a2, Eq a3, Eq a4) => Eq (a1,a2,a3,a4) where
+ (a1,a2,a3,a4) == (z1,z2,z3,z4) = a1==z1 && a2==z2 && a3==z3 && a4 == z4
+
+instance (Text a1, Text a2, Text a3, Text a4) => Text (a1,a2,a3,a4) where
+ readsPrec p = readParen False
+ (\r0 -> [((a1,a2,a3,a4), w) |
+ ("(",r1) <- lex r0,
+ (a1,r2) <- reads r1,
+ (",",r3) <- lex r2,
+ (a2,r4) <- reads r3,
+ (",",r5) <- lex r4,
+ (a3,r6) <- reads r5,
+ (",",r7) <- lex r6,
+ (a4,r8) <- reads r7,
+ (")",w) <- lex r8 ])
+ showsPrec p (a1,a2,a3,a4) =
+ showChar '(' . shows a1 . showChar ',' .
+ shows a2 . showChar ',' .
+ shows a3 . showChar ',' .
+ shows a4 . showChar ')'
+
+instance (Text a1, Text a2, Text a3, Text a4, Text a5) =>
+ Text (a1,a2,a3,a4,a5) where
+ readsPrec p = error "Read of 5 tuples not implemented"
+ showsPrec p (a1,a2,a3,a4,a5) =
+ showChar '(' . shows a1 . showChar ',' .
+ shows a2 . showChar ',' .
+ shows a3 . showChar ',' .
+ shows a4 . showChar ',' .
+ shows a5 . showChar ')'
+
+instance (Text a1, Text a2, Text a3, Text a4, Text a5, Text a6) =>
+ Text (a1,a2,a3,a4,a5,a6) where
+ readsPrec p = error "Read of 6 tuples not implemented"
+ showsPrec p (a1,a2,a3,a4,a5,a6) =
+ showChar '(' . shows a1 . showChar ',' .
+ shows a2 . showChar ',' .
+ shows a3 . showChar ',' .
+ shows a4 . showChar ',' .
+ shows a5 . showChar ',' .
+ shows a6 . showChar ')'
+
+
+-}
diff --git a/progs/prelude/PreludeIO.hs b/progs/prelude/PreludeIO.hs
new file mode 100644
index 0000000..6173d8c
--- /dev/null
+++ b/progs/prelude/PreludeIO.hs
@@ -0,0 +1,232 @@
+-- I/O functions and definitions
+
+module PreludeIO(stdin,stdout,stderr,stdecho,{-Request(..),Response(..),-}
+ IOError(..),Dialogue(..),IO(..),SystemState,IOResult,
+ SuccCont(..),StrCont(..),
+ StrListCont(..),BinCont(..),FailCont(..),
+ readFile, writeFile, appendFile, readBinFile,
+ writeBinFile, appendBinFile, deleteFile, statusFile,
+ readChan, appendChan, readBinChan, appendBinChan,
+ statusChan, echo, getArgs, getProgName, getEnv, setEnv,
+ done, exit, abort, print, prints, interact,
+ thenIO,thenIO_,seqIO,returnIO, doneIO)
+ where
+
+import PreludeBltinIO
+import PreludeBltinArray(strict1)
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+-- These datatypes are used by the monad.
+
+type IO a = SystemState -> IOResult a
+
+data SystemState = SystemState
+data IOResult a = IOResult a
+
+-- Operations in the monad
+
+-- This definition is needed to allow proper tail recursion of the Lisp
+-- code. The use of strict1 forces f1 s (since getState is strict) before
+-- the call to f2. The optimizer removed getState and getRes from the
+-- generated code.
+
+{-# thenIO :: Inline #-}
+thenIO f1 f2 s =
+ let g = f1 s
+ s' = getState g in
+ strict1 s' (f2 (getRes g) s')
+
+{-# thenIO_ :: Inline #-}
+x `thenIO_` y = x `thenIO` \_ -> y
+x `seqIO` y = x `thenIO` \_ -> y
+
+-- The returnIO function is implemented directly as a primitive.
+doneIO = returnIO ()
+
+
+-- File and channel names:
+
+stdin = "stdin"
+stdout = "stdout"
+stderr = "stderr"
+stdecho = "stdecho"
+
+
+-- Requests and responses:
+
+{- Not used since streams are no longer supported:
+data Request = -- file system requests:
+ ReadFile String
+ | WriteFile String String
+ | AppendFile String String
+ | ReadBinFile String
+ | WriteBinFile String Bin
+ | AppendBinFile String Bin
+ | DeleteFile String
+ | StatusFile String
+ -- channel system requests:
+ | ReadChan String
+ | AppendChan String String
+ | ReadBinChan String
+ | AppendBinChan String Bin
+ | StatusChan String
+ -- environment requests:
+ | Echo Bool
+ | GetArgs
+ | GetProgName
+ | GetEnv String
+ | SetEnv String String
+ deriving Text
+
+data Response = Success
+ | Str String
+ | StrList [String]
+ | Bn Bin
+ | Failure IOError
+ deriving Text
+
+-}
+
+data IOError = WriteError String
+ | ReadError String
+ | SearchError String
+ | FormatError String
+ | OtherError String
+ deriving Text
+
+-- Continuation-based I/O:
+
+type Dialogue = IO ()
+type SuccCont = Dialogue
+type StrCont = String -> Dialogue
+type StrListCont = [String] -> Dialogue
+type BinCont = Bin -> Dialogue
+type FailCont = IOError -> Dialogue
+
+done :: Dialogue
+readFile :: String -> FailCont -> StrCont -> Dialogue
+writeFile :: String -> String -> FailCont -> SuccCont -> Dialogue
+appendFile :: String -> String -> FailCont -> SuccCont -> Dialogue
+readBinFile :: String -> FailCont -> BinCont -> Dialogue
+writeBinFile :: String -> Bin -> FailCont -> SuccCont -> Dialogue
+appendBinFile :: String -> Bin -> FailCont -> SuccCont -> Dialogue
+deleteFile :: String -> FailCont -> SuccCont -> Dialogue
+statusFile :: String -> FailCont -> StrCont -> Dialogue
+readChan :: String -> FailCont -> StrCont -> Dialogue
+appendChan :: String -> String -> FailCont -> SuccCont -> Dialogue
+readBinChan :: String -> FailCont -> BinCont -> Dialogue
+appendBinChan :: String -> Bin -> FailCont -> SuccCont -> Dialogue
+statusChan :: String -> FailCont -> StrCont -> Dialogue
+echo :: Bool -> FailCont -> SuccCont -> Dialogue
+getArgs :: FailCont -> StrListCont -> Dialogue
+getProgName :: FailCont -> StrCont -> Dialogue
+getEnv :: String -> FailCont -> StrCont -> Dialogue
+setEnv :: String -> String -> FailCont -> SuccCont -> Dialogue
+
+done = returnIO ()
+
+readFile name fail succ =
+ primReadStringFile name `thenIO` objDispatch fail succ
+
+writeFile name contents fail succ =
+ primWriteStringFile name contents `thenIO` succDispatch fail succ
+
+appendFile name contents fail succ =
+ primAppendStringFile name contents `thenIO` succDispatch fail succ
+
+readBinFile name fail succ =
+ primReadBinFile name `thenIO` objDispatch fail succ
+
+writeBinFile name contents fail succ =
+ primWriteBinFile name contents `thenIO` succDispatch fail succ
+
+appendBinFile name contents fail succ =
+ primAppendBinFile name contents `thenIO` succDispatch fail succ
+
+deleteFile name fail succ =
+ primDeleteFile name `thenIO` succDispatch fail succ
+
+statusFile name fail succ =
+ primStatusFile name `thenIO`
+ (\status -> case status of Succ s -> succ s
+ Fail msg -> fail (SearchError msg))
+
+readChan name fail succ =
+ if name == stdin then
+ primReadStdin `thenIO` succ
+ else
+ badChan fail name
+
+appendChan name contents fail succ =
+ if name == stdout then
+ primWriteStdout contents `thenIO` succDispatch fail succ
+ else
+ badChan fail name
+
+readBinChan name fail succ =
+ if name == stdin then
+ primReadBinStdin `thenIO` objDispatch fail succ
+ else
+ badChan fail name
+
+appendBinChan name contents fail succ =
+ if name == stdout then
+ primWriteBinStdout contents `thenIO` succDispatch fail succ
+ else
+ badChan fail name
+
+statusChan name fail succ =
+ if name == stdin || name == stdout then
+ succ "0 0"
+ else
+ fail (SearchError "Channel not defined")
+
+echo bool fail succ =
+ if bool then
+ succ
+ else
+ fail (OtherError "Echo cannot be turned off")
+
+getArgs fail succ =
+ succ [""]
+
+getProgName fail succ =
+ succ "haskell"
+
+getEnv name fail succ =
+ primGetEnv name `thenIO` objDispatch fail succ
+
+setEnv name val fail succ =
+ fail (OtherError "setEnv not implemented")
+
+objDispatch fail succ r =
+ case r of Succ s -> succ s
+ Fail msg -> fail (OtherError msg)
+
+succDispatch fail succ r =
+ case r of Succ _ -> succ
+ Fail msg -> fail (OtherError msg)
+
+badChan f name = f (OtherError ("Improper IO Channel: " ++ name))
+
+abort :: FailCont
+abort err = done
+
+exit :: FailCont
+exit err = appendChan stderr (msg ++ "\n") abort done
+ where msg = case err of ReadError s -> s
+ WriteError s -> s
+ SearchError s -> s
+ FormatError s -> s
+ OtherError s -> s
+
+print :: (Text a) => a -> Dialogue
+print x = appendChan stdout (show x) exit done
+prints :: (Text a) => a -> String -> Dialogue
+prints x s = appendChan stdout (shows x s) exit done
+
+interact :: (String -> String) -> Dialogue
+interact f = readChan stdin exit
+ (\x -> appendChan stdout (f x) exit done)
+
diff --git a/progs/prelude/PreludeIOMonad.hs b/progs/prelude/PreludeIOMonad.hs
new file mode 100644
index 0000000..9a45606
--- /dev/null
+++ b/progs/prelude/PreludeIOMonad.hs
@@ -0,0 +1,60 @@
+module IOMonad (State, IO(..)) where
+
+import IOMonadPrims
+
+{- I use data instead of type so that IO can be abstract. For efficiency,
+ IO can be annotated as a strict constructor.
+-}
+
+type IO a = State -> (State, a)
+
+data State = State
+
+-- The rest of this file is unnecessary at the moment since
+-- unitIO & bindIO are primitives and we're not using the rest of this
+
+{- Implemented as a primitives:
+bindIO :: IO a -> (a -> IO b) -> IO b
+bindIO (IO m) (IO k) = IO (\s0 -> let (s1, a) = m s0 in k a s1) -}
+
+unitIO :: a -> IO a
+unitIO x = IO (\s -> (s, x))
+
+-}
+
+{- Not currently used:
+pureIO :: IO a -> a
+pureIO (IO m) = let (s, x) = m State in x
+
+-- execIO executes a program of type IO ().
+execIO :: IO () -> State
+execIO (IO m) = let (s, x) = m State in s
+
+infixr 1 =:
+infixr 1 ?
+
+-- assignment
+(=:) :: a -> Var a -> IO ()
+x =: v = IO (\s -> (update v x s, ()))
+
+-- reader
+(?) :: Var a -> (a -> IO b) -> IO b
+v ? k = IO (\s -> (s, readVar v s)) `bindIO` k
+
+-- new
+newvar :: IO (Var a)
+newvar = IO allocVar
+
+instance Eq (Var a) where
+ x == y = eqVar x y
+-}
+
+
+
+
+
+
+
+
+
+
diff --git a/progs/prelude/PreludeIOPrims.hi b/progs/prelude/PreludeIOPrims.hi
new file mode 100644
index 0000000..e4c2e74
--- /dev/null
+++ b/progs/prelude/PreludeIOPrims.hi
@@ -0,0 +1,55 @@
+-- These lisp functions implement the standard Haskell requests
+
+interface PreludeBltinIO where
+
+import PreludeCore(String,Bin)
+import PreludeIO(SystemState,IOResult,IO)
+data IOResponse a = Succ a | Fail String
+
+{-# Prelude #-}
+
+primReadStringFile :: String -> IO (IOResponse String)
+primWriteStringFile :: String -> String -> IO (IOResponse ())
+primAppendStringFile :: String -> String -> IO (IOResponse ())
+primReadBinFile :: String -> IO (IOResponse Bin)
+primWriteBinFile :: String -> Bin -> IO (IOResponse ())
+primAppendBinFile :: String -> Bin -> IO (IOResponse ())
+primDeleteFile :: String -> IO (IOResponse ())
+primStatusFile :: String -> IO (IOResponse String)
+primReadStdin :: IO String
+primWriteStdout :: String -> IO (IOResponse ())
+primReadBinStdin :: IO (IOResponse Bin)
+primWriteBinStdout :: Bin -> IO (IOResponse ())
+primGetEnv :: String -> IO (IOResponse String)
+
+{-#
+primReadStringFile :: LispName("prim.read-string-file")
+primWriteStringFile :: LispName("prim.write-string-file"), NoConversion
+primAppendStringFile :: LispName("prim.append-string-file"), NoConversion
+primReadBinFile :: LispName("prim.read-bin-file")
+primWriteBinFile :: LispName("prim.write-bin-file")
+primAppendBinFile :: LispName("prim.append-bin-file")
+primDeleteFile :: LispName("prim.delete-file")
+primStatusFile :: LispName("prim.status-file")
+primReadStdin :: LispName("prim.read-string-stdin"), NoConversion
+primWriteStdout :: LispName("prim.write-string-stdout"), NoConversion
+primReadBinStdin :: LispName("prim.read-bin-stdin")
+primWriteBinStdout :: LispName("prim.write-bin-stdout")
+primGetEnv :: LispName("prim.getenv")
+#-}
+
+-- Monad prims
+
+returnIO :: a -> IO a
+getState :: IOResult a -> SystemState
+getRes :: IOResult a -> a
+
+{-#
+returnIO :: LispName("prim.returnio"),
+ Strictness("N,S"), NoConversion, Complexity(3)
+getState :: LispName("prim.getstate"),
+ Strictness("S"), NoConversion, Complexity(3)
+getRes :: LispName("prim.getres"),
+ Strictness("S"), NoConversion
+#-}
+
diff --git a/progs/prelude/PreludeIOPrims.hu b/progs/prelude/PreludeIOPrims.hu
new file mode 100644
index 0000000..66393c5
--- /dev/null
+++ b/progs/prelude/PreludeIOPrims.hu
@@ -0,0 +1,4 @@
+:output $PRELUDEBIN/PreludeIOPrims
+:stable
+:prelude
+PreludeIOPrims.hi
diff --git a/progs/prelude/PreludeList.hs b/progs/prelude/PreludeList.hs
new file mode 100644
index 0000000..3e445c3
--- /dev/null
+++ b/progs/prelude/PreludeList.hs
@@ -0,0 +1,585 @@
+-- Standard list functions
+
+-- build really shouldn't be exported, but what the heck.
+-- some of the helper functions in this file shouldn't be
+-- exported either!
+
+module PreludeList (PreludeList.., foldr, build) where
+
+import PreludePrims(build, foldr)
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+infixl 9 !!
+infix 5 \\
+infixr 5 ++
+infix 4 `elem`, `notElem`
+
+
+-- These are primitives used by the deforestation stuff in the optimizer.
+-- the optimizer will turn references to foldr and build into
+-- inlineFoldr and inlineBuild, respectively, but doesn't want to
+-- necessarily inline all references immediately.
+
+inlineFoldr :: (a -> b -> b) -> b -> [a] -> b
+inlineFoldr f z l =
+ let foldr' [] = z
+ foldr' (x:xs) = f x (foldr' xs)
+ in foldr' l
+{-# inlineFoldr :: Inline #-}
+
+
+inlineBuild :: ((a -> [a] -> [a]) -> [b] -> [c]) -> [c]
+inlineBuild g = g (:) []
+{-# inlineBuild :: Inline #-}
+
+
+-- head and tail extract the first element and remaining elements,
+-- respectively, of a list, which must be non-empty. last and init
+-- are the dual functions working from the end of a finite list,
+-- rather than the beginning.
+
+head :: [a] -> a
+head (x:_) = x
+head [] = error "head{PreludeList}: head []"
+
+last :: [a] -> a
+last [x] = x
+last (_:xs) = last xs
+last [] = error "last{PreludeList}: last []"
+
+tail :: [a] -> [a]
+tail (_:xs) = xs
+tail [] = error "tail{PreludeList}: tail []"
+
+init :: [a] -> [a]
+init [x] = []
+init (x:xs) = x : init xs
+init [] = error "init{PreludeList}: init []"
+
+-- null determines if a list is empty.
+null :: [a] -> Bool
+null [] = True
+null (_:_) = False
+
+
+-- list concatenation (right-associative)
+
+(++) :: [a] -> [a] -> [a]
+xs ++ ys = build (\ c n -> foldr c (foldr c n ys) xs)
+{-# (++) :: Inline #-}
+
+
+-- the first occurrence of each element of ys in turn (if any)
+-- has been removed from xs. Thus, (xs ++ ys) \\ xs == ys.
+(\\) :: (Eq a) => [a] -> [a] -> [a]
+(\\) = foldl del
+ where [] `del` _ = []
+ (x:xs) `del` y
+ | x == y = xs
+ | otherwise = x : xs `del` y
+
+-- length returns the length of a finite list as an Int; it is an instance
+-- of the more general genericLength, the result type of which may be
+-- any kind of number.
+
+genericLength :: (Num a) => [b] -> a
+genericLength l = foldr (\ x n -> 1 + n) 0 l
+--genericLength [] = 0
+--genericLength (x:xs) = 1 + genericLength xs
+{-# genericLength :: Inline #-}
+
+
+length :: [a] -> Int
+length l = foldr (\ x n -> 1 + n) 0 l
+--length [] = 0
+--length (x:xs) = 1 + length xs
+{-# length :: Inline #-}
+
+-- List index (subscript) operator, 0-origin
+(!!) :: (Integral a) => [b] -> a -> b
+l !! i = nth l (fromIntegral i)
+{-# (!!) :: Inline #-}
+
+nth :: [b] -> Int -> b
+nth l m = let f x g 0 = x
+ f x g i = g (i - 1)
+ fail _ = error "(!!){PreludeList}: index too large"
+ in foldr f fail l m
+{-# nth :: Inline #-}
+--nth _ n | n < 0 = error "(!!){PreludeList}: negative index"
+--nth [] n = error "(!!){PreludeList}: index too large"
+--nth (x:xs) n
+-- | n == 0 = x
+-- | otherwise = nth xs (n - 1)
+--{-# nth :: Strictness("S,S") #-}
+
+-- map f xs applies f to each element of xs; i.e., map f xs == [f x | x <- xs].
+map :: (a -> b) -> [a] -> [b]
+map f xs = build (\ c n -> foldr (\ a b -> c (f a) b) n xs)
+--map f [] = []
+--map f (x:xs) = f x : map f xs
+{-# map :: Inline #-}
+
+
+-- filter, applied to a predicate and a list, returns the list of those
+-- elements that satisfy the predicate; i.e.,
+-- filter p xs == [x | x <- xs, p x].
+filter :: (a -> Bool) -> [a] -> [a]
+filter f xs = build (\ c n ->
+ foldr (\ a b -> if f a then c a b else b)
+ n xs)
+--filter p = foldr (\x xs -> if p x then x:xs else xs) []
+{-# filter :: Inline #-}
+
+
+-- partition takes a predicate and a list and returns a pair of lists:
+-- those elements of the argument list that do and do not satisfy the
+-- predicate, respectively; i.e.,
+-- partition p xs == (filter p xs, filter (not . p) xs).
+partition :: (a -> Bool) -> [a] -> ([a],[a])
+partition p = foldr select ([],[])
+ where select x (ts,fs) | p x = (x:ts,fs)
+ | otherwise = (ts,x:fs)
+{-# partition :: Inline #-}
+
+
+-- foldl, applied to a binary operator, a starting value (typically the
+-- left-identity of the operator), and a list, reduces the list using
+-- the binary operator, from left to right:
+-- foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn
+-- foldl1 is a variant that has no starting value argument, and thus must
+-- be applied to non-empty lists. scanl is similar to foldl, but returns
+-- a list of successive reduced values from the left:
+-- scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
+-- Note that last (scanl f z xs) == foldl f z xs.
+-- scanl1 is similar, again without the starting element:
+-- scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]
+
+foldl :: (a -> b -> a) -> a -> [b] -> a
+foldl f z xs = foldr (\ b g a -> g (f a b)) id xs z
+--foldl f z [] = z
+--foldl f z (x:xs) = foldl f (f z x) xs
+{-# foldl :: Inline #-}
+
+foldl1 :: (a -> a -> a) -> [a] -> a
+foldl1 f (x:xs) = foldl f x xs
+foldl1 _ [] = error "foldl1{PreludeList}: empty list"
+{-# foldl1 :: Inline #-}
+
+scanl :: (a -> b -> a) -> a -> [b] -> [a]
+scanl f q xs = q : (case xs of
+ [] -> []
+ x:xs -> scanl f (f q x) xs)
+{-# scanl :: Inline #-}
+
+scanl1 :: (a -> a -> a) -> [a] -> [a]
+scanl1 f (x:xs) = scanl f x xs
+scanl1 _ [] = error "scanl1{PreludeList}: empty list"
+{-# scanl1 :: Inline #-}
+
+
+-- foldr, foldr1, scanr, and scanr1 are the right-to-left duals of the
+-- above functions.
+
+--foldr :: (a -> b -> b) -> b -> [a] -> b
+--foldr f z [] = z
+--foldr f z (x:xs) = f x (foldr f z xs)
+
+
+foldr1 :: (a -> a -> a) -> [a] -> a
+foldr1 f [x] = x
+foldr1 f (x:xs) = f x (foldr1 f xs)
+foldr1 _ [] = error "foldr1{PreludeList}: empty list"
+{-# foldr1 :: Inline #-}
+
+
+-- I'm not sure the build/foldr expansion wins.
+
+scanr :: (a -> b -> b) -> b -> [a] -> [b]
+--scanr f q0 l = build (\ c n ->
+-- let g x qs@(q:_) = c (f x q) qs
+-- in foldr g (c q0 n) l)
+scanr f q0 [] = [q0]
+scanr f q0 (x:xs) = f x q : qs
+ where qs@(q:_) = scanr f q0 xs
+{-# scanr :: Inline #-}
+
+scanr1 :: (a -> a -> a) -> [a] -> [a]
+scanr1 f [x] = [x]
+scanr1 f (x:xs) = f x q : qs
+ where qs@(q:_) = scanr1 f xs
+scanr1 _ [] = error "scanr1{PreludeList}: empty list"
+{-# scanr1 :: Inline #-}
+
+
+-- iterate f x returns an infinite list of repeated applications of f to x:
+-- iterate f x == [x, f x, f (f x), ...]
+iterate :: (a -> a) -> a -> [a]
+iterate f x = build (\ c n ->
+ let iterate' x' = c x' (iterate' (f x'))
+ in iterate' x)
+--iterate f x = x : iterate f (f x)
+{-# iterate :: Inline #-}
+
+
+-- repeat x is an infinite list, with x the value of every element.
+repeat :: a -> [a]
+repeat x = build (\ c n -> let r = c x r in r)
+--repeat x = xs where xs = x:xs
+{-# repeat :: Inline #-}
+
+-- cycle ties a finite list into a circular one, or equivalently,
+-- the infinite repetition of the original list. It is the identity
+-- on infinite lists.
+
+cycle :: [a] -> [a]
+cycle xs = xs' where xs' = xs ++ xs'
+
+
+-- take n, applied to a list xs, returns the prefix of xs of length n,
+-- or xs itself if n > length xs. drop n xs returns the suffix of xs
+-- after the first n elements, or [] if n > length xs. splitAt n xs
+-- is equivalent to (take n xs, drop n xs).
+
+take :: (Integral a) => a -> [b] -> [b]
+take n l = takeInt (fromIntegral n) l
+{-# take :: Inline #-}
+
+takeInt :: Int -> [b] -> [b]
+takeInt m l =
+ build (\ c n ->
+ let f x g i | i <= 0 = n
+ | otherwise = c x (g (i - 1))
+ in foldr f (\ _ -> n) l m)
+--takeInt 0 _ = []
+--takeInt _ [] = []
+--takeInt n l | n > 0 = primTake n l
+{-# takeInt :: Inline #-}
+
+
+
+-- Writing drop and friends in terms of build/foldr seems to lose
+-- way big since they cause an extra traversal of the list tail
+-- (except when the calls are being deforested).
+
+drop :: (Integral a) => a -> [b] -> [b]
+drop n l = dropInt (fromIntegral n) l
+{-# drop :: Inline #-}
+{-# drop :: Strictness("S,S") #-}
+
+
+dropInt :: Int -> [b] -> [b]
+dropInt 0 xs = xs
+dropInt _ [] = []
+dropInt (n+1) (_:xs) = dropInt n xs
+{-# dropInt :: Inline #-}
+
+splitAt :: (Integral a) => a -> [b] -> ([b],[b])
+splitAt n l = splitAtInt (fromIntegral n) l
+{-# splitAt :: Inline #-}
+
+splitAtInt :: Int -> [b] -> ([b],[b])
+splitAtInt 0 xs = ([],xs)
+splitAtInt _ [] = ([],[])
+splitAtInt (n+1) (x:xs) = (x:xs',xs'') where (xs',xs'') = splitAtInt n xs
+{-# splitAtInt :: Inline #-}
+
+-- takeWhile, applied to a predicate p and a list xs, returns the longest
+-- prefix (possibly empty) of xs of elements that satisfy p. dropWhile p xs
+-- returns the remaining suffix. Span p xs is equivalent to
+-- (takeWhile p xs, dropWhile p xs), while break p uses the negation of p.
+
+takeWhile :: (a -> Bool) -> [a] -> [a]
+takeWhile p l = build (\ c n -> foldr (\ a b -> if p a then c a b else n) n l)
+--takeWhile p [] = []
+--takeWhile p (x:xs)
+-- | p x = x : takeWhile p xs
+-- | otherwise = []
+{-# takeWhile :: Inline #-}
+
+
+dropWhile :: (a -> Bool) -> [a] -> [a]
+dropWhile p [] = []
+dropWhile p xs@(x:xs')
+ | p x = dropWhile p xs'
+ | otherwise = xs
+{-# dropWhile :: Inline #-}
+
+span, break :: (a -> Bool) -> [a] -> ([a],[a])
+span p [] = ([],[])
+span p xs@(x:xs')
+ | p x = let (ys,zs) = span p xs' in (x:ys,zs)
+ | otherwise = ([],xs)
+break p = span (not . p)
+
+{-# span :: Inline #-}
+{-# break :: Inline #-}
+
+
+-- lines breaks a string up into a list of strings at newline characters.
+-- The resulting strings do not contain newlines. Similary, words
+-- breaks a string up into a list of words, which were delimited by
+-- white space. unlines and unwords are the inverse operations.
+-- unlines joins lines with terminating newlines, and unwords joins
+-- words with separating spaces.
+
+lines :: String -> [String]
+lines "" = []
+lines s = let (l, s') = break (== '\n') s
+ in l : case s' of
+ [] -> []
+ (_:s'') -> lines s''
+
+words :: String -> [String]
+words s = case dropWhile isSpace s of
+ "" -> []
+ s' -> w : words s''
+ where (w, s'') = break isSpace s'
+
+unlines :: [String] -> String
+unlines = concat . map (++ "\n")
+{-# unlines :: Inline #-}
+
+
+unwords :: [String] -> String
+unwords [] = ""
+unwords ws = foldr1 (\w s -> w ++ ' ':s) ws
+
+-- nub (meaning "essence") removes duplicate elements from its list argument.
+nub :: (Eq a) => [a] -> [a]
+nub l = build (\ c n ->
+ let f x g [] = c x (g [x])
+ f x g xs = if elem x xs
+ then (g xs)
+ else c x (g (x:xs))
+ in foldr f (\ _ -> n) l [])
+{-# nub :: Inline #-}
+--nub [] = []
+--nub (x:xs) = x : nub (filter (/= x) xs)
+
+-- reverse xs returns the elements of xs in reverse order. xs must be finite.
+reverse :: [a] -> [a]
+reverse l = build (\ c n ->
+ let f x g tail = g (c x tail)
+ in foldr f id l n)
+{-# reverse :: Inline #-}
+--reverse x = reverse1 x [] where
+-- reverse1 [] a = a
+-- reverse1 (x:xs) a = reverse1 xs (x:a)
+
+-- and returns the conjunction of a Boolean list. For the result to be
+-- True, the list must be finite; False, however, results from a False
+-- value at a finite index of a finite or infinite list. or is the
+-- disjunctive dual of and.
+and, or :: [Bool] -> Bool
+and = foldr (&&) True
+or = foldr (||) False
+{-# and :: Inline #-}
+{-# or :: Inline #-}
+
+-- Applied to a predicate and a list, any determines if any element
+-- of the list satisfies the predicate. Similarly, for all.
+any, all :: (a -> Bool) -> [a] -> Bool
+any p = or . map p
+all p = and . map p
+{-# any :: Inline #-}
+{-# all :: Inline #-}
+
+-- elem is the list membership predicate, usually written in infix form,
+-- e.g., x `elem` xs. notElem is the negation.
+elem, notElem :: (Eq a) => a -> [a] -> Bool
+
+elem x ys = foldr (\ y t -> (x == y) || t) False ys
+--x `elem` [] = False
+--x `elem` (y:ys) = x == y || x `elem` ys
+{-# elem :: Inline #-}
+notElem x y = not (x `elem` y)
+
+-- sum and product compute the sum or product of a finite list of numbers.
+sum, product :: (Num a) => [a] -> a
+sum = foldl (+) 0
+product = foldl (*) 1
+{-# sum :: Inline #-}
+{-# product :: Inline #-}
+
+-- sums and products give a list of running sums or products from
+-- a list of numbers. For example, sums [1,2,3] == [0,1,3,6].
+sums, products :: (Num a) => [a] -> [a]
+sums = scanl (+) 0
+products = scanl (*) 1
+
+-- maximum and minimum return the maximum or minimum value from a list,
+-- which must be non-empty, finite, and of an ordered type.
+maximum, minimum :: (Ord a) => [a] -> a
+maximum = foldl1 max
+minimum = foldl1 min
+{-# maximum :: Inline #-}
+{-# minimum :: Inline #-}
+
+-- concat, applied to a list of lists, returns their flattened concatenation.
+concat :: [[a]] -> [a]
+concat xs = build (\ c n -> foldr (\ x y -> foldr c y x) n xs)
+--concat [] = []
+--concat (l:ls) = l ++ concat ls
+{-# concat :: Inline #-}
+
+
+-- transpose, applied to a list of lists, returns that list with the
+-- "rows" and "columns" interchanged. The input need not be rectangular
+-- (a list of equal-length lists) to be completely transposable, but can
+-- be "triangular": Each successive component list must be not longer
+-- than the previous one; any elements outside of the "triangular"
+-- transposable region are lost. The input can be infinite in either
+-- dimension or both.
+transpose :: [[a]] -> [[a]]
+transpose = foldr
+ (\xs xss -> zipWith (:) xs (xss ++ repeat []))
+ []
+{-# transpose :: Inline #-}
+
+-- zip takes two lists and returns a list of corresponding pairs. If one
+-- input list is short, excess elements of the longer list are discarded.
+-- zip3 takes three lists and returns a list of triples, etc. Versions
+-- of zip producing up to septuplets are defined here.
+
+zip :: [a] -> [b] -> [(a,b)]
+zip = zipWith (\a b -> (a,b))
+{-# zip :: Inline #-}
+
+zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
+zip3 = zipWith3 (\a b c -> (a,b,c))
+{-# zip3 :: Inline #-}
+
+zip4 :: [a] -> [b] -> [c] -> [d] -> [(a,b,c,d)]
+zip4 = zipWith4 (\a b c d -> (a,b,c,d))
+{-# zip4 :: Inline #-}
+
+zip5 :: [a] -> [b] -> [c] -> [d] -> [e] -> [(a,b,c,d,e)]
+zip5 = zipWith5 (\a b c d e -> (a,b,c,d,e))
+{-# zip5 :: Inline #-}
+
+zip6 :: [a] -> [b] -> [c] -> [d] -> [e] -> [f]
+ -> [(a,b,c,d,e,f)]
+zip6 = zipWith6 (\a b c d e f -> (a,b,c,d,e,f))
+{-# zip6 :: Inline #-}
+
+zip7 :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g]
+ -> [(a,b,c,d,e,f,g)]
+zip7 = zipWith7 (\a b c d e f g -> (a,b,c,d,e,f,g))
+{-# zip7 :: Inline #-}
+
+-- The zipWith family generalises the zip family by zipping with the
+-- function given as the first argument, instead of a tupling function.
+-- For example, zipWith (+) is applied to two lists to produce the list
+-- of corresponding sums.
+
+zipWith :: (a->b->c) -> [a]->[b]->[c]
+zipWith z as bs =
+ build (\ c' n' ->
+ let f' a g' (b:bs) = c' (z a b) (g' bs)
+ f' a g' _ = n'
+ in foldr f' (\ _ -> n') as bs)
+--zipWith z (a:as) (b:bs) = z a b : zipWith z as bs
+--zipWith _ _ _ = []
+{-# zipWith :: Inline #-}
+
+zipWith3 :: (a->b->c->d) -> [a]->[b]->[c]->[d]
+zipWith3 z as bs cs =
+ build (\ c' n' ->
+ let f' a g' (b:bs) (c:cs) = c' (z a b c) (g' bs cs)
+ f' a g' _ _ = n'
+ in foldr f' (\ _ _ -> n') as bs cs)
+{-# zipWith3 :: Inline #-}
+--zipWith3 z (a:as) (b:bs) (c:cs)
+-- = z a b c : zipWith3 z as bs cs
+--zipWith3 _ _ _ _ = []
+
+zipWith4 :: (a->b->c->d->e) -> [a]->[b]->[c]->[d]->[e]
+zipWith4 z as bs cs ds =
+ build (\ c' n' ->
+ let f' a g' (b:bs) (c:cs) (d:ds) = c' (z a b c d) (g' bs cs ds)
+ f' a g' _ _ _ = n'
+ in foldr f' (\ _ _ _ -> n') as bs cs ds)
+{-# zipWith4 :: Inline #-}
+--zipWith4 z (a:as) (b:bs) (c:cs) (d:ds)
+-- = z a b c d : zipWith4 z as bs cs ds
+--zipWith4 _ _ _ _ _ = []
+
+zipWith5 :: (a->b->c->d->e->f)
+ -> [a]->[b]->[c]->[d]->[e]->[f]
+zipWith5 z as bs cs ds es=
+ build (\ c' n' ->
+ let f' a g' (b:bs) (c:cs) (d:ds) (e:es) =
+ c' (z a b c d e) (g' bs cs ds es)
+ f' a g' _ _ _ _ = n'
+ in foldr f' (\ _ _ _ _ -> n') as bs cs ds es)
+{-# zipWith5 :: Inline #-}
+--zipWith5 z (a:as) (b:bs) (c:cs) (d:ds) (e:es)
+-- = z a b c d e : zipWith5 z as bs cs ds es
+--zipWith5 _ _ _ _ _ _ = []
+
+zipWith6 :: (a->b->c->d->e->f->g)
+ -> [a]->[b]->[c]->[d]->[e]->[f]->[g]
+zipWith6 z as bs cs ds es fs =
+ build (\ c' n' ->
+ let f' a g' (b:bs) (c:cs) (d:ds) (e:es) (f:fs) =
+ c' (z a b c d e f) (g' bs cs ds es fs)
+ f' a g' _ _ _ _ _ = n'
+ in foldr f' (\ _ _ _ _ _ -> n') as bs cs ds es fs)
+{-# zipWith6 :: Inline #-}
+--zipWith6 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs)
+-- = z a b c d e f : zipWith6 z as bs cs ds es fs
+--zipWith6 _ _ _ _ _ _ _ = []
+
+zipWith7 :: (a->b->c->d->e->f->g->h)
+ -> [a]->[b]->[c]->[d]->[e]->[f]->[g]->[h]
+zipWith7 z as bs cs ds es fs gs =
+ build (\ c' n' ->
+ let f' a g' (b:bs) (c:cs) (d:ds) (e:es) (f:fs) (g:gs) =
+ c' (z a b c d e f g) (g' bs cs ds es fs gs)
+ f' a g' _ _ _ _ _ _ = n'
+ in foldr f' (\ _ _ _ _ _ _ -> n') as bs cs ds es fs gs)
+{-# zipWith7 :: Inline #-}
+--zipWith7 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs) (g:gs)
+-- = z a b c d e f g : zipWith7 z as bs cs ds es fs gs
+--zipWith7 _ _ _ _ _ _ _ _ = []
+
+
+-- unzip transforms a list of pairs into a pair of lists. As with zip,
+-- a family of such functions up to septuplets is provided.
+
+unzip :: [(a,b)] -> ([a],[b])
+unzip = foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])
+{-# unzip :: Inline #-}
+
+
+unzip3 :: [(a,b,c)] -> ([a],[b],[c])
+unzip3 = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
+ ([],[],[])
+{-# unzip3 :: Inline #-}
+
+unzip4 :: [(a,b,c,d)] -> ([a],[b],[c],[d])
+unzip4 = foldr (\(a,b,c,d) ~(as,bs,cs,ds) ->
+ (a:as,b:bs,c:cs,d:ds))
+ ([],[],[],[])
+{-# unzip4 :: Inline #-}
+
+unzip5 :: [(a,b,c,d,e)] -> ([a],[b],[c],[d],[e])
+unzip5 = foldr (\(a,b,c,d,e) ~(as,bs,cs,ds,es) ->
+ (a:as,b:bs,c:cs,d:ds,e:es))
+ ([],[],[],[],[])
+{-# unzip5 :: Inline #-}
+
+unzip6 :: [(a,b,c,d,e,f)] -> ([a],[b],[c],[d],[e],[f])
+unzip6 = foldr (\(a,b,c,d,e,f) ~(as,bs,cs,ds,es,fs) ->
+ (a:as,b:bs,c:cs,d:ds,e:es,f:fs))
+ ([],[],[],[],[],[])
+{-# unzip6 :: Inline #-}
+
+unzip7 :: [(a,b,c,d,e,f,g)] -> ([a],[b],[c],[d],[e],[f],[g])
+unzip7 = foldr (\(a,b,c,d,e,f,g) ~(as,bs,cs,ds,es,fs,gs) ->
+ (a:as,b:bs,c:cs,d:ds,e:es,f:fs,g:gs))
+ ([],[],[],[],[],[],[])
+{-# unzip7 :: Inline #-}
+
diff --git a/progs/prelude/PreludeLocal.hs b/progs/prelude/PreludeLocal.hs
new file mode 100644
index 0000000..6e52bbf
--- /dev/null
+++ b/progs/prelude/PreludeLocal.hs
@@ -0,0 +1,16 @@
+module PreludeLocal where
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+infixr 5 :
+
+data Int = MkInt
+data Integer = MkInteger
+data Float = MkFloat
+data Double = MkDouble
+data Char = MkChar
+data Bin = MkBin
+data List a = a : (List a) | Nil
+data Arrow a b = MkArrow a b
+
+data Triv = MkTriv
diff --git a/progs/prelude/PreludeLocalIO.hs b/progs/prelude/PreludeLocalIO.hs
new file mode 100644
index 0000000..2753071
--- /dev/null
+++ b/progs/prelude/PreludeLocalIO.hs
@@ -0,0 +1,144 @@
+module PreludeLocalIO where
+
+import PreludeIOPrims
+import PreludeIOMonad
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+data IOResponse a = Succ a | Fail String deriving Text
+
+exec :: ([Response] -> [Request]) -> IO ()
+{-
+-- Sunderesh's original definition
+exec p = case (p bottom) of
+ [] -> unitIO ()
+ (q:qs) -> processRequest q `bindIO` \r ->
+ exec (\rs -> tail (p (r:rs)))
+
+bottom :: a
+bottom = error "Should never be evaluated"
+-}
+-- modified from the existing compiler. no quadratic behavior
+-- needs
+-- pure :: IO a -> a
+-- other alternatives:
+-- 1. use reference cells
+-- 2. implement exec in Lisp
+
+exec p = os requests `bindIO` \x -> unitIO () where
+ requests = p responses
+ responses = pureIO (os requests)
+
+os :: [Request] -> IO [Response]
+os [] = unitIO []
+os (q:qs) = processRequest q `bindIO` \r ->
+ os qs `bindIO` \rs ->
+ unitIO (r:rs)
+
+processRequest :: Request -> IO Response
+
+-- This needs to be rewritten in terms of the continuation based defs
+
+processRequest request =
+ case request of
+
+-- File system requests
+ ReadFile name ->
+ primReadStringFile name `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Str s)
+ Fail e -> unitIO (Failure e)
+ WriteFile name contents ->
+ primWriteStringFile name contents `bindIO` \a ->
+ case a of
+ MaybeNot -> unitIO Success
+ Maybe e -> unitIO (Failure e)
+ AppendFile name contents ->
+ primAppendStringFile name contents `bindIO` \a ->
+ case a of
+ MaybeNot -> unitIO Success
+ Maybe e -> unitIO (Failure e)
+ ReadBinFile name ->
+ primReadBinFile name `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Bn s)
+ Fail e -> unitIO (Failure e)
+ WriteBinFile name bin ->
+ primWriteBinFile name bin `bindIO` \a ->
+ case a of
+ MaybeNot -> unitIO Success
+ Maybe e -> unitIO (Failure e)
+ AppendBinFile name bin ->
+ primAppendBinFile name bin `bindIO` \a ->
+ case a of
+ MaybeNot -> unitIO Success
+ Maybe e -> unitIO (Failure e)
+ DeleteFile name ->
+ primDeleteFile name `bindIO` \a ->
+ case a of
+ MaybeNot -> Success
+ Maybe e -> unitIO (Failure e)
+ StatusFile name ->
+ primStatusFile name `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Str s)
+ Fail e -> unitIO (Failure e)
+
+-- Channel system requests
+ ReadChan name ->
+ primReadChan name `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Str s)
+ Fail e -> unitIO (Failure e)
+ AppendChan name string ->
+ primAppendChan name string `bindIO` \a ->
+ case a of
+ MaybeNot -> unitIO Success
+ Maybe e -> unitIO (Failure e)
+ ReadBinChan name ->
+ primReadBinChan name `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Bn s)
+ Fail e -> unitIO (Failure e)
+ AppendBinChan name bin ->
+ primAppendBinChan name bin `bindIO` \a ->
+ case a of
+ MaybeNot -> unitIO Success
+ Maybe e -> unitIO (Failure e)
+ StatusChan name ->
+ primStatusChan name `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Str s)
+ Fail e -> unitIO (Failure e)
+
+-- Environment requests
+ Echo status ->
+ primEcho status `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Str s)
+ Fail e -> unitIO (Failure e)
+ GetArgs ->
+ primGetArgs `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Str s)
+ Fail e -> unitIO (Failure e)
+ GetProgName ->
+ primProgArgs `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Str s)
+ Fail e -> unitIO (Failure e)
+ GetEnv name ->
+ primGetEnv name `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Str s)
+ Fail e -> unitIO (Failure e)
+ SetEnv name string ->
+ primGetEnv name string `bindIO` \a ->
+ case a of
+ Succ s -> unitIO (Str s)
+ Fail e -> unitIO (Failure e)
+ _ -> unitIO (Failure (OtherError "Unrecognized IO Feature"))
+
+-- Monadic Style IO
+-- Channel system requests
+
diff --git a/progs/prelude/PreludePrims.hi b/progs/prelude/PreludePrims.hi
new file mode 100644
index 0000000..737a448
--- /dev/null
+++ b/progs/prelude/PreludePrims.hi
@@ -0,0 +1,252 @@
+-- interface.scm -- define interface to primitives
+--
+-- author : Sandra & John
+-- date : 24 Apr 1992
+--
+-- This file declares the interface to the runtime system primitives.
+-- The actual definitions for the Lisp functions all appear elsewhere;
+-- they all have names like prim.xxx. (They can actually be macros
+-- instead of functions since they're never referenced by name.)
+
+interface PreludePrims where
+
+{-# Prelude #-}
+
+import PreludeCore(Int,Integer,Float,Double,Char,Bool)
+import PreludeRational(Rational)
+
+error :: String -> a
+primCharToInt :: Char -> Int
+primIntToChar :: Int -> Char
+primEqChar, primNeqChar, primLeChar, primGtChar, primLsChar, primGeChar
+ :: Char -> Char -> Bool
+primMaxChar :: Int
+primEqFloat, primNeqFloat, primLeFloat, primGtFloat, primLsFloat, primGeFloat
+ :: Float -> Float -> Bool
+primFloatMax, primFloatMin :: Float -> Float -> Float
+primEqDouble, primNeqDouble, primLeDouble, primGtDouble,
+ primLsDouble, primGeDouble
+ :: Double -> Double -> Bool
+primDoubleMax, primDoubleMin :: Double -> Double -> Double
+primPlusFloat, primMinusFloat, primMulFloat, primDivFloat
+ :: Float -> Float -> Float
+primPlusDouble, primMinusDouble, primMulDouble, primDivDouble
+ :: Double -> Double -> Double
+primNegFloat, primAbsFloat :: Float -> Float
+primNegDouble, primAbsDouble :: Double -> Double
+primExpFloat, primLogFloat, primSqrtFloat, primSinFloat, primCosFloat,
+ primTanFloat, primAsinFloat, primAcosFloat, primAtanFloat, primSinhFloat,
+ primCoshFloat, primTanhFloat, primAsinhFloat, primAcoshFloat, primAtanhFloat
+ :: Float -> Float
+primExpDouble, primLogDouble, primSqrtDouble, primSinDouble, primCosDouble,
+ primTanDouble, primAsinDouble, primAcosDouble, primAtanDouble, primSinhDouble,
+ primCoshDouble, primTanhDouble, primAsinhDouble, primAcoshDouble, primAtanhDouble
+ :: Double -> Double
+primPiFloat :: Float
+primPiDouble :: Double
+primRationalToFloat :: Rational -> Float
+primRationalToDouble :: Rational -> Double
+primFloatToRational :: Float -> Rational
+primDoubleToRational :: Double -> Rational
+primFloatDigits :: Int
+primFloatRadix :: Integer
+primFloatMinExp :: Int
+primFloatMaxExp :: Int
+primFloatRange :: Float -> (Int, Int)
+primDecodeFloat :: Float -> (Integer, Int)
+primEncodeFloat :: Integer -> Int -> Float
+primDoubleDigits :: Int
+primDoubleRadix :: Integer
+primDoubleMinExp :: Int
+primDoubleMaxExp :: Int
+primDoubleRange :: Double -> (Int, Int)
+primDecodeDouble :: Double -> (Integer, Int)
+primEncodeDouble :: Integer -> Int -> Double
+primEqInt, primNeqInt, primLeInt, primGtInt, primLsInt, primGeInt
+ :: Int -> Int -> Bool
+primIntMax, primIntMin :: Int -> Int -> Int
+primEqInteger, primNeqInteger, primLeInteger, primGtInteger,
+ primLsInteger, primGeInteger
+ :: Integer -> Integer -> Bool
+primIntegerMax, primIntegerMin :: Integer -> Integer -> Integer
+primPlusInt, primMinusInt, primMulInt :: Int -> Int -> Int
+primMinInt,primMaxInt :: Int
+primNegInt, primAbsInt :: Int -> Int
+primPlusInteger, primMinusInteger, primMulInteger :: Integer -> Integer -> Integer
+primNegInteger, primAbsInteger :: Integer -> Integer
+primQuotRemInt :: Int -> Int -> (Int, Int)
+primQuotRemInteger :: Integer -> Integer -> (Integer, Integer)
+primIntegerToInt :: Integer -> Int
+primIntToInteger :: Int -> Integer
+primNullBin :: Bin
+primIsNullBin :: Bin -> Bool
+primShowBinInt :: Int -> Bin -> Bin
+primShowBinInteger :: Integer -> Bin -> Bin
+primShowBinFloat :: Float -> Bin -> Bin
+primShowBinDouble :: Double -> Bin -> Bin
+primReadBinInt :: Bin -> (Int,Bin)
+primReadBinInteger :: Bin -> (Integer,Bin)
+primReadBinFloat :: Bin -> (Float,Bin)
+primReadBinDouble :: Bin -> (Double,Bin)
+primReadBinSmallInt :: Bin -> Int -> (Int,Bin)
+primAppendBin :: Bin -> Bin -> Bin
+
+primStringEq :: [Char] -> [Char] -> Bool
+
+primAppend :: [a] -> [a] -> [a]
+primTake :: Int -> [a] -> [a]
+
+foldr :: (a -> b -> b) -> b -> [a] -> b
+build :: ((a -> [a] -> [a]) -> [b] -> [c]) -> [c]
+
+
+
+-- I've assigned complexities for arithmetic primitives as follows:
+-- Int and Char comparisons and arithmetic are very cheap (complexity 1).
+-- Double and Float comparsions are also cheap, but most implementations
+-- need to box the results of floating-point arithmetic so I have given
+-- them a complexity of 3.
+-- Integer operations need to do an extra bignum check that has a fixed
+-- overhead. I assume that actual bignums will be rare and give them
+-- all a complexity of 2.
+
+{-#
+error :: LispName("prim.abort")
+primCharToInt :: LispName("prim.char-to-int"), Complexity(0),NoConversion
+primIntToChar :: LispName("prim.int-to-char"), Complexity(0),NoConversion
+primEqChar :: LispName("prim.eq-char"), Complexity(1), NoConversion
+primNeqChar:: LispName("prim.not-eq-char"), Complexity(1), NoConversion
+primLeChar :: LispName("prim.le-char"), Complexity(1), NoConversion
+primGtChar :: LispName("prim.not-le-char"), Complexity(1), NoConversion
+primLsChar :: LispName("prim.lt-char"), Complexity(1), NoConversion
+primGeChar :: LispName("prim.not-lt-char"), Complexity(1), NoConversion
+primMaxChar :: LispName("prim.max-char"), NoConversion
+primEqFloat :: LispName("prim.eq-float"), Complexity(1)
+primNeqFloat :: LispName("prim.not-eq-float"), Complexity(1)
+primLeFloat :: LispName("prim.le-float"), Complexity(1)
+primGtFloat :: LispName("prim.not-le-float"), Complexity(1)
+primLsFloat :: LispName("prim.lt-float"), Complexity(1)
+primGeFloat :: LispName("prim.not-lt-float"), Complexity(1)
+primFloatMax :: LispName("prim.float-max"), Complexity(3)
+primFloatMin :: LispName("prim.float-min"), Complexity(3)
+primEqDouble :: LispName("prim.eq-double"), Complexity(1)
+primNeqDouble :: LispName("prim.not-eq-double"), Complexity(1)
+primLeDouble :: LispName("prim.le-double"), Complexity(1)
+primGtDouble :: LispName("prim.not-le-double"), Complexity(1)
+primLsDouble :: LispName("prim.lt-double"), Complexity(1)
+primGeDouble :: LispName("prim.not-lt-double"), Complexity(1)
+primDoubleMax :: LispName("prim.double-max"), Complexity(3)
+primDoubleMin :: LispName("prim.double-min"), Complexity(3)
+primPlusFloat :: LispName("prim.plus-float"), Complexity(3)
+primMinusFloat :: LispName("prim.minus-float"), Complexity(3)
+primMulFloat :: LispName("prim.mul-float"), Complexity(3)
+primDivFloat :: LispName("prim.div-float"), Complexity(3)
+primPlusDouble :: LispName("prim.plus-double"), Complexity(3)
+primMinusDouble :: LispName("prim.minus-double"), Complexity(3)
+primMulDouble :: LispName("prim.mul-double"), Complexity(3)
+primDivDouble :: LispName("prim.div-double"), Complexity(3)
+primNegFloat :: LispName("prim.neg-float"), Complexity(3)
+primAbsFloat :: LispName("prim.abs-float"), Complexity(3)
+primNegDouble :: LispName("prim.neg-double"), Complexity(3)
+primAbsDouble :: LispName("prim.abs-double"), Complexity(3)
+primExpFloat :: LispName("prim.exp-float")
+primLogFloat :: LispName("prim.log-float")
+primSqrtFloat :: LispName("prim.sqrt-float")
+primSinFloat :: LispName("prim.sin-float")
+primCosFloat :: LispName("prim.cos-float")
+primTanFloat :: LispName("prim.tan-float")
+primAsinFloat :: LispName("prim.asin-float")
+primAcosFloat :: LispName("prim.acos-float")
+primAtanFloat :: LispName("prim.atan-float")
+primSinhFloat :: LispName("prim.sinh-float")
+primCoshFloat :: LispName("prim.cosh-float")
+primTanhFloat :: LispName("prim.tanh-float")
+primAsinhFloat :: LispName("prim.asinh-float")
+primAcoshFloat :: LispName("prim.acosh-float")
+primAtanhFloat :: LispName("prim.atanh-float")
+primExpDouble :: LispName("prim.exp-double")
+primLogDouble :: LispName("prim.log-double")
+primSqrtDouble :: LispName("prim.sqrt-double")
+primSinDouble :: LispName("prim.sin-double")
+primCosDouble :: LispName("prim.cos-double")
+primTanDouble :: LispName("prim.tan-double")
+primAsinDouble :: LispName("prim.asin-double")
+primAcosDouble :: LispName("prim.acos-double")
+primAtanDouble :: LispName("prim.atan-double")
+primSinhDouble :: LispName("prim.sinh-double")
+primCoshDouble :: LispName("prim.cosh-double")
+primTanhDouble :: LispName("prim.tanh-double")
+primAsinhDouble :: LispName("prim.asinh-double")
+primAcoshDouble :: LispName("prim.acosh-double")
+primAtanhDouble :: LispName("prim.atanh-double")
+primPiFloat :: LispName("prim.pi-float")
+primPiDouble :: LispName("prim.pi-double")
+primRationalToFloat :: LispName("prim.rational-to-float"), Complexity(3)
+primRationalToDouble :: LispName("prim.rational-to-double"), Complexity(3)
+primFloatToRational :: LispName("prim.float-to-rational"), Complexity(3)
+primDoubleToRational :: LispName("prim.double-to-rational"), Complexity(3)
+primFloatDigits :: LispName("prim.float-digits")
+primFloatRadix :: LispName("prim.float-radix")
+primFloatMinExp :: LispName("prim.float-min-exp")
+primFloatMaxExp :: LispName("prim.float-max-exp")
+primFloatRange :: LispName("prim.float-range")
+primDecodeFloat :: LispName("prim.decode-float")
+primEncodeFloat :: LispName("prim.encode-float")
+primDoubleDigits :: LispName("prim.double-digits")
+primDoubleRadix :: LispName("prim.double-radix")
+primDoubleMinExp :: LispName("prim.double-min-exp")
+primDoubleMaxExp :: LispName("prim.double-max-exp")
+primDoubleRange :: LispName("prim.double-range")
+primDecodeDouble :: LispName("prim.decode-double")
+primEncodeDouble :: LispName("prim.encode-double")
+primEqInt :: LispName("prim.eq-int"), Complexity(1)
+primNeqInt:: LispName("prim.not-eq-int"), Complexity(1)
+primLeInt :: LispName("prim.le-int"), Complexity(1)
+primGtInt :: LispName("prim.not-le-int"), Complexity(1)
+primLsInt :: LispName("prim.lt-int"), Complexity(1)
+primGeInt :: LispName("prim.not-lt-int"), Complexity(1)
+primIntMax :: LispName("prim.int-max"), Complexity(1)
+primIntMin :: LispName("prim.int-min"), Complexity(1)
+primEqInteger :: LispName("prim.eq-integer"), Complexity(2)
+primNeqInteger:: LispName("prim.not-eq-integer"), Complexity(2)
+primLeInteger :: LispName("prim.le-integer"), Complexity(2)
+primGtInteger :: LispName("prim.not-le-integer"), Complexity(2)
+primLsInteger :: LispName("prim.lt-integer"), Complexity(2)
+primGeInteger :: LispName("prim.not-lt-integer"), Complexity(2)
+primIntegerMax :: LispName("prim.integer-max"), Complexity(2)
+primIntegerMin :: LispName("prim.integer-min"), Complexity(2)
+primPlusInt :: LispName("prim.plus-int"), Complexity(1)
+primMinusInt :: LispName("prim.minus-int"), Complexity(1)
+primMulInt :: LispName("prim.mul-int"), Complexity(1)
+primMinInt :: LispName("prim.minint")
+primMaxInt :: LispName("prim.maxint")
+primNegInt :: LispName("prim.neg-int"), Complexity(1)
+primAbsInt :: LispName("prim.abs-int"), Complexity(1)
+primPlusInteger :: LispName("prim.plus-integer"), Complexity(2)
+primMinusInteger :: LispName("prim.minus-integer"), Complexity(2)
+primMulInteger :: LispName("prim.mul-integer"), Complexity(2)
+primNegInteger :: LispName("prim.neg-integer"), Complexity(2)
+primAbsInteger :: LispName("prim.abs-integer"), Complexity(2)
+primQuotRemInt :: LispName("prim.div-rem-int")
+primQuotRemInteger :: LispName("prim.div-rem-integer")
+primIntegerToInt :: LispName("prim.integer-to-int"), Complexity(1)
+primIntToInteger :: LispName("prim.int-to-integer"), Complexity(0)
+primNullBin :: LispName("prim.nullbin")
+primIsNullBin :: LispName("prim.is-null-bin"), Complexity(1)
+primShowBinInt :: LispName("prim.show-bin-int"), Complexity(2)
+primShowBinInteger :: LispName("prim.show-bin-integer"), Complexity(2)
+primShowBinFloat :: LispName("prim.show-bin-float"), Complexity(2)
+primShowBinDouble :: LispName("prim.show-bin-double"), Complexity(2)
+primReadBinInt :: LispName("prim.read-bin-int")
+primReadBinInteger :: LispName("prim.read-bin-integer")
+primReadBinFloat :: LispName("prim.read-bin-float")
+primReadBinDouble :: LispName("prim.read-bin-double")
+primReadBinSmallInt :: LispName("prim.read-bin-small-int")
+primAppendBin :: LispName("prim.append-bin")
+primStringEq :: LispName("prim.string-eq"), Strictness("S,S"), NoConversion
+primAppend :: LispName("prim.append"), Strictness("S,N"), NoConversion
+primTake :: LispName("prim.take"), Strictness("S,S"), NoConversion
+foldr :: LispName("prim.foldr"), Strictness("N,N,S"), NoConversion
+build :: LispName("prim.build"), Strictness("S"), NoConversion
+
+#-}
diff --git a/progs/prelude/PreludePrims.hu b/progs/prelude/PreludePrims.hu
new file mode 100644
index 0000000..fd2cdcc
--- /dev/null
+++ b/progs/prelude/PreludePrims.hu
@@ -0,0 +1,4 @@
+:output $PRELUDEBIN/PreludePrims
+:stable
+:prelude
+PreludePrims.hi
diff --git a/progs/prelude/PreludeRatio.hs b/progs/prelude/PreludeRatio.hs
new file mode 100644
index 0000000..564558e
--- /dev/null
+++ b/progs/prelude/PreludeRatio.hs
@@ -0,0 +1,98 @@
+-- Standard functions on rational numbers
+
+module PreludeRatio (
+ Ratio, Rational(..), (%), numerator, denominator, approxRational ) where
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+infixl 7 %, :%
+
+prec = 7
+
+data (Integral a) => Ratio a = a {-# STRICT #-} :% a {-# STRICT #-}
+ deriving (Eq, Binary)
+
+type Rational = Ratio Integer
+
+(%) :: (Integral a) => a -> a -> Ratio a
+numerator, denominator :: (Integral a) => Ratio a -> a
+approxRational :: (RealFrac a) => a -> a -> Rational
+
+
+reduce _ 0 = error "(%){PreludeRatio}: zero denominator"
+reduce x y = (x `quot` d) :% (y `quot` d)
+ where d = gcd x y
+
+
+x % y = reduce (x * signum y) (abs y)
+
+numerator (x:%y) = x
+
+denominator (x:%y) = y
+
+
+instance (Integral a) => Ord (Ratio a) where
+ (x:%y) <= (x':%y') = x * y' <= x' * y
+ (x:%y) < (x':%y') = x * y' < x' * y
+
+instance (Integral a) => Num (Ratio a) where
+ (x:%y) + (x':%y') = reduce (x*y' + x'*y) (y*y')
+ (x:%y) * (x':%y') = reduce (x * x') (y * y')
+ negate (x:%y) = (-x) :% y
+ abs (x:%y) = abs x :% y
+ signum (x:%y) = signum x :% 1
+ fromInteger x = fromInteger x :% 1
+
+instance (Integral a) => Real (Ratio a) where
+ toRational (x:%y) = toInteger x :% toInteger y
+
+instance (Integral a) => Fractional (Ratio a) where
+ (x:%y) / (x':%y') = (x*y') % (y*x')
+ recip (x:%y) = if x < 0 then (-y) :% (-x) else y :% x
+ fromRational (x:%y) = fromInteger x :% fromInteger y
+
+instance (Integral a) => RealFrac (Ratio a) where
+ properFraction (x:%y) = (fromIntegral q, r:%y)
+ where (q,r) = quotRem x y
+
+instance (Integral a) => Enum (Ratio a) where
+ enumFrom = iterate ((+)1)
+ enumFromThen n m = iterate ((+)(m-n)) n
+
+instance (Integral a) => Text (Ratio a) where
+ readsPrec p = readParen (p > prec)
+ (\r -> [(x%y,u) | (x,s) <- reads r,
+ ("%",t) <- lex s,
+ (y,u) <- reads t ])
+
+ showsPrec p (x:%y) = showParen (p > prec)
+ (shows x . showString " % " . shows y)
+
+
+-- approxRational, applied to two real fractional numbers x and epsilon,
+-- returns the simplest rational number within epsilon of x. A rational
+-- number n%d in reduced form is said to be simpler than another n'%d' if
+-- abs n <= abs n' && d <= d'. Any real interval contains a unique
+-- simplest rational; here, for simplicity, we assume a closed rational
+-- interval. If such an interval includes at least one whole number, then
+-- the simplest rational is the absolutely least whole number. Otherwise,
+-- the bounds are of the form q%1 + r%d and q%1 + r'%d', where abs r < d
+-- and abs r' < d', and the simplest rational is q%1 + the reciprocal of
+-- the simplest rational between d'%r' and d%r.
+
+approxRational x eps = simplest (x-eps) (x+eps)
+ where simplest x y | y < x = simplest y x
+ | x == y = xr
+ | x > 0 = simplest' n d n' d'
+ | y < 0 = - simplest' (-n') d' (-n) d
+ | otherwise = 0 :% 1
+ where xr@(n:%d) = toRational x
+ (n':%d') = toRational y
+
+ simplest' n d n' d' -- assumes 0 < n%d < n'%d'
+ | r == 0 = q :% 1
+ | q /= q' = (q+1) :% 1
+ | otherwise = (q*n''+d'') :% n''
+ where (q,r) = quotRem n d
+ (q',r') = quotRem n' d'
+ (n'':%d'') = simplest' d' r' d r
diff --git a/progs/prelude/PreludeText.hs b/progs/prelude/PreludeText.hs
new file mode 100644
index 0000000..9e4e353
--- /dev/null
+++ b/progs/prelude/PreludeText.hs
@@ -0,0 +1,260 @@
+module PreludeText (
+ reads, shows, show, read, lex,
+ showChar, showString, readParen, showParen, readLitChar, showLitChar,
+ readSigned, showSigned, readDec, showInt, readFloat, showFloat ) where
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+reads :: (Text a) => ReadS a
+reads = readsPrec 0
+
+shows :: (Text a) => a -> ShowS
+shows = showsPrec 0
+
+read :: (Text a) => String -> a
+read s = case [x | (x,t) <- reads s, ("","") <- lex t] of
+ [x] -> x
+ [] -> error "read{PreludeText}: no parse"
+ _ -> error "read{PreludeText}: ambiguous parse"
+
+show :: (Text a) => a -> String
+show x = shows x ""
+
+showChar :: Char -> ShowS
+showChar = (:)
+
+showString :: String -> ShowS
+showString = (++)
+
+showParen :: Bool -> ShowS -> ShowS
+showParen b p = if b then showChar '(' . p . showChar ')' else p
+
+readParen :: Bool -> ReadS a -> ReadS a
+readParen b g = if b then mandatory else optional
+ where optional r = g r ++ mandatory r
+ mandatory r = [(x,u) | ("(",s) <- lex r,
+ (x,t) <- optional s,
+ (")",u) <- lex t ]
+
+lex :: ReadS String
+lex "" = [("","")]
+lex (c:s) | isSpace c = lex (dropWhile isSpace s)
+lex ('-':'-':s) = case dropWhile (/= '\n') s of
+ '\n':t -> lex t
+ _ -> [] -- unterminated end-of-line
+ -- comment
+
+lex ('{':'-':s) = lexNest lex s
+ where
+ lexNest f ('-':'}':s) = f s
+ lexNest f ('{':'-':s) = lexNest (lexNest f) s
+ lexNest f (c:s) = lexNest f s
+ lexNest _ "" = [] -- unterminated
+ -- nested comment
+
+lex ('<':'-':s) = [("<-",s)]
+lex ('\'':s) = [('\'':ch++"'", t) | (ch,'\'':t) <- lexLitChar s,
+ ch /= "'" ]
+lex ('"':s) = [('"':str, t) | (str,t) <- lexString s]
+ where
+ lexString ('"':s) = [("\"",s)]
+ lexString s = [(ch++str, u)
+ | (ch,t) <- lexStrItem s,
+ (str,u) <- lexString t ]
+
+ lexStrItem ('\\':'&':s) = [("\\&",s)]
+ lexStrItem ('\\':c:s) | isSpace c
+ = [("\\&",t) | '\\':t <- [dropWhile isSpace s]]
+ lexStrItem s = lexLitChar s
+
+lex (c:s) | isSingle c = [([c],s)]
+ | isSym1 c = [(c:sym,t) | (sym,t) <- [span isSym s]]
+ | isAlpha c = [(c:nam,t) | (nam,t) <- [span isIdChar s]]
+ | isDigit c = [(c:ds++fe,t) | (ds,s) <- [span isDigit s],
+ (fe,t) <- lexFracExp s ]
+ | otherwise = [] -- bad character
+ where
+ isSingle c = c `elem` ",;()[]{}_"
+ isSym1 c = c `elem` "-~" || isSym c
+ isSym c = c `elem` "!@#$%&*+./<=>?\\^|:"
+ isIdChar c = isAlphanum c || c `elem` "_'"
+
+ lexFracExp ('.':s) = [('.':ds++e,u) | (ds,t) <- lexDigits s,
+ (e,u) <- lexExp t ]
+ lexFracExp s = [("",s)]
+
+ lexExp (e:s) | e `elem` "eE"
+ = [(e:c:ds,u) | (c:t) <- [s], c `elem` "+-",
+ (ds,u) <- lexDigits t] ++
+ [(e:ds,t) | (ds,t) <- lexDigits s]
+ lexExp s = [("",s)]
+
+lexDigits :: ReadS String
+lexDigits = nonnull isDigit
+
+nonnull :: (Char -> Bool) -> ReadS String
+nonnull p s = [(cs,t) | (cs@(_:_),t) <- [span p s]]
+
+lexLitChar :: ReadS String
+lexLitChar ('\\':s) = [('\\':esc, t) | (esc,t) <- lexEsc s]
+ where
+ lexEsc (c:s) | c `elem` "abfnrtv\\\"'" = [([c],s)]
+ lexEsc ('^':c:s) | c >= '@' && c <= '_' = [(['^',c],s)]
+ lexEsc s@(d:_) | isDigit d = lexDigits s
+ lexEsc ('o':s) = [('o':os, t) | (os,t) <- nonnull isOctDigit s]
+ lexEsc ('x':s) = [('x':xs, t) | (xs,t) <- nonnull isHexDigit s]
+ lexEsc s@(c:_) | isUpper c
+ = case [(mne,s') | mne <- "DEL" : elems asciiTab,
+ ([],s') <- [match mne s] ]
+ of (pr:_) -> [pr]
+ [] -> []
+ lexEsc _ = []
+lexLitChar (c:s) = [([c],s)]
+lexLitChar "" = []
+
+isOctDigit c = c >= '0' && c <= '7'
+isHexDigit c = isDigit c || c >= 'A' && c <= 'F'
+ || c >= 'a' && c <= 'f'
+
+match :: (Eq a) => [a] -> [a] -> ([a],[a])
+match (x:xs) (y:ys) | x == y = match xs ys
+match xs ys = (xs,ys)
+
+asciiTab = listArray ('\NUL', ' ')
+ ["NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
+ "SP"]
+
+
+
+readLitChar :: ReadS Char
+readLitChar ('\\':s) = readEsc s
+ where
+ readEsc ('a':s) = [('\a',s)]
+ readEsc ('b':s) = [('\b',s)]
+ readEsc ('f':s) = [('\f',s)]
+ readEsc ('n':s) = [('\n',s)]
+ readEsc ('r':s) = [('\r',s)]
+ readEsc ('t':s) = [('\t',s)]
+ readEsc ('v':s) = [('\v',s)]
+ readEsc ('\\':s) = [('\\',s)]
+ readEsc ('"':s) = [('"',s)]
+ readEsc ('\'':s) = [('\'',s)]
+ readEsc ('^':c:s) | c >= '@' && c <= '_'
+ = [(chr (ord c - ord '@'), s)]
+ readEsc s@(d:_) | isDigit d
+ = [(chr n, t) | (n,t) <- readDec s]
+ readEsc ('o':s) = [(chr n, t) | (n,t) <- readOct s]
+ readEsc ('x':s) = [(chr n, t) | (n,t) <- readHex s]
+ readEsc s@(c:_) | isUpper c
+ = let table = ('\DEL' := "DEL") : assocs asciiTab
+ in case [(c,s') | (c := mne) <- table,
+ ([],s') <- [match mne s]]
+ of (pr:_) -> [pr]
+ [] -> []
+ readEsc _ = []
+readLitChar (c:s) = [(c,s)]
+
+showLitChar :: Char -> ShowS
+showLitChar c | c > '\DEL' = showChar '\\' . protectEsc isDigit (shows (ord c))
+showLitChar '\DEL' = showString "\\DEL"
+showLitChar '\\' = showString "\\\\"
+showLitChar c | c >= ' ' = showChar c
+showLitChar '\a' = showString "\\a"
+showLitChar '\b' = showString "\\b"
+showLitChar '\f' = showString "\\f"
+showLitChar '\n' = showString "\\n"
+showLitChar '\r' = showString "\\r"
+showLitChar '\t' = showString "\\t"
+showLitChar '\v' = showString "\\v"
+showLitChar '\SO' = protectEsc (== 'H') (showString "\\SO")
+showLitChar c = showString ('\\' : asciiTab!c)
+
+protectEsc p f = f . cont
+ where cont s@(c:_) | p c = "\\&" ++ s
+ cont s = s
+
+readDec, readOct, readHex :: (Integral a) => ReadS a
+readDec = readInt 10 isDigit (\d -> ord d - ord '0')
+readOct = readInt 8 isOctDigit (\d -> ord d - ord '0')
+readHex = readInt 16 isHexDigit hex
+ where hex d = ord d - (if isDigit d then ord '0'
+ else ord (if isUpper d then 'A' else 'a')
+ - 10)
+
+readInt :: (Integral a) => a -> (Char -> Bool) -> (Char -> Int) -> ReadS a
+readInt radix isDig digToInt s =
+ [(foldl1 (\n d -> n * radix + d) (map (fromIntegral . digToInt) ds), r)
+ | (ds,r) <- nonnull isDig s ]
+
+showInt :: (Integral a) => a -> ShowS
+showInt n r = let (n',d) = quotRem n 10
+ r' = chr (ord '0' + fromIntegral d) : r
+ in if n' == 0 then r' else showInt n' r'
+
+readSigned:: (Real a) => ReadS a -> ReadS a
+readSigned readPos = readParen False read'
+ where read' r = read'' r ++
+ [(-x,t) | ("-",s) <- lex r,
+ (x,t) <- read'' s]
+ read'' r = [(n,s) | (str,s) <- lex r,
+ (n,"") <- readPos str]
+
+showSigned:: (Real a) => (a -> ShowS) -> Int -> a -> ShowS
+showSigned showPos p x = if x < 0 then showParen (p > 6)
+ (showChar '-' . showPos (-x))
+ else showPos x
+
+
+-- The functions readFloat and showFloat below use rational arithmetic
+-- to insure correct conversion between the floating-point radix and
+-- decimal. It is often possible to use a higher-precision floating-
+-- point type to obtain the same results.
+
+readFloat:: (RealFloat a) => ReadS a
+readFloat r = [(fromRational ((n%1)*10^^(k-d)), t) | (n,d,s) <- readFix r,
+ (k,t) <- readExp s]
+ where readFix r = [(read (ds++ds'), length ds', t)
+ | (ds,'.':s) <- lexDigits r,
+ (ds',t) <- lexDigits s ]
+
+ readExp (e:s) | e `elem` "eE" = readExp' s
+ readExp s = [(0,s)]
+
+ readExp' ('-':s) = [(-k,t) | (k,t) <- readDec s]
+ readExp' ('+':s) = readDec s
+ readExp' s = readDec s
+
+-- The number of decimal digits m below is chosen to guarantee
+-- read (show x) == x. See
+-- Matula, D. W. A formalization of floating-point numeric base
+-- conversion. IEEE Transactions on Computers C-19, 8 (1970 August),
+-- 681-692.
+
+showFloat:: (RealFloat a) => a -> ShowS
+showFloat x =
+ if x == 0 then showString ("0." ++ take (m-1) (repeat '0'))
+ else if e >= m-1 || e < 0 then showSci else showFix
+ where
+ showFix = showString whole . showChar '.' . showString frac
+ where (whole,frac) = splitAt (e+1) (show sig)
+ showSci = showChar d . showChar '.' . showString frac
+ . showChar 'e' . shows e
+ where (d:frac) = show sig
+ (m, sig, e) = if b == 10 then (w, s, n+w-1)
+ else (m', sig', e' )
+ m' = ceiling
+ (fromIntegral w * log (fromInteger b) / log 10 :: Double)
+ + 1
+ (sig', e') = if sig1 >= 10^m' then (round (t/10), e1+1)
+ else if sig1 < 10^(m'-1) then (round (t*10), e1-1)
+ else (sig1, e1 )
+ sig1 :: Integer
+ sig1 = round t
+ t = s%1 * (b%1)^^n * 10^^(m'-e1-1)
+ e1 = floor (logBase 10 x)
+ (s, n) = decodeFloat x
+ b = floatRadix x
+ w = floatDigits x
diff --git a/progs/prelude/PreludeTuple.hs b/progs/prelude/PreludeTuple.hs
new file mode 100644
index 0000000..4f2637a
--- /dev/null
+++ b/progs/prelude/PreludeTuple.hs
@@ -0,0 +1,213 @@
+module PreludeTuple where
+
+{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
+
+import PreludeTuplePrims
+
+-- This module contains support routines which handle tuple instances.
+-- These are based on a implementation level data type which represents
+-- general tuples and a data type to hold the set of dictionaries which
+-- are associated with the tuple.
+
+-- Each of these functions takes the tupledicts as the first argument.
+-- Force all of these functions to take strict arguments because they'll
+-- never be called with 0-length tuples anyway.
+
+-- The following primitives operate on tuples.
+
+-- tupleSize :: TupleDicts -> Int
+-- tupleSel :: Tuple -> Int -> Int -> a
+-- dictSel :: TupleDicts -> method -> Int -> a
+-- listToTuple :: [a] -> Tuple
+
+-- Eq functions
+
+tupleEq :: TupleDicts -> Tuple -> Tuple -> Bool
+{-# tupleEq :: Strictness("S,S,S") #-}
+tupleEq dicts x y = tupleEq1 0 where
+ tupleEq1 i | i == size = True
+ | otherwise =
+ ((dictSel (cmpEq dicts i)) x' y') && tupleEq1 (i+1)
+ where
+ x' = tupleSel x i size
+ y' = tupleSel y i size
+ size = tupleSize dicts
+
+cmpEq x y = x == y
+
+tupleNeq dicts x y = not (tupleEq dicts x y)
+
+-- Ord functions
+
+tupleLe :: TupleDicts -> Tuple -> Tuple -> Bool
+{-# tupleLe :: Strictness("S,S,S") #-}
+tupleLe dicts x y = tupleLe1 0 where
+ tupleLe1 i | i == size = False
+ | (dictSel (cmpLs dicts i)) x' y' = True
+ | (dictSel (ordEq dicts i)) x' y' = tupleLe1 (i+1)
+ | otherwise = False
+ where
+ x' = tupleSel x i size
+ y' = tupleSel y i size
+ size = tupleSize dicts
+
+cmpLs x y = x < y
+
+ordEq :: Ord a => a -> a -> Bool
+ordEq x y = x == y
+
+tupleLeq :: TupleDicts -> Tuple -> Tuple -> Bool
+{-# tupleLeq :: Strictness("S,S,S") #-}
+tupleLeq dicts x y = tupleLeq1 0 where
+ tupleLeq1 i | i == size = True
+ | (dictSel (cmpLs dicts i)) x' y' = True
+ | (dictSel (ordEq dicts i)) x' y' = tupleLeq1 (i+1)
+ | otherwise = False
+ where
+ x' = tupleSel x i size
+ y' = tupleSel y i size
+ size = tupleSize dicts
+
+tupleGe :: TupleDicts -> Tuple -> Tuple -> Bool
+tupleGe d x y = tupleLe d y x
+
+tupleGeq :: TupleDicts -> Tuple -> Tuple -> Bool
+tupleGeq d x y = tupleLeq d y x
+
+tupleMax,tupleMin :: TupleDicts -> Tuple -> Tuple -> Tuple
+tupleMax d x y = if tupleGe d x y then x else y
+tupleMin d x y = if tupleLe d x y then x else y
+
+-- Ix functions
+
+tupleRange :: TupleDicts -> (Tuple,Tuple) -> [Tuple]
+{-# tupleRange :: Strictness("S,S") #-}
+
+tupleRange dicts (x,y) = map listToTuple (tupleRange' 0) where
+ tupleRange' i | i == size = [[]]
+ | otherwise =
+ [(i1 : i2) | i1 <- r, i2 <- tupleRange' (i+1)]
+ where
+ x' = tupleSel x i size
+ y' = tupleSel y i size
+ r = (dictSel (range' dicts i)) (x',y')
+ size = tupleSize dicts
+
+range' x = range x
+
+tupleIndex :: TupleDicts -> (Tuple,Tuple) -> Tuple -> Int
+{-# tupleIndex :: Strictness("S,S,S") #-}
+
+tupleIndex dicts (low,high) n = tupleIndex' (size-1) where
+ size = tupleSize dicts
+ tupleIndex' i | i == 0 = i'
+ | otherwise = i' + r' * (tupleIndex' (i-1))
+ where
+ low' = tupleSel low i size
+ high' = tupleSel high i size
+ n' = tupleSel n i size
+ i' = (dictSel (index' dicts i)) (low',high') n'
+ r' = (dictSel (rangeSize dicts i)) (low',high')
+
+index' x = index x
+
+rangeSize :: (Ix a) => (a,a) -> Int
+rangeSize (l,u) = index (l,u) u + 1
+
+tupleInRange :: TupleDicts -> (Tuple,Tuple) -> Tuple -> Bool
+{-# tupleInRange :: Strictness("S,S,S") #-}
+tupleInRange dicts (low,high) n = tupleInRange' 0 where
+ size = tupleSize dicts
+ tupleInRange' i | i == size = True
+ | otherwise = (dictSel (inRange' dicts i)) (low',high') n'
+ && tupleInRange' (i+1)
+ where
+ low' = tupleSel low i size
+ high' = tupleSel high i size
+ n' = tupleSel n i size
+
+inRange' x = inRange x
+
+-- Text functions
+
+tupleReadsPrec :: TupleDicts -> Int -> ReadS Tuple
+
+tupleReadsPrec dicts p = readParen False
+ (\s -> map ( \ (t,w) -> (listToTuple t,w))
+ (tRP' s 0))
+ where
+ size = tupleSize dicts
+ tRP' s i | i == 0 = [(t':t,w) |
+ ("(",s1) <- lex s,
+ (t',s2) <- nextItem s1,
+ (t,w) <- tRP' s2 (i+1)]
+ | i == size = [([],w) | (")",w) <- lex s]
+ | otherwise =
+ [(t':t,w) |
+ (",",s1) <- lex s,
+ (t',s2) <- nextItem s1,
+ (t,w) <- tRP' s2 (i+1)]
+ where
+ nextItem s = (dictSel (reads dicts i)) s
+
+tupleShowsPrec :: TupleDicts -> Int -> Tuple -> ShowS
+
+tupleShowsPrec dicts p tuple =
+ showChar '(' . tSP' 0
+ where
+ size = tupleSize dicts
+ tSP' i | i == (size-1) =
+ showTup . showChar ')'
+ | otherwise =
+ showTup . showChar ',' . tSP' (i+1)
+ where
+ showTup = (dictSel (shows dicts i)) (tupleSel tuple i size)
+
+tupleReadList :: TupleDicts -> ReadS [Tuple]
+
+tupleReadList dicts =
+ readParen False (\r -> [pr | ("[",s) <- lex r,
+ pr <- readl s])
+ where readl s = [([],t) | ("]",t) <- lex s] ++
+ [(x:xs,u) | (x,t) <- tupleReads s,
+ (xs,u) <- readl' t]
+ readl' s = [([],t) | ("]",t) <- lex s] ++
+ [(x:xs,v) | (",",t) <- lex s,
+ (x,u) <- tupleReads t,
+ (xs,v) <- readl' u]
+ tupleReads s = tupleReadsPrec dicts 0 s
+
+tupleShowList :: TupleDicts -> [Tuple] -> ShowS
+
+tupleShowList dicts [] = showString "[]"
+tupleShowList dicts (x:xs)
+ = showChar '[' . showsTuple x . showl xs
+ where showl [] = showChar ']'
+ showl (x:xs) = showString ", " . showsTuple x
+ . showl xs
+ showsTuple x = tupleShowsPrec dicts 0 x
+
+-- Binary functions
+
+tupleShowBin :: TupleDicts -> Tuple -> Bin -> Bin
+
+tupleShowBin dicts t bin = tSB' 0
+ where
+ size = tupleSize dicts
+ tSB' i | i == size = bin
+ tSB' i | otherwise =
+ (dictSel (showBin' dicts i)) (tupleSel t i size) (tSB' (i+1))
+
+showBin' x = showBin x
+
+tupleReadBin :: TupleDicts -> Bin -> (Tuple,Bin)
+
+tupleReadBin dicts bin = (listToTuple t,b) where
+ size = tupleSize dicts
+ (t,b) = tRB' bin 0
+ tRB' b i | i == size = ([],b)
+ | otherwise = (t':ts,b') where
+ (t',b'') = (dictSel (readBin' dicts i)) b
+ (ts,b') = tRB' b'' (i+1)
+
+readBin' x = readBin x
diff --git a/progs/prelude/PreludeTuplePrims.hi b/progs/prelude/PreludeTuplePrims.hi
new file mode 100644
index 0000000..6af0dfd
--- /dev/null
+++ b/progs/prelude/PreludeTuplePrims.hi
@@ -0,0 +1,48 @@
+
+-- This is the interface to the primitives used to implement arbitrary
+-- sized tuples.
+
+interface PreludeTuplePrims where
+
+{-# Prelude #-}
+
+-- The type checker fiddles around with the call to dictSel to use the
+-- dictionary to resolve the overloading of a subexpression. The call
+-- dictSel (exp dict i) will typecheck exp and use the ith component of
+-- the tupleDict dict to resolve the overloading. No check is made to ensure
+-- that the type of the dictionary matches the overloaded class! Beware!
+
+import PreludeData(Int)
+
+data Tuple
+data TupleDicts
+
+
+tupleSize :: TupleDicts -> Int
+tupleSel :: Tuple -> Int -> Int -> a
+dictSel :: TupleDicts -> Int -> a
+listToTuple :: [a] -> Tuple
+-- These are not called by haskell code directly; these are introduced
+-- during dictionary conversion by the type checker.
+tupleEqDict :: a
+tupleOrdDict :: a
+tupleIxDict :: a
+tupleTextDict :: a
+tupleBinaryDict :: a
+
+{-#
+tupleSize :: LispName("prim.tupleSize"), Complexity(1)
+tupleSel :: LispName("prim.tupleSel")
+dictSel :: LispName("prim.dict-sel")
+listToTuple :: LispName("prim.list->tuple"), NoConversion
+tupleEqDict :: LispName("prim.tupleEqDict")
+tupleOrdDict :: LispName("prim.tupleOrdDict")
+tupleIxDict :: LispName("prim.tupleIxDict")
+tupleTextDict :: LispName("prim.tupleTextDict")
+tupleBinaryDict :: LispName("prim.tupleBinaryDict")
+
+#-}
+
+
+
+
diff --git a/progs/prelude/PreludeTuplePrims.hu b/progs/prelude/PreludeTuplePrims.hu
new file mode 100644
index 0000000..eaa0385
--- /dev/null
+++ b/progs/prelude/PreludeTuplePrims.hu
@@ -0,0 +1,4 @@
+:output $PRELUDEBIN/PreludeTuplePrims
+:stable
+:prelude
+PreludeTuplePrims.hi
diff --git a/progs/prelude/README b/progs/prelude/README
new file mode 100644
index 0000000..2decc21
--- /dev/null
+++ b/progs/prelude/README
@@ -0,0 +1,12 @@
+
+This is the actual prelude used by the Yale system. This contains a many
+small changes to the standard prelude, mostly optimizer annotations.
+PreludeIO is totally different since we have flushed streams in favor
+of the monad. Primitives are defined using the Haskell to Lisp interface.
+
+Arrays are implemented internally using destructive updates - no array
+primitive involves more than one copy operation and lookup is constant
+time.
+
+The data constructors for Complex and Rational are strict.
+
diff --git a/progs/tutorial/README b/progs/tutorial/README
new file mode 100644
index 0000000..defe248
--- /dev/null
+++ b/progs/tutorial/README
@@ -0,0 +1,12 @@
+
+This is the text of the online version of the tutorial. It is set up to
+run under Emacs only. Form feeds divide the pages of the tutorial. Emacs
+has a special mode just for the tutorial which makes a local copy of each
+page for the user to scribble on without disturbing this source.
+
+It is possible that this could be adapted to the command interface by
+breaking it up into one file per page.
+
+This is still preliminary - we need to work on the text and examples.
+Please send comments to haskell-request@cs.yale.edu.
+
diff --git a/progs/tutorial/tutorial.hs b/progs/tutorial/tutorial.hs
new file mode 100644
index 0000000..eb6a78d
--- /dev/null
+++ b/progs/tutorial/tutorial.hs
@@ -0,0 +1,2143 @@
+-- Page 0 Introduction
+
+This is a programming supplement to `A Gentle Introduction to Haskell'
+by Hudak and Fasel. This supplement augments the tutorial by
+providing executable Haskell programs which you can run and
+experiment with. All program fragments in the tutorial are
+found here, as well as other examples not included in the tutorial.
+
+
+Using This Tutorial
+
+You should have a copy of both the `Gentle Introduction' and the
+report itself to make full use of this tutorial. Although the
+`Gentle Introduction' is meant to stand by itself, it is often easier
+to learn a language through actual use and experimentation than by
+reading alone. Once you finish this introduction, we recommend that
+you proceed section by section through the `Gentle Introduction' and
+after having read each section go back to this online tutorial. You
+should wait until you have finished the tutorial before attempting to
+read the report. We assume that you are familiar with the basics of
+Emacs and that Haskell has been installed at your site.
+
+This tutorial does not assume any familiarity with Haskell or other
+functional languages. However, knowledge of almost-functional
+languages such as ML or Scheme is very useful. Throughout the
+online component of this tutorial, we try to relate Haskell to
+other programming languages and clarify the written tutorial through
+additional examples and text.
+
+
+Organization of the Online Tutorial
+
+This online tutorial is divided into a series of pages. Each page
+covers one or more sections in the written tutorial. You can use
+special Emacs commands to move back and forth through the pages of the
+online tutorial. Each page is a single Haskell program. Comments in
+the program contain the text of the online tutorial. You can modify
+the program freely (this will not change the underlying tutorial
+file!) and ask the system to print the value of expressions defined in
+the program.
+
+At the beginning of each page, the sections covered by the page are
+listed. In addition, the start of each individual section is
+marked within each page. Emacs commands can take you directly to a
+specific page or section in the tutorial.
+
+To create useful, executable examples of Haskell code, some language
+constructs need to be revealed well before they are explained in the
+tutorial. We attempt to point these out when they occur. Some
+small changes have been made to the examples in the written tutorial;
+these are usually cosmetic and should be ignored. Don't feel you have
+to understand everything on a page before you move on -- many times
+concepts become clearer as you move on and can relate them to other
+aspect of the language.
+
+Each page of the tutorial defines a set of variables. Some of
+these are named e1, e2, and so on. These `e' variables are the ones
+which are meant for you to evaluate as you go through the tutorial.
+Of course you may evaluate any other expressions or variables you wish.
+
+
+The Haskell Report
+
+While the report is not itself a tutorial on the Haskell language, it
+can be an invaluable reference to even a novice user. A very
+important feature of Haskell is the prelude. The prelude is a
+rather large chunk of Haskell code which is implicitly a part of every
+Haskell program. Whenever you see functions used which are not
+defined in the current page, these come from the Prelude. Appendix A
+of the report lists the entire Prelude; the index has an entry for
+every function in the Prelude. Looking at the definitions in the
+Prelude is sometimes necessary to fully understand the programs in
+this tutorial.
+
+Another reason to look at the report is to understand the syntax of
+Haskell. Appendix B contains the complete syntax for Haskell. The
+tutorial treats the syntax very informally; the precise details are
+found only in the report.
+
+
+The Yale Haskell System
+
+This version of the tutorial runs under version Y2.0 of Yale Haskell.
+The Yale Haskell system is an interactive programming environment for
+the Haskell language. The system is best used in conjunction with the
+Emacs editor. Yale Haskell is available free of change via ftp.
+
+
+Using the Compiler
+
+Yale Haskell runs as a subprocess under Emacs. While many commands
+are available to the Yale Haskell user, a single command is the
+primary means of communicating with the compiler: C-c e. This command
+evaluates and prints an expression in the context of the program on
+the screen. Here is what this command does:
+
+a) You are prompted for an expression in the minibuffer. You can
+use M-p or M-n to move through a ring of previous inputs.
+
+b) If an inferior Haskell process is not running, a buffer named *haskell*
+is created and the Haskell compiler is started up. The *haskell* buffer
+pops onto your screen.
+
+c) If the program in the current page of the tutorial has not yet been
+compiled or the page has been modified after its most recent
+compilation, the entire page is compiled. This may result in a short delay.
+
+d) If there are no errors in the program, the expression entered in
+step a) is compiled in the context of the program. Any value defined
+in the current page can be referenced.
+
+e) If there are no errors in the expression, its value is printed in
+the *haskell* buffer.
+
+There are also a few other commands you can use. C-c i interrupts
+the Haskell program. Some tight loops cannot be interrupted; in this
+case you will have to kill the Haskell process. C-c q exits the Haskell
+process.
+
+
+Emacs Commands Used by the Tutorial
+
+These commands are specific to the tutorial. The tutorial is entered
+using M-x haskell-tutorial and is exited with C-c q. To move among
+the pages of the tutorial, use
+
+C-c C-f -- go forward 1 page
+C-c C-b -- go back 1 page
+M-x ht-goto-page - goto a specific page of the tutorial
+M-x ht-goto-section - goto a specific section of the tutorial
+
+Each page of the tutorial can be modified without changing the
+underlying text of the tutorial. Changes are not saved as you go
+between pages. To revert a page to its original form use C-c C-l.
+
+You can get help regarding the Emacs commands with C-c ?.
+
+Summary of Emacs commands used by the tutorial:
+ M-x haskell-tutorial - start the tutorial
+ C-c C-f - Go to the next page of the tutorial program
+ C-c C-b - Go back to the previous page of the tutorial program
+ C-c C-l - Restore the current page to its original form
+ C-c e - Evaluate a Haskell expression
+ C-c i - Interrupt a running Haskell program
+ C-c ? - Shows a help message
+ M-x ht-goto-page - goto a specific page of the tutorial
+ M-x ht-goto-section - goto a specific section of the tutorial
+
+
+You are now ready to start the tutorial. Start by reading the `Gentle
+Introduction' section 1 then proceed through the online tutorial using
+C-c C-f to advance to the next page. You should read about each topic
+first before turning to the associated programming example in the
+online tutorial.
+
+
+-- Page 1 Section 2
+
+-- Section 2 Values, Types, and Other Goodies
+
+-- Haskell uses `--' to designate end of line comments. We use these
+-- throughout the tutorial to place explanatory text in the program.
+
+-- Remember to use C-c e to evaluate expressions, C-c ? for help.
+
+-- All Haskell programs must start with a module declaration. Ignore this
+-- for now.
+
+module Test(Bool) where
+
+-- We will start by defining some identifiers (variables) using equations.
+-- You can print out the value of an identifier by typing C-c e and
+-- typing the name of the identifier you wish to evaluate. This will
+-- compile the entire program, not just the line with the definition
+-- you want to see. Not all definitions are very interesting to print out -
+-- by convention, we will use variables e1, e2, ... to denote values that
+-- are `interesting' to print.
+
+-- We'll start with some constants as well as their associated type.
+-- There are two ways to associate a type with a value: a type declaration
+-- and an expression type signature. Here is an equation and a type
+-- declaration:
+
+e1 :: Int -- This is a type declaration for the identifier e1
+e1 = 5 -- This is an equation defining e1
+
+-- You can evaluate the expression e1 and watch the system print `5'! Wow!
+
+-- Remember that C-c e is prompting for an expression. Expressions like
+-- e1 or 5 or 1+1 are all valid. However, `e1 = 5' is a definition,
+-- not an expression. Trying to evaluate it will result in a syntax error.
+
+-- The type declaration for e1 is not really necessary but we will try to
+-- always provide type declarations for values to help document the program
+-- and to ensure that the system infers the same type we do for an expression.
+-- If you change the value for e1 to `True', the program will no longer
+-- compile due to the type mismatch.
+
+-- We will briefly mention expression type signatures: these are attached to
+-- expressions instead of identifiers. Here are equivalent ways to do
+-- the previous definition:
+
+e2 = 5 :: Int
+e3 = (2 :: Int) + (3 :: Int)
+
+-- The :: has very low precedence in expressions and should usually be placed
+-- in parenthesis.
+
+-- Note that there are two completely separate languages: an expression
+-- language for values and a type language for type signatures. The type
+-- language is used only in the type declarations previously described and
+-- declarations of new types, described later. Haskell uses a
+-- uniform syntax so that values resemble their type signature as much as
+-- possible. However, you must always be aware of the difference between
+-- type expressions and value expressions.
+
+-- Here are some of the predefined types Haskell provides:
+-- type Value Syntax Type Syntax
+-- Small integers <digits> Int
+e4 :: Int
+e4 = 12345
+-- Characters '<character>' Char
+e5 :: Char
+e5 = 'a'
+-- Boolean True, False Bool
+e6 :: Bool
+e6 = True
+-- Floating point <digits.digits> Float
+e7 :: Float
+e7 = 123.456
+-- We will introduce these types now; there will be much more to say later.
+-- Homogenous List [<exp1>,<exp2>,...] [<constituant type>]
+e8 :: [Int]
+e8 = [1,2,3]
+-- Tuple (<exp1>,<exp2>,...) (<exp1-type>,<exp2-type>,...)
+e9 :: (Char,Int)
+e9 = ('b',4)
+-- Functional described later domain type -> range type
+succ :: Int -> Int -- a function which takes an Int argument and returns Int
+succ x = x + 1 -- test this by evaluating `succ 4'
+
+-- Here's a few leftover examples from section 2:
+
+e10 = succ (succ 3) -- you could also evaluate `succ (succ 3)' directly
+ -- by entering the entire expression to the C-c e
+
+-- If you want to evaluate something more complex than the `e' variables
+-- defined here, it is better to enter a complex expression, such as
+-- succ (succ 3), directly than to edit a new definition like e10 into
+-- the program. This is because any change to the program will require
+-- recompilation of the entire page. The expressions entered to C-c e are
+-- compiled separately (and very quickly!).
+
+-- Uncomment this next line to see a compile time type error.
+-- e11 = 'a'+'b'
+-- Don't worry about the error message - it will make more sense later.
+
+-- Proceed to the next page using C-c C-f
+
+-- Page 2 Section 2.1
+
+-- Section 2.1 Polymorphic Types
+
+module Test(Bool) where
+
+-- The following line allows us to redefine functions in the standard
+-- prelude. Ignore this for now.
+
+import Prelude hiding (length,head,tail,null)
+
+-- start with some sample lists to use in test cases
+
+list1 :: [Int]
+list1 = [1,2,3]
+list2 :: [Char] -- This is the really a string
+list2 = ['a','b','c'] -- This is the same as "abc"; evaluate list2 and see.
+list3 :: [[a]] -- The element type of the inner list is unknown
+list3 = [[],[],[],[]] -- so this list can't be printed
+list4 :: [Int]
+list4 = 1:2:3:4:[] -- Exactly the same as [1,2,3,4]; print it and see.
+
+-- This is the length function. You can test it by evaluating expressions
+-- such as `length list1'. Function application is written by
+-- simple juxtaposition: `f(x)' in other languages would be `f x' in Haskell.
+
+length :: [a] -> Int
+length [] = 0
+length (x:xs) = 1 + length xs
+
+-- Function application has the highest precedence, so 1 + length xs is
+-- parsed as 1 + (length xs). In general, you have to surround
+-- non-atomic arguments to a function with parens. This includes
+-- arguments which are also function applications. For example,
+-- f g x is the function f applied to arguments g and x, similar to
+-- f(g,x) in other languages. However, f (g x) is f applied to (g x), or
+-- f(g(x)), which means something quite different! Be especially
+-- careful with infix operators: f x+1 y-2 would be parsed as (f x)+(1 y)-2.
+-- This is also true on the left of the `=': the parens around (x:xs) are
+-- absolutely necessary. length x:xs would be parsed as (length x):xs.
+
+-- Also be careful with prefix negation, -. The application `f -1' is
+-- f-1, not f(-1). Add parens around negative numbers to avoid this
+-- problem.
+
+-- Here are some other list functions:
+
+head :: [a] -> a -- returns the first element in a list (same as car in lisp)
+head (x:xs) = x
+
+tail :: [a] -> [a] -- removes the first element from a list (same as cdr)
+tail (x:xs) = xs
+
+null :: [a] -> Bool
+null [] = True
+null (x:xs) = False
+
+cons :: a -> [a] -> [a]
+cons x xs = x:xs
+
+nil :: [a]
+nil = []
+
+-- Length could be defined using these functions too. This is
+-- not good Haskell style but does illustrate these other list functions.
+-- The if - then - else will be discussed later. Haskell programmers feel
+-- that the pattern matching style, as used in the previous version of
+-- length, is more natural and readable.
+
+length' :: [a] -> Int -- Note that ' can be part of a name
+length' x = if null x then 0 else 1 + length' (tail x)
+
+-- A test case for length', cons, and nil
+
+e1 = length' (cons 1 (cons 2 nil))
+
+-- We haven't said anything about errors yet. Each of the following
+-- examples illustrates a potential runtime or compile time error. The
+-- compile time error is commented out so that other examples will compile;
+-- you can uncomment them and see what happens.
+
+-- e2 = cons True False -- Why is this not possible in Haskell?
+e3 = tail (tail ['a']) -- What happens if you evaluate this?
+e4 = [] -- This is especially mysterious!
+
+-- This last example, e4, is something hard to explain but is often
+-- encountered early by novices. We haven't explained yet how the system
+-- prints out the expressions you type in - this will wait until later.
+-- However, the problem here is that e4 has the type [a]. The printer for
+-- the list datatype is complaining that it needs to know a specific type
+-- for the list elements even though the list has no elements! This can
+-- be avoided by giving e4 a type such as [Int]. (To further confuse you,
+-- try giving e4 the type [Char] and see what happens.)
+
+-- Page 3 Section 2.2
+
+-- Section 2.2 User-Defined Types
+
+module Test(Bool) where
+
+-- The type Bool is already defined in the Prelude so there is no
+-- need to define it here.
+
+data Color = Red | Green | Blue | Indigo | Violet deriving Text
+-- The `deriving Text' is necessary if you want to print a Color value.
+
+-- You can now evaluate these expressions.
+e1 :: Color
+e1 = Red
+e2 :: [Color]
+e2 = [Red,Blue]
+
+-- It is very important to keep the expression language and the type
+-- language in Haskell separated. The data declaration above defines
+-- the type constructor Color. This is a nullary constructor: it takes no
+-- arguments. Color is found ONLY in the type language - it can not be
+-- part of an expression. e1 = Color is meaningless. (Actually, Color could
+-- be both a data constructor and a type constructor but we'll ignore this
+-- possibility for now). On the other hand, Red, Blue, and so on are
+-- (nullary) data constructors. They can appear in expressions and
+-- in patterns (described later). The declaration e1 :: Blue would also
+-- be meaningless. Data constructors can be defined ONLY in a data
+-- declaration.
+
+-- In the next example, Point is a type constructor and Pt is a data
+-- constructor. Point takes one argument and Pt takes two. A data constructor
+-- like Pt is really just an ordinary function except that it can be used in
+-- a pattern. Type signatures can not be supplied directly for data
+-- constructors; their typing is completely defined by the data declaration.
+-- However, data constructors have a signature just like any variable:
+-- Pt :: a -> a -> Point a -- Not valid Haskell syntax
+-- That is, Pt is a function which takes two arguments with the same
+-- arbitrary type and returns a value containing the two argument values.
+
+data Point a = Pt a a deriving Text
+
+e3 :: Point Float
+e3 = Pt 2.0 3.0
+e4 :: Point Char
+e4 = Pt 'a' 'b'
+e5 :: Point (Point Int)
+e5 = Pt (Pt 1 2) (Pt 3 4)
+-- e6 = Pt 'a' True -- This is a typing error
+
+-- The individual components of a point do not have names.
+-- Let's jump ahead a little so that we can write functions using these
+-- data types. Data constructors (Red, Blue, ..., and Pt) can be used in
+-- patterns. When more than one equation is used to define a function,
+-- pattern matching occurs top down.
+
+-- A function to remove red from a list of colors.
+
+removeRed :: [Color] -> [Color]
+removeRed [] = []
+removeRed (Red:cs) = removeRed cs
+removeRed (c:cs) = c : removeRed cs -- c cannot be Red at this point
+
+e7 :: [Color]
+e7 = removeRed [Blue,Red,Green,Red]
+
+-- Pattern matching is capable of testing equality with a specific color.
+
+-- All equations defining a function must share a common type. A
+-- definition such as:
+-- foo Red = 1
+-- foo (Pt x y) = x
+-- would result in a type error since the argument to foo cannot be both a
+-- Color and a Point. Similarly, the right hand sides must also share a
+-- common type; a definition such as
+-- foo Red = Blue
+-- foo Blue = Pt Red Red
+-- would also result in a type error.
+
+-- Here's a couple of functions defined on points.
+
+dist :: Point Float -> Point Float -> Float
+dist (Pt x1 y1) (Pt x2 y2) = sqrt ((x1-x2)^2 + (y1-y2)^2)
+
+midpoint :: Point Float -> Point Float -> Point Float
+midpoint (Pt x1 y1) (Pt x2 y2) = Pt ((x1+x2)/2) ((y1+y2)/2)
+
+p1 :: Point Float
+p1 = Pt 1.0 1.0
+p2 :: Point Float
+p2 = Pt 2.0 2.0
+
+e8 :: Float
+e8 = dist p1 p2
+e9 :: Point Float
+e9 = midpoint p1 p2
+
+-- The only way to take apart a point is to pattern match.
+-- That is, the two values which constitute a point must be extracted
+-- by matching a pattern containing the Pt data constructor. Much
+-- more will be said about pattern matching later.
+
+-- Haskell prints values in the same syntax used in expressions. Thus
+-- Pt 1 2 would print as Pt 1 2 (of course, Pt 1 (1+1) would also print
+-- as Pt 1 2).
+
+-- Page 4 Section 2.3
+
+-- Section 2.3 Recursive Types
+
+module Test where
+
+data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Text
+
+-- The following typings are implied by this declaration. As before,
+-- this is not valid Haskell syntax.
+-- Leaf :: a -> Tree a
+-- Branch :: Tree a -> Tree a -> Tree a
+
+fringe :: Tree a -> [a]
+fringe (Leaf x) = [x]
+fringe (Branch left right) = fringe left ++ fringe right
+
+-- The following trees can be used to test functions:
+
+tree1 :: Tree Int
+tree1 = Branch (Leaf 1) (Branch (Branch (Leaf 2) (Leaf 3)) (Leaf 4))
+tree2 :: Tree Int
+tree2 = Branch (Branch (Leaf 3) (Leaf 1)) (Branch (Leaf 4) (Leaf 1))
+tree3 :: Tree Int
+tree3 = Branch tree1 tree2
+
+-- Try evaluating `fringe tree1' and others.
+
+-- Here's another tree function:
+
+twist :: Tree a -> Tree a
+twist (Branch left right) = Branch right left
+twist x = x -- This equation only applies to leaves
+
+-- Here's a function which compares two trees to see if they have the
+-- same shape. Note the signature: the two trees need not contain the
+-- same type of values.
+
+sameShape :: Tree a -> Tree b -> Bool
+sameShape (Leaf x) (Leaf y) = True
+sameShape (Branch l1 r1) (Branch l2 r2) = sameShape l1 l2 && sameShape r1 r2
+sameShape x y = False -- One is a branch, the other is a leaf
+
+-- The && function is a boolean AND function.
+
+-- The entire pattern on the left hand side must match in order for the
+-- right hand side to be evaluated. The first clause requires both
+-- arguments to be a leaf' otherwise the next equation is tested.
+-- The last clause will always match: the final x and y match both
+-- leaves and branches.
+
+-- This compares a tree of integers to a tree of booleans.
+e1 = sameShape tree1 (Branch (Leaf True) (Leaf False))
+
+-- Page 5 Sections 2.4, 2.5, 2.6
+
+-- Section 2.4 Type Synonyms
+
+module Test(Bool) where
+
+-- Since type synonyms are part of the type language only, it's hard to
+-- write a program which shows what they do. Essentially, they are like
+-- macros for the type language. They can be used interchangably with their
+-- definition:
+
+e1 :: String
+e1 = "abc"
+e2 :: [Char] -- No different than String
+e2 = e1
+
+-- In the written tutorial the declaration of `Addr' is a data type
+-- declaration, not a synonym declaration. This shows that the data
+-- type declaration as well as a signature can reference a synonym.
+
+-- Section 2.5 Built-in Types
+
+-- Tuples are an easy way of grouping a set of data values. Here are
+-- a few tuples. Note the consistancy in notation between the values and
+-- types.
+
+e3 :: (Bool,Int)
+e3 = (True,4)
+e4 :: (Char,[Int],Char)
+e4 = ('a',[1,2,3],'b')
+
+-- Here's a function which returns the second component of a 3 tuple.
+second :: (a,b,c) -> b
+second (a,b,c) = b
+
+-- Try out `second e3' and `second e4' - what happens?
+-- Each different size of tuple is a completely distinct type. There is
+-- no general way to append two arbitrary tuples or randomly select the
+-- i'th component of an arbitrary tuple. Here's a function built using
+-- 2-tuples to represent intervals.
+
+-- Use a type synonym to represent homogenous 2 tuples
+type Interval a = (a,a)
+
+containsInterval :: Interval Int -> Interval Int -> Bool
+containsInterval (xmin,xmax) (ymin,ymax) = xmin <= ymin && xmax >= ymax
+
+p1 :: Interval Int
+p1 = (2,3)
+p2 :: Interval Int
+p2 = (1,4)
+
+e5 = containsInterval p1 p2
+e6 = containsInterval p2 p1
+
+-- Here's a type declaration for a type isomorphic to lists:
+
+data List a = Nil | Cons a (List a) deriving Text
+
+-- Except for the notation, this is completely equivalent to ordinary lists
+-- in Haskell.
+
+length' :: List a -> Int
+length' Nil = 0
+length' (Cons x y) = 1 + length' y
+
+e7 = length' (Cons 'a' (Cons 'b' (Cons 'c' Nil)))
+
+-- It's hard to demonstrate much about the `non-specialness' of built-in
+-- types. However, here is a brief summary:
+
+-- Numbers and characters, such as 1, 2.2, or 'a', are the same as nullary
+-- type constructors.
+
+-- Lists have a special type constructor, [a] instead of List a, and
+-- an odd looking data constructor, []. The other data constructor, :, is
+-- not `unusual', syntactically speaking. The notation [x,y] is just
+-- syntax for x:y:[] and "abc" for 'a' : 'b' : 'c' : [].
+
+-- Tuples use a special syntax. In a type expression, a 2 tuple containing
+-- types a and be would be written (a,b) instead of using a prefix type
+-- constructor such as Tuple2 a b. This same notation is used to build
+-- tuple values: (1,2) would construct a 2 tuple containing the values 1 and 2.
+
+
+-- Page 6 Sections 2.5.1, 2.5.2
+
+module Test(Bool) where
+
+-- Section 2.5.1 List Comprehensions and Arithmetic Sequences
+
+-- Warning: brackets in Haskell are used in three different types
+-- of expressions: lists, as in [a,b,c], sequences (distinguished by
+-- the ..), as in [1..2], and list comprehensions (distinguished by the
+-- bar: |), as in [x+1 | x <- xs, x > 1].
+
+-- Before list comprehensions, let's start out with sequences:
+
+e1 :: [Int]
+e1 = [1..10] -- Step is 1
+e2 :: [Int]
+e2 = [1,3..10] -- Step is 3 - 1
+e3 :: [Int]
+e3 = [1,-1..-10]
+e4 :: [Char]
+e4 = ['a'..'z'] -- This works on chars too
+
+-- We'll avoid infinite sequences like [1..] for now. If you print one,
+-- use C-c i to interrupt the Haskell program.
+
+-- List comprehensions are very similar to nested loops. They return a
+-- list of values generated by the expression inside the loop. The filter
+-- expressions are similar to conditionals in the loop.
+
+-- This function does nothing at all! It just scans through a list and
+-- copies it into a new one.
+
+doNothing :: [a] -> [a]
+doNothing l = [x | x <- l]
+
+-- Adding a filter to the previous function allows only selected elements to
+-- be generated. This is similar to what is done in quicksort.
+
+positives :: [Int] -> [Int]
+positives l = [x | x <- l, x > 0]
+
+e5 = positives [2,-4,5,6,-5,3]
+
+-- Now the full quicksort function.
+
+quicksort :: [Char] -> [Char] -- Use Char just to be different!
+quicksort [] = []
+quicksort (x:xs) = quicksort [y | y <- xs, y <= x] ++
+ [x] ++
+ quicksort [y | y <- xs, y > x]
+
+e6 = quicksort "Why use Haskell?"
+
+-- Now for some nested loops. Each generator, <-, adds another level of
+-- nesting to the loop. Note that the variable introduced by each generator
+-- can be used in each following generator; all variables can be used in the
+-- generated expression:
+
+e7 :: [(Int,Int)]
+e7 = [(x,y) | x <- [1..5], y <- [x..5]]
+
+-- Now let's add some guards: (the /= function is `not equal')
+
+e8 :: [(Int,Int)]
+e8 = [(x,y) | x <- [1..7], x /= 5, y <- [x..8] , x*y /= 12]
+
+-- This is the same as the loop: (going to a psuedo Algol notation)
+-- for x := 1 to 7 do
+-- if x <> 5 then
+-- for y := x to 8 do
+-- if x*y <> 12
+-- generate (x,y)
+
+-- Section 2.5.2 Strings
+
+e9 = "hello" ++ " world"
+
+-- Page 7 Sections 3, 3.1
+
+module Test(Bool) where
+import Prelude hiding (map)
+
+-- Section 3 Functions
+
+add :: Int -> Int -> Int
+add x y = x+y
+
+e1 :: Int
+e1 = add 1 2
+
+-- This Int -> Int is the latter part of the signature of add:
+-- add :: Int -> (Int -> Int)
+
+succ :: Int -> Int
+succ = add 1
+
+e2 :: Int
+e2 = succ 3
+
+map :: (a->b) -> [a] -> [b]
+map f [] = []
+map f (x:xs) = f x : (map f xs)
+
+e3 :: [Int]
+e3 = map (add 1) [1,2,3]
+-- This next definition is the equivalent to e3
+e4 :: [Int]
+e4 = map succ [1,2,3]
+
+-- Heres a more complex example. Define flist to be a list of functions:
+flist :: [Int -> Int]
+flist = map add [1,2,3]
+-- This returns a list of functions which add 1, 2, or 3 to their input.
+-- Warning: Haskell should print flist as something like
+-- [<<function>>,<<function>>,<<function>>]
+
+
+-- Now, define a function which takes a function and returns its value
+-- when applied to the constant 1:
+applyTo1 :: (Int -> a) -> a
+applyTo1 f = f 1
+
+e5 :: [Int]
+e5 = map applyTo1 flist -- Apply each function in flist to 1
+
+-- If you want to look at how the type inference works, figure out how
+-- the signatures of map, applyTo1, and flist combine to yield [Int].
+
+-- Section 3.1 Lambda Abstractions
+
+-- The symbol \ is like `lambda' in lisp or scheme.
+
+-- Anonymous functions are written as \ arg1 arg2 ... argn -> body
+-- Instead of naming every function, you can code it inline with this
+-- notation:
+
+e6 = map (\f -> f 1) flist
+
+-- Be careful with the syntax here. \x->\y->x+y parses as
+-- \ x ->\ y -> x + y. The ->\ is all one token. Use spaces!!
+
+-- This is identical to e5 except that the applyTo1 function has no name.
+
+-- Function arguments on the left of an = are the same as lambda on the
+-- right:
+
+add' = \x y -> x+y -- identical to add
+succ' = \x -> x+1 -- identical to succ
+
+-- As with ordinary function, the parameters to anonymous functions
+-- can be patterns:
+
+e7 :: [Int]
+e7 = map (\(x,y) -> x+y) [(1,2),(3,4),(5,6)]
+
+-- Functions defined by more than one equation, like map, cannot
+-- be converted to anonymous lambda functions quite as easily - a case
+-- statement is also required. This is discussed later.
+
+-- Page 8 Sections 3.2, 3.2.1, 3.2.2
+
+module Test(Bool) where
+
+import Prelude hiding ((++),(.))
+
+-- Section 3.2 Infix operators
+
+-- Haskell has both identifiers, like x, and operators, like +.
+-- These are just two different types of syntax for variables.
+-- However, operators are by default used in infix notation.
+
+-- Briefly, identifiers begin with a letter and may have numbers, _, and '
+-- in them: x, xyz123, x'', xYz'_12a. The case of the first letter
+-- distinguishes variables from data constructors (or type variables from
+-- type constructors). An operator is a string of symbols, where
+-- :!#$%&*+./<=>?@\^| are all symbols. If the first character is : then
+-- the operator is a data constructor; otherwise it is an ordinary
+-- variable operator. The - and ~ characters may start a symbol but cannot
+-- be used after the first character. This allows a*-b to parse as
+-- a * - b instead of a *- b.
+
+-- Operators can be converted to identifiers by enclosing them in parens.
+-- This is required in signature declarations. Operators can be defined
+-- as well as used in the infix style:
+
+(++) :: [a] -> [a] -> [a]
+[] ++ y = y
+(x:xs) ++ y = x : (xs ++ y)
+
+-- Table 2 (Page 54) of the report is invaluable for sorting out the
+-- precedences of the many predefined infix operators.
+
+e1 = "Foo" ++ "Bar"
+
+-- This is the same function without operator syntax
+appendList :: [a] -> [a] -> [a]
+appendList [] y = y
+appendList (x:xs) y = x : appendList xs y
+
+(.) :: (b -> c) -> (a -> b) -> (a -> c)
+f . g = \x -> f (g x)
+
+add1 :: Int -> Int
+add1 x = x+1
+
+e2 = (add1 . add1) 3
+
+-- Section 3.2.1 Sections
+
+-- Sections are a way of creating unary functions from infix binary
+-- functions. When a parenthesized expression starts or ends in an
+-- operator, it is a section. Another definition of add1:
+
+add1' :: Int -> Int
+add1' = (+ 1)
+
+e3 = add1' 4
+
+-- Here are a few section examples:
+
+e4 = map (++ "abc") ["x","y","z"]
+
+e5 = map ("abc" ++) ["x","y","z"]
+
+
+-- Section 3.2.2 Fixity Declarations
+
+-- We'll avoid any demonstration of fixity declarations. The Prelude
+-- contains numerous examples.
+
+-- Page 9 Sections 3.3, 3.4, 3.5
+module Test(Bool) where
+
+import Prelude hiding (take,zip)
+
+-- Section 3.3 Functions are Non-strict
+
+-- Observing lazy evaluation can present difficulties. The essential
+-- question is `does an expression get evaluated?'. While in theory using a
+-- non-terminating computation is the way evaluation issues are examined,
+-- we need a more practical approach. The `error' function serves as
+-- a bottom value. Evaluating this function prints an error message and
+-- halts execution.
+
+bot = error "Evaluating Bottom"
+
+e1 :: Bool -- This can be any type at all!
+e1 = bot -- evaluate this and see what happens.
+
+const1 :: a -> Int
+const1 x = 1
+
+e2 :: Int
+e2 = const1 bot -- The bottom is not needed and will thus not be evaluated.
+
+-- Section 3.4 "Infinite" Data Structures
+
+-- Data structures are constructed lazily. A constructor like : will not
+-- evaluate its arguments until they are demanded. All demands arise from
+-- the need to print the result of the computation -- components not needed
+-- to compute the printed result will not be evaluated.
+
+list1 :: [Int]
+list1 = (1:bot)
+
+e3 = head list1 -- doesnt evaluate bot
+e4 = tail list1 -- does evaluate bot
+
+-- Some infinite data structures. Don't print these! If you do, you will
+-- need to interrupt the system (C-c i) or kill the Haskell process.
+
+ones :: [Int]
+ones = 1 : ones
+
+numsFrom :: Int -> [Int]
+numsFrom n = n : numsFrom (n+1)
+
+-- An alternate numsFrom using series notation:
+
+numsFrom' :: Int -> [Int]
+numsFrom' n = [n..]
+
+squares :: [Int]
+squares = map (^2) (numsFrom 0)
+
+-- Before we start printing anything, we need a function to truncate these
+-- infinite lists down to a more manageable size. The `take' function
+-- extracts the first k elements of a list:
+
+take :: Int -> [a] -> [a]
+take 0 x = [] -- two base cases: k = 0
+take k [] = [] -- or the list is empty
+take k (x:xs) = x : take (k-1) xs
+
+-- now some printable lists:
+
+e5 :: [Int]
+e5 = take 5 ones
+
+e6 :: [Int]
+e6 = take 5 (numsFrom 10)
+
+e7 :: [Int]
+e7 = take 5 (numsFrom' 0)
+
+e8 :: [Int]
+e8 = take 5 squares
+
+-- zip is a function which turns two lists into a list of 2 tuples. If
+-- the lists are of differing sizes, the result is as long as the
+-- shortest list.
+
+zip (x:xs) (y:ys) = (x,y) : zip xs ys
+zip xs ys = [] -- one of the lists is []
+
+e9 :: [(Int,Int)]
+e9 = zip [1,2,3] [4,5,6]
+
+e10 :: [(Int,Int)]
+e10 = zip [1,2,3] ones
+
+fib :: [Int]
+fib = 1 : 1 : [x+y | (x,y) <- zip fib (tail fib)]
+
+e11 = take 5 fib
+
+-- Let's do this without the list comprehension:
+
+fib' :: [Int]
+fib' = 1 : 1 : map (\(x,y) -> x+y) (zip fib (tail fib))
+
+-- This could be written even more cleanly using a map function which
+-- maps a binary function over two lists at once. This is in the
+-- Prelude and is called zipWith.
+
+fib'' :: [Int]
+fib'' = 1 : 1 : zipWith (+) fib (tail fib)
+
+-- For more examples using infinite structures look in the demo files
+-- that come with Yale Haskell. Both the pascal program and the
+-- primes program use infinite lists.
+
+-- Section 3.5 The Error Function
+
+-- Too late - we already used it!
+
+
+-- Page 10 Sections 4, 4.1, 4.2
+
+module Test(Bool) where
+
+import Prelude hiding (take,(^))
+
+-- Section 4 Case Expressions and Pattern Matching
+
+-- Now for details of pattern matching. We use [Int] instead of [a]
+-- since the only value of type [a] is [].
+
+contrived :: ([Int], Char, (Int, Float), String, Bool) -> Bool
+contrived ([], 'b', (1, 2.0), "hi", True) = False
+contrived x = True -- add a second equation to avoid runtime errors
+
+e1 :: Bool
+e1 = contrived ([], 'b', (1, 2.0), "hi", True)
+e2 :: Bool
+e2 = contrived ([1], 'b', (1, 2.0), "hi", True)
+
+-- Contrived just tests its input against a big constant.
+
+-- Linearity in pattern matching implies that patterns can only compare
+-- values with constants. The following is not valid Haskell:
+
+-- member x [] = False
+-- member x (x:ys) = True -- Invalid since x appears twice
+-- member x (y:ys) = member x ys
+
+f :: [a] -> [a]
+f s@(x:xs) = x:s
+f _ = []
+
+e3 = f "abc"
+
+-- Another use of _:
+
+middle :: (a,b,c) -> b
+middle (_,x,_) = x
+
+e4 :: Char
+e4 = middle (True, 'a', "123")
+
+(^) :: Int -> Int -> Int
+x ^ 0 = 1
+x ^ (n+1) = x*(x^n)
+
+e5 :: Int
+e5 = 3^3
+e6 :: Int
+e6 = 4^(-2) -- Notice the behavior of the + pattern on this one
+
+-- Section 4.1 Pattern Matching Semantics
+
+-- Here's an extended example to illustrate the left -> right, top -> bottom
+-- semantics of pattern matching.
+
+foo :: (Int,[Int],Int) -> Int
+foo (1,[2],3) = 1
+foo (2,(3:_),3) = 2
+foo (1,_,3) = 3
+foo _ = 4
+
+bot = error "Bottom Evaluated"
+
+e7 = foo (1,[],3)
+e8 = foo (1,bot,3)
+e9 = foo (1,1:bot,3)
+e10 = foo (2,bot,2)
+e11 = foo (3,bot,bot)
+
+-- Now add some guards:
+
+sign :: Int -> Int
+sign x | x > 0 = 1
+ | x == 0 = 0
+ | x < 0 = -1
+
+e12 = sign 3
+
+-- The last guard is often `True' to catch all other cases. The identifier
+-- `otherwise' is defined as True for use in guards:
+
+max' :: Int -> Int -> Int
+max' x y | x > y = x
+ | otherwise = y
+
+-- Guards can refer to any variables bound by pattern matching. When
+-- no guard is true, pattern matching resumes at the next equation. Guards
+-- may also refer to values bound in an associated where declaration.
+
+
+inOrder :: [Int] -> Bool
+inOrder (x1:x2:xs) | x1 <= x2 = True
+inOrder _ = False
+
+e13 = inOrder [1,2,3]
+e14 = inOrder [2,1]
+
+-- Section 4.2 An Example
+
+take :: Int -> [a] -> [a]
+take 0 _ = []
+take _ [] = []
+take (n+1) (x:xs) = x:take n xs
+
+take' :: Int -> [a] -> [a]
+take' _ [] = []
+take' 0 _ = []
+take' (n+1) (x:xs) = x:take' n xs
+
+e15, e16, e17, e18 :: [Int]
+e15 = take 0 bot
+e16 = take' 0 bot
+e17 = take bot []
+e18 = take' bot []
+
+-- Page 11 Sections 4.3, 4.4, 4.5, 4.6
+
+module Test(Bool) where
+
+-- import Prelude hiding (take,Request(..),Response(..)) -- Standard Haskell
+import Prelude hiding (take) -- Y2.0-b4 only
+
+-- Section 4.3 Case Expressions
+
+-- The function take using a case statement instead of multiple equations
+
+take :: Int -> [a] -> [a]
+take m ys = case (m,ys) of
+ (0 ,_) -> []
+ (_ ,[]) -> []
+ (n+1,x:xs) -> x : take n xs
+
+-- The function take using if then else. We can also eliminate the n+k
+-- pattern just for fun. The original version of take is much easier to read!
+
+take' :: Int -> [a] -> [a]
+take' m ys = if m == 0 then [] else
+ if null ys then [] else
+ if m > 0 then head ys : take (m-1) (tail ys)
+ else error "m < 0"
+
+-- Section 4.4 Lazy Patterns
+
+-- Before the client-server example, here is a contrived example of lazy
+-- patterns. The first version will fail to pattern match whenever the
+-- the first argument is []. The second version will always pattern
+-- match initially but x will fail if used when the list is [].
+
+nonlazy :: [Int] -> Bool -> [Int]
+nonlazy (x:xs) isNull = if isNull then [] else [x]
+
+e1 = nonlazy [1,2] False
+e2 = nonlazy [] True
+e3 = nonlazy [] False
+
+-- This version will never fail the initial pattern match
+lazy :: [Int] -> Bool -> [Int]
+lazy ~(x:xs) isNull = if isNull then [] else [x]
+
+e4 = lazy [1,2] False
+e5 = lazy [] True
+e6 = lazy [] False
+
+-- The server - client example is a little hard to demonstrate. We'll avoid
+-- the initial version which loops. Here is the version with irrefutable
+-- patterns.
+
+type Response = Int
+type Request = Int
+
+client :: Request -> [Response] -> [Request]
+client init ~(resp:resps) = init : client (next resp) resps
+
+server :: [Request] -> [Response]
+server (req : reqs) = process req : server reqs
+
+-- Next maps the response from the previous request onto the next request
+next :: Response -> Request
+next resp = resp
+
+-- Process maps a request to a response
+process :: Request -> Response
+process req = req+1
+
+requests :: [Request]
+requests = client 0 responses
+
+responses :: [Response]
+responses = server requests
+
+e7 = take 5 responses
+
+-- The lists of requests and responses are infinite - there is no need to
+-- check for [] in this program. These lists correspond to streams in other
+-- languages.
+
+-- Here is fib again:
+
+fib :: [Int]
+fib@(1:tfib) = 1 : 1 : [ a+b | (a,b) <- zip fib tfib]
+
+e8 = take 10 fib
+
+-- Section 4.5 Lexical Scoping and Nested Forms
+
+-- One thing that is important to note is that the order of the
+-- definitions in a program, let expression, or where clauses is
+-- completely arbitrary. Definitions can be arranged 'top down'
+-- or `bottom up' without changing the program.
+
+e9 = let y = 2 :: Float
+ f x = (x+y)/y
+ in f 1 + f 2
+
+f :: Int -> Int -> String
+f x y | y > z = "y > x^2"
+ | y == z = "y = x^2"
+ | y < z = "y < x^2"
+ where
+ z = x*x
+
+e10 = f 2 5
+e11 = f 2 4
+
+-- Section 4.6 Layout
+
+-- There's nothing much to demonstrate here. We have been using layout all
+-- through the tutorial. The main thing is to be careful line up the
+-- first character of each definition. For example, if you
+-- change the indentation of the definition of f in e9 you will get a
+-- parse error.
+
+-- Page 12 Section 5
+module Test(Bool) where
+
+import Prelude hiding (elem)
+
+-- Section 5 Type Classes
+
+-- Names in the basic class structure of Haskell cannot be hidden (they are
+-- in PreludeCore) so we have to modify the names used in the tutorial.
+
+-- Here is a new Eq class:
+
+class Eq' a where
+ eq :: a -> a -> Bool
+
+-- Now we can define elem using eq from above:
+
+elem :: (Eq' a) => a -> [a] -> Bool
+x `elem` [] = False
+x `elem` (y:ys) = x `eq` y || x `elem` ys
+
+-- Before this is of any use, we need to admit some types to Eq'
+
+instance Eq' Int where
+ x `eq` y = abs (x-y) < 3 -- Let's make this `nearly equal' just for fun
+
+instance Eq' Float where
+ x `eq` y = abs (x-y) < 0.1
+
+list1 :: [Int]
+list1 = [1,5,9,23]
+
+list2 :: [Float]
+list2 = [0.2,5.6,33,12.34]
+
+e1 = 2 `elem` list1
+e2 = 100 `elem` list1
+e3 = 0.22 `elem` list2
+
+-- Watch out! Integers in Haskell are overloaded - without a type signature
+-- to designate an integer as an Int, expressions like 3 `eq` 3 will be
+-- ambiguous. See 5.5.4 about this problem.
+
+-- Now to add the tree type:
+
+data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Text
+
+instance (Eq' a) => Eq' (Tree a) where
+ (Leaf a) `eq` (Leaf b) = a `eq` b
+ (Branch l1 r1) `eq` (Branch l2 r2) = (l1 `eq` l2) && (r1 `eq` r2)
+ _ `eq` _ = False
+
+tree1,tree2 :: Tree Int
+tree1 = Branch (Leaf 1) (Leaf 2)
+tree2 = Branch (Leaf 2) (Leaf 1)
+
+e4 = tree1 `eq` tree2
+
+-- Now make a new class with Eq' as a super class:
+
+class (Eq' a) => Ord' a where
+ lt,le :: a -> a -> Bool -- lt and le are operators in Ord'
+ x `le` y = x `eq` y || x `lt` y -- This is a default for le
+
+-- The typing of lt & le is
+-- le,lt :: (Ord' a) => a -> a -> Bool
+-- This is identical to
+-- le,lt :: (Eq' a,Ord' a) => a -> a -> Bool
+
+-- Make Int an instance of Ord
+instance Ord' Int where
+ x `lt` y = x < y+1
+
+i :: Int -- Avoid ambiguity
+i = 3
+e5 :: Bool
+e5 = i `lt` i
+
+-- Some constraints on instance declarations:
+-- A program can never have more than one instance declaration for
+-- a given combination of data type and class.
+-- If a type is declared to be a member of a class, it must also be
+-- declared in all superclasses of that class.
+-- An instance declaration does not need to supply a method for every
+-- operator in the class. When a method is not supplied in an
+-- instance declaration and no default is present in the class
+-- declaration, a runtime error occurs if the method is invoked.
+-- You must supply the correct context for an instance declaration --
+-- this context is not inferred automatically.
+
+-- Section 5.1 Equality and Ordered Classes
+-- Section 5.2 Enumeration and Index Classes
+
+-- No examples are provided for 5.1 or 5.2. The standard Prelude contains
+-- many instance declarations which illustrate the Eq, Ord, and Enum classes.
+
+-- Page 13 Section 5.3
+
+module Test(Bool) where
+
+-- Section 5.3 Text and Binary Classes
+
+-- This is the slow showTree. The `show' function is part of the
+-- Text class and works with all the built-in types. The context `Text a'
+-- arises from the call to show for leaf values.
+
+data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Text
+
+showTree :: (Text a) => Tree a -> String
+showTree (Leaf x) = show x
+showTree (Branch l r) = "<" ++ showTree l ++ "|" ++ showTree r ++ ">"
+
+tree1 :: Tree Int
+tree1 = Branch (Leaf 1) (Branch (Leaf 3) (Leaf 6))
+
+e1 = showTree tree1
+
+-- Now the improved showTree; shows is already defined for all
+-- built in types.
+
+showsTree :: Text a => Tree a -> String -> String
+showsTree (Leaf x) s = shows x s
+showsTree (Branch l r) s = '<' : showsTree l ('|' : showsTree r ('>' : s))
+
+e2 = showsTree tree1 ""
+
+-- The final polished version. ShowS is predefined in the Prelude so we
+-- don't need it here.
+
+
+showsTree' :: Text a => Tree a -> ShowS
+showsTree' (Leaf x) = shows x
+showsTree' (Branch l r) = ('<' :) . showsTree' l . ('|' :) .
+ showsTree' r . ('>' :)
+
+e3 = showsTree' tree1 ""
+
+
+-- Page 14 This page break is just to keep recompilation from getting too
+-- long. The compiler takes a little longer to compile this
+-- page than other pages.
+
+module Test(Bool) where
+
+data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Text
+
+-- Now for the reading function. Again, ReadS is predefined and reads works
+-- for all built-in types. The generators in the list comprehensions are
+-- patterns: p <- l binds pattern p to successive elements of l which match
+-- p. Elements not matching p are skipped.
+
+readsTree :: (Text a) => ReadS (Tree a)
+readsTree ('<':s) = [(Branch l r, u) | (l, '|':t) <- readsTree s,
+ (r, '>':u) <- readsTree t ]
+readsTree s = [(Leaf x,t) | (x,t) <- reads s]
+
+e4 :: [(Int,String)]
+e4 = reads "5 golden rings"
+
+e5 :: [(Tree Int,String)]
+e5 = readsTree "<1|<2|3>>"
+e6 :: [(Tree Int,String)]
+e6 = readsTree "<1|2"
+e7 :: [(Tree Int,String)]
+e7 = readsTree "<1|<<2|3>|<4|5>>> junk at end"
+
+-- Before we do the next readTree, let's play with the lex function.
+
+e8 :: [(String,String)]
+e8 = lex "foo bar bletch"
+
+-- Here's a function to completely lex a string. This does not handle
+-- lexical ambiguity - lex would return more than one possible lexeme
+-- when an ambiguity is encountered and the patterns used here would not
+-- match.
+
+lexAll :: String -> [String]
+lexAll s = case lex s of
+ [("",_)] -> [] -- lex returns an empty token if none is found
+ [(token,rest)] -> token : lexAll rest
+
+e9 = lexAll "lexAll :: String -> [String]"
+e10 = lexAll "<1|<a|3>>"
+
+-- Finally, the `hard core' reader. This is not sensitive to
+-- white space as were the previous versions.
+
+
+readsTree' :: (Text a) => ReadS (Tree a)
+readsTree' s = [(Branch l r, x) | ("<", t) <- lex s,
+ (l, u) <- readsTree' t,
+ ("|", v) <- lex u,
+ (r, w) <- readsTree' v,
+ (">", x) <- lex w ]
+ ++
+ [(Leaf x, t) | (x, t) <- reads s]
+
+-- When testing this program, you must make sure the input conforms to
+-- Haskell lexical syntax. If you remove spaces between | and < or
+-- > and > they will lex as a single token.
+
+e11 :: [(Tree Int,String)]
+e11 = readsTree' "<1 | <2 | 3> >"
+e12 :: [(Tree Bool,String)]
+e12 = readsTree' "<True|False>"
+
+-- Finally, here is a simple version of read for trees only:
+
+read' :: (Text a) => String -> (Tree a)
+read' s = case (readsTree' s) of
+ [(tree,"")] -> tree -- Only one parse, no junk at end
+ [] -> error "Couldn't parse tree"
+ [_] -> error "Crud after the tree" -- unread chars at end
+ _ -> error "Ambiguous parse of tree"
+
+e13 :: Tree Int
+e13 = read' "foo"
+e14 :: Tree Int
+e14 = read' "< 1 | < 2 | 3 > >"
+e15 :: Tree Int
+e15 = read' "3 xxx"
+
+-- Page 15 Section 5.4
+
+module Test(Bool) where
+
+-- Section 5.4 Derived Instances
+
+-- We have actually been using the derived Text instances all along for
+-- printing out trees and other structures we have defined. The code
+-- in the tutorial for the Eq and Ord instance of Tree is created
+-- implicitly by the deriving clause so there is no need to write it
+-- here.
+
+data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving (Eq,Ord,Text)
+
+-- Now we can fire up both Eq and Ord functions for trees:
+
+tree1, tree2, tree3, tree4 :: Tree Int
+tree1 = Branch (Leaf 1) (Leaf 3)
+tree2 = Branch (Leaf 1) (Leaf 5)
+tree3 = Leaf 4
+tree4 = Branch (Branch (Leaf 4) (Leaf 3)) (Leaf 5)
+
+e1 = tree1 == tree1
+e2 = tree1 == tree2
+e3 = tree1 < tree2
+
+quicksort :: Ord a => [a] -> [a]
+quicksort [] = []
+quicksort (x:xs) = quicksort [y | y <- xs, y <= x] ++
+ [x] ++
+ quicksort [y | y <- xs, y > x]
+
+e4 = quicksort [tree1,tree2,tree3,tree4]
+
+-- Now for Enum:
+
+data Day = Sunday | Monday | Tuesday | Wednesday | Thursday |
+ Friday | Saturday deriving (Text,Eq,Ord,Enum)
+
+e5 = quicksort [Monday,Saturday,Friday,Sunday]
+e6 = [Wednesday .. Friday]
+e7 = [Monday, Wednesday ..]
+e8 = [Saturday, Friday ..]
+
+
+-- Page 16 Sections 5.5, 5.5.1, 5.5.2, 5.5.3
+
+module Test(Bool) where
+
+-- Section 5.5 Numbers
+-- Section 5.5.1 Numeric Class Structure
+-- Section 5.5.2 Constructed Numbers
+
+-- Here's a brief summary of Haskell numeric classes.
+
+-- Class Num
+-- Most general numeric class. Has addition, subtraction, multiplication.
+-- Integers can be coerced to any instance of Num with fromInteger.
+-- All integer constants are in this class.
+-- Instances: Int, Integer, Float, Double, Ratio a, Complex a
+
+-- Class Real
+-- This class contains ordered numbers which can be converted to
+-- rationals.
+-- Instances: Int, Integer, Float, Double, Ratio a
+
+-- Class Integral
+-- This class deals with integer division. All values in Integral can
+-- be mapped onto Integer.
+-- Instances: Int, Integer
+
+-- Class Fractional
+-- These are numbers which can be divided. Any rational number can
+-- be converted to a fractional. Floating point constants are in
+-- this class: 1.2 would be 12/10.
+-- Instances: Float, Double, Ratio a
+
+-- Class Floating
+-- This class contains all the standard floating point functions such
+-- as sqrt and sin.
+-- Instances: Float, Double, Complex a
+
+-- Class RealFrac
+-- These values can be rounded to integers and approximated by rationals.
+-- Instances: Float, Double, Ratio a
+
+-- Class RealFloat
+-- These are floating point numbers constructed from a fixed precision
+-- mantissa and exponent.
+-- Instances: Float, Double
+
+-- There are only a few sensible combinations of the constructed numerics
+-- with built-in types:
+-- Ratio Integer (same as Rational): arbitrary precision rationals
+-- Ratio Int: limited precision rationals
+-- Complex Float: complex numbers with standard precision components
+-- Complex Double: complex numbers with double precision components
+
+
+-- The following function works for arbitrary numerics:
+
+fact :: (Num a) => a -> a
+fact 0 = 1
+fact n = n*(fact (n-1))
+
+-- Note the behavior when applied to different types of numbers:
+
+e1 :: Int
+e1 = fact 6
+e2 :: Int
+e2 = fact 20 -- Yale Haskell may not handle overflow gracefully!
+e3 :: Integer
+e3 = fact 20
+e4 :: Rational
+e4 = fact 6
+e5 :: Float
+e5 = fact 6
+e6 :: Complex Float
+e6 = fact 6
+
+-- Be careful: values like `fact 1.5' will loop!
+
+-- As a practical matter, Int operations are much faster than Integer
+-- operations. Also, overloaded functions can be much slower than non-
+-- overloaded functions. Giving a function like fact a precise typing:
+
+-- fact :: Int -> Int
+
+-- will yield much faster code.
+
+-- In general, numeric expressions work as expected. Literals are
+-- a little tricky - they are coerced to the appropriate value. A
+-- constant like 1 can be used as ANY numeric type.
+
+e7 :: Float
+e7 = sqrt 2
+e8 :: Rational
+e8 = ((4%5) * (1%2)) / (3%4)
+e9 :: Rational
+e9 = 2.2 * (3%11) - 1
+e10 :: Complex Float
+e10 = (2 * (3:+3)) / (1.1:+2.0 - 1)
+e11 :: Complex Float
+e11 = sqrt (-1)
+e12 :: Integer
+e12 = numerator (4%2)
+e13 :: Complex Float
+e13 = conjugate (4:+5.2)
+
+-- A function using pattern matching on complex numbers:
+
+mag :: (RealFloat a) => Complex a -> a
+mag (a:+b) = sqrt (a^2 + b^2)
+
+e14 :: Float
+e14 = mag (1:+1)
+
+-- Section 5.5.3 Numeric Coercions and Overloaded Literals
+
+-- The Haskell type system does NOT implicitly coerce values between
+-- the different numeric types! Although overloaded constants are
+-- coerced when the overloading is resolved, no implicit coercion goes
+-- on when values of different types are mixed. For example:
+
+f :: Float
+f = 1.1
+i1 :: Int
+i1 = 1
+i2 :: Integer
+i2 = 2
+
+-- All of these expressions would result in a type error (try them!):
+
+-- g = i1 + f
+-- h = i1 + i2
+-- i3 :: Int
+-- i3 = i2
+
+-- Appropriate coercions must be introduced by the user to allow
+-- the mixing of types in arithmetic expressions.
+
+e15 :: Float
+e15 = f + fromIntegral i1
+e16 :: Integer
+e16 = fromIntegral i1 + i2
+e17 :: Int
+e17 = i1 + fromInteger i2 -- fromIntegral would have worked too.
+
+-- Page 17 Section 5.5.4
+module Test(Bool) where
+
+-- Section 5.5.4 Default Numeric Types
+
+-- Ambiguous contexts arise frequently in numeric expressions. When an
+-- expression which produces a value with a general type, such as
+-- `1' (same as `fromInteger 1'; the type is (Num a) => a), with
+-- another expression which `consumes' the type, such as `show' or
+-- `toInteger', ambiguity arises. This ambiguity can be resolved
+-- using expression type signatures, but this gets tedious fast!
+-- Assigning a type to the top level of an ambiguous expression does
+-- not help: the ambiguity does not propagate to the top level.
+
+e1 :: String -- This type does not influence the type of the argument to show
+e1 = show 1 -- Does this mean to show an Int or a Float or ...
+e2 :: String
+e2 = show (1 :: Float)
+e3 :: String
+e3 = show (1 :: Complex Float)
+
+-- The reason the first example works is that ambiguous numeric types are
+-- resolved using defaults. The defaults in effect here are Int and
+-- Double. Since Int `fits' in the expression for e1, Int is used.
+-- When Int is not valid (due to other context constraints), Double
+-- will be tried.
+
+-- This function defaults the type of the 2's to be Int
+
+rms :: (Floating a) => a -> a -> a
+rms x y = sqrt ((x^2 + y^2) * 0.5)
+
+-- The C-c e evaluation used to the Haskell system also makes use of
+-- defaulting. When you type an expression, the system creates a
+-- simple program to print the value of the expression using a function
+-- like show. If no type signature for the printed expression is given,
+-- defaulting may occur.
+
+-- One of the reasons for adding type signatures throughout these examples
+-- is to avoid unexpected defaulting. Many of the top level signatures are
+-- required to avoid ambiguity.
+
+-- Defaulting can lead to overflow problems when values exceed Int limits.
+-- Evaluate a very large integer without a type signature to observe this
+-- (unfortunately this may cause a core dump or other unpleasantness).
+
+-- Notice that defaulting applies only to numeric classes. The
+-- show (read "xyz") -- Try this if you want!
+-- example uses only class Text so no defaulting occurs.
+
+-- Ambiguity also arises with polymorphic types. As discussed previously,
+-- expressions like [] have a similar problem.
+
+-- e4 = [] -- Won't work since [] has type [a] and `a' is not known.
+
+-- Note the difference: even though the lists have no components, the type
+-- of component makes a difference in printing.
+
+e5 = ([] :: [Int])
+e6 = ([] :: [Char])
+
+-- Page 18 Sections 6, 6.1, 6.2
+
+-- Section 6 Modules
+
+module Tree ( Tree(Leaf,Branch), fringe ) where
+-- Tree(..) would work also
+
+data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Text
+
+fringe :: Tree a -> [a]
+fringe (Leaf x) = [x]
+fringe (Branch left right) = fringe left ++ fringe right
+
+-- The Emacs interface to Haskell performs evaluation within the
+-- module containing the cursor. To evaluate e1 you must place the
+-- cursor in module Main.
+
+module Main (Tree) where
+import Tree ( Tree(Leaf, Branch), fringe)
+-- import Tree -- this would be the same thing
+e1 :: [Int]
+e1 = fringe (Branch (Leaf 1) (Leaf 2))
+
+-- This interactive Haskell environment can evaluate expressions in
+-- any module. The use of module Main is optional.
+
+-- Section 6.1 Original Names and Renaming
+
+module Renamed where
+import Tree ( Tree(Leaf,Branch), fringe)
+ renaming (Leaf to Root, Branch to Twig)
+
+e2 :: Tree Int
+e2 = Twig (Root 1) (Root 2) -- Printing always uses the original names
+
+-- Section 6.2 Interfaces and Implementations
+
+-- Yale Haskell allows separate compilation of modules using
+-- unit files. These are described in the user's guide.
+
+
+-- Page 19 Sections 6.3, 6.4
+
+-- Section 6.3 Abstract Data Types
+
+-- Since TreeADT does not import Tree it can use the name Tree without
+-- any conflict. Each module has its own separate namespace.
+
+module TreeADT (Tree, leaf, branch, cell, left,
+ right, isLeaf) where
+
+data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Text
+
+leaf = Leaf
+branch = Branch
+cell (Leaf a) = a
+left (Branch l r) = l
+right (Branch l r) = r
+isLeaf (Leaf _) = True
+isLeaf _ = False
+
+module Test where
+import TreeADT
+
+-- Since the constructors for type Tree are hidden, pattern matching
+-- cannot be used.
+
+fringe :: Tree a -> [a]
+fringe x = if isLeaf x then [cell x]
+ else fringe (left x) ++ fringe (right x)
+
+e1 :: [Int]
+e1 = fringe (branch (branch (leaf 3) (leaf 2)) (leaf 1))
+
+-- Section 6.4
+
+
+-- Page 20 Sections 7, 7.1, 7.2, 7.3
+
+-- Section 7 Typing Pitfalls
+
+-- Section 7.1 Let-Bound Polymorphism
+
+module Test(e2) where
+
+-- f g = (g 'a',g []) -- This won't typecheck.
+
+-- Section 7.2 Overloaded Numerals
+
+-- Overloaded numerics were covered previously - here is one more example.
+-- sum is a prelude function which sums the elements of a list.
+
+average :: (Fractional a) => [a] -> a
+average xs = sum xs / fromIntegral (length xs)
+
+e1 :: Float -- Note that e1 would default to Double instead of Int -
+ -- this is due to the Fractional context.
+e1 = average [1,2,3]
+
+-- Section 7.3 The Monomorphism Restriction
+
+-- The monomorphism restriction is usually encountered when functions
+-- are defined without parameters. If you remove the signature for sum'
+-- the monomorphism restriction will apply.
+-- This will generate an error if either:
+-- sum' is added to the module export list at the start of this section
+-- both sumInt and sumFloat remain in the program.
+-- If sum' is not exported and all uses of sum' have the same overloading,
+-- there is no type error.
+
+sum' :: (Num a) => [a] -> a
+sum' = foldl (+) 0 -- foldl reduces a list with a binary function
+ -- 0 is the initial value.
+
+sumInt :: Int
+sumInt = sum' [1,2,3]
+
+sumFloat :: Float
+sumFloat = sum' [1,2,3]
+
+-- If you use overloaded constants you also may encounter monomorphism:
+
+x :: Num a => a
+x = 1 -- The type of x is Num a => a
+y :: Int
+y = x -- Uses x as an Int
+z :: Integer
+z = x -- Uses x as an Integer. A monomorphism will occur of the
+ -- signature for x is removed.
+ -- comments to see an error.
+
+-- Finally, if a value is exported it must not be overloaded unless bound
+-- by a function binding. e2 is the only value exported.
+
+e2 :: Int -- Remove this to get an error. Without this line e1 will
+ -- be overloaded.
+e2 = 1
+
+-- To prevent annoying error messages about exported monomorphic variables,
+-- most modules in this tutorial do not implicitly export everything - they
+-- only export a single value, Bool, which was chosen to keep the export
+-- list non-empty (a syntactic restriction!). In Haskell systems without
+-- the evaluator used here, a module which does not export any names would
+-- be useless.
+
+-- module Test where -- this would export everything in the module
+-- module Test(Bool) -- exports only Bool
+-- module Test() -- this is what we really want to do but is not valid.
+
+-- Page 21 Sections 8, 8.1
+
+module Test(Bool) where
+
+-- Section 8 Input/Output
+-- Section 8.1 Introduction to Continuations
+
+-- Simplify f here to be 1/x.
+
+data Maybe a = Ok a | Oops String deriving Text
+
+f :: Float -> Maybe Float
+f x = if x == 0 then Oops "Divide by 0" else Ok (1/x)
+
+-- g is a `safe' call to x. The call to error could be replaced by
+-- some explicit value like Oops msg -> 0.
+
+g x = case f x of
+ Ok y -> y
+ Oops msg -> error msg
+
+e1 = f 0
+e2 = g 0
+e3 = g 1
+
+-- Here is the same example using continuations:
+
+f' :: Float -> (String -> Float) -> Float
+f' x c = if x == 0 then c "Divide by 0"
+ else 1/x
+
+g' x = f' x error -- calls error on divide by 0
+g'' x = f' x (\s -> 0) -- returns 0 on divide by 0
+
+e4 = g' 0
+e5 = g'' 0
+
+-- Page 22 Sections 8.2, 8.3
+
+module Test where
+
+-- Section 8.2 Continuation Based I/O
+
+-- We will skip the program fragments at the start of this section and
+-- move directly to the writeFile / readFile example.
+
+-- Before we can use Haskell I/O, we need to introduce a new Emacs command:
+-- C-c r. This command runs a dialogue instead of printing a value.
+-- (Actually C-c e creates a dialogue on the fly and runs it in the same
+-- manner as C-c r). As with C-c e you are prompted for an expression.
+-- In this case, the expression must be of type Dialogue and it is
+-- executed by the I/O system. We use d1,d2,... for dialogues to be
+-- executed by C-c r.
+
+-- We make the file name a parameter to allow for easier testing.
+-- Don't expect much error handling in exit.
+
+s1 = "This is a test of Haskell"
+
+main file = writeFile file s1 exit (
+ readFile file exit (\s2 ->
+ appendChan stdout (if s1==s2 then "contents match"
+ else "something intervened!") exit
+ done))
+
+d1,d2 :: Dialogue
+d1 = main "/tmp/ReadMe"
+d2 = main "/dev/null" -- this will read back as the empty string
+
+-- A simple IO program using $ for readability: ($ is defined in the Prelude)
+
+d3 = appendChan "stdout" "Type something: " exit $
+ readChan "stdin" exit $ \s2 ->
+ appendChan "stdout" ("You typed " ++ head (lines s2)) exit $
+ done
+
+-- This program suffers from a strictness problem. Strictness deals
+-- with when things get evaluated. In this program, the input is not
+-- needed until after the "You typed " is printed. Fixing this would
+-- require some operation to look at the string before the final
+-- appendChan. Here is one possible fix:
+
+d4 = appendChan "stdout" "Type something: " exit $
+ readChan "stdin" exit $ \s2 ->
+ let str = head (lines s2) in
+ if str == str then -- This evaluates str
+ appendChan "stdout" ("You typed " ++ head (lines s2)) exit $
+ done
+ else done
+
+
+-- Section 8.3 Terminal I/O
+
+-- Since this programming environment runs under Emacs, the issue of
+-- echoing does not really apply. However, the synchronization between
+-- input and output can be seen in the following example. Since the input
+-- comes a line at a time, the X's come in groups between input lines.
+-- The cursor will move into the haskell dialogue buffer when the program
+-- requests input. Use a ^D to stop the program (^Q^D actually). [Warning:
+-- some brain damaged lisps stop not only the Haskell program but also
+-- the entire compiler on ^D]
+
+d5 = readChan stdin exit processInput where
+ processInput s = loop 1 s
+ loop n [] = done
+ loop n (x:xs) | n == 10 = appendChan stdout "X" exit (loop 1 xs)
+ | True = loop (n+1) xs
+
+-- For more examples using the I/O system look in the demo programs
+-- that come with haskell (in $HASKELL/progs/demo) and the report.
+
+-- Page 23 Sections 9, 9.1, 9.2
+
+module Test(Bool) where
+
+-- Section 9 Arrays
+-- Section 9.1 Index Types
+
+-- Arrays are built on the class Ix. Here are some quick examples of Ix:
+
+e1 :: [Int]
+e1 = range (0,4)
+e2 :: Int
+e2 = index (0,4) 2
+low,high :: (Int,Int)
+low = (1,1)
+high = (3,4)
+e3 = range (low,high)
+e4 = index (low,high) (3,2)
+e5 = inRange (low,high) (4,3)
+
+-- Section 9.2 Array Creation
+
+squares :: Array Int Int
+squares = array (1,100) [i := i*i | i <- [1..100]]
+
+-- We can also parameterize this a little:
+
+squares' :: Int -> Array Int Int
+squares' n = array (1,n) [i := i*i | i <- [1..n]]
+
+e6 :: Int
+e6 = squares!6
+e7 :: (Int,Int)
+e7 = bounds squares
+e8 :: Array Int Int
+e8 = squares' 10
+
+-- Here is a function which corresponds to `take' for lists. It takes
+-- an arbitrary slice out of an array.
+
+atake :: (Ix a) => Array a b -> (a,a) -> Array a b
+atake a (l,u) | inRange (bounds a) l && inRange (bounds a) u =
+ array (l,u) [i := a!i | i <- range (l,u)]
+ | otherwise = error "Subarray out of range"
+
+e9 = atake squares (4,8)
+
+mkArray :: Ix a => (a -> b) -> (a,a) -> Array a b
+mkArray f bnds = array bnds [i := f i | i <- range bnds]
+
+e10 :: Array Int Int
+e10 = mkArray (\i -> i*i) (1,10)
+
+fibs :: Int -> Array Int Int
+fibs n = a where
+ a = array (0,n) ([0 := 1, 1 := 1] ++
+ [i := a!(i-1) + a!(i-2) | i <- [2..n]])
+
+e11 = atake (fibs 50) (3,10)
+
+wavefront :: Int -> Array (Int,Int) Int
+wavefront n = a where
+ a = array ((1,1),(n,n))
+ ([(1,j) := 1 | j <- [1..n]] ++
+ [(i,1) := 1 | i <- [2..n]] ++
+ [(i,j) := a!(i,j-1) + a!(i-1,j-1) + a!(i-1,j)
+ | i <- [2..n], j <- [2..n]])
+
+wave = wavefront 20
+e12 = atake wave ((1,1),(3,3))
+e13 = atake wave ((3,3),(5,5))
+
+-- Here are some errors in array operations:
+
+e14 :: Int
+e14 = wave ! (0,0) -- Out of bounds
+arr1 :: Array Int Int
+arr1 = array (1,10) [1 := 1] -- No value provided for 2..10
+e15,e16 :: Int
+e15 = arr1 ! 1 -- works OK
+e16 = arr1 ! 2 -- undefined by array
+
+-- Page 24 Sections 9.3, 9.4
+
+module Test(Bool) where
+
+-- Section 9.3 Accumulation
+
+hist :: (Ix a, Integral b) => (a,a) -> [a] -> Array a b
+hist bnds is = accumArray (+) 0 bnds [i := 1 | i <- is, inRange bnds i]
+
+e1 :: Array Char Int
+e1 = hist ('a','z') "This counts the frequencies of each lowercase letter"
+
+decades :: (RealFrac a) => a -> a -> [a] -> Array Int Int
+decades a b = hist (0,9) . map decade
+ where
+ decade x = floor ((x-a) * s)
+ s = 10 / (b - a)
+
+test1 :: [Float]
+test1 = map sin [0..100] -- take the sine of the 0 - 100
+e2 = decades 0 1 test1
+
+-- Section 9.4 Incremental Updates
+
+swapRows :: (Ix a, Ix b, Enum b) => a -> a -> Array (a,b) c -> Array (a,b) c
+swapRows i i' a = a // ([(i,j) := a!(i',j) | j <- [jLo..jHi]] ++
+ [(i',j) := a!(i,j) | j <- [jLo..jHi]])
+ where ((iLo,jLo),(iHi,jHi)) = bounds a
+
+arr1 :: Array (Int,Int) (Int,Int)
+arr1 = array ((1,1),(5,5)) [(i,j) := (i,j) | (i,j) <- range ((1,1),(5,5))]
+
+e3 = swapRows 2 3 arr1
+
+-- Printing the arrays in more readable form makes the results easier
+-- to view.
+
+-- This is a printer for 2d arrays
+
+aprint a width = shows (bounds a) . showChar '\n' . showRows lx ly where
+ showRows r c | r > ux = showChar '\n'
+ showRows r c | c > uy = showChar '\n' . showRows (r+1) ly
+ showRows r c = showElt (a!(r,c)) . showRows r (c+1)
+ showElt e = showString (take width (show e ++ repeat ' ')) . showChar ' '
+ ((lx,ly),(ux,uy)) = bounds a
+
+showArray a w = appendChan stdout (aprint a w "") abort done
+
+d1 = showArray e3 6
+
+swapRows' :: (Ix a, Ix b, Enum b) => a -> a -> Array (a,b) c -> Array (a,b) c
+swapRows' i i' a = a // [assoc | j <- [jLo..jHi],
+ assoc <- [(i,j) := a!(i',j),
+ (i',j) := a!(i,j)]]
+ where ((iLo,jLo),(iHi,jHi)) = bounds a
+
+d2 = showArray (swapRows' 1 5 arr1) 6
+
+-- Page 25 Section 9.5
+
+module Test(Bool) where
+
+-- Section 9.5 An example: Matrix Multiplication
+
+aprint a width = shows (bounds a) . showChar '\n' . showRows lx ly where
+ showRows r c | r > ux = showChar '\n'
+ showRows r c | c > uy = showChar '\n' . showRows (r+1) ly
+ showRows r c = showElt (a!(r,c)) . showRows r (c+1)
+ showElt e = showString (take width (show e ++ repeat ' ')) . showChar ' '
+ ((lx,ly),(ux,uy)) = bounds a
+
+showArray a w = appendChan stdout (aprint a w "") abort done
+
+matMult :: (Ix a, Ix b, Ix c, Num d) =>
+ Array (a,b) d -> Array (b,c) d -> Array (a,c) d
+matMult x y =
+ array resultBounds
+ [(i,j) := sum [x!(i,k) * y!(k,j) | k <- range (lj,uj)]
+ | i <- range (li,ui),
+ j <- range (lj',uj')]
+ where
+ ((li,lj),(ui,uj)) = bounds x
+ ((li',lj'),(ui',uj')) = bounds y
+ resultBounds
+ | (lj,uj)==(li',ui') = ((li,lj'),(ui,uj'))
+ | otherwise = error "matMult: incompatible bounds"
+
+mat1,mat2,mat3,mat4 :: Array (Int,Int) Int
+mat1 = array ((0,0),(1,1)) [(0,0) := 1,(0,1) := 0,(1,0) := 0,(1,1) := 1]
+mat2 = array ((0,0),(1,1)) [(0,0) := 1,(0,1) := 1,(1,0) := 1,(1,1) := 1]
+mat3 = array ((0,0),(1,1)) [(0,0) := 1,(0,1) := 2,(1,0) := 3,(1,1) := 4]
+mat4 = array ((0,0),(1,2)) [(0,0) := 1,(0,1) := 2,(0,2) := 3,
+ (1,0) := 4,(1,1) := 5,(1,2) := 6]
+
+d1 = showArray (matMult mat1 mat2) 4
+d2 = showArray (matMult mat2 mat3) 4
+d3 = showArray (matMult mat1 mat4) 4
+d4 = showArray (matMult mat4 mat1) 4
+
+matMult' :: (Ix a, Ix b, Ix c, Num d) =>
+ Array (a,b) d -> Array (b,c) d -> Array (a,c) d
+matMult' x y =
+ accumArray (+) 0 ((li,lj'),(ui,uj'))
+ [(i,j) := x!(i,k) * y!(k,j)
+ | i <- range (li,ui),
+ j <- range (lj',uj'),
+ k <- range (lj,uj)]
+
+ where
+ ((li,lj),(ui,uj)) = bounds x
+ ((li',lj'),(ui',uj')) = bounds y
+ resultBounds
+ | (lj,uj)==(li',ui') = ((li,lj'),(ui,uj'))
+ | otherwise = error "matMult: incompatible bounds"
+
+d5 = showArray (matMult mat1 mat2) 4
+d6 = showArray (matMult mat2 mat3) 4
+
+genMatMul :: (Ix a, Ix b, Ix c) =>
+ ([f] -> g) -> (d -> e -> f) ->
+ Array (a,b) d -> Array (b,c) e -> Array (a,c) g
+genMatMul f g x y =
+ array ((li,lj'),(ui,uj'))
+ [(i,j) := f [(x!(i,k)) `g` (y!(k,j)) | k <- range (lj,uj)]
+ | i <- range (li,ui),
+ j <- range (lj',uj')]
+ where
+ ((li,lj),(ui,uj)) = bounds x
+ ((li',lj'),(ui',uj')) = bounds y
+ resultBounds
+ | (lj,uj)==(li',ui') = ((li,lj'),(ui,uj'))
+ | otherwise = error "matMult: incompatible bounds"
+
+d7 = showArray (genMatMul maximum (-) mat2 mat1) 4
+d8 = showArray (genMatMul and (==) mat1 mat2) 6
+d9 = showArray (genMatMul and (==) mat1 mat1) 6
+
+-- Page 26 More about Haskell
+
+This is the end of the tutorial. If you wish to see more examples of
+Haskell programming, Yale Haskell comes with a set of demo programs.
+These can be found in $HASKELL/progs/demo. Once you have mastered the
+tutorial, both the report and the user manual for Yale Haskell should
+be understandable. Many examples of Haskell programming can be found in
+the Prelude. The directory $HASKELL/progs/prelude contains the sources
+for the Prelude.
+
+We appreciate any comments you have on this tutorial. Send any comments
+to haskell-requests@cs.yale.edu.
+
+ The Yale Haskell Group