4 INSTITUTE OF INFORMATICS, UNIVERSITY OF WARSAW
\r
17 # ###### ###### # ###### # # #### ####
\r
18 # # # # # # # ## # # # # #
\r
19 # # # # # # # # # # #### #
\r
20 # # # # ## # ###### # # # # # #
\r
21 # # # # # # # # # ## # # #
\r
22 ###### ###### ###### ###### # # # # #### ######
\r
27 PROGRAMMING LANGUAGE (*)
\r
37 W.M.BARTOL, P.GBURZYNSKI, P.FINDEISEN, A.KRECZMAR, M.LAO, A.LITWINIUK
\r
39 T.MULDNER, W.NYKOWSKI, H.OKTABA, A.SALWICKI, D.SZCZEPANSKA-WASERSZTRUM
\r
54 ---------------------------------------------------------
\r
55 (*) Supported in part by Zjednoczenie "MERA", POLAND
\r
67 We submit to the reader the report of a language whose design is still in
\r
68 progress. Therefore any remarks and comments are very desirable. They can
\r
72 UNIVERSITY OF WARSAW
\r
73 INSTITUTE OF INFORMATICS
\r
83 The edition has been produced by using the editor program (prepared by
\r
84 P.Gburzynski, University of Warsaw) on minicomputer MERA 400. This original
\r
85 Polish minicomputer was used for the first implementation of LOGLAN-82.
\r
89 Warszawa, June, 1982
\r
96 List of symbols...................................................3
\r
98 1. Preface........................................................4
\r
100 2. The basic characteristics of LOGLAN-82.........................8
\r
101 2.1. Control structure.........................................8
\r
102 2.2. Block structure...........................................11
\r
103 2.3. Procedures and functions..................................13
\r
104 2.4. Classes...................................................14
\r
105 2.5. Prefixing.................................................15
\r
106 2.6. Object deallocator........................................17
\r
107 2.7. Arrays....................................................18
\r
108 2.8. Parameters................................................19
\r
109 2.9. Coroutines................................................20
\r
110 2.10. Processes.................................................21
\r
111 2.11. Other important features..................................22
\r
113 3. Lexical and textual structure..................................23
\r
115 4. Types..........................................................26
\r
116 4.1. Primitive types............................................27
\r
117 4.2. System types...............................................28
\r
118 4.3. Compound types and objects.................................29
\r
119 4.3.1. Array type.............................................29
\r
120 4.3.2. Class type.............................................30
\r
121 4.4. Formal types...............................................30
\r
123 5.Declarations....................................................31
\r
124 5.1. Constant declaration.......................................31
\r
125 5.2. Variable declaration.......................................32
\r
126 5.3. Unit declaration...........................................33
\r
127 5.3.1. Class declaration (introduction).......................33
\r
128 5.3.2. Subprogram declaration (introduction)..................34
\r
129 5.3.3. Block..................................................35
\r
130 5.3.4. Prefixing..............................................36
\r
131 5.3.5. Formal parameters......................................37
\r
132 5.3.6. Unit body..............................................40
\r
134 6. Static and dynamic locations . Visibility rules................42
\r
135 6.1. Unit attributes............................................42
\r
136 6.2. Protected attributes.......................................43
\r
137 6.2.1. Hidden attributes......................................43
\r
138 6.2.2. Taken attributes.......................................44
\r
139 6.2.3. Legal and illegal identifiers .........................44
\r
140 6.2.4. Close attributes.......................................45
\r
141 6.3. Static location............................................46
\r
142 6.4. Objects....................................................48
\r
143 6.4.1.ements..........................................71
\r
144 9.1. Sequential primitive statements............................71
\r
145 9.1.1. Evaluation statement...................................72
\r
146 9.1.2. Configuration statement................................75
\r
147 9.1.2.1. Allocation statement...............................75
\r
148 9.1.2.2. Deallocation statement.............................83
\r
149 9.1.3. Simple control statement...............................84
\r
150 9.1.4. Coroutine statement....................................86
\r
151 9.2. Compound statements.......................................87
\r
152 9.2.1. Conditional statement..................................87
\r
153 9.2.2. Case statement.........................................89
\r
157 9.2.3. Iteration statement....................................90
\r
159 10. Exception handling............................................96
\r
160 10.1. Signal specification.......................................96
\r
161 10.2. Signal handlers............................................97
\r
162 10.3. Signal raising.............................................98
\r
163 10.4. Handler execution.........................................101
\r
164 10.5. System signals............................................103
\r
166 11. Processes....................................................104
\r
167 11.1. Transition state statement...............................106
\r
168 11.2. Primitive synchronizing statement........................109
\r
169 11.3. Monitors (compound synchronization facilities)...........112
\r
171 12. Separate compilation of units................................115
\r
172 12.1. Library items............................................117
\r
173 12.1.1. Interface............................................118
\r
174 12.1.2. Using languages......................................121
\r
175 12.1.3. Using externals......................................122
\r
176 12.1.4. Using sl-virtuals....................................122
\r
177 12.2. Linking library items....................................123
\r
178 12.2.1. Connecting the interface.............................123
\r
179 12.3. Binary items.............................................126
\r
180 12.4. Processing libraries.....................................127
\r
181 12.4.1. Recompilation........................................127
\r
182 12.4.2. Insertions and deletions.............................128
\r
184 13. File processing..............................................129
\r
185 13.1. External and internal files..............................129
\r
186 13.2. File generation and deallocation.........................130
\r
187 13.3. Binary input-output......................................132
\r
188 13.4. Other predefined operations..............................133
\r
189 13.5. Text input-output........................................134
\r
190 13.6. Example of high-level file processing....................136
\r
192 Bibliography.....................................................137
\r
193 Index............................................................139
\r
202 We shall use the following symbols (with indices if necessary):
\r
204 A - arithmetic expression,
\r
205 B - boolean expression,
\r
206 C - character expression,
\r
207 D - string expression,
\r
208 E - arbitrary expression,
\r
209 F - function/procedure,
\r
210 G, H - statement (or sequence of statements),
\r
211 i, j, k, l, u - integer variable or index,
\r
212 M, N, P, R, S, T - type or unit identifier,
\r
216 W - arbitrary identifier,
\r
217 X - object expression,
\r
218 Y - arbitrary variable,
\r
219 Z - simple variable,
\r
220 Pf - formal parameter,
\r
221 Pa - actual parameter,
\r
222 VE - the value of an expression E.
\r
229 LOGLAN-82 #) is a universal programming language designed at the
\r
230 Institute of Informatics, University of Warsaw. The shortest, informal
\r
231 characterization of the language would read as follows. LOGLAN-82 belongs
\r
232 to the Algol family of programming languages. Its syntax, however, is
\r
233 patterned upon Pascal's. Many ideas are borrowed from SIMULA-67 [3]. The
\r
234 language includes also some modern facilities such as concurrency and
\r
235 exception handling.
\r
237 The characteristic programming constructs and facilities of the language
\r
240 - a convenient set of structured statements,
\r
242 - procedures an functions,
\r
245 - programmed deallocation,
\r
246 - adjustable arrays,
\r
247 - formal types and formal procedures,
\r
250 - encapsulation techniques,
\r
251 - exception handling,
\r
252 - separate compilation techniques,
\r
259 In the early seventies the Institute of Mathematical Machines "MERA"
\r
260 (with two members of the present team of authors) and the Institute of
\r
261 Informatics of Warsaw University initiated the design of a new high level
\r
262 programming language. There were two main inspirations for taking up this
\r
263 research. First the awareness that the SIMULA 67 programming language was a
\r
264 substantial contribution to the software methodology and second that the
\r
265 fast development of multiprocessor hardware will change the software
\r
267 We began our work with analytical studies, seminars and lectures dealing
\r
268 with the basic constructs and features of the known programming languages.
\r
269 This helped us to establish the goals a new programming language should
\r
270 reach. By then, however, we decided that the design of the programming
\r
271 language would be a component of a broader software project, called LOGLAN.
\r
280 -------------------------------------------------------------------------
\r
281 #) Recently we received information about another LOGLAN - an
\r
282 esperanto-like language developed in US.
\r
286 There is no doubt that the environment in which our investigations have
\r
287 been carried out has shed a new light on these goals. In particular, the
\r
288 experience accumulated by a big part of our team in the field of
\r
289 Algorithmic Logic [15] influenced the form of the solutions accepted.
\r
290 The first step of our work was finished in 1977 with the report on the
\r
291 LOGLAN programming language [12]. The report provides a general outline of
\r
292 a universal programming language. Among its most important features let us
\r
293 mention a new approach to arrays, assignments, parameter transmission and
\r
294 parallel computations. This version was not implemented. It constituted the
\r
295 base for the agreement between the University of Warsaw and the State
\r
296 Industrial Trust MERA, signed a year later.
\r
297 A careful analysis of the constructs suggested in the primary project
\r
298 preceded an actual implementation. With the intention of attaining this,
\r
299 the interpreter of the language was designed. At that stage a number of
\r
300 important modifications were introduced to the proposed outline. They
\r
301 resulted from experiments with the interpreter which proved the usefulness
\r
302 of some constructs and the uselessness of some others.
\r
303 At the next stage of research the language was implemented on the
\r
304 original Polish two-processor minicomputer MERA 400. The design was
\r
305 restricted in several points because of the implementation constraints.
\r
306 Some constructs were rejected, the decision concerning some others was put
\r
307 off until a more elaborate analysis was carried out.
\r
308 The experience of the team in the field of abstract data types and
\r
309 computational complexity helped us to solve one of the most fundamental
\r
310 implementation problems - a proper structure for secure and fast storage
\r
311 management. In consequence, the language is furnished with a programmed
\r
312 deallocator which allows the user to design the best strategy of storage
\r
313 management at run time.
\r
314 The implementation of unrestricted prefixing needed a completely new
\r
315 approach. The well-known mechanisms like Dijkstra's display do not allow us
\r
316 to release the SIMULA restrictions (the most important forbids the use
\r
317 prefixing at different levels of unit nesting). Such a solution was found
\r
318 and the LOGLAN-82 users may apply prefixing at an arbitrary level of unit
\r
320 Of the results we have obtained so far let us mention paper [1], which
\r
321 deals with the principles of an efficient implementation of programming
\r
322 languages with prefixing at many levels. The paper introduces the
\r
323 generalized display mechanism and proves the correctness of an
\r
324 update-display algorithm. A new data structure for efficient and secure
\r
325 storage management is also provided.
\r
326 Paper [2] deals with the design and implementation of class Simulation
\r
327 (improving that provided in SIMULA 67).
\r
328 The concurency problems are described in the special mathematical model
\r
329 [19]. The correctness of the monitor implementation is proved in [20]. The
\r
330 semantics of an assignment statement for subscripted variables is defined
\r
331 and carefully examined in [21]. Paper [16] describes the semantics of
\r
332 allocation, deallocation and control statements.
\r
333 A comprehensive survey about LOGLAN-82 and its applications is supplied
\r
334 in [8]. Let us mention the close connections between the development of the
\r
335 language itself and of Algorithmic Logic, see [15, 22, 23, 24, 25, 26].
\r
339 LOGLAN-82 high points
\r
340 ---------------------
\r
343 - An orderly and intellectually manageable fashion of program design.
\r
345 - Clean, modular extensibility (by means of the above mentioned
\r
346 facilities, in particular by prefixing). An algorithm employing an
\r
347 abstract data structure can be prefixed by a class realizing that
\r
348 structure. The class may be programmed by the user himself or by
\r
349 another user, taken from the system library etc. In this way,
\r
350 programs may be developed by teams of programmers.
\r
352 - An environment for distributed and safe development of large
\r
353 programs and systems with easy inter-communication between members
\r
354 of software teams, i.e., different parts of the design are easy to
\r
355 read, check and modify. The modifications do not entail unexpected
\r
358 - Possibility of systematic debugging in a way which contributes to
\r
359 confidence in the overall program correctness.
\r
361 - The separate compilation facility.
\r
363 - Type checking, especially of references to objects, which
\r
364 substantially reduces the need for run-time checks and increases the
\r
365 safety of handling pointers.
\r
367 - Efficient storage management by means of well-tailored allocation/
\r
368 deallocation operations.
\r
370 - Clear visibility rules with the capability of unit encapsulation
\r
373 - Concurrent computations in which several processes are
\r
374 simultaneously and independently executed by any number of
\r
375 processors. The concurrent multiprocessor computations were treated
\r
376 with due care. We reached the necessary foundations for the
\r
377 description of atomic operations for the concurrent statements. The
\r
378 atomic operations may be efficiently implemented in any operating
\r
379 system kernel. It is well known that concurrent computations have to
\r
380 be synchronized and scheduled. We do not prejudge which facilities
\r
381 are to be used for those purposes. In LOGLAN-82 all known
\r
382 synchronization methods may be declared as predefined classes. For
\r
383 example, let us mention that it is possible to define:
\r
385 - monitoring dialect similar to CONCURRENT PASCAL,
\r
386 cf.[5], with the main notions: process, monitor, entry
\r
387 procedure, delay, continue,
\r
388 - tasking dialect similar to ADA's tasks, cf.[11], with
\r
389 the main notions: task, accept, select, rendez-vous.
\r
394 First implementation of LOGLAN-82
\r
395 ---------------------------------
\r
398 The first implementation of the language was finished in December 1981 on
\r
399 the two processors Polish minicomputer MERA-400 (uni-bus architecture). The
\r
400 whole compiler was programmed in FORTRAN IV Standard. The run-time system
\r
401 and file processing were coded in the Mera Assembly Language GASS.
\r
402 The implementation team was headed by Antoni Kreczmar (who is the author
\r
403 of Running System) and included Pawel Gburzynski (File Processing), Marek
\r
404 Lao (Semantic Analysis), Andrzej Litwiniuk (Code Generation), Wojtek
\r
405 Nykowski (Parsing) and Danuta Szczepanska-Wasersztrum (Static Semantics).
\r
410 Further work on LOGLAN-82
\r
411 -------------------------
\r
413 Although we are convinced that LOGLAN-82 will prove to be useful for an
\r
414 average user, we would like to stress that we were interested mainly in
\r
415 finding answers to research questions. Our approach is more scientific than
\r
417 Among the studies that are planned for the nearest future, let us mention
\r
418 further research on LOGLAN-82 itself and on its first compiler. The
\r
419 portability of the compiler seems to be the main target of our team.
\r
420 Moreover, LOGLAN-82 will be used in several applications. In this way the
\r
421 language will be verified and its usefulness will be analyzed. We are
\r
422 convinced that the new computer architecture and multiprocessor environment
\r
423 should be taken into account. Therefore, we plan studies which could
\r
424 support an efficient implementation of the language with richer semantics
\r
425 are planned. It seems that the crucial point of the future hardware would
\r
426 be the efficient implementation of the storage management.
\r
437 We wish to express our gratitude to all institutions and persons who
\r
438 supported us materially or morally. Thanks are due to the State Industrial
\r
439 Trust "MERA" and to its deputy director A.Janicki for the arrangements that
\r
440 enabled us to realize the LOGLAN-82 project.
\r
441 The LOGLAN-82 team wishes to thank all colleagues in Warsaw for criticism
\r
442 and helpful remarks. This report has been carefully read by a number of
\r
443 people, including J.Deminet, F.Kluzniak, A.Janicki, J.Rudzinski,
\r
444 W.M.Turski. Their critical comments helped us to avoid numerous mistakes.
\r
448 2. The basic characteristics of LOGLAN-82
\r
449 #########################################
\r
451 2.1. Control structure
\r
452 **********************
\r
455 Compound statements in LOGLAN-82 are built up from simple statements
\r
456 (like assignment or call statement) by means of conditional, iteration and
\r
460 The syntax of a conditional statement is as follows:
\r
462 if boolean expression
\r
464 sequence of statements
\r
466 sequence of statements
\r
469 The semantics of a conditional statement is standard. The keyword fi
\r
470 allows us to nest conditional statements without the appearence of the
\r
471 "dangling else" ambiguity. The "else" part in a conditional statement may
\r
474 if boolean expression
\r
476 sequence of statements
\r
479 Another version of a conditonal statement has the form:
\r
481 if B1 orif ... orif Bk
\r
483 sequence of statements
\r
485 sequence of statements
\r
488 For the execution of a conditional statement with the orif list the
\r
489 specified conditions B1, ..., Bk are evaluated in succession, until the
\r
490 first one evaluates to true. Then the rest of the sequence is abandoned and
\r
491 the "then" part is executed. If none of the conditions evaluates to true,
\r
492 the "else" part is executed (if any). The orif construction provides a good
\r
493 method for a short circuit technique, since the boolean expression
\r
494 controling the conditional statement execution need not be evaluated till
\r
499 Similarly, a conditional statement with the andif list has the form:
\r
501 if B1 andif ...andif Bk
\r
503 sequence of statements
\r
505 sequence of statements
\r
508 For the execution of this kind of statement the conditions B1, ..., Bk
\r
509 are evaluated in succession until the first one evaluates to false. Then
\r
510 the "else" part is executed (if any). Otherwise the "then" part is
\r
514 The basic form of an iteration statement in LOGLAN-82 is the following:
\r
517 sequence of statements
\r
520 To terminate the iteration statement one can use the simple control
\r
521 statement exit, which has the following syntactic form:
\r
525 repeated an arbitrary number of times. It may occur in a nested loop
\r
526 statement. The execution of exit.....exit (i - times) statement consists in
\r
527 the control transfer to the statement immediately following the i-th od
\r
528 after the exit statement, (where in counting the od's, the pairs do-od are
\r
529 disregarded). In particular, when exit occurs in a simple loop the control
\r
530 is transferred to the statement immediately following the od symbol, which
\r
531 allows us to terminate the loop. Similarly, a double exit terminates two
\r
532 nested loops, a triple exit terminates three nested loops etc. Moreover, a
\r
533 LOGLAN-82 iteration statement allows us to place many loop exit points in
\r
534 arbitrary configurations, e.g., exit may appear in nested conditional
\r
535 statements, case statements, etc.
\r
537 Iteration statements with controlled variables (for statements) have the
\r
540 for j := A1 step A2 to (or downto) A3
\r
542 sequence of statements
\r
547 The type of the controlled variable j must be discrete. The value of this
\r
548 variable in the case of the for statement with to is increased, and in the
\r
549 case of the for statement with downto is decreased. The discrete range
\r
550 begins with the value of A1 and changes with the step equal to the value of
\r
551 A2. The execution of the for statement with to terminates when the value of
\r
552 j becomes for the first time greater than A3 (with downto when the value of
\r
553 j becomes for the first time less than A3). The values of the expressions
\r
554 A1, A2, A3 are evaluated once, upon entry to the iteration statement. The
\r
555 default value of A2 is equal to 1 (when the keyword step and A2 are
\r
559 An iteration statement with the while condition has the form:
\r
561 while boolean expression
\r
563 sequence of statements
\r
566 and is equivalent to
\r
569 if not boolean expression then exit fi;
\r
570 sequence of statements
\r
573 To enhance the users's comfort, the simple statement repeat is provided.
\r
574 It may appear in an iteration statement and causes the current iteration to
\r
575 be finished and the next one to be continued (something like jump to
\r
576 CONTINUE in Fortran's DO statement). In general, this statement has the
\r
579 exit ... exit repeat
\r
581 and causes the current iteration of the corresponding enclosing iteration
\r
582 statement to be finished and the next one to be continued.
\r
584 A case statement in LOGLAN-82 has the form:
\r
594 where A is an arithmetic expression, Q1, ..., Qk are constants and G1, ...,
\r
595 Gk are sequences of statements. A case statement selects for execution a
\r
596 sequence Gj where the value of A equals Qj. The choice others covers all
\r
597 values (possibly none) not given in the previous choices.
\r
601 2.2. Block structure
\r
602 ********************
\r
606 LOGLAN-82 adopts and extends the main semantic features of the ALGOL
\r
607 family programming languages (ALGOL-60, ALGOL-68, SIMULA-67) i.e., the
\r
608 block structure. The block concept of ALGOL-60 is a fundamental example of
\r
609 this mechanism. The syntactic structure of a block is as follows:
\r
612 list of declarations
\r
614 sequence of statements
\r
617 The list of declarations defines some syntactic entities, e.g. constants,
\r
618 variables, procedures, functions etc., whose scope is that block. The
\r
619 syntactic entities occurring in the sequence of statements are identified
\r
620 by means of identifiers which are introduced in the declaration lists. For
\r
621 every identifier occurrence it must be possible to identify the
\r
622 corresponding syntactic entity. This kind of correspondence between
\r
623 occurrences of identifiers and syntactic entities is necessary to define
\r
624 the semantics of a block statement. The block statement semantics may be
\r
625 described as follows.
\r
627 When a block is entered, a dynamic instance of the block is generated. In
\r
628 a computer, a block instance takes the form of a memory frame containing
\r
629 syntactic entities declared in that block. All local syntactic entities of
\r
630 an instance will be called its attributes .
\r
632 The frame of a block instance may be viewed as a box (with displayed
\r
633 attributes when necessary).
\r
635 ------------------------
\r
637 ------------------------
\r
639 ------------------------
\r
641 ------------------------
\r
643 ------------------------
\r
648 A block is a statement, and so other blocks may occur in its sequence of
\r
649 statement (i.e., blocks may be nested). Observe, that the occurrences of
\r
650 identifiers in an inner block need not be local. They can refer to entities
\r
651 declared in the outer block. For a non-local occurrence of identifier, the
\r
652 corresponding attribute of a non-local instance should be identified. That
\r
653 identification is possible thanks to an auxiliary notion of a syntactic
\r
656 Consider the following block structure:
\r
669 When the statements of block[2] are executed, the following two dynamic
\r
670 block instances are created:
\r
674 ! O[2] !=============>! O[1] !
\r
675 -------- SL --------
\r
677 Here O[1] is an instance of the block[1], and O[2] is an instance of the
\r
680 The instance O[1] is called the syntactic father of O[2] (or
\r
681 alternatively the instance O[2] is syntactically linked by the SL-link with
\r
682 the instance O[1]). During a program's execution the sequence of syntactic
\r
683 fathers determined by an active instance forms a chain, called an SL-chain.
\r
684 The instances forming the SL-chain correspond to the consequtive enclosing
\r
685 units of the program, starting from the active one and ending on the main
\r
686 block. Thus, this chain allows us to identify all non-local occurrences of
\r
689 A block statement terminates when the control reaches its final end, and
\r
690 then its instance is automatically deallocated.
\r
694 2.3. Procedures and functions
\r
695 *****************************
\r
698 A block is the simplest example of a unit. Blocks are syntactic units
\r
699 generated by means of a block statement and deallocated automatically when
\r
700 the end symbol is reached. Procedures and functions constitute the next
\r
701 step of know-how in high level programming languages.
\r
703 The syntactic form of a procedure declaration is as follows:
\r
705 unit name: procedure(formal parameters);
\r
706 list of declarations
\r
708 sequence of statements
\r
711 A procedure is a named syntactic unit which may be invoked only via its
\r
712 identifier by means of a call statement:
\r
714 call name (actual parameters);
\r
716 (Procedures differ from blocks also in that they can have parameters, but
\r
717 this question will be discussed later.)
\r
719 When a procedure is called, its instance is created, as in the case of a
\r
720 block. All local attributes are allocated in the new frame. A syntactic
\r
721 father of such a newly generated instance is defined as usual, and allows
\r
722 us to identify all non-local attributes.
\r
724 A procedure call is terminated when the control reaches return statement
\r
725 or the final end. Then the control returns to the instance where the
\r
726 procedure was called. That instance is referred to by another system
\r
729 After the termination of a procedure call there is no syntactic means to
\r
730 access its local attributes, hence its instance is automatically
\r
733 Functions differ from procedures only in that they return a value and are
\r
734 invoked in the expressions.
\r
741 To meet the need for permanent data structures LOGLAN-82 introduces the
\r
742 notion of class (cf [3]). Class is declared in a similar way to procedure.
\r
743 It is named and may have parameters:
\r
745 unit M :class(formal parameters);
\r
746 list of declarations
\r
748 sequence of statements
\r
751 The main difference between classes and procedures consists in the way
\r
752 the instances of these syntactic units are treated. (To distiguish class
\r
753 instances from those of blocks, functions and procedures they will be
\r
754 called class objects or simply objects). The class generation yields a
\r
755 class object which is a permanent data unlike the vanishing procedure
\r
756 (function, block) instance. The object O of class M is generated by the
\r
757 object generator statement:
\r
761 This statement invokes the same sequence of actions as a procedure call,
\r
762 i.e., it opens a new object, transmits parameters and executes the sequence
\r
763 of statements of M. Return to the caller is made by the execution of a
\r
764 return statement or when the final end is reached.
\r
765 The access to such an object is then possible if its address is set to a
\r
766 variable. The variables whose values point to class objects are called
\r
767 reference variables.
\r
768 A reference variable of type M is declared as follows:
\r
772 and may point to any object of class M, for instance, the statement:
\r
776 generates an object O of class M and assigns its address (reference) to X.
\r
777 The default value of any reference variable is none, which denotes
\r
778 fictitious non-existing object.
\r
779 What is left behind is a structure of attributes which can be accessed by
\r
780 means of dot-notation. These accessible attributes are either formal
\r
781 parameters or local entities. If X is a reference variable of type M and W
\r
782 is an attribute of class M, then the remote access to the attribute W has
\r
787 The above remote access is correct if X points to an object O of class M.
\r
788 Otherwise a run time error is raised (for instance when the value of X is
\r
796 Prefixing is another important programming facility borrowed from
\r
797 SIMULA-67. Its most important feature consists in the possibility of unit
\r
798 extension. Consider the following example. Let M be a class:
\r
801 list of declarations of M
\r
803 sequence of statements of M
\r
806 Now let N be a class:
\r
809 list of declarations of N
\r
811 sequence of statements of N
\r
814 Class N is prefixed by class M. The name of the prefix is located
\r
815 immediately before the symbol class. Class N is treated as an extension of
\r
816 M, i.e., the object of class N has a compact frame consisting of the
\r
817 attributes of N as well as the attributes of M:
\r
821 ! ... ! M-attributes
\r
823 --------------- - - - - - -
\r
826 ! ... ! N-attributes
\r
832 The structure of such an object is determined by the class M as well as
\r
833 by N (thus containing both M-attributes and N-attributes).
\r
838 where X is a variable of type N, creates an object of class N.
\r
842 The sequences of statements of classes M and N are also concatenated. In
\r
843 the sequence of statements of a class the keyword inner may occur anywhere,
\r
844 but once only. The sequence of statements of N consists of the sequence of
\r
845 statements of M with inner replaced by the sequence of statements of N
\r
846 (inner in N is equivalent to an empty statement). If class N prefixes
\r
847 another class P, then inner in N is replaced by the sequence of statements
\r
848 of P, and so on. If inner does not occur explicitly, an implicit occurrence
\r
849 of inner just before the final end of class is assumed.
\r
851 Prefixing allows the programmer to extend units. Assume, for instance,
\r
852 that STACK is the data structure which defines a push-down memory:
\r
856 unit pop: function...
\r
859 unit push: procedure...
\r
866 Any class prefixed by STACK inherits the operations on stack. For
\r
867 instance, in a class declaration
\r
869 unit N: STACK class;
\r
877 the function pop and the procedure push may be used as any other local
\r
880 A class may also be used to prefix blocks, procedures and functions. An
\r
881 instance of a prefixed block is a compound object and is created upon entry
\r
882 to the block and deallocated after its termination, as in the case of a
\r
883 simple block. Similarly, an instance of a prefixed procedure (function) is
\r
884 a compound object which is created when a procedure (function) is called
\r
885 and deallocated after its termination.
\r
889 2.6. Object deallocator
\r
890 ***********************
\r
892 The classical methods used to deallocate class objects are based on
\r
893 reference counters or garbage collection. Sometimes both methods may be
\r
894 combined. The reference counter is a system attribute holding the number of
\r
895 references pointing to the given object. Hence any change of the value of a
\r
896 reference variable X is followed by a corresponding increase or decrease of
\r
897 the value of its reference counter. When the reference counter becomes
\r
898 equal to 0, the object can be deallocated.
\r
900 The deallocation of class objects may also occur during the process of
\r
901 garbage collection. During this process all unreferenced objects are found
\r
902 and removed (while memory may be compactified). In order to keep the
\r
903 garbage collector able to collect all the garbage, the user should clear
\r
904 all reference variables, i.e., set to none, whenever possible. This system
\r
905 has many disadvantages. First of all, the programmer is forced to clear all
\r
906 reference variables, even those which are of auxiliary character. Moreover,
\r
907 the garbage collector is a very expensive mechanism and thus can be used
\r
908 only in emergency cases.
\r
910 In LOGLAN-82 a dual operation to the object generator, the so-called
\r
911 object deallocator is provided. Its syntactic form is as follows:
\r
915 where X is a reference expression. If the value of X points to no object
\r
916 (none) then kill(X) is equivalent to an empty statement. If the value of X
\r
917 points to an object O, then after the execution of kill(X) the object O is
\r
918 deallocated. Moreover, all reference variables which pointed to O are set
\r
919 to none., This deallocator provides full security, i.e., the attempt to
\r
920 access the deallocated object O is checked and results in a run-time error.
\r
923 Y:=X; kill(X); Y.W:=Z;
\r
925 causes the same run-time error as
\r
929 The system of storage management is arranged in such a way that the
\r
930 frames of killed objects may be immediately reused without the necessity of
\r
931 calling the garbage collector, i.e., the relocation is performed
\r
939 LOGLAN-82's array is a kind of a class with indices instead of
\r
940 identifiers selecting the attributes. A variable of an array type is a
\r
941 reference variable pointing to an object which contains components of a
\r
942 one-dimensional array. The components of such an array may also point to
\r
943 one-dimensional arrays and so forth, hence multi-dimensional arrays may be
\r
946 The declaration of a variable Y of array type has the following form:
\r
948 var Y : array_of ... array_of T
\r
950 where the number of array_of defines the dimension of Y. The declaration of
\r
951 a variable Y fixes its dimension, while the bound pairs are still
\r
952 undetermined. The array generation statement has the form
\r
954 new_array Y dim (l : u)
\r
956 where l, u are arithmetic expressions determining the lower and upper
\r
957 bounds of the first index. The object O of an array is generated and the
\r
958 reference to O is assigned to Y.
\r
960 If Y is declared as a two-dimensional array, then one can generate a
\r
961 two-dimensional array by means of the statements
\r
963 new_array Y dim (l:u);
\r
967 new_array Y(i) dim (li:ui)
\r
970 where the shape of each row is determined by the bounds li, ui. Hence
\r
971 triangular, tridiagonal, streaked arrays, etc. may be generated. Moreover,
\r
972 the assignment statements allow us to interchange array references that are
\r
973 of the same dimension and the same type, e.g. Y(i):=Y(j). In consequence,
\r
974 the user may operate on array slices. The default value of any array
\r
975 variable is none, as in the case of a reference variable.
\r
983 In LOGLAN-82 there are four categories of parameters: variable
\r
984 parameters, procedure parameters, function parameters and type parameters.
\r
986 Variable parameters
\r
987 -------------------
\r
989 Variable parameter transmission is simplified in comparison with ALGOL-60
\r
990 and SIMULA-67. There are three transmission modes of variable parameters:
\r
991 input mode, output mode and inout mode. In the syntactic unit which is a
\r
992 procedure, a function or a class, the formal input parameters are preceded
\r
993 by the symbol input, the formal output parameters are preceded by the
\r
994 symbol output and the formal inout parameters are preceded by the symbol
\r
995 inout. The default transmission mode is input. Input parameters are treated
\r
996 as local variables initialized by the values of the corresponding actual
\r
997 ones. Output parameters are treated as local variables initialized in the
\r
998 standard manner (real with 0.0, integer with 0, reference with none, etc.).
\r
999 Upon return their values are assigned to the corresponding actual
\r
1000 parameters, which in this case must be the variables. Inout parameters act
\r
1001 as input and output parameters together.
\r
1003 Procedure and function parameters
\r
1004 ---------------------------------
\r
1006 In LOGLAN-82 procedures and functions may also be formal parameters. This
\r
1007 category of parameters allows us to parametrize a unit with respect to some
\r
1008 operations. A formal procedure (function) has the full specification part,
\r
1009 i.e., the parameter list (and the function type), for instance :
\r
1011 unit Bisec: procedure(function f(x: real): real; a, b, eps:real);
\r
1019 Types are also allowed to be transmitted as parameters. This kind of
\r
1020 parameters enables us to parametrize a unit with respect to some types. For
\r
1021 instance consider the following declaration:
\r
1023 unit sort:procedure(type T;A:arrayof T; function less(x, y:T):boolean);
\r
1028 The actual parameter corresponding to the formal T must be a
\r
1029 non-primitive type. The array A must be the array of elements of the actual
\r
1031 If function less defines the ordering relation on the elements of the
\r
1032 actual type, then this procedure may be invoked to sort the array A.
\r
1039 Coroutine is a generalization of class. A coroutine object is an object
\r
1040 whose sequence of statements can be suspended and reactivated in the
\r
1041 programmed manner. The generation of a coroutine object terminates with the
\r
1042 execution of the return statement (then the control is passed to the caller
\r
1043 as in the case of classes). A coroutine object after the execution of the
\r
1044 return statement is suspended. A suspended coroutine object may be
\r
1045 reactivated with the help of the attach statement:
\r
1049 where X is a reference variable designating the activating object.
\r
1051 In general, from the moment of generation a coroutine object is either
\r
1052 active or suspended. Any reactivation of a suspended coroutine object O
\r
1053 causes the active coroutine object to be suspended and continues the
\r
1054 execution of O from the statement following the last executed one.
\r
1056 During a coroutine execution some other unit instances may be generated.
\r
1057 They are dynamically dependent on that coroutine object. Thus, an active
\r
1058 coroutine (in particular the main program) can be illustrated by the
\r
1061 -------- -------- --------
\r
1062 ! O[k] ! ---> !O[k-1]! --->...---> ! O[1] !--->
\r
1063 -------- -------- --------
\r
1066 where the arrows denote the DL-links.
\r
1068 This DL-chain is transformed into the DL-cycle when the control is
\r
1069 transferred to another coroutine as the result of the attach statement.
\r
1071 -------- -------- --------
\r
1072 ! O[k] ! ---> !O[k-1]! --->...---> ! O[1] !--->
\r
1073 -------- -------- -------- !
\r
1075 <----------------------------------------------!
\r
1084 The concept of process in LOGLAN-82 is a natural extension of coroutine.
\r
1085 Coroutines are units which once generated may operate independently, each
\r
1086 one treated as a separate process. For coroutines, however, an essential
\r
1087 assumption is established; namely, when one coroutine object is activated,
\r
1088 the active one must be suspended. When processes are used, the activation
\r
1089 of a new process does not require the active one to be suspended. Thus
\r
1090 during a program's execution many processes may be active simultaneously.
\r
1091 Their statements are computed in parallel.
\r
1092 There are two operations, stop and resume, which concern the control of
\r
1095 stop Operation which causes the active process to be
\r
1097 resume(X) Operation which reactivates the process referenced by X.
\r
1099 Synchronization and scheduling.
\r
1101 Elementary synchronization in LOGLAN-82 is achieved by two-valued
\r
1102 semaphores and a number of simple indivisible statements operating on them.
\r
1103 These statements are the following (where Z denotes a variable of semaphore
\r
1107 ts(Z) Test-and-set boolean function which closes semaphore Z
\r
1108 and returns the value true if Z was open and false if Z
\r
1110 lock(Z) Operation which tests the value of the semaphore Z and
\r
1111 either enables the given process to enter the critical
\r
1112 region guarded by Z (if Z is open) or suspends the
\r
1113 process (in the opposite case) until another one opens
\r
1114 that critical region.
\r
1115 unlock(Z) Operation the execution of which opens the critical
\r
1116 region guarded by Z.
\r
1117 stop(Z) Operation that opens the critical region guarded by Z
\r
1118 and stops the execution of the given process.
\r
1120 The above operations are implemented in the kernel of the operating
\r
1121 system. One can use them to define any complex synchronization facility,
\r
1122 e.g., monitors (cf. 11.3.). Once defined and stored in the library, the
\r
1123 facility can be used by any user. Moreover, using the high level
\r
1124 synchronizing tools, the user can cover the low level, primitive ones
\r
1125 (therefore the properties of high level tools cannot be disturbed).
\r
1127 There is also a parameterless function wait. If wait is called in the
\r
1128 given process X, then process X waits for the termination of any of its son
\r
1129 (a son of X is a process which was generated in X). The returned value of
\r
1130 wait points to the first terminated son, and then, the computation of
\r
1131 process X is continued. If there is no such son, the returned value of wait
\r
1136 2.11. Other important features
\r
1137 ******************************
\r
1139 In LOGLAN-82 the access control mechanism is enlarged so that it supports
\r
1140 the data encapsulation technique and the protection of attributes in
\r
1141 different environments. The mode of accessibility to attributes of a class
\r
1142 can be controlled by means of the specification hidden and close. On the
\r
1143 other hand, the mode of accessibility to attributes of a unit that are
\r
1144 inherited from its prefix can be controlled by means of the specifification
\r
1145 taken. This permits more flexible communication across the unit boundary as
\r
1146 well as defining of abstract behaviour with a hidden auxiliary structure.
\r
1147 (For details see 6).
\r
1149 The language provides facilities for dealing with run time errors and
\r
1150 other exceptional situations raised by the user. These events are called
\r
1151 exceptions. So, the exceptions cause interruption of a normal program
\r
1152 execution. The response to an exception is defined by an exception handler.
\r
1153 The user is allowed to define the actions that should be raised when an
\r
1154 exception is encountered.
\r
1155 (For details see 10).
\r
1157 Program units can be compiled separately. Two kinds of separately
\r
1158 compiled units are provided: binary items ready to be executed, and library
\r
1159 items. The purposes of separate compilation are the following: creating
\r
1160 user libraries, handling system and user libraries, compiling program
\r
1161 components during program testing, and program overlaying.
\r
1162 (For details see 12).
\r
1164 Input-output facilities and file processing are defined by means of some
\r
1165 simple primitives. The user is able, however, to declare in the language
\r
1166 any class that provides high-level and secure file operations. Examples of
\r
1167 system classes that deal with high-level file operations are also given.
\r
1168 (For details see 13).
\r
1172 3. Lexical and textual structure
\r
1173 ################################
\r
1176 The basic character set consists of
\r
1178 (a) 26 upper case letters:
\r
1180 a b c d e f g h i j k l m n o p q r s t u v w x y z
\r
1184 0 1 2 3 4 5 6 7 8 9
\r
1186 (c) 16 auxiliary characters:
\r
1188 . : , ; _ = / + - * < > ' " ( )
\r
1190 (d) the space character
\r
1192 This set can be extended with the following characters:
\r
1194 (e) lower case letters
\r
1196 (f) other special ASCII characters, e.g.:
\r
1200 (lower case letters are equivalent to the corresponding upper case ones.)
\r
1202 A finite sequence of characters is called a word. The words called
\r
1203 identifiers have a special meaning. They are composed of letters, digits,
\r
1204 and underscores and start with a letter:
\r
1210 ----------> <letter> -------------------------->
\r
1213 !---> <digit> ----> ! !
\r
1218 <-------------------------------
\r
1225 Identifiers serve to identify program entities, i.e., constants, variables,
\r
1226 types, functions, procedures, classes, coroutines and processes. There are
\r
1227 a certain number of predefined system identifiers which have special
\r
1228 significance in the language. The following system identifiers are reserved
\r
1229 words (these identifiers cannot be declared by the programmer).
\r
1236 and_if detach if od taken
\r
1237 and dim in open terminate
\r
1238 array_of div inner or then
\r
1239 attach do input or_if this
\r
1240 downto inout others to
\r
1243 block end kill pref unit
\r
1244 esac procedure unlock
\r
1245 exit last_will process
\r
1249 class function mod wait
\r
1251 const get new read when
\r
1252 copy new_array repeat while
\r
1253 coroutine hidden none repeat write
\r
1254 handlers not return writeln
\r
1265 The lexical entities are identifiers, numbers, strings and delimiters.
\r
1266 The delimiters from the basic character set are:
\r
1268 , ; = / + - * > < . ( ) :
\r
1270 and the compound symbols are :
\r
1274 Spaces play the role of separators, i.e., at least one space must
\r
1275 separate adjacent identifiers or numbers. The end of each line is
\r
1276 equivalent to a space.
\r
1278 A comment starts with a left parenthesis and an asterisk and is
\r
1279 terminated by an asterisk and a right parenthesis. It may only appear
\r
1280 following a lexical unit or at the beginning or end of a program entity.
\r
1281 Comments have no effect on the meaning of a program and are used solely for
\r
1282 program documentation.
\r
1284 By an identifier definition we mean a declaration or description in the
\r
1285 list of formal parameters.
\r
1287 The notion of a unit is explained by the following diagram:
\r
1290 ---------------------- unit ----------------------
\r
1294 -----subprogram---- generalized class !
\r
1297 function procedure class coroutine process block
\r
1305 A type T determines a set !T! of values and a family of operations
\r
1306 applicable to the elements of the set. Three kinds of types are
\r
1307 distinguished: primitive types, system types and compound types. Variables
\r
1308 may be declared to be of type T. Depending on the kind of type T we have to
\r
1309 distinguish two cases.
\r
1312 a) T is a primitive type. The value assigned to a variable Y of type
\r
1313 T must belong to the set !T!.
\r
1316 b) T is a compound or system type. The value assigned to a variable
\r
1317 Y of type T must be a reference pointing to an object in the set
\r
1318 !T! (for the notion of reference cf 4.3. and 6.3.)
\r
1326 <type identifier>:
\r
1328 -----> <primitive type> ------>
\r
1330 !-> <system type> ----->!
\r
1332 !-> <compound type> --->!
\r
1334 !-> <formal type> ----->!
\r
1336 !-> <file type> ------->!
\r
1340 Primitive and system types are pre-defined, compound types are defined by
\r
1341 the user. For file type see section 13.
\r
1345 4.1. Primitive types
\r
1346 ********************
\r
1354 -----> integer -------->
\r
1360 !-> character -->!
\r
1364 !-> semaphore -->!
\r
1371 A primitive type determines a finite set of values which can be effectively
\r
1372 represented in a computer memory:
\r
1374 !integer! - a subset of integers;
\r
1375 !real! - a subset of reals;
\r
1376 !boolean! - the set consisting of logical values T (true) and F (false);
\r
1377 !semaphore! - the set consisting of two values (closed and open);
\r
1378 !character! - a set of characters;
\r
1379 !string! - a subset of strings;
\r
1381 These sets will be precisely defined in a concrete implementation. The
\r
1382 way in which the primitive type values are represented in a computer memory
\r
1383 is not essential for the description of semantics; however, the values of
\r
1384 integer and real types are differently represented. Namely, integers are
\r
1385 represented in the fixed-point form with a point after the last significant
\r
1386 digit, reals are represented in the floating-point form. So they will be
\r
1387 denoted differently, e.g., 2 and 2.0. Those values can be mutually
\r
1388 converted: the value of type integer is converted to type real by means of
\r
1389 conversion into the floating point form; the conversion into the opposite
\r
1390 direction truncates and transforms the real value into the fixed-point
\r
1404 --------> coroutine -------->
\r
1406 !----> process --->!
\r
1413 The set !coroutine! is equal to the union of sets !T! for every type T
\r
1416 - unit T : coroutine
\r
1417 - unit T : process
\r
1418 - unit T : S class
\r
1419 where !S! is already a subset of the set !coroutine!.
\r
1421 The set !process! is equal to the union of sets !T! for every type T
\r
1424 - unit T : process
\r
1425 - unit T : S class
\r
1426 where !S! is already a subset of the set !process!.
\r
1428 The user may declare a variable of coroutine (process) type, e.g. of the
\r
1431 var X : coroutine;
\r
1432 (var X : process;)
\r
1434 and then to assign:
\r
1437 where T belongs to the set !coroutine! (!process!).
\r
1439 The main block belongs to both sets - !coroutine! and !process!. The
\r
1440 system variable main gives the reference to the main block. The variable
\r
1441 main may occur in the statements attach(main) and resume(main) only.
\r
1445 4.3. Compound types and objects
\r
1446 *******************************
\r
1453 --------> <array type> ---------->
\r
1455 !----> <class type> --->!
\r
1461 Objects of array type will be called array objects or shortly arrays. An
\r
1462 array can be considered as a vector; the access to its components is
\r
1463 provided by means of indexing.
\r
1471 ------> array_of -----> <type identifier> ---->
\r
1477 LOGLAN-82 types can be uniformly denoted in the following way
\r
1480 !! array_of ... array_of T for i>0
\r
1482 (array_of)<i>T= !!
\r
1486 where T is a type identifier.
\r
1488 For i>0, the set !(array_of)<i>T! consists of the array objects. Every
\r
1489 array object has the attributes accessed via indices l, l+1, ..., u where
\r
1490 l, u are the values of the lower and upper bounds, respectively, and l<=u.
\r
1491 The attributes with the indices l, ..., u are of type (array_of)<i-1>T.
\r
1493 Let O be an arbitrary fixed array object and let Y be a variable whose
\r
1494 value points to O. The operations related to the object O are:
\r
1496 - Y(j), where l<=j<=u, gives the j-th attribute of the object O,
\r
1497 - lower(Y) and upper(Y), which give the value l and u,
\r
1511 -----> <class identifier> ----->
\r
1514 <class identifier>:
\r
1516 ------> <identifier> ---------->
\r
1522 A class T is a description of a data structure consisting of attributes
\r
1523 i.e., types, functions, procedures, variables, and a sequence of
\r
1524 statements. The family of admissible operations on the objects from the set
\r
1525 !T! contains the operations defined in the sequence of statements and those
\r
1526 defined in the declarations of functions and procedures. The other
\r
1527 operations are related to the notion of remote access. They allow us to
\r
1528 operate on the objects of type !T! from outside of them.
\r
1541 -----> <formal type identifier> ----->
\r
1544 <formal type identifier>:
\r
1546 -----> <identifier> ------------------>
\r
1552 A formal type is a formal parameter of a unit and can be treated as the
\r
1553 name of an abstract data structure without any attribute. The corresponding
\r
1554 actual type must be a system type or a compound type. The set of objects of
\r
1555 the formal type T from a dynamic object O is equal to the set of objects of
\r
1556 the actual type which occurs in the actual parameter list of O.
\r
1564 Every identifier which is to be used in a program must be defined. System
\r
1565 identifiers are pre-defined, other identifiers are pre-compiled, (see 12.)
\r
1566 or they are defined by means of a declaration or description in the formal
\r
1567 parameter list. LOGLAN-82 is not strongly typed in the sense that sometimes
\r
1568 the type of variable and function value cannot be determined at compilation
\r
1569 time. The user may balance the generality and convenience given by the
\r
1570 formal types mechanism and the risk of reduced efficiency of his program
\r
1571 execution. The compiler option, however, allows us to supress the run time
\r
1572 checking with respect to the type compatibility.
\r
1579 ------> <constant declaration> -------->
\r
1581 !--> <variable declaration> -->!
\r
1583 !--> <unit declaration> ------>!
\r
1585 !--> <signal declaration> ---->!
\r
1587 !--> <linked item specific.>-->!
\r
1590 (For the definition of a signal declaration see 10.
\r
1591 For the definition of linked item specification see 12.)
\r
1594 5.1. Constant declaration
\r
1595 *************************
\r
1601 <constant declaration>:
\r
1603 --> const ---> <identifier> ---> = ---> <expression> ------------------->
\r
1605 <------------------------ , ---------------------
\r
1611 The expression defining the constant must be determinable at compilation
\r
1612 time. The type and the value of the constant is given by its declaration.
\r
1613 They are always primitive.
\r
1618 const pi=3.1415926, pihalf=pi/2;
\r
1623 5.2. Variable declaration
\r
1624 *************************
\r
1630 <variable declaration>:
\r
1632 ---> var ---><specification list>--->
\r
1635 <specification list>:
\r
1637 ----> <identifier list> ---> : ---> <type identifier> ------>
\r
1639 !<------------------ , <--------------------------------!
\r
1642 <identifier list>:
\r
1644 -----> <identifier> ------->
\r
1646 !<---- , <---------!
\r
1652 A variable is of a type given in a variable declaration. A declaration is
\r
1653 elaborated at the instant of generation of a unit object which contains
\r
1654 that declaration. An elaboration determines an initial value for every
\r
1655 variable. This value depends on the type identifier :
\r
1661 character and string - defined in concrete implementation
\r
1662 any compound and system type- none
\r
1664 The value of the variable may be modified by means of an assignment
\r
1665 statement (see 9.1.1.), but the variables of type T may only point to the
\r
1666 object from the set !T!.
\r
1671 var left, right: node, counter: integer, cycle: array_of boolean;
\r
1677 5.3. Unit declaration
\r
1678 *********************
\r
1684 <unit declaration>:
\r
1686 ----> unit -------> <class declaration> ---------------------->
\r
1688 !----> <subprogram declaration> --->!
\r
1691 5.3.1. Class declaration (introduction)
\r
1692 ***************************************
\r
1695 A class declaration is understood as a declaration of a class itself, as
\r
1696 well as a declaration of a coroutine or a process. The prefixing will be
\r
1697 described in 5.3.4..
\r
1703 <class declaration>:
\r
1705 ----------><class identifier> : ---> <prefix> -----> class ----->!
\r
1707 ------------->!-><system type>->!
\r
1709 !<------------------------------------------------------------!
\r
1711 !-> <formal parameter list> ------------------------------->!
\r
1713 !<------------------------------ ; ----------!
\r
1715 !--> <class body> ----------------------------->
\r
1717 !-> <class identifier> ->!
\r
1722 ----------------> <class identifier> ------>
\r
1727 unit complex: class(re, im:real);
\r
1730 module:=sqrt(re*re+im*im)
\r
1735 5.3.2. Subprogram declaration (introduction)
\r
1736 ********************************************
\r
1742 <procedure declaration>:
\r
1744 --> virtual --> <procedure identifier>--> : --><prefix> ---> procedure
\r
1746 !----------! !------------! !
\r
1748 <-------------------------------------------------------!
\r
1750 !--> <formal parameter list> -------------------------->!
\r
1752 <------------------------- ; ---------------------!
\r
1754 !--> <subprogram body> ------------------------------>
\r
1756 !-> <procedure identifier>->!
\r
1760 <procedure identifier> :
\r
1762 ---- <identifier> ------->
\r
1765 <function declaration>:
\r
1767 --> virtual --> <function identifier>--> : --> <prefix> --> function
\r
1769 !----------! !-----------! !
\r
1771 !<------------------------------------------------------------!
\r
1773 !-> <formal parameter list> ---------> : ----> <type identifier>->
\r
1775 !<-------------------- ; ----------------------------!
\r
1777 !-> <subprogram body> ------------------------------->
\r
1779 !-> <function identifier>->!
\r
1783 <function identifier>:
\r
1785 -----> <identifier> ---------->
\r
1790 Class (function, procedure) identifier may optionally follow the end
\r
1791 symbol (and if present must match the unit name).
\r
1798 unit Euclid: function(n, m:integer):integer;
\r
1803 if k=0 then result:=m; return fi;
\r
1814 In order to complete the description of LOGLAN-82 units the block syntax
\r
1815 is given here, however the occurrence of a block results in the execution
\r
1816 of its statements - see 9.1.2..
\r
1825 --> pref --> <prefix> ---> <actual parameter list> ---> block ---->
\r
1827 !-------------------->!--------------------------->! !
\r
1829 !<------------------------------------------!
\r
1831 !--> <subprogram body>------>
\r
1837 var a, b, c, p, S:real;
\r
1841 S:=sqrt(p*(p-a)*(p-b)*(p-c));
\r
1851 A unit which is a specialized form of a certain class (i.e., which has
\r
1852 all the properties of that class and some additional properties defined in
\r
1853 the unit) can be defined by means of prefixing. An identifier of the
\r
1854 prefixed unit may serve as a prefix for another unit, and so tree
\r
1855 structured hierarchies of units can be created. By a prefix sequence of a
\r
1856 unit M we mean a sequence M1, ..., Mk of units such that Mk = M, the unit
\r
1857 M1 has no prefix; for i = 1, ..., k-1, the unit Mi+1 is prefixed by Mi. Any
\r
1858 unit may be prefixed by a class without changing its character (e.g., a
\r
1859 prefixed procedure still remains a procedure). Procedures, functions, and
\r
1860 blocks cannot be used as prefixes. Process and coroutine, as special cases
\r
1861 of class, may also serve as prefixes, but not for procedures, functions or
\r
1864 If a coroutine (a process) occurs in a prefix sequence of a unit then
\r
1865 this unit is treated as a coroutine (a process), and so it has all the
\r
1866 properties of a coroutine (a process). Therefore, if a prefix sequence of a
\r
1867 unit M contains both a coroutine and a process then M has the properties of
\r
1868 a coroutine as well as those of a process.
\r
1870 No unit is allowed to occur more than once in its prefix sequence.
\r
1872 Put T pref* S if a unit T belongs to the prefix sequence of the unit S.
\r
1873 Unit S is called a subunit of unit T. As one can see from the definition of
\r
1874 object, any object of S has the attributes of the units S and T. Moreover,
\r
1875 the statements of that object come from the body of the unit T as well as
\r
1876 from that of the unit S.
\r
1878 From the way of implementation it follows that prefixing is not a
\r
1879 macro-definition and so it does not require any pre-processing.
\r
1883 5.3.5. Formal parameters
\r
1884 ************************
\r
1891 <formal parameter list>:
\r
1893 ---> ( -----> <input parameters> ---------------> ) ---->
\r
1895 ! !--> <output parameters> -->! !
\r
1897 ! !--> <inout parameters> --->! !
\r
1899 ! !--> <type parameters> ---->! !
\r
1901 ! !--> <procedure parameter>->! !
\r
1903 ! !--> <function parameter> ->! !
\r
1905 !<----------- ; <------------------!
\r
1908 <input parameters>:
\r
1910 ----> input -----> <specification list> ------->
\r
1915 <output parameters>:
\r
1917 ----> output ----> <specification list> ------->
\r
1920 <inout parameters>:
\r
1922 ----> inout ----> <specification list> ------->
\r
1925 <type parameters>:
\r
1927 ----> type ------> <identifier list> ----------->
\r
1933 <procedure parameter>:
\r
1935 ----> procedure ---> <procedure identifier> ---->!
\r
1937 !<-----------------------------------------!
\r
1939 !---> <formal parameter simp. list> ------>
\r
1941 !----------------------------------->!
\r
1943 <function parameter>:
\r
1945 ---> function --> <function identifier> ------>!
\r
1947 !<----------------------------------------------!
\r
1949 !--> <formal parameter simp. list> --> : --> <type identifier> -->
\r
1951 !-------------------------------->!
\r
1954 <formal parameter simp. list>:
\r
1956 -------> ( --------> <input parameters> -----------------> ) ----->
\r
1958 ! !--> <output parameters> ->! !
\r
1960 ! !--> <inout parameters> -->! !
\r
1962 ! !--> <type parameters> --->! !
\r
1964 ! !-> <proc. simp. param.>-->! !
\r
1966 ! !--> <func. simp. param.>->! !
\r
1968 <----------------- ; <-------------------!
\r
1971 <procedure simp. parameter>:
\r
1973 ----> procedure -----> <procedure identifier> ------>
\r
1976 <function simp. parameter>:
\r
1978 ----> function -------> <function identifier> ------->
\r
1986 By a formal parameter list of a unit M we shall mean a concatenated list
\r
1987 of formal parameters of the bodies of all units M1, ...., Mk = M from the
\r
1988 prefix sequence of unit M (successively from 1 to k). The parameters
\r
1989 occurring in a unit declaration are called formal parameters to stress that
\r
1990 they constitute a pattern for parameters occurring in the unit body. At the
\r
1991 instant of object generation the actual parameters for this generation are
\r
1992 fixed. The relations between formal and actual parameters depend on the
\r
1993 transmission mode which is specified in the formal parameter list.
\r
1995 Those relations make possible the communication between a unit and its
\r
1996 environment. The first mode of transmission rectricts the communication to
\r
1997 the input (as the beginning of the body) of the actual parameter value for
\r
1998 the corresponding formal parameter. The second mode restricts the
\r
1999 communication to the output (as the end of the body) of the formal
\r
2000 parameter value for the corresponding actual parameter. The third mode
\r
2001 possesses both possibilities of the input and output transmission modes. In
\r
2002 all three cases, the formal parameters are considered to be declared in the
\r
2005 The next two modes of transmission are designed for subprograms and
\r
2006 types. The occurrence of a formal subprogram/type in the unit body is
\r
2007 matched with the corresponding actual subprogram/type (which is assigned at
\r
2008 the beginning of the body execution). In the case of a formal subprogram, a
\r
2009 simplified description of its parameters is required.
\r
2011 Hence a LOGLAN-82 unit may be parametrized and designates the union of
\r
2012 all units definable by assigning specific actual types to the formal ones.
\r
2013 The actual type cannot be a primitive one. Parametrized units make possible
\r
2014 the design of universal algorithms, which will be defined in detail at
\r
2015 lower levels of program nesting.
\r
2029 ---> <inheritance list> ---> <protection list> ---> <body> ----->
\r
2031 !--------------------->! !------------------->!
\r
2034 <subprogram body>:
\r
2036 ----> <inheritance list> ------> <body> ------>
\r
2038 !---------------------->!
\r
2041 <inheritance list>:
\r
2043 ----> taken -----> <identifier list> -----> ; ---->
\r
2045 !-----------------------!
\r
2048 <protection list>:
\r
2050 ------------> hidden -------------------> <identifier list> --> ; --->
\r
2052 !---------> close ------------>! !
\r
2054 !<--------------------------------------------------------------!
\r
2060 ----> <declaration list> ---->!
\r
2062 <handlers' declaration> ---> begin --> <statement list> --> end -->
\r
2064 !---------------------------!
\r
2068 <declaration list>:
\r
2070 !------------------------------------>!
\r
2072 --------> <declaration> -------> ; ---------------->
\r
2074 !<------------------------------!
\r
2079 ------> <statement > ------->
\r
2081 !<----- ; ------------!
\r
2087 In a unit body, a sequence of statements (if any) starts from the begin
\r
2088 symbol. Declarations/statements are separated by semicolons. An execution
\r
2089 of the unit body begins at the time of the generation of an object (of that
\r
2090 unit), see 9.1.2.. A declaration of a unit M is restricted at several
\r
2096 (i) The least (textual) unit containing an occurrence of a
\r
2097 control statement inner (see 9.1.3.) must be a generalized
\r
2098 class. An inner statement may occur in the class body at
\r
2099 the most once. If it does not occur explicitly then the
\r
2100 body of unit M is assumed to contain the inner statement as
\r
2101 the last one (preceding the end symbol).
\r
2103 (ii) All identifiers defined in the body of unit M are
\r
2106 (iii) The input/output formal parameters of unit M cannot be of a
\r
2107 type declared in unit M.
\r
2109 (iv) If a type T is a formal parameter of unit M then its
\r
2110 occurrence in the list of parameters must precede the
\r
2111 occurrences of other parameters whose description makes use
\r
2116 6. Static and dynamic locations of identifiers. Visibility rules.
\r
2117 #################################################################
\r
2120 As noted before, a non-system identifier used in a program must be
\r
2121 defined in the program by a declaration or by a description in a formal
\r
2122 parameter list. An identifier need not correspond, however, to only one
\r
2123 syntactic entity. A program is composed of units, and so the user designing
\r
2124 a unit must pay attention to the relationship between a given unit and the
\r
2125 other ones. He should feel free to define his own attributes with the same
\r
2126 identifiers as those used in the other units as long as he is not
\r
2127 interested in the entities they describe. Therefore some strict rules of
\r
2128 correspondence between the identifier and the attribute as well as its
\r
2129 valuation are necessary. The first correspondence is called the static
\r
2130 location of an identifier, and the second is called the dynamic location.
\r
2131 The static location is determined by the syntactic structure of a program.
\r
2132 The dynamic location depends on the dynamic configuration of objects.
\r
2135 6.1. Unit attributes
\r
2136 *********************
\r
2139 A set of attributes is assigned to each unit M. This set consists of all
\r
2140 syntactic entities defined in M and in the prefix sequence of M. Most of
\r
2141 them form the set of attributes which belong to each object of the unit,
\r
2142 i.e., they are dynamic. Virtual functions and procedures are attributes of
\r
2143 a very special kind. They are presented separately in 6.4.1. Some other
\r
2144 attributes, like constants, are static, i.e., they are not attrributes of
\r
2145 the objects of the unit but of the unit itself. Therefore static attributes
\r
2146 cannot be accessed by means of dot notation (cf 8.2.3.).
\r
2147 The user may protect attributes. The protection mechanisms are introduced
\r
2148 in the following sections and discussed in 8.2.3.
\r
2149 LOGLAN-82 identifiers cannot be overloaded, i.e., an identifier used in
\r
2150 the given unit corresponds to "exactly one" attribute determined by the
\r
2151 context. However, identifiers may be redefined. Therefore strict
\r
2152 correspondence between the occurrences of the identifiers and the
\r
2153 attributes must de defined.
\r
2154 Let W be a syntactic entity and M a syntactic unit. We say that W is
\r
2155 defined in M iff W is a formal parameter of M (but not of the prefix of M)
\r
2156 or W is declared in M. If W is defined in M, the entity it denotes is the
\r
2157 meaning of W. From now on we shall use interchangeably the notions of an
\r
2158 identifier and of an attribute.
\r
2159 Let W be an identifier and M a unit. If W is defined in M or in a unit
\r
2160 from M's prefix sequence, then W corresponds to an attribute of M. More
\r
2161 precisely, the corresponding attribute is the one defined in M, if it
\r
2162 exists, or the one defined in the prefix sequence. That means that the
\r
2163 redefinition of an identifier in a prefixed unit covers the attribute
\r
2164 corresponding to that identifier.
\r
2168 6.2. Protected attributes
\r
2169 *************************
\r
2171 Let us consider a declaration of a prefixed unit. Let M be such a unit
\r
2172 and N its prefix. The attributes of N are visible in M (unless covered by
\r
2173 the local redefinition). The user, however, can restrict the use of N's
\r
2174 attributes in M. The protection may be specified already in unit N as well
\r
2175 as in M. The first way corresponds to the hidden specification while the
\r
2176 second to the taken specification.
\r
2179 6.2.1. Hidden attributes
\r
2180 ************************
\r
2183 A list of hidden attributes is a filter from the prefixing unit. The user
\r
2184 may specify within prefix N the attributes whose occurrence is illegal in
\r
2185 any unit prefixed by N (unless the identifiers of these attributes are
\r
2186 covered by the redeclarations). Remote access to such attributes is
\r
2187 forbidden as well (cf 6.2). The absence of hidden specification denotes the
\r
2189 Consider an example:
\r
2193 var x, y, z:integer;
\r
2199 var x, y, t:integer;
\r
2203 Variables x, y declared in N are redeclared in M, and so the identifiers
\r
2204 x, y in M refer to the local entities. Variable t is declared in M and is
\r
2205 hidden in the units prefixed by M. Variable z is hidden in N, hence it
\r
2206 cannot be used in M.
\r
2210 6.2.2. Taken attributes
\r
2211 ***********************
\r
2214 The list of taken attributes is a filter on the prefixed unit. In unit M
\r
2215 the user may specify explicitly the attributes from prefix N which are used
\r
2216 in M. Then in M the only attributes accessible from N are those from the
\r
2217 taken list. The occurrence of another attribute from N in M's body is
\r
2218 illegal. The absence of taken specification denotes the list of all (legal
\r
2219 and not hidden) identifiers from N. This means that the user is not
\r
2220 interested in the specification of this kind of filtering.
\r
2221 The identifiers in the taken list must be defined in the prefix sequence,
\r
2222 not in unit M. An exception is an identifier of a virtual attribute (cf
\r
2226 6.2.3. Legal and illegal identifiers
\r
2227 ************************************
\r
2229 In this section we consider only identifiers corresponding to the
\r
2230 attributes of a given unit.
\r
2232 All identifiers defined in a unit are legal in that unit. In particular,
\r
2233 all identifiers declared in a non-prefixed unit are legal.
\r
2235 Now let M be a unit, N its prefix and W an identifier not defined in M.
\r
2236 Then W is a legal identifier corresponding to an attribute of M iff
\r
2240 - W does not occur in the hidden list in N
\r
2241 - W occurs in the taken list in M or this list is absent
\r
2244 All identifiers specified in every context in a unit must be legal in
\r
2245 that unit. All identifiers specified in the taken list must be legal in the
\r
2248 An identifier is illegal in a unit iff it denotes an attribute of the
\r
2249 unit (according to 6.1) and that attribute is not legal.
\r
2253 6.2.4. Close attributes
\r
2254 ***********************
\r
2257 Close attributes are not accessible by means of remote access (cf.
\r
2258 8.2.3.) outside the unit.
\r
2260 Let M be a unit with the prefix sequence M1, ..., Mk=M. An attribute W of
\r
2261 unit M is called a close attribute if W occurs in the close list of Mj for
\r
2262 some j, 1<=j<=k, and W is not redefined in any unit following that Mj in
\r
2263 the prefix sequence. However, remote access to a close attribute W is
\r
2264 allowed within the text of the unit M specifying it to be close, i.e., if
\r
2265 the static qualification of the object expression is equal to M, remote
\r
2266 access to W is allowed in all the units declared (directly or indirectly)
\r
2269 The list of close attributes must consist of legal identifiers. All
\r
2270 hidden attributes are simultaneously close attributes.
\r
2281 var x, z:real, y:A;
\r
2287 ... z ... (* is illegal since hidden in A *)
\r
2288 ... x ... (* is legal *)
\r
2289 .. y.x+y.z .. (* is legal since y is qualified by A
\r
2290 and the expression is within A *)
\r
2291 ... t.x .. (* is illegal since t is qualified by B *)
\r
2296 ... v.x+y.x .... (* is legal *)
\r
2300 begin (* outside A *)
\r
2302 ... v.z .. (* is illegal since hidden, and so close as well *)
\r
2303 ... v.y.x ... (* is illegal since x is close *)
\r
2308 6.3. Static location
\r
2309 *********************
\r
2312 We say that the occurrence of an identifier W is in a unit M if M is the
\r
2313 syntactic unit most tightly enclosing that occurrence. On the basis of the
\r
2314 program structure every occurrence of an identifier W in a unit M can be
\r
2315 unequivocally related to a unit N, where the corresponding attribute W is
\r
2316 defined. The unit N is called the static container for that occurrence of W
\r
2317 in M and is denoted by SC(W, M).
\r
2318 More precisely, by a static container of an occurrence of an identifier W
\r
2319 in a unit M we mean a syntactic unit N such that:
\r
2321 - W is defined in N
\r
2323 - there exists a unit P satisfying the following conditons:
\r
2326 (1) N belongs to the prefix sequence of P (or is P),
\r
2327 (2) M is declared in P directly or indirectly,
\r
2328 (3) there is no other unit closer to M than P satisfying (2) in
\r
2329 which W is an attribute,
\r
2330 (4) N is P's nearest prefix defining W
\r
2331 (5) if W is illegal (hidden or not taken) in P, then the static
\r
2332 container is undefined.
\r
2334 The following figure illustrates this definition
\r
2336 the prefix sequence of P
\r
2337 P <-------- R <------------ SC(W,M)=N ... declaration of W ...
\r
2345 M ... the occurrence of W ...
\r
2348 The static location of an identifier W is defined for the occurrence of W
\r
2349 in a unit M iff there exists a static container SC(W, M). Every program
\r
2350 must be an expression in which the static location is defined for all
\r
2351 occurring identifiers.
\r
2352 The static container is sufficient to determine the static attribute of a
\r
2360 Consider the following program
\r
2363 unit M: class; var X ... end M;
\r
2364 unit N: M class; var X ... end N;
\r
2366 pref N block (* P *)
\r
2374 pref N block (* S *)
\r
2389 SC(X, R)=SC(X, T)=N
\r
2390 and SC(Y, R)=P, SC(Y, T)=S.
\r
2400 An object O of type M with the prefix sequence M1, ..., Mk=M (k=>1) is:
\r
2402 - a k-tuple of the form O = (<V1, M1>, ... <Vk, Mk>) where Vi
\r
2403 is the valuation of non-static attributes defined in the
\r
2407 - and a unique reference pointing to this k-tuple.
\r
2410 Since the references are unique, two objects are different even if their
\r
2411 tuples are identical.
\r
2413 Now let us define the valuation of an attribute of object O, depending on
\r
2414 the kind of that attribute:
\r
2416 - the valuation of variables and variable parameters gives
\r
2419 - the valuation of an attribute which is a subprogram is the
\r
2420 text of its declaration and an environment. (The environment
\r
2421 is the object containing the declaration of the subprogram.
\r
2422 In the case of a formal subprogram the value is determined
\r
2423 by the actual one (see 9.1.2.). The case of virtuals is
\r
2426 - an attribute which is a type has the value of the form:
\r
2427 (array_of)<j> text of declaration.
\r
2431 6.4.1. Virtual attributes
\r
2432 *************************
\r
2435 The main feature of virtual atributes is that a redeclaration of an
\r
2436 identifier denoting a virtual subprogram in a prefixed unit does not cover
\r
2437 the declaration in the prefix but replaces it in all occurrences. The
\r
2438 replacement takes place in the so-called virtual chains of identifiers. We
\r
2439 define this notion below.
\r
2440 Let F be a subprogram and M a unit. By a virtual chain of F in M we mean
\r
2441 a sequence of virtuals corresponding to the maximal subsequence N1, ..., Nk
\r
2442 of the prefix sequence of M such that:
\r
2444 (1) F is a legal identifier in every Ni and denotes an attribute
\r
2445 specified as virtual (unit virtual F: ...)
\r
2446 (2) In all the units Ni except Nk, F must not occur in the
\r
2448 (3) In all the units except N1, F must occur in the taken list
\r
2449 unless the list is not specified. F must not occur in the
\r
2450 taken list in N1 if the list is specified.
\r
2451 (4) After removing the declaration of F from N1, F should be an
\r
2452 illegal attribute in N1 (hidden in the prefix, not taken) or
\r
2453 should denote a non-virtual attribute
\r
2454 (5) If Nk is not M, then one of the following conditions must be
\r
2456 - F occurs in the hidden list in Nk,
\r
2457 - F does not occur in the taken list in the unit
\r
2458 prefixed directly by Nk if the list is
\r
2460 - F is redefined in the unit prefixed directly
\r
2461 by Nk as a non-virtual attribute (then it must
\r
2462 not occur in the taken list either).
\r
2463 The class Nk from the definition is called the end of the virtual chain.
\r
2464 For a given unit and an identifier there may exist more than one virtual
\r
2473 M unit virtual F: <M-body>
\r
2475 N unit virtual F: <N-body>
\r
2479 R unit F: <R-body>
\r
2481 S unit virtual F: <S-body>
\r
2484 T unit F: <T-body>
\r
2486 We have three virtual chains of F with respect to T. One is for F from the
\r
2488 (F: <M-body>), (F: <N-body>),
\r
2489 The second is for F from the class S:
\r
2491 And the third one is for F in T:
\r
2498 (i) All virtual attributes belonging to the same virtual chain must be of
\r
2499 the same kind (either function or procedure),
\r
2501 (ii) All the declarations of the virtuals belonging to the same virtual
\r
2502 chain must have formal parameter lists of the same pattern, in particular:
\r
2504 - the lists may use different names of formal parameters,
\r
2505 but the correspondence between formal types must remain
\r
2508 - the class types of corresponding formal variables or
\r
2509 functions must belong to the same prefix sequence,
\r
2511 - the types of variable parameters or formal functions in
\r
2512 the ending of the virtual chain must not be less strongly
\r
2513 defined than the types of the corresponding parameters in
\r
2514 the beginning, i.e., a formal or system type against a
\r
2515 statically defined type,
\r
2517 - the types of virtual functions must be identical or the
\r
2518 type of the function from the beginning of the virtual
\r
2519 chain must be a prefix of the type of the function from
\r
2522 (iii) The compatibility of virtuals must be defined statically.
\r
2530 The following lists are not compatible
\r
2531 .... (type T; type P; X: T; Y: P) ....
\r
2532 .... (type R; type S; X: S; Y: R) ....
\r
2536 The following lists are compatible iff M and N belong to the same prefix
\r
2537 sequence (and both are classes)
\r
2538 .... (type T; Z: T; Z1: M) ....
\r
2539 .... (type P; X: P; Y: N) ....
\r
2543 The following lists are compatible iff M denotes a system type (coroutine
\r
2544 or process) or is a formal type
\r
2546 at the beginning: (X: M; Y: real)
\r
2547 at the ending: (X:coroutine; Y:real)
\r
2550 The following lists are not compatible:
\r
2556 The lists of the function from the beginning of the chain
\r
2558 ... function (Z:integer; Z1:P) : M
\r
2560 and from the ending
\r
2562 ... function (Z:integer; Z1:P) :N
\r
2564 are compatible iff M is a prefix of N.
\r
2568 6.4.2. Valuation of virtuals
\r
2569 ****************************
\r
2572 Let O be an object of type M with the prefix sequence M1, ..., Mk=M. The
\r
2573 value of virtual attribute F declared in Mi is:
\r
2575 - the text of the declaration taken from the end of the virtual chain,
\r
2576 - the environment of the object O.
\r
2580 An object of the class T given in the example 1 from 6.4.1 is of the
\r
2583 ---------------------------------------------
\r
2585 ! F : body F from N ! M !
\r
2586 ---------------------------------------------
\r
2588 ! F : body F from N ! N !
\r
2589 ---------------------------------------------
\r
2592 ---------------------------------------------
\r
2594 ! F : body F from R ! R !
\r
2595 ---------------------------------------------
\r
2597 ! F : body F from S ! S !
\r
2598 ---------------------------------------------
\r
2600 ! F : body F from T ! T !
\r
2601 ---------------------------------------------
\r
2604 The name "virtual subprogram" is derived from the features of virtual
\r
2605 entities, i.e., in any class a virtual subprogram F with an empty statement
\r
2606 list can be declared and then used as a virtual entity within the body of
\r
2607 the class. The user can assume the results of its execution without
\r
2608 knowledge of its internal structure. He can declare in a subclass a virtual
\r
2609 subprogram F again. This declaration replaces the previous one. So, during
\r
2610 the calls of the subprogram F in the body of the class as well as in the
\r
2611 body of the subclass, the subprogram with the text defined in the subclass
\r
2612 will be executed. This replacement is done only if F is a virtual attribute
\r
2613 of the subclass. Otherwise the new declaration of F covers the virtual
\r
2614 attribute of the class.
\r
2620 Abstention from those rules permits us:
\r
2622 (i) to define the types of the parameters of a virtual subprogram and to
\r
2623 check them already at compilation time,
\r
2625 (ii) to execute the virtual subprogram declared at the beginning of the
\r
2626 prefix sequence; its body may be empty, but it is always defined,
\r
2628 (iii) to end the virtual chain and to cover a virtual identifier by a
\r
2631 The possibilities (ii) and (iii) can be used in the following case. Let M
\r
2632 and N be system classes of the form :
\r
2635 unit virtual error: procedure;
\r
2636 (* virtual procedure to be defined in M's subclasses*)
\r
2640 if B1 then call error fi;
\r
2644 unit virtual error: procedure;
\r
2645 (* the definition of the body of error. It
\r
2646 will be executed during the calls within N
\r
2647 as well as in M *)
\r
2651 if B2 then call error fi;
\r
2654 If the programmer prefixes his own units by class M, he can declare his
\r
2655 own virtual procedure error. If he does not intend to signalize any errors,
\r
2656 he is able to use M without a redeclaration. Then if the condition B1 is
\r
2657 satisfied, the procedure with an empty body will be called, i.e., no
\r
2658 statement will be executed. On the other hand, if the programmer uses N as
\r
2659 a prefix of his own units, he can redeclare his own non-virtual procedure
\r
2660 error. In consequence, during the execution of statements of the classes M
\r
2661 and N the procedure defined by this system in the class N will be executed.
\r
2662 However during the execution of the user's units the procedures defined by
\r
2663 himself will be executed.
\r
2667 6.5. Dynamic location
\r
2668 **********************
\r
2670 An executable program must always be a well-formed expression. During its
\r
2671 execution we can deal with many objects of the same syntactic unit even at
\r
2672 the same time. Hence an execution of a statement (in an object) requires
\r
2673 identification and access to all the syntactic entities used. In order to
\r
2674 define the syntactic environment of object O (of unit M) a static link (SL)
\r
2675 is introduced. This link always points to an object O1 of a unit N such
\r
2676 that M is declared in N.
\r
2677 Let us consider the occurrence of identifier W within a body of class N
\r
2678 from the prefix sequence of M. Let SL(M) denote the SL-chain of objects
\r
2679 starting from an object of unit M. This means that SL(M) is a sequence of
\r
2680 objects O1, ..., Ok such that O1 is an object of unit M, Ok is an object of
\r
2681 the main program, the SL-link of object Oi points to object Oi+1, for every
\r
2684 The dynamic container of the occurrence of W in a body of class N with
\r
2685 respect to an object O1 (denoted by DC(W, N, O1)) is an object Oi from
\r
2688 (*) Oi is an object of the unit prefixed by the static container SC(W,
\r
2690 (**) Oi is the nearest object in the SL-chain such that Oi satisfies (*).
\r
2692 Hence the dynamic container is the unique object which contains the
\r
2693 valuation of the entity W related to the occurrence of this entity. Let us
\r
2694 return to the example from 6.3.; after the creation (new T) of an object O
\r
2695 of the class T the SL-chain of O is as follows:
\r
2697 -------------- ------------ ---------------
\r
2698 ! X ! M ! ! X ! M ! ! ! R !
\r
2699 <----- !------!-----! <------- !-----!----! <------ !-------!-----!
\r
2700 ! X ! N ! SL ! X ! N ! SL ! ! !
\r
2701 !------!-----! !-----!----! ! ! T !
\r
2702 OP ! Y,R ! P ! OS ! Y,T ! S ! O ! ! !
\r
2703 -------------- ------------ ---------------
\r
2705 Because SC(X, R)=SC(X, T)=N , we have DC(X, R, O)=DC(X, T, O)=OS. Since
\r
2706 SC(Y, T)=S , we have DC(Y, T, O)=OS. On the other hand SC(Y, R)=P and DC(Y,
\r
2708 The syntactic environment of an object is determined by the SL chain. Its
\r
2709 main property is that for each identifier occurrence in the statements of
\r
2710 the given object exists its dynamic container in the chain. In order to
\r
2711 define the dynamic location of identifier W occurring in object O of unit M
\r
2712 in a body of unit R (which belongs to the prefix sequence of M), the
\r
2713 following steps are performed:
\r
2715 - a static container N=SC(W, R) is defined;
\r
2716 - a dynamic container O1=DC(W, R, O) is defined (in the SL chain of object
\r
2717 O, the nearest object O1 is found such that this object has a "layer" <V,
\r
2719 - a valuation V1(W) is found in the layers <V1, N1> of the object O1 such
\r
2720 that N1 is the nearest N's prefix.
\r
2724 7. Consistency of types
\r
2725 #######################
\r
2727 In order to determine the context-sensitive correctness of an assignment
\r
2728 statement and parameter transmission it is necessary to introduce the
\r
2729 notion of the static consistency of types. Nevertheless this notion is not
\r
2730 sufficient to determine the correctness of the executions of those
\r
2731 constructs. Therefore, the notion of the dynamic consistency of types will
\r
2732 be introduced to define the semantic correctness of program. The introduced
\r
2733 distinction follows from the implementation constraints; namely, static
\r
2734 consistency is verified at compilation time, dynamic consistency is
\r
2735 verified at run time.
\r
2738 Static consistency of types
\r
2739 ---------------------------
\r
2741 The type (array_of)<i>T is statically consistent with the type
\r
2742 (array_of)<j>S, where T and S are not array types, iff one of the following
\r
2745 - i=j=0 and T, S are integer or real types,
\r
2746 - both T and S are formal types,
\r
2747 - T is a formal type, S is not a formal type and i<=j,
\r
2748 - S is a formal type, T is not a formal type and j<=i,
\r
2749 - i=j=0 and T, S are generalized class types and T pref* S or
\r
2751 - i=j=0 and T and S are one of them a system type and the other a
\r
2752 generalized class or system type.
\r
2755 Dynamic consistency of types.
\r
2756 -----------------------------
\r
2758 The type (array_of)<i>T is dynamically consistent with the type
\r
2759 (array_of)<j>S, where T and S are not array types, iff one of the following
\r
2762 - i=j=0 and T, S are integer or real types,
\r
2763 - i=j=0 and T, S are generalized class types and T pref* S,
\r
2764 - i=j=0, T = coroutine, and S is declared as:
\r
2765 unit S: ... coroutine ...; or
\r
2766 unit S: ... process .....; or
\r
2767 unit S: R class..., where T is dynamically consistent with R,
\r
2768 - i=j=0, T = process, and S is declared as:
\r
2769 unit S: ... process .......; or
\r
2770 unit S: R class..., where T is dynamically consistent with R.
\r
2772 At run time all formal types are replaced by actual non-formal ones.
\r
2773 Therefore, there is no reason to define dynamic consistency for formal
\r
2775 Dynamic consistency is a subrelation of static consistency. Thus the
\r
2776 dynamic consistency is checked at compilation time, if possible. In other
\r
2777 cases the check is made at run-time.
\r
2778 From now on we shall use the following notation:
\r
2779 - for the desription of context properties, an occurrence of an
\r
2780 expression E is considered to be contained in the body of unit M,
\r
2781 - for the desription of semantic properties, an occurrence of an
\r
2782 expression E is considered to be contained in the body of unit M, with
\r
2783 respect to an object O of type M0 such that M pref* M0.
\r
2791 Expressions are composed of primitive expressions - constants and
\r
2792 variables by means of system operators and functions. They serve as
\r
2793 patterns for computing a certain value. Two kinds of expression properties
\r
2794 have to be considered: context (static) and semantic (dynamic) ones.
\r
2799 Context properties.
\r
2800 -------------------
\r
2802 We consider two context properties of each expression:
\r
2803 - to be a well-formed formula,
\r
2804 - to have a static type.
\r
2806 The context correctness of an expression is examined at compilation time.
\r
2807 From now on, an expression is said to be a well-formed formula (shortly :
\r
2808 WFF) if it is statically correct. The static type of an expression is
\r
2809 determined by the program text.
\r
2814 Semantic properties.
\r
2815 --------------------
\r
2817 We consider three semantic properties of each expression:
\r
2819 - to have a dynamic type,
\r
2820 - to have the type of its value.
\r
2822 In some cases (for expressions of formal types) type must be determined
\r
2823 at run-time. Replacing formal types by the corresponding actual ones in the
\r
2824 static types of expressions, we obtain the dynamic types of those
\r
2825 expressions. Notice, that the actual type may not be accessible, if the
\r
2826 dynamic container for the formal type of the expression was killed. The
\r
2827 dynamic type will be defined only for the expressions which may occur on
\r
2828 the left side of an assignment, i.e., for variables. When the value and the
\r
2829 type of the value are computed, the semantic correctness of the expression
\r
2831 From now on an expression is said to be defined if it is dynamically
\r
2832 correct at run-time. The correctness of an expression will be examined
\r
2833 under the assumption that it is a WFF. Five kinds of expressions are
\r
2834 distinguished: arithmetic, boolean, character, string, and object
\r
2848 -----> <identifier> ----->
\r
2853 Let E be a constant Q. The expression Q is a WFF if the static container
\r
2854 SC(Q, M) exists. The static type of Q is determined by its declaration (see
\r
2855 5.1.). A constant cannot occur on the left side of an assignment statement,
\r
2856 as an actual output parameter, or in an expression X.Q, where X is an
\r
2857 object expression.
\r
2862 The constant Q is always defined. The value of the constant is fixed from
\r
2863 the declaration of that constant and cannot be modified. The type of the
\r
2864 value is equal to the static type.
\r
2878 --------> <simple variable> ------------>
\r
2880 !---> <subscripted variable>->!
\r
2882 !----> <dotted variable> ---->!
\r
2884 !----> <system variable> ---->!
\r
2887 For each kind of variables its context and semantic correctness will be
\r
2888 defined. Additionally the dynamic address of a variable will be defined as
\r
2889 a pair: (reference to an object, attribute of that object).
\r
2893 8.2.1. Simple variable
\r
2894 **********************
\r
2901 (simple variable>:
\r
2903 ----> <identifier> ----->
\r
2906 Let E be a variable Z.
\r
2912 The variable Z is a WFF if the static container SC(Z, M) = R exists. The
\r
2913 static type of Z is determined by the declaration of Z and may be a formal
\r
2919 The variable Z is defined if the dynamic container O1 = DC(Z, M, O)
\r
2920 exists. Let the static type of Z be: (array_of)<i>S. The dynamic type of Z
\r
2921 is equal to (array_of)<i>S in the case where S is not formal, otherwise it
\r
2922 is (array_of)<i+k>T, where the actual type corresponding to the formal one
\r
2923 is (array_of)<k>T.
\r
2924 The actual type is taken from the dynamic container DC(S, R, O1), i.e.,
\r
2925 from an object belonging to the SL chain of the object O1. The value of Z
\r
2926 is given by the corresponding valuation of Z in the object O1. The address
\r
2927 of Z is a pair: (the reference to O1, attribute Z of O1).
\r
2931 8.2.2. Subscripted variable
\r
2932 ***************************
\r
2939 <subscripted variable>:
\r
2941 --> <simple variable> --> ( -> <arithmetic expression> -----> ) -->
\r
2943 !<----------- , --------------!
\r
2946 Let E be an expression of the form Z(A1, ..., Ak), where Z is a simple
\r
2947 variable and A1, ..., Ak are arithmetic expressions.
\r
2952 Let (array_of)<i>S denote a static type of Z. The expression Z(A1, ...,
\r
2954 - Z and A1, ..., Ak are WFFs,
\r
2955 - static types of A1, ..., Ak are integer or real,
\r
2957 The static type of E is (array_of)<i-k>S.
\r
2962 The expression E is defined if:
\r
2963 - the expression Z(A1, ..., Ak-1) is defined and its value equals the
\r
2964 reference to a non-empty array object O1 with the bounds l and u, l<=u.
\r
2965 - the value of Ak is defined and its truncation l1 satisfies: l<=l1<=u.
\r
2966 The dynamic type of E is equal to the static one if S is not formal,
\r
2967 otherwise it is (array_of)<i-k+j>T where the actual type corresponding to
\r
2968 the formal one is (array_of)<j>T. The actual type is determined as for a
\r
2969 simple variable (see 8.2.1.). The value of E is that of the attribute (l1)
\r
2970 of the object O1. The address of E is the pair: (the reference to O1,
\r
2975 8.2.3. Dotted variable
\r
2976 **********************
\r
2983 <dotted variable>:
\r
2985 -> <qualified object expression> -->. --> <variable> ---->
\r
2988 It is sufficient to consider the expression E of the form X.Y, where Y is
\r
2989 a simple or subscripted variable.
\r
2994 The expression E is a WFF if:
\r
2997 - X, Y are WFFs, X is the qualified object expression,
\r
2998 - the static type of X is a generalized class type,
\r
2999 - Y is a non-closed attribute of the static type of X.
\r
3002 The static type of E is the same as the static type of Y. Notice that the
\r
3003 static type of X cannot be a formal type.
\r
3008 The expression E is defined if:
\r
3011 - the expression X is defined,
\r
3012 - the value of X is a reference to a non-empty object O1.
\r
3015 The dynamic type of E is the same as the dynamic type of Y would be if Y
\r
3016 occurred in the object O1. The value of X.Y is that of the attribute Y of
\r
3017 the object O1. The address of X.Y is the address of Y would be if Y
\r
3022 8.2.4. System variable
\r
3023 **********************
\r
3029 <system variable>:
\r
3031 ------> result ---------------------------------------->
\r
3034 CONTEXT and SEMANTICS.
\r
3035 ----------------------
\r
3037 For every function F there is an implicitly declared variable result of
\r
3038 type T of the value of function F. The initial value of that variable
\r
3039 depends on type T (is equal to the default value of type T), the final
\r
3040 value (after completion of a function call) is also the value of function F
\r
3041 for the given call (see 9.1.2.). An occurrence of the variable result is
\r
3042 matched with the smallest unit F which contains that occurrence and which
\r
3049 unit Newton_symbol: function (i, k:integer): integer;
\r
3056 result:=result*(i-j)div(j+1)
\r
3059 end Newton_symbol;
\r
3063 8.3. Arithmetic expression
\r
3064 **************************
\r
3070 <arithmetic expression>:
\r
3072 !------------------->!
\r
3074 -----------> <sign> --------> <term> ------->
\r
3076 !<--------------------------------!
\r
3090 ---------> <factor> ----------------->
\r
3092 ! !<-------------------!
\r
3098 !<-----------------!
\r
3104 ------------------ <integer> -------------------------------->
\r
3106 !-<abs>-! !---> <real> ---------------------------->!
\r
3108 !--> <constant> ------------------------->!
\r
3110 !--> <variable> ------------------------->!
\r
3112 !------> <function call> ---------------->!
\r
3114 !-> ( -><arithmetic expression>-> ) ----->!
\r
3120 -----> <digit> ------>
\r
3129 ---> <integer>--> . ---> <integer>----->E --> <sign>--> <integer> -->
\r
3131 !------------------>! !---------------------------->!
\r
3134 (function call will be defined in 9.1.2.).
\r
3136 CONTEXT and SEMANTICS.
\r
3137 ----------------------
\r
3139 The type of the value of an arithmetic expression is always equal to its
\r
3140 static type. The dynamic type is not to be defined. The context and
\r
3141 semantic properties of arithmetic expressions will be defined inductively.
\r
3144 The type of an integer is integer, the type of a real is real, their
\r
3145 values are given directly. Constant, variable, and function call must be
\r
3146 WFFs (in the meaning of 8.1., 8.2 and 9.1.2.), and of type integer or real
\r
3147 (in order to create a well-formed factor). The factor is defined iff the
\r
3148 variable and the function call are defined. The context and semantic
\r
3149 properties of the factors of the form " abs A1 ", and " (A2) " are the same
\r
3150 as those of arithmetic expressions A1 and A2, respectively. The value of "
\r
3151 abs A1 " is the absolute value of A1.
\r
3155 The operators *, /, div, mod are interpreted as multiplication, division,
\r
3156 integer division and remaindering, respectively. The last two operators are
\r
3157 defined for integer arguments only, " A1 div A2 " is equal to the
\r
3158 truncation of A1/A2; " A1 mod A2 " is equal to the remainder of A1/A2. The
\r
3159 type of a term of the form <factor> <operator> <factor> is real if the
\r
3160 operator is /, or at least one of the arguments is of type real. The term "
\r
3161 A1/A2 " is defined if the value of A2 is different from 0. The value is
\r
3162 defined inductively if Av1 and Av2 are the values of factor A1 and term A2
\r
3163 respectively, and <W> is an interpretation of operator W, then the value of
\r
3164 a term of the form " A1 W A2 " is Av1 <W> Av2. If one of the arguments is
\r
3165 of type integer and the other is of type real then for the operators *, /
\r
3166 the integer type value is converted into a real type one.
\r
3169 Arithmetic expression.
\r
3170 An arithmetic expression of the form <term> <sign> <term> is of type
\r
3171 integer if both terms are of that type and it is of type real in the
\r
3172 opposite case. A value is defined inductively: if Av1 and Av2 are the
\r
3173 values of term A1 and arithmetic expression A2, respectively, then the
\r
3174 value of an expression A1+(-)A2 is Av1+(-)Av2, the value of +(-)A1 is
\r
3175 +(-)Av1. If one of the arguments is of type integer and the other is of
\r
3176 type real, then the integer type value is converted into a real type one.
\r
3180 8.4. Boolean expression
\r
3181 ***********************
\r
3187 <boolean expression>:
\r
3189 -------> <boolean term> ---------------->
\r
3191 !<---- or <---------------!
\r
3196 ------> <boolean factor> ---------->
\r
3198 !<---- and <------------!
\r
3203 ----> not ----> <boolean primary> ------------>
\r
3208 <boolean primary>:
\r
3210 --------> <boolean constant> -------------------->
\r
3212 !----> <constant> -------------------->!
\r
3214 !----> <variable> -------------------->!
\r
3216 !----> <function call> --------------->!
\r
3218 !----> <relation> -------------------->!
\r
3220 !--> ( --> <boolean expression> ->)--->!
\r
3225 -----> <arithmetic relation> --------------->
\r
3227 !-> <boolean relation> ----------->!
\r
3229 !-> <character relation> --------->!
\r
3231 !-> <reference relation> --------->!
\r
3233 !-> <object relation> ------------>!
\r
3236 <boolean constant>:
\r
3238 -----> false -------->
\r
3244 <arithmetic relation>:
\r
3246 ---> <arithmetic expression> --> <arithmetic relational operator>
\r
3248 !<-----------------------!
\r
3250 !---> <arithmetic expression> ---->
\r
3253 <arithmetic relational operator>:
\r
3255 ----> <equality operator> --------->
\r
3257 !-> <inequality operator> -->!
\r
3260 <equality operator>:
\r
3262 ----------> = ---------------->
\r
3264 !------> =/= ------->!
\r
3267 <inequality operator>:
\r
3269 --------------------------------->!
\r
3273 !------------------------------->
\r
3276 <character relation>:
\r
3278 ---> <character expression> --> <equality operator> -->
\r
3280 !<-----------------------------------------!
\r
3282 !---> <character expression> ----->
\r
3285 <reference relation>:
\r
3287 ---> <object expression> --> <equality operator> -->
\r
3289 !<----------------------------------------------!
\r
3291 !---> <object expression> ------>
\r
3294 <object relation>:
\r
3296 ---> <object expression> ----> is ------> <system type> ------->
\r
3298 !--> in -->! !--> <class type> ---->!
\r
3302 CONTEXT and SEMANTICS.
\r
3303 ----------------------
\r
3305 The context and semantic properties of boolean expressions can be defined
\r
3306 in the same way as those of arithmetic ones. A boolean expression is of
\r
3310 The value of a boolean constant true and false is T and F, respectively.
\r
3311 The equality and inequality operators have the usual interpretation. Let
\r
3312 A1, A2 be two defined arithmetic expressions and let Av1, Av2 be their
\r
3313 values. Let <W> be an interpretation of the arithmetic relational operator
\r
3314 W. Then the value of arithmetic relation " A1 W A2 " is Av1 <W> Av2. If one
\r
3315 of the expressions is of type integer and the other is of type real then
\r
3316 the integer type value is converted into real type one.
\r
3318 Let C1, C2 be two defined character expressions and let Cv1, Cv2 be their
\r
3319 values. Then the value of the character relation " C1=C2 " (" C1=/=C2 ") is
\r
3320 true iff the characters Cv1, Cv2 are identical (different). For string type
\r
3321 there are no relations, even no equality.
\r
3323 A reference relation " X1=X2 " (" X1=/=X2 ") is a WFF if X1 and X2 are
\r
3324 well-formed object expression. The static types of the expressions have to
\r
3325 be statically consistent. The relation is defined if X1 and X2 are defined.
\r
3326 The value of that relation is true iff the values of both expressions are
\r
3327 equal to (different from) the same reference; in particular, if they are
\r
3328 both equal to none, then the value of " X1=X2 " is T.
\r
3329 An object relation "X is S" is a WFF if S is a generalized class
\r
3330 identifier, X is a WFF, and the static type of X is statically consistent
\r
3331 with S. An object relation "X in S" is a WFF if S is a generalized class or
\r
3332 system type identifier, X is a WFF, and the static type of X is statically
\r
3333 consistent with S. The value of the relation "X is S" is T iff the value of
\r
3334 the expression X is the reference to an object of class S. The value of the
\r
3335 relation "X in S" is T iff the value of X belongs to the set !S! .
\r
3338 The value of a boolean factor "not B", where B is a boolean primary, is T
\r
3339 iff the value of B is F.
\r
3342 Let Bv2 and Bv1 be the values of boolean factor B2 and boolean term B1,
\r
3343 respectively. Then the value of a term of the form "B1 and B2" is T iff
\r
3346 Boolean expression
\r
3347 Let Bv1 and Bv2 be the values of boolean term B1 and boolean expression
\r
3348 B2, respectively. Then the value of an expression of the form "B1 or B2" is
\r
3351 The value of the arithmetic and boolean expression is computed from left
\r
3352 to right with the following operator priorities:
\r
3353 (1) parentheses (, ), abs
\r
3354 (2) *, /, div, mod
\r
3356 (4) <, <=, >, >=, =, =/=
\r
3363 8.5. Character expression
\r
3364 *************************
\r
3370 <character expression>:
\r
3372 ----> <character constant> --------------------->
\r
3374 !---> <constant> --------------->!
\r
3376 !---> <variable> --------------->!
\r
3378 !---> <function call> ---------->!
\r
3381 <character constant>:
\r
3383 ----> ' -----> <symbol> -----> ' ------>
\r
3388 -------> <letter> ---------------------------->
\r
3390 !---> <digit> --------------->!
\r
3392 !---> <auxiliary sign> ------>!
\r
3394 !--> <other characters> ----->!
\r
3396 !-> (: --> <integer> --> :) ->!
\r
3401 CONTEXT and SEMANTICS.
\r
3402 ----------------------
\r
3404 Constant, variable and function call are WFFs if they are of type
\r
3405 character. The standard function ord is defined for a character expression
\r
3406 and gives an integer value (dependent on implementation).
\r
3410 8.6. String expression
\r
3411 **********************
\r
3418 <string expression>:
\r
3420 -----> <string constant> -------->
\r
3422 !---> <constant> ------->!
\r
3424 !---> <variable> ------->!
\r
3426 !---> <function call> -->!
\r
3430 <string constant>:
\r
3432 ---> " -------> <character> ---------------------> " ----->
\r
3434 !<-------------------------------------!
\r
3441 Constant, variable and function call are WFFs if they are of string type.
\r
3442 The quotation mark " in the string constant is written twice "".
\r
3446 The string type is a constant type in the sense that the universe is
\r
3447 defined at compilation time and there are no string operations predefined
\r
3448 in the language. However, a standard function may transform a string into
\r
3449 an array of characters. Then the user can treat the array of character as a
\r
3450 text type and can define any set of suitable text operations.
\r
3457 8.7. Object expression
\r
3458 **********************
\r
3463 <qualified object expression>:
\r
3465 --------> <object expression>--------------------------------------->
\r
3467 !--> <variable>--------> qua -> <class type identifier> -->!
\r
3469 !--> <function call> -!
\r
3471 <object expression>:
\r
3473 ----------> <object constant> --------------------->
\r
3475 !-----> <variable> ------------>!
\r
3477 !---> <function call> --------->!
\r
3479 !---> <object generator> ------>!
\r
3481 !----> <local object> --------->!
\r
3483 !-----> <process waiting> ----->!
\r
3485 <object constant>:
\r
3487 -----> none -------- >
\r
3491 ----> this ----> <class type> --------->
\r
3494 (Function call and object generator will be defined in 9.1.2, process
\r
3495 waiting will be defined in 11.1. Variable is described in 8.2.).
\r
3501 The constant none is of a fictitious type statically consistent with any
\r
3502 non-primitive type.
\r
3503 To define the context of a local expression let us recall that the
\r
3504 occurrence of the expression E is considered in the unit M. Let E be the
\r
3505 local object "this T", then E is a WFF if there exists a unit N such that M
\r
3506 decl* N and T pref* N, (i.e., there exists a unit N statically enclosing M
\r
3507 and containing T in its prefix sequence). The static type of the expression
\r
3509 The qualified object expression of the form "X qua T" is a WFF if X is a
\r
3510 WFF and the static type of X is statically consistent with T. The static
\r
3511 type of this expression is T.
\r
3515 The constant none is always defined as an empty object. Every compound
\r
3516 and system type is dynamically consistent with the fictitious type of none.
\r
3517 The value of the local object "this T" is the nearest object of the type T1
\r
3518 belonging to the SL chain of the object O such that T1 is prefixed by T,
\r
3519 (recall that O contains the given occurrence of the local object). The
\r
3520 expression "this T" is defined if its value exists. The dynamic type is not
\r
3521 to be defined. The type of the value is S. The qualified object expression
\r
3522 of the form "X qua T" is defined if X is defined, its value is different
\r
3523 from none, and the dynamic type of X as well as the type of its value are
\r
3524 dynamically consistent with T. The value of this expression is equal to the
\r
3525 value of X. The dynamic type is not to be defined.
\r
3529 9. Sequential statements.
\r
3530 ##########################
\r
3533 Sequential statements are patterns for the sequencing of primitive actions.
\r
3540 <sequential statement>:
\r
3542 --------> <primitive statement> ------------>
\r
3544 !-------> <compound statement> ---->!
\r
3548 In a similar way to that followed in the description of expressions we
\r
3549 shall consider context and semantic properties of statements. A statement
\r
3550 will be called a WFF if it is correct at compilation time, and said to be
\r
3551 defined if it is correct at run time.
\r
3558 9.1. Sequential primitive statements
\r
3559 *************************************
\r
3562 The result of an execution of a primitive statement consists in the
\r
3564 - the valuation (assignment statement);
\r
3565 - the configuration (allocation and deallocation statement);
\r
3566 - the control (control statement).
\r
3568 By a configuration we mean the set of all objects existing at a given state
\r
3576 <primitive statement>:
\r
3578 --------> <evaluation statement> ------------->
\r
3580 !----> <configuration statement> ---->!
\r
3582 !----> <simple control statement> --->!
\r
3584 !----> <coroutine statement> -------->!
\r
3590 9.1.1. Evaluation statement
\r
3591 ****************************
\r
3597 <evaluation statement>:
\r
3599 --------> <empty statement> ---------------------->
\r
3601 !----> <assignment statement> ------>!
\r
3603 !----> <copying statement> --------->!
\r
3607 <empty statement>:
\r
3609 --------------------------->
\r
3615 An execution of an empty statement has no effect.
\r
3625 <assignment statement>:
\r
3627 ------> <variable list> ---> := --> <expression> ---->
\r
3632 ----------> <variable> ------> , --------------->
\r
3635 <---------------------------------
\r
3641 An assignment statement of the form y1, ..., yk:=e is a WFF if:
\r
3642 - variables y1, ..., yk and expression E are WFFs;
\r
3643 - the static types T1, ..., Tk of variables y1, ..., yk are statically
\r
3644 consistent with the static type S of the expression E.
\r
3651 The execution of a statement consists of three steps : prologue, body and
\r
3654 In the prologue the computation of the addresses of variables y1, ..., yk
\r
3655 is performed, i.e.:
\r
3657 - For a dotted variable of the form X.z, the value of the expression X is
\r
3659 - For a subscripted variable of the form Z(i1, ..., ij) the value of the
\r
3660 expression Z(i1, ..., ij-1) is computed. If Z is of a formal type, then the
\r
3661 dynamic type T of the variable Z is determined. Finally the value of the
\r
3662 expression ij is computed.
\r
3664 The above actions are performed from left to right.
\r
3667 During the body the computation of the type and the value of expression E
\r
3671 The epilogue checks if the statement is well-defined and assigns the
\r
3672 values to the attributes determined by the addresses evaluated during the
\r
3675 An assignment is defined, if:
\r
3676 - the expressions y1, .., yk, E are defined;
\r
3677 - the dynamic types of y1, .., yk are defined and are dynamically
\r
3678 consistent with the type of the value of E.
\r
3680 The values are assigned from right to left, i.e., at first the value of E
\r
3681 is assigned to yk (with possible conversion to the type of yk), next the
\r
3682 value of yk is assigned to yk-1 (with appropriate conversion), and so on.
\r
3683 For example, when r is real, n is integer, then:
\r
3685 after r, n:=2.5 we have n=2, r=2.0,
\r
3686 after n, r:=2.5 we have r=2.5, n=2.
\r
3691 The value of the expression Z computed at prologue may point to a non-empty
\r
3692 object O, but it could be changed to none as a result of the deallocation
\r
3693 of the object O (during the execution of the statement). It will be
\r
3694 detected at epilogue and will result in a run-time error.
\r
3701 An object of a compound type can be simultanously referenced by a number
\r
3702 of variables. If X and Y are the variables of such a type, then after
\r
3703 assignment X:=Y, both variables reference the same object. Hence some
\r
3704 side-effects may occur: the value of an attribute of the object referenced
\r
3705 by variable X can be changed as a result of an access to that object by
\r
3706 means of variable Y. In order to avoid such effects, one can use a copying
\r
3711 after which both variables reference identical objects but not the very
\r
3718 <copying statement>:
\r
3720 -> <variable list> -> := -> copy -> ( -> <object expression> -> ) ->
\r
3723 CONTEXT and SEMANTICS.
\r
3724 ----------------------
\r
3726 The semantics of the copying statement differs from that of the assignment
\r
3727 statement in the following points:
\r
3730 - The copying statement is defined if the value of the right side object
\r
3731 expression E is a reference to a terminated class object (i.e., an object
\r
3732 whose all statements were completed, see 9.1.3). Coroutine or process
\r
3733 objects must not be copied.
\r
3736 - During the epilogue, the copy of the value of the expression E is
\r
3737 assigned (a copy of none is none).
\r
3741 9.1.2. Configuration statement
\r
3742 *******************************
\r
3745 Configuration statements correspond to the generation and deallocation of
\r
3746 units and arrays. Allocation of an array object is a result of array
\r
3747 generation, allocation of a unit object is a result of a subprogram call,
\r
3748 generation of a generalized class object or block statement.
\r
3754 <configuration statement>:
\r
3756 -----> <object allocation> ------->
\r
3758 !--> <object deallocation> -->!
\r
3761 9.1.2.1. Allocation statement
\r
3762 *****************************
\r
3769 <object allocation>:
\r
3771 ------> <function call> ----------------->
\r
3773 !--> <procedure call> -------->!
\r
3775 !--> <object generation> ----->!
\r
3777 !---> <block statement>------->!
\r
3779 !--> <array generation> ------>!
\r
3784 ---> <remote function identifier> ---> <actual parameter list> ---->
\r
3786 !--------------------------->!
\r
3791 --> call --> <remote procedure identifier> -->!
\r
3793 !<-----------------------!
\r
3795 !---> < actual parameter list> ------------>
\r
3797 !----------------------------------->!
\r
3801 <object generation>:
\r
3803 --> <qualified object expression> --> . --> new -----!
\r
3805 !--------------------------------------! !
\r
3807 !--------------------------------------------------!
\r
3809 !--> <class identifier>---> <actual parameter list> -------->
\r
3811 !---------------------------!
\r
3814 <remote function identifier>:
\r
3816 ----> <qualified object expression> --> . -->!
\r
3818 !----------------------------------------! !
\r
3820 !--------------------------------------------!
\r
3822 !---> <function identifier> --->
\r
3825 <remote procedure identifier>:
\r
3827 ----> <qualified object expression> --> . -->!
\r
3829 !----------------------------------------! !
\r
3831 !--------------------------------------------!
\r
3833 !---> <procedure identifier> --->
\r
3836 <actual parameter list>:
\r
3838 ---->(----------------> <expression> ----------------> ) ---->
\r
3840 ! !-><remote function identifier>-------->! !
\r
3842 ! !-><remote procedure identifier>------->! !
\r
3844 ! !-><type identifier>------------------->! !
\r
3846 !--------------- , <---------------------------!
\r
3853 We shall start with an allocation of a unit object O, i.e., subprogram
\r
3854 call, object generation and block statement. The execution of those
\r
3855 statements causes the generation of the new object O. Let Pa1, ..., Pak
\r
3856 denote actual parameters, k>=0, and let X be an object expression. The
\r
3857 allocation of an object of unit M is of one of the following forms:
\r
3859 - for function M: M(Pa1, ..., Pak) or X.M(Pa1, ..., Pak)
\r
3860 (a function call must occur in an expression; it is not allowed as an
\r
3861 independent statement);
\r
3863 - for procedure M: call M(Pa1, ..., Pak) or call X.M(Pa1, ..., Pak);
\r
3865 - for class M: new M(Pa1, ..., Pak) or X.new M(Pa1, ..., Pak);
\r
3866 (an object generator may occur in an expression and it is also allowed as
\r
3867 an independent statement).
\r
3869 - for block statement: pref M(Pa1, ..., Pak) block...end or block... end
\r
3870 (a block can be considered as an unnamed unit and a generation of its
\r
3871 object is the result of an occurrence of that block statement).
\r
3874 The allocation of a unit object is a WFF if:
\r
3876 - a unit identifier M is visible (in the sense of the rules
\r
3877 used for the variables, see 8.2.),
\r
3878 - the actual parameters are WFFs,
\r
3879 - the formal parameter list and the actual parameter list
\r
3880 are statically compatible in the sense given below.
\r
3882 Let us recall (5.3.5.) that a formal parameter list of a unit M is
\r
3883 defined as a concatenation of the lists of units belonging to the prefix
\r
3886 Static compatibility of parameters.
\r
3888 The list of formal parameters (Pf1, ..., Pfj) is statically compatible
\r
3889 with the list of actual parameters (Pa1, ..., Pak) if j=k and for i=1, ...,
\r
3890 k the following conditions hold:
\r
3892 - if Pfi is an input/output formal parameter then Pai is a
\r
3893 WFF of a static type which is statically compatible with
\r
3894 the static type of parameter Pfi,
\r
3895 - if Pfi is an output/inout parameter then Pai is a
\r
3897 - if Pfi is a formal function (procedure) then Pai is a
\r
3898 function (procedure) identifier,
\r
3899 - if Pfi is a formal type then Pai is a non-primitive type
\r
3907 The allocation of a unit object O is defined if:
\r
3908 - the unit and its environment are determined,
\r
3909 - the list of formal parameters is dynamically compatible
\r
3910 with that of actual parameters (in the sense provided
\r
3912 - three steps of actions, called prologue, body, and
\r
3913 epilogue, are determined.
\r
3915 Note the difference between the unit identifier and the unit itself. The
\r
3916 environment is the object which becomes the syntactic father of O. In the
\r
3917 case of a formal subprogram, the unit identifier may be replaced by one of
\r
3918 many existing units. Denote by O1 the object containing the given unit
\r
3919 object allocation statement. The prologue computes the values for input
\r
3920 formal parameters, determines the addresses of output actual parameters,
\r
3921 and determines actual subprograms/types. The prologue is executed in the
\r
3922 environment of the object O1. The body transfers the control to the
\r
3923 statements from the prefix sequence of the given unit. Those statements are
\r
3924 executed in the environment of the object O.
\r
3925 The epilogue transmits the values of output formal parameters (in the
\r
3926 environment of the object O1).
\r
3930 Consider the allocation of a unit which is not a block. A unit identifier
\r
3931 has one of the following forms:
\r
3934 (b) X.M or X.new M .
\r
3936 Ad (a). Let the static location of the given occurrence of M be
\r
3937 determined by the attribute M of the unit T. Consider three cases:
\r
3939 (a1) M is an attribute of T and it is neither a virtual attribute nor a
\r
3940 formal parameter. Then the declaration of M is determined as (at
\r
3941 compilation time) as the declaration of the attribute M of unit T. The
\r
3942 environment of the unit M is the dynamic container of identifier M with
\r
3943 respect to the object O1.
\r
3945 (a2) M is a virtual attribute of T. Then the declaration of M is
\r
3946 determined at run-time by the dynamic location of identifier M with respect
\r
3947 to the given occurrence (see 6.1.5.). The environment is determined as in
\r
3950 (a3) M is a formal subprogram of T. Then the declaration of M and its
\r
3951 environment are taken from the dynamic container of the identifier M. The
\r
3952 dynamic container is determined with respect to the object O1.
\r
3954 Ad (b). Let X be a well-formed object expression of type R, let M be a
\r
3955 not close attribute of R, and let the expression X be defined. Denote by O2
\r
3956 the non-empty object of unit R0 (R pref* R0) which is pointed to by X. The
\r
3957 cases (a1)-(a3) have to be considered in the same way as the above ones.
\r
3958 The descriptions differ in that the environments are determined with
\r
3959 respect to the object O2. Note that the environment of the object becomes
\r
3960 the syntactic father of the object O.
\r
3964 Dynamic compatibility of parameters.
\r
3966 First let us note the difference between the determination of dynamic type
\r
3967 for the actual parameter Pa and the formal parameter Pf. The dynamic type
\r
3968 of Pa is determined in the environment of the object O1 (containing the
\r
3969 given allocation). It means that for the formal type S the actual type is
\r
3970 taken from the dynamic container with respect to O1. Recall that it
\r
3971 corresponds to the determination of the valuation of identifier S in the
\r
3972 SL-chain of O1 (according to the visibility rules) and taking the text of
\r
3973 declaration assigned to S (cf. 6.1.5.).
\r
3974 The dynamic type of Pf is determined in the corresponding environment. It
\r
3975 means that for the formal type S the actual type is taken from the
\r
3976 corresponding dynamic container. In other words, the valuation of
\r
3977 identifier S is searched for in the SL-chain of the environment (according
\r
3978 to the visibility rules).
\r
3980 The list of formal parameters is dynamically compatible with the list of
\r
3981 actual parameters if the following conditions hold:
\r
3983 - if Pfi is an input formal parameter, then Pai is defined and
\r
3984 the dynamic type of Pfi is dynamically consistent with the
\r
3985 type of the value of Pai,
\r
3986 - if Pfi is an output/inout formal parameter, then Pai is
\r
3987 defined and the dynamic type of Pai is statically consistent
\r
3988 (!) with the dynamic type of Pfi,
\r
3989 - if Pfi is a formal function (procedure), then the lists of
\r
3990 formal parameters of Pfi and that of Pai must be of the same
\r
3991 pattern (disregarding the descriptions of subprogram
\r
3992 parameters). They may differ in the parameter identifiers, and
\r
3993 they may differ in the class types of corresponding parameters
\r
3994 (however, the class types must belong to the same prefix
\r
3996 - if Pfi is a formal function, then the dynamic type of Pfi
\r
3997 prefixes the dynamic type of Pai, or the two types are
\r
4000 The above conditions are checked from left to right (i.e., for i=1, ...,
\r
4003 Recall that in the following description of prologue and epilogue the
\r
4004 computations of the values and addresses for formal parameters and actual
\r
4005 ones are performed in the syntactic environment of the object O1.
\r
4011 The prologue consists of the following steps:
\r
4013 (i) The frame for a new object O is allocated, the object O1 is called
\r
4014 the dynamic father of the object O. The sequence of dynamic fathers creates
\r
4015 a chain called the DL chain (DL for dynamic links);
\r
4017 (ii) For the input and inout formal parameter Pf, the value of the
\r
4018 corresponding actual parameter is computed and assigned to Pf;
\r
4020 (iii) For the output and inout formal parameter Pf, the address of the
\r
4021 corresponding actual parameter Pa is computed (in other words, the prologue
\r
4022 of the assignment of Pf to Pa is performed);
\r
4024 (iv) For the formal type parameter Pf, the corresponding actual type Pa
\r
4025 is determined. According to 6.1.5. the valuation of the object O assigns
\r
4026 the text of the determined type Pa to the identifier Pf. Therefore as long
\r
4027 as that object exists the access to Pf is well-defined and connected with
\r
4030 (v) For the formal subprogram parameter, the actual subprogram is fixed
\r
4031 (in the same way as the determination of the allocated unit and its
\r
4035 After the execution of the epilogue the control is transferred to the
\r
4036 object O. Let M1, ..., Mk=M be the prefix sequence of M. The execution of
\r
4037 the statements from the object O begins from the first statement of the
\r
4038 unit M1 (for the description of the further progress of computation, see
\r
4039 inner statement, 9.1.3.). Note that those statements are executed in the
\r
4040 syntactic environment of the object O. When the control returns to the
\r
4041 calling object O1, the actions of the epilogue are performed.
\r
4047 The epilogue consists of the following steps:
\r
4049 (i) For the output and inout formal parameter Pf the actions of the
\r
4050 epilogue for the assignment Pa:=Pf are performed, where Pa is the actual
\r
4051 parameter corresponding to Pf. It means that the value of Pf (computed
\r
4052 during the execution of the body) is assigned to Pa (this address was
\r
4053 computed during the prologue);
\r
4055 (ii) If the unit is a function, then the result of the given call is
\r
4056 determined by the current value of the corresponding variable result,
\r
4058 (iii) If the unit is a generalized class, then the result of a new M is a
\r
4059 reference to the object O;
\r
4061 (iv) A terminated object (cf. 9.1.3.) of a block or a subprogram is
\r
4062 deallocated. However, the terminated object of a generalized class is
\r
4063 accessible as long as there is a reference pointing to it (unless it is
\r
4064 directly deallocated by means of the kill statement).
\r
4070 Note that for the input formal parameter Pf of non-primitive type, the
\r
4071 value of the corresponding actual variable parameter Pa may be updated
\r
4072 (both the formal parameter and the actual one point to the same object). In
\r
4073 order to access the value of Pa without the possibility of its modification
\r
4074 one can use the copying statement Pf:=copy(Pf) at the end of the unit body.
\r
4089 <array generation>:
\r
4091 ----> new_array -----> <variable > -----> ( -->!
\r
4093 !<----------------------------------------------!
\r
4095 !--> <arithmetic expression> --> : --> <arithmetic expression>--> ) -->
\r
4098 A declaration of a variable of an array type fixes the type of the array
\r
4099 elements; bound pairs are fixed at the time of generation.
\r
4104 A statement new_array Y dim (l:u) is a WFF if:
\r
4106 - Y is a variable of the type (array_of)<i>T, where i>0, T is a type
\r
4109 - l, u are WFFs and arithmetic expressions.
\r
4111 The above statement is considered to be an assignment of a reference (to a
\r
4112 newly created object) on the variable Y.
\r
4117 The following actions are performed:
\r
4119 - determine the address of variable Y;
\r
4120 - compute the values l1, u1 of expressions l, u;
\r
4121 - put l0, u0 truncations of l1, u1 respectively;
\r
4122 - check the condition l0<=u0;
\r
4123 - generate an array object and assign its address to Y.
\r
4125 The initial values of attributes (l0), ..., (u0) depend on their type of
\r
4126 the form (array_of)<i-1>T.
\r
4127 The value of an array type variable may be changed by means of
\r
4128 assignment, copying, and generation statements. The generation of an
\r
4129 n-dimensional array consists of n steps. The first dimension is generated:
\r
4130 e.g. new_array Y dim (l1:u1),
\r
4131 next the second dimension:
\r
4132 e.g. for i:=l1 to u1 do new_array Y(i) dim (li2:ui2) od
\r
4133 and so on. Unregular arrays can be generated in this way.
\r
4137 9.1.2.2. Deallocation statement
\r
4138 *******************************
\r
4141 <object deallocation>:
\r
4143 ----> kill ----> ( ----> <object expression> ----> ) --->
\r
4145 CONTEXT and SEMANTICS.
\r
4146 ----------------------
\r
4148 A statement kill(X) is a WFF if X is a well formed object expression of
\r
4149 compound type. The statement kill(none) is always WFF and it is equivalent
\r
4150 to the empty statement.
\r
4151 The statement is defined if X points to an object O not belonging to the
\r
4152 SL chain or DL chain of an active object. By an active object we mean the
\r
4153 object containing the statement currently being executed (notice that in
\r
4154 the case of parallelism there may co-exist several active objects).
\r
4155 The execution of the statement results in the deallocation of object O,
\r
4156 all variables pointing to O are set to none. The deallocation of an object
\r
4157 which belongs to the SL chain or DL chain of an active object results in a
\r
4159 The statement kill(X) where X points to a coroutine head is described in
\r
4160 9.1.4. The statement kill(X) where X points to a process is described in
\r
4166 After a block or subprogram termination, the corresponding object is
\r
4167 automatically deallocated. On the other hand, the array, class, coroutine,
\r
4168 or process objects are not automatically deallocated. The computer memory
\r
4169 may be overloaded with such objects even if they are no longer referenced.
\r
4170 Those objects are recovered with the help of the system program called the
\r
4171 garbage collector. The user can help in the execution of that system
\r
4172 program and increase the efficiency of his program execution if he
\r
4173 deallocates unnecessary objects. One should realize, however, what are the
\r
4174 effects of deallocation (in particular, a side effect consisting in the
\r
4175 modification of the values of all variables which point to the same
\r
4176 deallocated object).
\r
4184 The deallocation of a binary tree can be performed by means of the
\r
4185 following recursive procedure:
\r
4187 unit tree_kill: procedure (n:node);
\r
4189 if n.l=/=none then call tree_kill(n.l) fi;
\r
4190 if n.r=/=none then call tree_kill(n.r) fi ;
\r
4194 where the class node has the form
\r
4205 9.1.3. Simple control statement
\r
4206 ********************************
\r
4209 There are two kinds of simple control statements: a textual control
\r
4210 statement and a dynamic control statement. In this section we shall
\r
4211 consider the occurrence of a control statement in the object O of the unit
\r
4212 M, in the body of the unit Mj, where M has the prefix sequence M1, ...,
\r
4213 Mk=M, and 1<=j<=k.
\r
4218 <simple control statement>:
\r
4220 -----> <textual control statement> -------->
\r
4222 !--> <dynamic control statement> --->!
\r
4224 <textual control statement>:
\r
4226 -------> inner ----->
\r
4229 !-----> exit ----->!
\r
4233 !---> repeat ----->!
\r
4239 For j=1, ..., k-1 the execution of the inner statement results in the
\r
4240 commencement of the execution of the unit Mj+1. The inner statement in the
\r
4241 body of the unit Mk=M is empty.
\r
4243 ------- ------- ------- -------
\r
4245 inner < inner < ........ < inner < .....
\r
4247 ------- ------- ------- -------
\r
4249 body of M1 body of M2 body of Mk-1 body of Mk
\r
4251 The semantics of repeat and exit statements will be defined jointly with
\r
4252 the semantics of a loop statement, see 9.2.3..
\r
4260 <dynamic control statement>:
\r
4262 ---------> return ----------->
\r
4267 In this section we shall describe the semantics of a return statement and
\r
4268 a pseudo-statement end (which bound a unit declaration).
\r
4269 An object may be in one of the following three states: non-generated,
\r
4270 generated, terminated. An object is non-generated until the control reaches
\r
4271 the first return statement. From that moment an object becomes generated.
\r
4272 An object is terminated after the execution of its end statement. The main
\r
4273 program is considered to be always generated. A generated object is
\r
4274 considered to have no dynamic father (its DL is none). Note that the
\r
4275 execution of a terminated object cannot be resumed. However, the execution
\r
4276 of the generated object of a coroutine or a process can be resumed and
\r
4277 suspended. The return statement is empty if M is a coroutine and O is
\r
4278 generated. If M is a block, subprogram, or generalized class and O is
\r
4279 non-generated then O becomes generated. The control returns to the dynamic
\r
4280 father of O. For a coroutine or process the statement following the return
\r
4281 statement is a reactivation point.
\r
4283 Now we shall consider the execution of the final end. For j=2, ..., k the
\r
4284 execution of the final end results in the control transfer to the statement
\r
4285 following the inner statement from the unit Mj-1. Suppose that j=1. If O is
\r
4286 a non-generated object of a coroutine, then O becomes generated and the
\r
4287 control returns to the dynamic father of O. Otherwise (O is a
\r
4288 coroutine/process object) the object O becomes terminated. The control
\r
4289 transfer is the same as in the case of detach statement. Moreover, if M is
\r
4290 a process, then the control becomes idle (and the corresponding processor
\r
4291 may be released, see 11).
\r
4295 9.1.4. Coroutine statement
\r
4296 ***************************
\r
4301 <coroutine statement>:
\r
4303 ------> detach ---------------------------------------------->
\r
4305 !-----> attach ----> ( ---> <object expression>--> ) -->!
\r
4307 CONTEXT and SEMANTICS.
\r
4308 ----------------------
\r
4310 By a chain of coroutine N with the head Ol we shall mean the DL chain of
\r
4311 objects O1, ..., Ol such that:
\r
4312 - for i=1, ..., l-1 the object Oi+1 is the dynamic father of Oi;
\r
4313 - Ol is the generated object of the coroutine N;
\r
4314 - Ol is non-terminated.
\r
4315 Thus the chain contains non-generated objects with the exception of the
\r
4316 head, which is generated but non-terminated.
\r
4317 The execution of a kill(X) statement where X points to the head Ol of the
\r
4318 coroutine chain results in a deallocation of the entire chain.
\r
4320 The chain may be in one of the following two states:
\r
4321 - detached - the execution of the statements contained in this
\r
4322 chain is suspended, the object O1 contains a distinguished
\r
4323 point, called the reactivation point of the chain;
\r
4324 - attached - a statement from the object O1 is currently
\r
4327 In the case of a sequential program exactly one chain is operational,
\r
4328 i.e., in the attached state. Note that a coroutine head may be the main
\r
4329 program. Coroutine control statements change the states of coroutine
\r
4330 chains. A reference to the coroutine chain W1 which has recently
\r
4331 transferred the control to the chain W is associated with chain W. Let us
\r
4332 denote this reference by CL (coroutine link). This link is then used by the
\r
4333 detach statement. Suppose that the object O (containing the occurrence of
\r
4334 the coroutine control statement) belongs to the chain W of the coroutine N
\r
4336 The statement attach(X) is a WFF if X is a well formed object expression
\r
4337 or the system variable main. The statement is defined if X points to the
\r
4338 head O1 of a coroutine chain W1. The execution of the statement results in
\r
4339 changing the state of W to a detached one and that of W1 to an attached
\r
4340 one. The statement determined by the reactivation point of the chain W1
\r
4341 starts its execution. The CL link to the chain W is associated with the
\r
4342 chain W1. If O=O1 then the statement is empty.
\r
4343 The statement detach is defined except the case where the CL link of
\r
4344 chain W is none. The execution of the statement results in detaching the
\r
4345 chain W and attaching the chain W1 determined by the corresponding CL link
\r
4346 associated with W. The statement following the detach statement is the
\r
4347 reactivation point of the chain W. The execution of the chain W1 is resumed
\r
4348 at its reactivation point.
\r
4352 9.2. Compound statements
\r
4353 *************************
\r
4355 Compound statements define case analysis (conditional and case statement)
\r
4356 and iteration (loop statements).
\r
4362 <compound statement):
\r
4364 ----------> <conditional statement> -------->
\r
4366 !-----> <case statement> ------->!
\r
4368 !-----> <loop statement> ------->!
\r
4373 9.2.1. Conditional statement
\r
4374 *****************************
\r
4381 <conditional statement>:
\r
4383 ---> if --> <boolean expression> --> then --> <statement list>
\r
4385 !---> <orif list> ------->! !
\r
4387 !---> <andif list> ------>! !
\r
4391 <-----------------------------------------------!
\r
4393 !------> else --> <statement list> --------> fi ---------->
\r
4403 ---- <boolean expression> ----------------->
\r
4405 !<------- or_if <----------!
\r
4410 ---- <boolean expression> ----------------->
\r
4412 !<------ and_if <----------!
\r
4415 CONTEXT and SEMANTICS.
\r
4416 ----------------------
\r
4419 For the execution of an if statement of the form:
\r
4421 if B1 or_if B2 ... or_if Bj
\r
4429 the boolean expressions B1, .., Bj are evaluated in succession until the
\r
4430 first one evaluates to true, then the sequence G of statements is executed.
\r
4431 If none of the boolean expressions evaluates to true, then the sequence H
\r
4432 is executed. The conditional statement with the "else" part omitted is
\r
4433 equivalent to the conditional statement with the empty statement following
\r
4434 the else symbol. If the "andif" list occurs instead of the "orif" list,
\r
4435 then the expressions B1, ..., Bj are evaluated in succession until the
\r
4436 first one evaluates to false; then the sequence H is executed. Otherwise
\r
4437 the sequence G is executed. When a boolean expression occurs instead of an
\r
4438 "orif" or "andif" list, then its value controls the execution of the
\r
4439 conditional statement in the standard manner.
\r
4443 9.2.2. Case statement
\r
4444 **********************
\r
4454 ! !-------------------->!
\r
4456 ! <---- <statement list> <--- : -----! !
\r
4458 !-> <arithmetic expression> ---> when ---> ---<integer>-------->! !
\r
4460 ! ! -> <constant> ->! ! !
\r
4462 ! <----- , -------------! !
\r
4464 !-> <character expression> ---> when ---><character constant>->:-! !
\r
4466 ! ! !-> <constant> ->! ! ! !
\r
4468 ! !<--------- , --------! ! !
\r
4470 !<------ <statement list> <----------! !
\r
4473 <------------------------------------------------------------!
\r
4476 !-> others ----> <statement list> ---------> esac ---->
\r
4480 CONTEXT and SEMANTICS.
\r
4481 ----------------------
\r
4492 is a WFF if E is an arithmetic or character expression and l1, ..., lk are
\r
4493 sequences of different constants. If the list H is empty, then the "others"
\r
4494 part can be omitted.
\r
4495 The case statement selects for execution a sequence Gi where the value of
\r
4496 E belongs to the sequence li. The choice others covers all values (possibly
\r
4497 none) not given in the previous choices. The choices in a case statement
\r
4498 must be mutually disjoint and if the "others" part is not present they must
\r
4499 exhaust all the possibile values of the expression E.
\r
4506 9.2.3. Iteration statement
\r
4507 ***************************
\r
4514 <iteration statement>:
\r
4517 -------> <loop statement> ---------------------------------------->
\r
4519 !---> <loop statement with condition> --------------------->!
\r
4521 !---> <loop statement with control variable> -------------->!
\r
4527 ---> do -----> <statement list> ----> od --->
\r
4530 <loop statement with condition>:
\r
4533 --> while --> <boolean expression> --> do --> <statement list>--> od -->
\r
4536 <loop statement with control variable>:
\r
4538 ---> for ---> <simple variable> -->:= --> <arithmetic expression> -->!
\r
4540 <------------------------------------------------------------------!
\r
4542 !--> step --> <arithmetic expression>----> to ----->!
\r
4546 <---------------------------------------------------!
\r
4548 !-> <arithmetic expression> -->do--> <statement list>--->od -->
\r
4552 CONTEXT and SEMANTICS.
\r
4553 ----------------------
\r
4555 Let us start from the semantics of loop and exit statements. The loop
\r
4562 causes the iteration of the sequence G until an exit statement is
\r
4564 Consider the occurrence of the exit statement exit ... exit(k-times)
\r
4565 where k >=1 . Let us denote this statement by H. Suppose that statement H
\r
4566 occurs in l (l>=0) nested iteration statements G1, ..., Gl, i.e., the
\r
4567 statement G2 is nested in G1, G3 in G2, etc. Let M be the smallest unit
\r
4568 enclosing that occurrence of H.
\r
4569 If k>l then the execution of H causes the termination of the unit body M
\r
4570 (jump to the final end). Otherwise the iteration statement Gk terminates,
\r
4571 and either the execution of the iteration statement Gk-1 is continued if
\r
4572 k<l or the execution of the outermost iteration statement G1 terminates if
\r
4574 The keyword repeat may occur just after the sequence of exit's. Then the
\r
4575 iteration statement Gk is continued (if k<=l), i.e., the control is
\r
4576 switched not outside but to the beginning of the loop without the execution
\r
4577 of the statements occurring after repeat. If the statement Gk is a loop
\r
4578 statement with the while condition, then the consequtive iteration starts
\r
4579 from the condition evaluation. If it is a for statement, then the
\r
4580 consequtive iteration starts with the change of the controlled variable
\r
4587 The goto statement is totally deleted from LOGLAN-82 (contrary to other
\r
4588 languages, like ADA where goto within a single unit is allowed). The
\r
4589 structured statements defined above were applied to many examples of known
\r
4590 algorithms. These exercises showed that the proposed structured statements
\r
4591 constitute a good balance point between a non structured goto-label
\r
4592 statement and a classical while statement (which often requires auxiliary
\r
4593 control boolean variables).
\r
4594 Notice that the above unit M body is considered to be "non-concatenated",
\r
4595 i.e., in the case of the jump to end symbol, this end is taken from the
\r
4596 body of M, not from the body of M concatenated with its prefix sequence. We
\r
4597 stress that the textual control statements do not lead outside one unit.
\r
4604 A loop statement with condition:
\r
4611 is equivalent to a loop statement of the form:
\r
4614 if not B then exit fi;
\r
4618 A loop statements with controlled variables are of the forms:
\r
4620 (*) for i:=A1 step A2 to A3 do G od
\r
4621 (**) for i:=A1 step A2 downto A3 do G od
\r
4623 The controlled variable i must be of discrete type. The statement (*) is
\r
4624 equivalent to the following sequence of statements:
\r
4626 Av1:=A1; Av2:=A2; Av3:=A3; i:=Av1;
\r
4633 The statement (**) is equivalent to the above sequence of statements with
\r
4634 the condition Av3>=i replaced by Av3<=i and the assignment i:=i+Av2
\r
4635 replaced by i:=i-Av2. The variables Av1, Av2, Av3 are fictitious variables
\r
4636 introduced only in order to define the semantics. The expression step A2
\r
4637 may be omitted if the value of A2 equals 1. The value of the controlled
\r
4638 variable i should not be modified inside the loop (however, the result of
\r
4639 such a modification would be well-defined). Moreover, its value is
\r
4640 determined when loop is terminated according to the introduced semantics.
\r
4648 (1) A palindrome is a word which is identical when written from left to
\r
4649 right and conversely. The given algorithm looks for the first occurrence of
\r
4650 a palindrome in a text and writes its length, (if found).
\r
4652 unit palindrome: procedure;
\r
4653 var i, j, k: integer,
\r
4654 text: array_of character;
\r
4657 new_array text dim (1:j);
\r
4665 while text(k)=text(i-k+1)
\r
4670 write ("found at i-th item");
\r
4675 write ("not found")
\r
4680 (2) A dictionary is a data structure S with the following operations:
\r
4682 member(x, S) - determines whether x is a member of S
\r
4683 insert(x, S) - replaces S by the union of S and (x)
\r
4684 delete(x, S) - replaces S by the difference of S and (x)
\r
4686 The elements of the set S are assumed to be of the same type T and to be
\r
4687 ordered by the relation less. A dictionary will be implemented by means of
\r
4688 binary search trees. The user has the access to the operations member,
\r
4689 insert, and delete and does not have to bother about the way of their
\r
4690 implementation. Below we propose how to accomplish these operations as
\r
4693 unit bst: class (type t; function less(x, y:t):boolean);
\r
4694 hidden root, e, i, d;
\r
4695 var root: node, member: e, insert: i, delete: d;
\r
4696 unit node: class (value: t);
\r
4700 unit e: coroutine; (*elem- output attribute*)
\r
4701 close trick, q, v;
\r
4702 var trick, elem: boolean, q, v: node, x:t;
\r
4705 do trick, elem:=false; (* loop for member *)
\r
4710 if less(x, q.value)
\r
4713 if less(q.value, x)
\r
4715 else elem:=true; exit
\r
4719 inner; (* elem=true iff x belongs to S *)
\r
4724 unit help: E coroutine;
\r
4725 taken trick, elem, q, v, x;
\r
4727 inner; (* trick=true iff x does not belong to S *)
\r
4728 if not trick then exit fi;
\r
4732 if less(x, v.value)
\r
4735 fi (* after insert or delete *)
\r
4736 fi (* attach new node q to its father v *)
\r
4741 unit i: help coroutine;
\r
4742 taken trick, elem, q, x;
\r
4745 if elem then exit fi;
\r
4746 q:=new node(x) (* insert is a dummy if x belongs to S *)
\r
4749 unit d: help coroutine;
\r
4751 hidden close w, u, s;
\r
4752 var w, u, s: node;
\r
4753 begin (* delete is a dummy if x does belong to S *)
\r
4754 if not elem then exit fi;
\r
4763 then u.l:=q.l; q:=u
\r
4766 if s.l=none then exit fi;
\r
4769 s.l.:=w.l; u.l:=s.r;
\r
4778 member:=new e; insert:=new i; delete:=new d;
\r
4780 kill(member); kill(insert); kill(delete)
\r
4783 pref bst(t, less) block
\r
4784 taken member, insert, delete;
\r
4791 if member.elem then ... fi;
\r
4803 10. Exception handling
\r
4804 #######################
\r
4807 This section defines the facilities for dealing with errors or other
\r
4808 exceptional situations that may arise during program execution. An
\r
4809 exception is an event that causes a suspention of normal program execution.
\r
4810 The occurrence of an exception is expressed by raising a signal. Executing
\r
4811 some actions in response to the arising of an exceptional situation, is
\r
4812 called signal handling.
\r
4814 Signal names are introduced by signal specifications. Signals can be
\r
4815 raised by raise statements, or alternatively, their raising is caused by an
\r
4816 occurrence of a run-time error. When an exception arises, the control can
\r
4817 be passed to a user-pointed handler associated with the raised signal. The
\r
4818 principles of determining a handler that responds to the raised signals are
\r
4819 presented in 10.3.
\r
4822 10.1 Signal specification
\r
4823 *************************
\r
4829 <signal specification>:
\r
4831 ----> signal ---> <signal name> ---> ( --> <formal par. list> --> ) -->; -->
\r
4833 ! !-------------------------------->!!
\r
4834 !<---------------------- , ---------------------------!
\r
4839 The signal specification defines signals which can appear in raise
\r
4840 statements and in signal handlers within the scope of the specification.
\r
4841 The identifiers of system signals, i.e., signals associated with run-time
\r
4842 errors, are not specified in the signal specification.
\r
4843 Signal identifiers are not accessible by remote access. They can occur,
\r
4844 however, in a hidden, close or taken list of a unit.
\r
4848 10.2 Signal handlers
\r
4849 ********************
\r
4851 The response to one or more signals is specified by a signal handler.
\r
4857 <handlers' declaration>:
\r
4861 !-----------> when ---> <signal name> --> : --> <statement list> --!
\r
4863 ! !<------ , -------! !
\r
4865 !--------<------------------------------------------------------!
\r
4867 !-----------> others ----> <statement list> --!
\r
4869 !----------------------------------------> end handlers
\r
4875 Handlers' declaration may appear at the end of the declaration part of a
\r
4876 unit. All identifiers visible in the unit and the signal formal parameters
\r
4877 may be used in the handler statements. A handler can handle the named
\r
4878 signals. A handler corresponding to the choice others handles all signals
\r
4879 not listed in the previously specified handlers, including those whose
\r
4880 identifiers are not visible within the unit.
\r
4882 Any statement (except inner) whose occurrence in a unit is legal may
\r
4883 occur in the handler.
\r
4888 The formal parameter lists of signals associated with the same handler
\r
4889 must be identical.
\r
4896 when emptytree: T:=new treelem; return;
\r
4897 others write(" signal not handled"); raise Error;
\r
4902 10.3. Signal raising
\r
4903 ********************
\r
4909 ----> raise ---> <signal name> --> ( --> <actual par. list> --> ) ----->
\r
4911 !----------------------------------->!
\r
4917 The signal name in the raise statement ought to be visible in the unit in
\r
4918 which the raise statement appears. The formal and actual parameter lists of
\r
4919 the signal must be compatible.
\r
4924 raise empty(exprstack);
\r
4925 raise end_of_file (input);
\r
4930 When a signal is raised, the normal process execution is suspended and
\r
4931 the control is passed to a signal handler. The actual parameters are
\r
4932 transmitted to the handler, as in the case of a procedure. However, the
\r
4933 crucial point of exception handling is the way in which such a handler is
\r
4934 searched for and activated. Below we present the principles of handler
\r
4937 Let us assume that signal f is raised in object Ok. This object and its
\r
4938 corresponding DL-chain may be illustrated as follows:
\r
4941 ------------ ------------ ------------
\r
4943 ! ! !handlers ! ! !
\r
4944 ! !<---...........<---!when f !<---........<---!raise f !
\r
4947 ------------ ------------ ------------
\r
4950 where O1 is the object of a coroutine or a process.
\r
4954 The objects in the DL-chain of Ok are successively checked whether they
\r
4955 contain a handler for signal f or a handler corresponding to the choice
\r
4956 others. The object Ok is checked first, next the object Ok-1 is checked and
\r
4957 so on. This search stops when the first object Oi containing the handler
\r
4958 for f or the handler for others is found. If such a handler is not found in
\r
4959 this DL-chain, then the system trap handler is executed and the process
\r
4961 For the situation presented in the figure, the handler from object Oi is
\r
4962 executed, provided that none of the objetcs Oi+1, ..., Ok contains a
\r
4963 handler for signal f or the handler for others.
\r
4965 In a concatenated object, i.e., in an object corresponding to a unit with
\r
4966 a non-empty prefix, the handlers declared in the prefixing unit are covered
\r
4967 by the handlers declared in the prefixed unit if they have the same
\r
4968 identifiers. Thus the signal raised during the execution of the prefix
\r
4969 statements may be handled by a handler declared in the prefixed unit. The
\r
4970 handler corresponding to the choice others responds to all the signals not
\r
4971 listed in the handlers declared in the units from the prefix sequence. The
\r
4972 handler for the choice others is taken from the innermost unit (with
\r
4973 respect to prefixing).
\r
4979 unit A: procedure;
\r
4985 unit B: procedure;
\r
4987 when f: .....; (* <----------- handler H1 *)
\r
4998 when f: .....; (* <----------- handler H2 *)
\r
5008 If signal f is raised in the block satement, hanlder H2 will be executed.
\r
5009 If signal f is raised in procedure B or in procedure A, handler H1 will be
\r
5019 when g: .....; (* <---------- handler G1 *)
\r
5030 when f: .....; (* <---------- handler F1 *)
\r
5031 when g: .....; (* <---------- hadller G2 *)
\r
5044 If signal f is raised in an object of class B, handler F1 will be
\r
5045 executed. If signal g is raised in an object of class B, handler G2 will be
\r
5046 executed even if the signal is raised in the statements of class A.
\r
5050 10.4. Handler execution
\r
5051 ***********************
\r
5053 A handler execution terminates if one of the special control statements
\r
5059 <handler termination>:
\r
5061 ------> return ----->!
\r
5063 --->!---> wind --------------->
\r
5065 !---> terminate ---->!
\r
5070 The statements wind and terminate may appear only within a handler
\r
5071 declaration. If none of them occurs in a handler statement list, the
\r
5072 statement terminate is assumed to be the last statement in such a list.
\r
5073 The execution of the statements wind and terminate causes an abnormal
\r
5074 termination of the corresponding objects from the DL-chain (see below). In
\r
5075 that case, the "last-will" statements are executed before the termination
\r
5082 <last-will statements>:
\r
5084 -----> last_will ----> : ---> <statement list> ----------->
\r
5089 Any unit body may be terminated with a sequence of statements labelled by
\r
5090 last_will. They are not executed during normal program execution. The
\r
5091 statement inner must not occur within the "last-will" statements.
\r
5100 Let us assume that a signal f raised in an object Ok is handled by a
\r
5101 handler H from an object Oi:
\r
5104 O1 Oi-1 Oi Oi+1 Ok
\r
5105 ----- ----- ----- ----- -----
\r
5106 ! ! <---...<---! !<---! !<----! !<---........<---! !
\r
5107 ----- DL ----- DL ----- DL ----- DL -----
\r
5111 ! ! H-------------------------------->!
\r
5114 The statement return in a handler has a similar effect to that of the
\r
5115 statement return in a procedure. The handler object is deallocated and the
\r
5116 control is passed to the statement just following the corresponding raise
\r
5118 The execution of the statement wind causes the termination and the
\r
5119 deallocation of the objects H, Ok, ..., Oi+1. Before the termination of
\r
5120 each of them, the "last-will" statements, if any, are executed. They
\r
5121 complete the object execution. In the prefixed object the "last-will"
\r
5122 statements of each prefix are successively executed, starting from the
\r
5123 innermost and ending on the outermost prefix. When the termination and
\r
5124 deallocation of these objects is completed, the control is passed to object
\r
5125 Oi, where the computation is continued in a normal way. Note that the wind
\r
5126 statement in the case of k=i is equivalent to return.
\r
5128 The statement terminate causes the termination and the deallocation of
\r
5129 the objects H, Ok, ..., Oi+1, Oi. They are completed as in the case of
\r
5130 wind, i.e., the "last-will" statements are executed as well. The control is
\r
5131 passed to Oi-1, if such an object exists. If Oi-1 does not exists, i.e., Oi
\r
5132 is the head of the DL-chain, then this head is terminated (cf. the
\r
5133 semantics of the end statement of coroutine and process).
\r
5139 If any control statement (raise, detach, attach, etc.) is executed within
\r
5140 the "last-will" statements and the control returns to the interrupted
\r
5141 object, the execution of the "last-will" statements as well as the
\r
5142 termination of the remaining objects in the DL-chain will be continued.
\r
5149 10.5. System signals
\r
5150 ********************
\r
5152 Some of the signals, called system signals, are predefined in the
\r
5153 language. They are raised automatically when a run-time error or another
\r
5154 exceptional system situation appears.
\r
5155 System signals have no parameters. They are not declared in the signal
\r
5156 specification, but the user may declare handlers for them. The execution of
\r
5157 the statement return is not allowed in the handler responding to such a
\r
5158 signal (note that sometimes the statement wind is equivallent to return).
\r
5160 The following signals are predefined in the language:
\r
5163 A remote access to a non-existing object or an error in the
\r
5164 expression ...x qua A (x does not exist or the type of the object
\r
5165 pointed to by x is not prefixed by the type A).
\r
5167 There is no free space for the allocation of a new object.
\r
5169 A numerical error, such as for instance integer overflow,
\r
5170 floating-point overflow, division by zero etc.
\r
5172 Any kind of the LOGLAN Running System error (except access error)
\r
5173 like e.g., an attempt to pass the control in a way inconsistent
\r
5174 with the LOGLAN-82 rules, an attempt to kill an active object, etc.
\r
5176 The value of an index expression exceeds the range of array indices
\r
5177 or the array bounds are incorrect.
\r
5179 Any kind of system error like e.g., input-output error, parity
\r
5182 Some other errors may also be introduced as system errors but are not
\r
5183 predefined in the language.
\r
5191 Let us consider a snap-shot of a program's computation. This snap-shot is
\r
5192 called a configuration. Up till now a configuration has consisted of a
\r
5193 finite number of objects creating a number of coroutine chains. The main
\r
5194 program is the only chain with the head of process type.
\r
5195 Moreover, exactly one object has been considered "active" - i.e., its
\r
5196 statements have been executed by a physical processor. By a physical
\r
5197 processor we mean here an actual processor as well as the portion of time
\r
5198 of a central unit.
\r
5199 A configuration with many active objects illustrates the computation of a
\r
5200 program with parallel statements. Concurrent computation to some extent
\r
5201 generalizes coroutines, i.e., a configuration may contain many coroutine
\r
5202 chains with heads of coroutine type and many process chains with heads of
\r
5204 The fundamental notion is that of a process. A process may be treated as
\r
5205 a sequential program - only one statement of a process is being executed at
\r
5206 a time. A parallel program consists of a number of processes. In LOGLAN-82
\r
5207 a process is a system type. A process object may be generated by means of
\r
5208 the new statement. The generated process object is suspended with the
\r
5209 execution of the return statement. This process may be resumed by means of
\r
5210 the resume statement. After resumption, process statements are executed by
\r
5211 a new processor, concurrently with the other active processes. During its
\r
5212 computations, the process may suspend its actions (but not the actions of
\r
5213 other processes) by means of the stop statement, then it may be resumed
\r
5215 Observe that the attach and detach statements switch the processors from
\r
5216 one object to another, while the resume and stop statements acquire and
\r
5217 release a processor respectively. Resumption of a coroutine chain is
\r
5218 connected with the control transfer from the active coroutine chain.
\r
5219 Resumption of a process chain acquires new processor for that chain.
\r
5220 Similarly, suspension of a coroutine chain gives the control back to
\r
5221 another chain, while suspension of a process chain releases the processor.
\r
5222 Note that a process object is more complex than a coroutine object. So
\r
5223 coroutine operations are more efficient with respect to time and space.
\r
5224 Therefore the user should use processes only when they are indispensable.
\r
5228 In order to deal with communication among processes (e.g., by messages)
\r
5229 as well as their competition in acquiring a resource (such as a shared
\r
5230 variable) one should have the ability to define some synchronizing
\r
5231 operations. Those operations arise from the following constrains:
\r
5233 - timing, i.e., mutual exclusion of actions;
\r
5234 - scheduling i.e., stating which of the waiting processes is to be resumed
\r
5238 For this purpose some synchronizing facilities are provided. One may think
\r
5239 of many such facilities, from low level ones, such as Dijkstra's semaphores
\r
5240 to high level ones, such as Hoare's monitors. The decision which one of the
\r
5241 synchronization methods should be chosen and incorporated into the language
\r
5242 is weighty. The primitive tools are difficult to use, but they are
\r
5243 efficient. The high-level constructs are safer, but they often limit
\r
5244 parallelism (because of the strong synchronizing constraints).
\r
5245 The synchronizing facilities introduced in LOGLAN-82 are elementary (low
\r
5246 level). Therefore they are implemented efficiently in the kernel of the
\r
5247 operating system. However, the high-level facilities e.g., monitors (see
\r
5248 [5], [6]), can be defined with their help. The user can, for a concrete
\r
5249 synchronization problem, make a choice between the pre-defined facilities
\r
5250 or program other ones. The low-level facilities are hidden when the high
\r
5251 level facilities are used. Thus, the properties of the latter cannot be
\r
5253 In any case, speaking about a parallel execution of processes, we mean
\r
5254 that they are executed really in parallel, independently of the relations
\r
5255 between a number of "ready" processes and a number of available processors
\r
5256 (the details of processor management are hidden in an operating system).
\r
5264 <parallel statement>:
\r
5266 ------> <process state transition> ----------------->
\r
5268 !--> <primitive synchronizing statement> ----->!
\r
5274 11.1. Transition state statement
\r
5275 *********************************
\r
5278 Each process can be in one of five states: active, suspended, locked,
\r
5279 awaiting, terminated. The transitions among these states are described by
\r
5280 the following graph (where X denotes the reference to the given process and
\r
5287 **************** X:=new
\r
5290 end of son! ! wait !
\r
5293 ************* <------ ************* ------------> ***************
\r
5294 * locked * * active * stop * suspended *
\r
5295 ************* -------> ************* <----------- ***************
\r
5296 unlock(Z) ! resume(X)
\r
5301 ******************
\r
5303 ******************
\r
5307 We shall now present the syntax and semantics of object expressions and
\r
5308 statements connected with the transitions of the process states:
\r
5314 <process state transition>:
\r
5316 !---> <process suspension> ------------>
\r
5318 !---> <process resumption> ------->!
\r
5320 !------> <process waiting> ------->!
\r
5326 <process suspension>:
\r
5328 -----> stop --------> ( ---> <variable> ----> ) ------->
\r
5330 !--------------------------------->!
\r
5333 <process resumption>:
\r
5335 ----> resume -----> ( ---> <object expression> ---> ) ------>
\r
5338 <process waiting>:
\r
5340 -----> wait -------------------------------------------->
\r
5347 From now on we shall consider the occurrence of the transition state
\r
5348 statement in the object O which belongs to the process R (i.e., there
\r
5349 exists a DL chain connecting the object O with the object O(R) of the
\r
5350 process R). If the process O(P) is generated in the process O(R), then the
\r
5351 process object O(R) is called the father of the process object O(P), and
\r
5352 O(P) is called a son of O(R).
\r
5353 The execution of the statement resume(X), where X points to the process
\r
5354 object, causes resumption of that process, providing that it was previously
\r
5355 suspended. Otherwise a run-time error occurs.
\r
5359 The statement stop suspends the process R. The statement stop(Z) is a
\r
5360 WFF if Z is a variable of type semaphore. The execution of this statement
\r
5361 suspends the given process and simultaneously opens semaphore Z. The
\r
5362 indivisibility of those actions means that no other process can refer to
\r
5363 the variable Z in the meantime (the statement stop(Z) is useful in the
\r
5364 synchronization of processes, see 11.2.).
\r
5366 A process may wait for the termination of its son with the help of the
\r
5367 wait expression. The execution of the expression wait in an object
\r
5368 belonging to the process R causes waiting for the termination of any son of
\r
5369 the process R. When the first such son terminates its actions, the
\r
5370 reference to that son is returned as the value of wait and process R
\r
5371 continues its computation. If the process S does not embrace a
\r
5372 non-terminated son, the value of the expression wait is none. Thus the
\r
5373 execution of the statement
\r
5375 while wait =/= none do od
\r
5377 causes waiting for the termination of all the sons of the given process.
\r
5379 The execution of the deallocation statement kill(X) where X points to a
\r
5380 process depends on its state. When that process is suspended or terminated,
\r
5381 then the execution of this statement is the same as in the case of a
\r
5382 coroutine. Otherwise it results in a run-time error.
\r
5385 Relations between parallel and coroutine computations.
\r
5387 LOGLAN-82's coroutine computations can easily be simulated by means of
\r
5388 parallel computations. Coroutine computations are provided in LOGLAN-82,
\r
5389 nevertheless, in order to deal with the case of interleaving processes.
\r
5390 With coroutines instead of processes, one can avoid unnecessary memory
\r
5391 overloading by data structures inherited for processes and, moreover,
\r
5392 unnecessary scheduler activations.
\r
5393 Each process is also a coroutine, and so a process may also be subject to
\r
5394 the coroutine operations detach and attach. Therefore, the description of
\r
5395 possible state transitions provided above should be extended to transitions
\r
5396 caused by coroutine operations.
\r
5397 The execution of attach(Y) in the active process X results in the control
\r
5398 transfer from process X to process Y, i.e., if Y is not suspended then the
\r
5399 statement is illegal, otherwise process X becomes suspended and process Y
\r
5401 The execution of the detach statement in the active process X has the
\r
5402 effect as the execution of attach(Y), where Y is the coroutine (process)
\r
5403 recently resumed (by means of attach statement) by process X.
\r
5407 11.2. Primitive synchronizing statement
\r
5408 ****************************************
\r
5414 <primitive synchronizing statement>:
\r
5416 ----> lock ----> ( ---> <variable> ---> ) ---->
\r
5421 The expression test-and-set (ts) is a boolean expression (see 8.4.).
\r
5426 -----> ts ---> (--><variable> ---> ) --->
\r
5431 The variable Z occurring in the expression ts(Z) has to be of type
\r
5432 semaphore. Evaluation of the expression consists in indivisible actions: Z
\r
5433 is closed and the returned value is true iff Z was open.
\r
5434 The statement lock(Z) is a WFF provided Z is a variable of type
\r
5435 semaphore. If Z is closed then the process which executes this statement is
\r
5436 suspended until Z becomes open. If Z is open then exactly one process of
\r
5437 those waiting for this event (having executed the lock instruction) will be
\r
5438 able to perform its actions. The others remain suspended as long as Z
\r
5439 becomes open again. Then exactly one process is allowed to proceed and Z
\r
5441 The statement lock(Z) guards the entry into a critical region, i.e., a
\r
5442 sequence of statements, which are to be executed by only one process . The
\r
5443 entrance into a critical region may be of the form
\r
5447 as well, but it would cause busy waiting of processes awaiting for the
\r
5448 entrance. The statement lock is implemented in the operating system kernel
\r
5449 and its execution does not engage the processors by delayed processes.
\r
5451 The exit from a critical region is offered by one of the following two
\r
5452 statements: stop(Z) or unlock(Z). The former statement is described in
\r
5453 11.1. The unlock statement is a WFF provided Z is a variable of type
\r
5454 semaphore. The execution of this statement brings about the following
\r
5455 indivisible actions: Z becomes open, and if there are processes waiting for
\r
5456 entrance, then exactly one of the waiting processes enters the region. The
\r
5457 scheduling of the waiting processes is assumed to be fair.
\r
5459 Thus a critical region may be written as follows:
\r
5463 ............ or ............
\r
5464 unlock(Z) stop (Z)
\r
5472 Suppose that the following statements occur in two processes executed in
\r
5475 process P: process Q:
\r
5476 lock (sem); lock (sem);
\r
5477 x:=(x+4)*x; x:=-3;
\r
5478 unlock(sem) unlock(sem)
\r
5480 and the initial value of the variable x is equal to 0. The execution of the
\r
5481 statement x:=(x+4)*x will not be interleaved by the execution of the
\r
5482 statement x:=-3, irrespectively of the succession of the arrival of
\r
5483 processes P and Q at their regions. Thus, these statements will be executed
\r
5484 in sequence and, independently of the succession, the final value of the
\r
5485 variable x after executing both those statements is equal to -3.
\r
5486 If the given statements did not occur in the critical regions, their
\r
5487 concurrent execution might be the following: compute x+4 - (yielding 4),
\r
5488 assign x:=-3, compute x*(x+4) - (yielding -12) and assign this value to x.
\r
5489 The presented critical regions make timing possible. For the description
\r
5490 of scheduling one should use more complex tools, presented in the next
\r
5496 Consider an algorithm which performs the copying of records from the
\r
5497 input queue to the output queue (comp. [5]). The algorithm gets the first
\r
5498 record from the input queue and stores it in the input buffer, next copies
\r
5499 the input buffer into the output buffer, and finally puts the output buffer
\r
5500 to the output queue and at the same time gets the next record from the
\r
5501 input queue, as in the following diagram:
\r
5521 In order to program a parallel execution of get and put operations one
\r
5522 can use the cobegin-coend program connectives. A particular case of these
\r
5523 connectives is implemented in the copying procedure given below. We assume
\r
5524 that in the environment of this procedure the type T and the attributes of
\r
5525 class queue are visible.
\r
5529 unit copying: procedure (input_queue, output_queue: head);
\r
5530 var input_buffer, output_buffer:T, completed:boolean, sem:semaphore,
\r
5531 counter:integer, getr:get_type, putr:put_type;
\r
5532 unit cobegin: procedure;
\r
5533 (*resumes the processes putr and getr, suspends the calling process*)
\r
5540 unit coend: procedure;
\r
5541 (*suspends the calling process, if both processes
\r
5542 are suspended then the main program is resumed*)
\r
5549 counter:=0; resume(main)
\r
5554 unit get_type: process;
\r
5558 if empty(input_queue)
\r
5559 then completed:=true
\r
5560 else (*get next record*)
\r
5561 input_buffer := out(input_queue)
\r
5567 unit put_type: process;
\r
5571 call output_buffer.into(output_queue);
\r
5577 if not empty(input_queue)
\r
5579 input_buffer:=out(input_queue);
\r
5580 getr:=new get_type; putr:=new put_type;
\r
5582 output_buffer:=copy(input_buffer);
\r
5584 if completed then exit fi
\r
5586 kill(getr); kill(putr)
\r
5592 11.3. Monitors (compound synchronization facilities)
\r
5593 *****************************************************
\r
5596 In this section we shall describe Hoare's monitors ([6]). A monitor is a
\r
5597 data structure shared by many processes and a set of procedures operating
\r
5598 on this structure. Access to the shared monitor data is possible only via
\r
5599 these procedures, and so their bodies constitute critical regions.
\r
5600 Let us present an example of a class that realizes Hoare's monitors.
\r
5601 Non-conflict access to the monitor data is realized by the so-called entry
\r
5602 procedures. An entry procedure has a prefix entry which guarantees that
\r
5603 only one such procedure may enter the monitor.
\r
5604 In order to permit scheduling of processes that have entered the monitor,
\r
5605 two specialized procedures operating on the inner monitor queues are
\r
5608 delay(Q) -stops the execution of the process and puts it
\r
5609 into a queue Q, the entry to the monitor is free,
\r
5610 continue(Q) -resumes the execution of the first process from a
\r
5611 queue Q (if Q is non-empty, otherwise the entry to
\r
5612 the monitor is free).
\r
5614 As can easily be seen, correct use of these constructs is achieved when
\r
5615 continue is called as the last statement of an entry procedure.
\r
5617 The declaration of the class Monitor is as follows:
\r
5619 unit Monitor : queue class;
\r
5620 hidden sem, queue;
\r
5621 var sem:semaphore;
\r
5623 unit entry: class; (* all entry procedures must have prefix entry *)
\r
5626 unit delay: procedure(Q:queue);
\r
5628 call Q.into(this process);
\r
5631 unit continue:procedure(Q:queue);
\r
5632 (* continue can be called as the last statement of an entry procedure *)
\r
5640 begin (* beginning of the prefix entry *)
\r
5641 lock(sem); (* entry to the critical region *)
\r
5655 A simple mail-box system with a circular buffer may be defined as the
\r
5656 following class prefixed by a Monitor:
\r
5658 unit Mailbox:Monitor class(type T; size: integer);
\r
5659 var pool: arrayof T, count, in_index, out_index: integer;
\r
5660 var readers_queue, writers_queue:queue;
\r
5661 unit writer:entry procedure (r:T);
\r
5663 if count=size then call delay(writers_queue) fi;
\r
5664 in_index:=in_index mod size +1; count:=count+1;
\r
5665 pool(in_index):=r; call continue(readers_queue)
\r
5667 unit reader:entry procedure (output r: T);
\r
5669 if count=0 then call delay(readers_queue) fi;
\r
5670 out_index:=out_index mod size +1; count:=count-1;
\r
5671 r:=pool(out_index); call continue(writers_queue)
\r
5674 new_array pool dim (1:size);
\r
5675 redears_queue:=new queue; writers_queue:=new queue;
\r
5680 Let W be a non-singular k to k matrix such that the norm of W is less than
\r
5681 1. In order to solve the system of linear equations
\r
5685 one can use the Jacobi iteration method, i.e., for a given approximation Y
\r
5686 of a solution, the next approximation will be of the form:
\r
5688 x(i)= -(W(i, 1)*y(1)+...+W(i, i-1)*y(i-1)+W(i, i+1)*y(i+1)+...+W(i, k)*y(k))+B(i)
\r
5690 (without loss of generality one can assume that W(i, i)=1.)
\r
5692 We shall use k parallel processes to compute the corresponding components
\r
5693 of the vector x. When the computation of all the components is completed,
\r
5694 the next approximation starts. Suppose that vector B is included in the
\r
5695 array W, i.e., it is the last column of W. In general, array W has many
\r
5696 zeros, and so instead of this array the user delivers the functions
\r
5697 computing the values
\r
5699 -(W(i, 1)*y(1)+...+W(i, i-1)*y(i-1)+W(i, i+1)*y(i+1)+...+W(i, k)*y(k))+W(i, k+1)
\r
5701 for the given vector y.
\r
5705 unit Jacobi : procedure(k:integer;eps:real;inout x:array_of real;
\r
5706 function W(i:integer; y:array_of real):real);
\r
5707 (* eps-accuracy, the starting point of the iteration should be
\r
5708 the actual parameter corresponding to x, the final value of x
\r
5709 will be equal to the solution found *)
\r
5711 unit jac_unit :Monitor class;
\r
5713 var dist:real, q:queue;
\r
5715 unit puti: entry procedure(i:integer);
\r
5716 taken delay, continue;
\r
5718 dist:=dist+abs(x(i)-y(i));
\r
5719 (*y-new iteration, x-old one*)
\r
5720 if q.cardinal<k-1 (*q.cardinal<k always*)
\r
5721 then (*wait for others*)
\r
5723 else (*test stop condition*)
\r
5729 dist:=0; call continue(q)
\r
5738 unit jac: process(i:integer);
\r
5740 if i=1 then lock(done) fi;
\r
5744 call jac_mon.puti(i);
\r
5748 var y, z:array_of real, jac_mon:jac_unit, j:integer, done: semaphore;
\r
5749 var jacob: array_of jac;
\r
5752 new_array y dim(1:k); new_array jacob dim(1:k);
\r
5753 jac_mon:=new jac_unit;
\r
5755 jacob(j):= new jac(j); resume(jacob(j))
\r
5758 for j:=1 to k do kill(jacob(j)) od;
\r
5759 kill(y); kill(jacob); kill(jac_mon)
\r
5765 12. Separate compilation of units
\r
5766 #################################
\r
5769 Prefixing is a very convenient way of designing large programs and systems.
\r
5770 These are constructed by linking together individual units and by using
\r
5771 prefixes as languages in which the programs are written. There are two
\r
5772 distinct purposes for compiling modules:
\r
5774 -producing an object module, linking it with some units stored in
\r
5775 libraries and then executing it
\r
5776 -producing a library item which in turn may be connected with other
\r
5781 Therefore LOGLAN-82 distnguishes two kinds of compilation units:
\r
5783 -binary items ready to be executed, and
\r
5787 By an item we mean the basic unit of compilation, i.e., the smallest and
\r
5788 self-contained class, coroutine, process, function or procedure. It defines
\r
5789 also the minimum interface, i.e., units which have to be accessible at run
\r
5790 time. Most of this section deals with how separately compiled units are put
\r
5791 together to build large systems.
\r
5792 Because of checking many context-sensitive conditions, LOGLAN-82 requires
\r
5793 access to system and user libraries; therefore the language provides tools
\r
5794 for processing them. The form of a library depends upon a given
\r
5795 implementation. However, the library has to store some necessary
\r
5796 information about the interface of a module, its source (or slightly
\r
5797 preprocessed) code and its object code. Each library posesses its own
\r
5798 identifier, built with respect to ordinary LOGLAN-82 rules. Any library
\r
5799 item is identified by its own identifier and the name of the library where
\r
5800 it is stored. A unit identifier must be unique within the library.
\r
5804 Library items may be used by another module in two main ways:
\r
5806 -as if they were declared within the module, or
\r
5807 -as if they were only accessible as non-local attributes from the
\r
5808 SL-chain of the module.
\r
5809 The first manner we shall call linking a library item, the other forms the
\r
5810 interface needed by the module.
\r
5817 Let M be an already compiled item stored in a library. And let N be an
\r
5818 item being compiled.
\r
5819 Linking means that the program tree of N is the following:
\r
5825 O O <- linking point of M
\r
5829 ! O <- M - item from the library
\r
5833 If the item N specifies M in its interface, it is expected that the
\r
5834 module which links N is of the form:
\r
5839 O <- linking point of M
\r
5849 O O <- linking point of N
\r
5858 Indeed, in n's SL-chain-to-come the module N will also be linked.
\r
5861 The SL-chain-to-come of an item being compiled will be called the
\r
5862 environment of the linking point of the item.
\r
5866 12.1. Library items
\r
5867 *******************
\r
5870 A library item consists of the interface specification and the body. The
\r
5871 interface is a connector between separate units: it allows us to code in
\r
5872 the item the access parts of other units and to use other units as prefixes
\r
5874 The interface defines three kinds of units needed in order to execute the
\r
5876 -externals - these are already compiled units stored in libraries. They
\r
5877 are expected to be visible in the environment of the linking point,
\r
5878 -languages- these are also already compiled units stored in libraries.
\r
5879 They must prefix some module in the SL-chain-to-come,
\r
5880 -sl_virtuals - functions and procedures which will use the item being
\r
5881 compiled and its environment whatever links the item. They are not known
\r
5882 during the compilation of the item.
\r
5888 <compilation of a library item>:
\r
5890 --------->library item -->into <library identifier>-->;--->!
\r
5892 !--------------------------->-! !
\r
5894 <-----------------------------------------------!
\r
5897 !------> <interface specification> --->!
\r
5899 ! <------------------------------------!
\r
5901 !--> compile ---> <unit declaration> ---------------->
\r
5907 The item is compiled and then stored in a given library. If in the library
\r
5908 there is already a module of the same name, it is replaced by the one being
\r
5910 The default library identifier is the userlib.
\r
5915 library item into mathlib;
\r
5917 unit sin : function (input x: real) : real;
\r
5931 <interface specification>:
\r
5933 ---------->languages--> <language specification> --> ; ----->!
\r
5935 ! !<----------- , ------------! !
\r
5937 ! <---------------------------------------------------!
\r
5939 !----> externals --> <external specification> --> ; ->!
\r
5941 ! !<----------- , ------------! !
\r
5943 ! <---------------------------------------------------!
\r
5945 !----> sl_virtuals --> <sl_virtual specif. > --> ; -->!
\r
5947 ! !<---------- , -----------! !
\r
5949 ! <---------------------------------------------------!
\r
5951 !------------------->
\r
5954 <language specification>:
\r
5956 -----> <lib. item identifier> -----> from <library ident.> ------>
\r
5958 !<-------------- , -----------! !------------------------> !
\r
5961 <external specification>:
\r
5963 ------> unit <lib. item identifier> : ----> class ------------>!
\r
5965 !-> coroutine -->! !
\r
5967 !-> process ---->! !
\r
5969 !-> function --->! !
\r
5971 !-> procedure -->! !
\r
5973 ! <--------------------------------------------------------!
\r
5975 !---> from <library identifier> -------------------------> !
\r
5979 The default library identifier is the userlib.
\r
5983 <sl_virtual specification>:
\r
5985 -> unit <identifier> : -> function -> <form. par. simp. list> ->!
\r
5987 ! !<-------------------------------!
\r
5989 ! !--> : <type identifier> -------->!
\r
5991 !--> <form. par. simp. list> ------------>!
\r
5999 The interface defines a minimum environment of the point at which the item
\r
6000 being compiled is to be linked. It is used to code the item and also to
\r
6001 check its static properties. Therefore, changing externals or languages in
\r
6002 the library, the user has to recompile also units depending on them.
\r
6003 Identifiers of externals may be used in sl_virtual specification to
\r
6004 define types of parameters and by the compiled unit as prefixes, types of
\r
6005 data and so on. Interface specification is not redundant, i.e., if an
\r
6006 external or language uses some other library items in its own interface,
\r
6007 they do not have to be specified again. However, only identifiers of the
\r
6008 specified units are accessible in the item being compiled.
\r
6013 library item into datalib;
\r
6015 unit heap : class....
\r
6019 library item into datalib;
\r
6021 unit heap: class from datalib;
\r
6023 unit priority_queue: heap class ...
\r
6025 end priority_queue;
\r
6027 library item into proglib;
\r
6029 unit priority_queue: class from datalib;
\r
6031 unit prog1: class;
\r
6032 var x: priority_queue;
\r
6036 Within the body of prog1 we can use the identifier of the priority_queue.
\r
6037 Class heap will be automatically connected, we are not allowed, however, to
\r
6038 use the identifier of heap. To make it possible we should define another
\r
6043 library item into proglib;
\r
6045 unit priority_queue: class from datalib;
\r
6046 unit heap: class from datalib;
\r
6048 unit prog2: class...
\r
6049 var x: priority_queue;
\r
6061 library item into datalib;
\r
6063 unit heap: class from datalib;
\r
6070 library item into proglib;
\r
6072 unit priority_queue: class from datalib;
\r
6073 unit test: class from datalib;
\r
6075 unit prog3: class;
\r
6076 var p: priority_queue, e: test;
\r
6083 In this interface heap means the same class for both the priority_queue
\r
6088 12.1.2. Using languages
\r
6089 ***********************
\r
6091 Languages are classes (coroutines, processes) already compiled. They are
\r
6092 expected to prefix modules in the SL-chain of the point of linking the item
\r
6093 being compiled. Their attributes may be used within the body of the
\r
6094 compiled item by means of the construction:
\r
6095 this <language identifier>.<attribute>
\r
6096 If it does not lead to any confusion, the phrase
\r
6097 this <language identifier>.
\r
6098 may be omitted. The rules of accessing attributes in the case of regular
\r
6099 units are also valid in the case of languages. A language may also be used
\r
6100 like any of the specified externals.
\r
6105 library item into syslib;
\r
6111 library item into syslib;
\r
6113 unit basicio: class;
\r
6118 languages math, basicio from syslib;
\r
6120 unit prog: class...
\r
6122 this math.sin (* or simply sin *)
\r
6123 this basicio.writereal (*or simply writereal *)
\r
6126 A correct use of the unit prog may be of the following form:
\r
6130 unit math: class from syslib,
\r
6131 unit basicio: class from syslib;
\r
6133 unit user: class;...
\r
6137 external unit prog from userlib
\r
6138 (* this is linking prog- see 12.2 *)
\r
6144 12.1.3. Using externals
\r
6145 ***********************
\r
6148 External items are expected to be linked by the environment of the linking
\r
6149 point of the item being compiled. They may be used like units which are
\r
6150 declared and visible in the environment of a regular object. Some simple
\r
6151 examples have been given in 12.1.1. Some others are given in 12.2.
\r
6155 12.1.4. Using sl_virtuals
\r
6156 *************************
\r
6159 The main purpose of sl_virtuals is to permit communication between the
\r
6160 compiled item and the modules which will use it. Communication may depend
\r
6161 upon the modules and there may be many fairly distinct of them. Sl_virtuals
\r
6162 and the modules are not previously compiled, i.e., they are not other
\r
6163 library items. Sl_virtuals are very similar to formal parameters or
\r
6164 external subroutines in FORTRAN.
\r
6169 This is an example of a procedure which sorts real numbers stored in any
\r
6170 structure with operations put_real and get_real.
\r
6172 library item into sortlib;
\r
6174 unit empty : function : boolean,
\r
6175 unit get_real : function : real,
\r
6176 unit put_real : procedure (input X : real),
\r
6177 unit clear : procedure;
\r
6179 unit sqsetort : procedure;
\r
6182 (*reading numbers*)
\r
6190 (*writing numbers*)
\r
6202 12.2. Linking library items
\r
6203 ***************************
\r
6206 Declarations within a module may include specification of a library item to
\r
6207 be linked at that point.
\r
6213 <linked item specification>:
\r
6215 ----------> external <external specification> ---------->
\r
6221 The object code of the linked item is added to the object code of the item
\r
6222 being compiled. Adding the same item a few times we create some unrelated
\r
6223 copies of the item as if the same source code occurred many times in
\r
6227 12.2.1.Connecting the interface
\r
6228 *******************************
\r
6231 Languages and sl_virtuals.
\r
6232 --------------------------
\r
6234 Languages and sl_virtuals specified by the linked item are looked for in
\r
6235 the environment of the linking point. If they are not found there, they
\r
6236 must be explicitly specified in the interface of the item being compiled.
\r
6241 library item into lib;
\r
6247 library item into lib;
\r
6253 library item into lib;
\r
6254 languages M, N from lib;
\r
6262 library item into lib;
\r
6263 languages M from lib;
\r
6268 external unit N : class from lib;
\r
6273 external unit P : class from lib;
\r
6277 Sl_virtual specification must be compatible in terms of the usual LOGLAN-82
\r
6278 rules with the actual version or with the specification in the interface of
\r
6279 the item being compiled.
\r
6284 The externals specified in the added item are taken from the SL-chain of
\r
6285 the linking point or from the interface of the item being compiled. If they
\r
6286 do not occur there, they are linked together with the specified linked item
\r
6287 at the same point.
\r
6292 library item into lib;
\r
6298 library item into lib;
\r
6300 unit M : class from lib;
\r
6307 library item into lib;
\r
6309 unit M : class from lib;
\r
6312 external unit N : class from lib;
\r
6316 The actual version of the module M used by the module N is taken from the
\r
6317 interface of the module p. The SL-link of M is not known.
\r
6322 library item into lib;
\r
6326 external unit M : class from lib;
\r
6330 external unit N : class from lib;
\r
6333 The module M used by the module N comes from P where it is linked. The
\r
6334 SL-link of M is P.
\r
6335 Notice that if the program tree is the following:
\r
6347 N1 - copy of N-> O ! ! O <- N2 - copy of N
\r
6351 Then the attributes X in both copies are compatible, i.e., they are of the
\r
6356 library item into lib;
\r
6360 external unit N : class from lib;
\r
6364 external unit N : class from lib;
\r
6370 In this case two copies of N are formed. Because there occurs no copy of M
\r
6371 in the SL-chain or in the interface of P, two copies of M are also added.
\r
6372 The attributes X in the copies of N are of different types and are not
\r
6373 compatible. The copies of M are "own" copies for each N.
\r
6377 12.3. Binary items
\r
6378 ******************
\r
6381 A binary item consists of a very simple interface specification and the
\r
6382 body. The interface defines languages in which the program is written. A
\r
6383 binary compiled program is embedded in a number of blocks prefixed by these
\r
6384 languages. There is also a block containing definitions of linked library
\r
6386 Compilation of a binary item results in an object code ready for
\r
6394 <compilation of a binary item>:
\r
6396 -----> binary item ---> into <library identifier> ---> ; ------>!
\r
6398 !---------------------------->! !
\r
6400 !<------------------------------------------------------------!
\r
6402 !-----> languages ---> <language specification> --> ; --->!
\r
6404 ! !<------------ , ------------! !
\r
6406 ! <-------------------------------------------------------!
\r
6408 !------> externals ---> <external specification> --> ; -->!
\r
6410 ! !<------------- , ------------! !
\r
6412 ! <-------------------------------------------------------!
\r
6414 !---> compile <declaration of a program unit> ----------------->
\r
6417 The rules of using languages and externals are the same as for library
\r
6419 The default library identifier is bin.
\r
6423 12.4. Processing libraries
\r
6424 **************************
\r
6427 12.4.1. Recompilation
\r
6428 *********************
\r
6431 LOGLAN-82 guarantees uniqueness for types and units. The compiler
\r
6432 associates a "time stamp" (time of definition and compilation) with each
\r
6433 compiled unit. Compiling a module twice (even if no changes are made in its
\r
6434 source code) makes all units defined in the module different
\r
6435 (non-equivalent). Therefore after some changes in the library we should
\r
6436 recompile all modules connecting the changed items.
\r
6437 For example, consider the case where defs1 is used by defs2, and defs2 is
\r
6438 linked with the user. Suppose that defs1 is recompiled for some reason,
\r
6439 then defs2 is recompiled, too. Then the user should also be recompiled,
\r
6440 because recompiling defs2 invalidated the version of the user.
\r
6442 Compilations and recompilations must occur in a specific order.
\r
6443 To recompile a module storedin the library, LOGLAN-82 commands the
\r
6447 --> recompile --> <lib. item identifier> --> from <library ident.> -->
\r
6449 !<------------ , ----------!
\r
6451 It is suggested that the LOGLAN-82 compiler makes the necessary
\r
6452 recompilations automatically.
\r
6456 12.4.2. Insertions and deletions
\r
6457 ********************************
\r
6460 To insert an item into a library the programmer writes only the source code
\r
6461 of the item. It is a code between
\r
6465 library binary item into <library identifier>;
\r
6470 This code results in the insertion of the module into a given library. If
\r
6471 in the given library there already exists a module of the same name, the
\r
6472 new one replaces the old one.
\r
6474 Deletions are made by using the following syntax:
\r
6477 --> delete ---> <lib. item identifier> ---> from <library ident.> ---->
\r
6479 !<------------ , -----------!
\r
6481 A linked item may be deleted from the library. However, the linking module
\r
6482 cannot be recompiled after that.
\r
6486 13. File processing
\r
6487 ####################
\r
6490 13.1. External and internal files
\r
6491 *********************************
\r
6493 External files are named after character strings and denote peripheral
\r
6494 devices or data sets. The logical and the physical structure of an external
\r
6495 file depend on the given computer and its file system, and so, for the
\r
6496 users of LOGLAN-82, external files are accessible via internal files only.
\r
6499 An internal file is an object of the predefined class type file. When an
\r
6500 internal file is generated, it may be associated with an appropriate
\r
6501 external file. Sometimes the user wish to generate an internal file not
\r
6502 associated with any specified external one. Such a file is called a local
\r
6503 file and its life-time is not longer than the life-time of the program
\r
6504 where it has been generated.
\r
6507 A file is always treated as an unbounded sequence of bytes. A file can be
\r
6508 read or written, and can be set to a required position. Each transmission
\r
6509 from or on a file starts at the byte pointed out by the so-called current
\r
6510 file position advanced by the number of transmitted bytes. File size is
\r
6511 defined as the greatest number of a byte transmitted on the file.
\r
6513 There are some primitive facilities in the language which enable the user
\r
6514 to read or write a specified number of bytes, to change the current file
\r
6515 position, to obtain the file size, etc. All these facilities are in some
\r
6516 sense low-level, since they operate on bytes. The user is able, however, to
\r
6517 declare a class for file processing with high-level operations.
\r
6519 An example of a system class which defines a set of input-output
\r
6520 operations applicable to files containing elements of a single type is
\r
6521 shown in 13.6. Moreover this is not the only way to define high-level file
\r
6522 processing. The user can declare, for instance, a class which defines
\r
6523 operations applicable to files containing elements of mixed types, a class
\r
6524 which defines operations on a file of arrays of various lengths, etc.
\r
6528 13.2. File generation and deallocation
\r
6529 **************************************
\r
6532 Before any operation on a file can be carried out, an internal file must
\r
6533 be generated. If the user wishes to communicate with an external file, then
\r
6534 the generated internal file must be associated with that external one. When
\r
6535 the generation of an internal file is in effect, the file is said to be
\r
6541 <file declaration>:
\r
6543 -----> <variable list> ----> : file -------------->
\r
6545 <file generation>:
\r
6552 <object expression> ---> , ---> <string> ----> ) ------->
\r
6554 !-------------------->!
\r
6559 Variables of file type are declared as any other variables of class type.
\r
6560 An object of file type (internal file) has no attributes visible to the
\r
6562 File generation differs from class generation. It is performed by an open
\r
6563 statement. If the second argument appears, then a new internal file
\r
6564 associated with an external one (identified by the string) is generated.
\r
6565 The reference to such an internal file is set to the variable of type file
\r
6566 occurring as the first argument. If there is only one argument, then a new
\r
6567 local file is generated and the reference to the corresponding internal
\r
6568 file is set to the variable of type file occurring as the argument of the
\r
6569 operation. For instance:
\r
6571 open(X, "teletype")
\r
6573 generates a new internal file associated with the external file "teletype".
\r
6578 generates a new local file referenced by Y.
\r
6582 Thus the operation new is not applicable to files. Moreover, remote
\r
6583 access to internal files is not permissible (no attributes visible to the
\r
6585 Except file generation, remote access and prefixing, file type can be
\r
6586 applied as any other class type. In particular, expressions of file type
\r
6587 may be compared, assignments on variables of type file are allowed, the
\r
6588 user can declare a function of type file, etc.
\r
6594 External file processing is not predefined in the language. The
\r
6595 operations on external files, such as file creation, file deletion, file
\r
6596 protection and so on, depend on the given file system. They may be
\r
6597 introduced into the language as standard functions or procedures in the
\r
6598 individual implementation.
\r
6605 After processing has been completed on a file, it can be closed and the
\r
6606 corresponding internal file may be deallocated. These actions are performed
\r
6607 by the kill statement, where the argument points to the corresponding
\r
6612 13.3. Binary input-output
\r
6613 *************************
\r
6620 < binary input-output operations>:
\r
6622 ---> put ---> (---> <object expression>-> , ---> <expression list> --> ) ---->
\r
6624 ---> get ---> (---> <object expression>-> , ---> <expression list> --> ) ---->
\r
6631 Operation put transmits a sequence of bytes from memory to an open file
\r
6632 (defined by the first parameter) at the current file position. This
\r
6633 sequence of bytes is defined by the list of expressions. For any list
\r
6634 element, going from left to right, the value of the expression is computed.
\r
6635 If this value is primitive, then the transmitted bytes correspond exactly
\r
6636 to the internal representation of the value. If the value is a reference to
\r
6637 an object, then the transmitted bytes cover all non-system attributes of
\r
6638 the referenced object. If this value is none, then no transmission is
\r
6640 Operation get transmits a sequence of bytes from an open file (defined by
\r
6641 the first parameter) to the memory. If a list element is an object
\r
6642 expression, then the transmitted bytes cover all non-system attributes of
\r
6643 the referenced object (hence, if the value of this expression is none, then
\r
6644 no transmission is performed). Otherwise, list element must be a variable
\r
6645 of primitive type, and then the transmitted bytes cover exactly its
\r
6646 internal representation. The sequence of transmitted bytes starts at the
\r
6647 current file position.
\r
6649 For instance, let x be a real, i an integer and Y a reference variable to
\r
6650 an object of type A:
\r
6652 unit A:class(j:integer);
\r
6656 Then the statement
\r
6658 put(F, x, i, x+i, "nothing", Y)
\r
6660 transmits to file F the internal representation of the values of x, i, x+i,
\r
6661 the internal representation of the text "nothing" (i.e., the sequence of
\r
6662 characters) and the internal representation of the attributes j, u, v, w
\r
6663 from the object referenced by Y.
\r
6667 13.4. Other predefined operations
\r
6668 *********************************
\r
6675 !-----> <type> ----------->!
\r
6677 ------> size ---> ( -! !---> ) -------->
\r
6679 !----> < expression> ----->!
\r
6683 ------> eof -----> ( ---> <object expression> ----> ) ------------------>
\r
6685 <position operator>:
\r
6687 ----> position ---> ( ---> <object expression> -----> ) --------------->
\r
6691 --> seek --> ( --> <object expression> --> , --> <arithmetic expression> --> ) -->
\r
6697 The size operator of integer type gives the number of bytes of the
\r
6698 internal representation of an argument. If the argument is an expression of
\r
6699 primitive type, then the returned value may be computed at compilation time
\r
6700 and equals the number of bytes of the internal representation of that
\r
6701 primitive type. If the argument is an expression of class or array type,
\r
6702 then the returned value gives the number of bytes of the object referenced
\r
6703 by the argument (except system-attributes). If the object none is
\r
6704 referenced, then the returned value is 0.
\r
6705 Another kind of argument of size operator is type. It may be either an
\r
6706 explicitly written type or a formal type. If the argument is a primitive
\r
6707 type or a class type, then its length in bytes computed at compilation time
\r
6708 is returned. If the argument is an array type, then its size cannot be
\r
6709 established and so the expression is incorrect. If the argument is a formal
\r
6710 type, the returned value is defined similarly but computed at run time.
\r
6711 Thus when the actual type is array the run time error is raised.
\r
6712 In all these cases size operator informs the user about the length in
\r
6713 bytes of the internal representation of the argument (if possible). In
\r
6714 particular, the argument may be a file and then the length in bytes of the
\r
6715 corresponding external or local file is returned.
\r
6717 The argument of the boolean operator eof must be a file. It returns the
\r
6718 value true iff the current position of the file exceeds or equals its size.
\r
6719 The argument of the integer operator position must also be a file. It
\r
6720 returns the current position of the file.
\r
6721 The first argument of the seek operation must be a file. Then the current
\r
6722 position of this file is set to the value defined by the second argument of
\r
6727 13.5. Text input-output
\r
6728 ***********************
\r
6731 Besides binary input-output LOGLAN-82 provides text input-output
\r
6732 operations also. The operations read and write are available for input and
\r
6733 output in human readable form. Namely, operation read decodes a sequence of
\r
6734 bytes into the internal representation of the corresponding value before
\r
6735 the transmission is performed. Similarly operation write encodes the
\r
6736 internal representation of a value into the corresponding sequence of bytes
\r
6737 before transmission is performed.
\r
6744 <text input-output statement>:
\r
6746 !--------------------------->!
\r
6748 --> read --> ( --> <object expression> ---> , --> <variable list> --> ) ---->
\r
6751 !------------------------------------>!
\r
6753 ->writeln --> ( --> <object expression> --> ) ------------------------->
\r
6756 ->write --> ( -------------->!
\r
6758 <object expression>-> , -> <expression> ----> <format> ---> ) -------->
\r
6760 !<--------- , ------------!
\r
6765 ------------------------------------------------------------------->
\r
6767 !-> : -> <arithmetic expression>-!- : -> <arithmetic expression> -!
\r
6774 An input statement read(F, y1, ..., yk) is correct if F is a file and y1,
\r
6775 ..., yk are variables of integer, real, or character type. File F is
\r
6776 treated as a sequence of symbols. The execution of that statement causes
\r
6777 the input data represented as the corresponding sequence of symbols from
\r
6778 file F to be read, decoded and assigned to y1, ..., yk respectively. The
\r
6779 input statement is defined if the assignments are defined (going from left
\r
6781 An output statement write(F, E:A1) is correct if F is a file, E is an
\r
6782 expression of a primitive type, and A1 is an arithmetic expression of
\r
6784 Consider first the case where expression E is of integer type. The value
\r
6785 of expression A1 determines the number of symbols to be outputed on file F.
\r
6786 If the specified number of symbols is greater (less) than the number of
\r
6787 symbols required for the representation of the value of expression E, then
\r
6788 the value of E is preceded by the appropriate number of blanks (then the
\r
6789 least significant digits are omitted). The absence of format indicates a
\r
6790 standard one (dependent on an individual implementation).
\r
6791 If expression E is of real type, then the output statement may be of the
\r
6792 form write(F, E:A1:A2), where A1 and A2 are arithmetic expressions of
\r
6793 integer type. The meaning of the expression A1 is that described above, the
\r
6794 value of the expression A2 determines the number of digits following the
\r
6795 decimal point. In case of an output statement of the form write(F, E:A1),
\r
6796 where E is of real type, the exponent part is always present. The absence
\r
6797 of format indicates a standard one (dependent on an individual
\r
6799 An output statement of the form write(F, E) where E is an expression of
\r
6800 character type causes the external representation of E to be outputed on
\r
6802 If E is an expression of string type, then its external representation is
\r
6803 outputed on file F. In this case format A1 may appear and defines the
\r
6804 maximal number of symbols which may be outputed, i.e., if the length of a
\r
6805 string exceeds the defined format, then the last symbols are dropped.
\r
6806 In the statement write(F, E:A1:A2) format A2 is computed first (if
\r
6807 present), format A1 is computed next (if present), and finally the value of
\r
6808 E is computed and outputed according to the defined formats.
\r
6809 The execution of an output statement with a list results in the
\r
6810 successive evaluations of the expressions A2, A1, E, and in the output of
\r
6811 the computed value.
\r
6812 Statement writeln outputs the end of line symbol after output is
\r
6813 completed. If writeln has only the file parameter, then the end of the line
\r
6814 symbol is outputed on file F.
\r
6815 If no file is specified, a default standard input or standard output file
\r
6816 is used. At the beginning of program execution, these files are open and
\r
6817 associated with two implementation defined external files.
\r
6821 13.6. Example of high-level file processing
\r
6822 *******************************************
\r
6824 A class defining high-level file processing is presented below. The user
\r
6825 can prefix the main block of his program by such a class, and then, the
\r
6826 high-level file operations are provided automatically.
\r
6828 unit input_output class;
\r
6830 unit uni_file :class(type T);
\r
6831 hidden element_size;
\r
6832 var F:file, element_size:integer;
\r
6833 unit set_position:procedure(i:integer);
\r
6835 call seek(F, i*element_size)
\r
6837 unit file_position:function:integer;
\r
6839 result:=position(F) div element_size
\r
6840 end file_position;
\r
6841 unit end_of_file:function:boolean;
\r
6845 unit file_size:function:integer;
\r
6847 result:=size(F) div element_size
\r
6849 unit read_element:procedure(output x:T);
\r
6853 unit write_element:procedure(x:T);
\r
6856 end write_element;
\r
6858 element_size:=size(T)
\r
6860 unit inout_file:uni_file class(S:string);
\r
6865 unit in_file:inout_file class;
\r
6866 hidden write_element;
\r
6868 unit out_file:inout_file class;
\r
6869 hidden read_element;
\r
6871 unit local_file:uni_file class;
\r
6876 unit close_file:procedure(E:uni_file);
\r
6878 kill(E.F); kill(E)
\r
6887 Part A: the papers related to the language itself.
\r
6889 [1] Bartol W.M, Kreczmar A., Litwiniuk A., Oktaba H.: Semantics and
\r
6890 implementation of prefixing at many levels, Ins.Inf.U.W. reports, nr 94.,
\r
6893 [2] Bartol-Ratajczak W.M., Szczepanska-Wasersztrum D.: Data structure for
\r
6894 simulation purposes in LOGLAN. ICS PAS report 373, 1979.
\r
6896 [3] Dahl O-J., Myhrhaug B., Nygaard K.: Common base language. NCC s-22,
\r
6899 [4] Dahl O-J., Wang A.: Coroutine sequencing in a block structured
\r
6900 environment. BIT 11, 1971, pp.425-49.
\r
6902 [5] Hansen P.B.: CONCURRENT PASCAL, a programming language for operating
\r
6903 system design. IST report no.10 April 1974.
\r
6905 [6] Hoare C.A.R.: Monitors, an operating system structuring concept. CACM,
\r
6906 vol.17, n.10, October 1974, pp.549-57.
\r
6908 [7] Muldner T.: On the properties of ADA's rendez-vous and an
\r
6909 implementation of its counterpart in LOGLAN. To appear.
\r
6911 [8] Muldner T.: LOGLAN-82 programmer's manual (in Polish), pp.1-417.
\r
6913 [9] Myhre O.: Protecting attributes of a local class. SIMULA Newsletters,
\r
6914 vol.5, n.4. November 1977.
\r
6916 [10] Naur P.(ed): Revised report on the algorithmic language ALGOL 60. ACM
\r
6919 [11] Preliminary ADA reference manual. Sigplan Notices, vol.14 n.6, June
\r
6922 [12] Salwicki A., Muldner T., Oktaba H., Bartol-Ratajczak W.M.: Base
\r
6923 machine language. General outline. (in Polish). Archiwum opracowan nr 20,
\r
6926 [13] Wirth N.: The programming language PASCAL, Acta Informatica, 1971, 1,
\r
6931 Part B: The papers related to the general project LOGLAN-82
\r
6933 [14] Aho A.V., Hopcroft J.E., Ullman J.D.: The design and analysis of
\r
6934 computer algorithms. Addison-Wesley. 1974.
\r
6936 [15] Banachowski L., Kreczmar A., Mirkowska G., Rasiowa H., Salwicki A.: An
\r
6937 introduction to algorithmic logic. Mathematiccal investigations in the
\r
6938 theory of programs. In Banach Center publications, Warsaw 1977.
\r
6940 [16] Bartol W.M.: The definition of the semantics of some statements of a
\r
6941 block structured language with type prefixing. To appear in: Lect.Notes in
\r
6942 Comp. Sc. Proc. Poznan 1980, Symp. on algorithmic logic and LOGLAN.
\r
6944 [17] Burkhard H.D.: On priorities of parallelism: Petri nets under the
\r
6945 maximum firing strategy. To appear in Lect. Notes in Comp.Sc. Proc. Poznan
\r
6946 1980, Symp. on algorithmic logic and LOGLAN.
\r
6948 [18] Dahl O-J., Dijkstra E.W., Hoare C.A.R.: Structured programming.
\r
6949 London. Academic Press 1972.
\r
6951 [19] Muldner T.: On the semantics of parallel programs. ICS PAS report 348,
\r
6952 1979, extended version to appear in Fund. Informaticae.
\r
6954 [20] Muldner T.: Implementation and properties of certain tools for
\r
6955 parallel programs. ICS PAS report 356, 1979. see also FCT' 77,
\r
6956 Lect.Not.Comp.Sc.56.
\r
6958 [21] Oktaba H.: On the algorithmic theory of references. To appear in:
\r
6959 Lect.Not. in Comp.Sc. Proc. Poznan 1980, Algorithmic logic and LOGLAN.
\r
6961 [22] Salwicki A.: Programmability and recursiveness, to appear.
\r
6963 [23] Salwicki A.: Formalized algorithmic languages. Bull.Acad. Polon.Sci.
\r
6964 18, 1970, pp.227-232.
\r
6966 [24] Salwicki A.: Applied algorithmic logic. Proc. MFCS' 77. Lect.Not. of
\r
6967 Comp.Sc. 53, 1977, pp.122-134.
\r
6969 [25] Salwicki A.: An algorithmic approach to set theory. Proc.FCT'77. Lect.
\r
6970 Not. in Comp. Sc. 56, 1977.
\r
6972 [26] Salwicki A.: On the algorithmic theory of stacks. Proc. MFCS' 78
\r
6973 Lect.Not. in Comp.Sc. 64, 1978.
\r
6983 actual paratemetr list, 76 deallocation, 17, 83
\r
6984 allocation statement, 75-81 - statement, 83
\r
6985 andif, 9 declaration list, 41
\r
6986 arithmetic expression, 64-66 detach, 86,104,108
\r
6987 array, 18,29,75,82 dotted variable, 60
\r
6988 - generation statement 18,75,82 dynamic compatibility
\r
6989 - object, 29 of parameters, 79
\r
6990 - type, 29 dynamic consistency
\r
6991 assignment statement, 72 of types, 55
\r
6992 attach, 20,86,104,108 dynamic control statements, 85
\r
6993 attribute, 11,30,42 dynamic instance, 11,13
\r
6994 dynamic location, 42,54
\r
6997 binary item, 126 evaluation statement, 71-73
\r
6998 block statement, 11-12,35,75 exception, 22,96
\r
6999 block structure,11 - handler, 22,97
\r
7003 call statement, 13 external, 122-123
\r
7004 case statement, 10,87,89 external file, 129
\r
7006 character expression, 67 F
\r
7007 class, 14,33 file, 129,136
\r
7008 - declaration, 33 - declaration, 130
\r
7009 - object, 14,17 - generation, 130
\r
7010 close, 22,40,45 formal
\r
7011 comment, 25 - function parameter, 38-39
\r
7012 compound statement, 8,71,87-88 - input parameter, 37-39
\r
7013 conditional statement, 8,87 - output parameter, 37-39
\r
7014 configuration statement, 71 - parameter, 37-39
\r
7015 consistency of types, 55 - procedure parameter, 38-39,41
\r
7016 constant ,31,57 - type, 30
\r
7017 - declaration, 31 - type parameter, 37-39
\r
7018 context properties, 56 function, 13
\r
7019 copy, 74 - call, 75-81
\r
7020 copying statement, 72,74
\r
7021 coroutine, 20,28,36,86
\r
7028 garbage collection, 17 object, 14,48
\r
7029 get, 132 - deallocation, 75,83
\r
7031 H - expression, 69-70
\r
7032 handler - generation, 75
\r
7033 - declaration, 40 - generator statement, 14
\r
7034 - execution, 101-102 orif, 8
\r
7035 - termination, 101-102
\r
7039 identifier definition, 25 parallel statement, 105
\r
7040 illegal identifier, 44 prefix 15-16,36
\r
7041 inheritance list, 40 - sequence, 36
\r
7042 inner, 16,41,84 prefixing, 15,36
\r
7043 interface, 118 primitive statement, 71
\r
7044 internal file, 129 primitive synchronizing
\r
7045 iteration statement, 9,10,90-92 statement, 105,109
\r
7048 kill, 17,83 process, 21,28,36,104
\r
7049 - state transition, 105
\r
7050 L protection list, 40
\r
7051 languages, 118,121-123 protection of attributes, 22,43
\r
7052 last_will, 101-102 put, 132
\r
7053 - statement, 101-102
\r
7054 legal identifier, 44 Q
\r
7055 lexical entity, 25 qua, 70
\r
7056 library items, 115,117 qualified object expression, 69-70,76
\r
7057 linked item specification, 31
\r
7059 loop statement, 87,91 raise, 98
\r
7061 M recompilation, 127
\r
7062 main, 28 reference variable, 14
\r
7063 monitor, 112 remote
\r
7065 N - function identifier, 76
\r
7066 none, 69 - procedure identifier, 76
\r
7068 resume, 21,104,107-108
\r
7070 run-time error, 22
\r
7075 scheduling, 21,105 taken, 40,44
\r
7076 semantic properties, 56 terminate, 101-102
\r
7077 semaphore, 27 textual control statement, 84
\r
7078 separate compilation, 22,115-128 this, 70
\r
7079 sequential statements, 71 ts, 21,109
\r
7080 signal, 96 type, 26
\r
7081 - declaration, 31 - class, 30
\r
7082 - handler, 97 - compound, 26,29
\r
7083 - raising, 98 - primitive, 26-27
\r
7084 - specification, 96
\r
7085 simple control statement, 84 U
\r
7086 simple variable, 58 unit, 13,25,31
\r
7087 sl-virtual, 118,122-123 - attributes, 42
\r
7088 statement list, 41 - body, 40-41
\r
7089 static attribute, 46 - declaration, 31
\r
7090 static compatibility unlock, 21,109
\r
7092 static consistency V
\r
7093 of types, 55 variable, 32,57
\r
7094 static container, 46 - declaration, 31
\r
7095 static location, 42,46 virtual
\r
7096 storage management, 17 - attribute, 49-53
\r
7097 stop, 21,104,107-108 - chain, 49-53
\r
7098 string, 27 - subprogram, 49-53
\r
7099 - constant, 68 visibility rules, 42,44
\r
7101 subprogram declaration, 34 W
\r
7102 - body, 40 wait, 21,107-108
\r
7103 subscripted variable, 59 wind, 101-102
\r
7104 synchronization, 21,105 write, 134-135
\r
7105 syntactic writeln, 134-135
\r
7109 system signals, 103
\r
7110 system variable, 61
\r