Algol-68 Interpreter March, 1987 The Algol-68 Interpreter is intented to provide a tool to run small (up to 60 lines) Algol-68 programs in order to become familiar with the general philosophy of the language. It is appropriate for students' programs in a two-term programming course, but not in an industrial scale. Not all the exotic features are implemented. In particular there are no semaphores, formats and parallel-clauses. The transput is restricted to the minimal one, namely formatless character transput to channels `stand in' and `stand out' only. This manual contains a brief description how the Interpreter can be used under Linux, a list of the restrictions on the Interpreter, how to interpret the dump informations, and a list of error messages. It also contains a few sample programs. History: the Interpreter originates from the one made by L. Ammeraal in the Mathematical Center, Amsterdam, in 1973. It was written in Algol-60. The interpreter was debugged and implemented on an ICL 1903A machine by L.Csirmaz in 1974. The present competely revised version was written in C. The lexical analyzer was written by Sam Rebelsky, the other parts by L. Csirmaz, both at the University of Chicago. Later it has been ported to DOS and Linux by L. Csirmaz. C O N T E N T S 1. How to use the Interpreter 2. Spelling an Algol-68 program, symbols 3. Restrictions, deviations from the REPORT 4. Standard prelude and transput 5. Internal representation 6. What the `dump' is good for 7. Error messages 8. Sample programs 1. How to use the Interpreter In the following we describe the commands that can used to run an Algol-68 program. We use the percentage mark `%' to denote the prompt symbol. The Interpreter consists of a lexical analyzer, the interpreter proper, two utility programs to print out dump information and legible error messages, a data file containing the standard prelude, and a driver. Different parts communicate through files named `.a68.w1', `.a68.w2', and `.a68.dump' which will sit in the home directory of the calling process. The command % a68 filename invokes the Interpreter. It reads an Algol-68 program from the file `filename'. The `filename' cannot be `dump'. The program must start with an (i.e. 'begin' 'case' 'if' or `('), and the lexical analyzer reads until the end of file, or until the brackets become balanced, whichever comes first. The program text is printed, and, if no spelling error was detected, interpreted. All the transput initiated by the program goes to the standard output and comes from the standard input. Whenever an error is detected, the message *** ERROR xx.x *** at nnn closes the output. `xx.x' is a number referring to the type of the error, and `nnn' is the serial number of the symbol at which the error was detected (see Section 7; the program listing shows this number for the first symbol in every line). Also, dump information is placed in the binary file `.a68.dump'. An edited listing of the dump may be printed by the command % a68 dump Also, a dump is made upon interrupt (control-C), but NOT upon normal termination. An unedited (rather lengthy and illegible) listing results from appending the parameter `-': % a68 dump - If you don't want the source program to be listed, use the `-l' parameter: % a68 -l [filename] The parameter has no effect if the program contains syntactical (spelling) error. 2. Spelling Algol-68 programs Every Algol-68 program is a sequence of symbols. The task of the lexical analyzer is to split up the program into these symbols, so that the interpreter need not bother with such nuisances as long identifiers, integers, or real numbers (denotations). In fact, the interpreter is working on a sequence of symbols, and not on the character form of the program -- this is why error messages refer to symbol number, and not the line number and character position in it. 2.1. Symbols Each symbol falls into one of the following categories: bold symbol, identifier, operator, denotation, and special character. 2.1.1. Bold symbol Since there is no such a thing in Algol-68 as a reserved word, such symbols as `begin' or `end' must be distinguished from the identifier with the same letters. Those words usually appear in bold face font, or are underlined in the printed form of programs. On the computer, however, only one font is available. To make a word bold, it must be surrounded by single quotation marks ('). Thus these quotation marks can occur only in pairs (except in a string or character denotation), and between them ONLY LETTERS can occur. Both lower and upper case letters are allowed. Thus 'ThisIsAGoodBoldSymbol' is an acceptable bold symbol, while none of 'bold symbol' '2' 'mybold5' or 'bold\ symbol' Lower and upper case bold words count different, and all the standard symbols are in lower case letters. The program 'BEGIN' print("Hello word") 'END' is spelled wrongly: it does not begin with an . There is no a priory upper bound on the length of a bold symbol. For easier reading we follow the policy to _u_n_d_e_r_l_i_n_e bold words rather than enclosing them by single quotes. In programs, however, bold words MUST always be enclosed: the Interpreter does not understand underlining. The following bold symbols have special "built-in" meaning and cannot be used as mode indicators or operators: _t_r_u_e _f_a_l_s_e _e_m_p_t_y _l_o_c _h_e_a_p _r_e_f _s_t_r_u_c_t _f_l_e_x _p_r_o_c _u_n_i_o_n _o_p _p_r_i_o _m_o_d_e _i_n_t _r_e_a_l _b_o_o_l _c_h_a_r _v_o_i_d _b_i_t_s _c_o_m_p_l _s_t_r_i_n_g _b_e_g_i_n _e_n_d _i_f _t_h_e_n _e_l_s_e _e_l_i_f _f_i _e_x_i_t _o_f _c_a_s_e _i_n _o_u_t _o_u_s_e _e_s_a_c _i_s _i_s_n_t _g_o_t_o _g_o _s_k_i_p _c_o _c_o_m_m_e_n_t _f_o_r _f_r_o_m _b_y _t_o _w_h_i_l_e _d_o _o_d _a_t _n_i_l 2.1.2. Identifier An identifier is, as usual, a sequence of letters and digits starting with a letter. However no typographical features are of significance: white spaces (space, tabulator or newline) are disregarded in identifiers. Thus `stand in', `standin' and `s t a n d i n' spell the same identifier. An identifier can even be continued in the following line. Lower and upper case letters count different, and all the standard identifiers are in lower case letters. So `pi' is predeclared in the standard prelude, but `PI' is not. 2.1.3. Operator Operators may consists of up to four characters, and they are parsed according to the following syntax: : ; ; ; . : `+'; `-'; `%'; `^'; `&'; `?'; `!'; `~'. : `<'; `='; `>'; `/'; `*'. : `:='; `=:'; . Also, or cannot be used to denote a monadic operator. Thus `+/:=' is parsed as a single operator, while `+//:=' is a sequence of two operators, namely `+' and `//:='. However, to prevent unintentional parsing (or misleading spelling), operators cannot contain intervening white spaces (spaces, tabulators, newline characters). Thus `**' is a single operator, while `* *' is two applications of the `*' operator, the second of which is, erroneously, monadic. 2.1.4. Denotation Denotations are the constants written into the program text. Like identifiers, except for string and character denotations, they can also contain intervening white spaces. Integer denotations are simple (unsigned) digit sequences. Real denotations contain either fractional or exponent part, or both. The decimal point belongs to the fractional part, and must be followed by at least one digit. The exponent can be indicated by `e' or `E' which is followed by a signed integer. The exponent part must contain at least one digit. Bits denotations start with the character sequence `2', `4', `8', or `16', followed by either `r' or `R' (for RADIX), and by an appropriate digit sequence. In case of radix 2 only the digits `0'and `1' can be used; in radix 16 the letters from `a' to `f' and from `A' to `F' stand for digits of value 10 to 15. Strings are enclosed within double quotes ("), the double quote character within a string must be doubled. Strings cannot contain newline characters, a string must be closed in the same line where it was opened. There is no denotation for strings of length one; they are character denotations instead. 2.1.5. Special characters The following characters and character sequences fall into this category: ( ) [ ] , : ; # | |: := :=: :/=: There can be no intervening space between the elements of these sequences. 2.2. Comments Comments can be placed between symbols (but not inside them) anywhere in the program text between the first and the matching . A comment starts and ends with the same symbol which can be any of the the following: # _c_o _c_o_m_m_e_n_t In a comment enclosed by one kind of a separator every other separator may occur. Comments are not restricted into a single line, so an unmatched causes to drop the whole remaining portion of the program text. 3. Restrictions, deviations from the REPORT The official definition of Algol-68 is the REPORT (Revised Report on the Algorithmic Language Algol-68, Edited by A.van Wijngaarden, B.J.Mailloux, J.E.L.Peck, C.H.A.Koster, M.Sintzoff, C.H.Lindsey, L.G.Meertens, and R.G. Fisker). The language was planned to compiled and not interpreted. Thus to maintain some kind of efficiency, not only are certain exotic constructs not implemented, but the Interpreter deviates from the official definitions in certain cases. 3.1. Restrictions a) _b_y_t_e_s, _s_e_m_a, _f_i_l_e, _f_o_r_m_a_t and _c_h_a_n_n_e_l modes are NOT implemented, values of these modes cannot be used. (`stand in' and `stand out' are exceptions, see Section 4.4). b) Integers, reals, complex numbers, and bits can be used only in single precision. Thus the bold words _s_h_o_r_t and _l_o_n_g cannot occur in declarers. c) Synchronization operations are not available (_d_o_w_n and _u_p operators for semaphores), consequently, no parallel clauses are allowed, i.e. a collateral clause cannot be preceded by the bold word _p_a_r. d) Pragmats cannot be used. e) No selection can be made from a row of structures, which is done twice in the following program: _b_e_g_i_n [3]_s_t_r_u_c_t(_i_n_t s,t)a; s _o_f a := t _o_f a := (1,2,3) _e_n_d Instead, you can use displays as follows: _b_e_g_i_n [3]_s_t_r_u_c_t(_i_n_t s,t)a; a:=((1,1),(2,2),(3,3)) _e_n_d f) The standard prelude, especially the transput, is restricted (see Section 4. for the details). 3.2. Deviations Since the program is interpreted and not compiled, errors, even serious syntactical ones, remain undetected if the control does not reach the spot where they reside. Thus symbol sequences, which are not programs in sense of the REPORT, are sometimes accepted. Also in cases when the elaboration is "undefined", or even if the construct is forbidden, the Interpreter behaves quite intelligently. In certain cases, however it does not work exactly according to the official definition. a) There are no local generators, every generator is global (even those which start with _l_o_c). b) The mode is not implemented, so names sliced from flexible arrays can be remembered (but not necessarily refer to any actual element of that array). The following program is typical in this respect. ( _s_t_r_i_n_g a := "dear"; _r_e_f _c_h_a_r a1 = a[1]; a1 := "b"; print(a); # bear # a := "duck"; a1:= "b"; print (a) #still duck # ) c) During elaboration of a declarer, no jump out of the declarer can occur. Thus the following program, reading a value outside the range, issues an error message instead terminating the run: _b_e_g_i_n _s_t_r_i_n_g month = _c_a_s_e print("Type in the number of the month: "); _i_n_t m; read(m); m _i_n "Jan", "Feb","March","April","May","June", "July","Aug","Sept", "Oct", "Nov","Dec" _o_u_t stop _e_s_a_c; print(month) _e_n_d d) Certain (standard) operators are mapped onto the same internal symbol, which means that these operators are, in fact, the same. Thus redeclaring one of them redeclares the other(s) automatically. Such operators are: <= and _l_e = and _e_q /= and _n_e >= and _g_e & and _a_n_d ** and _u_p and ^ e) Balancing is done only in s. In an or each constituent is in the same syntactical position as the itself (mainly because only the executed part of the is consulted deciding the a priori mode of the result). Thus in the following program the `?' operator is not identified: _b_e_g_i_n _o_p ? = (_r_e_a_l)_v_o_i_d: _s_k_i_p ; ?( _t_r_u_e | 1 | 0.5) _e_n_d . Similarly, having the declarations _r_e_f _i_n_t ii; _i_n_t i,j; _b_o_o_l b; in the assignation `( b | i | ii ) := j' the right hand side is dereferenced or not depending on whether the actual value of `b' is true or false, and in no case will `ii' be dereferenced prior to the assignation. Of course, _r_e_f _i_n_t ( b | i | jj ) := j; does the trick. f) The in a behaves (as far as the Interpreter is concerned) as a "black box", i.e. no search is made to determine its actual scope. Instead, the following rule is applied: the scope of the is that of the tightest range which contains an elaborated declaration. Thus the first printing out `2+j' has scope 1 (being the declaration of `pp' in this range); while the second one has the scope the body of `pp' only, since, in principle, it can reach `i' which was declared there. After deproceduring `pp', the yielded routine text has newer scope than the surrounding environment, thus calling the routine text (with `0' as parameter) causes a "scope violation error" and does not print anything: _b_e_g_i_n #1# _p_r_o_c pp = _p_r_o_c (_i_n_t) _v_o_i_d : _b_e_g_i_n #2# print(1); (_i_n_t j) _v_o_i_d : print(2+j); #scope is 1# _i_n_t i; (_i_n_t j) _v_o_i_d : print(3+j) #scope is 2# _e_n_d #2#; pp(0) _e_n_d #1# The program runs as expected if the declaration `_i_n_t i;' is missing. g) To avoid unintented scope violations, if an yields, by a MORF construct, a parameterless procedure whose scope is just the scope of the clause itself, then instead letting the routine text to slip out of the clause, the procedure is called (repeatedly if necessary). Thus the program _b_e_g_i_n _p_r_o_c _p_r_o_c _v_o_i_d pp = _p_r_o_c _v_o_i_d : _b_e_g_i_n _i_n_t i; print(1); _v_o_i_d : print(2) _e_n_d; _p_r_o_c _v_o_i_d (pp) _e_n_d prints out the numbers `1' and `2' since the scope of `_v_o_i_d: print(2)' happens to be that of the body of `pp'. The yield of the `_p_r_o_c _v_o_i_d (pp)' is a routine text coerced from the result _v_o_i_d (which, when called, issues an error message). This arrangement makes the following program work which prints out the numbers 1 and 2: _b_e_g_i_n print(( _p_r_o_c p = _i_n_t: (print((1,newline)); _g_o_t_o lbl); _g_o_t_o end; lbl: 2 _e_x_i_t end: p )) _e_n_d h) The in a , in a , or in a always has the same scope as the enclosing clause, independently of the existence of other elaborated declarations. The scope of the routine text in the below is the same as that of range 1: _b_e_g_i_n #1# _i_n_t n; read(n); _b_e_g_i_n #2# _p_r_o_c (_i_n_t) _i_n_t f = (_i_n_t i) _i_n_t : (i=0 | 1 | i*f(i-1) # here # ); print(f(n)) _e_n_d #2# _e_n_d #1# This means that when executing the of the routine text, declarations only at range 1 and outside are considered. Thus the application `f(i-1)' will find `f' "undeclared" since it is not declared there. Using `_p_r_o_c pp = (_i_n_t i) _i_n_t : ...', the scope of `f' will be that of range 2, after which the program works correctly. 4. Standard prelude and transput 4.1. Standard modes The following modes are defined by the Interpreter: _v_o_i_d _b_o_o_l _i_n_t _r_e_a_l _c_h_a_r _c_o_m_p_l _b_i_t_s _s_t_r_i_n_g Integers, reals and complexs are only of single precision, so neither _s_h_o_r_t nor _l_o_n_g can be used with the above declarers. Integers and bits are stored in 32 bit long words, reals occupy 64 bits (double in C). The bits of a mode value are counted from left to right, the leftmost (i.e. sign) bit has serial number 0, the following, most significant bit is the first, and the rightmost, i.e. parity bit is the 31st. 4.2. Operators The available standard operators are grouped here according to their operands. 4.2.1. Row _l_w_b, _u_p_b, both monadic and dyadic, gives the lower and upper bound, respectively, of the i-th dimension (or the first dimension if the operator is monadic) of the right hand side operand, which must be a row. 4.2.2. Boolean The operators _o_r, _a_n_d, _n_o_t, =, /= have their standard meaning. `_a_b_s b' is 1 if `b' is true, and 0 if `b' is false. 4.2.3. Integer The comparison operators <, <=, =, /=, >=, > yield boolean result. The arithmetical operators +, -, *, %, %*, ^ yield integer results. `%' denotes integer division, `i%*j' is the remainder when `i' is divided by `j'. Exponentiation is repeated multiplication; if the exponent is negative, the result will be -1, 0, or +1. `i/j' yields the quotient as a real number. The applicable monadic operators are +, -, _a_b_s, _o_d_d, and _s_i_g_n. 4.2.4. Real The comparison operators <, <=, =, /=, >=, >, and the arithmetical operators +, -, *, / are all available. They may be applied to mixed parameters too. In the exponentiation `x^i' the exponent must be an integer, exponentiation is not defined with real exponent. For reals the defined monadic operators are +, -, _a_b_s, _s_i_g_n, _r_o_u_n_d, and _e_n_t_i_e_r, the last two yielding an integer result. 4.2.5. Complex Only two comparison operators, = and /= are available. The arithmetical operators are +, -, *, and / . All the operators are defined for those cases when one of the operands is complex, and the other is either complex, integer or real. Exponentiation is also defined with integer exponent. The monadic operators are _r_e, _i_m, _a_b_s, _a_r_g, _c_o_n_j. The dyadic operator _i, applied to reals or integers (mixed operands are allowed) gives the complex number with the first argument as real part, and the second argument as imaginary part. 4.2.6. Bits Bits can be compared by = or by /= . The operators _a_n_d, _o_r, and _n_o_t behave bitwise. `b1 <= b2' yields true if `b1 _o_r b2 = b2'; similarly for `b1 >= b2'. _u_p and _d_o_w_n with integer second operand shift the first bits operand logically left and right, respectively. `i _e_l_e_m b' yields true if the `i'-th bit of `b' (counted from left) is one. The monadic operator `_a_b_s b' gives the integer with the same bit pattern as `b'; the inverse operator is _b_i_n. 4.2.7. Character and string Strings and characters can be compared by <, <=, =, /=, >=, >. They can be added up (concatenation), and multiplied by an integer (both from left and from right).`_a_b_s c' for a character `c' gives its ASCII code; the inverse operator is _r_e_p_r. 4.2.8. Assignment operators They are +:=, -:=, *:=, %:=, %*:=, /:=, and are applicable where they can be applied reasonably. Moreover the operator +=: can be applied with a string or character left operand and a string variable right operand; the L.H.S. will be added to the content of the R.H.S from the left, and the result put back into the R.H.S. 4.3. Identifiers 4.3.1. Constants The real constant `pi' with value 3.1415926...; integer constant `bits width' with value 31; character constant `blank' with value the space character (= _r_e_p_r 32). 4.3.2. Procedures The parameterless procedure `random' produces pseudorandom real numbers between 0.0 and 1.0. The mathematical functions `sin', `cos', `tan', `arcsin', `arccos', `arctan', `sqrt', `exp', `ln' are all predefined. Also, the function `bits pack' produces a bits value from a row of boolean. 4.3.3. Halting label The label `stop' is put immediately after the closing symbol of the program. Jumping to this label causes the program to terminate. 4.3.4. Transput The following identifiers are defined in connection with transput: `stand in', `stand out', `newpage', `newline', `space', `print', `write', and `read'. 4.4. Transput Only the simplest formatless transput has been implemented. There is no binary transput, both input and output uses character conversion. The input comes from the standard input, and the output goes to the standard output. There is also no way to define new channels or files, and the identifiers `stand in' and `stand out' are provided to identify the files at the standard channels. `newpage', `newline', and `space' are, in fact, procedures which require a file as a parameter. Since files cannot be declared, the only way to call them is using `stand in' or `stand out' as parameter. These calls are equivalent to `read()' and `print()', respectively. 4.4.1. Output Procedures `print' and `write' are identical, in fact they perform the same task. After straightening the parameter of the procedure, the actual printing is done through the C procedure "printf" with the following conversions: mode of the value conversion string integer "%d " real "%lg " char "%c" bits "%#o " bool the printed string is either "t " or "f " That is, integer, real, bits, and bool values are printed using the shortest possible form, which is followed by a space character. If the value to be printed is the procedure `newpage', `newline', or `space', then a newpage, newline, or space character (with ASCII code 12, 10, and 32) is written to the standard output. 4.4.2. Input The procedure `read' uses mainly the C procedure "scanf" to read an actual value with the following conversion strings: mode of the value conversion string integer "%d" real "%g" char "%c" (it reads a single character) bits "%o" bool "%1s" requesting 1, t, or T for true, 0, f, or F for false. If the value to be read in is `space' then the next character is skipped (by calling "getchar()"); and if it is `newpage' or `newline' then the input is skipped until a newpage (newline) character is found. In contrast to the REPORT, reading into a flexible row of character (i.e. into a _s_t_r_i_n_g) is done in the same way as reading into any other row. Namely, the Interpreter reads exactly as many characters as many elements the row has, the bounds of the row do not change during reading. For example, the program line _s_t_r_i_n_g s; read(s); reads nothing, since, after the declaration, `s' has lower bound 1 and upper bound 0, thus has no element. 5. Internal representation The Interpreter uses three main areas to store the values it has to deal with. The first one is the `Program text area', where the symbolic form of the program text resides. The second is the `Linkage area' which is the linking chain between the external and internal objects. Finally, the `Working area' contains the internal objects on which the program operates. These areas are dumped out in case of abnormal termination of the interpreted program. 5.1. Program text area The symbolic form of the program text resides here. All s (such as `(', `[', _o_p_e_n, _i_f, _c_a_s_e) are replaced by `(', and all the s by `)'. The identifiers and the user defined bold words are replaced by certain numbers which uniquely identify them; denotations are represented as pointers into a separate table. There is always an extra _b_e_g_i_n symbol just before the first symbol of the program text (this is why the symbol numbering starts at 2), and ; stop: _s_k_i_p _e_n_d \0 is appended at the end. `\0', a zero character, is the last in the program text. 5.2. Linkage area This area serves to link the "external objects" residing in the Program text area to the "internal objects" of Working area. Each entry here consists of two fields: the "object" and the "value". The "object" is usually (the internal code of) an identifier or user-defined bold symbol as found in the Program text, and the "value" is a pointer to the Working area giving the address of the corresponding internal object (value). If the "object" is an identifier, which, in turn, is a label, then the corresponding "value" is negative, and the absolute value is the place where the label is found in the Program text area. During the elaboration of a declaration (or parameter passing), the newly declared objects are "masked" so that they are not recognized until the end of the declaration. The following program shows the effect of masking: ( _i_n_t a=1,b=0; ( _i_n_t b=a,a=b; print((a,b)) # 0, 1 #); ( _i_n_t b=a; _i_n_t a=b; print((a,b)) # 1, 1#) ) Masked object are signified by an asterisk (*) after their "value". This area also serves to handle multiple declarations of the same external object. The "object" of an entry can be "----" which simply signifies a boundary between different regions. In this case "value" is the address of the last entry of the dynamically preceding region. To find the actual binding of an external object, one has to start at the END of the area always going backward. If the "object" field of the entry happens to be the boundary mark "----", then the search continues at the address found in the "value" field. The Linkage area has room for 2000 entries. 204 of them are occupied by the bindings of the standard prelude. 5.3. Working area All the internal objects are stored here, both those which actually represent some value, and those which describe only a mode. No value is associated with the latter. Each entry in this area has three fields "A", "B", "C". Some objects occupy a single entry, others occupy more blocks consisting of consecutive entries. In the following description the ~ means that the content is immaterial. mode of the value A B C integer INT value ~ real REAL value in B and C bool (1=true, 0=false) BOOL value ~ bits BITS value ~ void VOID ~ ~ priority (n is between 1 and 9) PRIO n ~ reference REF M nil `M' is the Working area address of the referenced value. `nil' is 0 if the actual name is _n_i_l, otherwise it is 1. structured value STRUCT (|) n has `n' fields, `M1',...,`Mn' are the _____________| field's Working area addresses, `S1',... | `Sn' are the (codes of the) selectors. |-> ~ M1 S1 ... ... ... ~ Mn Sn collateral value COLL (|) n exists only until the elaboration of a ______________| collateral clause. It has `n' elements, | `M1',...,`Mn' are their Working area |-> ~ M1 ~ addresses. ... ... ... ~ Mn ~ rowed value ROW (|) flex has `dim' dimensions. `flex' is 0 if the ______________| row is flexible, otherwise it is 1. `m' | is the number of elements. If it is zero |-> dim M m there is a ghost element at `M', otherwise lw1 up1 st1 `M' is the Working area address of the ... ... ... first element. `lwi', `upi' and `sti' are lwdim updim stdim the lower, upper bounds, and steps for dimension `i'. procedure PROC (|) n has `n' parameters. `u' is a pointer into ______________| the Linkage area showing the dynamic range | `v' points to the beginning of the |-> u M0 v in the routine text, or negative if the ~ M1 P1 procedure standard. `M0' is the mode of the ... ... ... result, `M1',...,`Mn' are the modes of the ~ Mn Pn parameters, and are Working area pointers. `P1',...`Pn' are the formal parameters. united value UNION (|) M The possible modes are shown by `M1',... ______________| `Mn', all pointers to the Working area. `M' | is either 0 in which case it possesses no |-> ~ M1 n actual value; otherwise `M' is a Working ~ M2 ~ area address pointing a value with mode ... ... ... among the modes of `M1',...,`Mn'. ~ Mn ~ mode indicator MODE M v `M' is either -1, or the mode declarer is under elaboration, when `M' is a Working area pointer giving a value of the actual mode. `v' is the Program text area pointer to the actual declarer. operator OP (|) prio here `prio' is the priority which is 10 ______________| if the operator is monadic. The third line | is present only if the operator is dyadic. |-> u M0 v The other notations are the same as for M2 M1 P1 procedures. ~ M2 P2 The Working area is capable to store 16000 entries, the first 620 is occupied by values from the standard prelude. 6. What the `dump' is good for Whenever the interpreted program terminates abnormally, the Interpreter dumps out the three main areas it works with: the Program text area, the Linkage area and the Working area. There is also an error number (if applicable), the program address at which the error was detected (or the interrupt occurred), the Working area address of the last value the Interpreter dealt with, and a mystic line saying whether the last statement was MORF or COMORF. (A statement is MORF if the result should be deprocedured in voiding, and COMORF otherwise. In the latter group we find the assignment, identity relation, generator, cast, and denotation.) In the Program text area identifiers are replaced by numbers, user defined bold words by (underlined) capital letter words, all of them preceded by percentage marks (%). The s appear as `(', the s as `)'. The listed text can be used to determine the representation of the external objects (since they are used in the Linkage area), also to check for check possible misspelling (e.g. _r_e_r_p instead of _r_e_p_r). `\0' denotes the end of the program. Only that part of the Linkage area is listed which contains the bindings of the program, the unlisted part binds standard operators and identifiers. It can be used to determine the actual binding of identifiers and operators. Similarly, the Working area is listed only for the program-defined values. Since it is handled as a heap, the occupied locations do not necessary form consecutive entries. The missing entries simply do not contain living information. For each entry, the content of field `A' is given both by name and value (if applicable), the others by value only. It is marked by an asterisk (*) if it corresponds to the initial node of a recursive mode. In certain cases a Working area entry can refer to other entries which are unlisted. Usually they sit in the standard prelude part; the most frequently referred ones are i A B C 1 (28) _v_o_i_d 0 0 2 (37) _i_n_t 31 0 3 (38) _r_e_a_l 3.1415926 4 (39) _b_o_o_l 1 0 (true) 6 (40) _c_h_a_r 32 0 (space) 7 (43) _b_i_t_s 037777777777 0 (-1) 8 (28) _v_o_i_d 0 0 9 (48) _r_o_w 14 0 (_s_t_r_i_n_g) 10 (33) _s_t_r_u_c_t 16 2 (_c_o_m_p_l) 14 1 6 0 15 1 0 1 16 0 3 51 (`re') 17 0 3 52 (`im') 7. Error messages There are two kind of error messages the Interpreter can issue. The first one is given by the lexical analyzer, they appear INSIDE the program text, and their presence means that the program won't be interpreted. An error message AFTER the program text (there can be only one) means that your program started to run but something went wrong. In the first case the messages are textual, in the second besides the text a number is also given which is unique for all possible errors. 7.1. Messages from the Lexical Analyzer The error messages appear INSIDE the program text, and usually they refer to az erroneous situation which was detected at that point. If the Lexical Analyzer discovers an error, the program won't be interpreted. The error texts are the following: -- unrecognizable character either some control character, or one of { } ` $ \ _ outside a string or character denotation. -- the program must start with an open symbol -- end of file was hit unexpectedly -- parenthesis mismatch means an unmatching open/close symbol, an _i_f without closing _f_i, or _e_l_s_e without preceding _t_h_e_n, etc. -- misplaced bold delimiter -- missing bold delimiter a bold word is enclosed by single quote symbols, and contains letters only -- too long string -- too long number -- too long operator sequence the Lexical Analyzer cannot handle so long constructs -- missing string delimiter a string or character denotation cannot contain newline or other control characters, except for the tabulator -- wrong bits denotation in a bits denotation the radix (base) is not 2, 4, 8 or 16 -- too many denotations -- hash table is full -- character table is full the internal tables are full. 7.2. Messages from the Interpreter A message is of the form `*** ERROR xx.x *** at nnn'. Here `xx.x' is a number referring to the type of the error, and `nnn' is the place where the error was DETECTED, which is not necessarily the same as where the error is. The first two digits of the error number refer to some general context, the third refines that one. Not all the possible numbers are listed here, and, as it is the case with any kind of error messages, the true reason for the appearance of that number might be absolutely different from what is given. The texts mainly refer to what the Interpreter THINKS about the actual construct, and not what it might intented to be. The textual error message relies on the first two digits only and differs slightly from those listed here. 7.2.1. System areas 11.X Linkage area is full, too many declarations or parameter calls 12.X Working area is full. 13.X Too difficult or too large recursive mode. 7.2.2. General constructs 22.X Enclosed clause 22.1 A unit or declaration is expected at this point. Maybe the enclosed clause starting here is syntactically wrong (a `;' is before the closing symbol). 22.2 A `;' is expected after a declaration; a declaration cannot be the last element in a closed clause. 22.3 An enclosed clause ends here and no is found. Maybe the preceding enquiry clause contains a label. 23.X Collateral clause 23.1 A collateral clause or display ends here and no was found. Maybe a wrong separator. 23.2 A missing or wrong unit. 24.X Choice clause 24.1 A choice clause ends here without a . 24.2 The _e_l_s_e (_o_u_t) part of a choice clause is syntactically wrong. 24.3 The _e_l_i_f (_o_u_s_e) part of a choice clause is syntactically wrong. 24.4 In a conditional clause the _t_h_e_n part is syntactically wrong. 24.5 Wrong unit in a case clause. 24.6 Wrong enquiry clause after _e_l_i_f or _o_u_s_e. 25.X Conformity clause 25.1 The unit following a declarer is wrong. 25.2 The declarer is of wrong format. 26.X Loop 26.1 Missing identifier after _f_o_r. 26.2 Wrong unit after _f_r_o_m, _b_y, _t_o. 26.5 The enquiry clause after _w_h_i_l_e is syntactically wrong (maybe a label is in it). 27.X The clause between _d_o and _o_d is wrong. 7.2.3. Declarer 31.X _r_e_f must be followed by a virtual declarer. 32.X Syntax error in a _s_t_r_u_c_t declarer. 33.X Syntax error in a _u_n_i_o_n declarer. 33.5 Circular chain of _u_n_i_o_n definitions. 34.X Wrong row declarer. 34.1 This is an actual declarer, you must supply the bounds. 34.2 A unit is missing after the colon (:). 34.3 A jump occurred during elaboration of the actual bounds. 35.X Wrong actual declarer for a mode indicator. 35.1 Circular chain of mode declaration. 36.X Syntax error in a plan. 36.4 Missing identifier in a routine text's plan. 7.2.4. Declarator 41.X A routine text is expected after `=' or `:=' in a routine declaration. 42.X A unit is expected after `=' in an identity declaration. 43.X Missing unit after `:=' in a variable declaration. 44.X Wrong priority declaration. 45.X Wrong operator declaration 45.1 The routine text must be either monadic or dyadic. 46.X Wrong mode declaration. 47.X A forbidden jump during elaboration of 47.1 an identity declaration, 47.2 a variable declaration, 47.3 an operator declaration. 48.X Missing identifier after a declarator. 7.2.5. Coercion 51.X _n_i_l can be coerced into a name (i.e. a mode starting with _r_e_f) only. 52.X An attempt was made to dereference a name with actual value _n_i_l 52.1 in an assignation, 52.2 in an identity relation. 53.X An operator cannot be identified. 53.5 The operator possesses no actual routine text. 54.X A meek integer is expected here. 55.X The yield of a construct cannot be coerced into the a posteriori mode 55.1 in an assignment, 55.2 in an identity declaration, 55.3 in a variable declaration, 55.4 in an operator declaration, 55.5 in a cast, 55.6 after the execution of the unit in a routine text, 55.7 for the actual parameter in a procedure call, 55.8 for the enquiry clause in a choice clause, 55.9 for the result of the enquiry clause between _w_h_i_l_e and _d_o. 7.2.6. Other constructs 61.X General 61.1 Undeclared identifier. 61.2 Neither procedure nor a row followed by an open symbol. Maybe you left out a semicolon. 61.3 Label used in inappropriate place. 62.X Assignation 62.1 Unrecognizable unit on the right hand side. 62.3 The left hand side is not a name. 62.4 Non-flexible arrays have different bounds. 63.X Identity relation 63.1 Wrong or missing tertiary on the right hand side. 63.3 The left hand side is not a name. 63.4 The right hand side in not a name. 64.X Slicing and trimming 64.1 Missing or syntactically wrong unit after `@'. 64.2 Some index is less than the actual lower bound. 64.3 Some index is greater than the actual upper bound. 64.4 Too many or too less dimensions in the slicing. 65.X Display 65.1 A collateral clause can be coerced into a row or struct only. 65.2 A structure display has a wrong number of elements. 65.3 An element of a structure display is of wrong mode. 65.4 An element in a row display is of wrong mode. 65.5 In a multidimensional row display elements have different bounds. 66.X Selection 66.1 Missing or wrong secondary after _o_f. 66.2 The secondary after _o_f is not a structure. 66.3 The identifier before _o_f is not found among the field selectors. 67.X Procedure call 67.1 Missing or wrong actual parameter. 67.2 Wrong number of actual parameters in a procedure call. 67.3 Scope error, a procedure was called outside its scope. 67.4 A procedure with no actual value (e.g. one coerced from _s_k_i_p) was called. 68.X Routine text 68.1 Wrong or missing unit in a routine text. 69.X Other 69.1 Missing or wrong argument after a monadic operator. 69.2 Missing or wrong argument after a dyadic operator. 69.3 Badly formed generator or misplaced _l_o_c or _h_e_a_p. 69.4 Wrong symbol after _g_o_t_o. 7.2.7. Standard operators 71.X Mathematical functions (`sin', `sqrt', etc.) require a single _r_e_a_l parameter. 72.X When applying the standard `+=:' operator, the right hand side must be a non-nil, flexible row of char. 73.X The right hand side of a standard assignment operator must be a non-nil name. 73.2 The left hand side of `+:=' must be a flexible row of char. 74.X The first operand for lwb or upb does not correspond to a valid dimension of the second operand. 75.X `bitspack' must have a single parameter of mode []_b_o_o_l. 76.X Division by zero. 7.2.8. Transput 81.X Only `space', `newline' and 'newpage' may occur in `read', `print' and `write' as procedure with parameters; and the only parameters for `space', `newline' and `newpage' are the identifiers `stand in' and `stand out'. 82.X Wrong arguments to `read', `print' or `write'. 82.1 They require a single unit as parameter. 82.3 Forbidden jump during elaboration of the parameter. 83.X Inappropriate input object 83.1 An empty (uninitialized) _u_n_i_o_n was attempted to read. 83.2 A reference to a name, a name with actual value _n_i_l,or not a name. 84.X A read was attempted from the input file, but either there were no more characters, or did not correspond to the mode 84.1 integer 84.2 bool - no more character 84.3 bool - a character different from `t',`T',`f',`F',`0',`1' 84.4 real 84.5 char 84.6 bits. 85.X Inappropriate output object 8. Sample programs The main purpose of this section is to illustrate some of the features of Algol-68 without going into details. For easier readability bold words are underlined in the program texts, otherwise they can be run by the Interpreter without any change. Each program is followed by the output of a sample run. ------------------------------------------------------------------------------ _b_e_g_i_n # 8.1. procedure variable # _p_r_o_c(_i_n_t)_i_n_t myproc; myproc := (_i_n_t i)_i_n_t: i+1; print(myproc(10)); myproc := (_i_n_t j)_i_n_t: j-1; print(myproc(10)) _e_n_d ***** 11 9 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.2. greatest common divisor # _p_r_o_c gcd = (_i_n_t a,b)_i_n_t: (b=0 | _a_b_s a | gcd(b,a _m_o_d b)); _w_h_i_l_e _i_n_t a,b; print((newline,"two integers please : ")); read((a,b)); a>0 _o_r b>0 _d_o print((blank*15,"gcd of ",a,"and ",b,"is ",gcd(a,b))) _o_d _e_n_d ***** two integers please : 35 5555 gcd of 35 and 5555 is 5 two integers please : 777 7777777 gcd of 777 and 7777777 is 7 two integers please : 37 999 gcd of 37 and 999 is 37 two integers please : 0 0 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.3. summation procedure # _p_r_o_c sum = (_i_n_t n, _p_r_o_c(_i_n_t)_r_e_a_l p)_r_e_a_l: _b_e_g_i_n _r_e_a_l s:=0; _f_o_r i _t_o n _d_o s+:=p(i) _o_d; s _e_n_d; print((sum(10,(_i_n_t j)_r_e_a_l: sin(2*pi*j/10)),newline, sum(10,(_i_n_t j)_r_e_a_l: cos(2*pi*j/10)))) _e_n_d ***** -2.742152e-015 -6.661338e-015 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.4. drawing # _r_e_a_l c=2*pi; _p_r_o_c f=(_r_e_a_l x)_r_e_a_l: exp(-x)*sin(c*x); _r_e_a_l d=.0625, s=32; _i_n_t h=34, lim=30; _f_o_r i _f_r_o_m 0 _t_o lim _d_o _r_e_a_l y = f(d*i); print((blank*(_r_o_u_n_d(s*y)+h),"*",newline)) _o_d _e_n_d ***** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ------------------------------------------------------------------------------ _b_e_g_i_n # 8.5. continued fraction # _o_p ? = ([]_r_e_a_l a)_r_e_a_l: (_u_p_b a = 1 | a[1] | a[1]+1.0/ ?a[2:]); []_r_e_a_l x=(1,1,1,1,1,1,1,1), y=(1,2,3,4,5,6,7,8); print((?x, newline, ?y)) _e_n_d ***** 1.619048 1.433127 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.6. sample program for united modes # _m_o_d_e _r_c = _u_n_i_o_n(_r_e_a_l,_c_o_m_p_l); _p_r_o_c qe = (_r_e_a_l a,b,c)[]_r_c: # quadratic equation with real coefficients # _i_f _r_e_a_l d:=b^2-4*a*c; d>0 _t_h_e_n d:=sqrt(d)/2/a; (-b/2/a+d, -b/2/a-d) _e_l_i_f d=0 _t_h_e_n -b/2/a _e_l_s_e d:=sqrt(-d)/2/a; _r_e_a_l re=-b/2/a; (re _i d, re _i -d) _f_i; __w_h_i_l_e _r_e_a_l a,b,c; print((newline,"the coefficients, please : ")); read((a,b,c)); a/=0 _d_o print(qe(a,b,c)) _o_d _e_n_d ***** the coefficients, please : 1 2 1 -1 the coefficients, please : 4 0 1 0 0.5 0 -0.5 the coefficients, please : 1 1 1 -0.5 0.866025 -0.5 -0.866025 the coefficients, please : 0 0 0 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.7. generating permutations # _i_n_t n; read(n); _p_r_o_c perm =(_r_e_f[]_i_n_t a)_v_o_i_d: (_i_n_t n = _u_p_b a; _i_f n=1 _t_h_e_n printperm _e_l_s_e _t_o n _d_o perm(a[:n-1]); _i_n_t a1=a[1]; a[:n-1]:=a[2:]; a[n]:=a1 _o_d _f_i ); _p_r_o_c printperm = _v_o_i_d: (_f_o_r i _t_o n _d_o print(t[i]) _o_d; print(newline)); [n]_i_n_t t; _f_o_r i _t_o n _d_o t[i]:=i _o_d; perm(t) _e_n_d ***** 3 1 2 3 2 1 3 2 3 1 3 2 1 3 1 2 1 3 2 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.8. procedure with itself as parameter # _m_o_d_e _p = _p_r_o_c(_p)_i_n_t; _p_r_o_c fact = (_p f)_i_n_t: (i=0|1|_i_n_t j=i; i-:=1; j*f(f)); _p_r_o_c q = (_i_n_t n)_i_n_t: (i:=n; fact(fact)); _i_n_t i; _f_o_r i _t_o 10 _d_o print((q(i),newline)) _o_d _e_n_d ***** 1 2 6 24 120 720 5040 40320 362880 3628800 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.9. calendar # _p_r_o_c what = (_i_n_t month,day,year)_v_o_i_d: ( _b_o_o_l greg = year>1582 _o_r year=1582 _a_n_d month*100+day>=1015; _b_o_o_l leap = year%*4=0 _a_n_d (_n_o_t greg _o_r year%*100/=0 _o_r year%*400=0); _i_n_t r = day + year + _c_a_s_e month _i_n 0,3,3,6,1,4,6,2,5,0,3,5 _e_s_a_c + _i_f greg _t_h_e_n _i_n_t j = year-1600; year%4-j%100+j%400-10 _e_l_s_e year%4 _f_i - _a_b_s(leap _a_n_d month<3); print(( blank*17, "that day is ", _c_a_s_e r%*7 _i_n "Friday","Saturday","Sunday","Monday","Tuesday","Wednesday" _o_u_t "Thursday" _e_s_a_c, newline)) ); _w_h_i_l_e _i_n_t month,day,year; print("your date (month, day, year)? "); read((month,day,year)); month>0 _a_n_d month<13 _d_o what(month,day,year) _o_d _e_n_d ***** your date (month, day, year)? 07 04 1776 that day is Thursday your date (month, day, year)? 12 31 1987 that day is Thursday your date (month, day, year)? 01 01 1988 that day is Friday your date (month, day, year)? 0 0 0 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.10. scope error # _i_n_t n; read(n); _b_e_g_i_n _p_r_o_c(_i_n_t)_i_n_t f = (_i_n_t i)_i_n_t: (i=0|1|i*f(i-1)); _p_r_o_c g = (_i_n_t i)_i_n_t: (i=0|1|i*g(i-1)); print(g(n)); print(f(n)) _e_n_d _e_n_d ***** 7 5040 *** ERROR 61.1 *** at 35 Undeclared identifier; or unrecognizable unit ------------------------------------------------------------------------------ _b_e_g_i_n # 8.11. magic quadrangle # _p_r_o_c Q = (_i_n_t n)_v_o_i_d: (_i_n_t m=2*n+1; [0:m-1,0:m-1]_i_n_t A; _i_n_t x:=n, y:=m, i:=0; _t_o m _d_o x-:=1; y-:=2; _t_o m _d_o A[(x+:=1)%*m,(y+:=1)%*m]:= i+:=1 _o_d _o_d; print((newline, "The rank: ",m,newline)); _f_o_r k _t_o m _d_o _f_o_r j _t_o m _d_o print(( (A[j-1,k-1]<10|" "|" "), A[j-1,k-1])) _o_d; print(newline) _o_d ); Q(1); Q(3) _e_n_d ***** The rank: 3 4 9 2 3 5 7 8 1 6 The rank: 7 22 31 40 49 2 11 20 21 23 32 41 43 3 12 13 15 24 33 42 44 4 5 14 16 25 34 36 45 46 6 8 17 26 35 37 38 47 7 9 18 27 29 30 39 48 1 10 19 28 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.12. alphabetical ordering # _m_o_d_e _s_t_a_c_k = _s_t_r_u_c_t(_r_e_f _s_t_a_c_k left, _s_t_r_i_n_g word, _r_e_f _s_t_a_c_k right); _r_e_f _s_t_a_c_k roof:= _n_i_l; _p_r_o_c in=(_s_t_r_i_n_g a, _r_e_f _r_e_f _s_t_a_c_k b) _v_o_i_d: _i_f _r_e_f _s_t_a_c_k (b):=: _n_i_l _t_h_e_n b:= _h_e_a_p _s_t_a_c_k := (_n_i_l,a,_n_i_l ) _e_l_s_e in(a, _i_f a12 _o_r day<1 _o_r day>31 _t_h_e_n print((newline,"Sorry, wrong date")); stop _f_i; print((newline,newline)); _s_t_r_i_n_g f:="The weather tomorrow will be "; _i_n_t n=_u_p_b f+1; f +:= _i_f random<.5 _t_h_e_n "warm" _e_l_s_e "cold" _f_i + "er than usual."; f := f + _r_e_p_r 10 #newline# + _i_f random<.5 _t_h_e_n "No precipitation" _e_l_s_e _i_f f[n:n+3]="warm" _t_h_e_n (month<3|"Some flurries"|:month<10|"Light rain"|"Wet snow") _e_l_s_e (month<5 _o_r 9eps _t_h_e_n y1:=y2; h/:=2; c:=0; out:=_f_a_l_s_e; L2 _f_i; _i_f out _t_h_e_n y3 _e_l_s_e x+:=2*h; y:=y3; _i_f (c+:=1)>5 _t_h_e_n c:=0; h*:=2 _f_i; _i_f _a_b_s(x1-x)<2.01*_a_b_s h _t_h_e_n out:=_t_r_u_e; h:=(x1-x)/2 _f_i; L1 _f_i ); print(RK(0,1,(_r_e_a_l x,y)_r_e_a_l:y,3,.00001)); print((exp(3),newline)); print(RK(0,0,(_r_e_a_l x,y)_r_e_a_l:x+y,3,.00001)); print((exp(3)-4,newline)) _e_n_d ***** 20.085516 20.085537 16.085516 16.085537 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.15. a recursive procedure # _p_r_o_c p = (_i_n_t n, _p_r_o_c _i_n_t t)_i_n_t: ( _i_n_t m=n-1; _p_r_o_c B = _i_n_t: (m>0|p(m,t)+p(m-1,t)|t); _i_f m>0 _t_h_e_n p(m,B)+p(m-1,B) _e_l_s_e t _f_i ); _f_o_r i _t_o 4 _d_o print((p(i,_i_n_t:1),newline)) _o_d _e_n_d ***** 1 4 25 841 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.16. linear algebra # _o_p * = ([]_r_e_a_l A,B)_r_e_a_l: #inner product# (_r_e_a_l p:=0; _f_o_r i _t_o _u_p_b A _d_o p+:=A[i]*B[i] _o_d; p); _o_p * = ([]_r_e_a_l A, [,]_r_e_a_l B)[]_r_e_a_l: # matrix product # ([1:_u_p_b A]_r_e_a_l P; _f_o_r i _t_o _u_p_b A _d_o P[i]:=A*B[,i] _o_d; P); _o_p / = ([]_r_e_a_l A, [,]_r_e_a_l B)[]_r_e_a_l: # linear equation # _b_e_g_i_n _i_n_t n=_u_p_b A; _i_n_t n1=n+1; [1:n,1:n1]_r_e_a_l P; P[,1:n]:=B; P[,n1]:=A; _f_o_r i _t_o n _d_o _i_n_t i1=i+1, _r_e_a_l m=1/P[i,i]; _f_o_r j _f_r_o_m i+1 _t_o n1 _d_o P[i,j]*:=m _o_d; _f_o_r j _t_o n _d_o _i_f i/=j _t_h_e_n _r_e_a_l m=P[j,i]; _f_o_r k _f_r_o_m i1 _t_o n1 _d_o P[j,k]-:=m*P[i,k] _o_d _f_i _o_d _o_d; P[,n+1] _e_n_d; [,]_r_e_a_l A=((2,1,0),(1,2,1),(0,1,2)); []_r_e_a_l B=(3,4,3), C = (3,1,-3); print(("A[1,] ",A[1,],newline,"A[2,] ",A[2,],newline)); print(("A[3,] ",A[3,],newline,newline)); print(("B = ",B," C = ",C," B*C = ",B*C,newline,newline)); print(("B/A = ",B/A,blank*5,"B/A*A = ",B/A*A,newline)); print(("C/A = ",C/A,blank*4,"C/A*A = ",C/A*A,newline)) _e_n_d ***** A[1,] 2 1 0 A[2,] 1 2 1 A[3,] 0 1 2 B = 3 4 3 C = 3 1 -3 B*C = 4 B/A = 1 1 1 B/A*A = 3 4 3 C/A = 1 1 -2 C/A*A = 3 1 -3 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.17. pancakes game # _i_n_t n; _w_h_i_l_e print("How many pancakes do you want to play with? "); read(n); n<3 _o_r n>20 _d_o _s_k_i_p _o_d ; [n]_i_n_t A; _b_o_o_l again:=_t_r_u_e; _p_r_o_c pancakes = _v_o_i_d: _b_e_g_i_n print(newline); _f_o_r i _t_o n _d_o _i_n_t ai=A[i]; print((newline,(i<10|" "|""),i," "*(n-ai+7),"*"*(2*ai-1))) _o_d; print(newline) _e_n_d; _e_n_d; _w_h_i_l_e again _d_o _f_o_r i _t_o n _d_o A[i]:=i _o_d; _f_o_r i _t_o n-1 _d_o _i_n_t j=i+_e_n_t_i_e_r((n+1-i)*random), ai=A[i]; A[i]:=A[j]; A[j]:=ai _o_d; _i_n_t move:=0; _w_h_i_l_e _b_o_o_l b:=_t_r_u_e; _f_o_r i _t_o n _w_h_i_l_e b _d_o b:=A[i]=i _o_d; _n_o_t b _d_o pancakes; _i_n_t k; _w_h_i_l_e print((newline,move," your move: ")); read(k); k<2 _o_r k>n _d_o print(" wrong answer, try again") _o_d; move +:= 1; _f_o_r i _t_o k%2 _d_o _i_n_t ai=A[i]; A[i]:=A[k+1-i]; A[k+1-i]:=ai _o_d _o_d; pancakes; print((newline,newline,"you win in ",move,"moves!!",newline)); _c_h_a_r c; _w_h_i_l_e print("more game (answer y or n)? "); read((newline,c)); c/="y" _a_n_d c/="n" _d_o _s_k_i_p _o_d; again := c="y" _o_d _e_n_d ***** How many pancakes do you want to play with? 5 1 ********* 2 *** 3 * 4 ******* 5 ***** 0 your move: 5 1 ***** 2 ******* 3 * 4 *** 5 ********* 1 your move: 3 1 * 2 ******* 3 ***** 4 *** 5 ********* 2 your move: 4 1 *** 2 ***** 3 ******* 4 * 5 ********* 3 your move: 3 1 ******* 2 ***** 3 *** 4 * 5 ********* 4 your move: 4 1 * 2 *** 3 ***** 4 ******* 5 ********* you win in 5 moves!! more game (answer y or n)? n ------------------------------------------------------------------------------ _b_e_g_i_n # 8.18. a package to implement compound lists # _m_o_d_e _a_t_o_m = _u_n_i_o_n(_i_n_t, _r_e_f _l_i_s_t), _l_i_s_t = _s_t_r_u_c_t(_a_t_o_m item, _r_e_f _l_i_s_t rest); _p_r_o_c size = (_r_e_f _l_i_s_t h)_i_n_t: _i_f h:=:_n_i_l _t_h_e_n 0 _e_l_s_e size(rest _o_f h)+(item _o_f h|(_i_n_t):1,(_r_e_f _l_i_s_t k):size(k)) _f_i; _p_r_o_c agree = (_a_t_o_m a,b)_b_o_o_l: _c_a_s_e a _i_n (_i_n_t i):(b|(_i_n_t j):i=j|_f_a_l_s_e), (_r_e_f _l_i_s_t h1):(b|(_r_e_f _l_i_s_t h2):eqn(h1,h2)|_f_a_l_s_e) _e_s_a_c; _p_r_o_c eqn = (_r_e_f _l_i_s_t h1,h2)_b_o_o_l: _i_f h1:=:_n_i_l _t_h_e_n h2:=:_n_i_l _e_l_i_f h2:=:_n_i_l _t_h_e_n _f_a_l_s_e _e_l_i_f agree(item _o_f h1,item _o_f h2) _t_h_e_n eqn(rest _o_f h1,rest _o_f h2) _e_l_s_e _f_a_l_s_e _f_i; _p_r_o_c delete = (_r_e_f _l_i_s_t h, _a_t_o_m a)_r_e_f _l_i_s_t: _i_f h:=:_n_i_l _t_h_e_n _n_i_l _e_l_i_f agree(item _o_f h,a) _t_h_e_n delete(rest _o_f h,a) _e_l_s_e rest _o_f h:=delete(rest _o_f h,a); _c_a_s_e item _o_f h _i_n (_r_e_f _l_i_s_t h1):item _o_f h:=delete(h1,a) _e_s_a_c; h _f_i; _p_r_o_c out = (_r_e_f _l_i_s_t h)_v_o_i_d: _i_f h:=:_n_i_l _t_h_e_n print(" ~ ") _e_l_s_e print("("); (item _o_f h|(_i_n_t i):print((blank,i)), (_r_e_f _l_i_s_t h):out(h)); print("|"); out(rest _o_f h); print(")") _f_i; _p_r_o_c copy = (_r_e_f _l_i_s_t h)_r_e_f _l_i_s_t: _i_f h:=:_n_i_l _t_h_e_n _n_i_l _e_l_s_e _h_e_a_p _l_i_s_t:=((item _o_f h|(_i_n_t i):i,(_r_e_f _l_i_s_t h):copy(h)), copy(rest _o_f h) ) _f_i; _a_t_o_m one:=1, two:=2, zero:=0; _l_i_s_t l1,l2,l3,l4,l5,l6,l7; _l_i_s_t head:=(one,l1); l1:=(l2,l3); l2:=(two,l4); l3:=(one,l5); l4:=(l6,_n_i_l); l5:=(l7,_n_i_l); l6:=(one,_n_i_l); l7:=(one,_n_i_l); out(head); print((newline," size=",size(head),newline)); _r_e_f _l_i_s_t d1=delete(copy(head),one); out(d1); print((newline," size=",size(d1),newline)); _r_e_f _l_i_s_t d2=delete(copy(head),two); out(d2); print((newline," size=",size(d2),newline)); _r_e_f _l_i_s_t d3=delete(delete(head,l2),one); out(d3); print((newline," size=",size(d3),newline)) _e_n_d ***** ( 1 |(( 2 |(( 1 | ~ )| ~ ))|( 1 |(( 1 | ~ )| ~ )))) size=5 (( 2 |( ~ | ~ ))|( ~ | ~ )) size=1 ( 1 |((( 1 | ~ )| ~ )|( 1 |(( 1 | ~ )| ~ )))) size=4 ( ~ | ~ ) size=0 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.19. Euler summation # _p_r_o_c euler = (_p_r_o_c(_i_n_t)_r_e_a_l f, _r_e_a_l eps, _i_n_t tim)_r_e_a_l: _b_e_g_i_n _i_n_t n:=1,t; _r_e_a_l mn,ds:=eps; [1:16]_r_e_a_l m; _r_e_a_l sum:=(m[1]:=f(1))/2; _f_o_r i _f_r_o_m 2 _w_h_i_l_e (t:=(_a_b_s ds < eps|t+1|1))<=tim _d_o mn:=f(i); _f_o_r k _t_o n _d_o mn:=((ds:=mn)+m[k])/2;m[k]:=ds _o_d; sum+:=(ds:=(_a_b_s mn < _a_b_s m[n] _a_n_d n<16|n+:=1;m[n]:=mn;mn/2|mn)) _o_d; sum _e_n_d; print(4*euler((_i_n_t i)_r_e_a_l:(_o_d_d i|1/(2*i-1)|-1/(2*i-1)),1e-6,2)) _e_n_d ***** 3.141592 ------------------------------------------------------------------------------ _b_e_g_i_n # 8.20. formula manipulation # _m_o_d_e _E = _s_t_r_u_c_t(_r_F L, _i_n_t op, _r_F R); _m_o_d_e _F = _u_n_i_o_n(_r_e_a_l, _c_h_a_r, _E); _m_o_d_e _r_F = _r_e_f _F; _F zero:=0.0, one:=1.0; _o_p = = (_r_F a, _i_n_t b)_b_o_o_l: _c_a_s_e a _i_n (_r_e_a_l x): _a_b_s(x-b)<1e-5 _o_u_t _f_a_l_s_e _e_s_a_c; _o_p + = (_r_F a,b)_r_F: _i_f a=0 _t_h_e_n b _e_l_i_f b=0 _t_h_e_n a _e_l_s_e _h_e_a_p _F := _E((a,1,b)) _f_i; _o_p - = (_r_F a,b)_r_F: _i_f b=0 _t_h_e_n a _e_l_s_e _h_e_a_p _F := _E((a,2,b)) _f_i; _o_p * = (_r_F a,b)_r_F: _i_f a=0 _o_r b=0 _t_h_e_n zero _e_l_i_f a=1 _t_h_e_n b _e_l_i_f b=1 _t_h_e_n a _e_l_s_e _h_e_a_p _F := _E((a,3,b)) _f_i; _o_p / = (_r_F a,b)_r_F: _i_f a=0 _t_h_e_n zero _e_l_i_f b=1 _t_h_e_n a _e_l_s_e _h_e_a_p _F := _E((a,4,b)) _f_i; _p_r_i_o = =4, + =6,- =6,* =7,/ =7; _p_r_o_c der = (_r_F f)_r_F: _c_a_s_e f _i_n (_r_e_a_l): zero, (_c_h_a_r): one, (_E e ): _c_a_s_e _r_F Le=L _o_f e, Re=R _o_f e; _r_F dLe=der(Le), dRe=der(Re); op _o_f e _i_n dLe+dRe, dLe-dRe, Le*dRe+dLe*Re, (dLe-f*dRe)/Re _e_s_a_c _e_s_a_c; _p_r_o_c value = (_r_F f, _r_e_a_l x)_r_e_a_l: _c_a_s_e f _i_n (_r_e_a_l y): y, (_c_h_a_r ): x, (_E e ): _c_a_s_e _r_e_a_l L=value(L _o_f e,x), R=value(R _o_f e,x); op _o_f e _i_n L+R, L-R, L*R, L/R _e_s_a_c _e_s_a_c; _p_r_o_c write = (_r_F f)_v_o_i_d: _c_a_s_e f _i_n (_u_n_i_o_n(_r_e_a_l, _c_h_a_r) y): print(y), (_E e): (print("("); write(L _o_f e); print((op _o_f e|"+", "-", "*", "/")); write(R _o_f e); print(")") ) _e_s_a_c; _F x:="x"; _r_F f:=(one-x)/(one-x); _r_F df=der(f); print(newline); write(f); print(newline); write(df); print(newline); print((value(f,0), value(df,0))) _e_n_d ***** ((1 -x)/(1 -x)) (((0 -1 )-(((1 -x)/(1 -x))*(0 -1 )))/(1 -x)) 1 0 ------------------------------------------------------------------------------