sail tutorial - the stanford university...

58
I i Stanford Artificial Intelligence Laboratory Memo AIM-290 Computer Science Department Report No. STAN-B-760575 SAIL TUTORIAL Length: 19 ft. I Beam: 6 ft. 6 in. HEADBOARD &y / Draft: 4 ft. llY2 in. ;’ Weight: 700 Ibs. minimum /: / - ,;’ .i’ BA-ITEN POCKET <~>hI I . . f . / . . : ~ / ..I . . . MAINSAIL .L %. . . .> ‘--~ MAST - BACKSTAY - . CENTERBOARD TRUNK &‘ it JUMPER STRUTS ! '\ t : i : i b; SPREADER JIBSTAY SHROUDS ,:- CENTERBOARD 4 Research sponsored by National Institutes of Health and Advanced Research Projects Agency ARPA Order No. 2494 October 1976 ,RDS COMPUTER SCIENCE DEPARTMENT Stanford University

Upload: dangduong

Post on 30-Aug-2018

231 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

I

i

Stanford Artificial Intelligence LaboratoryMemo AIM-290

Computer Science DepartmentReport No. STAN-B-760575

SAIL TUTORIAL

Length : 19 f t . IB e a m : 6 f t . 6 i n .

HEADBOARD &y/

D r a f t : 4 f t . llY2 in. ;’

W e i g h t : 7 0 0 Ibs. m i n i m u m/:

/

- ,;’.i’

BA-ITEN POCKET <~>hI

I . .f .

/ . .: ~

/ ..I . . .

MAINSAIL .L%.. .

.>‘--~ MAST -

BACKSTAY - .

CENTERBOARD TRUNK &‘

it JUMPER STRUTS

! '\t :i :i b; SPREADER

JIBSTAY

SHROUDS

,:- CENTERBOARD4

Research sponsored by

National Institutes of Healthand

Advanced Research Projects AgencyARPA Order No. 2494

October 1976

,RDS

COMPUTER SCIENCE DEPARTMENTStanford University

Page 2: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail
Page 3: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

St anford Artificial Intelligence LaboratoryMemo AIM-290

October 1976

Computer Science DepartmentReport No. STAN-G-76-575

. SAIL TUTORIAL

bY

Nanoy W. SmithSUMEX-AIM Computer Project

Department of Genetic6Stanford University Medic&l Center

ABSTRACT

This TUTORIAL is designed for a beginning user of Sail, an ALGOL-like language for thePDP 10. The first part covers the basic statements and expressions of the language; remainingtopics include macros, records, conditional compilation, and input/output. Detailed examples ofSail programming are included throughout, and only a mini,mum of programming background isassumed.

.

This -manual was prepared as part of the SUMEX-AIM computing resoutce supported bythe Biotechdogy Resources Program of the National Institutes of Health under grant RR-00735. Printing and preparation for publication were supported by ARPA under ContractM DA903076-C-0206.

. The views and conclusions contained in this document are those of the author(s) and should not beinterpreted as necessarily representing the oficial policies, either expressed or implied, of Stanford

*University, NIH, ARPA, or the V. S. Government.

Reproduced in the U.S.A. Available from the National Technical Information Service, Springfield,Virginia 2216 1,

Page 4: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail
Page 5: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL TABLE OF CONTENTS

T A B L E O F C O N T E N T S

SECTION PAGE

1 The Load Module2 Source Files3 Macros and Conditional Compilation

45

t;

1 Int reduction 1

APPENDIX A: Sail and ALGOL W Comparison48

REFERENCES 49

2 The ALGOL-Part of Sail 2INDEX 50

1 Blocks 22 Declarations 23 Statements 54 Expressions 105 Scope of Blocks 5 136 More Control Statements 157 Procedures 19

3 Macros 25

4 String Scanning 27

5 Input/Output 30

1, Simple Terminal l/O 302 Notes on Terminal l/O for TENEX Sail Only

303 Setting Up a Channel for I/O 304 Input from a File 375 Output to a File 39,

.

6 Records 40

1 Declaring and Creating Records 402 Accessing Fields of Records 413- Linking Records Together 41

7 Condition al Compilation 44

Page 6: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail
Page 7: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL’ Introduction

SECTION 1

Introduction

The ‘Sail manual [l] is a reference manualcontaining complete information on Sail but maybe difficult for a new user of the language towork with. The purpose of this TUTORIAL * is tointroduce new users to the language. It does notdeal in depth with advanced features like theLEAP portion of Sail; and uses pointers to the

. relevant portions of the manual for somedescriptions. aFollowing the pointers and readingspecific ‘portions of the manual will help you todevelop some familiarity with the manual. Afteryou have gained some Sail programmingexperience, it will be worthwhile to browsethrough the complete reference manual to find avariety of more advanced structures which arenot covered in the TUTORIAL but may be usefulin your particular programming tasks. The Sailmanual also covers use of the BAIL debugger forSail.

The TUTORIAL is not at an appropriate level fora computer novice. The following assumptionsare .made about the background of the reader:

1) Some experience with the PDP-10 including knowledge of an editor,understanding of the file system, andfamiliarity with routine utility programsand system commands. If you are a newuser or have previous experience onlyon a non-timesharing system, you shouldread the TENEX EXEC MANUAL [7] (forTENEX systems) or the DEC USERSHANDBOOK [6] (for standard TOPS-10systems) or the MONITOR MANUAL [3]and UUO MANUAL [2] (for Stanford AlLab users). In addition, you might wantto glance through and keep ready forreference: the TENEX JSYS MANUAL [8Jand/or the DEC ASSEMBLY LANGUAGEHANDBOOK [5J. Also, each POP-10system usually has its own introductorymateriel for new users describing theoperation _of the system.

2) Some experience with aprogramming language--probablyFORTRAN, ALGOL or an assembly

language. If you have no programmingexperience, you may need help gettingstarted even with this TUTORIAL. Sail is

’ based on ALGOL SO the general conceptsand most of the actual statements are thesame in what is often called the “ALGOLpart” of Sail. The major additions to Sailare its input/output routines. AppendixA contains a list of the differencesbetween the ALGOL W syntax and Sail.

Programs written in standard Sail (which willhenceforth be called TOPS-10 Sail) will usuallyrun on a TENEX system through the emulator(PA10501 which simulates the TOPS-10 UUO’s,but such use is quite inefficient. Sail also has aversion for TENEX systems which we refer to asTENEX Sail. (The new TOPS-20 system is verysimilar to TENEX; either TENEX Sail or a new Sailversion should be running on TOPS-20 shortly.)Note that the Sail compiler on your system willbe called simply Sail but will in fact be either theTENEX Sail or TOPS-10 Sail version of thecompiler. Aside from implementation differenceswhich will not be discussed here, the languagedifferences are mainly in the input/output (I/O)routines. And of course the system levelcommands to compile, load, and run a finishedprogram differ slightly in the TENEX and TOPS-10 systems.

* I would like to thank Robert Smith for editingthe final version; and Scott Daniels for hiscontributions to the RECORD section. JohnReiser, Les Earnest, Russ Taylor, Marney Beard,and Mike Hinckley all made valuable suggestions.

1

Page 8: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail SAIL TUTORIAL

S E C T I O N 2 . which will print out on the terminal:

. The ALGOL-Part of Sail . SQUARE ROOT OF 5 IS 2.236668 .

2.1 Blocks 2.2 Declarations

Sail is a block-ttructurod language. Each blockhas the form:

BEGIN

A list of all the kinds of declarations is given inthe Sail manual (Sec. 2.1). In this section we willcover typo doclarrtionr and array declarations.Procedure declarations will be discussed inSection 2.7. Consult the Sail manual fordetails on all of the other varieties ofdeclarations listed.

estatomonts>

.

END

2.2.1 Type De&rat ions

The purpose of type declarations is to tell thecompiler what it needs to know to set up thestorage locations for your data. There are fourdata types available in the ALGOL portion of Sail:

Your enfire program will be a block with theabove format. This program block is a somewhatspecial block called the outor block BEGIN andEND are rosorvod words in Sail that mark thebeginning and end of blocks, with the outermostBEGIN/END pair also marking the beginning andend of your program. (Reserved words arewords that automatically mean something to Sail;they are called “reserved” because you shouldnot try to give them your own meaning.)

Doclrritiom are used to give the compilerinformation about the data structures that *youwill be using so that the compiler can set upstorage locations of the proper types andassociate the desired name with each location. ’

Strtomontr form the bulk of your program. Theyare the actual commands available in Sail to usefor coding the trsk at hand.

. All declarations in each block must precede allstatements in that block Here is a very simpleone-block program that outputs the square root

* of 5:

I BEGINDECLARATIDNS mi> INTEGER ii

REAL x; 5SfAfEftENfS ==> i l 51

x + SPRTti); .PRINT (“SQUCIRE ROOT OF “, i ,

” IS “, IdjEND

I 2

1) INTEGERS are counting numberslike -1, 0, 1, 2, 3, etc. (Note that commascannot be used in numbers, e.g., 15724not 15,724;)

2) REALS are decimal numbers like-1.2, 3.14159, 100087.2, etc.

3) BOOLEANs ‘are ’ assigned thevalues TRUE or FALSE (which arereserved words). These are predefinedfor you in Sail (TRUE - -1 and FALSE =0).

4) STRINGS are a d a t a t ype notfound in all programming languages.Very often what you will be working withare not numbers at all but text. Yourprogram may need to output text to theuser’s terminal while he/she is runningthe program. It may ask the userquestions and input text which is theanswer to the question. It may in factprocess whole files of text. One simpleexample of this is a program which workswith a file containing a list of words andoutputs to a new file the same list ofwords in alphabetical order. It ispossible to do these things in languageswith only the integer and real data typesbut very clumsy. Text has certainpropert ies di f ferent f rom those ofnumbers. For example, it is very useful

Page 9: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL The ALGOL-Part of Sail

to be able to point to certain of thecharacters in the text and work with justthose temporarily or to take one letteroff of the text at a time and process it.Sail has the data type STRING for holding“strings” of text characters. Andassociated with the STRING data type arestring operations that work in a wayanalogous to how the numeric operators(+,-,*, etc.) work with the numeric datatypes. We write the actual stringsenclosed in quotation marks. Any of thecharacters in the ASCII character set canbe used in strings (control characters,letters, numerals, punctuation marks).Some examples of strings are:

“OUTPUT FILE= ”“HELP”*PIoas~ type your namm.”“aardvark’“8123456789”“!““#9X8”“RaBbCcDdEaFf”

“” (thr empty str ing)NULL (also the l pty string)

Upper and lowercase letters are not- equivalent in strings, i.e., “8” is a

different string than “A”. (Note that toput a ” in a string, you use *“, e.g., “quotea ““word”““.)

in your programs, you will have both vrriablosand constants. We have already given someexamples of constants in each of the data types.REAL and INTEGER constants are just numbers asyou usually see them written (2, 618, -4.35, etc.);the BOOLEAN constants are TRUE and FALSE; andSTMNG constants are a sequence .of textcharacters enclosed in double quotes (and NULLfor the empty string).

Variables are used rather than constants whenyou know that a value will be needed in thegiven computation but do not know in advancewhat the exact value will be. For example, youmay want to add 4 numbers, but the numberswill be specified by the user at runtime or takenfrom a data file. Or the numbers may be theresults of pre-vious computations. YOU might becomputing weekly totals and then when you havethe results for each week adding the four weekstogether for a monthly total. So instead of an

expression like 2 + 31 + 25 + 5 you need anexpression like X+Y+Z+WWEEK1 + WEEK2 + WEEK3 + WEEK4. This is dote’by declaring (through a declaration) that you willneed a variable of a certain data type with aspecified name. The compiler will set up astorage location of the proper type and enterthe name and location in its symbol table. Eachtime that you have an intermediate result whichneeds to be stored, you must set up the storagelocation in advance. When we discuss thevarious statements available, you will see howvalues are input from the user or from a file orsaved from a computation and stored in theappropriate location. The names for thesevariables are often’ referred to as theiridontifiors. identifiers can be as long (or short)as you want. However, if you will be debuggingwith DDT or using TOPS-10 programs such asthe CREF cross-referencing program, you shouldmake your identifiers unique to the first sixcharacters, i.e., DDT can distinguish LONGSYMBOLfrom LONGNAME but not from LONGSYNONYMbecause the first 6 characters are the same.Identifiers must begin with a letter but followingthat can be made up of any sequence of lettersand numbers. The characters ! and S areconsidered to be letters. Certain reserved wordsand predeclarod identifiers are unavailable foruse as names of your own identifiers. A list ofthese is given in the Sail manual in Appendices Band C.

Typical declarations are:

INTEGER i, j,k;REAL x,y,rjSTRING s, 1;

where these are the letters conventionally usedas identifiers of the various types. There is noreason why you couldn’t have INTEGER XI REAL i Iexcept that other people reading your programmight be confused. In some languages the letterused for the variable automatically tells its type.This is not true in Sail. The type of the vari.ableis established by the declaration. In general,simple one-letter identifiers like these are usedfor simple, straightforward and usuallytemporary purposes such as to count aniteration. (ALGOL W users note that iterationvariables must be declared in Sail.)

Most of the variables in your program will bedeclared and used for a specific purpose and the

Page 10: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The AtGOL-Part of Sail SAIL TUTORIAL

name you specify should reflect the use of thev a r i a b l e .

INTEGER noxtlJord, pagolcount;RERL to ta I, subTota I ;S T R I N G lastname, firlstnamlBOOLEAN p a r t i a l , abortswitch, o u t p u t s w ;

Both upper and lowercase fetters are equivalentin identifiers and so the case as well as the useof ! and 8 can contribute to the readability ofyour programs. Of course, the above examplescontain a mixture of styles; you will want to

choose some style that looks best to you anduse it consistently. The equivalence’ of upperand lowercase also means that

TOTAL I total I Total I tofal I ate.

are all instances of the same identifier. So thatwhile it is desirable to be consistent, forgettingoccasionally doesn’t hurt anything.

Some programmers use uppercase for thestandard words ‘like BEGIN, INTEGER, END, etc.and lowercase for their identifiers. Othersreverse this. Another approach is uppercase foractual program code and lowercase forcomments. It is important to develop some stylewhich you feel makes your programs as easy toread as possible.

Another important element of program clarity isthe format, The Sail compiler is free formatwhich means that blank lines, indentations, extraspaces, etc. are ignored. Your whole programcould be on one line and the compiler wouldn’tknow the difference. (Lines should be less than250 characters if a listing is being made usingthe compiler listing options.) But programsusually have each statement and declaration on aseparate line with all lines of each blockindented the same number of spaces. Someprogrlinmers put BEGIN and END on lines bythemselves and others put them on the closestline of-code. It is very important to format yourprograms so that they are easy to read.

2.2.2 Array Declarations

An array is a data structure designed to let youdeal with a group of variables together. Forexample, if you were accumulating weekly totalsover a period of a year, it would be cumbersometo declare: .

R E A L warkl, wrrk2, work&. . . . . ,uaok52 ;

and then have to work with the 52 variableseach having a separate name. instead you candeclare:

REAL ARRAY weokt Ilr 521 l

The array declaration consists of one of the datatype words (REAL, INTEGER, BOOLEAN, STRING)followed by the word ARRAY followed by theidentifier followed by the dimensions of thearray enclosed in [ J’s. The dimensions give thebounds of the array. The lower bound does notneed to be 1. Another common value for thelower bound is 0, but you may make it anythingyou like. (The LOADER will have difficulties if thelowe’r bound is a number of large positive ornegative magnitude.) YOU may declare more thanone array in the same declaration provided theyare the same type and have the samedimensions. For example, one array might beused for the total employee salary paid in theweek which will be a real number, but you mightalso need to record the total employee hoursworked and the total profit made (one integerand one real value) so you could declare:

INTEGER ARRAY hours IlrS21 jR E A L RRRRY salarlos, p r o f i t s 111521;

These 3 arrays are examples of prrrllol arrays.

it is also possible to have multi-dimensionedarrays. A common example is an array used torepresent a chessboard:

INTEGER ARRAY tihossboard I1:8,1:81;

1,l 1,2 1,3 1,4 1,s 1,6 1,7 1,82,l 2,2 2,3 2,4 2,s 2,6 2,7 2,8

. . . . . . . .l . . . . . . .

. . . . . . . .

. . . l . . l .

8;l 8;2 8;3 8;) 8;s 8;6 817 8;8

4

Page 11: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TlJTORlAL

In fact even the terminology used is the same.Arrays, like matrices and chessboards, have rows(across) and columns (up-and-down). Arrayswhich are statically allocated (all outer block andOWN arrays) may have at most 5 dimensions.Arrays which are allocated dynamically may haveany number of dimensions.

Each element of the array is a separate variableand can be used anywhere that a simple variablecan be used. We refer to the elements by givingthe name of the array followed by the particularcoordinates (called the &scripts) of the givenelement enclosed in [3’s, for example: tmksf341,woks 1271, chessboard 12,s) , and chessboard t&81.

2.3 Statements

All of the statements available in Sail are listedin the Sail manual (Sec. 1.1 with the syntax forthe statements in Sec. 3.1). For now, we willdiscuss the assignment statement, the PRINTstatement, and the IFl..THEN statement which willallow us to give some sample programs.

2.3.1 Assignment St at ement

Assignment statements are used to assign valuesto variables:

var iab lo c oxprrss ion

The variable being assigned to and theexpression whose value. is being assigned to itare separated by the character which is abackwards arrow in 1965 ASCII (and StanfordASCII) and is -an underbar (underlining character)in 1968 ‘ASCII. The assignment statement isoften read as:

vrriablo bocomet l xprossionOR variable is assigned lhr valur of l xprosrionOR vrriablo gets l xprosslon

You may assign values to any of the ,four typesof vaiiables (INTEGER, REAL, BOOLEAN, STRING)or to the individual variables in arrays.

Essentially, an expression is something that has avalue. An expression is not a statement(although we will see later that some of theconstructions -of the language can be eitherstatements or . expressions depending on thecurrent use). It is most important to remember

The ALdOL-Part of Sail

that an expression can be evaluated. It is asymbol or sequence of symbols that whenevaluated produces a value that can be assigned,used in a computation, tested (e.g. for equalitywith another value), etc. An expression may be

a) a constant

b) a ,variable

c) a construction using constants,variables, and the various operators onthem.

Examples of these 3 types of expressions inassignment statements are: *

DON’T FORGET TO DECLARE VRRIABLLS. FIRST!

INTEGER i , j;RERL X,YISTRING s, 1;BOOLEAN is~,~s~,/~s~;I N T E G E R ARRRY wry tlr 1611

a) i c 21 COtltlENT now i = 21

x c 2.4; COtMENT n o u x = 2 . 4 ;s t “abc”l COtlMENT now EQU (8, “abc”) 8Isw e TRUE; COMIENT now i SM I T R U E ;osu l FRLSE j COlltlENT now OSM I F A L S E ;arryt41 c 2 2 ; C O t l t l E N T nocr arryt41 I 22;

b) j&i! COtlflENT nay i I j I 2;

Y + Xl COMlENT nou x I y (C 2 . 4 ;t * 81 COfltlENT nou EPU fs, “abc”)

AND EQU(t,“abc”l;,l rryt81 l ji COIIPIENT i= j=arry 181’21

cl I *j +4j COtlflENT j t 2 FIND i = 65x 6 2y - i; COPMENT ~~2.4 RND ir6

RND x =’ -1.2;rrryt31 c i / j ; COMMENT 116 A N D j=2

RN0 a r r y t31=3;iosw l lsw OR otu; COtltlENT isu I TRUE

RN0 otu = FRLSERND iosu I T R U E ;

NOTEl: Most of the operators for stringsare different than those for the

’ arithmetic variables. The differencebetween = and EQU will be coveredlater.

NOTE2: Logical operators such as ANDand OR are also available forboolean expressions.

5

Page 12: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

. .The ALGOL-Part of Sail

NOTE3: You may Put “comments”anywhere in your program by usingthe word COMMENT followed by thetext of your comment and endedwith a semi-colon (no semi-colonscan appear within the comment).Generally comments are placedbetween declarations or statementsrather than inside of them.

NOTE4: In all our examples, you will seethat the declarations and statementsare separated by semi-colons.

In a later section,’ we will discuss: .l) typeconversion which occurs when the data types ofthe variable and the expression are not thesame, 2) the order of evaluation in theexpression, and 3) many more complicatedexpressions including string expressions (first weneed to know more of the string operators).

2.3.2 PRINT Statement

PRINJ is a relat ively new but very usefulstatement in Sail. lt is used for outputting to theuser’s terminal. You can give it as m a n yarguments as you want and the arguments maybe of any type. PRINT firs1 converts eachargument to a string if necessary and thenoutputs it. Remember that only strings can beprinted anywhere. Numbers are stored

* internally as 36-bit words and when they areoutput in 7-bit bytes for text the results arevery strange. Fortunately PRINT does theconversion to strings for you automatically, e.g.,the number 237 is printed as the string “237”.The format of the PRINT statement is the wordPRINT followed by a list of arguments separatedby commas with the entire list enclosed inparent hoses. Each argument may be anyconstant, variable, or complex expression. Foraxample, if you wanted to output the weeklysalary totals from a previous example and thenumb& of the current week was stored inINTEGER curUoti, you might use:

PRINT(“UEEK “, curhrk,*r Salaries “, sa I l r i OS tcurbhokl 11 .

which for _ curbrk = 28 and the array elementsa I l r lot t 281 = 27543.82 would print Out:

WEEK 281 Salaries 27543.82

SAIL TUTORIAL

NOTE: The printing format for reals(number of leading zeroes printedand places after the decimal point)is discussed in the Sail manual undertype conversions.

2.3.3 Built-in Procedures

Using just the assignment statement, the PRINTstatement, and three built-in procoduros, we canwrite a sample program. Procedures are a veryimportant feature of Sail and you will be writingmany of your own. The details of procedurewriting and use will be covered in Section2.7. Without giving any details now, we willjust say that some procedures to handle verycommon tasks have been written for you and areavailable as built-in procedures. The SQRT,lNCHWL and CVD procedures that we will beusing here are all procedures which returnvalues. Examples are:

I l INCHWL)i l CVDW;x c 2 + SQRTW;

Procedures may have any number of arguments(or none). SQRT and CVS have a single argumentand INCWL has no arguments (but does return avalue). The procedure call is made by writingthe procedure name followed by the argument(s)in parentheses. In the expression in which it isused, the procedure call is equivalent to thevalue that it returns.

SQRT returns the square root of itsargument.

CVD returns the result of converting itsstring’ argument to an integer. Thestring is assumed to contain anumber in decimal representation--CVO converts strings containingoctal numbers, e.g., after executing

i c CVO(“14724”); j c CVO(“14724”);

then the following

i = 14724 AND j = 6612

would be true.

INCHWL returns the next line of typing

6

Page 13: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL The ALGOL-Part of Sail

from the user at the controllingterminal. n u m b e CW (INCHUL);

NOTE: In TENEX-Sail the INTTY procedureis available and SHOULD be used inpreference to the INCH’WL procedurefor inputting lines. This may not bementioned in every example, but isvery important for TENEX users toremember.

and eliminate the declaration of the STRING rap~y.Next we can eliminate ti and take the SORT

directly:

cqroot l SORT WO(INCHUL))~

At first you might think that we could go a stepfurther to

* So, for the statement I) l INCHUL; , the value ofINCHWL wtll be the line typed at the terminal(minus the terminator which iib usually carriagereturn). This value is a string and is assignedhere to the string variable t.

So far we have seen five uses of expressions: asthe right-hand-side of the assignment statement,8s an actual parameter or argument in aprocedure call, as an argument to the PRINTstatement, for giving the bounds in an arraydeclaration (except for arrays declared in theouter block which must have constant bounds),and for the array subscripts for the elements ofarrays. In fact the whole range of kinds ofexpressions can be used in nearly all the placesthat constants and var iables (which qrepa$cular kinds of expressions) can be used.Two exceptions to this that we have alreadyseen are 1) the left-hand-side of the assignmentstatement (you can assign a value to a variable.but not to a constant or a more complicatedexpression) and 2) the array bounds for outer

b l o c k a r r a y s w h i c h coma at a poin t in theprogram before any assignments have beenmade to any of the variables so only constantsmay be used;-ths declarations in the outer blockare before any program statements at all.

PRINT (“FINS: “, SQRT KW (INCHUL 1) 1;

and we could as far as the Sail syntax isconcerned but it would produce a. bug in ourprogram. We would be printing out “ANS: W rightafter “Typo number: a before the user would havetime to even start typing. But we haveconsiderably simplified our program to:

BEGINRERL rqroo t ;PRINT (“Typo numbor: “I;s q r o o t * SORT (CM (INCHUL));

’P R I N T (“(INSI “,sqroot);ENOj

Remember that intermediate results do not needto be stored unless you will need them againlater for something else. By not storing resultsunnecessarily, you save the extra assignmentstatement and the storage space by not needingto declare a variable for temporary storage.

2.3.4 IF...THEN Stat emsnt

In general, any construction that makes sense toyou is probably legal in’ Sail. By using some ofthe more complicated expressions, , you can saveyourself steps in your program. For example,

&INRERL sqroot;INTEGER numb)

S T R I N G .rrply;PRIAf("Typ~ number: "1;roplycINCtiUL;nuubCVD(roply)~sqroo t cSQRf humb) ;PRINT("RNSI ',sqroot)jENOj

The previous example included no errorchecking. There are several fundamentalprogramming tasks that cannot be handled withjust the assignment and PRINT statements suchas 1) conditional tasks like checking the value ofa number (is it negative?) and taking actionaccording to the result of the test and 2) loopingor iterative tasks so that we could go back to .the beginning and ask the user for anothernumber to be. processed. These sorts offunctions are performed by a group of ’statements called control ttatoments. In thissection we will cover the IF..THEN statement forconditionals. More advanced control statementswill be discussed in Section 2.6.

There aie two kinds of IF...THEN statements:

IF booloan rxprrss ion THEN ttatrmant

7

can be shortened by several steps. First, wecan’co’mbine INCHUL with CM):

Page 14: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail SAIL TUTORIAL

* IF booloan sxprrrrion T H E N rtatrnwntELSE rtatrmnt

COtlllENT I=3 AN0 )rZ;ENOi

A boolean expression is an expression whosevalue is either true or false. A wide variety o,fexpressions can effectively be used in thisposition, Any arithmetic expression can be aboolean4 if its value - 0 then it is FILSE. For anyother value, it is T R U E . For now we will justconsider the following three cases:

1) BOOLEAN variables (wherel rrorsu, basa8, a n d riniVorrion aredeclared as BOOLEANs):

IF errorsw THENPRINT(‘Thoro’t beon a n error.“) 4

IF brs.8 THEN dig i ts c “91234567”ELSE digits l “#123456789” 1

IF miniVersion THEN counter + 18ELSE counter, + 1891

2) Expressions with relationaloperators such as EQU, -, <, >, LEQ,NEQ, and GEQ:

. IF x < currentSmatlost THEN ,currontSmallost l xl .

IF divisor NEQ 0 THEN

quotiontcdivldond/divimor;IF i GEQ 0 T H E N i&I ELSE w-1;

3) Complex expressions formedwith the logical operators AND, OR, andNOJ-:

IF NOT l rrorsw THEN

l nsudrrkountrrl c quot lent;IF x<O OR y<o THEN

PRINTt”Wogativo nuubors not l llotmd.“)ELBE z c SORT(xI+SQRT(yI;

In the IF..THEN statement, the boolean expressionis evaluated. If it is true then the statementfollowing the THEN is executed. If the booleanexpression is false and the particular statementhas no ELSE part then nothing is done. If theboolean is false and there is an ELSE part thenthe statement following the ELSE will baexecuted.

BEGIN BOOLERN boo I ; INTEGER I, j ;booleTRllEl icl) J+liI F boo1 T H E N icl+l; COllHENT 112 RN0 jmlrIF bool -THEN ici+l ELSE j*j+ll

boolefalsr;COtBlENT h3 RN0 j=l;

IF bool THEN i+i+l; COtitlENT im3 RN0 j=llIF b o o l T H E N i*i+l ELSE j*)+l;

It is VERY IMPORTANT to note that NO semi-colonappears between the statement and the ELSE.Semi-colons are used a) to separate declarationsfrom each other, b) to separate the finaldeclaration from the first statement in the block,c) to separate statements from each other, andd) to mark the end of a comment, The key pointto note is that semi-colons are used to separateand NOT to terminate. In some cases it doesn’thurt to put a semi-colon where it is not needed.For example, no semi-colon is needed at the endof the program but it doesn’t hurt. However, theformat

IF l xprossion THEN statomont ; ELSE statrmont ;

makes it difficult for the compiler to understandyour code. The first semi-colon marks the endof what could be a legitimate IF...THEN statementand it will be taken as such. Then the compileris faced with

E L S E rtatrmsnt 1

which is meaningless and will produce an errormessage.

The following is a part of a sample programwhich uses several IF,.THEN statements:

BEGIN BOOLEAN wrbororw~ STRING rrplyi

PRINT(“Vorboro mdo? ( T y p o Y o r MI r “Iir e p l y + INCHUL; COllllENT INTTY for TENEX;

IF rsplyr”Y” OR reply-“y” THEN vorbotosu c T R U EELSEIF rrply=“N” OR roplyr”n” THEN vorbososwcFALSE;

IF vorbosotw THEN PRINTS”-long nsg-“1ELSE PRINT (“0shor t mg-“I ;

COilllENT nou a l l o u r messages p r i n t r d o u t t oterminal w i l l bo c o n d i t i o n a l o n vrrbososw;ENO;

There are two interesting points to note aboutthis sample program. First is the use of - ratherthan EQU to check the user’s reply. EQU is usedto check the equality of variables of type STRINGand - is used to check the equality of variablesof type INTEGER or REAL. If we were asking theuser for a full word answer like “yes” or “no”instead of the single character then we wouldneed the EQU to check what the input string was.

8

Page 15: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail

However, in this case where we only have asingle character, we can use the fact thrt when astring (either a string variable or a st r ingconstant) is put someplace in a program wherean integer is expected then Sail automaticallyconverts to the integer which is the ASCII codefor the FIRST character in the string. Forexample, in the environment

S T R I N G s t r ; s t r c “Fl”;

all of the following are true:

“A” I str = 65 = ‘181“ A ” NEQ “a”str NEP “a”str + 1 I “A” + 1 = ‘182 I “8”r t r = “Aardvark”NOT EQU (s tr, “Aardvark “1

(‘101 iS an octal integer constant.) .

When you are dealing with single characterstrings (or are only interested in the firstcharacter of a string) then you can treat themlike integers and use the arithmetic operatorslike the - operator rather than EQU. In general(over 90% of the time), EQU is slower.

A second point to note in the above IF,.THENexample ,is the use of a nostod IF...THEN Thestatements following the THEN and the ELSE maybe any kind of statement including rnotharIF..THEN statement. For example,

IF uppor0nly THEN Isttns * “ABC” .

ELSE IF IouorOnly THEN Isttors l �(lb@�

E L S E I s t t s r s 6 “ABCabc”;

This is a very common construction when youhave, a small list of possibilities to check for.

. (Note: if there are a large number of cases to bechecked use the CASE statement instead.) Thenested IF..THEN.ELSE statements save a lot ofprocessing if used properly. For example,without the nesting this would be:

I . I F umorOnlu T H E N Iottors c “RBC”:I F l&rOnl~ T H E N l e t tot-s + •abc”~IF NOT upperOnly FIN0 NOT lowerOnly THEN

Iottors 6 “RBCabc”l

RegardlesS o f t h e v a l u e s o f upporonly a n dlouoronly, _the -boolean expreselons in the threeIF..THEN statements need to be checked. In thenested version, if upperOnly is TRUE then lowwon lywill never be checked. For greatest efficiency,

- the most likely case should be the first one

tested in a nested IF...THEN statement. If thatlikely case is true, no further testing will bedone.

To avoid ambiguity in parsing the nestedIF..THEN..ELSE construction, the following rule isused: Each ELSE matches up with the lastunmatched THEN So that

IF l xpl THEN IF rxp2 T H E N sl E L S E s2 ;

will group the ELSE with the second THEN whichis equivalent to

IF expl THENBEGIN

IF iwp2 THEN sl ELSE 82;ENOj

and also equivalent to

IF l xpl AND l xp2 THEN sl;IF l xpl RN! NOT sxp2 THEN r2j .

You can change the structure with BEGIN/END to:

IF l xpl THENBEGIN

IF l xp2 THEN ‘81 *END ELSE s2 ; ,

which is equivalent to

IF sxpl AN0 ixp2 THEN sl;IF NOT sxpl THEN s2l

There is another common use of BEGIN/END inIF-THEN statements. All the examples so farhave shown a single simple statement ‘to beexecuted. In fact, you often will have a varietyof tasks to perform based on the conditiontested for. For example, before you make anentry into an array, you may want to check thatyou are within the array bounds and if so thenboth make the entry and increment the pointerso that it will be ready for the next entry:

IF pointor LE9 MX THENBEGIN

datatpointrrl c nowEntry;pointsrcpoint r r 4 1;

EN0E L S E PRINTWkray ORTR i s already f u l l . “ ; ;

Here we see the use of a compound strtomont.Compound statements are exactly, like blocksexcept that they have no declarations. It wouldalso be perfectly acceptable to use a block with ,

~ 9

Page 16: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail SAIL TUTORIAL‘,

declarations where the compound statement isused here. In fact both blocks and compoundstatements ARE statements and can be used ANYplace that a simple statement can be used. All ofthe statements between BEGIN and END areexecuted as a unit (unless one of the statementsitself . causes the flow of execution to bechanged).

COMENT updrtos ptr 8 fi Ils n r x t a r r a yslot in rlnglr stop;

Note that the assignment operator has lowprecedence and SO you will often need to useparenthesizing to get the’ proper order ofevalurtion This ia an area where many codingerrors commonly occur.

2.4 Expressions is parsed like

We have already seen many of the operatorsused in expressions. Sections 4 and 8 of the Sailmanual cover the operators, the’ order of

evaluation of expressions, and type conversions.Appendix. 1 of the manual gives the wordequivalents for the single character operators,e.g., LEQ for the less-than-or-equal-to sign,which are not available except at SU-AI. Youshould read these sections especially for acomplete l is t of the ar i thmet ic and booleanoperators available (the s!ring operators will becovared shortly in this TUTORIAL). A shortdiscussion of type conversion will be given laterin #his section but you should also read thesesections in *the Sail manual for complete detailson type conversions.

IF i*() OR boolo) THEN . . . .

rather than

IF (IQ OR boolo THEN a..,

ThGre are three kinds of expressions that we. have not used yet: assignment, conditional, and

case expressions. These are much like. thestatements of the same names.

See the sections in the Sail manual referencedabove for a more complete discussion of theorder of evaluation in expressions. In general itis the normal order for the arithmetic operators;then the logical operators AND and OR (so thatOR has the Jowest precedence of any operatorexcept the assignment operator); and left to rightorder is used for two operators at the samelevel (but the manual gives examples ofexceptions). You can use parentheses anywhereto specify the order that you want. As anexample of the offoct of left-to-right evaluation,note that

Indoxarc2larry I I ndexorl l (

. 2.4.1 Assignment Expressions

Anywhere that you can have an expression, youmay at the same time make an assignment. Thevalue will be used as the value of the expressionand also assigned to the given variable. Foroxrmple:

IF (rapl~~INClfUL) = “?’ THEN . . . .CONtlENT lnpytr rrply a n d aakrr first t o r t

on It In singlo rkpj

IF kountrr*countrr+l) B maxEntry THEN . . . .COWlENT updrtos countor md chocks I t for

0vWf low in on0 stop1

countrr+ptr~nrxtloc4;COMENT inl tirllros sovorrl vwlrblos t o 8

- i n on0 rtrtrrntl

rrrylptr*ptr+ll + nawEnt~ 1

IF I*] OR boolo THEN . . . .

lndrxerc indexrr+l) ; .

will put the value 3 in l rryt21, since thedest inat ion is evaluated before indoxor isincremented.

A word of caution is needed about assignmentexpressions. Make sure if you put an ordinaryassignment in an expression that that expressionis in a position where it will ALWAYS beevaluated. Of course,

IF i<J THEN icl+l;

will not always increment i but this is theintended result. However, the following isunintended and incorrect:

IF vorbososw THENPRINTVTho rquarr r o o t o f *,numb,” is “,

sqroot&QRT(numb),” . “1ELSE PRINT (sqroo t 1 ;

Page 17: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL a The ALGOL-Part of Sail

If verbosesw I FALSE, the THEN portion is not converted to INTEGER and then converted toexecuted and the assignment to sqroot is not REAL for the assignment to X .made. Thus rqroot. will not have the appropriate X4F flag THEN 2 ELSE 3.5; Will assign either 2 . 8value when it is PRINTed. Assigning the result of or 3.0 to x (assuming x is REAL). Examples are:a computation to a variable to save recomputingit is an excellent practice but be careful where REAL RRRRY resultsyou put the assignment. fl: IF rinlwrsion THEN 18 ELSE 1801;

Anot her very bad place for assignment PRINT (IF found THEN wordsItexpressions is following either the AND or CR ELSE “Uord not found.“);logical operators. The compiler handles these byperforming as little evaluation as possible so in

COUNT wordsfll wrt be a string;

p r o f i t + IF (nmt c inconn-cost) > 8 T H E N nmtl xpl OR l xp2 ELSE 0;

the compiler will first evaluate OXPI and if it isTRUE then the compiler knows that the entireboolean expression is true and doesn’t bother toevaluate 0~~2. Any assignments in l xp2 will notbe made since 0~~2 is not evaluated. (Of course,if l xpl is FALSE then 0~~2 will beevaluated.) Similarly for

l xpl FIN0 l xp2

if OXPI * is FALSE then the compiler knows thewhole AND-expression is FALSE and doesn’tbother evaluating l ~cp2.

As with nested IF...THEN..ELSE statements, it is agood coding practice to choose the order of theexpressions carefully to rave processing. Themost likely expression should be first in an ORexpression and the least likely first in an ANDexpression.

These conditional expressions will often need tobe parent hesized.

2.4.3 CASE Expressions

CASE statements are described in Section2.6.4 below. CASE expressions are alsoallowed with the format:

CASE intogor OF (rxp8,rxpl,...,oxpN)

where the first case is always 0. This takes thevalue you give which must be an integerbetween 0 and N and uses the correspondingexpression from the list. A frequent use is forerror handling where each, error is assigned anumbr and the number of the current error isput in a variable. Then .a statement like thefollowing can be used to print the proper errormessrge:

2.4.2 Conditional Expressions 1 PRINTMSE l rrno OF

Conditionals can also be used in expressions.(“Zero d i v i s i o n attmptod”,“ N o nogatlvr numborr allowd”,

These have a more r igid structure thanconditional statements. It must be

“ Input not a numbor”));

IF boo Iom rxpross Ion THEN l xpl ELSE l xp2

’ where the ELSE is not optional.

Remember that rrrno here must range from 0 to2; otherwise, a case overflow occurs.

N. B. The type of a conditional expression is the 2.4.4 St ring Operat or6type of axal. If 0~~2 is evaluated, it will beconverted to the type of OXPA. (At compile time The STRING, operators are:it is not known which will be used so anarbitrary decision is made by always using the ” ’ EQUtype o f l xpl.)

T o r t f o r s t r i n g equality:Thus the statement, rc”FIBC”j t+“abc*;

x4F f lag THEN 2 ELSE y; , will always assign a ntos tcEQU (s, t 1;

RESULT: test l FALSE .INTEGER to x. If x and y are REALS then y is

11

Page 18: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail SAIL TUTORIAL

8 C o n c a t o n a t r t u o s t r i n g s togothrrts+“abc*l te”drf”l ucs8tl ,R E S U L T : EQU(u, “abcdof “1 = TRUE .

LENGTH Roturns t h e length o f a string!s+“abc” ; I *LENGTH (ml ;RESULT: i m 3 .

LOP Removrs t h r first c h a r i n a s t r i n ga n d rrturns 111s+“abc*; tcLOP (s1 lRESULT: (EQllk, “bc”) AND

EQU(t,“a”)) I TRUE .

Although LENGTH and LOP look like proceduressyntactially, they actually compile code “in-line”.This means that they compile very fast code.However,. one unfortunate side-effect is that LOPcannot be used as a statement, i.e., you cannotsay LOP(S); if you just want to throw away thefirst character of the string. You must alwayseither ‘use or assign the character returned byLOP even if you don’t want it for anything, e.g.,junKeLOP (5) ; . Another point to note about LOP isthat it actually removes the character from theoriginal string. If you will need the intact stringagain, you should make a copy of it before youstart LOP’ing, e.g., t0mpC0ppsj .

From this we can see that LENGTH and LOP arevery efficient operations. LENGTH picks up thelength from the descriptor word; and LOPdecrements the length by 1, picks up thecharacter designated by the byte pointer, andincrements the byte pointer. LOP does not needto do anything with string space. Concatenationswith & are however fairly inefficient since ingeneral new strings must be created. For t a t,there is usually no way to change the descriptorwords to come up with the pew string (unless tand t are already adjacent in string space).Instead both s and t must be copied into a newstring in string space. In general since thepointer is kept to the beginning of the string, itis less expensive to look at the beginning thanthe end. On the other hand, when concatenating,it is better to keep building onto the end of agiven string rather than the beginning. Theruntime routines know what is at the end ofstring space and, if you happen to concatenateto the end of the last string put in, the routinescan do that efficiently without needing to copythe last string.

Assigning one string variable to another, e.g., formaking a temporary copy of the string, is alsofast since the string descriptor rather than thetext is copied.

A little background on the implementation ofstrihgs should help you to use them moreefficiently. Inefficient use of strings can be asignificant inefficiency in your programs. Ssilsets up an* area of memory called string spacewhere all the actual strings are stored. Theruntime system increases the size of this areadynamically as it begins to become full. Theruntime. system also performs garbage, collectionsto retrieve space taken by strings that are nolonger needed so that the space can be reused.The text of the strings is stored in string space.Nothing is put in string space until you actuallyspecify what the string is to be, i.e., by anassignment statement. At the time of thedeclaration, nothing is put in string space .Instead *the compiler sets up a 2-word stringdescriptor for each string declared. The firstword contains in its left-half an indication ofwhether the string is a constant or a variableand in its right-half the length of the string. Thesecond word is a byte pointer to the location ofthe start of the string in Btring space. At thetime of the declaration, the length will be zeroand the byte pointer word will be empty sincethe string is not yet in string space.

These are general guidelines rather than strictrules. Different programs will have differentspecific needs and features.

2.4.5 Subst rings

Sail provides a way of dealing with selectedsubportions of strings called substrings. Thereare two different ways to designate the desiredsubstring:

sti T O jIs(i FOR jl

where ti TO jl means the substring starting atthe ith character in the string through the jthcharacter and ti FOR 11 is the substring startingat the ith character that is j characters long.The + numbering starts with 1 at the firstcharacter on the left. The special symbol INF canbe used to refer to the last character (therightmost) in the string. So, l HNF FOR II is thelast character; and rt7 TO INFI is all but the firstsix characters. If you are using a substring of a

12

Page 19: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

.

SAIL TUTORIAL

string array element then the format isarrytindrwl ti TO jl.

Suppose you have made the assignmentt c “abcdof * . Then,

St1 TO 31 is “abc”s (2 FOR 31 is “bed”sC1 T O INFI i s “abcdei”

s tINF-1 T O INFI is “Of”s Cl TO ~lU”X”8st4 TO INFI I s “abcXdrf* .

Since substrings are parts of the text of theirsource strings, it is a very cheap operation tobreak a string down, but is fairly expensive tobuild up a new string out of substrings. .

24.6 Type Conversions

If you use an expression of one type whereanother type was expected, then automatic typeconversion is performed. For example,

INTEGER I;I e SQRTtS)j

will cause 5’ to be converted to real (becauseSQRT expects a real argument) and the squareroot of 5.0 to be automatically converted to aninteger before it is assigned to i which wasdeclared as an integer variable and can onlyhave integer values. As noted in Section 4.2 ofthe Sail manual, this conversion is done bytruncating the real value.

Another example of automatic type conversionthat we have used here in many of the sampleprograms is:

IF rmply I “Y” THEN . . . . .

where the - operator always expects integer orreal arguments rather than strings. Both thevalue of the string variable ~OPIY and the stringconstant *Y” will be converted to integer valuesbefore the equality test. The manual shows thatthis conversion, string-to-integer, is performedby taking the first character of the string andusing its ASCII value. Similarly converting frominteger to string is done by interpreting theinteger (or just the rightmost seven bits if it isless than II or-it is too large--that is any numberover 127 or ‘177) as an ASCII code and using thecharacter that the code represents as the string.So, for example,

fho ALGOL-Part of Sail

STRING s;8 l ‘181 a ‘182 a ‘1831

will make the string “ABC”.

The other common conversions that we haveseen are integer/real to boolean and string toboolean. Integers and reals are true if non-zero;strings are true if they have a non-zero lengthand the first character of the string is not theNUL character (which is ASCII code 0).

You may also call one of the built-in typeconversion procedures explicitly. We have usedCVD extensively to convert strings containing ,digits to the integer number which the digitsrepresent. CVD and a number of other usefultype conversion procedures are described inSection 8.1 of the Sail manual. Also this sectiondiscusses the SETFORMAT procedure which isused for’ specifying the number of leading zeroesand the maximum length of the decimal portion ofthe real when printing. SETFORMAT is extremelyuseful if you will be outputting numbers astables and need to have them automatically lineup vertically.

2.5 Scope of Blocks

So far we have seen basically only one use ofinner blocks. With the IF..THEN statement, wesaw that you sometimes need a block rather thana simple statement following the THEN or ELSEso that a group of statements can be executedas a unit.

In fact, blocks can be used within the programany place that you can use a single statement.Syntactically, blocks are statements. A typicalprogram might look like this:

BEGIN “prog”..

BEGIN *Initialitatlona.

EN;) “Initlalitatlon”

BEGIN “main part”

BEGIN “procoss data”..

BEGIN “output rrsul ts”.

13

Page 20: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail SAIL TUTORIAL

END “output results”

END “process data”

END “main part”

BEGIN “finish u p ”

ENi “ f i n i s h u p ”

END “prog“

The declarations in each block establish variableswhich can only be used in the given block. SOanother reason for using inner blocks is tomanage variables needed for a specific shortrange task.

Each block can (should) have a block name. Thename ii given in quotes following the BEGIN andEND of the block. The case of the letters,number of spaces, etc. are important (as in stringconstants) so that the names “MAIN LOOP”,“Main Loop”, “main loop”, and “Main loop” are alldifferent and will not match. There are severaladvantages to using block names: your programsare easier to read, the names will be used by thedebugger and thus will make debugging easier,and- the compiler will check block names andreport any mismatches to help you pinpointmissing END’s (a very common programmingerror).

The above example shows us how blocks maynest. Any block which is completely within thescope of another block is said to be nested inthat block. In any, program, all of the innerblocks are nested in the outer block. Here, inaddition to all the blocks being within the “prog”block, we f ind “output results” nested in“process data” and both “output results” and“process data” nested in “main part”. The threeblocks called “initialization”, “main part” and“finish up” are not nested with relation to eachother but are said to be at the same Iavel. Noneof the variables declared in any of these threeblocks is available to any of the others. In orderto have a variable shared by these blocks, weneed to declare it in a block ‘which is “outer” toall of them, which is in this case the veryoutermost block “prog”.

Variables are available in the blockin which theyere declared and in all the blocks nested in that

block UNLESS the inner block also has a variableof the same name declared (a very bad idea ingeneral). The portion of the program, i.e., theblocks, in which the variable is available is calledthe fcopo of the vrriablo.

BEGIN ‘kin”INTEGER i, jri&ri4PRINT("CRSE A: i=",I," b",ih

BEGIN “Inner”INTEGER i, kjitl0jb3JPRINT("CRSE B: /s",/," j=",j," ks”,k);

WIE N D “innor” ;

PRINT(“CRSE CI II”, 1,” j=“, u;END “main”

Here we cannot access k except in block “inner”.The variable j is the same throughout the entireprogram. There are 2 variables both named i.So the program will print out:

CASE A: iL5 j12CASE 8: irle 112 ~13CASE C: 115 j=4

Variables are referred to as local variables in theblock in which they are declared. They arecalled global variables in relation to any of theblocks nested in the block of their declaration.With both a local and a global variable of thesame name, the local variable takes precedence.There are three relationships that a variable canhave to a block:

1) It is inaccessible to the block ifthe variable is declared in a block at thesame level as the given block or it isdeclared in a block nested within thegiven block.

2) It is local to the block if it isdeclared in the block.

3) It is global to the block if it isdeclared in oae of the blocks that thegiven block is nested within.

Often the term “global variables” is usedspecifically to mean the variables declared in theouter block which are global to all the otherblocks.

14

Page 21: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

.

sAk ‘TUTORIAL The ALGOL-Part of Sail

In reading the Sail manual, you will see theterms: allocation, deallocation, initialization, andreinitirlization. It is not important to completelyunderstand the implementation details, but it is

, extremely important to understand the effects.The key point is that allocating storage for datacan be handled in one of two ways. Storagoallocation refers to the actual setting up of datalocations in memory. This can be done 1) atcompile time or 2) at runtime. If it is done atruntime then we say that the allocation isdynamic. Basically, it is arrays which aredynamically allocated (excluding outer blockarrays and other arrays which are declared asOWN). LISTS, SETS, and RECORDS which we havenot discussed in this section are also. allocateddynamically. The following are allocated a tcompile time and are NOT dynamic: scalarvariables (INTEGER, BOOLEAN, REAL and STRING)except where the scalar var iable is in arecursive procedure, outer block arrays, andother OWN arrays. ALGOL users should note thisas an important ALGOL/Sail difference.

Dynamic storage (inner block arrays, etc.) will beallocated at the point that the block is enteredand deallocated when the block is exited. Thismakes for quite efficient use of large amounts ofstorage space that serve a short term need.

. ATso, it allows you to set variable size boundsfor these arrays since the value does not needto be known at compile time. .

At the time that storage is allocated, it is alsoinitialized. This means that the initial value is

’ assigned---NULL for strings and 0 for integers,reals, and booleans. Since arrays are, allocatedeach time the block is entered, they arereinitialiied each time. We have not yet seenany cases where the same block is executedmore than once but this is very frequent withthe iterative and looping control statements.

Scalar variables and outer block arrays are notdynamically allocated. They are allocated by thecompiler and will receive the inital null or zerovalue when the program is loaded but they willnever be reinitialized. While you are not in theblock, the variables are not accessible to you butthey are not deallocated so they will have thesame value when you enter the block the nexttime as when-you exited it on the previous use.Usually you will find that this is not what youwant. You should initialize all local scalarvariables yourself somewhere near the start ofthe block--usually to NULL for strings and 0 for

arithmetic variables unless you need some otherspecific initial value. You should also initialize allglobal scalars (and outer block arrays) at. thestart of your program to be on the safe side.They are initialized for you when the compiledprogram is later run, but their values will not bereinitialized if the program is restarted whilealready in core and the results will be verystrange.

One exception is the blocks in RECURSIVEPROCEDURE S which do have all non-OWNvariables properly handled and initialized asrecursive calls are made on the blocks.

If you should want to clear an array, thecommand

ARRCLR tarry)

will clear arry (set string arrays to NULL andarithmetic to 0). For arithmetic (NOT string)arrays,

RRRCLR (airy, va I)

will set the elements of l rry to Van.

See Sections 2.2-2.4 of the Sail manual for moreinformation on OWN, SAFE, and PRELOADEDarrays and Section 8.5 for the ARRBLT andARRTRAN routinor for moving the contents ofarrays. ,

2.6 More Control Statements

2.6.1 FOR Statement

The FOR statement is used ‘for a definite numberof iterations. Many times you will want torepeat certain code a specific number of times(where usually the number in the sequence ofrepetitions is also important in the codeperformed). For example, .

FOR i + 1 STEP 1 UNTIL 5 DOPRINTU, ” “, SQRTW);

which will print out a table of the square rootsof the numbers 1 to 5.

The syntax of the (simple) FOR statement is

FOR varlablo c starting-value STEP lncramontUNTIL rnd-value DO statomont

15

Page 22: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail

The iteration vrrirblo is assigned the starting-value and tested to check if it exceeds the end-value; if it is within the range then the statementafter the DO is executed (otherwise the FORstatement is finished). This completes the firstexecution of the FOR-loop.

Next the increment is added to the variable andit is tested to see if it now exceeds the end-value. If it does then the statement is notexecuted again and the FOR statement is finished.If it is within the maximum ‘(or equal to it) thenthe statement is executed again but all instancesof the iteration variable in the statement willnow have the new value. This incrementing andchecking and executing loop is repeated until theiteration variable exceeds the end-value.

For those users familar with GOT0 statementsand LABELS, the fol lowing two programfragmentS for COmpUting r n s l FACT(n) a r eequivalent.

FOR i c2STEPlUNTILnDO l nscanse i l

is equivalent to:

a n t c 11i l 21

loop1 IF I > n THEN GOT0 bryond 1ant c ans t i;I * I + 1;GOT0 loopj

beyond I

There is considerable dispute on whether or nott h e u s e of GOT0 statements should beencouraged and if so under what conditions.These statements are available in Sail but willnot be discussed in this Tutorial.

Very often FOR-loops are used for indexingthrough arrays. For example,, if you arecomputing averages, you wilt need to addtogether numbers which might be stored in anarray. The following program allows a teacherto input the total number of tests taken and alist of the scores; then the program returns theaverage score.

BEGIN “avoragor”RERL rwrrge; I N T E G E R numbTosts, total il verrgm-numbTostsetotale8;COtttlENT rommbw t o initialltr vrrirblor~PRINl(“Total numbrr o f t o r t s : VinumbTostscCVD(INCtWL)1

iAlL TUTORIAL

BEGIN “usoRrray*INTEGER ARRAY tos tScoros Ilr numblw tsl ;CORRENT array has var iable bounds so must

br i n lnnrr blocklINTEGER i jCOHHENT f o r uso a s the Itoration vrriablo;

FOR I + 1 STEP 1 UNTIL numbfosts D OBEGIN “fillrrrry”

PRINTt”Test Scora #“,i,” 8 “1;. tmtScorrsIl1 + CVDfINCHUL);

EN0 “fillarrry”i

FOR i * 1 STEP 1 UNTIL numbfos ts DOtotalctotal+t~stScorrt[il;

CORHENT n o t r t h a t t o t a l uas initialized t o0 abow;

END “usoArray*~

I F numbTosts neq 8 T H E N rverag~etotal/numbTosts;PRINTf”The avarrgr i s “,avmrago,“.“);EN0 “averagw’;

In the first FOR-loop, we see that i is used in thePRINT statement to tell the user which test scoreis wanted then it is used again as the array‘subscript to put the score into the i’th elementof the array. Similarly it is used in the secondFOR-loop to add the i’th element to thecumulative total.

The iteration variable, start-value, increment, endend-value can all be reals as well as integers.They can also be negatives (in which case themaximum is taken as a minimum). See the Sailmanual for details on other variations wheremultiple values can be given for more complexstatements (these aren’t used often). One pointto note is that in Sail the end-value expression isevaluated each time through the loop, while theincrement value is evaluated only at thebeginning if it is a complex expression, asopposed to a constant or a simple variable. Thismeans that for efficiency, if your loop will beperformed very many times you should not havevery complicated expressions in the end-valueposition. If you need to compute the end-value,do it before the FOR-loop and assign the valueto a variable that can be used in the FOR-loop tosave having to recompute the value each time.This doesn’t save much and probably isn’t worthit for 5 or 10 iterations but for 500 or 1000 itcan be quite a savings. For example use:

uxc(ptr-of fsot)/PjF O R lcoffsrt STEP 1 UNTIL MX DO s ;

16

Page 23: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL The AL&L-Part of Sail

rather than

F O R leoffsmt STEP 1 UNTIL (ptr-offsat)/ DO s;

.

2.6.2 WHILE...DO Statement and DQ..UNTILSt at ement

I Often you will want to repeat code but not knowin advince how many times. Instead the iterationwill be finished when a certain condition is met.This is called indofinito iteration and is done witheither a WHILE...DO or a DD...UNTIL statement.

The syntax of WHILE statements is:

W H I L E b o o l r a n - • x p r o s s j o n D O strtemnt

The boolean is checked and if FALSE nothing isdone. If TRUE the statement is executed andthen the boolean is checked again, etc.

For example, suppose we want to check throughthe elements of an integer array until we find enelement containing a given number n:,

INTEGER ARRAY arry 118 maxI_ ptr + 1;

W H I L E (arrytptrl N E D n) llND (ptr < ~8x1 D Dptrcptr*lj

If the array element currently pointed to by ptris the number we are looking for OR if the ptr is

at the’upper bound of the array then the WHlLEstatement is finished. Otherwise the ptr isincremented and the boolean (now using the nextelement) is checked again. When the WHILE~JOstatement is finished, either ptr will point to thearray element ‘with the number or ptr-max willmean that nothing was found.

The WHILE...00 statement is equivalent to thefollowing format with LABELS and the GOT0statement:

loop: IF NOT boolean expression THENGOT0 beyond;

statomontjGOT0 loop;

boyond-i

continues UNTIL the boolean becomes true ratherthan WHILE it is true.

D O rtrtomnt U N T I L b o o l e a n - r x p r o s s i o n

For example, suppose we want to get a series ofnames from the user and store the names in a.string array. We will finish inputting the nameswhen the user types a bare carriage-return(which results in a string of length 0 fromINCHWL or INTTY).

id;D O PRINT(“Nama X”,ici+l,” i s : “1

UNTIL (LENGTH hmes f i I c INCHUL 1 t 8 1;

The equivalent of the DD...UNTIL statement usingLABELS and the GOT0 statement is:

loop: strtemont;IF NOT boolorn l xprossion THEN GOT0 loop;

Note that the checks in the WHILE...00 andDO...WUTIL statements are the reverse of eachother. WHILE...DO continues as long as theexpression is true but DO...UNTlL continues as .long as the expression is NOT true. So that

UHILE I < 180 DO . . . . .

is equivalent to

DO . . . . . UNTIL I GEQ 188

except that the statement is guaranteed to beexecuted at least once with the DO...UNTIL butnot with the WHILE...DO.

The WHILE and DO statements can be used, forexample, to check that a string which we haveinput from the user is really an integer. CVDstops converting if it hits a non-digit and returnsthe results of the conversion to that point butdoes not give an error indication so that a checkof this sort should probably be done on numbersinput from the user before CVD is called.

The DO..MUTlL statement is very similar exceptthat 1) the statement is always executed thefirst time and then the check is made beforeeach ,subsequent loop through and 2) the loop

17

Page 24: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail

INTEGER numb, char;S T R I N G raply,tanpl BOOLERN error1PRINT(“Type the numbor: “); . ’DO

BEGINl rror+FALSEltemp+replycINCHULjUHILE LENGTH 1 tomp) DO

IF NOT (“8” LEQ (charcLDP(tomp)) LEO “9”)THEN rrrorcTRUE;

iF error T H E N PRINT(“Dops, t r y rgrinr “11EN0UNTIL NOT crrror;

numb4VD (rap ly) l

2.6.3 DONE and CONTINUE Statements

Even with definite and indefinite iterationsavailable, there will still be times when you needa greater degree of control over the loop. Thisis accomplished by the DONE and CONTINUEstatements which can be used in any loop whichbegins with DO, e.g.,

FOR icl STEP 1 UNTIL j m . . .00 . . . UNTIL rxp

UHILE l xp t)o . . .

(See the manual for a discussion of the NEXTstatement which is not often used.) DONE meansto abort execution of the entire FOR, DO...UNTILor WHILE...00 statement immediately. CONTINUEmeans to stop executing the current passthrough the loop and continue to the nextiteration.

Suppose a string array is being used as a“dictionary” to hold a list of 100 words and wewant to look up one of the words which isnowstored in a string called target:

FOR i c 1 STEP 1 UNTIL 188 DOIF EDU(uordsfi1, trrgat) THEN DONE1

IF i>lW T H E N PRINT(trrget,” not found.“)j

If the target is found, the FOR-loop will stopregardless of the current value of i. Note thatthe iteration variable can be checked after theloop is terminated’ to determine whether theDONE forced the termination (i LEQ 100) or thetarget was never found and the loop terminatednaturally (i > 100).

If the loops are nested then the DONE or

S-AIL TUTORIAL

CONTINUE applies to the innermost loop unlessthere are names on the blocks to be executed byeach loop and the name is given explicitly, e.g.,OONE “some I oop”. With the DONE and CONTINUEstatements, we can now give the complete codeto be used for the sample program given earlierwhere a number was accepted from the user andthe square root of the number was returned. Avariety of error checks are made and the usercan continue giving numbers until finished. Inthis example, block names will be used with DONEand CONTINUE only where they are necessaryfor the correctness of the program; but use ofblock names everywhere is a good practice forclear programming.

BEdIN “prog” STRING trmp,rop lyl INTEGER numb;,

UHILE TRUE DOCOMENT a wry common construct ion which just

loops unt i l DONEjBEGIN “procossnuntb”

PRINT(“Typr a numbrr, <CR> t o e n d , o r 3 r*)lUHILE TRUE DO

BEGIN’ “checkor”IF NOT tENGTH(trmpcrrp IycINCHUL) THEN

DONE “processnumb’lIF rep ly t “7” T H E N

BEGINPRINTV..holptrxt 8 roprompt..“)jCONTINUE jCOllllENT dofrults t o *checkor”j

ENOjUHILE LENGTH (temp) DO

IF NOT (“0” LED LOP (tomp) LEQ “9”) THENBEGIN

PRINT(?Oops, t r y rgainr “)jCONTINUE “chockor”;

ENDjIF (numbcCVD (rep I y) 1 K 0 T H E N

BEGINPRINT(“Nog81 i v o , t r y again: “1;CONTINUE j

ENO;DONEjCOtltlENT i f 81 I the chocks have boon

passrd t h r n don.1EN0 “chockor”l

PRINT(“The Square R o o t o f *,numb,” i s “,SQRT(numb), *. “1 j

COWlENT n o w ue go brck t o t o p o f l o o pf o r n e x t i n p u t j

END “processnumb*lEND “prog”

Page 25: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL The ALGOL-Part of Sail

2.6.4 CASE St at ement CASE char-V” OFCOHHENT “A”-“R” i s 8 , and i s t h u s case 8 ;

BEGIN<cod. f o r A option*;<code f o r B optlowl

.

<cidm for E opt ion>ENDj

The CASE statement is similar to the CASEexpression where SO,S 1 ,...Sn represent thestatements to be given at these positions.

CASE intogw O FBEGINS81

i2;COtlflENT t h e empty rtatomont;

S;lEND;

where cs are included for those cases where no, action is to be taken. Another version of theCASE statement is:

CRSE intrgrr O FBEGIN181 S8;t41 S4; COtltlENT cases c a n bo skippodjt31 S 3 ; COflflENT nard n o t bo i n ordarjt51 s s ;

(61 t71 S61 COflllENT n a y bo same ttatoatmt~181 S8; *

tnl l SnENO;

where explicit numbers in [J’s are given for thecases to be included.

It is very IMPORTANT not to use ,s semi-colonafter the final statement before the END. Also,do NOT use- CASE statements if you have asparse number of cases spread over a widerange because the compiler will make a giantt a b l e , e . g . ,

CQISE numbor O FBEG IN181 S8;t 18881 Sl888;f28881 $2888

.ENDi

would pyoduce a 2001 word table!

Remember that the first case is 0 not 1. Anexample is using a CASE statement to processlettered options:

INTEGER char!PRINf(“Typo A,B,C,O, o r E I “1;chrrclNCHWL~

2.7 Procedures

We have been using built-in procedures and infact would be lost without them if we had to doall our own coding for the arithmetic functions,the interactions with the system likeInput/Output, and the general utility routines thatsimplify our programming. Similarly, goodprogrammers would be lost without the ability towrite their own procedures. It takes a little timeand practice getting into the habit of looking atprogramming tasks with an eye to spottingpotential procedure components in the task, butit is well worth the effort.

Often in programming, the same steps must berepeated in different places in the program.Another way of looking at it is to say that thesame task must be performed in more than onecontext. The wry this is usually handled is towrite a procodwo which is the sequence ofstatements that will perform the task. Thisprocedure itself appears in the declarationportion of one of the blocks in your program andwe will discuss later the details of how youdeclare the procedure. Essentially at the timethat you are writing the statement portion ofyour program, you can think of your proceduresas black boxes. You recognize that you have aninstance of the task that you have designed oneof your procedures to perform and you includeat that point in your sequence of statements aprocoduro call statement. The procedure will beinvoked and will handle the task for you. In thesimplest case, the procedure call is accomplishedby just writing the procedure’s name.

For example, suppose you have a calculator-typeprogram that accepts an arithmetic expressionfrom the user and evaluates it. At suitableplaces in the program you will have checks tomake sure that no divisions by zero are beingattempted. You might write a procedure calledzrrobiv which prints out a message to the usersaying that a zero division has occurred, repeats

19

Page 26: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail SAIL TUTORIAL

the current arithmetic expression, and asks if theuser would like to see the prepared help text forthe program. Every time you check for zerodivision anyplace in your program ‘and find it,you will call, this procedure with the statement:

zero0 ivi

and it will do everything it is supposed to do.

Sometimes the general format of the task w’ill bethe same but some details will be .different.

I These cases can be covered by writing aparrmotorized procoduro. Suppose that wewanted something like our toroDiv procedure, butmore general, that would handle a number ofother kinds of errors. It still needs to print out adescription of the error, the current expressionbeing evaluated, and a suggestion that the userconsult the help *text; but the description of theerror will be different depending on what theerror was. We accomplish this by using avariable when we write the procedure; in thiscase an integer variable for the error number.The procedure includes code to print out theappropriate message for each error number; andthe integer variable l rrno is added to theparameter list of the procedure. Each of thepar-meters is a variable that will need to have avalue associated with it automatically at the timethe procedure is called. (Actually arrays andother procedures can also be parameters; butthey will be discussed later.) We won’t worryabout the handling of parameters in proceduredeclarations now. We are concerned with theway the parameters are specif ied in theprocedure call. Our procedure l rrorHand ier willhave one integer parameter so we call it withthe expression to be associated with the integervariable l rrno given in parentheses following theprocedure name in the procedure call. Forexample,

l rrorHand ior (8)l rrorHand ior (1).rrorHand I or (2)

would be the valid calls possible if we had threeI different possible errors.

If there is-more than one parameter, they areput in the order given in the declaration and

. separated -by -commas. (Argumontt is anotherterm used for the actual parameters supplied ina procedure call.) Any expression can be usedfor the parameter, e.g., for the built-in procedureSORT:

SQRT (4 1SORT (numb)SQRT KVD (INCHUL) 1SQRT(numb/dlvitor)

When Sail compiles the code for these procedurecalls, it first includes code to associate theappropriate values in the procedure call with thevariables given in the parameter list of the *procedure declaration and then includes the codeto execute the procedure. When l rrorHand ierPRIM% the error message, the variable l rrno ‘willhave the appropriate value associated with it.This is not an assignment such as those done bythe assignment statement and we will also bediscussing calls by REFERENCE as well as calls byVALUE; but we don’t need to go into the detailsof the actual implementation -- see the manual ifyou are interested in how procedure calls areimplemented and arguments pushed on the stack.

Just ‘as we often perform the same task manytimes in a given program so there are tas’ksperformed frequently in many programs by manyprogrammers. The authors of Sail have writtenprocedures for a number of such tasks which canbe used by everyone. These are the built-inprocedures (CVD, INCHWL, etc.) and are actuallydeclared in the Sail runtime package so all that isneeded for you to use them is placing theprocedure calls at the appropriate places. Thusthese procedures are indeed black boxes whenthey are used.

However, for our own procedures, we do need towrite the code ourselves. An example of auseful procedure is one which converts a stringargument to all uppercase characters. First, theprogram with the procedure call to upper at theappropriate place and the position marked wherethe procedure declaration will go:

BEGINSTRING rrpiy,namr;w$procoduro d o c i a r a t i o n herrlctrcl:

PRINT(“Typo RERD, URITE, or SEARCH: “1;rap I y4Jppor (INCHUL) ;IF EDUhpiy, “READ”) THEN . . . .

ELSE IF EDUhpiy,“WRITE”) THEN . . . .ELSE IF EQUhpiy, “SERRCH”) THEN . . . .E L S E e... ;

END;

We put the code for the procedure right in the

20

Page 27: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL- TUTORIAL The ALGOL-Part of Sail

procedure declarat ion which goes in thedeclaration portion of any block. Remember thatthe procedure must be declared in a block whichwill make it accessible to the blocks where youare going to use it; in the same way that avariable must be declared in the appropriateplace. Also, any variables that appear in thecode of the procedure must already be declared(even in the declaration immediately precedingthe procedure declaration is fine).

Here is the procedure declaration for upper whichshould be inserted at the marked position in theabove code:

STRING PROCEDURE upper (STRING ram tr ingl ;BEGIN “uppar”S’TRING tmp; I N T E G E R char1tmpcNULL;UHILE LENGTH (raw tr ing) DO

BEGINcharcLDP (raur tr ing) itmp+tmpd(IF “ a ” LED c h a r LED “t”

THEN char-‘48 ELSE char11END;

RETURN f tmp) ;END “upper”;

The syntax is:

t y p o - q u a i i f i o rstatewnt

PROCEDURE idantifior l

for procedures with no parameters OR

typo-quaiiflor PROCEDURE idontifior( p a r r m o t o r - l i s t 1 ; statrment

where the parameter-list is enclosed in 0% and asemi-colon precedes the statement (which isoften called the procedure body). The ‘type-qualifier>% will be discussed shortly.

The parameter list includes the names and typesof the parameters and must NOT have a semi-colon following the final item on the list.Examples are: .

PROCEDURE offrrHoip ;INTEGER PROCEDURE f indUord ’

(STRING targrtl STRING ARRRY words) ;SINPLE PROCEDURE l rrorH&ndlor

(INTEGER l rrno) lRECURSIVE INTEGER PROCEOURE factorial

.(INTEGER numbor) ;

PROCEDURE sortEntries(INTEGER ptr, f irst; REAL ARRRY unsorted) ;

STRING PROCEDURE upprr (STRING raMString) ;

Each of these now needs a procedure body.

PROCEDURE of forHo ip l

BEGIN “offorHoip”COlltlENf the procedure name i s u s u a l l y u s e d

as block namojPRINT(“Wouid y o u I ikm help (Y o r N): “1;I F uppw(INCHiJL) = “Y” T H E N PRINT(“..heip. .“I

ELSE RETURN;PRINT(“Uould y o u I i k r mro h r i p (Y o r N)r “1;I F uppor(INCHUL) m “Y” T H E N

PRINTS”. .morm help.. “1 lEND “offorHoip”;

This offers a brief help text and if it is rejectedthen RETURNS from the procedure withoutprinting anything. A RETURN statement may beincluded in any procedure at any t ime.Otherwise the brief help message is printed andthe extended help offered. After the extendedhelp message is printed (or not printed), theprocedure finishes and returns without needing aspecific RETURN statement because the code forthe procedure is over. Note that we can useprocedure calls to other procedures such a supprr provided that we declare them in theproper order wi th u p p e r d e c l a r e d b e f o r eof frrHrip.

PROCEDURE declarations will usually have type-qualifiers. There are two kinds: 1) the simpletypes--INTEGER, STRING, BOOLEAN, and REAL and2) the special ones--FORWARD, RECURSIVE, andSIMPLE.

FORWARD is typically used if two procedures calleach other. This creates a problem because aprocedure must be declared before it can becalled. For example, if of ferHolp called upper, andupper also called of forHelp then we would need:

FORURRD STRING PROCEDURE upper(STRING raw tr ing) ;

PROCEDURE offorHoip lBEGIN “of farHelp”

. . .*code for, offorHolp i n c l u d i n g c a l I t o upper,

ENi ‘o;fwHaip”l

STRING PROCEDURE upper (STRING rarrstr ing) ;

21

Page 28: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Fart of Sail

BEGIN “upper”. . .

<code for upper inc luding call to offerHalp>. . .

EN0 “upper” ;

The FORWARD declaration does not include thebody but does include the parameter list (if any).This declaration gives the compiler enoughinformation about the upper protedure for it toprocess the of forHo tp procedure. FORWARD isalso used when there is no order of declarationof a series of procedures such that everyprocedure is declared before it is used.FORWARD declarations can sometimes beeliminated by putting one of the procedures inthe body ,of the other, which can be done if youdon’t need to use both of them later.

RECURSIVE is used to qualify the declaration ofany procedure which calls itself. The compilerwill add special handling of variables so that thevalues of the variables in the block arepreserved when the block is called again andrestored after the return from the recursive call.For example,

RECURSIVE INTEGER PROCEOURE factorial(INTEGER i);

-RETURN(IF i L 8 T H E N 1 E L S E factorial(i-l)*i)l

The compiler adds some overhead to proceduresthat can be omitted if you do not use anycomplicated structures. Declaring proceduresSIMPLE inhibits the addition of this overhead.However, there are severe restrictions onSIMPLE procedures; and also, BAIL can be usedmore effectively with non-SIMPLE procedures.So the appropriate use of SIMPLE is during theoptimization stage (if any) after the program isdebugged. At this time the SIMPLE qualifier canbe added to the short, simple procedures whichwill save some overhead. The restrictions onSIMPLE procedures are:

1) Cannot allocate storagedynamically, i.e., no non-OWN arrays can ,be declared in SIMPLE procedures.

2) Cannot do GO TO’s outside ofthemselves (the GO TO statement has notbeen covered here).

- -3) Cannot, if declared inside other

procedures, make any use of theparameters of the other procedures.

22

S’AIL TUTORIAL

Procedures which are declared as one of thesimple types (REAL, INTEGER, BOOLEAN, orSTRING) are called typed procedures as opposedto untyped procedures (note that the SIMPLE,FORWARD, and RECURSIVE qualifiers have noeffect on this distinction). Typed procedures canreturn values. Thus typed procedures are likeFORTRAN functions and untyped procedures arelike FORTRAN subroutines. The type of the valuereturned corresponds to the type of theprocedure declaration. Only a single value maybe returned by any procedure. The format isRETURN ( rxpross I on 1 where the expression isenclosed in 0’s. Procedure upper which wasgiven above is a typed procedure which returnsas its value the uppercase version of the string.Another example is:

REAL PROCEDURE avoragrr(INTEGER ARRAY scorosi INTEGER max) ;

BEGIN “avoragw” R E A L total! INTEGER i;t o t a l c 8~F O R I c 1 STEP 1 UNTIL max 00

total + t o t a l 4 scorrstllfIF max NEP 8 THEN RETURN(total/nax)

ELSE RETURN (8) jEN0 “avoragor”;

We might have a variety of calls to thisprocedure:

tar thorago c avoragor (tot tScores,numborScores) ;salaryAvoragr c l vrragrr(salarios,numbrrEnrployoos~~spoodRvrragr e av~ragrr(spords,numbrrTrlrlr)i

w h e r e testScorm, salar irs, and spuds a re a l lINTEGER ARRAYS.

Procedure calls can always be used asstatements, e.g.,

1) I F divisor4 T H E N rrro6HandlerW;2) o f forHolp;3) upper(trxt);

but as in 3) it makes little sense to use aprocedure that returns a value as a statementsince the value is lost. Thus typed procedureswhich return values can also be used asexpressions, e.g.,

rrplyeuppor(INCHUL1;PRINT (upper (name) 1;

It is not necessary to have a RETURN statement

Page 29: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL The ALGOL-Part of Sail

in untyped procedures. If you do have a RETURNstatement in an untyped procedure it CANNOTspecify a value; and if you have a R E T U R Nstatement in a typed procedure it MUST specifya value to be returned. If there is no RETURNstatement in’a typed procedure then the valuereturned will be garbage for integer and realprocedures or the null string for stringprocedures; this is not good coding practice.

Procedures f requent ly wi l l RETURN(true) orRETURN(false) to indicate success or a problem.For example, a procedure which is supposed toget a filename from the user and open the filewill return true if successful and false if no filewas actually opened:

specified in the parameter list so you don’t haveto remember them) and the subtask is taken careof. If you don’t modularize your programs in thisway, you are juggling too many open tasks atthe same time. Another approach is to tackle themajor tasks first and every time you see asubtask put in a procedure call with reasonablearguments and then later actually write theprocedures for the subtasks. Usually a mixtureof these approaches is appropriate; and you willalso find yourself carrying particularly goodutility procedures over from one program toanother, building a library of your own generalutility routines.

IF gotFllo THEN processlnputELSE l rrorHand I or (22) i

This is quite typical code where you can see thatall the tasks have been procedurized. Manyprograms will have 25 pages of proceduredeclarations and then only 1 or 2 pages of actualstatements calling the appropriate procedures atthe appropriate times. In fact, programs can bewritten with pages of procedures and then onlya single statement to call the main procedure.

The second advantage of parameters over globalvariables is that the global variables will actuallybe changed by any code within the proceduresbut variables used as parameters to procedureswill not. The changing of global variables issometimes called a side-•ffoct of the procedure.

Here are a pair of procedures that illustrate boththese points:

Basically there are two ways of givinginformation to a procedure and three ways ofreturning information. TO give information youcan 1) use parameters to pass the informationexplicitly or 2) make sure that the appropriatevalues are in global variables at the time of thecall and code the procedures so that they accessthose varirbles. There are severaldisadvantages to the latter approach although itcertainly does have its uses.

BOOLERN PROCEDURE hmrl (STRING s);BEGIN “Quesl”IF “?” = LOP(s) THEN RETURN (true)

ELSE RETURN(falsr);EN0 “Q~~s1”;

STRING s tr;BOOLEAN PROCEOURE Ques2 ;BEGIN “Quos2”IF “?” = LOP(s tr) THEN RETURN (true)

ELSE RETURN ( f a I so) 3EN0 ‘QuIs~“;

First, once a piece of information has beenassigned to a parameter, the coding proceedssmoothly. When you write the procedure call,you can .check the parameter list and see at aglance what arguments you need. If you insteaduse a global variable then you need to rememberto make sure it has the right value at the time ofeach procedure call. In fact in a complicatedprogram YOU will have enough troubleremembering the name of the variable. This isone of fhe beauties of procedures. You canthink about the task and all the components ofthe task end code them once and. then when youare in the middle of another larger task, you onlyneed to give the procedure name and the valuesfor all the parameters (which are clearly

The second procedure has these problems: 1) wehave to make sure our string is in the stringvariable str before the procedure call and 2) stris actually modified by the LOP so we have tomake sure we have another copy of it. With thefirst procedure, the string to be checked can beanywhere and no copy is needed. For example,if we want to check a string called command, wegive Qursl (cotwand) and the LOP done on thestring in QUOS~ will not affect command.

lnformrtionthree ways:

can be returned from procedures in

1) With a RETURNhaluo) statement.

2) Through global variables. Youmay sometimes actually want to change a

23

.

Page 30: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

The ALGOL-Part of Sail

global variable. Also, procedures canonly return a single value so if you haveseveral values being generated in theprocedure, you may use global variablesfor the others.

3) Through REFERENCE parameters.Parameters can be either VALUE orREFERENCE. By default all scalarparameters are VALUE and arrayparameters are REFERENCE. Arrayparameters CANNOT be value; but scalarscan be declared as reference parameters.Value parameters as we have seen aresimply used to pass a value to thevariable which appears in the procedure.Reference parameters actually associatethe variable address given in theprocedure call with the variable in theprocedure so that any changes made willbe made to the calling variable.

PROCEDURE manyReturns(REFERENCE INTEGER i, j,k, I,n);

BEGINici+l; jej+lj kek+l; lel41.; mcm41;

ENO;

when called with

w i l l ac tua l l y change the varl,..,varSvariables themselves. Arrays are alwayscalled by reference. This is useful; forexample, you might have a

PROCEDURE sorter (STRING ARRAY arry) ;

which sorts a string array alphabetically.It will actually do the sorting on thearray that you give it SO that the arraywill be sorted when the procedurereturns. Note that arrays cannot bereturned with the RETURN statement sothis eliminates the need for making allyour arrays global as a means ofreturning them.

See the Sail manual (Sec. 2) for details on usingprocedures as parameters to other procedures.

24

SAIL TUTORIAL

Page 31: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL Macros

SECTION 3

Macros

Sail macros are basically string substitutionsmade in your source code by. the scannor duringcompilation. Think of your source file as beingread by a scanner that substitutes definitionsinto the token stream going to a logical “innercompiler”. Anything that one can do withmacrosi one could have done without them byediting the file differently. Macros are’ used forseveral purposes.

They are used to define named constants, e.g.,

BEGINREQUIRE “il tl” DELIHITERS;D E F I N E maxS It. = 11881 ;R E A L RRRRY wry tl:~xSizrl;

The 0’s are used as dolimitors placed around theright-hand-side of the macro definition.Wherever the token MXS ire appears, the scannerwilt substitute 188 before the code is compiled.These substitutions of the source text on theright-hand-side of the DEFINE for the token onthe left-hand-side wherever it subsequently‘appears in the source file is called expanding the

macro. The above array declaration after macroexpansion is:

BEG INR E A L AkRRY wry 11:1881;

which is more efficient than using:

BEGIN INTEGER UXS irr;maxSltrcl88;

BEGIN* R E A L ARRAY wry tlrmaxSitd~

I Also, in this dxample, the use of the integer. variable for assignment of the ~XSIZO means that

the array-bounds declaration is variable ratherthan constant -so it must be in an inner’ block;with the macro, ~XS’~ZO is a constant so the array

. can be declared anywhere.

Other advantages to using macros to define

names for constants are 1) a name like naxs izoused in your code is easier to understand thanan arbitrary number when you or someone elseis reading through the program and 2) maxsitewill undoubtedly appear in many contexts in theprogram but if it needs to be changed, e.g., to200, only the single definition needs changing. Ifyou had used 100 instead of maxsiza throughoutthe program then you would have to changeeach 100 to 200.

Before giving your DEFINES you should requiresome delimiters. ()(), [](I or <><> a r e g o o dchoices. If you don’t require any delimiters thenthe defaults are *““” which are probably a poorchoice since they make it hard to define stringconstants. The first pair of delimiters given inthe REQUIRE statement are for the right-hand-side of the DEFINE. See the Sail manual fordetails on use of the second pair of delimiters.

DEFINES may appear anywhere in your program.They are neither statements nor declarations.REQUIRES can be e i ther dec la ra t ions o rstatements so they can also go anywhere in your .program.

Another use of macros is to define octalcharacters. If you have tried to use any of thesample programs here you will have discovereda glaring bug. Each time we have output ourresults with the PRIM: statement, no account hasbeen taken of the need for a CRLF (carriagereturn and line feed) sequence. So all the lineswill run together. Here are 4 possible solutionsto the problem:

1) PRINf(“Soam text.“, (‘156’12));

2) PRINTVSonn text.“)I

3) S T R I N G crlficrlfe”

“i P R I N T (“Soma toxt.“,crlf);

4) REQUIRE “11” DELIHITERS;D E F I N E crlf I I”

“11 PRINT(“Sonr toxt.“,crlf)i

The first solution is hard to type frequently withthe octals. (In general, concatenations should be ’avoided if possible since new strings mustusually be created for them; but in this case withonly constants in the concatenation, it will bedone at compile time so that is not aconsideration.) The second solution with the

25

Page 32: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Macros SAIL TUTORIAL

string extending to the next line to get the crlf is Here are some sample definitions followed by anunwieldy to use in your code. The fourth example of their use on the next line:solution is both the easiest to type and the mostefficient. REQUIRE "<><>" DELIHITERSj

You may also want to define a number of theother commonly used control characters:

DEFINE upto = <STEP 1 UNTIL,!FOR i upto 18 DO . . ..j

REQUIRE *<><>" DELIHITERSjD E F I N E f f r <(‘14BNULL)>,

i f I <(‘12BNULL)>,cr = <(‘lSUNULL)>,

t a b I <(‘llBNULL)>,c t I D I <‘17>;

The characters which will be used as argumentsin the PRINT statement must be forced to bestrings. If ff - ~‘14~ were used; then PRINT(ff)would print the number 12 (which is ‘14) ratherthan to print a formfeed because PRINT wouldtreat the ‘14 as an integer. For all the otherplaces that you can use these single characterdefinitions, they will work correctly whetherdefined as strings or integers, e.g.,

IF char = ctiD THEN . . . .

as well as

IF char IC ff THEN . . . .

Note that string constants like ‘15&‘12 and‘14&NULL do not ordinarily need par.enthesitingbut (‘15&‘12) and (‘14&NULL) were used above..This is a little trick to compile more efficientcode: The compiler will not ordinarily recognizethese as string constants when they appear in

the middle of a concatenated string, e.g.,

I . . . . iinml... “8’ 158’ 128”. , . . I inr2.. . ”

but with the proper parenthesizing

” . . . . iinal,.. “6(‘158’12)8”....iino2...”

DEFINE ! I <COHHENT>tici+l; ! increment i h e r o ;

D E F I N E forwrr I <UHILE TRUE,;forovw DO . . ..I

DEFINE l I f = <ELSE IF>;IF . . . THEN . . . .

EIF . . . . THEN .,..EIF .a.. THEN l ...;

Macros may also have parameters:

D E F I N E rppond(x,y) = <xex(Ly>iIF LENGTH (L) THEN apprnd(t,LDP(s))~

D E F I N E inch) s <hcn+l)>,dFc(n) I xhtn-l)>;

I F inc(ptr) s maxsize THEN . . . . .C D H H E N T uatch that you don’t forget

nerdrd parrnthmses hrrei

DEFINE ctr i (n) = <(“n”-‘l88)>,IF char s ctri(D) THEN abortPrInt;

As we saw in some of the sample macros, themacro does not need to be a complete statement, sexpression, etc. It can be just a fragment.Whether or not you want to use macros like thisis a matter of personal taste. However, it isquite clear that something like the following’ issimply terrible code although syntacticallycorrect (and rumored to have actually occurredin a program):

D E F I N E printor = <PRINTb;pr In ter “Hi thorr. “I i

the compiler will treat the crlf as a stringconstant at compile time and not need to do aconcatenation on ‘15 and ‘12 every time atruntime.

which expands to

PRINT(“Hi thrro.“);

Another very common use of macros is to“personali_ze” the Sail language slightly. Usuallymacros of this sort are used either to saverepetitive-typing of long sequences or to makethe code where they are used clearer. (Becareful--this can be carried overboard.)

On the other hand, those who completely shunmacros are erring in the other direction. One ofthe best coding practices in Sail is to DEFINE allconstant parameters such as array bounds.

I 26

Page 33: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL . String Scanning

SECTION 4

St ring Scanning

We have not yet covered Input/Output which isone of the most important topics. Before we dothat, however, we will cover the SCAN functionfor reading strings. SCAN which reads existingstrings is very similar to INPUT which is used toread in text from a file.

Both SCAN and INPUT use break tables. Whenyou are reading, you could of course read theentire file in at once but this is not what youusually want even if the file would all fit (and

’ with the case of SCAN for strings it would bepointless). A break table is used to 1). set up alist of characters which when read will terminatethe scan, 2) set up characters which are to beomitted from the resulting string, and 3) giveinstructions for what to do with the breakcharacter that terminated the scan (append it tothe result string, throw it away, leave it at thenew beginning of the old string, etc.). During thecourse of a program, you will want to scanstrjngs in different ways, for example: scan andbreak on a non-digit to check that the stringcontains only digits, scan and break on linefeed(If) so that you get one line of text at a, time,scan and omit all spaces so that you have acompact string, etc. For each of these purposes(which will h ave different break characters, omitcharacters, disposition of the break character,and setting of certain other modes available),you will need a different break table. You areallowed to set up as many as 54 different breaktables in a program. These are set up with aSETBREAK command.

A break table is referred to by its number (1 to54). The GETBREAK procedure is used to getthe number of the next free table and thenumber is stored in an integer variable.GETBREAK i s a r e l a t i v e l y n e w f e a t u r e .Previously, programmers had to keep track ofthe free numbers themselves. GETBREAK ishighly recommended especially if you will beinterfacing your program with another programwhich is also -assigning table numbers and mayuse the s a m e number for a different table.GETBREAK will know about all the table numbersin use. You assign this number to a break tableby giving it as the first argument to the

SETBREAK function. You can also u s eRELBREAK(tabiew) to release a table number forreassignment when you no longer need thatbreak table.

SETBREAK (tablol, “break-charac tow"“omit -charactors”, “modes”

where the first argument is an integer and the“‘3 around the other arguments here are astandard way of indicating, in a sampleprocedure call, that the argument expected .is astring. For example:

REQUIRE '<><>" DELIHITERS;D E F I N E i f = <'12>, cr = <'15>, f f = <‘14>;I N T E G E R IineBr, nonDiqitBr, nospaces;

SETBREAK(iineBrcGETBREAK, i f , ff8cr, " i n s " ) )SETBREAK(noSpacrs~CETBRERK, N U L L , " ", "ina")iSETBREAKhonDiqttBr~GETBRERK, “8123456789”,

NULL, "xns");

The characters in the “break-characters” stringwill be used as the break characters to terminatethe SCAN or INPUT. SCAN and INPUT return thatportion of the initial string up to the firstoccurrence of one of the break-characters.

The characters in the “omit-characters” stringwill be omitted from the string returned.

The “modes” establish what is to be done withthe break character that terminated the SCAN orINPUT. Any combination of the following modescan be given by putting the mode letterstogether in a string constant:

CHARACTERS USED FOR BREAK CHARACTERS:

“I” (inclusion) The characters in the break-characters string are the set of characterswhich will terminate the SCAN or INPUT.

“X” (eXclusion) Any character except those inthe break-characters string will terminatethe SCAN or INPUT, e.g., to break on any digituse:

INTEGER tbi;SETBREAK(tbicGETBREAK,"8123456789",NULL,"i"~;

and to break on any non-digit use:

INTEGER tbiiSETBREAK(tbi~GETBRERK,"8123456789","",~x"~i

27.

Page 34: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

String Scanning SAIL TUTORIAL

where NULL or “” can be used to indicate nocharacters are being given for that argument.

DISPOSITION OF BREAK CHARACTER:

“S” (skip) The character which actuallyterminates the SCAN or INPUT will be“skipped” and thus will not appear in theresult string returned nor will it be still inthe original string.

“A” (append) The terminating character will beappended to the end of the result string.

“R” (retain) The terminating character will beretained in its position in the original stringso that it will be the first character read by

. the next SCAN or INPUT.

OTHER MISCELLANEOUS MODES:

“K” This mode will convert characters to be putin the result string to uppercase.

“N” This mode will discard SOS line numbers ifany and should probably be used for breaktables which will be scanning text from a file.This is a very good Sail coding practice evenif it seems highly unlikely that an SOS file

_ will ever be given to your’ program.

“ r e s u l t - s t r i n g ” c SCANWsourco”, tablea, ebrchar);

In these sample formats, the ““‘s mean theargument is a string and the 4) prefix means thatthe argument is an argument by reference.

When you call the SCAN function, you give it asarguments 1) the source string, 2) the breaktable number and 3) the name of an INTEGERvariable where it will put a copy of thecharacter that terminated the scan. Both thesource string and the break character integerare reference parameters to the SCANprocedure and will have new ,values when theprocedure is finished. The following exampleillustrates the use of the SCAN procedure andalso shows how the “S”, “A”, and “R” modesaffect the resulting strings with the dispositionof the break character.

INTEGER sk ipBr, l ppendBr, retainBr, brcharlS T R I N G rosult, sk ipStr, appondst-r, retainStr;

SETBREAK (sk ipBreGETBRERK, ‘r”,NULL, “s”) 1SETBREAK(apprndBrcGETBRERK,“t”,NULL,”r”);

SEfBREAK(retainBrcGETBRERK,“*“,NULL,”r”);

skipStrcappendStrcrotainStrc*firstmocond”;resul t l SCAN(sk ipStr, sk ipBr, brchar);COlltlENT EOU(rrsul t,*f irst”) AN0

EQU(sk ipStr,“socond”) 1

resu I t l SCAN (appends tr, appondBr , brchar) ;COUllENT EQU(resul t,“f irstz”) RN0

EQU(appendStr,“second”);

r e s u l t c SCAN(rotainStr, rotainbr, b r c h a r ) ;COtlllENT EQU(rosul t,“f irst”) AND

EQU(rrtainStr,“esocond”)l

COWlENT in each casa a b o v e b r c h r r I *$”after the SCAN;

Now weabove:

can look again at the break tables given

This break table will return a single line up tothe If. Avy carr iage returns or formfeeds(usually used as page marks) will be omitted andthe break character is also omitted (skipped) sothat just the text of the line will be returned inthe result string. The more conventional way toread line by line where the line terminators arepreserved is

SETBREAK (readL ino, I f , NULL, * i na” 1;

Note here that it is extremely important that Ifrather than cr be used as the break charactersince it follows the cr in the actual text.Otherwise, you’ll end up with strings like

t e x t o f I ine<cr><lf>text o f Iine<cr>< I f >

instead of

t r x t o f Itex t o f I

ino*cr><lf>ine<cr><lf>

After the SCAN, the brchar variable can beeither the break character that terminated thescan (If in this case) or 0 if no break characterwas encountered and the scan terminated byreaching the end of the source string.

00 procassl i no (SCAN (str, roadL ine,brchar))UNTIL NOT brchar;

28

Page 35: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL String Scanning

This code would be used if you had a long multi-lined text stored in a string and wanted toprocess it one line at a time with PROCEDUREprocossl i ne.

nunb c fNTSCRN(reply,brchar);IF brchar THEN error;

This break table could be used to check if anumber input from the user contains only digits.

UHILE true 0 0BEGINPRINT(“Type a numborr “1;replyeINCHUL; ! INTTY for TENEX!SCfIN(rrply,nonOigitBr,brchar~~IF brchar THEN

PRINT(brchar8NULL,” i s n o t a diqit.“,crlf)ELSE OONE;

. END;

Here the value of brchar (converted to a stringconstant since the integer character code willprobably be meaningless to the user) wasprinted out to show the user the offendingcharacter. There are many other uses of thebrchar variable particularly if a number of

characters are specified in the break-charactersstring of the break table and different actionsare to be taken depending on which one actuallywas encountered.

SETBREAK (noSpacrs,NULL,” “, ” ina”) i

Here there are no break-characters but theomit-character(s) will be taken care of by thescan, ea.,

strc’a b c d’lresul tcSCRN(str,noSpaces, brchar) ;

will return “abed” as the result string.

If you need to scan a number which is stored ina string, two special scanning functions, INTSCANand REALSCAN, have been set up which do notrequire break tables but have the appropriatecode built in:

IptegerVar c INTSCAN(“nunbor-strinq”,(brchar);realVar l RERLSCRN(“nuinbor-string”,ebrchar)l

where the integer or real number read isreturned; and the string argument after the callcontains the remainder of the string with thenumber removed. We could use INTSCAN tocheck if ii str3ng input from a user is really Iproper number.

PRIlf(“Type t h e nunbert “1;reply + INCHIJL; ! INTTY for, TENEXj

29

Page 36: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Input/Output SAIL TUTORIAL

SECTION 5 are in @RAISE mode in TENEX) will convert thecharacters ‘173 to ‘176 to altmodes.

Input /Out put

5.2 Notes on Terminal I/O for TENEX SailOnly

5.1 Simple Terminal I/O

We have been doing input/output (I/O) from thecontrolling terminal with INCHWL (or INTTY forTENEX) and PRINT. A number of other TeletypeI/O routines are listed in the Sail manual inSections 7.5 and 12.4 but they are less oftenused. Also any of the file I/O routines which willbe covered next can be used with the TTY:specified in place of a file. Before we cover filef/O, a few comments are needed on the usualterminal input and output.

The INCHWL (INTTY) that we have used is like anINPUT ‘with the source of input prespecified asthe terminal and the break characters given asthe line terminators. Should you ever want tolook at the break character which terminated anINCHWL or INTTY, it will be in a special variablecalled !SKIP! which the Sail runtimes use for awide variety of purposes. INTTY will input amaximum of 200 characters. If the INTTY wasterminated for reaching the maximum limit then!SKIP! will be set to -1. Since this variable isdeclared in the runtime package rather than inyour program, if you are going to be looking atit, you will* need to declare it also, but as anEXTERNAL, to tell the compiler that you want theruntime variable.

EXTERNAL INTEGER ISKIP!;PRINT(“Number f o l l o w e d b y <CR> o r <RL’T,r “11rep IytINCtlUL; ! INTTY for TENEXlI F !SKIP! I cr T H E N .,....

E L S E I F !SKIP! = a l t T H E N . . . . .

Altmode (escape, enter, etc.) is one of thecharacters which is different in the differentcharacter sets. The standard for most of theworld including both TOPS-10 and TENEX is tohave aitmode as ‘33. At some point in the pastTOPS-10 used ‘176. This is now obsolete;however, the SU-AI character set follows thisconvention but does so incorrectly. It uses ‘175as altmode. This will present a problem forprograms transported among sites. It alsopartially explains why most systems when theybelieve they are dealing with a MODEL-33Teletype or other uppercase only terminal (or

If you are programming in TENEX Sail, you shoulduse INTTY in preference to the various teletyperoutines listed in the manual. TENEX does nothave a line editor built in. You can get theeffect of a line editor by using INTTY whichallows the user to edit his/her typing with theusual tA, ?R, TX, etc. up until the point where theline terminator is typed. If you use INCHWL, theediting characters are only DEL to rubout onecharacter and tU to start over. Efforts havebeen made in TENEX Sail to provide line-editingwhere needed in the various I/O routines whenaccessing the controlling terminal. Completedetails are contained in Section 12 of the Sailmanual.

TENEX also has a non-standard use of thecharacter set which can occasionally causeproblems. The original design of TENEX calledfor replacing crlf sequences with the ‘37character fool). This has since been largelyabandoned and most TENEX programs will notoutput tex t w i th eel’s bu t ra ther use thestandard crlf. Eel’s are still used by the TENEXsystem itself. The Sail input routines INPUT,INTTY, etc. convert eol’s to crlf sequences. Seethe Sail manual for details, if necessary; but ingeneral, the only time that you should ever havea problem is if you input from the terminal withsome routine that inputs a single character at atime, e.g., CHARIN. In these cases you will needto remember that end-of-line will be signalled byan eol rather than a cr. The user of course .types a cr but TENEX converts to eol; and theSail single character input functions do notreconvert. to cr as the other Sail input functionsdo.

5.3 Setting Up a Channel for I/O

Now.we need I/O for files. The input and outputoperations to files are much like what we haved o n e f o r t h e t e r m i n a l . CPRINT w i l l wr i tearguments to a file as PRINT writes them to theterminal. It is also possible with the SETPRINT

30

Page 37: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL _TUTORIAL Input /Out put

.command to specify that you would rather sendyour PRINT’s to a file (or to the terminal AND anamed file). See the manual for details.

There are a number of other functions availablefor I/O in addition to INPUT and CPRINT, but theyall have one common feature that we have notseen before. Each requires as first argument achannel number. The CPU performs I/O throughinput/output channels. Any device (TTY:, LPT:,DTA:, DSK:, etc.) can be at the other end of thechannel. Note that by opening the controllingterminal (TTY:) on a channel, you can use any ofthe input/output routines available. In the caseof directory devices such as DSK: and DTA:, afilename is also necessary to set up the I/O.There are several steps in the process ofestablishing the source/destination of I/O on anumbered channel and getting it ready for theactual transfer. This is the area in -which TOPS-10 and TENEX Sail have the most differences dueto the differences in the two operating systems.Therefore separate sections will be includedhere for TOPS-10 and TENEX Sail and you should

. read only the one relevant for you.

5.3.1 T O P S - 1 0 S a i l C h a n n e l a n d F i l eHandling

. Routines for opening and closing files in TOPS-10Sail correspond closely to the UlJO’s available inthe TOPS-10 system. The main routines are:

QETCHFIN OPEN LOOKUP ENTER RELERSE

Additional routines (not discussed here) are:

10 OPEN (or INIT) UUO. OPEN has eightparameters. Some of these refer to parametersthat the OPEN UUO will need; other parametersspecify the number of buffers desired, withother UUO’s called by OPEN to set up thisbuffering; still other parameters are internal Sailbookkeeping parameters. .

The parameters to OPEN are:

1) CHANNEL: channel number,t yp ica l l y the number re tu rned byGETCHAN.

2) “DEVICE”: a string argument thatis the name of the device that is desired,such as “DSK” for the disk or “TTY” forthe controlling terminal.

3) MODE: a number indicating themode of data transfer. Reasonablevalues are: 0 for characters and stringsand ‘14 for words and arrays of words.Mode ‘17 for dump mode transfers ofarrays is sometimes used but is notdiscussed here.

4) INBUFS: the number of inputbuffers that are to be set up.

5) OUTBUFS: the number of outputbuffers.

6) COUNT: a reference parameterspecifying the maximum number ofcharacters for the INPUT function.

USE11 USETO HTAPE CLOSE CLOSIN CLOSO

5.3.1.1 Device Opening

than * GETCHAN;

GETCHAN obtains the number of a free channel.On a- TOPS-10 system, channel numbers are 0through ‘17. GETCHAN finds the number of’ achannel not currently in use by Sail and returnsthat number. The. user is advised to useGETCHAN to obtain a channel number rather thanusing absolute channel numbers.

- -

OPENkhan, ‘dovica”, moda, ihbufs,o u t b u f s , m o u n t , U b r c h a r , QOOf)j

The OPEN procedure corresponds to the TOPS-

7) BRCHAR: a reference parameterin which the character on which INPUTbroke will be saved. *

8) EOF: a reference parameterwhich is set to TRUE when the file is atthe end. ,

The CHANNEL, “DEVICE”, and MODE parametersare passed to the OPEN UUO; INBUFS andOUTBUFS tell the Sail runtime system how manybuffers should be set up for data transfers; andthe COUNT, BRCHAR and EOF variables are cellsthat are used by Sail bookkeeping. N.B.: many ofthe above parameters have additional meaningsas given in the Sail manual. The examples in thissection are intended to demonstrate how to dosimple things.

31

Page 38: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Input/Output

RELEASE (than) ; BEGININTEGER INCHAN, INBRCHRR, INEOF;

The RELEASE function, which takes the channelnumber as an argument, finishes all the input andoutput and makes the channel rvailable for otheruse.

O P E N (INCHAN c G E T C H A N , “ T T Y ” , 8, 2, 8, 288,INBRCHAR, INEOF 1;

COilHENT

The following routine illustrates how to open adevice (in this case, the device is only theteletype) and output to that device. The.CPRlNTfunction, which is like PRINT except that itsoutput goes to an arbitrary channel destination,is used.

BEG IN

Oprns t h e T T Y i n mode 0 (charactors), u i t h2 input buffers, 8 o u t p u t buffers. Rt m o s t288 charactors wi l l be road in u i th l a c hI N P U T statomont, a n d t h e b r e a k c h a r a c t e ru i i i bo p u t i n t o v a r i a b l e I N B R C H R R . Theand-of-fit. uill bo signaliod b y I N E O Fb r i n g sit t o TRUE at tar some cai I to ani n p u t f u n c t i o n h a s f o u n d t h a t thorn i s n omore d a t a i n t h o f i la;

INTEGER OUTCHAN;

OPEN(OUTCHAN c GETCHAN,“TTY”,0,0,2,8,8,8))COtltlENT

(1) Obtain a channoi number , usingCETCHRN, and saw i t in var iable OUTCHAN.

(2) S p e c i f y devicr T T Y , i n m o d e 8 ,u i t h 0 i n p u t a n d 2 o u t p u t b u f f r r s .

(3) Iqnoro thm COUNT, BRCHAR, and EOFv a r i a b l e s , w h i c h arm t y p i c a l l y n o t noodad ift h e f i l e i s o n l y f o r o u t p u t . ;

.

WHILE NOT INEOF 00BEGIN

END; ’ * lcoda t o d o inpui - - SW bolou. . . .

RELEASE (INCHAN) j

ENOj

5.3.2 Reading and Writing Disk FilesCPR INT (OUTCHAN, “Hessag~ for OUTCHRNII

1;COilRENT A c t u a l d a t a t r a n s f o r . ;

-RECERSE (OUTCHAN) iCOMENT Cioso c h a n n o i ;END;

Most input and output will probably be done tothe disk. The disk (and, typically, the DECtape)are directory devices, which means that logicallyseparate files are associated with the device.When using a directory device, it is necessary toassociate a fib name with the channel that isopen to the device.

The following example illustrates how to readtext from a device, again using the teletype asthe device.

LOOKUPXHAN, “FILENFME”, QFLAG) jENTER KHAN, “F ILENRtlE * , QFLAG 1;

File names are associated with channels by threefunctions: LOOKUP, ENTER, and RENAME. We willdiscuss LOOKUP and ENTER here. Both LOOKUPand ENTER take three arguments: a channelnumber, such as returned by GETCHAN, whichhas already been opened; a text string which isthe name of the file, using the file nameconventions of the operating system; and areference flag that will be set to FALSE if theoperation is successful, or TRUE otherwise. (TheTRUE value is a bit pattern indicating the exactcause of failure, but we will not be concernedwith that here.) There are three permutations ofLOOKUP and ENTER that are useful:

32

SAIL TUTORIAL

1) LOOKUP alone: this is done whenyou want to read an already existing file.

2) ENTER alone: this is done when

.

Page 39: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL Input/Output

you want to write a file. If a file alreadyexists with the selected name, then a newone is created, and upon closing of thefile, the old version is deleted altogether.This is the standard way to write a file.

3) A LOOKUP followed by an ENTERusing the same name: this is the standardway to read and write an alreadyexisting file.

The following program will read an alreadyexisting text file, (e.g., with the INPUT, REALIN,and INTIN functions, which scan ASCII text.) Notethat the LOOKUP function is used to see if thefile is there, obtaining the name of the file fromthe user. See below for details about thefunctions that are used for the actual reading ofthe data in the file.

BEGINI N T E G E R INCHAN, INBRCHRR, INEOF, FLAG) .STRING F ILENRflE;

O P E N (INCHAN * GETCHRN, “DSK”, 8, 2, 8, 288,INBRCHRR, INEOFj;

UHILE TRUE 00BEGIN- .

PRINT(“Input fiio naaw *“I;LOOKUP(INCHRN, FILENRtlE + INCHWL, FLRGjjIF FLRG THEN OONE ELSE

PRINT(“Cannot find file “, F I L E N A H E ,* t r y again.

“)IENO;

UHILE NOT JNEOF 004EGIN “INPUT”

a... tom boiocc f o r wading charactors...EN0 “INPUT”;

RELERSE (INCHFIN) ;END;

The following program opens a file for writingcharacters.

BEGIN1,NTEGER OUTCHRN, FLcIGjSTR IHG -F ILENME j

O P E N tOUTCH?‘!N + GETCHRN, “DSK”, 0 , 8, 2, 0,

I UHILE TRUE 00BEG IN

PRlNf(“Output f I lo nan t”) j

ENTER(OUTCHAN, FILENAHE F INCHUL, FLAG) jIF NOT FLRG THEN DONE ELSE

PRINT(“Cannot wcito f i i r *, FILENME,” t r y a g a i n .

“)IENDj

,., now witr the text to OUTCHAN . . .

RELERSE (OUTCHRN) jENDj

5.3.2.1 Reading and Writing Full Words

Reading 36-bit POP10 words, using WORDIN andARRYIN, and writing words using WORDOUT andARRYOUT, is accomplished by opening the fileusing a binary mode such as ‘14. We recommendthe use of binary mode, with 2 or more inputand/or output buffers selected in the call to theOPEN function. There are other modes available,such as mode ‘17 for dump mode transfers; seethe timesharing manual for the operating system.

5.3.2.2 Other Input /Output Facilities

Files can be renamed using the RENAME function.Some random input and output is offered by theUSETI and USETO functions, but random input. andoutput produces strange results in TOPS-10 Sail.Best results are obtained by using USETI andUSETO and reading or writing 128-word arraysto the disk with ARRYIN and ARRYOUT.

Magnetic tape operations are performed with theMTAPE function.

See the Sail manual (Sec. 7) for more detailsabout these functions. In particular, we stressthat we have not covered all the capabilities ofthe functions that we have discussed.

5.3.3 TENEX Sail Channel, and File Handling

TENEX Sail has included all of the TOPS-l 0 Sailfunctions described in Section 7.2 of the Sailmanual for reasons of compatibjlity and hasimplemented them suitably to work on TENEX.Descriptions of how these functions actuallywork in TENEX are given in Section 12.2 of themanual. However, they are less efficient thanthe new set of specifically TENEX routines which

33

Page 40: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

input/Output SAIL TUTORIAL

have been added to TENEX Sail SO you probably that has not been used before. N does not meanshould skip these sections of the manual. The a new version as one might have expected. Innew TENEX routines are also greatly simplified general, the i/O routines use the relevant JSYS’sfor the user so that a number of the steps to directly and thus include all of the design errorsestablishing the I/O are done transparently. and bugs in the JSYS’s themselves.

Basical ly, you only need to know threecommands: 1) OPENFILE which establishes a fileon a channel, 2) SETINPUT which establishescertain parameters for the subsequent inputsfrom the file, and 3) CFILE which closes the fileand releases the channel when you are finished.

chard l OPENFILE (“f i Ienamr”, “modes”)

The OPENFILE function takes 2 arguments: astring containing the device and/or filename anda string constant containing a list of the desiredmodes. OPENFILE returns an integer which is thechannel number to be used in all subsequentinputs or outputs. If you give NULL as thef i lename then OPENFILE goes to the user’sterminal to get the name. (Be sure if you do thisthat you first PRINT a prompt to theterminal.) The modes are listed in the Sailmanual (Sec. 12.3) but not all of those listed arecommonly used. The following are the ones thatyou will usually give:

I N T E G E R infilr, outfile, dofaultsFllo;PRINT(“Input f i Ier “IfinFi l o c OPENFILE(NULL,“rc”);PRINT(“Output f i Ie : “I;ou tF i I e + OPENF ILE (NULL, “MC”) ;d e f a u l t s f i l e c

OPENFILE (“user-defaul tt. tmp”, “u”);

We now have files “open” on 3 channels--one forreading and two for writing. We have thechannel numbers stored in infile, outFile, anddefaultsFile so that we can refer to theappropriate channel for each input or output.Next we need to do a SETINPUT on the channelopen for input (reading).

SETINPUT khan#, count , ebrchar , eeof I

There are four arguments:

1) The channel number.

2) An integer number which is the- R or W or A for Read, Write, or Append . maximum number of characters to be

depending on what you intend to do read in any input operation (the default ifwith the file. no SETINPUT is done is 200).

if you are allowing multi-filespecifications, e.g., data.*;* .

if the user is giving thefilename from the terminal, C modewill prompt for [confirm].

if the user is giving thef i lename and an error occurs(typically when the wrong filenameis typed), the E mode returnscontrol to your program. If, E is notspecified the user is automaticallyasked to try again.

3) A reference integer variablewhere the input function will put thebreak character.

4) A reference integer variablewhere the input function will. put true orfalse for whether or not the end-of-filewas reached (or the error number if anerror was encountered while reading).

So here we need:

INTEGER inflleBrChr, inflleEoffSETINPUT (infi Ie, 2 8 0 , i n f i I e b r c h r , i n f i leEof);

Modes 0 and N for O!d or New File are alsoallowed but probably shouldn’t be used. Theyare misleading. The defaults, e.g. without either0 or N specified, are the usual conditions (readan old version and write a new version). The 0and N options are peculiar. For -example, “NW”means that you must specify a completely newfilename for the file to be written, e.g., a name

NOW we do the relevant input/output operationsand when finished:

CFILE(inf i le);CFILEfoutf i Ie);CFILEfdefaul tsFi IeI l

A simple example of the use of these routinesfor opening a file and outputting to it is:

Page 41: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL -TUTORIAL

INTEGER outfile;PRINT(“Type f i Iename f o r o u t p u t : “11outf i IeeOPENFILE(NULL,“wc”);

, CPRINT(outf ile, “message...“)~CFILEfoutf l le);

where CPRINT is like PRINT except for theadditional first argument which is the channelnumber.

The OPENFILE, SETINPUT, and CFILE commands. will handle most situations. If you have unusual

requirements or like to get really fancy thenthere are many variations of file handlingavailable. A few of the more commonly used willbe covered in the next section; but do not readthis section until you have tried the regularroutines and need to do more (if ever). On firstreading, you should now skip to Section 5.4.

5.3.4 Advanced ‘TENEX Sail Channel andFile Handling

If you want to use multiple file designators with&, you should give “s” as one of the options toOPENFILE. Then YOU will need to use INDEXFILEto- sequence thrbugh the multiple files. Thesyntax is

found!another!f I Ie c INDEXFILE(chan8)

.

where found!another!f I le is a boolean variable.INDEXFILE accomplishes two things. First, ifthere is another file in the sequence, it isproperly initialized on the channel; and second,INDEXFILE returns TRUE to indicate that it hasgotten another file. Note . that the originalOPENFILE gets the first file in the sequence onthe channel so that you don’t use the INDEXFILEuntil you have finished processing the first fileand are ready for the second. This is doneconveniently with a DO...UNTIL where the test isnot made until after the first time through theloop; e.g.,

wl t IFi l e t c OPENFILE(“data.*“,“r*“);DO

BEGIN. ..<lnput and process current file,...END -UNTIL NOT 1NOEXFlLEbultlFlles)l

Another available option to the OPENFILE routinewhich you should consider using is the “E” optionfor error handling. If you specify this option and

.

Input/Output

the user gives an incorrect filename thenOPENFILE will return -1 rather than a channelnumber and the TENEX error number will bereturned in !SKIP!. Remember to declareEXTERNAL INTEGER !SKIP! if you are going to belooking at it. Handling the errors yourself isoften a aood idea. TENEX is unmerciful. If theuser gives a bad filename, it will ask again andkeep on asking forever even when it is obviousafter a certain number of tries that there .is agenuine problem that needs to be resolved.

Another use for the “E” mode is to offer the userthe option of typing a bare <CR> to get a defaultfile. If the “E” mode has been specified and theuser types a carriage-return for the filenamethen we know that the error number returned in!SKIP! will be the number (listed in the JSYSmanual) for “Null filename not allowed.” so wecan intercept this error and simply do anotherOPENFILE with the default filename, e.g.,

EXTERNRL INTEGER ISKIP ! 1

outfllec-11W I L E outflle 8 - 1 D O

BEGINPRINTt”FI lename (<CR> f o r T T Y : ) b”);outfilecOPENFILE(NULL,“~e”IfI F Iskip! = ‘660115 THEN

outf lIecOPENFILE(“TTY:“,“w”);END1

The GTJFNL and GTJFN routines are useful if youneed more options than are provided in theOPENFILE routine, but neither of these actuallyopens the file so you will need an OPENF orOPENFILE after the GTJFNL or GTJFN unless yourpurpose in using the GTJFN is specifically thatyou do not want to open the file. The GTJFNLroutine is actually the long form of the GTJFNJSYS; and the GTJFN routine is the short form ofthe GTJFN JSYS. See the TENEX JSYS manual fordetails.

Another use of GTJFNL is to combine filenamespecification f rom a s t r ing w i th f i l enamespecification from the user. This is a simple wayto preprocess the filename from the user, i.e., tocheck if it is really a “?” rather than a filename.First, you need to declare !SKIP! and ask the userfor a filename:

EXTERNRL INTEGER ! SK IP ! ;WILE TRUE 00

BEGIN ‘getfllenam”PRINT(“Type I n p u t f I loname o r 3 t “I;

35

Page 42: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Input/Output

Next do a regular INTTY to get the reply into astring:

L l INTTYl

Then you process the string in any way that youchoose, e.g., check if it is a “?” or some otherspecial keyword:

IF s = “?” THEN BEGINgiveholp;CONTINUE “getfiloname”l.END1

If you decide it is a proper filename and want touse it then you give that string (with the breakcharacter from INTTY which will be in !SKIP!appended back on to the end of the string) tothe GTJFNL.

chanX c GTJFNL fsB!SKIP!, ‘160080000088,‘808106800181, NULL, NULL, NULL,NULL, NULL, NULL);

If the string ended in altmode meaning that theuser wanted filename recognition then that willbe done; and if the string is not enough forrecognition and more typein is needed then theGTJFNL will ring the bell and go back to theuse’r’s terminal without the user knowing thatany processing has gone on in the meantime, i.e.,to the user it looks exactly like the ordinaryOPENFILE. Thus the GTJFNL goes first to thejtring ‘that you give it but can then go to theterminal if more is needed.

After the GTJFNL don’t forget that you still needto OPENF the file. For reading a disk file, .

OPENF khanX, ‘448808280888) ;

is a reasonable default, and for writing:

OPENF khan8, ‘4488001880081;

The arguments to GTJFNL are:

chanll l GTJFNLf”f i lename”, f l a g s , j f n j f n ,“ d e v ” , “ d i r ” , “ n a m e ” , “ext”,“ p r o t e c t i o n ” , “acct”);

where the-flag specification is made by lookingup the FLAGS for the GTJFN JSYS in the JSYSmanual and figuring out which bits you wantturned on and which off. The 36-bit resultingword can be given here in its octalrepresentation. ‘160000000000 means bits 2(old file only), 3 (give messages) and 4 (require

36

SAIL TUTORIAL

confirm) are turned on. Remember that the bitsstart with Bit 0 on the left. The jfnjfn willprobably always be ‘000100000101. Thisargument is for the input and output devices tobe used if the string needs to be supplemented.Here the controlling terminal is used for both.Devices on the system have an octal numberassociated with them. The controlling terminal asinput device is ‘100 and as output is ‘101. Formost purposes you can refer to the terminal byits “name” which is TTY: but here the number isrequired. The input and output devices aregiven in half word format which means that ‘100is in the left and ‘101 in the right half of theword with the appropriate O’s filled out for therest.

The ’ next six arguments to GTJFNL are fordefaults if you want to give them for: device,directory, file name, file extension, fileprotection, and file account. If no default isgiven for a field then the standard default (ifany) is used, e.g., DSK: for device and ConnectedDirectory for directory. This is another reasonwhy you may choose GTJFNL over OPENFILE forgetting a filename. In this way, you can set updefaults for the filename or extension. You canalso use GTJFNL to simulate a directory searchpath. For example, the EXEC when accepting thename of a program to be run follows a searchpath to locate the file. First it looks on<SUBSYS> for a file of that name with a .SAVextension. Next it looks on the connecteddirectory and finally on the login directory. Ifyou have an analogous situation, you can use ahierarchical series o f GTJFNL’s w i t h t h eappropriate defaults specified:

EXTERNFlL INTEGER !SKIP!;INTEGER logdir,condir,ttynolSTRING logdirstr,condirrtr;

GJINFflogdir,condir,ttyno);COtltlENT p u t s t h e d i r e c t o r y n u m b e r s f o r login

and connected d i rectory and the ttyX ini ts reference integer arguments1

logdirstt-DlRSTflogdirI;condirrtrcDIRST(condirIlCDtiilENT returns a s t r i n g f o r t h e n a m e

corresponding to directory# lUHILE true DO

BEGIN “ge tname”PRINT(“Type the name of the program: “ I ;IF EDU (upper (NAtlE c INTTYI, “EXEC”) T H E N

BEGINnamec”BYSTEtl>EXEC.SFlV”;DONE “getname”;

END;IF name = “?” THEN

Page 43: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL-TUTORIAL

BEGINg i v e h e l p ;CONTINUE “gotnamo”l

END:name&tame8 ! SK IP ! l

CDtlRENT put the brrak char back o n ;DEFiNE f l a g I <‘100000088080>,j f n j f n = <‘1000@018l>rI F (tempChaneGTJFNLfname,flag,jfnjfn,NULL,

“SUBSYS”,NULL,“SRV”,NULL,NULL)I I -1. THEN

IF ftempChaneGTJFNL (name, f lag,jfn/fn,NULL,condirstr,NULL,“SAV”,NULL,NULL)) = -1 THEN

IF (tempChancGTJFNL (name, f lag,jfnjfn,NULL, logdirstr,NULL,“SAV”,NULL,NULL)I I -1 T H E N

BEGINPRINtf” ?“,crl f);CONTINUE “ge tname”!

END;COWlENT t r y oath drfault a n d i f n o t f o u n dthen t r y n e x t unt i I nono are f o u n d thanp r i n t ? a n d t r y a g a i n ;

n a m e c JFNS (tempChan, 8);COlltlENT g e t s n a m e o f f i l e o n t h a n - - 8

means in normal format;CFILE(tompChan);COtBlENT channrl not opened but d o e s

need to ‘be ro IoasodtDONE “go tname”;

tEND;

In this case, we did not want to open a channelat all since we will not be either reading orwriting the .SAV file. At the end of the abovecode, the complete filename is stored in STRINGname. We might wish to run the program with theRUNPRG routine. GTJFN and GTJFNL are oftenused for the purpose of establishing filenameseven though they are not to be opened at themoment. However, the Sail channel does need tobe released afterwards.

Some of the other JSYS’s which have beenimplemented in the runtime package were usedin this program: GJINF, DIRST;and JFNS. JFNS inparticular is very useful. It returns a stringwhich is the name of the file open on the

. channel. You might need this name to record orto print on the terminal or because you will beoutputting to a new version of the input filewhich you can’t do unless you know its name.-

These and a number of other routines arecovered in Section 12 of the Sail manual. Youshould probably glance through and see what isthere. Many of these commands corresponddirectly to utility JSYS’s available in TENEX and

Input/Output

will be difficult to use if you are not familiar withthe JSYS’s and the JSYS manual.

5.4 input from a File

In this section, we will assume that you have afile opened for reading on some channel and areready to input. Also that you have appropriatelyestablished the end-of-file and break charactervariables to be used by the input routines andthe break table if needed.

Another function which can be used inconjunction with the various input functions isSETPL:

S E T P L (chanl, G I inrl, epagd, asosl)

This allows you to set up the three referenceinteger var iables I tne#, pagd, and SOS# to beassociated with the channel so that any inputfunction on the channel will update their values.The I inoX variable is incremented each time a ‘12(If) is input’ and the pagel variable is incremented(and I ino# reset to 0) each time a ‘14 (formfeed)is input. The last SOS line number input (if any)will be in the SOS# variable. The SETPL should begiven before the inputting begins.

The major input function for text is INPUT.

“resu I t ” c INPUT (chan#, tab I l #) ;

where you give as arguments the channelnumber and the break table number; and theresulting input string is returned. This is verysimilar to SCAN.

To input one line at a time from a file (whereinft Ie is the channel number and inf i IeEof is theend-of-file variable):

SETBRERK(rradLinoeGETBRERK,lf,NULL,”ina”~;00

BEGINSTRING I lno;lineeINPUT(lnfilr,raadLino~;. ..<procoss t h r Ilno>...END

UNTIL InflloEof;

If the INPUT function sets the eof variable toTRUE then’ either the end-of-f i le wasencountered or there was a read error of somesort.

37

Page 44: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Input/Output SAIL TUTORIAL

If the INPUT terminated because a breakcharacter was read then the break character willbe in the brchar variable. If brchar-0 then youhave to look at the eof variable also todetermine what happened: If eof=TRUE then thatwas what terminated the INPUT but if eof=FALSEand brchar=O then the INPUT was terminated byreaching the maximum count per input that wasspecified for the channel.

If you are inputting numbers from the channelthen

realVar c RERL IN khan#)inteqervar c INTIN khan#)

which are like REALSCAN and INTSCAN can beused. The brchar established for the channelwill be used rather than needing to give it as anargument as in the REALSCAN and INTSCAN.

INPUT is designed for files of text. Several otherinput functions are available for other sorts offiles.

Number c WOROIN (Chad)

will read in a 36-bit word from a binary formatfile. For details see the manual.

ARRYINkhanX, eloc, c o u n t ) charptr c RCHPTR (chadI

is used for filling arrays with data from binary. format files. Count is the number of 36-bit wordsto be read in from the file. They are placed inconsecutive locations starting with the locationspecified by IOC, e.g.,

returns the current position of the characterpointer. This is given as an integer representingthe number of characters (bytes) from the startof the file which is byte 0. You can reset thepointer by

INTEGER RRRRY numbs tlrmaxl;ARRYIN(dataFi Ie,numbttll,rax);

ARRYIN can only be used for INTEGER and REALarrays (not STRING arrays).

5.4.1 Addit ional TENEX Sail input Routines

Two extra input routines which are quite fasthave been added to TENEX Sail to utilize theavailable input JSYS’s.

c h a r e CHRRIN khanl)

inputs a single character which can be assignedto an integer variable. If the file is at the endthen CHARIN returns 0.

“ r e s u l t ” cSIN1 (chard, m a x l e n g t h , b r e a k - c h a r a c t e r )

does a very fast input of a string which isterminated by either reading naxlength charactersor encountering the break-character. Note thatt h e break-character here is not a referenceinteger where the break character is to bereturned; rather i t actual ly is the b reakcharacter to be used like the “break-characters”established in a break table except that only onecharacter can be specified. If the SINI terminatedfor reaching maxlength then !SKIP! - -1 else !SKIP!will contain the break character.

TENEX Sail also offers random I/O which is notavailable in TOPS-10 Sail. A file bytepointer ismaintained for each file and is initialized to pointat the beginning of the file which is byte 0.. Itsubsequently moves through the ’ file alwayspointing to the character where the next read orwrite will begin. In fact the same file may beread and written at the same time (assuming ithas been opened in the appropriate way). If thepointer could only move in this way then onlysequential I/O would be available. However, youcan reset the pointer to any random position inthe file and begin the read/write at that pointwhich is called random I/O.

.

SCHPTR khan#, newp tr )

If newptr is given’ as -set to the end-of-file.

1 then the pointer will be

There are many uses for random I/O. Forexample, you can store the help text for aprogram in a separate file and keep track of thebytepointer to the start of each individualmessage. Then when you want to print out oneof the messages, you can set the file pointer tothe start of the appropriate message and print itout.

RWDPTR AND SWDPTR are also available forrandom I/O with words (36-bit bytes) as theprimary unit rather than characters (70bit bytes).

38

Page 45: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL -TUTORIAL Input/Output

5.5 Output to a File

The CPRINT function is used for outputting totext f iids.

CPRINT (chard, l rgl, arg2, . . . . , argN)

CPRINT is just like PRINT except that the channelmust be given as the first argument.

F O R lo-1 STEP 1 UNTIL naxUorkers D OCPRINT(outf lie, nametil, ” *,

talarytil,crlf)f

Each subsequent argument is converted to astring if necessary and printed out to thechannel.

UORDOUf (chard, numbor)

writes a single 360bit word to the channel.

ARRYOUTkhanl, ‘eloc, c o u n t )

writes out an array by outputting count numberof consecutive words starting at location IOC.

RERL RRRRY resu I ts Ilr maxl l

I*

- ARRYOUT&esuI tFl Io,rosul tsfl1 ,MX)J

TENEX Sail also has the routine:

CHAROUT (Chad, c h a r )

which outputs a single chsiacter to the channel..

The OUT function is generally obsolete now thatCPRINT is aviijabie.

Page 46: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Records

SECTION 6

Records

Records are the newest data structure in Sail.They take us beyond the basic part of thelanguage, but we describe them here in the hopethat they will be very useful to users of thelanguage. Sail records are similar to those inALGOL W (see Appendix A for the differences).Some other languages that contain record-likestructures are SIMULA and PASCAL.

Records. can be extremely useful in ‘setting upcomplicated data structures. They allow the Sailprogrammer: 1) a means of program controlled

storage allocation, and 2) a simple method ofreferring to bundles of information. (Locat ion(x)and memory [XI, which are not discussed here andshould be thought of as liberation from Sail,allow one to deal with addresses of things.) ,

6.1 Declaring a.nd Creating Records

SAIL TUTORIAL

r p c NEWIRECORD ( p e r s o n ) ;

creates a person, with ail fields initially 0 (orNULL for strings, etc). Records are createddynamically by the program and are garbagecollected when there is no longer a way toaccess them.

When a record is created, NEW!RECORD returns apointer to the new record. This pointer istypically stored in RECORD!POINTER.RECORD!POINTERs are variaables which must bedeclared. The RECORD!POINTER rp was usedabove. There is a very important distinction tobe made between a RECORD!POINTER and aRECORD. A RECORD is a block of variables calledfields, and a RECORD!POINTER is an entity thatpoints to some RECORD (hence can be thought ofas the “name” or “address” of a RECORD)., ARECORD has fields, but a RECORD!POINTER doesnot, although its associated RECORD may havefields. The following is a complete program thatdeclares RECORD!CLASSRECORD!POIf’?TER, and creates ‘a

declaresrecord in th:

RECORD!CLASS with the pointer to the newrecord stored in the RECORD!POINTER.

A record is rather like an array that can haveobjects of different syntactic types. Usually therecord represents different kinds of informationabout one object. For example, we can have aclass of records called person that contains

. records with information about people for anaccounting program. Thus, we might want tokeep: the person’s name, address, accountnumber, monetary balance. We could declare arecord class thus:

BEGINRECORD!CLRSS person (STRING name,address;

INTEGER account;REAL balancs)~

RECORDIPOINTER ( p e r s o n ) r p ;

COtltlENT program starts hero. ;r p c NEU!RECORD ( p e r s o n ) JENOr

RECORD!CLASS psrson (STRING name, address;INTEGER accountiREAL ba I l ncr)

This occurs at declaration level, and theidentifier person is available within the currentblock -- just like any other identifier.

RECORD!CLASS declarations do not actuallyreserve any storage space. instead they definea pattern or template for the class, showing whatfields the-pattern has. in the above, name, addrsss,account and ba I anco are all fields of theRECORD!CLASS person.

To create a record (e.g., when you get the dataon an actual person) you need to call theNEW!RECORD procedure, which takes as itsargument the RECORD!CLASS. Thus,

RECORD!POINTERs are usually associated withparticular record ciass(es). Notice that in theabove program the d e c l a r a t i o n o fRECORD!POINTER mentions the class psrson:

RECORD!POINTER (person) rp;

This means that the compiler will do typechecking and make sure that only pointers torecords of class person will be stored into rp. ARECORD!POINTER can .be of several classes, as in:

RECORD!POINTER (perton, university) rp;

assuming that we had a RECORD!CLASSuniversi ty.

RECORD!POINTERs can be of any class if we say:

40

Page 47: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL- TUTORIAL Records

RECORO!POINTER (ANYICLASS) rp;

but declaring the class(es) of record pointersgives compilation time checking of record classagreement. This becomes an advantage whenyou have several classes, since the compiler willcomplain about many of the simple mistakes youcan make by mis-assigning record pointers.

6.2 Accessing Fields of Records

I

The fields of records can be read/written justlike the elements of arrays. Developing theabove program a bit more, suppose we havecreated a new record of class prrson, and storedthe pointer to that record in rp. Then, we cangive the “person” a name, address, etc., with thefollowing statements.

.person:nameIrpl c “ J o h n Doe”1person: address frpl e “181 East Lansing Strrrt”lperson: accoun t lrpl c 14;person: ba lance frpl c 3888.871

and we could write these fields out with thestatement:

P R I N T ( “ N a m e i s “, personrnaaeIrp1, crlf,“ A d d r e s s is * , person:addrossIrpl, crlf,“ A c c o u n t i s * , personraccounttrpl, crlf,“ B a l a n c e i s ” , persontbalanceIrp1, crlfIl

The syntax for fields has the following features:

1) The fields are available withinthe lexical scope where theRECORD!CLASS was declared, and followALGOL block structure.

2) The fields in different classesmay have the same name, e.g., parent :nameand ch i Id: name.

.3) The syntax is rather like that for

arrays -- using brackets to surround therecord pointer in the same way bracketsare used for the array index.

4) The fields can be read or writteninto, also like array locations.

5) It is necessary _ to writeclass: f leldlpointerl -- i.e., you have toinclude the name of the class (hereparson) with a “:” before the name of thefield.

6.3 Linking Records Together

Notice, in the above example, that as we createthe persons, we have to store the pointers tothe records somewhere or else they will become“missing persons”. One way to do this would beto use an array of record pointers, allocating asmany pointers as we expect to have people. Ifthe number of people is not known in advancethen the more customary approach is to link therecords together, which is done by usingadditional fields in the records.

.

Suppose we upgrade the above example to thefollowing:

RECORDICLRSS person WRING name, address;INTEGER account;REAL balance;RECORO!POINTER(ANY!CLASS) n e x t ) ;

Notice now that there is a RECORD!POINTER fieldin the template. This may be used to keep apointer to the next person. The header to theentire- list of persons will be kept in a singleRECORD!POINTER.

Thus, the following program would createpersons dynamically and put them into a “linkedlist” with the newest at the head of the list. Thistechnique allows you to write programs that arenot restricted to some fixed maximum number ofpersons, but instead allocate the memory spacenecessary for a new person when you need it.

BEGINRECORO!CLRSS person (STRING name, address;

INTEGER account1 RERL balancofRECORO!POINTER(RNY!CLRSS) next11

RECORO!POINTER (RNYICLRSS) h e a d e r ;

UHILE TRUE 00BEGIN

STRING slRECORO!POINTER (RNYICLRSSI t a m p ;

PRINTt”Name o f n e x t p e r s o n , C R i f d o n o r ” ) ;IF NOT LENGTtlts c INCHWLl THEN DONE;

COMENT put neu person at head of list1tamp l NEU!RECORO(person)lCOMENT make a neu record;person: nex t I tamp1 c header;COllllENT the o ld hoad bocomos t h e s e c o n d ;

41

Page 48: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Records SAIL TUTORIAL

h e a d e r c tamp;COllHENT the n e w record becomes the hradj - A m 0 (A 181, 513) (8 181, Jr21

(C 111, J13) (0 Id, Jt3)COHHENT n o w f i l l i n f o r m a t l o n floldslperson: name t tamp1 l slCOllflENT n o u NO c a n f i l l a d d r e s s , a c c o u n t ,

. b a l a n c e i f w e uant...lEND;

END;

+ A very powerful feature of record structures isthe ability to have different sets of pointers.For example, there might be both forward andbackward links (in the above, we used a forwardlink). Structures such as binary trees, sparsematrices, *deques, priority queues, arid so on arenatural appl,ications of records, but it will take al i t t le study of the structures in order tounderstand how to build them, and what they aregood for.

Note that two RECORD!POINTERs are only equal ifthey point to the same record (regardless ofwhether the fields of the records that they pointto are equal). At the end of executing theprevious example, there are 3 distinct records,one pointed to by RECORD!POINTER b, onepointed to by RECORD!POINTER C, and onepointed to by RECORD!POINTERs a and d. Whenthe line that reads: palrtj Id1 l 31 is executed,the j-field of the record pointed at byRECORD!POINTER d is changed to 3, not the j-fieldof d (RECORD!POINTERs have no fields). Sincethat is the same record as the one pointed to byRECORD!POINTER a, when we print pa irr j tal , weget the value 3, not 2.

Be warned about the difference. betweenrecords, record pointers, record classes, and thefields of records: they are all distinct things, and

you can get in trouble if you forget it. Perhapsa simple example will show you what is meant:

Records can also help your programs to be morereadable, by using a record as a means ofreturning a collection of values from a procedure(no Sail procedure can return more than onevalue). If you wish to return a RECORD!POINTER,then the procedure declaration must indicate thisas an additional type-qualifier on the proceduredeclaration, for example:

BEGIN‘RECORO!CLASS p a i r ( I N T E G E R 1, j)l

RECORO!POINTER (pair) a , b , c , d ;

a + NEU!RECORO (pair11. pair: i [al e I;

p a i r : ) tal e 2 ;d l a;

,

b c NEU!RECGRO (pair11p a i r : l Ibl ‘C 1 ;pairr j lb1 l 2 ;c c NEU!RECORD (pair11pair8 i [cl c 1;pair : j [cl l 3 ;IF a t b THEN PRINTt * R t B * I;p a i r : j Id1 t 3 ;IF a t c THEN PRINTS * A = C * IlIF c = d THEN PRINTt ” C B 0 ” I lIF a = d THEN PRINTS * R I 0 * 1;PRINTS ” (f4 I : “ , pairs i [al, “, Jt”,

pair:j [al, “I” IlPRINTf * (B II”, p a i r ; i Ibl, “, Jt”,

p a i r : j Ibl, *I* IlPRINT{ ” (C I t “, pair, i ICI, “, J:‘,

p a i r : j tcl, “I” 1;PRINTS ” (0 It”, pair:1 Cdl, “, J:“,

RECORO!PGINTER (person) PROCEOURE maxBalance;BEGINRECOROIPOINTER (person) tempHeador,

currentHaxPerson1RERL currentllaxltampHeader c header1currentfiax c p e r s o n r b a l a n c e [tampHeaderI;currrntRaxPerson c tempHraderlUHLLE tempHeader c p e r s o n r n e x t ItempHeaderl 0 0IF personr b a lancr I tompHraderI * curronttlax T H E N

BEGINcurrontllax + person:balancr Itempheaderl;currentRaxPorson c totnpHoadrrl

END;RETURNkurrontRaxPerson);EN01

This procedure goes through the linked list ofrecords and finds the person with the highestbalance. It then returns a record pointer to therecord of that person. Thus, through the singleRETURN statement allowed, you get both thename of the person and the balance.

* pairr) Idl, “1” I;END;

.

RECORD!POINTERs can also be used as argumentsto procedures; they are by default VALUEparameters when used. Consider the followingquite complicated example:

will print: RECORO!CLRSS pnt (REAL x,y,t) lRECOROIPOINTER (pnt) PROCEDURE midpoint

(RECORO!POINTER fpnt) a,b) l

42

Page 49: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL -TUTORIAL Records

BEGINRECORO!POINTER (pnt) r e t v a l ;r e t v a l c NEU!RECORO (pnt);p n t : x I r e t v a l l e (pntrx tal + p n t : x Ibl) / 2 ;p n t : y t r e t v a l l e (pnt:y [al + pntty Ibl) / 21pnttz I r e t v a l l c (pnt:z [al 4 pntrz tbl) / 21RETURNf r e t v a l 1;END;

. . .p c midpointt q , r 11. . .

A

While this procedure may appear a bit clumsy, itmakes it easy to talk about such things as pntslater, using simply a record pointer to representeach pnt. Another common method for“returning” more than one thing from aprocedure is to use REFERENCE parameters, as inthe following example:

PROCEOURE midpoint (REFERENCE RERL rx,ry,rzlREAL ax,ay,ar,bx,by,bt)l

BEGINrx c (ax + bx) / 2;ry c (ay + by) / 2;rz c (at + br) / 2;ENO;

l . .

mPOINT( px, PY, PZ, qx, q y , qz, rx, ry, rh )I. . .

Here the code for the procedure looks .quitesimple, but there are so many arguments to itthat you can easily get lost in the main code.Much of the confusion comes about becauseprocedures simply cannot return more than onevalue, and the record structure allows you toreturn the name of a bundle of information.

43

Page 50: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Conditional Compilation

SECTION 7

Conditional Compilation

Conditional compilation is available so that thesame source file can be used to compile slightlydifferent versions of the program for differentpurposes. Conditional compilation is handled bythe scanner in a way similar to the handling ofmacros. The text of the source file ismanipulated before it is compiled. The format is

IFCR boo loan THENC code ELSEC code ENOC

This construction is not a statement or anexpression. It is not followed by a semi-colonbut just appears at any point in your program.The ELSEC is optional. The ENDC. must beincluded to mark the end but no begin is used.The code which follows the THENC (and ELSEC ifused) can be any valid Sail syntax or fragment ofsyntax. As with macros, the scanner is simplymanipulating text and does not check that thetext is valid syntax.

The boolean must be one which has a value atcompile time. This means it cannot be any valuecomputed by your program. Usually, the booleanwill be DEfINE’d by a macro. For example:

2) Maintainence of a single sourcefile for a program which is to beexported to several sites with minordifferences.

D E F I N E smallVersion I <TRUE>1. . .

OEFINE sumex I <TRUE>,is i I <FALSE>; +s

l . .

I F C R smallVersion T H E N C m a x c 18*total; IFCR sumex THENC docdir c “OOC”; ENOCELSEC max c 188ttotal; ENOC IFCR isi THENC docdir c “00CURENTAT10N”; ENOC

. . . *.*where every.difference in the program betweenthe small and large versions is handled with asimilar IFCR...THENC...ENDC construction. For thisconstruction, the scanner checks the value of theboolean; and if it is TRUE, the text followingTHENC is inserted in the source being sent to the

’ inner compiler--otherwise the text is simplythrown away and the code following the ELSEC(if any) is used. Here the code used for theabove will be max + 18*totali, and if you edit theprogram and instead

where only one site is set to TRUE foreach compilation.

3) “Commenting out” large portionsof the program. Sometimes you need totemporarily remove a large section of theprogram. You can insert the wordCOMMENT preceding every statement tobe removed but this is a lot of extrawork. A better way is to use:

D E F I N E smal IVersion I <FALSE>;

the result will be max + 188etotal;.- -

The code following the THENC and ELSEC will betaken exactly as is so that statements whichneed final semi-colons should have them. Theabove format of statement i ELSEC is correct.

SAIL TUTORIAL

If. this feature were not available then thefollowing would have to be used:

BOOLEAN smallVorsionlsmaiiVorsion l TRUE;

l .*

IF smallVersion THEN.nax l 18*totalELSE ma⌧ l 188*totall

..*

SO that a conditional would actually appear, inyour program.

Some typical uses of conditional compilation are:

1) Insertion of debugging or testingcode for experimental versions of aprogram and then removal for the finalversion. Note that the code will still bein your source file and can be turnedback on (recompilation is of courserequired) at any time that you again needto debug. When you do not turn on

debugging, the code completelydisappears from your program but notfrom your source file.

bo “rohovod”>

ENOC

44

Page 51: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL Systems Building in Sail

SECTION 8 2) Code them in a similar “style” forreadability among programmers.

Systems Building in Sail

Many new Sail users will find their first Sailproject involved with adding to an already-existing system of large size that has beenworked on by many people over a period ofyears. These systems include the speechrecognition programs at Carnegie-Mellon, thehand-eye software at Stanford Al, large CAIsystems at Stanford IMSSS, and various medicalprograms at SUMEX and NIH. This section doesnot attempt to deal with these individual systemsin any detail, but instead tries to describe someof the features of Sail that are frequently usedin systems building, and are common to all thesesystems. The exact documentation of thesefeatures is given elsewhere; this is intended tobe a guide to those features.

The Sail language itself is procedural, and thismeans that programs can be broken down intocomponents that represent conceptual blockscomprising the system. The block structuring ofALGOL also allows for local variables, whichshould be used wherever possible. The first ruleof systems building is: break the system downinto modules corresponding to conceptual units.This is partly a question of the design of thesystem--indeed, some systems by their verydesign philosophy will defy modularity to acertain extent. As a theory about therepresent at ion of knowledge in computerprograms, this may be necessary; but programsshould, most people would agree, be as modular“as possible”.

Once modularized, most of the parts of thesystem can be separate files, and we shall showbelow how this is possible. Of course, themodules will have to communicate together, andmay have to share common data (global arrays,flags, etc.). Also, since the modules will besharing the same core image (or job), there arecertain Sail and timesharing system resourcesthat will have to be commonly shared. The rulesto follow-here are:

1) Jvtake the various modules of asystem as independent and separate asdesign philosophy allows.

3) Make the points of interface andcommunication between the programs asclear and explicit as possible.

4) Clear up questions about whichmodules govern system resources (Sailand the timesharing system), such asfiles, terminals, etc. SO that they are notcompeting with each other for theseresources.

8.1 The Load Module

The most effective separation of modules isachieved through separate compilations. This isdone by having two or more separate sourcefiles, which are compiled separately and thenloaded together. Consider the following designfor an Al system QWERT. QWERT will containthree modules: a scanner module XSCAN, aparser module PARSE, and a main programQWERT. We give below the three files forQWERT.

First, the QWERT program, contained in fileQWERTSAI:

BEGfN"WERT"

EXTERNRL STRING PROCEDURE XSCRNtSTRINC S);REQUIRE "XSCdN' LORD!tlOOULE~

EXTERNAL STRING PROCEDURE PARSEtSTRINC S);REQUIRE "PARSE" LORD!tlODULE;

WHILE TRUE DOBEGIN

PRINT("~",PARSE(XSCRN(INCtlULHl;END;

END"QWERT";

Notice two features about QWERT.SAI:

1) There are two EXTERNALdeclarations. An EXTERNAL declarationsays that some identifier (procedure orvariable) is to be used in the currentprogram, but it will be found somewhereelse. The EXTERNAL causes the compilerto permit the use of the identifier, asrequested, and then to issue a requestfor a global fixup to the LOADERprogram.

Page 52: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Systems Building in Sail SAIL TUTORIAL

2) Secondly, there are two REQUIRE. . . LOAD!MODULE statements in theprogram. A load module is a file that isloaded by the loader, presumably theoutput of some compiler or assembler.These REQUIRE statements cause thecompiler to request that the loader loadmodules XSCAN.REL and PARSE.REL whenwe load MAIN.REL. This will hopefullysatisfy the global requests: i.e., theloader will find the two procedures in the*two mentioned files, and link theprograms all together into one “system”.

Second, the code for modules XSCAN and PARSE:

ENTRY,XSCRN;BEGIN

INTERNRL STRING PROCEDURE XSCAN6TRING 9;BEGIN

. . . . . c o d e f o r XSCRN . . . .RETURN ( resul t ing strinqljEND)

END;

and now PARSESAl:

- ENTRY PORSEjBEGIN .

INTERNRL STRING PROCEDURE PARSE(STRING S)jBEGIN

. . ..code f o r P A R S E . . . .RETURNhsultinq s t r i n g ) ;END;

END;

Both of these modules begin with an ENTRYdeclaration. This has the effect of saying thatthe prdgram to be compiled is not a “main”program (there can be only one main program ina core image), and also says that PARSE is to befound as an INTERNAL within this file. The list oftokens after the ENTRY construction is mainlyused for LlBRARYs rather than LOAD!MODULEs,and we do not discuss the difference here, sinceLlBRARYs-are not much used in system buildingdue to the difficulty in constructing them.

A few important remarks about LOAD!MODULES:

1) The use o f LOAD!MODULESdepends on the loaders (LOADER and

LINKlO) that are available on the system.In particular, there is no way to associatean external symbol with a part icularLOAD!MODULE.

2) The names of identifiers arelimited to six characters, and thecharacter set permissible is slightly lessthan might be expected. The symbol “!‘Iis, for example, mapped into “.” in globalsymbol requests.

3) The “semantics” of a symbo l(e.g., whether the symbol names aninteger or a string procedure) is in noway checked during loading.

Initialization routines in a LOAD!MODULE can beperformed automatically by including a REQUIRE. . . INITIALIZATION procedure. For example,suppose that INIT is a simple parameterless,valueless procedure that does the initializationfor a given module:

SItlPLE PROCEDURE INITjBEGIN

. ..initlalitation cod....END;

REQUIRE INIT INITIALIZATION;

will run INIT prior to the outer block of the mainprogram. It is difficult to control the order inwhich initializations are done, so it is advisableto make initializations that do not conflict witheach other.

8.2 Source Files

In addition to the ability to compile programsseparately, Sail allows a single compilation to bemade by inserting entire files into the scanstream during compilation. The construction:

REQUIRE "FILENfi.SRI" SOURCE!FILE;

inserts the text of file FILENMSAI into the streamof characters being scanned--having the sameeffect that would be obtained by copying all ofFILENM.SAI into the current file.

One pedestrian use of this is to divide a file intosmaller files for easier editing. While this can beconvenient, it can also unnecessarily fragment aprogram into little pieces without purpose.

46

Page 53: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

.

SAIL -TUTORIAL

There are, however, some real purposes of theSOURCE!FILE construction in systems building.One use is to include code that is needed inseveral places into one file, then “REQUIRE” thatfile in the places that it is needed. Macros are acommon example. n For example, a file of globaldefinitions might be put into a file MACROS.SAI:

R E W I R E "<><>* DELIflITERS;D E F I N E CIRRC)YSIZE489>,

NUllBEROFSTUDENTS=<288,,FILENWlEr<"FIL.DAT">;

A common use of source files is to provide aSOURCE!FILE that links to a load module: thesource file contains the EXTERNALS declarationsfor the procedures (and data) to be found in amodule, and also requires that file as a loadmodule. Such a file is sometimes called a“header” file. Consider the file XSCAN.HDR forthe above XSCAN load module:

EXTERNClL STRING PROCEDURE XSCRN(STRING 3;REQUIRE "XSCCIN" LOAD!llODULEj

The use of header files ameliorates some of thedeficiencies of the loader: the header file can,for example, be carefully designed to contain thedeclarations of the EXTERNAL procedures andd&a, reducing the likelihood of an error causedby misdeclaration. Remember, if you declare:

INTERNAL STRING PROCEDURE XSCAN(STRING S);BEGIN . . . . . END;

in one file and

EXTERNClL INTEGER PROCEDURE XSCAN(STRING 9;

in another, the correct linkages will not beand the program may crash quite strangely.

made,

8.3 Macros and Conditional Compilation

Macros, especially those contained in globalmacro files, can assist in system building.Parameters, file names, and the like can be“macroized”.

Systems Building in Sail

D E F I N E DEBUGGING=dALSE>jCOtftlENT falsr i f n o t dobuqqinqj

and then use it

IFCR DEBUGGING THENCPRINT("Now at PROC PR ",I," ",J,CRLF); E N D C

(See Section 7 on conditional compilation formore details.) In the above example, the code willdefine the switch to be FALSE, and the PRINTstatement will not be compiled, since it is in theFALSE consequent of an IFCR . ..THENC. In usingswitches, it is common that there is a defaultsetting that one generally wants. The followingcondition al compilation checks to see ifDEBUGGING has already been defined (ordeclared), and if not, defines it to be false. Thusthe default is established.

IFCR NOT DECLARATION(DEBUGGIN6) THENCDEFINE DEBUGGINC=<FRLSE>; ENDC

Then, another file, inserted prior to this one, setsthe compilation mode to get the DEBUGGINGversion if needed.

Macros and conditional compilation also allow anumber of complex compile-time operations, suchas building tables. These are beyond ourdiscussion here, except to note that complexmacros are often used (overused?) in systemsbuilding with Sail.

.

Condition-al compilation also assists in systemsbuilding by allowing the same source files to dodifferent things depending on _ the setting ofswitches. For example, suppose a file FILE isbeing used for both a debugging and a“product ion” version of. the same module. Wecan include a definition of the form:

47

Page 54: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

Sail and ALGOL W Comparison

APPENDIX A

Sail and ALGOL W Comparison

SAIL TUTORIAL

5) The first case in the CASE statement in Sail is0 rather than 1 as in ALGOL W. (Note thatSail also has CASE expressions.)

There are many variants of ALGOL. ThisAppendix will cover only the main differencesbetween Sail and ALGOL W.

The following are differences in terminology:

ALGOL u Sail

I - Rssignment operator

* * Exponentiation operator ; *VP Not equal * or NEQ<= Less than or equal 5 o r LEQ

>= Greater than or equal L o r GEQ’

REil Division remainder operator tlOD

END. Program end END

RESULT Procedure parameter type REFERENCErtr(ijj) Substrings strLi+l f o r jl

STRING(i) s String declarations STRING s

ar ry (1) Array subscript arry 111a r r y (1: : 10) Array declaration arry tl: 101

6) <, =, and > will not work for alphabetizingSail strings. They are arithmetic operatorso n l y .

7) ALGOL W parameter passing conventionsvary slightly from Sail. The ALGOL WRESULT parameter is close to the SailREFERENCE parameter, but there is adifference, in that the Sail REFERENCEparameter passes an address, whereas theALGOL W RESULT parameter creates a copyof the value during the execution of theprocedure.

8) A FORWARD PROCEDURE declaration isneeded in Sail if another procedure calls anas yet undeclared procedure. Sail is a one-pass compiler.

9) Sail uses SIMPLE PROCEDURE, PROCEDURE,and RECURSIVE PROCEDURE where ALGOLhas only PROCEDURE (equivalent to Sail’sRECURSIVE PROCEDURE).

The following are not available in Sait:

ODD ROUND ENTIER

10) Scalar variables in Sail are not cleared onblock entry in non-RECURSIVE procedures.

TRUNCATE Truncation is default conversion.

11) Outer block arrays in Sail must haveconstant bounds.

URITE, WRITEON Use PRINT statement for both..

REROON Use INPUT, RERLIN, INTIN.

Block expressions

12) The RECORD syntax is considerablydifferent. See below.

P r o c e d u r e e x p r e s s i o n s

Use RETURN statementin procedures.

Sail features (or improvements) not in ALGOL W:

a) Better string facilities with more flexibility.

Other differences are:b) More complete RECORD structures.

1) Iteration variables and Labels must bedeclared in Sail, but the iteration variable ismore general since it can be tested afterthe loop.

2) STEP UNTIL cannot be left out in the FOR-statement -in Sail.

c) Use of DONE and CONTINUE statements foreasier control of loops.

d) Assignment expressions for more compactcode.

e) Complete l/O facilities.

3) Sail strings do not have length declared andare not filled out with blanks.

f) Easy interface to machine instructions.

4) EQU not - is used for Sail strings.

48

Page 55: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL TUTORIAL Sail and ALGOL’W Comparison

The following compares Sail and ALGOL Wrecords in several important aspects.

Aspoc t Sail ALGOL U- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Dec lara t ion RECORD!CLRSS RECORD

of class

D e c l a r a t i o n o f RECORD!POINTER REFERENCE

record pointor ,Pointers can be pointers mustseveral classes or be to oneANY !CLRSS class

Empty record Reserved uord Reserved uord

NULL!RECORD NULL

REFERENCES

1. Reiser, John led.), Sail, Memo AIM-289,Stanford Artificial Intelligence Laboratory,August 1976.

2. Frost, Martin, UUO Manual (Second Edition),Stanford Artificial Intelligence LaboratoryOperating Note 55.4, July 1975.

3. Harvey, Brian (M. Frost, ed.), Monitor CommandManual, Stanford Artificial IntelligenceLaboratory Operating Note 54.5, January1976.

F i e l d s o f record 4. Feldman, J.A., LO W, J.A., Swinehart, D.C.,Use bracke 1s Use parens Taylor, R.H., “Recent Developments in Sail”,

AFIPS FJCC 1972, p. 1193-1202.llust use Don’ t use

CLRSS: brfore the class name 5. DECSYTEMlO Assembly Language Handbookfield name beforo f i e l d (3rd Edition), Digital Equipment Corporation,

Maynard, Massachusetts, 1973.

6. DECSYSTEMlO Users Handbook (2nd Edition),Digital Equipment Corporation, Maynard,Massachusetts, 1972.

7. Myer, Theodore and Barnaby, John, TENEXEXECUTIVE Manual (revised by WilliamPlummer), Bol t , Beranek and Newman,Cambridge, Massachusetts, 1973.

8. JSYS Manual (2nd Revision), Bolt, Beranek andNewman, Cambridge, Massachusetts, 1973.

I

,

49

Page 56: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

INDEX SAIL TUTORIAL

INDEX

!SKIP! 3 0

& 12

ALGOL 48allocation 15Altmode 30ANY!CLASS 41Arguments 20array 4, 7arrays 15, 16, 38ARRCLR ‘15ARRYIN 33, 38ARRYOUT 33,39assignment expressions 10assignment operator 10Assignment statements 5

BEGIN 2binary format files 38bits 36block 2block name 14blocks 9, 13BOOLEAN 2boolean expression 8break character 27, 30,38.break tables 27built-in procedures 6, 19

CASE expressions 11CFILE 3 4channel 34,37channel number 31CHARIN 3 8CHAROUT 3 9Commenting’ 44compile time 15compound statement 9Conditional compilation 44condition al expressions 11conditionals 7connected directory 36

, constants 3CONTINUE - 18control statements 7controlling-terminal 30, 36CPRINT 3 9crlf 3 0 ’CVD 6

data 38deallocation 15debugging 44Declarations 2D E F I N E 2 5delimiters 25directory devices 31, 32DIRST 37DO...UNTIL 17D O N E 1 8dynamic 15 ,

ELSEC 44emulator 1END 2end-of-file 37, 38 ,ENDC 44ENTER 32ENTRY 46eol 30EQU8,ll ,equality 8error handling 35expression 5, 6expressions 10EXTERNAL 30,45

FALSE 2fields 40file bytepointer 38file name 32files 30flag specification 36FOR statement 15format 4FORWARD 2 1free format 4

garbage collections 12GETBREAK 2 7GETCHAN 3 1GJINF 37global 14GTJFN 35GTJFNL 35

half word format 36

l/O 30identifiers 3IF..THEN statement 7IFCR 44INCHWL 6,30indefinite iteration 17

I 50

Page 57: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

SAIL:TUTORIAL INDEX

INDEXFILE 35initialization 15Initialization routines 46I N P U T 27,37input /output 30, 31INTEGER 2INTIN 3 8INTSCAN 2 9INTTY 3 0iteration variable 16

J F N S 3 7

LENGTH 12line terminators 28l ine-edi t ing 30LOAD!MQDULE 4 5LOADER 45local 14 ’login directory 36LOOKUP 32L O P 1 2lowercase 4

macro expansion 25macros 25modular i ty 45M T A P E 3 3multi-dimensioned arrays 4multiple file designators 35

nested 9, 14NEW!RECORD 4.0NUL character 13NULL 3

o c t a l r e p r e s e n t a t i o n 3 6OPEN 31OPENFILE 3 4order of evaluation 10outer b l o c k 2OWN 1 5

PA1050 1parallel arrays 4parameter list 20parameterized procedure 20parent hesized 11predeclared identifiers 3PRINT 6PRINT statement 25p r o c e d u r e 1 9procedure body 21procedure call 19

random I /O 38

RCHPTR 38read error 37REAL 2REALIN 3 8REALSCAN 2 9RECORD!CLASS 40RECORD!POINTER 40Records 40RECURSIVE 15,21REFERENCE 24reinitialization 15RELEASE 32RENAME 32reserved words 2,3RETURN statement 21runtime 1 5

scalar variables 15SCAN 27scanner 25SCHPTR 38scope of the variable 14search path 36semi-colon 8sequential I/O 38SETBREAK 2 7SETFORMAT 13SETINPUT 3 4SETPL 37SETPRINT 3 0side-effect 23SIMPLE 21SINI 3 8SOS line numbers 28SOURCE!FILE 47SQRT 6Statements 2statements 5Storage allocation 15STRING 2string descriptor 12STRING operators 11string space 12strings 27subscripts 5substrings 12

tables 13Teletype l/O 30TENEX Sail 1THENC 44TOPS-10 Sail 1TRUE 2TTY: 36type conversion 6

51

Page 58: SAIL TUTORIAL - The Stanford University InfoLabi.stanford.edu/pub/cstr/reports/cs/tr/76/575/CS-TR-76-575.pdf · Stanford Artificial Intelligence Laboratory ... The ALGOL-Part of Sail

INDEX

typed procedures 22

untyped procedures 22uppercase 4, 20, 28, 30USETI 3 3USETQ 3 3

V A L U E 2 4var iables 3 , 14

WHILE...00 1 7WORDIN 3 3 , 3 8WORDOUT 33,39

5 2

SAIL TUTORIAL