[comp.lang.modula2] diff -c pim2 pim3

neitzel@infbs.UUCP (Martin Neitzel) (06/24/89)

This is a context diff between the 2nd and the 3rd edition of
"Programming in Modula-2".


*** pim2	Sat Jun 24 01:43:02 1989
--- pim3	Sat Jun 24 01:33:31 1989
***************
*** 129,136 ****
  
  $	string = "'" {character} "'" | '"' {character} '"'.
  
! A single-character string is of type CHAR, a string consisting of n > 1 
! characters is of type (see 6.4)
  
  	ARRAY [0..n-1] OF CHAR
  
--- 129,135 ----
  
  $	string = "'" {character} "'" | '"' {character} '"'.
  
! A string consisting of n characters is of type (see 6.4)
  
  	ARRAY [0..n-1] OF CHAR
  
***************
*** 141,147 ****
  4. `Operators and delimiters' are the special characters, character
  pairs, or reserved words listed below.  These reserved words consist
  exclusively of capital letters and _must_ _not_ be used in the role of
! identifiers.  The symbols # and <> are synonyms, and so are & and AND.
  
  	+	=	AND		FOR		QUALIFIED
  	-	#	ARRAY		FROM		RECORD
--- 140,147 ----
  4. `Operators and delimiters' are the special characters, character
  pairs, or reserved words listed below.  These reserved words consist
  exclusively of capital letters and _must_ _not_ be used in the role of
! identifiers.  The symbols # and <> are synonyms, and so are &, AND,
! and ~, NOT.
  
  	+	=	AND		FOR		QUALIFIED
  	-	#	ARRAY		FROM		RECORD
***************
*** 201,228 ****
  An identifier may be `qualified'.  In this case it is prefixed by
  another identifier which designates the module (see Ch.11) in which
  the qualified identifier is defined.  The prefix and the identifier
! are separated by a period.
  
  $	qualident = ident { "." ident }.
  
! The following are standard identifiers:
  
- 			
- 			
- 	ABS		(10.2)		HIGH		(10.2)
- 	BITSET		(6.6)		INC		(10.2)
- 	BOOLEAN		(6.1)		INCL		(10.2)
- 	CAP		(10.2)		INTEGER		(6.1)
- 	CARDINAL	(6.1)		NEW		(10.2)
- 	CHAR		(6.1)		NIL		(6.7)
- 	CHR		(10.2)		ODD		(10.2)
- 	DEC		(10.2)		ORD		(10.2)
- 	DISPOSE		(10.2)		PROC		(6.8)
- 	EXCL		(10.2)		REAL		(6.1)
- 	FALSE		(6.1)		TRUE		(6.1)
- 	FLOAT		(10.2)		TRUNC		(10.2)
- 	HALT		(10.2)		VAL		(10.2)
- 
  
  5. Constant declarations
  
--- 201,226 ----
  An identifier may be `qualified'.  In this case it is prefixed by
  another identifier which designates the module (see Ch.11) in which
  the qualified identifier is defined.  The prefix and the identifier
! are separated by a period.  Standard identifiers appear below.
  
  $	qualident = ident { "." ident }.
  
! 	ABS		(10.2)		INCL		(10.2)
! 	BITSET		(6.6)		INTEGER		(6.1)
! 	BOOLEAN		(6.1)		LONGINT		(6.1)
! 	CAP		(10.2)		LONGREAL	(6.1)
! 	CARDINAL	(6.1)		MAX		(10.2)
! 	CHAR		(6.1)		MIN		(10.2)
! 	CHR		(10.2)		NIL		(6.7)
! 	DEC		(10.2)		ODD		(10.2)
! 	EXCL		(10.2)		ORD		(10.2)
! 	FALSE		(6.1)		PROC		(6.8)
! 	FLOAT		(10.2)		REAL		(6.1)
! 	HALT		(10.2)		SIZE		(10.2)
! 	HIGH		(10.2)		TRUE		(6.1)
! 	INC		(10.2)		TRUNC		(10.2)
! 					VAL		(10.2)
  
  
  5. Constant declarations
  
***************
*** 229,248 ****
  A constant declaration associates an identifier with a constant value.
  
  $	ConstantDeclaration = indent "=" ConstExpression.
! $	ConstExpression = SimpleConstExpr [relation SimpleConstExpr].
! $	relation = "=" | "#" | "<>" | "<" | "<=" | ">" | ">=" | IN.
! $	SimpleConstExpr = ["+"|"-"] ConstTerm {AddOperator ConstTerm}.
! $	AddOperator = "+" | "-" | OR.
! $	ConstTerm = ConstFactor {MulOperator ConstFactor}.
! $	MulOperator = "*" | "/" | DIV | MOD | AND | "&".
! $	ConstFactor = qualident | number | string | set |
! $		"(" ConstExpression ")" | NOT ConstFactor.
! $	set = [qualident] "{" [element {"," element}] "}".
! $	element = ConstExpression [".." ConstExpression].
  
! The meaning of operators is explained in Chapter 8.  The identifier
! preceding the left brace of a set specifies the type of the set.  If
! it is omitted, the standard type BITSET is assumed (see 6.6).
  
  Examples of constant declarations are
  
--- 227,237 ----
  A constant declaration associates an identifier with a constant value.
  
  $	ConstantDeclaration = indent "=" ConstExpression.
! $	ConstExpression = expression.
  
! A constant expression is an expression which can be evaluated by a
! mere textual scan without actually executing the program.  Its
! operands are constants.  (see Ch.8).
  
  Examples of constant declarations are
  
***************
*** 249,254 ****
--- 238,244 ----
  	N	= 100
  	limit	= 2*N-1
  	all	= {0..WordSize-1}
+ 	bound	= MAX (INTEGER) - N
  
  
  6. Type declarations
***************
*** 281,302 ****
  The following basic types are predeclared and denoted by standard
  identifiers:
  
! 1. A variable of type INTEGER assumes as values the integers between
!    MinInt and MaxInt.
  
! 2. A variable of type CARDINAL assumes as values the integers between
!    0 and MaxCard.
  
! 3. A variable of type BOOLEAN assumes the truth values TRUE or FALSE.
!    These are the only values of this type.
  
! 4. A variable of type CHAR assumes as elements values the character
!    set provided by the used computer system.
  
! 5. A variable of type REAL assumes as values real numbers.
  
! For implementations on 16-bit computers, MinInt = -32678, MaxInt =
! 32767, and MaxCard = 65535.
  
  
  6.2 Enumerations
--- 271,289 ----
  The following basic types are predeclared and denoted by standard
  identifiers:
  
! 1. INTEGER comprises the integers between MIN(INTEGER) and
!    MAX(INTEGER).
  
! 2. CARDINAL comprises the integers between 0 and MAX(CARDINAL).
  
! 3. BOOLEAN comprises the truth values TRUE or FALSE.
  
! 4. CHAR denotes the character set provided by the used computer system.
  
! 5. REAL (and LONGREAL) denote finite sets of real numbers.
  
! 6. LONGINT comprises the integers between MIN(LONGINT) and
!    MAX(LONGINT).
  
  
  6.2 Enumerations
***************
*** 324,330 ****
  type T1 (except REAL) by specification of the least and the highest
  value in the subrange.
  
! $	SubrangeType = "[" ConstExpression ".."	ConstExpression "]".
  
  The first constant specifies the lower bound, and must not be greater
  than the upper bound.  The type T1 of the bounds is called the `base
--- 311,317 ----
  type T1 (except REAL) by specification of the least and the highest
  value in the subrange.
  
! $	SubrangeType = [ident] "[" ConstExpression ".." ConstExpression "]".
  
  The first constant specifies the lower bound, and must not be greater
  than the upper bound.  The type T1 of the bounds is called the `base
***************
*** 332,339 ****
  also applicable to operands of type T.  However, a value to be
  assigned to a variable of a subrange type must lie within the
  specified interval.
! If the lower bound is a non-negative integer, the base type of the
! subrange is taken to be CARDINAL;
  if it is a negative integer, it is INTEGER.
  
  A type T1 is said to be `compatible' with a type T0, if it is declared
--- 319,327 ----
  also applicable to operands of type T.  However, a value to be
  assigned to a variable of a subrange type must lie within the
  specified interval.
! The base type can be specified by an identifier preceding the bounds.
! If it is omitted, and if the lower bound is a non-negative integer,
! the base type of the subrange is taken to be CARDINAL;
  if it is a negative integer, it is INTEGER.
  
  A type T1 is said to be `compatible' with a type T0, if it is declared
***************
*** 398,406 ****
  $	RecordType = RECORD FieldListSequence END.
  $	FieldListSequence = FieldList { ";" FieldList }.
  $	FieldList = [IdentList ":" type |
! $		CASE [ident ":"] qualident OF variant { "|" variant }
  $		[ELSE FieldListSequence ] END].
! $	variant = CaseLabelList ":" FieldListSequence.
  $	CaseLabelList = CaseLabels {"," CaseLabels }.
  $	CaseLabels = ConstExpression [ ".." ConstExpression ].
  
--- 386,394 ----
  $	RecordType = RECORD FieldListSequence END.
  $	FieldListSequence = FieldList { ";" FieldList }.
  $	FieldList = [IdentList ":" type |
! $		CASE [ident] ":" qualident OF variant { "|" variant }
  $		[ELSE FieldListSequence ] END].
! $	variant = [CaseLabelList ":" FieldListSequence].
  $	CaseLabelList = CaseLabels {"," CaseLabels }.
  $	CaseLabels = ConstExpression [ ".." ConstExpression ].
  
***************
*** 455,462 ****
  
  Variables of a pointer type P assume as values pointers to
  variables of another type T.  The pointer type P is said to be `bound'
! to T.  A pointer value is generated by a call to the standard
! procedure NEW (see 10.2).
  
  $	PointerType = POINTER TO type.
  
--- 443,450 ----
  
  Variables of a pointer type P assume as values pointers to
  variables of another type T.  The pointer type P is said to be `bound'
! to T.  A pointer value is generated by a call to an allocation
! procedure in a storage management module.
  
  $	PointerType = POINTER TO type.
  
***************
*** 508,514 ****
  		 RECORD ch: CHAR;
  		  count: CARDINAL
  		 END
- 	t:	TreePtr
  
  
  8. Expressions
--- 496,501 ----
***************
*** 568,577 ****
--- 555,569 ----
  are executed from left to right.
  
  $	expression = SimpleExpression [relation SimpleExpression].
+ $	relation = "=" | "#" | "<" | "<=" | ">" | ">=" | IN.
  $	SimpleExpression = ["+"|"-"] term {AddOperator term}.
+ $	AddOperator = "+" | "-" | OR.
  $	term = factor {MulOperator factor}.
+ $	MulOperator = "*" | "/" | DIV | MOD | AND.
  $	factor = number | string | set | designator [ActualParameters] |
  $		"(" expression ")" | NOT factor.
+ $	set = [qualident] "{" [element {"," element}] "}".
+ $	element = expression [".." expression].
  $	ActualParameters = "(" [ExpList] ")".
  
  The available operators are listed in the following tables.  In some
***************
*** 606,614 ****
  MOD are defined by the following rules:
  
  	x DIV y is equal to the truncated quotient of x/y
! 	x MOD y is equal to the remainder of the division x DIV y (for
! 		y>0)
! 	x = (x DIV y) * y + (x MOD y)
  
  8.2.2. Logical operators
  
--- 598,605 ----
  MOD are defined by the following rules:
  
  	x DIV y is equal to the truncated quotient of x/y
! 	x MOD y is equal to the remainder of the division x DIV y
! 	x = (x DIV y) * y + (x MOD y), 0 <= (x MOD y) < y
  
  8.2.2. Logical operators
  
***************
*** 717,722 ****
--- 708,714 ----
  A string of length n1 can be assigned to a string variable of length
  n2 > n1.
  In this case, the string value is extended with a null character (0C).
+ A string of length 1 is compatible with the type CHAR.
  
  Examples of assignments:
  
***************
*** 748,755 ****
  actual parameter must be an expression.  This expression is evaluated
  prior to the procedure activation, and the resulting value is assigned
  to the formal parameter which now constitutes a local variable.  The
! types of corresponding actual and formal parameters must be compatible
! in the case of variable parameters and assignment compatible in the
  case of value parameters.
  
  $	ProcedureCall = designator [ActualParameters].
--- 740,747 ----
  actual parameter must be an expression.  This expression is evaluated
  prior to the procedure activation, and the resulting value is assigned
  to the formal parameter which now constitutes a local variable.  The
! types of corresponding actual and formal parameters must be identical
! in the case of variable parameters, or assignment compatible in the
  case of value parameters.
  
  $	ProcedureCall = designator [ActualParameters].
***************
*** 806,812 ****
  
  $	CaseStatement = CASE expression OF case {"|" case}
  $		[ELSE StatementSequence] END.
! $	case = CaseLabelList ":" StatementSequence.
  
  Example:
  
--- 798,804 ----
  
  $	CaseStatement = CASE expression OF case {"|" case}
  $		[ELSE StatementSequence] END.
! $	case = [CaseLabelList ":" StatementSequence].
  
  Example:
  
***************
*** 878,884 ****
  successively assuming values A, A+C, A+2C, ... , A+nC where A+nC is
  the last term not exceeding B.  v is called the control variable, A
  the starting value, B the limit, and C the increment.  A and B must be
! assignment compatible with v; C must be a constant of type INTEGER or
  CARDINAL.  If no increment is specified, it is assumed to be 1.
  
  Examples:
--- 870,876 ----
  successively assuming values A, A+C, A+2C, ... , A+nC where A+nC is
  the last term not exceeding B.  v is called the control variable, A
  the starting value, B the limit, and C the increment.  A and B must be
! compatible with v; C must be a constant of type INTEGER or
  CARDINAL.  If no increment is specified, it is assumed to be 1.
  
  Examples:
***************
*** 1026,1033 ****
  $	FormalType = [ARRAY OF] qualident
  
  The type of each formal parameter is specified in the parameter list.
! In the case of variable parameters it must be compatible with its
! corresponding actual parameter (see 9.2),
  in the case of value parameters the formal type must be assignment
  compatible with the actual type (see 9.1).  If the parameter is an
  array, the form
--- 1018,1025 ----
  $	FormalType = [ARRAY OF] qualident
  
  The type of each formal parameter is specified in the parameter list.
! In the case of variable parameters it must be identical with its
! corresponding actual parameter (see 9.2, and 12. for exceptions);
  in the case of value parameters the formal type must be assignment
  compatible with the actual type (see 9.1).  If the parameter is an
  array, the form
***************
*** 1107,1112 ****
--- 1099,1108 ----
  
  	HIGH(a)		high index bound of array a.
  
+ 	MAX(T)		the maximum value of type T.
+ 
+ 	MIN(T)		the minimum value of type T.
+ 
  	ODD(x)		x MOD 2 # 0.
  
  	ORD(x)		ordinal number (of type CARDINAL) of x in the
***************
*** 1114,1119 ****
--- 1110,1119 ----
  			any enumeration type, CHAR, INTEGER, or
  			CARDINAL.
  
+ 	SIZE(T)		the number of storage units required by a
+ 			variable of type T, or the number of storage
+ 			units required by the variable T.
+ 
  	TRUNC(x)	real number x truncated to its integral part
  			(of type CARDINAL).
  
***************
*** 1134,1153 ****
  types and of type CHAR.  In these cases they replace x by its (n-th)
  successor or predecessor.
  
- NEW and DISPOSE are translated into calls to ALLOCATE and DEALLOCATE,
- procedures that are either explicitly programmed or imported from
- another module.
  
- 	NEW(p)			= ALLOCATE(p,TSIZE(T))
- 	DISPOSE(p)		= DEALLOCATE(p,TSIZE(T))
- 	NEW(p,t1,t2,...)	= ALLOCATE(p,TSIZE(T,t1,t2,...))
- 	DISPOSE(p,t1,t2,...)	= DEALLOCATE(p,TSIZE(T,t1,t2,...))
- 
- TSIZE is defined in Chapter 12, and p is declared as "VAR p: POINTER
- TO T".  These procedures must be compatible with the type
- 
- 	PROCEDURE(VAR ADDRESS, CARDINAL)
- 
  
  11. Modules
  
--- 1134,1140 ----
***************
*** 1199,1211 ****
  If a record type is exported, all its field identifiers are exported
  too.  The same holds for the constant identifiers in the case of an
  enumeration type.
- If a module identifier is exported, then all identifiers occurring in
- that module's export list are also exported.
  
- Standard identifiers are always imported automatically.  As a
- consequence, standard identifiers can be declared in procedures only,
- but not in modules, including the compilation unit (see Ch. 14).
- 
  Examples of module declarations:
  
  The following module serves to scan a text and to copy it into an
--- 1186,1192 ----
***************
*** 1318,1326 ****
  	therefore called a pseudo-module and need not be supplied as a
  	separate definition module (see Ch. 14).
  
! The module SYSTEM exports the types WORD, ADDRESS, PROCESS, and the
! procedures ADR, SIZE, TSIZE, NEWPROCESS, TRANSFER, and possibly other
! identifiers depending on the implementation being used (see Ch. 13).
  
  The type WORD represents an individually accessible storage unit.  No
  operation except assignment is defined on this type.  However, if a
--- 1299,1308 ----
  	therefore called a pseudo-module and need not be supplied as a
  	separate definition module (see Ch. 14).
  
! The facilities exported from the module SYSTEM are specified by
! individual implementations.  Normally, the types WORD and ADDRESS, and
! the procedures ADR, TSIZE, NEWPROCESS, TRANSFER, are among them (see
! also Ch. 13).
  
  The type WORD represents an individually accessible storage unit.  No
  operation except assignment is defined on this type.  However, if a
***************
*** 1327,1333 ****
  formal parameter of a procedure is of type WORD, the corresponding
  actual parameter may be of any type that uses one storage word in the
  given implementation.
- This includes the types CARDINAL, INTEGER, BITSET, and all pointers.
  If a formal parameter has the type ARRAY OF WORD, its corresponding
  actual parameter may be of any type; in particular it may be a record
  type to be interpreted as an array of words.
--- 1309,1314 ----
***************
*** 1340,1345 ****
--- 1321,1329 ----
  CARDINAL.  Therefore, all operators for integer arithmetic apply to
  operands of this type.  Hence, the type ADDRESS can be used to perform
  address computations and to export the results as pointers.
+ If a formal parameter is of type ADDRESS, the corresponding actual
+ parameter may be of any pointer type, even if the formal parameter is
+ a VAR parameter.
  The following example of a primitive storage allocator demonstrates a
  typical usage of the type ADDRESS.
  
***************
*** 1350,1356 ****
  	 VAR lastused: ADDRESS;
  
  	 PROCEDURE Allocate (VAR a: ADDRESS; n: CARDINAL);
! 	 BEGIN a := lastused; INC (lastused,n)
  	 END Allocate;
  
  	BEGIN lastused := 0
--- 1334,1340 ----
  	 VAR lastused: ADDRESS;
  
  	 PROCEDURE Allocate (VAR a: ADDRESS; n: CARDINAL);
! 	 BEGIN a := lastused; lastused := lastused+n
  	 END Allocate;
  
  	BEGIN lastused := 0
***************
*** 1357,1366 ****
  	END Storage
  
  The function ADR(x) denotes the storage address of the variable x and
! is of type ADDRESS.  SIZE(x) denotes the number of storage units
! assigned to the variable x.  TSIZE(T) is the number od storage units
! assigned to any variable of type T.  SIZE and TSIZE are of type
! CARDINAL.
  
  Examples:
  
--- 1341,1349 ----
  	END Storage
  
  The function ADR(x) denotes the storage address of the variable x and
! is of type ADDRESS.  TSIZE(T) is the number od storage units assigned
! to any variable of type T.  TSIZE is of an arithmetic type depending
! on the implementation.
  
  Examples:
  
***************
*** 1373,1379 ****
  Evidently, such functions are data representation dependent, and they
  involve no explicit conversion instructions.
  
! The second facility is used in variable declarations.
  It allows to specify the absolute address of a variable and to
  override the allocation scheme of a compiler.  This facility is
  intended for access to storage locations with specific purpose and
--- 1356,1363 ----
  Evidently, such functions are data representation dependent, and they
  involve no explicit conversion instructions.
  
! The second, non-standard facility may be provided in variable
! declarations.
  It allows to specify the absolute address of a variable and to
  override the allocation scheme of a compiler.  This facility is
  intended for access to storage locations with specific purpose and
***************
*** 1382,1388 ****
  expression enclosed in brackets immediately following the identifier
  in the variable declaration.  The choice of an appropriate data type
  is left to the programmer.
- For examples, refer to 13.2.
  
  
  
--- 1366,1371 ----
***************
*** 1401,1407 ****
  A new process is created by a call to
  
  	PROCEDURE NEWPROCESS (P: PROC;
! 	    A: ADDRESS; n: CARDINAL; VAR p1:PROCESS)
  
  	P   denotes the procedure which constitutes the process,
  	A   is the base address of the process' workspace,
--- 1384,1390 ----
  A new process is created by a call to
  
  	PROCEDURE NEWPROCESS (P: PROC;
! 	    A: ADDRESS; n: CARDINAL; VAR p1:ADDRESS)
  
  	P   denotes the procedure which constitutes the process,
  	A   is the base address of the process' workspace,
***************
*** 1414,1426 ****
  
  A transfer of control between two processes is specified by a call to
  
! 	PROCEDURE TRANSFER (VAR p1, p2:PROCESS)
  
  This call suspends the current process, assigns it to p1, and resumes
  the process designated by p2.  Evidently, p2 must have been assigned a
  process by an earlier call to either NEWPROCESS or TRANSFER.  Both
! procedures, as well as the type PROCESS, must be imported from the
! module SYSTEM.
  A program terminates, when control reaches the end of a procedure
  which is the body of a process.
  
--- 1397,1408 ----
  
  A transfer of control between two processes is specified by a call to
  
! 	PROCEDURE TRANSFER (VAR p1, p2:ADDRESS)
  
  This call suspends the current process, assigns it to p1, and resumes
  the process designated by p2.  Evidently, p2 must have been assigned a
  process by an earlier call to either NEWPROCESS or TRANSFER.  Both
! procedures must be imported.
  A program terminates, when control reaches the end of a procedure
  which is the body of a process.
  
***************
*** 1440,1446 ****
  PDP-11) preprogrammed by and combined with the transfer after device
  initiation.  This combination is expressed by a call to
  
! 	PROCEDURE IOTRANSFER (VAR p1, p2: PROCESS; va: CARDINAL)
  
  In analogy to TRANSFER, this call suspends the calling device process,
  assigns it to p1, resumes (transfers to) the suspended process p2, and
--- 1422,1428 ----
  PDP-11) preprogrammed by and combined with the transfer after device
  initiation.  This combination is expressed by a call to
  
! 	PROCEDURE IOTRANSFER (VAR p1, p2: ADDRESS; va: CARDINAL)
  
  In analogy to TRANSFER, this call suspends the calling device process,
  assigns it to p1, resumes (transfers to) the suspended process p2, and
***************
*** 1447,1454 ****
  in addition causes the interrupt transfer occurring upon device
  completion to assign the interrupted process to p2 and to resume the
  device process p1.  va is the interrupt vector address assigned to the
! device.  The procedure IOTRANSFER must be imported from the module
! SYSTEM, and should be considered as PDP-11 implementation-specific.
  
  It is necessary that interrupts can be postponed (disabled) at certain
  times, e.g. when variables common to the cooperating processes are
--- 1429,1436 ----
  in addition causes the interrupt transfer occurring upon device
  completion to assign the interrupted process to p2 and to resume the
  device process p1.  va is the interrupt vector address assigned to the
! device.  The procedure IOTRANSFER must be imported, and should be
! considered as PDP-11 implementation-specific.
  
  It is necessary that interrupts can be postponed (disabled) at certain
  times, e.g. when variables common to the cooperating processes are
***************
*** 1464,1513 ****
  calling program.  IOTRANSFER must be used within modules with a
  specified priority only.
  
- The following example (programmed for the PDP-11) shows a module with
- a process that acts as a driver for a typewriter.  The module contains
- a buffer B for N characters.
  
- 	MODULE Typewriter [4]; (* typewriter interrupt priority = 4 *)
- 	  FROM SYSTEM IMPORT
- 	    PROCESS, NEWPROCESS, TRANSFER, IOTRANSFER, LISTEN,
- 	    WORD, ADR, SIZE;
- 	  EXPORT typeout;
- 
- 	  CONST N = 32;
- 	  VAR n: INTEGER; (* no. of chars in buffer *)
- 	    in, out: [1..N];
- 	    B: ARRAY [1..N] OF CHAR;
- 	    PRO: PROCESS; (* producer *)
- 	    CON: PROCESS; (* consumer = typewriter driver *)
- 	    wsp: ARRAY [1..50] OF WORD;
- 	    TWS [177564B]: BITSET; (* status register *)
- 	    TWB [177566B]: CHAR; (* buffer register *)
- 
- 	  PROCEDURE typeout (ch: CHAR);
- 	  BEGIN INC(n);
- 	    WHILE n>N DO LISTEN END;
- 	    B[in] := ch; in := in MOD N + 1;
- 	    IF n=0 THEN TRANSFER(PRO,CON) END
- 	  END typeout;
- 
- 	  PROCEDURE driver;
- 	  BEGIN
- 	    LOOP DEC(n);
- 	      IF n<0 THEN TRANSFER(CON,PRO) END;
- 	      TWB := B[out]; out := out MOD n + 1;
- 	      TWS := {6}; IOTRANSFER(CON,PRO,64B); TWS := {}
- 	    END
- 	  END driver;
- 
- 	BEGIN n:=0; in:=1; out:=1;
- 	  NEWPROCESS(driver, ADR(wsp), SIZE(wsp), CON);
- 	  TRANSFER (PRO,CON)
- 	END Typewriter
- 
- LISTEN must be a procedure that lowers the processor's priority level
- so that pending interrupts may be accepted.
- 
  
  14. Compilation units
  
--- 1446,1452 ----
***************
*** 1524,1530 ****
  that are relevant to clients, i.e. other modules which import from it.
  The `implementation module' contains local objects and statements that
  need not be known to a client.  In particular the definition module
! contains the export list, constant, type, and variable declarations,
  and specifications of procedure headings.  The corresponding
  implementation module contains the complete procedure declarations,
  and possibly further declarations of objects not exported.  Definition
--- 1463,1469 ----
  that are relevant to clients, i.e. other modules which import from it.
  The `implementation module' contains local objects and statements that
  need not be known to a client.  In particular the definition module
! contains constant, type, and variable declarations,
  and specifications of procedure headings.  The corresponding
  implementation module contains the complete procedure declarations,
  and possibly further declarations of objects not exported.  Definition
***************
*** 1532,1539 ****
  lists, and all objects declared in the definition module are available
  in the corresponding implementation module without explicit import.
  
! $	DefinitionModule = DEFINITION MODULE ident ";" {import} 
! $		[export] {definition} END ident ".".
  $	definition = CONST {ConstantDeclaration ";"} |
  $		TYPE {ident ["=" type] ";"} |
  $		VAR {VariableDeclaration ";"} |
--- 1471,1478 ----
  lists, and all objects declared in the definition module are available
  in the corresponding implementation module without explicit import.
  
! $	DefinitionModule = DEFINITION MODULE ident ";"
! $		{import} {definition} END ident ".".
  $	definition = CONST {ConstantDeclaration ";"} |
  $		TYPE {ident ["=" type] ";"} |
  $		VAR {VariableDeclaration ";"} |
***************
*** 1543,1552 ****
  $	CompilationUnit = DefinitionModule | [IMPLEMENTATION] ProgramModule.
  
  The definition module evidently represents the interface between the
! definition/implementation module pair on one side and its clients on
! the other side.
  
! Definition modules require the use of qualified export.  Type
  definitions may consist of the full specification of the type (in this
  case its export is said to be transparent), or they may consist of the
  type identifier only. In this case the full specification must appear
--- 1482,1494 ----
  $	CompilationUnit = DefinitionModule | [IMPLEMENTATION] ProgramModule.
  
  The definition module evidently represents the interface between the
! implementation module on one side and its clients on the other side.
! The definition module contains those declarations which are relevant
! to the client modules, and presumably no other ones.  Hence, the
! definition module acts as the implementation module's (extended)
! export list, and all its declared objects are exported.
  
! Definition modules imply the use of qualified export.  Type
  definitions may consist of the full specification of the type (in this
  case its export is said to be transparent), or they may consist of the
  type identifier only. In this case the full specification must appear
***************
*** 1556,1559 ****
  operating on operands of this type, and in particular operating on its
  components, must be defined in the same implementation module which
  hides the type's properties.  Opaque export is restricted to
! pointers and to subranges of standard types.
--- 1498,1508 ----
  operating on operands of this type, and in particular operating on its
  components, must be defined in the same implementation module which
  hides the type's properties.  Opaque export is restricted to
! pointers.
! Assignment and test for equality are applicable to all opaque types.
! 
! As in local modules, the body of an implementation module acts as an
! initialization facility for its local objects.  Before its execution,
! the imported modules are initialized in the order in which they are
! listed.  If circular references occur among modules, their order of
! initialization is not defined.