Initial revision
This commit is contained in:
		
							parent
							
								
									00b8ca7b58
								
							
						
					
					
						commit
						690cd32023
					
				
					 12 changed files with 785 additions and 0 deletions
				
			
		
							
								
								
									
										17
									
								
								doc/occam/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								doc/occam/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| EMHOME=../.. | ||||
| FILES= p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 | ||||
| 
 | ||||
| PIC=pic | ||||
| EQN=eqn | ||||
| TBL=tbl | ||||
| ../occam.doc:	p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 channel.h.t channel.c.t | ||||
| 	cat $(FILES) | $(PIC) | $(TBL) | $(EQN) > $@ | ||||
| 
 | ||||
| channel.h.t:	$(EMHOME)/h/ocm_chan.h | ||||
| 	ctot <$(CDIR)/h/ocm_chan.h >channel.h.t | ||||
| 
 | ||||
| channel.c.t:	channel.c | ||||
| 	ctot <channel.c >channel.c.t | ||||
| 
 | ||||
| channel.c:	$(EMHOME)/lang/occam/lib/tail_ocm.a | ||||
| 		arch x tail_ocm.a channel.c | ||||
							
								
								
									
										8
									
								
								doc/occam/ctot
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								doc/occam/ctot
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| sed 's/^$/.sp 0.5/ | ||||
| s/\\/\\e/g | ||||
| s/^$/.ft\ | ||||
| .DE\ | ||||
| .bp\ | ||||
| .DS\ | ||||
| .ft 5\ | ||||
| .ta 0.65i 1.3i 1.95i 2.6i 3.25i 3.9i 4.55i 5.2i 5.85i 6.5i/' | ||||
							
								
								
									
										21
									
								
								doc/occam/p0
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								doc/occam/p0
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| .pl 11.7i | ||||
| .ND | ||||
| .de PT | ||||
| .if \\n%>0 .if e .tl '\fB%\fP''' | ||||
| .if \\n%>1 .if o .tl '''\fB%\fP' | ||||
| .. | ||||
| .TL | ||||
| An Occam Compiler | ||||
| .AU | ||||
| Kees Bot | ||||
| Edwin Scheffer | ||||
| .AI | ||||
| Vrije Universiteit | ||||
| Amsterdam, The Netherlands | ||||
| .AB | ||||
| This document describes the implementation of an \fBOccam\fP to \fBEM\fP | ||||
| compiler. The lexical analysis is done using \fBLex\fP. | ||||
| For the semantic analysis the extended LL(1) parser generator \fBLLgen\fP is | ||||
| used. To handle the Occam-specific features as channels and parallelism some | ||||
| library routines are required. | ||||
| .AE | ||||
							
								
								
									
										87
									
								
								doc/occam/p1
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								doc/occam/p1
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,87 @@ | |||
| .NH | ||||
| Introduction | ||||
| .PP | ||||
| Occam [1] is a programming language which is based on the concepts of | ||||
| concurrency and communication. These concepts enable today's applications of | ||||
| microprocessors and computers to be implemented more effectively.  | ||||
| .PP | ||||
| An Occam program consists of a (dynamically determined) number | ||||
| of processes communicating through channels. | ||||
| To communicate with the outside world some predefined channels are needed. | ||||
| A channel has only one writer and one reader; it carries machine words and | ||||
| bytes, at the reader/writer's discretion. The process with its communication | ||||
| in Occam replaces the procedure with parameters in other languages (there are | ||||
| no procedures in Occam). | ||||
| .PP | ||||
| In addition to the normal assignment statement, Occam has two more | ||||
| information-transfer statements, the input and the output: | ||||
| .DS | ||||
| .ft 5 | ||||
| 	chan1 ? x        -- reads a value from chan1 into x | ||||
| 	chan2 ! x        -- writes the value of x onto chan2 | ||||
| .ft | ||||
| .DE | ||||
| Both the outputting and the inputting processes wait until the other is there. | ||||
| Channels are declared and given names. Arrays of channels are possible. | ||||
| .PP | ||||
| Processes come in 5 varieties: sequential, parallel, alternative, | ||||
| conditional and repetitive. A process starts with a reserved word telling | ||||
| its nature, followed by an indented list of other processes. (Indentation | ||||
| is used to indicate block structure.) It may be preceded by declarations. | ||||
| The processes in a sequential/parallel process are executed sequentially/in | ||||
| parallel. The processes in an alternative process have guards based on the | ||||
| availability of input; the first to be ready is executed (this is waiting | ||||
| for multiple input). The conditional and repetitive processes are normal | ||||
| \fBIF\fPs and \fBWHILE\fPs. | ||||
| .PP | ||||
| \fIProducer-consumer example:\fP | ||||
| .DS | ||||
| .ft 5 | ||||
| .nf | ||||
| CHAN buffer:                    -- declares the channel buffer | ||||
| PAR | ||||
|   WHILE TRUE                    -- the producer | ||||
|     VAR x:                      -- a local variable | ||||
|     SEQ | ||||
|       produce(x)                -- in some way | ||||
|       buffer ! x                -- and send it | ||||
|   WHILE TRUE                    -- the consumer | ||||
|     VAR x: | ||||
|     SEQ | ||||
|       buffer ? x                -- get a value | ||||
|       consume(x)                -- in some way | ||||
| .ft | ||||
| .fi | ||||
| .DE | ||||
| .bp | ||||
| .PP | ||||
| Processes can be replicated from a given template; this combines | ||||
| with arrays of variables and/or channels. | ||||
| .PP | ||||
| \fIExample: 20 window-sorters in series:\fP | ||||
| .DS | ||||
| .ft 5 | ||||
| .nf | ||||
| CHAN s[20]:                     -- 20 channels | ||||
| PAR i = [ 0 FOR 19 ]            -- 19 processes | ||||
|   WHILE TRUE | ||||
|     VAR v1, v2: | ||||
|     SEQ | ||||
|       s[i] ? v1; v2             -- wait for 2 variables from s[i] | ||||
|       IF | ||||
|         v1 <= v2                -- ok | ||||
|           s[i+1] ! v1; v2 | ||||
|         v1 > v2                 -- reorder | ||||
|           s[i+1] ! v2; v1 | ||||
| .fi | ||||
| .ft | ||||
| .DE | ||||
| .PP | ||||
| A process may wait for a condition, which must include a comparison | ||||
| with \fBNOW\fP, the present clock value. | ||||
| .PP | ||||
| Processes may be distributed over several processors; all processes | ||||
| under a \fBVAR\fP declaration must run on the same processor. Concurrency can be | ||||
| improved by avoiding \fBVAR\fP declarations, and replacing them by \fBCHAN\fP | ||||
| declarations. Processes can be allocated explicitly on named processors and | ||||
| channels can be connected to physical ports. | ||||
							
								
								
									
										151
									
								
								doc/occam/p2
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								doc/occam/p2
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,151 @@ | |||
| .NH | ||||
| The Compiler | ||||
| .PP | ||||
| The compiler is written in \fBC\fP using LLgen and Lex and compiles | ||||
| Occam programs to EM code, using the procedural interface as defined for EM. | ||||
| In the following sub-sections we describe the LLgen parser generator and | ||||
| the aspect of indentation. | ||||
| .NH 2 | ||||
| The LLgen Parser Generator | ||||
| .PP | ||||
| LLgen accepts a Context Free syntax extended with the operators `\f5*\fP', `\f5?\fP' and `\f5+\fP' | ||||
| that have effects similar to those in regular expressions. | ||||
| The `\f5*\fP' is the closure set operator without an upperbound; `\f5+\fP' is the positive | ||||
| closure operator without an upperbound; `\f5?\fP' is the optional operator; | ||||
| `\f5[\fP' and `\f5]\fP' can be used for grouping. | ||||
| For example, a comma-separated list of expressions can be described as: | ||||
| .DS | ||||
| .ft 5 | ||||
| 	expression_list: | ||||
| 		  expression [ ',' expression ]* | ||||
| 		; | ||||
| .ft | ||||
| .DE | ||||
| .LP | ||||
| Alternatives must be separated by `\f5|\fP'. | ||||
| C code (``actions'') can be inserted at all points between the colon and the | ||||
| semicolon. | ||||
| Variables global to the complete rule can be declared just in front of the | ||||
| colon enclosed in the brackets `\f5{\fP' and `\f5}\fP'.  All other declarations are local to | ||||
| their actions. | ||||
| Nonterminals can have parameters to pass information. | ||||
| A more mature version of the above example would be: | ||||
| .DS | ||||
| .ft 5 | ||||
|        expression_list(expr *e;)       {	expr e1, e2;	} : | ||||
|                 expression(&e1) | ||||
|                 [ ',' expression(&e2) | ||||
|                                        {	e1=append(e1, e2);	} | ||||
|                 ]* | ||||
|                                        {	*e=e1;	} | ||||
|               ; | ||||
| .ft | ||||
| .DE | ||||
| As LLgen generates a recursive-descent parser with no backtrack, it must at all | ||||
| times be able to determine what to do, based on the current input symbol.  | ||||
| Unfortunately, this cannot be done for all grammars. Two kinds of conflicts | ||||
| are possible, viz. the \fBalternation\fP and \fBrepetition\fP conflict. | ||||
| An alternation confict arises if two sides of an alternation can start with the | ||||
| same symbol. E.g. | ||||
| .DS | ||||
| .ft 5 | ||||
| 	plus:	'+' | '+' ; | ||||
| .ft | ||||
| .DE | ||||
| The parser doesn't know which `\f5+\fP' to choose (neither do we). | ||||
| Such a conflict can be resolved by putting an \fBif-condition\fP in front of | ||||
| the first conflicting production. It consists of a \fB``%if''\fP followed by a | ||||
| C-expression between parentheses. | ||||
| If a conflict occurs (and only if it does) the C-expression is evaluated and | ||||
| parsing continues along this path if non-zero. Example: | ||||
| .DS | ||||
| .ft 5 | ||||
| 	plus: | ||||
| 		  %if (some_plusses_are_more_equal_than_others()) | ||||
| 		  '+' | ||||
| 		| | ||||
| 		  '+' | ||||
| 		; | ||||
| .ft | ||||
| .DE | ||||
| A repetition conflict arises when the parser cannot decide whether | ||||
| ``\f5productionrule\fP'' in e.g. ``\f5[ productionrule ]*\fP'' must be chosen | ||||
| once more, or that it should continue. | ||||
| This kind of conflicts can be resolved by putting a \fBwhile-condition\fP right | ||||
| after the opening parentheses.  It consists of a \fB``%while''\fP | ||||
| followed by a C-expression between parentheses. As an example, we can look at | ||||
| the \fBcomma-expression\fP in C.  The comma may only be used for the | ||||
| comma-expression if the total expression is not part of another comma-separated | ||||
| list: | ||||
| .DS | ||||
| .nf | ||||
| .ft 5 | ||||
| 	comma_expression: | ||||
| 		  sub_expression | ||||
| 		  [ %while (not_part_of_comma_separated_list()) | ||||
| 			  ',' sub_expression | ||||
| 		  ]* | ||||
| 		; | ||||
| .ft | ||||
| .fi | ||||
| .DE | ||||
| Again, the \fB``%while''\fP is only used in case of a conflict. | ||||
| .LP | ||||
| Error recovery is done almost completely automatically. All you have to do | ||||
| is to write a routine called \fILLmessage\fP to give the necessary error | ||||
| messages and supply information about terminals found missing. | ||||
| .NH 2	 | ||||
| Indentation | ||||
| .PP | ||||
| The way conflicts can be resolved are of great use to Occam. The use of | ||||
| indentation, to group statements, leads to many conflicts because the spaces | ||||
| used for indentation are just token separators to the lexical analyzer, i.e. | ||||
| ``white space''. The lexical analyzer can be instructed to generate `BEGIN' and | ||||
| `END' tokens at each indentation change, but that leads to great difficulties | ||||
| as expressions may occupy several lines, thus leading to indentation changes | ||||
| at the strangest moments. So we decided to resolve the conflicts by looking | ||||
| at the indentation ourselves. The lexical analyzer puts the current indentation | ||||
| level in the global variable \fIind\fP for use by the parser. The best example | ||||
| is the \fBSEQ\fP construct, which exists in two flavors, one with a replicator | ||||
| and one process: | ||||
| .DS | ||||
| .nf | ||||
| .ft 5 | ||||
| 	seq i = [ 1 for str[byte 0] ] | ||||
| 		out ! str[byte i] | ||||
| .ft | ||||
| .fi | ||||
| .DE | ||||
| and one without a replicator and several processes: | ||||
| .DS | ||||
| .nf | ||||
| .ft 5 | ||||
| 	seq | ||||
| 		in ? c | ||||
| 		out ! c | ||||
| .ft | ||||
| .fi | ||||
| .DE | ||||
| The LLgen skeleton grammar to handle these two is: | ||||
| .DS | ||||
| .nf | ||||
| .ft 5 | ||||
| 	SEQ			{	line=yylineno; oind=ind; } | ||||
| 	[	  %if (line==yylineno) | ||||
| 		  replicator | ||||
| 		  process | ||||
| 		| | ||||
| 		  [ %while (ind>oind) process ]* | ||||
| 	] | ||||
| .ft | ||||
| .fi | ||||
| .DE | ||||
| This shows clearly that, a replicator must be on the same line as the \fBSEQ\fP, | ||||
| and new processes are collected as long as the indentation level of each process | ||||
| is greater than the indentation level of \fBSEQ\fP (with appropriate checks on this | ||||
| identation). | ||||
| .PP | ||||
| Different indentation styles are accepted, as long as the same amount of spaces | ||||
| is used for each indentation shift. The ascii tab character sets the indentation | ||||
| level to an eight space boundary. The first indentation level found in a file | ||||
| is used to compare all other indentation levels to. | ||||
							
								
								
									
										337
									
								
								doc/occam/p3
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										337
									
								
								doc/occam/p3
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,337 @@ | |||
| .NH | ||||
| Implementation | ||||
| .PP | ||||
| It is now time to describe the implementation of some of the occam-specific | ||||
| features such as channels and \fBNOW\fP. Also the way communication with | ||||
| UNIX\(dg is performed must be described. | ||||
| .FS | ||||
| \(dg UNIX is a trademark of Bell Laboratories | ||||
| .FE | ||||
| For a thorough description of the library routines to simulate parallelism, | ||||
| which are e.g. used by the channel routines and by the \fBPAR\fP construct | ||||
| in Appendix B, see [6]. | ||||
| .NH 2 | ||||
| Channels | ||||
| .PP | ||||
| There are currently two types of channels (see Figure 1.) indicated by the type | ||||
| field of a channel variable: | ||||
| .IP - | ||||
| An interprocess communication channel with two additional fields: | ||||
| .RS | ||||
| .IP - | ||||
| A synchronization field to hold the state of an interprocess communication | ||||
| channel. | ||||
| .IP - | ||||
| An integer variable to hold the value to be send. | ||||
| .RE | ||||
| .IP - | ||||
| An outside world communication channel. This is a member of an array of | ||||
| channels connected to UNIX files. Its additional fields are: | ||||
| .RS | ||||
| .IP - | ||||
| A flags field holding a readahead flag and a flag that tells if this channel | ||||
| variable is currently connected to a file. | ||||
| .IP - | ||||
| A preread character, if readahead is done. | ||||
| .IP - | ||||
| An index field to find the corresponding UNIX file. | ||||
| .RE | ||||
| .LP | ||||
| .PS | ||||
| box ht 3.0 wid 3.0 | ||||
| box ht 0.75 wid 0.75 with .nw at 1st box.nw + (0.5, -0.5) "Process 1" | ||||
| box ht 0.75 wid 0.75 with .ne at 1st box.ne + (-0.5, -0.5) "Process 2" | ||||
| box ht 0.75 wid 0.75 with .sw at 1st box.sw + (0.5, 0.5) "Process 3" | ||||
| box ht 0.75 wid 0.75 with .se at 1st box.se + (-0.5, 0.5) "Process 4" | ||||
| line right from 5/12 <2nd box.ne, 2nd box.se> to 3rd box | ||||
| line right from 7/12 <2nd box.ne, 2nd box.se> to 3rd box | ||||
| line right from 5/12 <4th box.ne, 4th box.se> to 5th box | ||||
| line right from 7/12 <4th box.ne, 4th box.se> to 5th box | ||||
| line down from 5/12 <2nd box.sw, 2nd box.se> to 4th box | ||||
| line down from 7/12 <2nd box.sw, 2nd box.se> to 4th box | ||||
| line down from 5/12 <3rd box.sw, 3rd box.se> to 5th box | ||||
| line down from 7/12 <3rd box.sw, 3rd box.se> to 5th box | ||||
| line right 1.0 from 5/12 <5th box.ne, 5th box.se>  | ||||
| line right 1.0 from 7/12 <5th box.ne, 5th box.se>  | ||||
| line left 1.0 from 5/12 <2nd box.nw, 2nd box.sw>  | ||||
| line left 1.0 from 7/12 <2nd box.nw, 2nd box.sw>  | ||||
| .PE | ||||
| .DS C | ||||
| \fIFigure 1. Interprocess and outside world communication channels\fP | ||||
| .DE | ||||
| The basic channel handling is done by \f5chan_in\fP and \f5chan_out\fP. All | ||||
| other routines are based on them. The routine \f5chan_any\fP only checks if | ||||
| there's a value available on a given channel. (It does not read this value!) | ||||
| \f5C_init\fP initializes an array of interprocess communication channels. | ||||
| .LP | ||||
| The following table shows Occam statements paired with the routines used to | ||||
| execute them. | ||||
| .TS H | ||||
| center, box; | ||||
| c | c | c | ||||
| lf5 | lf5 | lf5. | ||||
| Occam statement	Channel handling routine	Called as | ||||
| = | ||||
| .sp 0.5 | ||||
| .TH | ||||
| T{ | ||||
| .nf | ||||
| CHAN c: | ||||
| CHAN c[z]: | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_init(c, z)  | ||||
| chan *c; unsigned z; | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_init(&c, 1); | ||||
| c_init(&c, z); | ||||
| .fi | ||||
| T} | ||||
| .sp 0.5 | ||||
| _ | ||||
| .sp 0.5 | ||||
| T{ | ||||
| .nf | ||||
| c ? v | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| chan_in(v, c) | ||||
| long *v; chan *c; | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| chan_in(&v, &c); | ||||
| .fi | ||||
| T} | ||||
| .sp 0.5 | ||||
| T{ | ||||
| .nf | ||||
| c ? b[byte i] | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| cbyte_in(b, c) | ||||
| char *b; chan *c; | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| cbyte_in(&b[i], &c); | ||||
| .fi | ||||
| T} | ||||
| .sp 0.5 | ||||
| T{ | ||||
| .nf | ||||
| c ? a[i for z] | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_wa_in(a, z, c) | ||||
| long *a; unsigned z; chan *c; | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_wa_in(&a[i], z, &c); | ||||
| .fi | ||||
| T} | ||||
| .sp 0.5 | ||||
| T{ | ||||
| .nf | ||||
| c ? a[byte i for z] | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_ba_in(a, z, c) | ||||
| long *a; unsigned z; chan *c; | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_ba_in(&a[i], z, &c); | ||||
| .fi | ||||
| T} | ||||
| .sp 0.5 | ||||
| _ | ||||
| .sp 0.5 | ||||
| T{ | ||||
| .nf | ||||
| c ! v | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| chan_out(v, c) | ||||
| long *v; chan *c; | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| chan_out(&v, &c); | ||||
| .fi | ||||
| T} | ||||
| .sp 0.5 | ||||
| T{ | ||||
| .nf | ||||
| c ! a[i for z] | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_wa_out(a, z, c) | ||||
| long *a; unsigned z; chan *c; | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_wa_out(&a[i], z, &c); | ||||
| .fi | ||||
| T} | ||||
| .sp 0.5 | ||||
| T{ | ||||
| .nf | ||||
| c ! a[byte i for z] | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_ba_out(a, z, c) | ||||
| long *a; unsigned z; chan *c; | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| c_ba_out(&a[i], z, &c); | ||||
| .fi | ||||
| T} | ||||
| .sp 0.5 | ||||
| _ | ||||
| .sp 0.5 | ||||
| T{ | ||||
| .nf | ||||
| alt | ||||
| 	c ? .... | ||||
| 		.... | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| int chan_any(c) | ||||
| chan *c; | ||||
| .fi | ||||
| T}	T{ | ||||
| .nf | ||||
| deadlock=0; | ||||
| for(;;) { | ||||
| 	if (chan_any(&c)) { | ||||
| 		.... | ||||
| 	.... | ||||
| .fi | ||||
| T} | ||||
| .sp 0.5 | ||||
| .TE | ||||
| The code of \f5c_init\fP, \f5chan_in\fP, \f5chan_out\fP and \f5chan_any\fP | ||||
| can be found in Appendix A. | ||||
| .NH 3 | ||||
| Synchronization on interprocess communication channels | ||||
| .PP | ||||
| The synchronization field can hold three different values indicating the | ||||
| state the channel is in: | ||||
| .IP "- \fBC\(ulS\(ulFREE\fP:" 15 | ||||
| Ground state, channel not in use. | ||||
| .IP "- \fBC\(ulS\(ulANY\fP:" 15 | ||||
| Channel holds a value, the sending process is waiting for an acknowledgement | ||||
| about its receipt. | ||||
| .IP "- \fBC\(ulS\(ulACK\fP:" 15 | ||||
| Channel data has been removed by a receiving process, the sending process can | ||||
| set the channel free now. | ||||
| .LP | ||||
| A sending process cannot simply wait until the channel changes state C\(ulS\(ulANY | ||||
| to state C\(ulS\(ulFREE before it continues. There is a third state needed to prevent | ||||
| a third process from using the channel before our sending process is  | ||||
| acknowledged. Note, however that it is not allowed to use a channel for input | ||||
| or output in more than one parallel process. This is too difficult to check | ||||
| in practice, so we tried to smooth it a little. | ||||
| .NH 2 | ||||
| NOW | ||||
| .PP | ||||
| \fBNOW\fP evaluates to the current time returned by the time(2) system call. | ||||
| The code is simply: | ||||
| .DS | ||||
| .ft 5 | ||||
| .nf | ||||
| 	long now() | ||||
| 	{ | ||||
| 		deadlock=0; | ||||
| 		return time((long *) 0); | ||||
| 	} | ||||
| .fi | ||||
| .ft | ||||
| .DE | ||||
| The ``deadlock=0'' prevents deadlocks while using the clock. | ||||
| .NH 2 | ||||
| UNIX interface | ||||
| .PP | ||||
| To handle the communication with the outside world the following channels are | ||||
| defined: | ||||
| .IP - | ||||
| \fBinput\fP, that corresponds with the standard input file, | ||||
| .IP - | ||||
| \fBoutput\fP, that corresponds with the standard output file, | ||||
| .IP - | ||||
| \fBerror\fP, that corresponds with the standard error file. | ||||
| .IP - | ||||
| \fBfile\fP, an array of channels that can be subscripted with an index | ||||
| obtained by the builtin named process ``\f5open\fP''. Note that | ||||
| \fBinput\fP=\fBfile\fP[0], \fBoutput\fP=\fBfile\fP[1] and | ||||
| \fBerror\fP=\fBfile\fP[2]. | ||||
| .LP | ||||
| Builtin named processes to open and close files are defined as | ||||
| .DS | ||||
| .nf | ||||
| .ft 5 | ||||
| proc open(var index, value name[], mode[]) = ..... : | ||||
| proc close(value index) = ..... : | ||||
| .fi | ||||
| .ft | ||||
| .DE | ||||
| To open a file `junk', write nonsense onto it, and close it, goes as follows: | ||||
| .DS | ||||
| .ft 5 | ||||
| .nf | ||||
| 	var i: | ||||
| 	seq | ||||
| 		open(i, "junk", "w") | ||||
| 		file[i] ! nonsense | ||||
| 		close(i) | ||||
| .fi | ||||
| .ft | ||||
| .DE | ||||
| Errors opening a file are reported by a negative index, which is the | ||||
| negative value of the error number (called \fIerrno\fP in UNIX). | ||||
| .LP | ||||
| Bytes read from or written onto these channels are taken from occam variables. | ||||
| As these variables can hold more than 256 values, some negative values are used | ||||
| to control channels. These values are: | ||||
| .IP "- \fBEOF\fP" 9 | ||||
| (-1): Eof from file channel is read as -1. | ||||
| .IP "- \fBTEXT\fP" 9 | ||||
| (-2): A -2 written onto any channel connected to a terminal puts this | ||||
| terminal in the normal line oriented mode (i.e. characters typed are echoed | ||||
| and lines are buffered before they are read). | ||||
| .IP "- \fBRAW\fP" 9 | ||||
| (-3): A -3 written onto any channel connected to a terminal puts it in raw mode | ||||
| (i.e. no echoing of typed characters and no line buffering). | ||||
| .LP | ||||
| To exit an Occam program, e.g. after an error, a builtin named process | ||||
| \f5exit\fP is available that takes an exit code as its argument. | ||||
| .NH 2 | ||||
| Replicators and slices | ||||
| .PP | ||||
| Both the base and the count of replicators like in | ||||
| .DS | ||||
| .ft 5 | ||||
| 	par i = [ base for count ] | ||||
| .ft | ||||
| .DE | ||||
| may be arbitrary expressions. The count in array slices like in | ||||
| .DS | ||||
| .ft 5 | ||||
| 	c ? A[ base for count ] | ||||
| .ft | ||||
| .DE | ||||
| must be a constant expression however, the base is again free. | ||||
							
								
								
									
										42
									
								
								doc/occam/p4
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								doc/occam/p4
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| .NH | ||||
| Particular details | ||||
| .NH 2 | ||||
| Lower case/Upper case | ||||
| .PP | ||||
| Keywords must be either fully written in lower case or in upper case, thus | ||||
| \fBPAR\fP is equivalent to \fBpar\fP but \fBPar\fP is not a keyword. Identifiers | ||||
| may be of mixed case. Different styles are used in our examples just to indicate | ||||
| what's accepted by the compiler. | ||||
| .NH 2 | ||||
| File inclusion | ||||
| .PP | ||||
| The C preprocessor is applied to the input file before | ||||
| compilation, so that files containing useful \fBPROC\fP and \fBDEF\fP | ||||
| declarations can be used in your program by using the \fB#include\fP-directive | ||||
| of the preprocessor. | ||||
| .NH 2 | ||||
| Substitution | ||||
| .PP | ||||
| Named processes are not textually substituted. A procedure call is used instead. | ||||
| The semantics of occam substitution imply this by letting a global variable | ||||
| (i.e. not declared inside the named process' body) be found where the named | ||||
| process is defined and not where it is substituted. | ||||
| .NH 2 | ||||
| ANY | ||||
| .PP | ||||
| According to the occam syntax the \fBANY\fP keyword may be the only argument of | ||||
| an input or output process. Thus, | ||||
| .DS | ||||
| .ft 5 | ||||
| 	c ? ANY; x | ||||
| .ft | ||||
| .DE | ||||
| is not allowed. Because it was easy to add, and it was used by some programs, | ||||
| our compiler allows it. (If you prefer portability you are advised not to make | ||||
| use of it.) | ||||
| .NH 2 | ||||
| Configuration | ||||
| .PP | ||||
| The special configuration keywords like \fBPLACED\fP, \fBALLOCATE\fP, \fBPORT\fP | ||||
| and \fBLOAD\fP are not implemented. Only \fBPRI\fP works because \fBPAR\fP and | ||||
| \fBALT\fP work the same without it. | ||||
							
								
								
									
										18
									
								
								doc/occam/p5
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								doc/occam/p5
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| .NH | ||||
| Conclusions | ||||
| .PP | ||||
| Writing the compiler was very straightforward using the LLgen parser generator. | ||||
| Its extended grammar and its way of conflict resolving were of great use to us, | ||||
| especially | ||||
| the indentation handling could be implemented quite easily. The automatic | ||||
| error recovery given by LLgen took a great weight of our shoulders. | ||||
| .PP | ||||
| A set of parallelism simulation routines makes implementing \fBPAR\fP constructs | ||||
| very simple. And we consider it a necessity to have such a layer to shield the | ||||
| compiler writer from these details. | ||||
| .PP | ||||
| The translation to EM code was fairly direct, no great tricks were needed to | ||||
| make things work. Only the different sizes of words and pointers that are given | ||||
| as parameters to the compiler must be carefully watched. Variables or pointers | ||||
| must sometimes be handled with double word instructions for different word or | ||||
| pointer sizes. | ||||
							
								
								
									
										5
									
								
								doc/occam/p6
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								doc/occam/p6
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| .NH | ||||
| Acknowledgement | ||||
| .PP | ||||
| We want to thank Dick Grune for his description of Occam which is used | ||||
| in the introduction. | ||||
							
								
								
									
										23
									
								
								doc/occam/p7
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								doc/occam/p7
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| .bp | ||||
| .NH | ||||
| References | ||||
| .LP | ||||
| .IP [1] | ||||
| INMOS limited, \fIOCCAM Programming manual\fP, Prentice-Hall, 1984. | ||||
| .IP [2] | ||||
| C. J. H. Jacobs, \fISome Topics in Parser Generation\fP, | ||||
| Informatica Rapport IR-105, Vrije Universiteit, Amsterdam, October 1985. | ||||
| .IP [3] | ||||
| B. W. Kernighan and D. M. Ritchie, \fIThe C Programming Language\fP, | ||||
| Prentice-Hall, 1978. | ||||
| .IP [4] | ||||
| M. E. Lesk, \fILex - A Lexical Analyser Generator\fP, Comp. Sci. Tech. Rep. | ||||
| No. 39, Bell Laboratories, Murrey Hill, New Jersey, October 1975. | ||||
| .IP [5] | ||||
| A. S. Tanenbaum, H. van Staveren, E. G. Keizer, J. W. Stevenson, | ||||
| \fIDescription of a Machine Architecture for use with Block Structured | ||||
| Languages\fP, Informatica Rapport IR-81, Vrije Universiteit, Amsterdam, 1983. | ||||
| .IP [6] | ||||
| K. Bot and E. Scheffer, \fIA set of multi-process primitives for stack based | ||||
| machines\fP, Vrije Universiteit, Amsterdam, 1986. | ||||
| .LP | ||||
							
								
								
									
										16
									
								
								doc/occam/p8
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								doc/occam/p8
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| .bp | ||||
| .NH | ||||
| Appendix A: Implementation of the channel routines | ||||
| .DS L | ||||
| .ft 5 | ||||
| .ta 0.65i 1.3i 1.95i 2.6i 3.25i 3.9i 4.55i 5.2i 5.85i 6.5i | ||||
| .so channel.h.t | ||||
| .ft | ||||
| .DE | ||||
| .bp | ||||
| .DS L | ||||
| .ft 5 | ||||
| .ta 0.65i 1.3i 1.95i 2.6i 3.25i 3.9i 4.55i 5.2i 5.85i 6.5i | ||||
| .so channel.c.t | ||||
| .ft | ||||
| .DE | ||||
							
								
								
									
										60
									
								
								doc/occam/p9
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								doc/occam/p9
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| .bp | ||||
| .NH | ||||
| Appendix B: Translation of a \fBPAR\fP construct to EM code using the library | ||||
| routines to simulate parallelism  | ||||
| .PP | ||||
| Translation of the parallel construct: | ||||
| .DS | ||||
| .ft 5 | ||||
| 	par | ||||
| 		P0 | ||||
| 		par i = [ 1 for n ] | ||||
| 			P(i) | ||||
| .DE | ||||
| is | ||||
| .TS | ||||
| center; | ||||
| lf5 lf5. | ||||
|  lal -20	; Assume 20 bytes of local variables at this moment | ||||
|  cal $parbegin	; Set up a process group | ||||
|  asp 4		; Assume pointersize = 4 | ||||
|  cal $parfork	; Split stack in two from local -20 | ||||
|  lfr 4		; Assume wordsize = 4 | ||||
|  zne *23	; One end jumps to second process, other continues here | ||||
|  lor 0	; Static link | ||||
|  cal $P0 | ||||
|  asp 4 | ||||
|  bra *24	; Jump to the outer parend | ||||
| 23 | ||||
|  cal $parfork	; Fork off `par i = ...'  process | ||||
|  lfr 4 | ||||
|  zne *25	; One end jumps to end of outer par | ||||
|  lal -20	; Place break just above i | ||||
|  cal $parbegin	; Set up another process group for the P(i) | ||||
|  loc 1 | ||||
|  stl -24	; i:=1 | ||||
|  lol n	; Assume n can be addressed this simply | ||||
|  stl -28	; A nameless counter | ||||
|  bra *26	; Branch to counter test | ||||
| 27 | ||||
|  cal $parfork	; Fork off one P(i) | ||||
|  lfr 4 | ||||
|  zne *28	; One jumps away to increment i, the other calls P(i) | ||||
|  lol -24 | ||||
|  lor 0 | ||||
|  cal $P | ||||
|  asp 8 | ||||
|  bra *29 | ||||
| 28 | ||||
|  inl -24	; i:=i+1 | ||||
|  del -28	; counter:=counter-1 | ||||
| 26 | ||||
|  lol -28 | ||||
|  zgt *27	; while counter>0 repeat loop | ||||
| 29 | ||||
|  cal $parend	; Wait for the P(i) to finish, then delete group | ||||
|  bra *24	; Jump to the higher up meeting place with P0 | ||||
| 25	; Note that the bra will be optimized away | ||||
| 24 | ||||
|  cal $parend	; Wait for both processes to end, then delete group | ||||
| .TE | ||||
		Loading…
	
	Add table
		
		Reference in a new issue