TEACH GSTART Aaron Sloman, Oct 1996 (Based on a suggestion from Sophia Langley) Updated 17 Oct 2011 Getting started with Pop-11 via graphical programming, using procedures from LIB RC_GRAPHIC, especially: rc_start(); rc_draw(number); rc_turn(number); rc_jumpto(x, y); rc_drawto(x, y); These form a powerful collection of primitives for making pictures composed of lines. They provide a rapid introduction to a collection of facilities in Pop-11, including procedure definitions, looping constructs, interactive programs, and list processing. This file was designed for use in the Poplog editor Ved/XVed but the contents can be used in any text editor. CONTENTS - (Use g to access required sections) -- Prerequisites -- What you will learn -- The procedures you will create -- Starting up, using the rc_graphic saved image -- Put your graphical procedures in a special file -- Put a definition of procedure rc_square into your file -- Defining square_picture -- Experimenting with square_picture -- Defining rc_polygon -- Defining locate_poly -- Joining up a list of points. -- Defining procedure rc_joinpoints -- Defining rc_get_draw: interactive drawing -- Defining rc_drawpicture -- Extending rc_get_draw -- Further information -- Prerequisites ------------------------------------------------------ Before working through this it is a good idea to have become familiar with VED. Reading TEACH VEDPOP would help. You'll need to know, in advance, how to mark a range, how to copy marked ranges from one file to another. -- What you will learn ------------------------------------------------ This file gives an introduction to Pop-11 via simple graphical programming, using the RC_GRAPHIC package ("RC" stands for "relative coordinates"). The material below will introduce the following. o You will learn how to create a program file called 'graphic.p' which contains definitions of Pop-11 procedures (in this case procedures for drawing simple pictures), along with "commented out" test instructions for those procedures, and additional comments describing the procedures. o You will learn to use the editor to switch between three files: o your program file 'graphic.p' o the output file 'output.p' in which non-graphical output appears o this TEACH file. o You will gain some experience of Pop-11 syntax, including procedure definitions, loops, conditionals, declaration of local variables. o You will learn some of the basics of list processing in Pop-11 (but not very much.) o You will meet the Pop-11 pattern matcher o You will learn a subset of the Pop-11 graphical facilities for use with the X window system. o You will get an introduction to interactive programming using the procedure readline. Most of the relevant features of Pop-11 are summarised in the online summary file TEACH POPCORE (also available in printed form), and in text books on Pop-11, as well as TEACH PRIMER, which is available in printed form from the school library, either for purchase or on loan. -- The procedures you will create ------------------------------------- Initially you will define the following procedures rc_square(side); Draw a square whose side is of the given length. square_picture(size1, size2); Draw a picture made of several squares in different orientations, of two different sizes. rc_polygon(len, num); Draw a regular polygin with side len, with num sides. locate_poly(xloc, yloc, startorient, len, num); Draw a polygon in a specified location with a specified orientation. rc_get_draw(); Define a procedure that reads in coordinates from the user, and draws lines joining up those points. -- Starting up -------------------------------------------------------- This section is relevant if you are reading this file in a printed format. If you are reading it in VED you should already have been through the steps described in this section. The basic pop11 command now starts up a version of poplog that includes the rc_graphic library, used below. E.g. you may need to type poplog pop11 or pop11 depending on your local setup. Then when you get the Pop11 prompt ":" give the command teach gstart to get this teach file into VED. (A slightly older version of this file is included in the Poplog Package. The differences do not affect the main content.) -- Put your graphical procedures in a special file -------------------- Create a file called graphic.p (As explained in TEACH VEDPOP). Put some comments between the comment brackets "/*" and "*/" at the top of the file, saying what the file is about. E.g. something like this ----------------------------------------------------------------------- /* File: graphic.p Author: Eve G. Eden Purpose: This file contains definitions of some simple Pop-11 procedures for use with the library package RC_GRAPHIC. It also contains some test commands between comment brackets so that they are not automatically obeyed every time the file is compiled. */ ----------------------------------------------------------------------- In your file also put the following Pop-11 commands, after the comment. ----------------------------------------------------------------------- uses rc_graphic ;;; This will load RC_GRAPHIC only if necessary false -> popradians; ;;; Make sure angles are measured in degrees ;;; Not radians ----------------------------------------------------------------------- Note that the bits following ";;;" are ignored by Pop-11. They are "end of line" comments. -- Put a definition of procedure rc_square into your file ------------- After the previous commands insert the following procedure definition into your graphic.p file. When the procedure is run it will draw a square of a given side, using the library procedures rc_draw (which takes a number representing a length) rc_turn (which takes a number representing an angle, in degrees) ----------------------------------------------------------------------- define rc_square(side); ;;; lvars side; repeat 4 times rc_draw(side); rc_turn(90); endrepeat enddefine; ----------------------------------------------------------------------- Then load (compile) that procedure as follows. 1. Put VED the cursor somewhere inside it 2. do: ENTER lcp RETURN There are two shortcut alternatives to load a procedure: o Put the VED cursor in the procedure and type or ESC c o Use the CompileProc option on the Compiling menu (If you use VED's menus.) If you get an error message when you compile the procedure that means you have made some sort of "syntactic" mistake. If you correct it just repeat the load command. Then create some test commands between comment brackets in your graphic.p file. ----------------------------------------------------------------------- /* ;;; start or clear the graphic window rc_start(); ;;; draw two squares rc_square(50); rc_square(100); ;;; do the same at a different part of the picture rc_jumpto(-150, -150); rc_square(50); rc_square(100); ;;; Do the same after rotating through an angle of 45 degrees rc_turn(45); rc_square(50); rc_square(100); ;;; Do the last three commands again several times more */ ----------------------------------------------------------------------- After putting all those test commands into your graphic.p file, run each test in turn, as follows (to run the "loadline" VED command) 1. Put the VED cursor on the line of the command 2: do ESC d An alternative to step 2 is to use the "CompileLine" menu option. You can try varying the commands in the previous test examples, and then redo them. E.g. try changing the numbers, and see what happens. Note: it is not necessary to define the procedure with a name beginning "rc_". However by using the convention that all your graphical programs use identifiers that start with a certain prefix you reduce the risk that later on you will want to use the same name for another procedure, and then discover a clash of names. -- Defining square_picture -------------------------------------------- If you wish to define a procedure to create a picture made of two sizes of squares drawn at 8 orientations you can do the following. Put this procedure at the end of your graphic.p file, followed by some test commands in comment brackets. ----------------------------------------------------------------------- define square_picture(size1, size2); ;;; Draw a picture made of 8 big squares and 8 small squares ;;; at 8 different orientations lvars size1, size2; repeat 8 times rc_square(size1); rc_square(size2); rc_turn(45); endrepeat enddefine; /* ;;; Tests for the above procedure rc_start(); ;;; clear the picture square_picture(150, 50); square_picture(100, 25); ;;; clear and start again rc_start(); ;;; clear the picture square_picture(150, 50); ;;; Now turn left 22.5 degrees, and repeat rc_turn(22.5); square_picture(150, 50); */ ----------------------------------------------------------------------- -- Experimenting with square_picture ---------------------------------- You might like to try extending that last example with a turn of 11.25 degrees, and see what the result looks like. You could also try different sizes for the big and small squares, e.g. something like this ----------------------------------------------------------------------- /* rc_start(); vars big, small; for big, small in [160 120 80 40], [75 55 35 15] do square_picture(big, small); rc_turn(45) endfor; */ ----------------------------------------------------------------------- In order to run that test you can mark and load the whole thing. First mark from the "vars" line to the "endfor" line. Then to load (compile) the marked range do ENTER lmr RETURN or, choose the "CompileRange" button from the "Compiling" menu. It's probably a good idea to clear the graphic window first. Try it again with different numbers in the lists and see if you can work out what's going on. The bit between for and endfor is a loop. The two variables, big and small, take successive values from the list, one from each list. Thus initially their values are 160 and 75, then 120 and 55, and so on. -- Defining rc_polygon ------------------------------------------------ Now define a procedure to draw a polygon of side len, and with num sides as follows and put it into your file graphic.p For the picture to "close up" you have to turn through an angle after each side, where the angle must be chosen so that after num turns it gets back to the original orientation, i.e. the total rotation after num turns is 360 degrees. So in each turn the rotation is 360/num ----------------------------------------------------------------------- define rc_polygon(len, num); ;;; lvars len, num; ;;; work out the external angle to turn after drawing each side lvars ang = 360/num; repeat num times .... you fill in this bit using rc_turn and rc_draw ..... endrepeat enddefine; /* rc_start(); rc_polygon(100,4); rc_polygon(100, 5); rc_polygon(35, 15); */ ----------------------------------------------------------------------- Add some additional tests, and make sure that your procedure does what you expect. HINT: If you had trouble completing the definition of rc_polygon, all that was needed to replace the line with dots was these two lines. rc_draw(len); rc_turn(ang); If you could not make it work, try inserting those two, then compile and test the procedure. -- Defining locate_poly ----------------------------------------------- Now try to extend that to start drawing a polygon in a given location and at a given orientation. ----------------------------------------------------------------------- define locate_poly(xloc, yloc, startorient, len, num); ;;; Draw a polygon at position with coordinates xloc, yloc, ;;; where each side is if size len, and there are num sides, ;;; and the first side is drawn at an angle of startorient with ;;; the horizontal. lvars xloc, yloc, startorient, len, num; rc_jumpto(xloc, yloc); startorient -> rc_heading; ;;; set the initial heading .... use rc_polygon to complete the definition.... enddefine; ----------------------------------------------------------------------- All you have to do to complete the definition is replace the line with dots. Use the procedure defined previously. Add some tests between comment brackets, such as locate_poly(-100, 0, 270, 100, 4); and others with different numbers. HINT: If you had trouble completing that procedure, replace the line with dots with the following: rc_polygon(len, num) -- Joining up a list of points. --------------------------------------- In the example using the for ... endfor loop above we used two lists of numbers, one for the succession of big square sizes and one for the succession of small square sizes. If we wanted to draw lines joining up a list of points given by their x and y coordinates it would be useful to be able to keep the x and y coordinates together, instead of having them in separate lists. We could then define a picture by a list of points represented by a list of two-element lists of coordinates, such as [ [0 0] [10 0] [10 20] [-20 20] [-20 -40] [40 -40] ] We could then use something like the following format for point in list_of_points do endfor The procedure rc_drawto nearly does what we want. Try the following commands in turn: rc_start(); rc_jumpto(0, 0); rc_drawto(10, 0); rc_drawto(10, 20); rc_drawto(-20, 20); rc_drawto(-20, -40); rc_drawto(40, -40); If you try to apply rc_jumpto or rc_drawto to a list of two numbers you will get an error (or "mishap" in Pop-11). Try it rc_drawto([40 40]); The following will appear in your output.p file. ;;; MISHAP - NUMBER(S) NEEDED ;;; INVOLVING: [] -1 ;;; DOING : mishap * rc_transxyout rc_drawline rc_drawto ..... Don't worry about where the empty list and the -1 come from. It's a long story. What the "DOING" line tells you is that rc_drawto gave some information to rc_drawline and that gave some information to rc_transxyout, and that tried to do a multiplication (i.e. the asterisk) and that found that it did not have two numbers to multiply. (Arguably, the procedure rc_drawto should have checked that it had the right format before calling rc_drawline. The reason it does not check is that it can handle Pop-11 objects called "pairs" and lists are made of pairs. But the full story is complicated and will not be given here.) Anyhow, if we can get the numbers out of the list before giving them to rc_drawto then all should be well. Fortunately Pop-11 has a procedure called explode. Try loadline on this explode([1 2 3 4]) => it should print the following in the output.p file ** 1 2 3 4 What this means is that the explode command produce a multiple result consisting of the four numbers, and the Pop-11 print arrow "=>" printed them all out. The numbers were left on the Pop-11 "stack", and "=>" prints out everything on the stack. Equally a procedure that requires two numbers can get them from the stack. For example: explode([40 40]); ;;; put the elements of the list on the stack rc_drawto(); ;;; given no inputs, so take two numbers from ;;; the stack. If you do those two commands separately in VED the items on the stack will be cleared after the first command. We can combine them thus: rc_drawto( explode( [40 40] ) ); rc_drawto( explode( [-40 40] ) ); rc_drawto( explode( [-40 -60] ) ); Try each of those commands. Now try the following: vars pointlist = [[0 0] [10 0] [10 20] [-20 20] [-20 -40] [40 -40]]; That declares the global variable pointlist, and initialises it with a list of lists as values. You can print out the value thus: pointlist => That should print out in the output.p file as ** [[0 0] [10 0] [10 20] [-20 20] [-20 -40] [40 -40]] Now try marking and loading the following: rc_start(); vars point; for point in pointlist do rc_drawto( explode(point) ); endfor; There is a slight problem remaining. The first point in the list given above was the centre of the window, namely the point [0 0]. That also happens to be the location at which the drawing will start after the window is cleared by rc_start(); If you had a pointlist that started from some other location the initial call of rc_drawto would draw a line from point 0,0 to that other location. Ideally we want that not to happen. So we need to get the graphic program JUMP to the first point, then DRAWTO all of the remaining points. You can get the first element of a list using the Pop-11 procedure called "hd" for "head", and get a list of all the remaining elements by using the Pop-11 procedure called "tl" for "tail". Try using them as follows: rc_start(); vars pointlist = [[-10 0] [0 0] [0 10] [10 10] [10 20] [20 20] [20 30] [30 30]]; vars point; rc_jumpto(explode(hd(pointlist))); ;;; jump to first location ;;; now draw to all the others in tl(pointlist) for point in tl(pointlist) do rc_drawto( explode(point) ); endfor; -- Defining procedure rc_joinpoints ----------------------------------- You now have all the information required to define a procedure with the following features 1. It is to be called rc_joinpoints 2. It takes one input, called points, which is a list of two-element lists representing points by their coordinates, 3. It uses rc_jumpto to jump to the first point, 4. It uses rc_drawto to draw to all the rest (using explode) Define such a procedure in your graphic.p file. Test it with a list of points making up a square with a triangular "roof". -- Defining rc_get_draw: interactive drawing -------------------------- If you want to create a procedure that reads in sets of points from the user and then draws them, try something like the following, using the readline procedure to get the information from the user: define rc_get_draw(); lvars firstpoint, next; lvars xloc, yloc; ;;; pattern variables used below repeat 'Please type in the starting point' => readline() -> firstpoint; if firstpoint matches ! [?xloc ?yloc] then rc_jumpto(xloc, yloc); quitloop(); else ;;; format wrong, try again 'Wrong format, please type in two numbers' => endif; endrepeat; ;;; now repeatedly get remaining points, till user types "bye" repeat 'Type "bye" to quit, or "close" to close figure and quit' => 'or type two numbers' => readline() -> next; if next = [bye] then 'finished' => quitloop(); elseif next = [close] then rc_drawto(explode(firstpoint)); 'picture closed up now' => quitloop(); endif; until next matches ! [?xloc ?yloc] do 'Wrong format. Please just two numbers, or "bye" or "close"' => readline() -> next; enduntil; rc_drawto(xloc, yloc); endrepeat; enddefine; Note: the "!" after "matches" is an operator that transforms patterns containing "?" or "??" so that the variables in such patterns are common with lvars in the procedure. Otherwas they would have to be declared as "vars". (See HELP LVARS). Now test it /* rc_start(); rc_get_draw(); */ -- Defining rc_drawpicture -------------------------------------------- Define a procedure called rc_drawpicture that takes a list of lists of lists, and for each of the lists of lists uses rc_joinpoints to joinup the points in that list. For example, rc_drawpicture could be applied to the list [ [[10 0] [0 100] [100 100] [10 0]] [[0 10] [100 0] [-100 100] [0 10]] [[-10 0] [0 -100] [-100 -100] [-10 0]] ] To make a picture formed from three connected sub-pictures. -- Extending rc_get_draw ---------------------------------------------- A problem with the interactive procedure rc_get_draw is that it can only draw connected pictures as it goes on joining up points until you type "bye" or "close". Modify the procedure rc_get_draw so that if the user types in "new" the procedure then asks for a new point to start drawing a new sub-picture, and uses rc_jumpto instead of rc_drawto, to get to that point. -- Further information ------------------------------------------------ If you want to find out more about the graphical facilities for drawing pictures see TEACH * RC_GRAPHIC for a tutorial introduction HELP * RC_GRAPHIC for a more compressed summary Overviews of Pop-11 TEACH * POPCORE for a summary of some of the main features of Pop-11 TEACH * PRIMER for a very full overview of Pop-11 (available in printed form) The following files introduce lots more features of Pop-11 TEACH * STACK for a tutorial on the Pop-11 stack HELP * DEFINE for more on the syntax of procedure definitions HELP * IF overview of conditionals in Pop-11 HELP * FOR more on the options available with "for... endfor" HELP * LOOPS more on loops in Pop-11 HELP * CONTROL different control mechanisms in Pop-11 TEACH * LISTS, * ARROW tutorial introduction to list processing TEACH * MATCHES, * MATCHARROW, * MOREMATCH, HELP * MATCHES tutorial introductions to the Pop-11 matcher HELP * OBJECTCLASS, TEACH * OBJECTCLASS_EXAMPLE, * ADVENT_OBJECTCLASS introduction to object oriented programming HELP * LVARS, * VARS, * LEXICAL, * DLOCAL more technical aspects of local and non-local variables and procedure entry and return HELP * POPUPTOOL explains a simple tool for menu-driven interfaces TEACH * VED_MENU, HELP * VED_MENU explains how to extend the VED control panels TEACH * PROPSHEET describes a far more sophisticated interface design tool, with menus, sliders, text fields, etc. (Not easy to use). HELP * DATABASE, TEACH * DATABASE, TEACH * FOREACH, HELP * FOREACH, HELP * FOREVERY, HELP * WHICH Introductions to the Pop-11 database mechanism (based on the matcher) TEACH * RULEBASE Introduces one of several expert system shells in Pop-11 TEACH * EXPERTS Introduces three different shells (mycin, prospector, eshell) TEACH * RECURSE1 * RECURSE2 * RECURSE3 Introduction to recursion of various kinds TEACH * SETS * LISTQUESTIONS * SETS2 Progressive exercises on list processing and set manipulation TEACH * ARITH, * DECIMALS HELP * MATH For mathematical facilities in Pop-11 TEACH * READLINE, * RESPOND Introduction to interactive programs using readline TEACH * SECTIONS For breaking up your program into sections in such a way as to prevent identifier clashes between sections. Other topics available More general introductions to the X interface in Poplog How to simulate or invoke Prolog from Pop-11 How to create and use saved images (with code already compiled) How to link in external procedures (C, Fortran). How to extend the syntax of Pop-11 with new constructs How to interface with the operating system (Unix). File manipulation procedures. How to do discrete event simulation. How to use the Pop-11 "process" mechanism, e.g. to simulate an operating system or other concurrent process How to define new data types (vector classes and record classes0 Various kinds of N-dimensional arrays in Pop-11 Hash-linked tables in Pop-11 (properties) How to program VED or (XVED). How to implement new languages in Pop-11. Parsing procedures. Image processing. --- $poplocal/local/teach/gstart --- Copyright University of Birmingham 2011. All rights reserved. ------