|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 192768 (0x2f100) Types: RcTekst Names: »99110141.WP«
└─⟦7fab0c8ae⟧ Bits:30005866/disk3.imd Dokumenter i RcTekst format (RCSL 99-1-*) └─⟦this⟧ »99110141.WP«
╱04002d4e0a00060000000003013c3100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ════════════════════════════════════════════════════════════════════════ ↓ ┆14┆┆b3┆┆06┆┆0b┆┆05┆↓ ┆b0┆┆a1┆1. INTRODUCTION↲ ↲ ┆b0┆┆a1┆1.1 Goals↲ ↲ The principle goal of Real-Time Pascal is to be a ↓ programming tool particularly well-suited in situations ↓ characterized by the following two requirements:↲ ↲ - ┆84┆the software must provide rapid response to external ↓ ┆19┆┆82┆┄┄events ("real-time"),↲ - ┆84┆programmers wish to utilize the organization of software ↓ ┆19┆┆82┆┄┄into parallel cooperating processes as a fundamental ↓ ┆19┆┆82┆┄┄structuring tool.↲ ↲ The major use of Real-Time Pascal has been and is foreseen ↓ to remain in the basic software of distributed processing ↓ systems and data communication network nodes:↲ ↲ - terminal emulation,↲ - layered protocol handling,↲ - local area networking services.↲ ↲ In these kinds of situations the two above-mentioned ↓ requirements are inherently present.↲ ↲ The programming of end-user applications, and in particular: ↓ programming by the end user, are not goals of Real-Time ↓ Pascal. High level run-time support functions, such as a ↓ general high level input/output system, are not included in ↓ the language. However, provided suitable tools are furnished ↓ along with support for the language itself, it may prove to ↓ be well suited for applications programming as well as ↓ systems programming.↲ ↲ Although Real-Time Pascal aims at low level programming it ↓ is very much a high level language. This is true in terms of ↓ syntax, in terms of programming facilities, and in ↓ particular in terms of the amount of consistency enforcement ↓ which is emboided in the language.↲ ↲ ┆8c┆┆83┆┆e0┆↓ Real-Time Pacal has not been designed specifically for any ↓ particular machine. However, the feasibility and usefulness ↓ of a planned implementation on the Intel iAPXn86 processor ↓ series have been absolute requirements. One type of machine ↓ dependency is built into the languageø in order that ↓ descriptive types (cf. section 3.11) be correctly ↓ implemented, the memory of the target machine must be ↓ addressable at the level of 8-bit bytes, and the ↓ significance of individual bytes within multi-byte entities ↓ (e.g. 16-bit words) must increase with increasing addresses.↲ ↲ ↲ ┆b0┆┆a1┆1.2 Main Features↲ ↲ In many respects Real-Time Pascal is, as one might ↓ anticipate, similar to standard Pascal (1, 2). The major ↓ difference is that Real-Time Pascal includes facilities for ↓ starting and controlling multiple processes as well as for ↓ the orderly synchronization and intercommunication between ↓ such processes. Features which are basic to Real-Time Pascal ↓ but well-known from standard Pascal are not discussed in ↓ this section.↲ ↲ ↲ ┆b0┆┆a1┆1.2.1 Processes↲ ↲ As in standard Pascal, a Real-Time Pascal ┆a1┆program┆e1┆ consists ↓ of declarations and definitions of data to be manipulated, ↓ and a description of actions to perform the desired ↓ manipulations. The execution of a Real-Time Pascal program ↓ is called a ┆a1┆process┆e1┆. A process is said to be an ┆a1┆incarnation┆e1┆ ↓ of the program which is executed.↲ ↲ Real-Time Pascal is intended for compilation. The major ↓ ingredient of an implementationis the compiler which will ↓ transform source programs into object code executable on ↓ some target machine. Throughout this document reference is ↓ made to ┆a1┆compiletime┆e1┆, the time when a source text is being ↓ ┆8c┆┆83┆┆c8┆↓ manipulated by a compiler, and ┆a1┆run-time┆e1┆, the time when a ↓ dynamic system consisting of a number of cooperating ↓ processes is operative.↲ ↲ In addition to declarations of data and descriptions of ↓ actions a program (and this is where Real-Time Pascal ↓ departs from standard Pascal) may contain sub-programs, and ↓ a process may create, start and control incarnations of sub-↓ programs of the program of which it is itself an ↓ incarnation. Sub-programs may be nested to any depth. In ↓ order words a number of Real-Time Pascal programs may ↓ constitute a ┆a1┆program tree┆e1┆. The encloser relation between a ↓ program and a sub-program is carried directly over to the ↓ ┆a1┆parent┆e1┆ relation that exists between a process and a ┆a1┆child┆e1┆ ↓ process which it has created. Thus the dynamic set of active ↓ processes will exhibit a control structure reflecting the ↓ nested structure of the program tree.↲ ↲ An essential feature of Real-Time Pascal is that a number of ↓ special types and operations on variables of these types are ↓ directly tailored to perform syncrhonization and exchange of ↓ access to shared data between processes in a well-defined ↓ and secure fashion. In particular one important invariant is ↓ maintained a priori (i.e. without the programmer needing to ↓ worry about it): to every ┆a1┆buffer┆e1┆ there exists at any given ↓ time precisely one ┆a1┆reference┆f0┆┆e1┆, allowing at most one process ↓ to access the buffer contents. Exchange of access to a ↓ buffer is achieved by passing the (contents of the) buffer ↓ as a message via a ┆a1┆mailbox.↲ ↲ The operations for process synchronization and message ↓ passing are available in Real-Time Pascal as predefined ↓ routines. This implies that an implementation of Real-Time ↓ Pascal will involve the construction of either:↲ ↲ - ┆84┆a software nucleus, i.e. a small operating system, which ↓ ┆19┆┆82┆┄┄performs the message passing and process synchronization ↓ ┆19┆┆82┆┄┄and scheduling functions, typically in a highly dedicated ↓ ┆19┆┆82┆┄┄manner, or↲ ↲ ┆8c┆┆83┆┆e0┆↓ - ┆84┆a run-time system providing a bridge to a general ↓ ┆19┆┆82┆┄┄operating system which lends itself to supporting the type ↓ ┆19┆┆82┆┄┄of process synchronization and inter-communication ↓ ┆19┆┆82┆┄┄functions defined as part of Real-Time Pascal.↲ ↲ An operating system to be used for the latter kind of ↓ implementation must support the execution of multiple ↓ processes either in true parallel on a single processor. The ↓ operating system must perform process scheduling; it must ↓ also support the exchange of messages via mailboxes. In ↓ general it is necessary to critically evaluate a given ↓ operating system before it is used as a foundation for an ↓ implementation of Real-Time Pascal.↲ ↲ When a suitable general operating system is used to perform ↓ the Real-Time Pascal functions of process synchronization ↓ and message passing, the ability is opened up for Real-Time ↓ Pascal processes to cooperate with processes written in ↓ other, typically low-level, languages supported under that ↓ operating system. In order to make this possibility ↓ practically useful, the data formats and operating system ↓ calling sequences used by the Real-Time Pascal compiler in ↓ question must be well-documented.↲ ↲ One area in which the use of other languages in conjunction ↓ with Real-Time Pascal is particularly important is the ↓ direct interaction with peripheral devices and the ↓ processing of interrupts. So-called driver processes which ↓ perform tasks of these types will always be machine ↓ dependent and may be programmed in assembler or PL/M-type ↓ languages. Consequently no input/output instructions or ↓ interrupt syncrhonization functions have been incorporated ↓ into Real-Time Pascal. It is a simple matter, however, to ↓ extend a particular implementation with these functions.↲ ↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆1.2.2 Data Typing↲ ↲ Like standard Pascal, Real-Time Pascal is a stronly typed ↓ language. Types, in the abstract, provide important ↓ assitance to structured programmer thinking, and the ↓ enforcement of strong typing is a useful tool in the ↓ detection of many kinds of errors. A particular class of ↓ types, the so-called descriptive types, on the other hand, ↓ may be used in a very concrete fashion to describe the ↓ precise interpretation of bit-strings in the memory of the ↓ machine executing a Real-Time Pascal program. This feature ↓ is particularly useful when the precise representation of ↓ data is prescribed as part of the external specifications of ↓ a software project, e.g. a standard protocol for some aspect ↓ of a data communication function.↲ ↲ Another feature which stands apart from the class room style ↓ of standard Pascal is that Real-Time Pascal allows the ↓ definition of families of conformant types, differing only ↓ in the values of type parameters which may determine e.g. ↓ the length of an array, but having the same structure. Types ↓ are also allowed to be dynamic, e.g. by having parameters ↓ which cannot be evaluated at compile-time. Both of these ↓ features support the construction of dynamically ↓ configurable software.↲ ↲ ↲ ┆b0┆┆a1┆1.2.3 Data Access↲ ↲ The data items manipulated by a process may be allocated as ↓ ┆a1┆private┆e1┆ to the process, or they may be allocated as ┆a1┆shared┆e1┆, ↓ implying that access to the data may be shared among several ↓ processes, as described above.↲ ↲ The handling of ┆a1┆variables┆e1┆ is based on the concepts of ↓ objects and types which are described in chapter 3. A ↓ private variable may be declared, in which chase allocation ↓ and deallocation of memory for the variable is performed ↓ automatically in a ┆a1┆stack┆e1┆ according to the well-known ↓ discipline for block structured languages. A declared ↓ ┆8c┆┆83┆┆e0┆↓ variable is accessed directly by name. A private variable ↓ may also be allocated dynamically in the so-called ┆a1┆heap┆e1┆ by ↓ an invocation of the predefined routine new. In this case ↓ the variable must be accessed through a pointer.↲ ↲ Each process has its own stack and heap, which are thus ↓ well-suited for private variables. However, a variable in ↓ the stack may be declared as shared, implying that it can ↓ only be accessed in a so-called ┆a1┆region┆e1┆. A shared variable ↓ can be made accessible to a child process as a process ↓ parameter.↲ ↲ A variable is said to be ┆a1┆owned┆e1┆ by the process in whose stack ↓ or heap it is allocated. A variable may become known to ↓ processes other than the owner by being passed as a process ↓ parameter.↲ ↲ Buffers are allocated neither in the stack nor in the heap ↓ of a process, but separate from both of these. Buffers are ↓ organized in ┆a1┆pools┆e1┆. a pool may contain a number of buffers ↓ of equal size.↲ ↲ A buffer is not in itself a variable, but like an object it ↓ occupies a number of consecutive bytes of memory, and a ↓ buffer may be treated as a variable by superimposing a type ↓ onto it in a lock statement.↲ ↲ Buffers are accessed through variables of the predefined ↓ type reference. A number of operations involving buffers are ↓ available as predfined routines taking references as ↓ parameters. In particular it is possible to build ┆a1┆buffer ↓ ┆19┆┄┄┆84┆stacks┆e1┆ (not to be confused with process stacks) and ┆a1┆buffer ↓ ┆19┆┄┄┆84┆chains┆e1┆.↲ ↲ Associated with a buffer is a set of buffer ┆a1┆attributes┆e1┆, one ↓ of which is the buffer size, i.e. the number of bytes it ↓ occupies. The values of some of the buffer attributes are ↓ accessible, and some may also be modified. A buffer of size ↓ ┆8c┆┆83┆┆c8┆↓ 0, called an ┆a1┆empty buffer┆e1┆, may be used meaningfully in ↓ connection with buffer stacks, and/or for simple ↓ synchronization purposes. An empty buffer has a full set of ↓ buffer attributes. Fig. 1 gives a sketch of how memory might ↓ be organized in an implementation of Real-Time Pascal. ↓ Clearly an architecture supporting segmentation will be ↓ helpful.↲ ↲ ↲ ┆b0┆┆a1┆1.2.4 Distributed Systems↲ ↲ A principal area of intended use of Real-Time Pascal is the ↓ construction of distributed systems according to the general ↓ architectural principles described in (4).↲ ↲ A resident module, in the sense of (4), may consist of a ↓ number of cooperating Real-Time Pascal processes. ↓ Intercommunication at the so-called level i, may then take ↓ place using the Real-Time Pascal facilities for inter-↓ process communication.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆06┆┆a1┆ ┆e1┆ ┆05┆┆a1┆buffers ↲ ↓ ↲ ┆a1┆ ┆e1┆ ┆a1┆ ┆e1┆ stack↲ ╞ ┆05┆┆a1┆ ↲ ┆a1┆ ┆e1┆ heap↲ ┆a1┆ ┆e1┆ ┆a1┆┆05┆↲ code of program A ┆a1┆ ↲ stack and heap↲ of process A ┆a1┆ ↲ ↲ ↲ ↲ ╞ ╞ ╞ ┆a1┆ ┆e1┆┆05┆┆a1┆ ↲ ┆a1┆ ┆e1┆╞ ╞ ┆a1┆ ┆e1┆↲ ┆a1┆↲ ┆a1┆ ┆e1┆ ┆a1┆ ┆05┆↲ ┆a1┆┆05┆↲ ┆a1┆ ↲ ┆a1┆ ┆e1┆ stack and heap↲ code of program B of process B┆82┆1 ┆81┆┆a1┆ ┆05┆↲ ↲ ↲ ┆06┆┆a1┆ ↲ ↲ ┆06┆┆a1┆ ↲ ↲ ┆06┆┆a1┆ ↲ ↲ ┆06┆┆a1┆ ↲ ╞ ╞ ╞ stack and heap↲ ╞ ╞ ╞ of process B┆82┆2↲ ↲ Figure 1: Example of memory organization.↲ ════════════════════════════════════════════════════════════════════════ ↓ To support inter-module communication (at the so-called ↓ level d) the predinfed type ┆a1┆port┆e1┆, representing the concept ↓ of port as described in (4) has been included in the ↓ language along with a set of predefined routines to perform ↓ inter-module communication (IMC) functions (5).↲ ↲ Implementations may exist which support only a limited set ↓ of IMC functions or none at all.↲ ↲ ↲ ┆b0┆┆a1┆1.2.5 Faults↲ ↲ The term ┆a1┆fault┆e1┆ is used throughout the following chapters to ↓ refer to violations of semantic rules which cannot be ↓ completely enforced at compile-time, i.e. violations which ↓ can in some cases only be detected when a program is ↓ executed.↲ ↲ The language allows partly programmer-defined handling of ↓ faults. By default the occurrence of a fault will cause the ↓ output of suitable diagnostic information.↲ ↲ ↲ ┆b0┆┆a1┆1.2.6 Extensibility↲ ↲ The general representation of built-in functions of the ↓ language is that of predefined routines working on ↓ parameters of predefined, and often shielded, types.↲ ↲ When a desire for extensions to the defined language arises, ↓ it will be both natural and usually also easy to define such ↓ extensions in terms of one or more types and routines ↓ operating on parameters of these types. For example, a ↓ general high-level input/output system may be implemented in ↓ this way.↲ ↲ The distinction between built-in functions and such ↓ extensions will not appear very sharp at all, nor is it ↓ ┆8c┆┆83┆┆c8┆↓ intended to. The only missing feature will be compiler ↓ supported protection of types one might wish to shield. ↓ Supporting a larger number of shielded types, however, ↓ requires very little in the way of compiler modification, ↓ and thus a future evolution of the language, e.g. toward ↓ supporting application programming, is at least feasible.↲ ↲ ↲ ┆b0┆┆a1┆1.3 Syntax Diagrams↲ ↲ Each ┆a1┆syntax category┆e1┆ of the context-free syntax of Real-Time ↓ Pascal is defined by a ┆a1┆syntax diagram┆e1┆. A syntax diagram ↓ consists of:↲ - ┆84┆the name of the defined syntax category followed by a ↓ ┆19┆┆82┆┄┄colon,↲ - arrows, which may include branching,↲ - ┆84┆indications of occurrences of syntax categories, in the ↓ ┆19┆┆82┆┄┄form of rectangular boses containing the category names,↲ - language symbols enclosed in rounded boxes.↲ ↲ ┆a1┆Example:↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ A source text or substring of a source text is ↓ asyntactically correct occurrence of a syntax category if it ↓ ┆8c┆┆83┆┆c8┆↓ can be obtained by traversing the diagram defining that ↓ category, following the arrows. When an indication of an ↓ occurrence of a syntax category is encountered (must be ↓ entered through an arrow), the traversal diagramis the ↓ sequence of lexical elements which have ultimately been ↓ encountered.↲ ↲ The names of syntax categories are used frequently in the ↓ descriptionsof the semantics of language consructs to refer ↓ to particular occurrences of syntax categories. To make it ↓ clear that a sequence of words in the text is indeed a ↓ reference to such an occurrence it may be enclosed in single ↓ quotes.↲ ↲ Prefixes terminated by underscores are also used in names of ↓ syntax categories to make it easier to refer to a particular ↓ occurrence of a syntax category. They have no significance ↓ in the context-free syntax. For example 'bound-type_name7 ↓ and 'parameterized-type_name' are syntactically equivalent ↓ and both defined by the diagram for 'name'. Hyphens and ↓ spaces are used exculisvely as reading aids.↲ ↲ A prefix which occurs in several syntax diagrams may be ↓ understood as an indication of a context-sensitive syntax ↓ rule. Such rules, however, are all explained in the text ↓ describing the semantics of the relevant constructs.↲ ↲ A complete set of syntax diagrams is collected in appendix ↓ B.↲ ↲ ↲ ┆b0┆┆a1┆1.4 Organization of this Manual↲ ↲ A rigorous definition of the Real-Time Pascal programming ↓ language is given in the following chapters. Each chapter is ↓ divided into sections, each dealing with a particular aspect ↓ of the language. The contents of a section are in general as ↓ follows:↲ ↲ ┆8c┆┆83┆┆d4┆↓ - introductory remarks,↲ - syntax diagrams (some sections contain no diagrams),↲ - ┆84┆description in natural language of the semantics of the ↓ ┆19┆┆82┆┄┄particular part of the language,↲ - ┆84┆optional notes, where specific consequences of the syntax ↓ ┆19┆┆82┆┄┄or semantics may be pointed out,↲ - examplex.↲ ↲ The notes and examples do not constitute part of the ↓ definition of the language.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆2. LEXICAL ELEMENTS↲ ↲ A Real-Time Pascal source program is a string of characters ↓ which can be (uniquely) parsed as consisting of a sequence ↓ of suitably separated lexical elements. Separators are ↓ comments and nonprinting symbols. There are five categories ↓ of lexical elements:↲ ↲ - names,↲ - character literals,↲ - character strings,↲ - numbers, and↲ - language symbols.↲ ↲ Of these only names are defined in terms of syntax diagrams; ↓ the others are verbally described. All language symbols, ↓ some of which are keywords similar to names, as well as som ↓ additional names, are predefined as part of the language. ↓ The remaining lexical elements are programmer-specified.↲ ↲ No separator may occur within a single lexical element. At ↓ least one separator must appear between any pair of ↓ consecutive lexical elements whenever this is necessary to ↓ provide unique delimitation.↲ ↲ An alphabetic character, a through z, is an occurrence of ↓ the category 'letter' which is referred to in the following. ↓ No destinction is made between the upper and lower case ↓ forms of the same letter, except in character literals or ↓ character strings.↲ ↲ ↲ ┆b0┆┆a1┆2.1 Names↲ ↲ All declared entitites, whether programs, routines, types, ↓ variables or merely constants, have a name.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆84┆┆b4┆↓ All characters in a name are significant. However, names ↓ used in conjunction with external linking may be abbreviated ↓ in an implementation/installation dependent fashion.↲ ↲ The keywords (cf. subsection 2.5.1) satisfy the syntax for ↓ 'name', but are explicitly excluded from the catagory. In ↓ addition a number of routines,types and constants exist (cf. ↓ Appendix C) with predefined names, i.e. these names can be ↓ redefined.↲ ↲ ┆a1┆Examples:↲ ↲ step usage_count process_117 Very_Long_Identifier_Name↲ ↲ ↲ ┆b0┆┆a1┆2.2 Character Literals↲ ↲ Character literals denote characters, which are values of ↓ the predefined type char. They are described in subsection ↓ 3.4.2.↲ ↲ ↲ ┆b0┆┆a1┆2.3 Character Strings↲ ↲ Character strings denote values of string types. They are ↓ described in subsection 3.9.4.↲ ↲ ↲ ┆b0┆┆a1┆2.4 Numbers↲ ↲ A number is a sequence of digits, possibly prefixed by a ↓ radix specification. A digit is a decimal digit, 0 through ↓ 9, or one of the letters A through F.↲ ↲ Numbers without a radix prefix are integer numbers in ↓ standard decimal notation; they denote values of the ↓ predefined type integer, cf. subsection 3.4.3.↲ ↲ ┆8c┆┆83┆┆c8┆↓ Numbers prefixed with a radix specification are interpreted ↓ as follows:↲ ↲ B╞ binary, digits must be 0,1↲ O╞ octal, digits must be 0..7↲ D╞ decimal, digits must be 0..9↲ H╞ hexadecimal, digits must be 0..9, A..F↲ ↲ If the number of digits following the radix specificationis ↓ less than or equal to 8, for binary, or 2, for other ↓ radices, then the type of the number is the predefined ↓ machine type byte; otherwise it is word. Cf. section 3.5.↲ ↲ ┆a1┆Examples:↲ ↲ B1010 - a byte↲ 0777 HCAFE D255 D37913 - four words↲ ↲ ↲ ┆b0┆┆a1┆2.5 Language Symbols↲ ↲ The predefined language symbols fall in two classes: ↓ keywords and special symbols.↲ ↲ ↲ ┆b0┆┆a1┆2.5.1 Keywords↲ ↲ Keywords are reserved names, i.e. it is illegal to use them ↓ as names in declarations. Throughout this document some ↓ keywords are rendered in small case letters and some in ↓ capitals, merely as a matter of style. The keywords are:↲ ↲ ╱04002d4e0a0006000000000301413100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ╱04002d4e0a00060000000003013c3100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ↓ AND ARRAY AS BEGIN boolean╞ byte↲ CASE chan char CONST CONTINUELOOP create↲ DIV DO DOWNTO ELSE END ENDLOOP↲ EXIT EXITLOOP EXTERNAL FOR FORWARD FUNCTION↲ GOTO IF IN INSPECT integer link↲ LOCK LOCKBUF LOOP mailbox MOD NOT↲ ┆8c┆┆83┆┆c8┆↓ OF OR OTHERWISE PACKED pool port↲ PROCEDURE process PROGRAM RECORD reference REGION↲ REPEAT SET SHARED SHIFT THEN TO↲ TYPE typesize unlink UNTIL VAR varsize↲ WHILE WITH word XOR↲ ↲ ↲ ╱04002d4e0a00060000000003013c3100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ╱04002d4e0a0006000000000301413100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ↓ ┆b0┆┆a1┆2.5.2 Special Symbols↲ ↲ The special symbols are special graphic symbols or short ↓ sequences of such symbols. The following special symbols are ↓ defined as part of the language:↲ ↲ + - * < > <> <= >= ( ) (. .) (: :)↲ ` = := :=: . , ; : .. *** ! ? &↲ ↲ ↲ ┆b0┆┆a1┆2.6 Comments↲ ↲ Comments may be inserted in a source program in three forms:↲ ↲ 1. (* comment *)↲ ┆84┆All characters between the delimiters (* and *) are part ↓ ┆19┆┆83┆┄┄of the comment, including any non-printing characters.↲ ↲ 2. <* comment *>↲ ┆84┆All characters between the delimiters <* and *> are part ↓ ┆19┆┆83┆┄┄of the comment, including any non-printing characters.↲ ↲ 3. -- comment end-of-line↲ ┆84┆All characters from the delimiter -- up to the first ↓ ┆19┆┆83┆┄┄occurence of a carriage return, line feed, or form feed ↓ ┆19┆┆83┆┄┄character are part of the comment.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆f0┆┆a1┆Examplex:↲ ↲ <* this is (* ... *) one comment *>↲ ↲ (* this is -- another↲ comment *)↲ ↲ -- a third comment↲ ↲ ↲ ┆b0┆┆a1┆2.7 Non-printing Characters↲ ↲ Non-printing characters which are not part of a comment are ↓ separators on threir own. Any Real-Time Pascal compiler ↓ should allow space, tabulation, line and form feed, and ↓ carriage return characters.↲ ↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆3. TYPES AND OBJECTS↲ ↲ An ┆a1┆object┆e1┆ is a data entity, manifest during the execution of ↓ a program as occupying some amount of memory. With one ↓ exception (irregular sub-objects of objects of a descriptive ↓ type, cf. section 3.11) an object always occupies an ↓ integral number of successive bytes of memory. The number of ↓ bytes is called the ┆a1┆size┆e1┆ of the object and the address of ↓ the lowest addressed byte is called the ┆a1┆address┆e1┆ of the ↓ object. The ┆a1┆value┆e1┆ of an object is at any given time ↓ represented by the bit pattern present in the part of memory ↓ occupied by the object. An object may be a declared, and ↓ thus named, constant, variable, or parameter, or it may be a ↓ temporary anonymous object which exists only during the ↓ evaluation of some expression or the execution of certain ↓ kinds of statements.↲ ↲ Every object has a ┆a1┆type┆e1┆. A type comprises a set of values ↓ which may be assumed by objects of the type. A number of ↓ predefined types exist as part of the language and ↓ additional types may be defined in type declarations. In ↓ particular it is possible to define structured types. ↓ Objects of structured types are composed of ┆a1┆sub-objects┆e1┆ of ↓ other (simpler) types. All objects of a type have the same ↓ size, called the size of the type.↲ ↲ Associated with a type is a set of ┆a1┆operations┆e1┆ applicable of ↓ values of the type. In the case of a structured type some of ↓ the operations provide access to the sub-objects of objects ↓ of the type.↲ ↲ An important relation between types is ┆a1┆compatibility┆e1┆ which ↓ playes a key role in determining when the assignment, ↓ explicit or by parameter passing, of a value to an object of ↓ some type is legal.↲ ↲ The structural aspects of a type are always obtainable from ↓ (the text of) the definition. However, the size of a type ↓ ┆8c┆┆83┆┆c8┆↓ may be given by expressions which in general can only be ↓ evaluated at tun-time. A type is said to be ┆a1┆established┆e1┆ when ↓ all expressions in the definition are evaluated and the ↓ actual layout of objects of the type and thus also the ↓ representation of values of the type, are determined. A type ↓ in whose definition all expressions are constant expressions ↓ and which can therefore be established at compile-time, is ↓ called a ┆a1┆static┆e1┆ type.↲ ↲ All tpes, whether explicitly specified or implicitly given ↓ by the context, are ┆a1┆classified┆e1┆ as:↲ ↲ - ordinal types,↲ - machine types,↲ - set types,↲ - pointer types,↲ - shielded types, or↲ - structured types.↲ ↲ Each class of types is described in a separate section of ↓ this chapter.↲ ↲ The language includes no "real" types. It is a simple matter ↓ to extend the language or an implementation with a class ↓ containing one or more real types.↲ ↲ Pointer types and shielded types are called ┆a1┆protected┆e1┆ types. ↓ The same is true of certain structured types, cf. section ↓ 3.9. Protected types cannot be used in conjunction with ↓ retyping (type conversion) in with statements.↲ ↲ ↲ ┆b0┆┆a1┆3.1 Specification of Types↲ ↲ Type specifications, which include type definitions, are ↓ used in type declarations, in object declarations, in with ↓ statements, and in the formal parameter lists of routine and ↓ program headings and of declarations of parameterized types. ↓ ┆8c┆┆83┆┆c8┆↓ The forms of type specification which may occur differ ↓ depending on the use.↲ ↲ The form of type specification used in type declarations is ↓ called a defining type specification. This form rules out ↓ alias types, i.e. the definition of a named type simply by ↓ reference to another (bound) type name.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The form of type specification most commenly used, e.g. in ↓ object declarations, in with statements, and in formal type ↓ parameter lists, is called a common type specification. This ↓ form covers all types with no unbound parameters.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ An augmented form of type specification is used in formal ↓ parameter lists of routines and programs where unbound ↓ parameterized types are allowed.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆e0┆↓ A type definitionis the ultimate definition of any type ↓ which is not predefined.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The form 'defined type' may be used in the specification of ↓ a type as either predefined or defined, bound, and named.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The missing details in the above description are given in ↓ the following sections:↲ ↲ ┆a1┆syntactic category section number↲ bound-type_name╞ ╞ 3.2↲ parameterized-type_name╞ ╞ 3.2↲ parameterized-type binding╞ 3.3↲ ordinal-type definition╞ ╞ 3.4↲ predifined ordinal type ╞ 3.4↲ machine type╞ ╞ ╞ 3.5↲ set-type definition╞ ╞ 3.6↲ pointer-type definition╞ ╞ 3.7↲ shielded type╞ ╞ ╞ 3.8↲ structured-type definition╞ 3.9↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆Note:↲ Of the six classes of types machine types are shielded types ↓ can only be predefined.↲ ↲ ↲ ┆b0┆┆a1┆3.2 Declaration of Types↲ ↲ Types may be named and defined in type declarations:↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The rules for defining types allow several types of use of ↓ (forward, bound, or parameterized) type names in 'defining ↓ type specifications'. However, no type name may be used on ↓ the right hand side of a 'single type declaration' until it ↓ has been introduced in a preceding declaration. In ↓ particular no type name may be used in its own 'defining ↓ type specification'.↲ ↲ A 'forward-type_name' may only be used in the definitionof ↓ pointer types and for every 'forward type_name' occurring in ↓ a 'type declaration', the same name must be given a ↓ definition (bound or parameterized) later within the ↓ declaration part of the same block.↲ ↲ ┆8c┆┆83┆┆e0┆↓ These rules exclude recursion in the definition of ↓ structured types, but allow objects of a structured type to ↓ contain pointers to objects of the same type and also allow ↓ mutual pointers between several structured types.↲ ↲ A single type declaration without parameters associates the ↓ 'bound-type_name' with the type specified on the right hand ↓ side, called ┆a1┆the defining type┆e1┆. That is, when the 'bound-↓ type_name' is itself used as a type specification, e.g. in ↓ the declaration of an object, the type thus specified ↓ inherits the value set, the representation of values, the ↓ object layout, the applicable operations and the ↓ classification of the defining type. However, the type ↓ specified by the 'bound-type_name' is ┆a1┆not┆e1┆ compatible with ↓ the defining type. An exception to the latter rule occurs ↓ when the defining type is a set type (cf. 3.10). The ↓ defining type is established when the type declaration is ↓ elaborated (cf. chapter 6).↲ ↲ A parameterized 'single type declaration' introduces the ↓ 'parameterized-type_name' as denoting a family of mutually ↓ conformant types. The 'formal type parameters', i.e. the ↓ 'type-parameter_names' may be used on the right hand side of ↓ the declaration. The types specified for formal type ↓ parameters must be ordinal types. Specification of a ↓ particular type in a parameterized family of types is ↓ described in the next section. No type is established when a ↓ parameterized type declaration is elaborated.↲ ↲ A typesize call is similar in form to a function call, but ↓ the "parameter" is the name of a type. The construct allows ↓ the size of a type to be used in computations.↲ ↲ ↲ ↲ ↲ The 'bound-type_name' must be the name of a bound (not ↓ parameterized) type. The value of a typesize call is the ↓ ┆8c┆┆83┆┆c8┆↓ size (number of bytes) of the named type as computed when ↓ the type was established. The type of a typesize call is ↓ integer.↲ ↲ ┆a1┆Example:↲ ↲ TYPE↲ ptr_type; -- forward announcement↲ bound_type=ARRAY(1..10) OF integer;↲ rec_type=RECORD -- Note:↲ f1: bound_type; -- type of f1 not compatible↲ f2: ARRAY(1..10) OF integer -- with type of f2↲ END(*RECORD*);↲ ptr_type= `rec_type;↲ mask_type= PACKED ARRAY(1..typesize(bound_type)) OF byte↲ ↲ ↲ ┆b0┆┆a1┆3.3 Parameterized Types↲ ↲ A family of parameterized types may be defined in a type ↓ declaration (see the preceding section). A particular type ↓ in such a family, called a ┆a1┆bound parameterized type┆e1┆, is ↓ obtained by binding values to the formal type parameters.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The 'parameterized-type_name' must occur in a preceding ↓ parameterized type declaration, i.e. it must denote a type ↓ family. The number of formal parameters in this declaration ↓ must equal the number of 'actual type parameters', and each ↓ ┆8c┆┆83┆┆c8┆↓ actual parameter must be assignable to the type of the ↓ corresponding formal parameter.↲ ↲ The type specified by a 'parameterized type binding' is ↓ established according to the right hand side of the ↓ parameterized type declaration, i.e. the defining type ↓ specification, after all occurrences of the formal type ↓ parameters have been replaced with the values of the ↓ corresponding actual parameters. The properties of the ↓ defining type are inherited in the same fashion as in the ↓ case of a 'bound-type_name', cf. the preceding section.↲ ↲ The actual parameter values used to establish a bound ↓ parameterized type are attached to objects of the type. The ↓ parameter values are accessible whenever the object to which ↓ they are attached is visible.↲ ↲ ↲ ↲ ↲ ↲ The type of the denoted object must be a bound parameterized ↓ type. The 'type-parameter_name' must occur among the 'formal ↓ type parameters' of this type. The type of a 'selected type ↓ parameter' is the (ordinal) type specified for the 'type-↓ parameter_name' and its value is the value of the ↓ corresponding actual parameter as evaluated when the object ↓ type was established.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆Example:↲ TYPE↲ column(rows: 1..100)= ARRAY(1..rows) OF integer;↲ matrix(rows: 1..100)= ARRAY(1..rows) OF column(rows);↲ matrix_10= matrix(10);↲ ...↲ PROCEDURE invert(a:matrix);↲ VAR↲ local_copy: matrix(a!rows);↲ ...↲ FOR i:=1 TO a!rows DO↲ ...↲ ↲ ↲ ┆b0┆┆a1┆3.4 Ordinal Types↲ ↲ Ordinal types are abstract types. For any ordinal type there ↓ exists a one-to-one mapping from the set of values of the ↓ type onto a finite interval of the integral numbers, ↓ yielding the ┆a1┆ordinal value┆e1┆ corresponding to each value of ↓ the type. It follows that the value set of an ordinal type ↓ is ordered by ordinal value and that every such value set ↓ has a first and a last element. By the ordering, every ↓ value, except the last one, has a ┆a1┆successor┆e1┆ and every value, ↓ except the first one, has a ┆a1┆predecessor┆e1┆. Similarly, the ↓ relations ┆a1┆greater than┆e1┆ and ┆a1┆smaller than┆e1┆ are defined for ↓ pairs of values by the ordering.↲ ↲ The relational operators which produce results of the ↓ predefined type boolean apply to pairs of operands of any ↓ ordinal type. i.e. the two operands must be of the same ↓ ordinal type. Let oleft and oright denote the ordinal values ↓ of left and right operand, respectively. The relational ↓ operators are then defined in the following table:↲ ↲ ╱04002d4e0a0006000000000301413100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ╱04002d4e0a00060000000003013c3100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ↓ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆operator result┆05┆┆05┆↲ =╞ true if oleft equals oright, otherwise false↲ <>╞ false if oleft equals oright, otherwise true↲ >╞ true if oleft is greater than oright, otherwise false↲ <=╞ false if oleft is greater than oright, otherwise true↲ <╞ true if oleft is smaller than oright, otherwise false↲ >=╞ false if oleft is smaller than oright, otherwise true↲ ↲ ╱04002d4e0a00060000000003013c3100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ╱04002d4e0a0006000000000301413100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ↓ For every ordinal type otype, there exist theree predefined ↓ functions as described below:↲ ↲ FUNCTION succ(v: otype): otype↲ The result of a call of succ is the successor of the value ↓ of the parameter v, except if this value is the last one, in ↓ which case the call causes a fault.↲ ↲ FUNCTION pred(v: otype): otype↲ The result of a call of pred is the predecessor of the value ↓ of the parameter v, except if this value is the first one, ↓ in which case the call causes a fault.↲ ↲ FUNCTION ord(v: otype): integer↲ The result of a call of ord is the ordinal value ↓ corresponding to the value of the parameter v.↲ ↲ There are three predefined ordinal types and two ways to ↓ define new ordinal types. These are described in detail in ↓ the following subsections.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆3.4.1 The Type Boolean↲ ↲ The type boolean has two values which correspond to truth ↓ values and are denoted by the predefined value names ┆a1┆false┆e1┆ ↓ and ┆a1┆true┆e1┆. The ordinal values are: ord(false)=0 and ↓ ord(true)=1.↲ ↲ There are two dyadic operators which take boolean operands ↓ and produce a boolean result: AND and OR. There is one ↓ monadic operator which takes a boolean operand and produces ↓ a boolean result: NOT. The results produced by these ↓ operators are in accordance with standard logical truth ↓ tables for conjunction, disjunction and negation, ↓ respectively. In addition the dyadic operator XOR is ↓ provided for boolean operands. Its result, which is also ↓ boolean, is defined by the formula↲ b1 XOR b2=(b1 AND NOT b2) OR (NOT b1 AND b2).↲ ↲ ↲ ┆b0┆┆a1┆3.4.2 The Type Char↲ ↲ the values of type char are characters belonging to a ↓ character set derived from ISO-646 (3), i.e. an ASCII-like ↓ character code set.↲ ↲ The ordinal values of the type char span the interval ↓ 0..255. The characters with the ordinal values 0..32 are ↓ denoted by the predefined value names NUL, SOH, STX, ETX, ↓ EOT, ENQ, ACK, BEL, BS, HT, LF, VT, FF, CR, SO, SI, DLE, ↓ DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC, FS, ↓ GS, RS, US, SP. The character with the ordinal value 127 is ↓ denoted by the predefined value name DEL. The characters ↓ with ordinal values in the range 32..126 are graphic ↓ charcters and are denoted by character literals, i.e. the ↓ graphic symbol (letter, digit etc.) in question, between ↓ single quotes. The set of available graphic characters and ↓ the corresponding ordinal values is implementation and/or ↓ installation dependent. No notation exists for characters ↓ with ordinal values in the range 128..255.↲ ↲ ┆8c┆┆83┆┆e0┆↓ The graphic character symbols supported by an ↓ implementation/installation may also be used in character ↓ strings (cf. subsection 3.9.4).↲ ↲ There exists a predefined function which yields a character ↓ result:↲ ↲ FUNCTION chr(n: 0..255): char↲ The result of a call of chr is the character whose ordinal ↓ value equals the value of the parameter n.↲ ↲ ┆a1┆Example:↲ CONST single_quote=''';↲ TYPE small_letter='a'..'z'↲ ↲ ↲ ┆b0┆┆a1┆3.4.3 The Type Integer↲ ↲ The values of type inteer are integral numbers. The ordinal ↓ value of such a number is the number itself. The range of ↓ the type integer, i.e. the interval spanned by its values is ↓ implementation dependent. Positive integer values are ↓ denoted by integer numbers, cf. section 2.4.↲ ↲ There are five dyadic operators which take integer operands ↓ and produce integer results:↲ ↲ ┆a1┆operator description┆05┆↲ +╞ addition↲ - subtraction↲ * multiplication↲ DIV integer division (quotient truncated toward zero)↲ MOD remainder of integer division, i.e.↲ a MOD b = a-b*(a DIV b)↲ ↲ + and - may also be used as monadic operators, implying an ↓ implicit left operand with value 0. When the result produced ↓ by an arithmetic operation falls outside the range of ↓ ┆8c┆┆83┆┆c8┆↓ integer values supported by the implementation a fault ↓ occurs.↲ ↲ The result of the predefined function abs:↲ ↲ FUNCTION abs(n: integer): 0..maxint↲ is the absolute value of the parameter value. If this value ↓ falls outside the supported range the call causes a fault.↲ ↲ The predefined value names maxint and minint denote the ↓ largest and the smallest integer value, respectively, ↓ supported by the implementation.↲ ↲ ↲ ┆b0┆┆a1┆3.4.4 Enumeration Types↲ ↲ An enumeration type is defined by explicitly naming its ↓ values:↲ ↲ ↲ ↲ ↲ ↲ The names given int he definition are used to denote the ↓ values of the type thus defined. Consider an enumeration ↓ type defined as (e┆82┆0┆81┆, e┆82┆1┆81┆, ..., e┆82┆n┆81┆). This type has precisely ↓ n+1 distinct values with ordinal values in the interval ↓ 0..n. The ordinal value corresponding to e┆82┆i┆81┆ is i, for ↓ i=0,1,...,n.↲ ↲ ┆a1┆Example:↲ TYPE colours= (red, blue, green, yellow, pink)↲ ↲ ↲ ┆b0┆┆a1┆3.4.5 Subrange Types↲ ↲ a subrange specifies a type compatible with an existing ↓ type, but with a constrained range of values:↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆84┆┆84┆↓ The lower and upper bound expressions must be of the same ↓ ordinal type, called the ┆a1┆base type┆e1┆ of the defined subrange ↓ type. The bounds are evaluated when the subrange type is ↓ established.↲ ↲ The number of elements in the value set of the subrange is ↓ ord(upper bound)-ord(lower bound)+1. the number may be zero ↓ in which case the subrange is empty, but it may not be ↓ negative. In the latter case a fault occurs.↲ ↲ The same set of operators and predefined functions apply to ↓ values of the subrange type as to values of the base type, ↓ but objects of the subrange type are constrained to assume ↓ values in the range between the lower and upper bound values ↓ (inclusively).↲ ↲ ┆a1┆Note┆e1┆:↲ A subrange definition is the only place where an expression ↓ can occur in a type definition. Thus all dynamic types are ↓ built from subranges. Conversely, if all expressions in the ↓ subrange definitions of a type definition are constant ↓ expressions, then the defined type is static.↲ ↲ ┆a1┆Example┆e1┆:↲ TYPE↲ pos_int= 0..maxint;↲ neg_int= minint..-1;↲ codes= (nocode, ..., dummy_last_code);↲ ╱04002d4e0a0006000000000301443100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ╱04002d4e0a00060000000003013c3100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ↓ conv_table= ARRAY(succ(nocode)..pred(dummy_last_code)) OF codes↲ ╱04002d4e0a00060000000003013c3100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ╱04002d4e0a0006000000000301443100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ↓ ↲ ↲ ┆b0┆┆a1┆3.5 Machine Types↲ ↲ Machine types allow a style of programming in which the ↓ machine instructions to be executed are specified in a very ↓ direct manner.↲ ↲ ┆8c┆┆83┆┆bc┆↓ Only predefined machine types exist. The repertoire of ↓ machine types depends on the implementation. However, tye ↓ types ┆a1┆byte┆e1┆ (8-bit quantity) and ┆a1┆word┆e1┆ (16-bit quantity) are ↓ mandatory.↲ ↲ Values of machine types are denoted by numbers with a radix ↓ specification, cf. section 2.4.↲ ↲ The operators applicable to machine types are intended to ↓ translate directly into machine instructions. Machine ↓ dependent extensions may therefore occur. The following ↓ operators are mandatory:↲ ↲ ┆8c┆┆81┆┆9c┆↓ ┆0e┆↓ ┆a1┆operator left op. right op. result description┆05┆↲ +╞ byte byte byte unsigned addition↲ + word byte word unsigned addition↲ + byte┆07┆ word word unsigned addition↲ +╞ word┆07┆ word word unsigned addition↲ - byte byte byte unsigned subtraction↲ - word byte word unsigned subtraction↲ - byte word word unsigned subtraction↲ - word word word unsigned subtraction↲ * byte byte word unsigned multiplication↲ * word byte word unsigned multiplication↲ * byte word word unsigned multiplication↲ * word word word unsigned multiplication↲ DIV byte byte byte unsigned division↲ DIV word byte word unsigned division↲ DIV byte word byte unsigned division↲ DIV word word word unsigned division↲ MOD byte byte byte unsigned remainder↲ MOD word byte word unsigned remainder↲ MOD byte word byte unsigned remainder↲ MOD word word word unsigned remainder↲ AND byte byte byte bitwise logical and↲ AND word word word bitwise logical and↲ OR byte byte byte bitwise logical or↲ OR word word word bitwise logical or↲ XOR byte byte byte bitwise exclusive or↲ XOR word word word bitwise exclusive or↲ NOT none byte byte bitwise negation↲ NOT none word word bitwise negation↲ SHIFT byte integer byte logical shift toward more↲ SHIFT word integer word significant positions↲ ┆0f┆↓ ↲ For arithemtic operations values of machine types are ↓ treated as unsigned binary numbers. There is no checking for ↓ overrun, however division by zero (DIV or MOD) will cause a ↓ fault.↲ ↲ ┆8c┆┆83┆┆bc┆↓ There are predefined procedures to increment and decrement ↓ variables of machine types (by 1, modulo 2┆81┆n┆82┆, where n is the ↓ number of bits used for the type):↲ ↲ PROCEDURE inc(VAR v: mtype)↲ PROCEDURE dec(VAR v: mtype)↲ where mtype may be any machine type.↲ ↲ Also for every machine type mtype there is a predefined ↓ function:↲ ↲ FUNCTION int(v: mtype): integer↲ which yields the (implementation dependent) value obtained ↓ by extending (by zero bits) or truncating the value of the ↓ parameter v to the number of bits used to represent integers ↓ and then interpreting the resulting bit pattern as an ↓ integer value.↲ ↲ The inverse functions are also predefined:↲ ↲ FUNCTION byt (v: integer): byte↲ A call of byt extracts the 8 least significant bits from the ↓ (implementation dependent) integer representation.↲ ↲ FUNCTION wrd (v: integer): word↲ A call of wrd extracts the 16 least significant bits from ↓ the (implementation dependent) integer representation.↲ ↲ Moreover, two values of the same machine type may be ↓ compared, using the relational operators which are described ↓ in section 3.4. Comparison applies to the unsigned binary ↓ values.↲ ↲ ↲ ┆b0┆┆a1┆3.6 Set Types↲ ↲ The set of values of a set type is the power set of the set ↓ of values of some ordinal type, called the element type of ↓ ┆8c┆┆83┆┆c8┆↓ the set type. The available operators for sets correspond to ↓ the standard operators of mathematical set theory.↲ ↲ ↲ ↲ ↲ ↲ The common type specification specifies the element type ↓ which must be an ordinal type.↲ ↲ Values of set types are denoted by lists of set elements.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ All expressions occurring in a 'set denotation' must be of ↓ the same ordinal type. The type of the 'set denotation' is a ↓ set type whose element type is the type of the expressions.↲ ↲ The value of a 'set denotation' is evaluated by evaluating ↓ all the expressions. Their values determine the members of ↓ the set value. When an 'element interval' occurs all values ↓ in the closed interval from the value of 'lower_expression' ↓ to the value of 'uipper_expression' are members. If the ↓ value of 'lower-expression' is greater than the value of ↓ 'upper-expression' the interval is empty.↲ ↲ When no expressions are present in a 'set denotation', i.e. ↓ (..), the value is the empty set. The empty set may occur ↓ whereever an operator of a set type is required. Occurring ↓ as an expression on its own, the empty set is assignable to ↓ any set type.↲ ↲ ┆8c┆┆83┆┆e0┆↓ The operators applicable to values of set types are ↓ described in the following table, where st means some set ↓ type, et means the element type of st, lop means left ↓ operand, and rop means right operand. Notice that multiple ↓ occurrences of st in any one line of the table refer to ↓ compatible set types.↲ ┆0e┆↓ ↲ oper- type of type of type of ↲ ┆a1┆ator lop rop result result┆05┆↲ + st st st lop rop↲ * st st st lop rop↲ - st st st lop rop↲ IN et st boolean true if lop rop,↲ ╞ ╞ ╞ false otherwise↲ <= st st boolean true if lop rop↲ ╞ ╞ ╞ ╞ false otherwise↲ >= st st boolean true if rop lop,↲ ╞ ╞ ╞ ╞ false otherwise↲ = st st boolean true if lop rop↲ ╞ ╞ ╞ ╞ and rop lop,↲ ╞ ╞ ╞ ╞ false otherwise↲ <> st st boolean NOT lop=rop↲ ┆0f┆↓ ↲ ┆a1┆Note:↲ There is no operator to test for strong set inclusion.↲ ↲ ┆a1┆Examples:↲ digits= (. '0'..'9' .)↲ letters= (. 'a'..'z', 'A'..'Z' .)↲ ↲ ↲ ┆b0┆┆a1┆3.7 Pointer Types↲ ↲ The values of a pointer type are NIL (no pointer) and ↓ pointers to heap-allocated variables of a specified type, ↓ called the base type of the pointer type. A pointer may be ↓ used to access the variable it points to.↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆ec┆↓ The common type specification specifies the base type of the ↓ defined pointer type. The initial value of a pointer ↓ variable is NIL, i.e. it does not point to any variable.↲ ↲ A variable accessed through a pointer is called a designated ↓ variable.↲ ↲ ↲ ↲ ↲ The type of the denoted object must be a pointer type. The ↓ type of the designated variable is the base type of this ↓ pointer type. If the value of the denoted pointer object is ↓ NIL a fault occurs when an attempt is made to access the ↓ designated variable.↲ ↲ The comparison operators = and <> may be applied to pairs of ↓ operands of compatible pointer types. The result produced by ↓ the = operator is true if both pointers designate the same ↓ object, or if both have value NIL. Otherwise it is false. ↓ The result produced by the <> operator is the negation of ↓ the result of =.↲ ↲ There is a predefined function to test whether a pointer, of ↓ any pointer type ptrtype, is NIL.↲ ↲ FUNCTION nil(ptr: ptrtype): boolean↲ The result of a call of nil is true if the value of the ↓ parameter is NIL and false otherwise.↲ ↲ A variable is allocated on the heap and a pointer to it ↓ assigned to a pointer variable by a call of the predefined ↓ procedure new, where the parameter type ptrtype may be any ↓ pointer type.↲ ↲ PROCEDURE new(VAR ptr: ptrtype)↲ A call of new causes memory for a variable of the base type ↓ of the type of the parameter ptr to be allocated on the heap ↓ ┆8c┆┆83┆┆c8┆↓ of the calling process. If an initial value is defined for ↓ the variable or any components of it, the initialization ↓ takes place immediately after allocation. The value of the ↓ parameter becomes a pointer to the allocated variable.↲ ↲ ┆a1┆Example:↲ TYPE↲ comp; comp1_type; -- forward declarations↲ comp1_type= RECORD↲ number: integer;↲ comp1_chain: `comp1_type;↲ comp_chain: `comp↲ END(*RECORD*);↲ comp= ARRAY(x..y) OF `comp1_type;↲ VAR↲ structure_start: `comp;↲ ...↲ new(structure_start);↲ new(structure_start`(X));↲ new(structure_start`(x)`.comp1_chain)↲ ...↲ ↲ ↲ ┆b0┆┆a1┆3.8 Shielded Types↲ ↲ Shielded types are used in conjunction with control of ↓ offspring processes and with inter-process and inter-module ↓ communication. In order that the integrity of buffers and of ↓ the data structures needed to administer muliple cooperating ↓ processes be preserved it is only possible to manipulate ↓ objects of shielded types by means of predefined routines. ↓ Accordingly, details of the representation of these types ↓ are not part of the reference definition of the language. ↓ Only predefined shielded types exist, six in all.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆84┆┆84┆↓ Constants of shielded types do not exist. Variables of ↓ shielded types, except reference, can only be declared at ↓ the outer block level of a program, cf. subsection 6.2.1.↲ ↲ An object of type process may be used to control a child ↓ process, i.e. an incarnation of a sub-program. The value of ↓ a process object is either NIL or a reference to a child ↓ process, the initial value being NIL. Process objects may be ↓ manipulated by the predefined routines create, start, stop ↓ and remove, as described in chapter 9.↲ ↲ The predefined function nil may be used to test whether a ↓ process variable has value NIL.↲ ↲ FUNCTION nil(VAR pr: process): boolean↲ The result of a call of nil is true if the value of the ↓ parameter pr is NIL, and false otherwise.↲ ↲ An object of type mailbox may be used to transfer access to ↓ a buffer stack from one process to another, using the ↓ predefined routines signal, wait and return, as described in ↓ chapter 9. The initial state of a mailbox is passive.↲ ↲ An object of type port may be used in conjunction with ↓ intermodule communication as described in chapter 11. The ↓ initial state of a port is closed.↲ ↲ Buffers are allocated using pools and accessed by means of ↓ objects of type reference. The value of a reference to a ↓ buffer stack, called the ┆a1┆designated stack┆e1┆. The top buffer of ↓ the designated stack is called the ┆a1┆designated buffer┆e1┆. Buffer ↓ stacks, and the predefined procedures push and pop working ↓ on them, are described in detail in chapter 10.↲ ↲ The predefined function nil may be used to test whether a ↓ reference is NIL.↲ ↲ FUNCTION nil(VAR ref: reference): boolean↲ ┆8c┆┆83┆┆c8┆↓ The result of a call of nil is true if the value of ref is ↓ NIL, and false otherwise.↲ ↲ Every buffer has fourteen attributes which are present even ↓ if the buffer is empty:↲ ↲ - home pool: the pool to which the buffer belongs,↲ - ┆84┆return address: mailbox to which the buffer may be ↓ ┆19┆┆82┆┄┄returned,↲ - ┆84┆u1, u2, u3, u4: objects of type 0..255 which may be read ↓ ┆19┆┆82┆┄┄and written,↲ - size of the buffer, i.e. number of bytes,↲ - ┆84┆offset, top, byte count: objects of type 0..maxint which ↓ ┆19┆┆82┆┄┄may be read and written; they describe the data area of ↓ ┆19┆┆82┆┄┄the buffer, see below,↲ - ┆84┆event kind: indicates how and why the buffer was placed in ↓ ┆19┆┆82┆┄┄the mailbox from which it has last been received or that ↓ ┆19┆┆82┆┄┄the buffer was removed from a pool; see details under the ↓ ┆19┆┆82┆┄┄predefined function eventkind below,↲ - ┆84┆connection index, credit count, reason: used in ↓ ┆19┆┆82┆┄┄conjunction with IMC functions, cf. chapter 11.↲ ↲ The values of the buffer attributes offset and top define an ↓ area within the buffer, called the ┆a1┆data area┆e1┆, which ↓ comprises the (byte) locations from offset through top-1 ↓ relative to the beginning of the buffer.↲ ↲ ╞ buffer↲ ╞ ┆a1┆ ↲ ┆a1┆! ! data area ! !↲ offset top↲ ↲ The byte count attribute is used to indicate the size of a ↓ unit of data which is located from the beginning of the data ↓ area, but which does not necessarily occupy the whole data ↓ area.↲ ↲ ┆8c┆┆83┆┆bc┆↓ In order for the data area description to be consistent, ↓ offset must be less thanor equal to top, which in turn must ↓ be less than or equal to the size of the buffer. In ↓ particular, if the buffer is empty, all three attributes ↓ must be zero.↲ ↲ In a buffer stack the size and data area description ↓ attributes of the top buffer will refer to the top non-empty ↓ buffer, cf. section 10.1.↲ ↲ The concept of data area is used in conjunction with the IMC ↓ functions, cf. chapter 11, and is also intended as a basis ↓ for the establishment of practical conventions for the use ↓ of the language.↲ ↲ FUNCTION releasepool)VAR p: pool;↲ no_of_bufs: 1..maxint): 0..maxint↲ ↲ The number of buffers indicated by the value of no_of_bufs ↓ are released from the pool p and become free memory. If the ↓ requested number of buffers is not present in the pool fewer ↓ buffers may be released. The actual number of released ↓ buffersis returned as the result of the function call.↲ ↲ A buffer is taken out from a pool by a call of the ↓ predefined procedure getbuf:↲ ↲ PROCEDURE getbuf(VAR p: pool; VAR ra: mailbox; VAR r: ↓ reference)↲ ↲ At the time of call the value of the parameter r must be ↓ NIL, otherwise a fault occurs. If the pool p is empty, i.e. ↓ all buffers have been removed, the calling process will wait ↓ until a buffer becomes available. This occurs when a buffer ↓ is put back to the pool by another process (call of putbuf, ↓ see below), or when additional memory is allocated for the ↓ pool (call of allocpool, see above). When severalprocesses ↓ attempt to take out buffers from an empty pool waiting takes ↓ place in a FIFO queue.↲ ↲ ┆8c┆┆83┆┆e0┆↓ When a buffer i available it is removed from the pool, its ↓ return address becomes the mailbox indicated by the ↓ parameter ra, and r will designate a buffer stack consisting ↓ only of the removed buffer.↲ ↲ When a buffer has just been removed from its home pool its ↓ data area will be the whole buffer, i.e. offset=zero and ↓ top=size of the buffer. The attributes u1, u2, u3, u4 and ↓ byte count will all be zero. The value of the event kind ↓ attribute will be not_event, indicating the buffer does not ↓ represent a system event.↲ ↲ It is possible to specify a maximum time which a process is ↓ willing to wait for a buffer. This can be done by calling ↓ getbufdelay instead of getbuf, cf. subsection 9.2.2.↲ ↲ A buffer is put back in its home pool by a call of the ↓ predefined procedure putbuf:↲ ↲ PROCEDRUE putbuf(VAR r: reference)↲ At the time of call the parameter must not be locked (cf. ↓ section 5.9), and its value must not be NIL, nor may the ↓ designated stack contain more than one buffer; otherwise a ↓ fault occurs. The buffer is put back in its home pool, and ↓ the value of r becomes NIL.↲ ↲ It can be tested whether a buffer belongs to a particular ↓ pool.↲ ↲ FUNCTION hometest(VAR p: pool; VAR ref: reference): boolean ↓ The value of ref must not be NIL when hometest is called. If ↓ it is, a fault occurs. The result of a call of hometest is ↓ true if p is the home pool of the buffer designated by ref, ↓ otherwise it is false.↲ ↲ The event kind attribute of a buffer may be read in order to ↓ determine the kind of event which the buffer represents.↲ ↲ ┆8c┆┆83┆┆c8┆↓ FUNCTION eventkind(VAR r: reference): event_type↲ ↲ If eventkind is called with a parameter with value NIL a ↓ fault occurs, otherwise the result is the value of the event ↓ kind attribute of the designated buffer. The result type is ↓ the predefined enumeration type↲ ↲ event_type=(not_event, message_event, answer_event↲ ╞ ╞ process_removed, port_closed, disconnected,↲ ╞ ╞ letter_sent, letter_arrived, local_connect,↲ ╞ ╞ remote_connect, reset_indication, ↓ ╞ ╞ reset_completion, credit, data_sent, ↲ ╞ ╞ data_arrived, data_overrun, dummy_letter,↲ ╞ ╞ dummy_lcnct, dummy_rcnct, dummy_rindic,↲ ╞ ╞ dummy_rcmpl, dummy_credit, dummy_sent,↲ ╞ ╞ dummy_arrived).↲ ↲ The value not_event indicates the buffer thas been obtained ↓ from a pool or its event kind has been reset. The value ↓ message_event indicates the buffer has been signalled from a ↓ process, cf. subsection 9.2.2. The value answer_event ↓ indicates the buffer has been returned by a process, cf. ↓ subsection 9.2.2. The value process_removed indicates the ↓ buffer has been returned from a process which was removed, ↓ cf. section 9.1. The remaining values indicate IMC events, ↓ cf. chapter 11.↲ ↲ The only way a process can modify the event kind attribute ↓ of a buffer while retaining access is by resetting it.↲ ↲ PROCEDURE resetevent(VAR r: reference)↲ ↲ If resetevent is called with a parameter with value NIL a ↓ fault occurs, otherwise the value of the event kind ↓ attribute of the designated buffer becomes not_event.↲ ↲ The u-attributes of a buffer may be read using the following ↓ four predefined functions:↲ ↲ ┆8c┆┆83┆┆d4┆↓ FUNCTION u1(VAR r: reference): 0..255↲ FUNCTION u2(VAR r: reference): 0..255↲ FUNCTION u3(VAR r: reference): 0..255↲ FUNCTION u4(VAR r: reference): 0..255↲ ↲ If one of these functions is called with a parameter with ↓ value NIL a fault occurs. Otherwise the result is the ↓ indicated u-attribute of the designated buffer.↲ ↲ The size of a buffer may be read using the predefined ↓ function bufsize:↲ ↲ FUNCTION bufsize(VAR r: reference): 0..maxint↲ If bufsize is called with a parameter with value NIL a fault ↓ occurs. Otherwise the size of the designated buffer is ↓ returned as result.↲ ↲ The following six predefined routines may be used to read ↓ and set the values of the attributes offset, top and byte ↓ count.↲ ↲ FUNCTION offset(VAR r: reference): 0..maxint↲ FUNCTION top(VAR r: reference): 0..maxint↲ FUNCTION bytecount(VAR r: reference): 0..maxint↲ ↲ If one of these three functions is called with a parameter ↓ with value NIL a fault occurs. Otherwise the result is the ↓ value of the indicated attribute of the designated buffer.↲ ↲ PROCEDURE setooset(VAR r: reference; val: 0..maxint)↲ PROCEDURE settop(VAR r: reference; val. 0..maxint)↲ PROCEDURE setbytecount(VAR r: reference; val. 0..maxint)↲ ↲ If one of these three functions is called with a reference ↓ parameter with value NIL a fault occurs. Otherwise the value ↓ of the val parameter is assigned to that attribute of the ↓ designated buffer which is indicated by the procedure name.↲ ↲ ┆8c┆┆83┆┆c8┆↓ Chain (linked lists) of buffer stacks may be built and ↓ manipulated by means of objects of the types reference and ↓ chain and the predefined routines chaininsert, chainextract, ↓ chainup, chaindown, chainstart, chainreset and described in ↓ section 10.2. A chain object serves as a handle to such a ↓ list. Access to a list cannot be transferred via a mailbox.↲ ↲ The routines eventkind, resetevent, u1, u2, u3, u4, setu1, ↓ setu2, setu3, setu4, bufsize, offset, top, bytecount, ↓ setoffset, settop, and setbytecount may also be called with ↓ a parameter of type chain instead of reference. In this ↓ case the relevant attribute of the current buffer is ↓ accessed. The chain must not be empty; if so a fault occurs.↲ ↲ ↲ ┆b0┆┆a1┆3.9 Structured Types↲ ↲ An object of a structured type is a structured collection of ↓ subobjects of other (simpler) types. The value of such an ↓ object is a structured collection of values of the sub-↓ objects. Structures may be arbitrarily deep, i.e. sub-↓ objects of a structured object may themselves be of ↓ structured types. The typesof the subobjects of objects of a ↓ structurted type are called the ┆a1┆constituent types┆e1┆. Sub-↓ objects which are not of structured types are called ↓ ┆a1┆components┆e1┆. The total set of components of a structured ↓ object are: those sub-objects which are themselves ↓ components plus the components of the remaining sub-objects.↲ ↲ If any component type of a structured type is protected ↓ (pointer or shielded) the structured tye is also said to be ↓ protected.↲ ↲ The comparison operators = and <> may be applied to pairs of ↓ operands of the same structured type, provided they apply to ↓ all components. The result produced by the = operator is ↓ true if all component values are pairwise equal, otherwise ↓ false. The result prodcued by <> is just the opposite, i.e. ↓ true if any pair of component values are not equal.↲ ↲ ┆8c┆┆83┆┆e0┆↓ A structure type is an array type or a record type, ↓ depending on the way it is built.↲ ↲ ↲ ↲ ↲ ↲ If the keyword PACKED is present the defined type is called ↓ a packed type. objects of the type are also called packed. ↓ Packed types constitute a sub-class of the class of ↓ structured types. Packing indicates that the code generated ↓ by a compiler to access objects of the defined type should ↓ be optimized for compactness of object representation rather ↓ than execution time. An important sub-class of packed types ↓ is the descriptive types, cf. section 3.11.↲ ↲ A packed object may contain components which either do not ↓ start on a byte boundary or do not occupy a multiple of 8 ↓ bits (or both). Such a component is called an irregular ↓ object. It may not be used for retyping in a with statement ↓ (cf. section 5.8) or as an actual parameter to be ↓ transferred by address (cf. section 6.2).↲ ↲ Array and record types are described in the following two ↓ subsections.↲ ↲ ┆a1┆Note:↲ Unless a packed type is descriptive, cf. section 3.11, the ↓ precise effect of packing is not defined. In particular, if ↓ the type has constituent types which are not static, packing ↓ cannot be expected to have any effect.↲ ↲ ↲ ┆b0┆┆a1┆3.9.1 Array Types↲ ↲ The sub-objects of an array are called elements. The ↓ elements are organized by indexing.↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆ec┆↓ The type specified between the parantheses is called the ↓ index type. It must be an ordinal type. All elements of an ↓ object of the defined array type are of the type specified ↓ following OF, called the element type. Every object of the ↓ array type has precisely one element associated with each ↓ value of the index type.↲ ↲ The syntax ARRAY(t┆82┆1┆81┆, t┆82┆2┆81┆, ..., t┆82┆n┆81┆) OF element_type↲ is permissible as shorthand for↲ ARRAY(t┆82┆1┆81┆) OF ARRAY(t┆82┆2┆81┆) OF ... ARRAY(t┆82┆n┆81┆) OF element_type.↲ Similarly PACKED ARRAY(T┆82┆1┆81┆, t┆82┆2┆81┆, ..., t┆82┆n┆81┆) OF element_type↲ is legal shorthand for PACKED ARRAY(t┆82┆1┆81┆) OF PACKED ARRAY(t┆82┆2┆81┆) ↓ OF ... PACKED ARRAY(t┆82┆n┆81┆) OF element type.↲ ↲ The elements of an array object are accessed by indexing.↲ ↲ ↲ ↲ ↲ The type of the denoted object must be an array type. The ↓ index expression must be assignable to the index type of ↓ this type. It is evaluated when access is made to the ↓ indexed element. the indexed element is that element of the ↓ array object whichis associated with the value of the ↓ expression. The type of the indexed element is the element ↓ type of the array type.↲ ↲ The syntax a(i┆82┆1┆81┆, i┆82┆2┆81┆, ..., i┆82┆n┆81┆), where a denotes an array ↓ object, is permissible as shorthand for a(i┆82┆1)(i┆82┆2) ... (i┆82┆n┆81┆).↲ ↲ ┆a1┆Note:↲ The above description implies that in general a range check ↓ is performed when an array element is accessed by indexing. ↓ A compiler may optionally allow index checking to be ↓ suppressed.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆Example┆e1┆: (cf. section 3.3)↲ VAR↲ amatrix: matrix_10;↲ temp_column: column(10);↲ ...↲ temp_column:=amatrix(i); -- assignment of complete column↲ amatrix(i,j):=amatrix(j,i); -- single component↲ ...↲ ↲ ↲ ┆b0┆┆a1┆3.9.2 Record Types↲ ↲ The sub-objects of a record are called fields. The fields ↓ are organized by naming.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ All the field names in a record type definition must be ↓ dcistinct. Each field name introduces and identifies a ↓ field. The type of the field, called the field type, is ↓ specified by the common type specification following :. A ↓ field type may not be specified by an 'enumeration-type ↓ definition'.↲ ↲ The fields of a record are accessed by selection by name.↲ ↲ ↲ ↲ ↲ The tye of the denoted object must be a record type. The ↓ field name must occur in the definitionof the record type. ↓ The selected field is that field of the record object which ↓ is identified by the field name. Its type is the specified ↓ field type.↲ ↲ ┆8c┆┆83┆┆d4┆↓ An abbreviated syntax for field access may be used in with ↓ statements, cf. section 5.8.↲ ↲ ┆a1┆Example:↲ VAR↲ rec: RECORD↲ f1,f2: integer;↲ ╞ f3: boolean↲ END(*RECORD*);↲ ...↲ rec.f1:=rec.f1+rec.f2↲ or↲ WITH rec DO f1:=f1+f2↲ ↲ ↲ ┆b0┆┆a1┆3.9.3 Notation for Values of Structured Types↲ ↲ Values of a structured type may be denoted by lists of ↓ element or field values.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The 'bound-type_name' or 'parameterized type binding' ↓ specifies the type of the structured value, which must be a ↓ structured type. The construct between (: and :) is ↓ evaluated to a list of values, by evaluating the expressions ↓ in the order of occurrence. If the type is specified by a ↓ 'parameterized tye binding' it is established before the ↓ value list is evaluated.↲ ↲ ┆8c┆┆83┆┆c8┆↓ If the structured type is an array type the values in the ↓ list are the element values in index order. The number of ↓ values must equal the number of elements and the type of ↓ each value must be assignable to the element type; otherwise ↓ a fault occurs. a 'repeated value', if present, is ↓ equivalent to a number ofrepeated occurrences of its ↓ 'value_expression'; however, the expression is only ↓ evaluated once. the number is given by the ordinal value ↓ corresponding to the value of the 'repetition_expression' ↓ which must be a non-negative integer. if the number is ↓ negative a fault occurs.↲ ↲ If the structured type is a record type the values in ↓ thelist are the field values in the order in which the field ↓ names occur in the definition of the record type. The number ↓ of values must equal the number of fields and the type of ↓ each value must be assignable to the corresponding field ↓ type; otherwise a fault occurs. If the record type contains ↓ unused fields (cf. section 3.11) no value should be given ↓ for these. They are implicitly set to value zero. In the ↓ case of a record type a 'repeated value' must not occur.↲ ↲ The type specification may be omitted when the type it ↓ specifies can be inferred from the context, i.e. in the ↓ following two situations:↲ ↲ 1. ┆84┆The 'structured value' occurs as a 'value_expression' ↓ ┆19┆┆83┆┄┄within a larger 'structured value'↲ ↲ 2. ┆84┆The 'structured value' occurs as an ↓ ┆19┆┆83┆┄┄'initialization_expression' in a variable declaration.↲ ↲ ┆a1┆Example┆e1┆: (cf. section 3.3)↲ CONST↲ identify_3=matrix_3(:(:1,0,0:), (:0,1,1:), (:0,0,1:):);↲ nul_list= list(:length***0:);↲ VAR↲ a4: matrix(4):= (:4***(:4***0:):); -- initially null↲ ↲ ↲ ┆8c┆┆83┆┆e0┆↓ ┆b0┆┆a1┆3.9.4 String Types↲ ↲ The family of one-dimensional character string (array) types ↓ is predefined:↲ ↲ string(length: 0..255)= ARRAY(1..length) OF char↲ ↲ Values of types from the string family may be denoted by ↓ character strings. A character stringis a string of graphic ↓ symbols, each representing a character value, enclosed in ↓ double quotes. The double quote character may itself be part ↓ of a character string. In this case it must be indicated by ↓ two adjacent occurrences of the " graphic symbol. Individual ↓ non-graphic characters may be included in a character string ↓ by means of the concatenation operator &.↲ ↲ The specific type of a character string, i.e. the particular ↓ member of the string family of which it denotes a value, is ↓ determined by its length, i.e. the number of characters it ↓ consists of.↲ ↲ As an implementation feature character strings may be ↓ truncated or extended with NUL characters when appropriate ↓ in the context, e.g. when occurringon the right hand side of ↓ an assignment statement where the corresponding component on ↓ the left hand side is of a string type with different ↓ length.↲ ↲ ┆a1┆Examples:↲ "this is a string"↲ "x""x" (* a string of length 3 *)↲ "*** illegal input message" & BEL & CR & LF -- string(28)↲ ↲ ↲ ┆b0┆┆a1┆3.10 Type Compatibility↲ ↲ The compatibility relations defined in this section are used ↓ to determine when a value may be assigned to an object, ↓ ┆8c┆┆83┆┆c8┆↓ either explicitly when an assignment statement is executed ↓ or implicitly in connection with parameter passing.↲ ↲ The essential relation is ┆a1┆assignment compatibility┆e1┆. However, ↓ the basis for that relation is the compatibility relation ↓ between types which is therefore defined first. The ↓ compatibility relation applies to established types.↲ ↲ Two types are said to be the same if:↲ - both are the same predefined type, or↲ - both are specified as the same bound-type_name, or↲ - ┆84┆both are specified as a binding of the same parameterized-↓ ┆19┆┆82┆┄┄type_name and the values of the actual type parameters are ↓ ┆19┆┆82┆┄┄pairwise equal.↲ ↲ Two objects are said to be of the same type if their types ↓ are the same (cf. above), if they are variables introduced ↓ in the same list of variable names, cf. subsection 3.12.2, ↓ or if they are formal parameters of kind value introduced in ↓ the same formal name list, cf. section 6.1.↲ ↲ Two types are said to be compatible if:↲ - they are the same type (cf. above), or↲ - ┆84┆one is a subrange of the other (or both are subranges of ↓ ┆19┆┆82┆┄┄the same type), or↲ - both are set types and the base types are compatible, or↲ - both are specified as `tname, where tname is a type name.↲ ↲ Type computation rules are defined for expressions (cf. ↓ chapter 4) so as to associate every expression with a type, ↓ either an explicitly specified type, or a predefined type ↓ determined implicitly by the structure of the expression. An ↓ expression exp of type t┆82┆2┆81┆ is defined to be assigment ↓ comptable with the type t┆82┆1┆81┆ if:↲ ↲ - ┆84┆t┆82┆1┆81┆ and t┆82┆2┆81┆ are compatible ordinal types and the value of ↓ ┆19┆┆82┆┄┄exp is within the range specified for t┆82┆1┆81┆, if any, or↲ ┆8c┆┆83┆┆bc┆↓ - ┆84┆t┆82┆1┆81┆ and t┆82┆2┆81┆ are compatible set types and all members of the ↓ ┆19┆┆82┆┄┄value of exp are within the range specified for t┆82┆1┆81┆, or↲ - ┆84┆t┆82┆1┆81┆ and t┆82┆2┆81┆ are compatible machine pointer, shielded, or ↓ ┆19┆┆82┆┄┄structured types, or↲ - t┆82┆1┆81┆ and t┆82┆2┆81┆ are both string types, cf. subsection 3.9.4.↲ ↲ Throughout this manual the shorthand form "assignable to" ↓ may be used instead of "assignment compatible with".↲ ↲ ┆a1┆Example:↲ In each line below the types of a and b are compatible.↲ a: boolean;╞ ╞ b: boolean;↲ a: def_type;╞ ╞ b: def_type;↲ a: param_type(7);╞ b: param_type(7);↲ a: 1..10;╞ ╞ b: 2..15;↲ a: SET OF 1..10;╞ b: SET OF 2..15;↲ a: `ptrtype;╞ ╞ b: `ptrtype;↲ ↲ ↲ ┆b0┆┆a1┆3.11 Object Layout↲ ↲ In general the definition of the language does not prescribe ↓ any specific layout for objects, and thus the way objects ↓ are laid out in memory and the way their values are ↓ represented depend on the implementation in question. In ↓ order to allow cooperation with processes whose programs are ↓ not written in Real-Time Pascal these aspects of an ↓ implementation must always be documented carefully.↲ ↲ By specifying a ┆a1┆descriptive type┆e1┆, however, it is possible ↓ within certain limits for the programmer to explicitly ↓ determine the layout of objects. Descriptive types ↓ constitute a subclass of packed types, recursively defined ↓ as having constituent types which are all either machine or ↓ static ordinal types, or themselves descriptive.↲ ↲ This definition implies that all component types of a ↓ descriptive tye are ordinal or machine types. Components of ↓ ┆8c┆┆83┆┆c8┆↓ machine types are laid out as machine bytes or words (cf. ↓ section 3.5), and the representation of ordinal type ↓ components is presently described. Notice that the ↓ description only covers sub-objects of objects of ↓ descriptive types.↲ ↲ A component of an ordinal type is represented as a binary ↓ number in a maximum of 16 bits. If the type includes ↓ negative values the two's complement representation is used. ↓ The number of bits used to represent objects of some type ↓ depends on the range of values. Let minval and maxval be the ↓ ordinal values corresponding to the first and last value of ↓ the type, respectively. Then the number of bits used for ↓ objects of the type is:↲ ↲ minval<0, maxval<0: log┆82┆2┆81┆(-minval)+1↲ minval<0, maxval>0: max log┆82┆2┆81┆(-minval), log┆82┆2┆81┆(maxval+1) +1↲ minval>0, maxval>0: log┆82┆2┆81┆(maxval+1)↲ ↲ The numbers obtained by these formulae must be rounded up to ↓ obtain integral numbers.↲ ↲ As sub-objects of an object of a descriptive type need not ↓ occupy whole bytes the total object is considerd as a ↓ bitstring rather than as a bytestring. The orderingof bits ↓ within such a bitstring is defined as follows:↲ ↲ - bits within separate bytes are ordered by byte address,↲ - ┆84┆bits within the same byte are ordered by significance, ↓ ┆19┆┆82┆┄┄i.e. least significant bits first.↲ ↲ This implies that the whole bitstring will be ordered by ↓ significance, see Fig. 2.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ bit number↲ ┆a1┆ 0 1 2 3 4 5 6 7 ↲ 0 ┆a1┆! !┆e1┆ When viewed in this fashion,↲ relative 1 ┆a1┆! !┆e1┆ i.e. the significance of bit↲ byte . ┆a1┆! !┆e1┆ i is the ith power of 2, bits↲ address . ┆a1┆! !┆e1┆ are ordered as the characters↲ n ┆b0┆┆f0┆┆a1┆! !┆e1┆ on a text page.↲ ↲ Figure 2: Bitstring ordering.↲ ↲ An ordering is also defined for the sub-objects of an object ↓ of a structured type: in the sace of an array type by index; ↓ in the case of a record type by the order of the field names ↓ in the record type definition.↲ ↲ The following simple rule defines the layout of objects of a ↓ descriptive type: within the bitstring occupied by the ↓ object subobjects are located contiguously and in order. ↓ Notice that this rule, like the definition of a descriptive ↓ type, is recursive. The following points complete the rule:↲ ↲ - ┆84┆every definition of a descriptive type is implicitly ↓ ┆19┆┆82┆┄┄extended with an unused component and the end so that ↓ ┆19┆┆82┆┄┄objects of the type occupy an integral number of bytes, if ↓ ┆19┆┆82┆┄┄this property is not already satisfied by the type as ↓ ┆19┆┆82┆┄┄stated,↲ - ┆84┆no component may cross two byte boundaries. When possible, ↓ ┆19┆┆82┆┄┄an unused component is inserted to fill up a byte so that ↓ ┆19┆┆82┆┄┄this situation is avoided.↲ ↲ An unused field of a descriptive record type may be ↓ specified explicitly in order to adjust the positioning of ↓ subsequent fields.↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆bc┆↓ An unused-specificationis equivalent to the declaration of a ↓ field of the specified type which must be a static ordinal ↓ type. The field is not accessible, i.e. it cannot be ↓ selected. Assignment to an unused field can only be made by ↓ assigning a value to the record object as a whole.↲ ↲ ┆a1┆Note:↲ If the comparison operator = and <> are applied to objects ↓ of structured types with unused components they are also ↓ applied to unused fields.↲ ↲ ┆a1┆Example:↲ Consider the types↲ rec_type= RECORD↲ a: integer;↲ b: 0..255;↲ c: 0..7;↲ d: -3..4;↲ e: -1000..1000;↲ f: char;↲ g: boolean;↲ h: integer↲ END(*RECORD:)↲ ↲ arr_type =ARRAY(1..4) OF 0..2000 (* 11 bits *)↲ ↲ Typical layouts for objects of these types are shown to the ↓ left in the figure below; note that this representation is ↓ not specified by the language. However, if the keyword ↓ PACKED had been present before RECORD/ARRAY, the types would ↓ have been descriptive and their layout prescribed to be as ↓ shown to the right.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ rec_type:↲ ┆a1┆ 0 1 2 3 4 5 6 7 ┆e1┆ ┆a1┆ 0 1 2 3 4 5 6 7 ↲ 0 ┆a1┆!┆e1┆ ┆a1┆!┆e1┆ 0 ┆a1┆!┆e1┆ ┆a1┆!↲ 1 ┆a1┆! a !┆e1┆ 1 ┆b0┆┆f0┆┆a1┆! a !↲ 2 ┆a1┆! b !┆e1┆ 2 ┆a1┆! b !↲ 3 ┆a1┆! c !┆e1┆ 3 ┆a1┆! c ! d !?!↲ 4 ┆a1┆! d !┆e1┆ 4 ┆a1┆! e-10 !↲ 5 ┆a1┆!┆e1┆ ┆a1┆!┆e1┆ 5 ┆a1┆! e-hi! f-10 !↲ 6 ┆a1┆! e !┆e1┆ 6 ┆a1┆! f-hi!g! ? !↲ 7 ┆a1┆! f !┆e1┆ 7 ┆a1┆!┆e1┆ ┆a1┆!↲ 8 ┆a1┆! g !┆e1┆ 8 ┆a1┆! h !↲ 9 ┆b0┆┆f0┆┆a1┆!┆e1┆ ┆a1┆!↲ 10 ┆a1┆! h !↲ ↲ arr_type:↲ ┆a1┆ 0 1 2 3 4 5 6 7 ┆e1┆ ┆a1┆ 0 1 2 3 4 5 6 7 ↲ 0 ┆a1┆!┆e1┆ ┆a1┆!┆e1┆ 0 ┆a1┆┆e1┆! (1┆a1┆) !↲ 1 ┆a1┆! (1) !┆e1┆ 1 ┆a1┆! !┆e1┆ ┆a1┆ !↲ 2 ┆a1┆!┆e1┆ ┆a1┆!┆e1┆ 2 ┆a1┆! (2) ! ?!↲ 3 ┆a1┆! (2) !┆e1┆ 3 ! (3┆a1┆) !↲ 4 ┆a1┆!┆e1┆ ┆a1┆!┆e1┆ 4 ┆a1┆! !┆e1┆ (4) ┆a1┆ !↲ 5 ┆a1┆! (3) !┆e1┆ 5 ┆a1┆! ! ?!↲ 6 ┆a1┆!┆e1┆ ┆a1┆!↲ 7 ┆a1┆! (4) !↲ ↲ Figure 3: Example of object layout.↲ ↲ ↲ ┆b0┆┆a1┆3.12 Object Declarations↲ ↲ Declarations of objects may occur in the declaration part of ↓ a program or routine block, cf. chapter 6.↲ ↲ An object declaration inctroduces and names an object which ↓ may be used in the remainder of the block.↲ ↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆3.12.1 Constant Declarations↲ ↲ A constant declaration serves to name a constant object, ↓ i.e. an object whose value can be computed at compile-time ↓ and which cannot be altered dynamically by assignment.↲ ↲ ↲ ↲ ↲ ↲ Each constant name introduced in a constant declaration ↓ denotes a constant object the type and value of which is ↓ determined by the expression following =. The expression ↓ must be a constant expression as described in chapter 4. The ↓ type of a constant must not be protected.↲ ↲ ↲ ┆a1┆3.12.2 Variable Declarations↲ ↲ A variable or shared declaration serves to name one or more ↓ stack-allocated private or shared variables and optionally ↓ to specify initial values for instances of such variables.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The variables introduced in a 'variable declaration' are ↓ private variables, i.e. they can only be accessed by the ↓ ┆8c┆┆83┆┆e0┆↓ process in whose stack they are allocated. The variables ↓ introduced in a 'shared declaration' are shared variables ↓ which can only be accessed in region statements.↲ ↲ The type of each variable named in a variable or shared ↓ declaration is given by the first following type ↓ specification and the initial value by the expression ↓ following :=, if present. The type of the expression must be ↓ assignable to the specified type of the variable. When ↓ several variable names are listed, separated by commas, each ↓ name introduces a variable of the specified type. The type ↓ of a shared variable must not be process, reference, or ↓ chain; nor may these types occur as component types in the ↓ types of shared variables.↲ ↲ When a variable or shared declaration is elaborated the ↓ specified types are established; memory is allocated on the ↓ stack for an instance of each of the named variables; the ↓ initialization expressions, if present, are evaluated; and ↓ the values of the expressions become initial values of the ↓ variables. An initialization expression must not contain ↓ function calls. However, the predefined functions abs, byt, ↓ chr, int, ord, pred, succ, and wrd may be used.↲ ↲ Variables of components for which initial values or states ↓ are predefined are initialized accordingly. The initial ↓ value of a variable for which an initial value is neither ↓ predefined nor specified is undefined.↲ ↲ In a structured value occurring in an initialization ↓ expression the notation ? may be used for components of ↓ protected types. This makes it possible to combine the ↓ predefined initialization of these components with an ↓ explicitly specified initialization of the remaining ↓ components.↲ ↲ A varsize call is similar in form to a function call. It ↓ allows the size of a variable to be used in computations.↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆f8┆↓ The 'variable_name' must be the name of a variable. It must ↓ have been introduced in a variable declaration. The value of ↓ a varsize call is the size (number of bytes) of the variable ↓ as computed whenits type was established. The type of a ↓ varsize call is integer.↲ ↲ ↲ ┆a1┆┆b0┆3.13 Notation for Objects and Values↲ ↲ An object which is declared or part of a (larger) declared ↓ object or accessed through a declared pointer, may be ↓ referred to by denotation.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The denoted object is said to be ┆a1┆accessed┆e1┆ when: an ↓ assignment statement in which it appears on the left hand ↓ side is executed; or the factor which it constitutes in some ↓ expression is evaluated.↲ ↲ If the 'object denotation' is an 'object_name' its type is ↓ the type of the named object as determined by its ↓ declaration. The types of the other forms of denoted objects ↓ are described in previous sections of this chapter.↲ ↲ The targetof an assignment may either be a variable object ↓ or the implicit result object associated with a function ↓ call.↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆bc┆↓ When an object denotation occurs as a variable denotationit ↓ must denote an object which is a variable or part of a ↓ variable in the stack or heap of a process, or superimposed ↓ on a buffer in a lock statement. It must not be a constant ↓ or part of a constant.↲ ↲ When a function name occurs as a variable denotation it ↓ denotes the implicitly declared result object of an ↓ activation of the function it names. A function name may be ↓ used in this fashion only in the action part of the ↓ function, i.e. not in inner blocks.↲ ↲ The type of a variable denotationis the type of the denoted ↓ object or the result type of the function, whichever ↓ applies.↲ ↲ Values which are not the values of objects or sub-objects ↓ may be used in expressions.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ A value denotation denotes the value of an anonymous object, ↓ the type and value of which is as described for the relevant ↓ one of the possible forms.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ════════════════════════════════════════════════════════════════════════ ↓ ┆14┆┆b3┆┆06┆┆0b┆↲ ┆a1┆┆b0┆4. EXPRESSIONS↲ ↲ An expression describes either an object to be addressed or ↓ some computation to be performed by applying operators and ↓ functions, predefined as well as programmer-defined, to ↓ values of objects as they are at the time of computation and ↓ to constant values which may be denoted directly in the ↓ expression.↲ ↲ The operators of the language are divided in groups with ↓ different precedence. In order of increasing precedence the ↓ groups are: relational operators, addition-type operators, ↓ multiplication-type operators, and the negation operator.↲ ↲ All operators are described in chapter 3 in conjunction with ↓ the description of the types of the operands they apply to. ↓ Some operators exist in several semantically distinct ↓ versions, applicable to different types of operands and ↓ producing results in different ways depending on the operand ↓ types, e.g. <= may be used for integer (or in general: ↓ ordinal value) comparison, as well as for set comparison ↓ (inclusion).↲ ↲ In section 4.1 reference is given, for each opeator, to all ↓ sections where a version of that operator is described. The ↓ following selection rule is used in the application of ↓ operators occurring in expressions: If the types of the ↓ operand(s) provided for an operator correspond to one of the ↓ versions of that operator, then that version of the operator ↓ is selected. Otherwise the expression is illegal. The type ↓ of the result is determined according to the description of ↓ the selected version of the operator. The result may again ↓ be used as an operand of another operator and the selection ↓ rule may then be applied repeatedly.↲ ↲ An expression which is used as an actual parameer where the ↓ kind of the corresponding formal parameter is variable, ↓ shared or inspect (cf. chapter 6) must have the form of an ↓ ┆8c┆┆83┆┆c8┆↓ 'object denotation'. Such an expressionis called an ┆a1┆object ↓ ┆19┆┄┄┆84┆expression┆e1┆. The evaluation of an object expression stops ↓ when the address of the denoted object has been computed. In ↓ all other cases the evaluation of an expression proceeds ↓ until a value has been obtained, as described in the ↓ following section.↲ ↲ ↲ ┆b0┆┆a1┆4.1 Evaluation of Expressions↲ ↲ The evaluation of an expression yields a type and a value. ↓ This section describes how the tye and value are obtained ↓ from the types and values of the parts of the expression ↓ which constitute the operands at the various stages of ↓ computation.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The expression is evaluated by evaluating the simple ↓ expression(s) in the order of occurrence. Then, if no ↓ operator is present, the type and value of the expression ↓ are the type and value of the (only) simple expression. ↓ Otherwise the appropriate version of the operator is applied ↓ to the values of the simple expressions; the result is the ↓ value of the expression, its type being boolean for all ↓ relational operators.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆84┆┆a8┆↓ A leading + or - implies an implicit left term with type ↓ integer and value 0.↲ ↲ ┆06┆versions (section)↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The evaluation of a simple expression proceeds from left to ↓ right. The leftmost term (possibly an implicit 0) is ↓ evaluated, yielding a ┆a1┆preliminary result┆e1┆. The following is ↓ then performed repeatedly:↲ ↲ The preliminary result is used as left operand of the ↓ leftmost remaining operator. The leftmost remaining term is ↓ evaluated and used as right operand. The appropriate version ↓ of the operator is then applied and produces a new ↓ preliminary result.↲ ↲ When no more operators and terms are left the simple ↓ expression has been completely evaluated; the final type and ↓ value of the preliminary result constitute the type and ↓ value of the simple expression.↲ ↲ There is one exception to the rule described above: if the ↓ left operand of the OR-operator is of type boolean and has ↓ value true, then the evaluation of the right operand is ↓ omitted; however, its type must still be boolean.↲ ↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆c8┆↓ ┆06┆version (section)↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The evaluation of a term proceeds from left to right in the ↓ same fashion as for a simple expression (i.e. substitute ↓ 'factor' for 'term' and 'term' for 'simple expression' in ↓ the above description).↲ ↲ There is one exception to the general rule: if the left ↓ operand of the AND-operator is of type boolean and has value ↓ false, then the evaluation of the right operand is omitted; ↓ however, its type must still be boolean.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The type and value of a factor are obtained as described ↓ below for each of the possible forms:↲ ↲ object denotation:↲ The value of the factor is the value of the denoted object ↓ at the time of evaluation. The type of the factor is the ↓ ┆8c┆┆83┆┆c8┆↓ type of the denoted object, except if this type is a ↓ subrange in which case the type of the factor is the base ↓ type of the subrange. If the value of the object is ↓ undefined (not initialized) the effect of evaluating the ↓ factor is not defined.↲ ↲ value denotation:↲ The type and value of the factor are the type and value of ↓ the denoted value, cf. section 3.13.↲ ↲ function call:╞ 4.2↲ typesize call:╞ 3.2↲ varsize call:╞ ╞ 3.12.2↲ link call:╞ ╞ 9.1↲ unlink call:╞ ╞ 9.1↲ create call:╞ ╞ 9.1↲ ↲ The type and value of the factor are the type and value of ↓ the call, as described in the indicated section.↲ ↲ (expression):↲ The factor is evaluated by evaluating the expression. The ↓ tye and value of the factor are the type and value of the ↓ expression.↲ ↲ NOT neg_factor:↲ the type and value of the factor are obtained by evaluating ↓ the neg_factor and applying the appropriate version of the ↓ NOT-operator to the result. The versions of the NOT-operator ↓ are described in subsection 3.4.1 and section 3.5.↲ ↲ ┆a1┆Note:↲ The precedence rules of Real-Time Pascal are those of ↓ standard Pascal which differ from the rules of other ↓ programming languages (e.g. ALGOL and PL/M languages).↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆Example:↲ As a consequence of the precedence rules the following is ↓ not a legal expression:↲ ╞ 0<x AND x<10↲ The expression should be written as:↲ ╞ (0<x) AND (x<10)↲ ↲ ↲ ┆b0┆┆a1┆4.2 Function Call↲ ↲ A function call causes a value to be computed by an ↓ activation of the indicated function.↲ ↲ ↲ ↲ ↲ ↲ The function name must be the name of a function, either ↓ predefined or programmer-defined. Evaluation of a function ↓ call takes place in two steps:↲ ↲ 1. ┆84┆The actual parameters are evaluated in the order of ↓ ┆19┆┆83┆┄┄occurrence.↲ 2. ┆84┆An activation of the block associated with the function ↓ ┆19┆┆83┆┄┄name is created and executed, cf. chapter 6.↲ ↲ The type of the function call is the result type of the ↓ function. The value of the function call is the value of the ↓ implicit result object associated with the activation of the ↓ function block when the execution of its action part ↓ terminates. If the value is undefined (no assignment) the ↓ effect of evaluating the function call is not defined.↲ ↲ ↲ ┆b0┆┆a1┆4.3 Constant Expressions↲ ↲ Constant expressions can be evaluated at compile-time. Only ↓ constant expressions may be used in constant declarations. ↓ If all expressions used in a type definition are constant ↓ expressions the type is said to be static.↲ ↲ ┆8c┆┆83┆┆ec┆↓ Constant expressions are recursively defined by the ↓ following restrictions.↲ ↲ 1. All denoted objects must be constants.↲ 2. ┆84┆Only the following (predefined) functions may be called: ↓ ┆19┆┆83┆┄┄abs, chr, int, ord, pred, succ, wrd, and byt.↲ 3. Any typesize call must name a static type.↲ 4. ┆84┆'link call', 'unlink call', and 'create call' must not ↓ ┆19┆┆83┆┄┄occur.↲ 5. Factors of set types must not occur.↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆5. STATEMENTS↲ ↲ This chapter contains subsections describing the syntax and ↓ the use of the different statements which are included in ↓ the Real Time Pascal language. Most of the statements are ↓ also found in standard Pascal and are well known language ↓ elements.↲ ↲ ↲ ┆b0┆┆a1┆5.1 Compound Statement↲ ↲ The statements of a program describe the actions which are ↓ executed by an incarnation. These statements are collected ↓ in a compound statement.↲ ↲ ↲ ↲ ↲ ↲ The statements are executed one at a time in the specified ↓ order. When all have been executed the compound statement ↓ has been completely executed or ┆a1┆exhausted┆e1┆.↲ ↲ Below, all statement forms are given together with reference ↓ to their precise decription:↲ ↲ ┆06┆section↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆84┆┆c0┆↓ ┆a1┆Note:↲ State ment may be empty.↲ ↲ ↲ ┆b0┆┆a1┆5.2 Data Transfer Statements↲ ↲ Assignment and exchange statements are the basic building ↓ blocks for other types of statements. They serve to transfer ↓ values to objects.↲ ↲ ↲ ┆b0┆┆a1┆5.2.1 Assignment Statement↲ ↲ The execution of an assignment statement causes the current ↓ value of a variable to be replaced with a new value ↓ specified by an expression. The right hand side expression ↓ must be of a type which is assignment compatible (cf. ↓ section 3.10) with the type of the variable.↲ ↲ ↲ ↲ ↲ The execution of an assignment statement takes place in four ↓ steps:↲ ↲ 1) ┆84┆The variable denotation is evaluated as an object ↓ ┆19┆┆83┆┄┄expression.↲ ↲ 2) The right hand side expression is evaluated.↲ ↲ 3) ┆84┆the run-time part of the type checking, including tests ↓ ┆19┆┆83┆┄┄for range constraints, is performed. A fault occurs if ↓ ┆19┆┆83┆┄┄some constraint is violated.↲ ↲ 4) ┆84┆The value of the expression replaces the value of the ↓ ┆19┆┆83┆┄┄variable.↲ ↲ ┆8c┆┆83┆┆bc┆↓ Assignments cannot be made to variables of shielded types or ↓ of structured types with shielded component types.↲ ↲ ┆a1┆Examples:↲ current_index:=current_index+1↲ catalog(current_index).author:="Andersen H C"↲ matrix:= matrix_type(:(:1, 0, 0:).↲ ╞ ╞ (:0, 1, 0:),↲ ╞ ╞ (:0, 0, 1:):)↲ ↲ ↲ ┆a1┆┆b0┆5.2.2 Exchange Statement↲ ↲ The values of two variables may be exchanged by executing an ↓ exchange statement.↲ ↲ ↲ ↲ ↲ The denoted objects must be variables, and they must be of ↓ the same type, cf. section 3.10. This type, or any of its ↓ components types, must not be mailbox, pool, chain, or port.↲ ↲ The execution of an exchange statement takes place in two ↓ steps:↲ ↲ 1) ┆84┆The addresses of the left hand side and right hand side ↓ ┆19┆┆83┆┄┄variables are evaluated, in that order.↲ ↲ 2) ┆84┆The values of the objects located at the addresses ↓ ┆19┆┆83┆┄┄evaluated in step 1 are interchanged.↲ ↲ If the two variables are of type reference or process or if ↓ they have components of these types the interchange takes ↓ place as an indivisible operation so that the integrity of ↓ references to buffers and processes is preserved.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆Examples:↲ current_buffer_ref:=:temp_buffer↲ matrix(i):=:matrix(j)↲ ↲ ↲ ┆b0┆┆a1┆5.3 If Statement↲ ↲ An if statement selects for execution one of two (possibly ↓ empty) statements depending on the value of a condition. The ↓ expression specifying the condition must be of the ↓ predefined type boolean.↲ ↲ ↲ ↲ ↲ ↲ The execution of an if statement takes place in two steps:↲ ↲ 1) The value of the boolean_expression is evaluated.↲ ↲ 2) ┆84┆If the expression evaluates to true the statement ↓ ┆19┆┆83┆┄┄following THEN is executed. Otherwise the statement after ↓ ┆19┆┆83┆┄┄ELSE (if present) is executed.↲ ↲ The ambiguous statement:↲ ╞ ╞ IF e1 THEN IF e2 THEN s1 ELSE s2↲ is defined to be equivalent to:↲ ╞ ╞ IF e1 THEN BEGIN↲ ╞ ╞ IF e2 THEN s1 ELSE s2↲ ╞ ╞ END↲ ↲ ┆a1┆Examples:↲ IF day=Sturday THEN↲ day:=Sunday↲ ELSE↲ day:=succ(day)↲ ↲ IF test THEN produce_test_record↲ ↲ ↲ ┆8c┆┆83┆┆e0┆↓ ┆b0┆┆a1┆5.4 Case Statement↲ ↲ A case statement selects for execution one of a number of ↓ alternative statements, depending on the value of an ↓ expression. The expression must be of an ordinal type.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ A case element is a statement labelled by one or more ↓ constant expressions. These constant expressions, called ↓ case labels, must all be of a type compatible with that of ↓ the selecting expression. Consecutive values may be given as ↓ a range, e.g. first..last. All the case labels of one case ↓ statement must be distinct.↲ ↲ The execution of a case statement takes place in three ↓ steps: ↲ ↲ 1) Evaluation of the selecting expression.↲ ↲ 2) ┆84┆The case element with the label corresponding to the ↓ ┆19┆┆83┆┄┄value of the selecting expression is selected for ↓ ┆19┆┆83┆┄┄execution.↲ ↲ ┆84┆The "label" OTHERWISE (keyword) corresponds to all values ↓ ┆19┆┆83┆┄┄of the type of the selecting expression which do not ↓ ┆8c┆┆83┆┆c8┆↓ ┆19┆┆83┆┄┄occur as case labels. A fault occurs if no case element ↓ ┆19┆┆83┆┄┄corresponds to the value of the selecting expression.↲ ↲ 3) Execution of the statement of the selected case element.↲ ↲ ┆a1┆Note:↲ Upon completion of the selected statement the case statement ↓ is also completed.↲ ↲ ┆a1┆Example:↲ CASE month OF↲ January..May:╞ ....;↲ October, December:╞ ....↲ OTHERWISE╞ ╞ ....↲ END (* of case *)↲ ↲ ↲ ┆b0┆┆a1┆5.5 Repetitive Statements↲ ↲ A repetitive statement specifies that a statement is to be ↓ executed repeatedly, zero or more times.↲ ↲ ↲ ┆b0┆┆a1┆5.5.1 For Statement↲ ↲ A for loop may be used if a statement is to be executed a ↓ fixed number of times and/or elaborates on consecutive ↓ values of an object (iteration).↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The execution of a for statement takes place in five steps, ↓ where three may be repeated:↲ ↲ ┆8c┆┆83┆┆c8┆↓ 1) ┆84┆The start and stop expressions are evaluated and define ↓ ┆19┆┆83┆┄┄an ordinal type, i.e. the expressions must be of the same ↓ ┆19┆┆83┆┄┄type, which must be an ordinal type.↲ ↲ 2) ┆84┆The ┆a1┆controlling variable┆e1┆ is allocated as an implicitly ↓ ┆19┆┆83┆┄┄declared variable, local to the for statement. Its name ↓ ┆19┆┆83┆┄┄is the 'for_name'. The type of the controlling variable ↓ ┆19┆┆83┆┄┄is the type of the start and stop expressions. The ↓ ┆19┆┆83┆┄┄initial value of the controlling variable is that of the ↓ ┆19┆┆83┆┄┄start expression.↲ ↲ 3) ┆84┆The termination conditionis tested. That is, if TO is ↓ ┆19┆┆83┆┄┄specified, execution of the for statement terminates when ↓ ┆19┆┆83┆┄┄the value of the controlling variable is greater than the ↓ ┆19┆┆83┆┄┄value of the stop expression; if DOWNTO is specified, ↓ ┆19┆┆83┆┄┄when the value of the controlling variable is less than ↓ ┆19┆┆83┆┄┄the value of the stop expression.↲ ↲ 4) ┆84┆The statement following DO is executed with the ↓ ┆19┆┆83┆┄┄controlling variable acting as a constant (i.e. it must ↓ ┆19┆┆83┆┄┄not appear on the left hand side of an assignment ↓ ┆19┆┆83┆┄┄statement, nor may it be passed as a variable parameter ↓ ┆19┆┆83┆┄┄of a routine call).↲ ↲ 5) ┆84┆The value of the controlling variable is updated, except ↓ ┆19┆┆83┆┄┄if it has already reached the upper or lower bound of the ↓ ┆19┆┆83┆┄┄permissible range in which case execution of the for ↓ ┆19┆┆83┆┄┄statement terminates immediately. The iteration can ↓ ┆19┆┆83┆┄┄either be with increasing values of the controlling ↓ ┆19┆┆83┆┄┄variable or with decreasing values. if TO is specified ↓ ┆19┆┆83┆┄┄the ordinal value of the controlling variable is ↓ ┆19┆┆83┆┄┄incremented in steps of one (succ). If DOWNTO is ↓ ┆19┆┆83┆┄┄specified the iteration is with decreasing values (pred). ↓ ┆19┆┆83┆┄┄the execution continues at step 3).↲ ↲ ┆a1┆Note:↲ The two expressions are evaluated once, before the ↓ repetition. If the terminaltion condition is satisfied ↓ ┆8c┆┆83┆┆c8┆↓ before the very first repetition the statement (following ↓ DO) of the for statement is not executed at all.↲ ↲ ┆a1┆Example:↲ FOR month:=January TO December DO↲ FOR date:=1 TO number_of_days(month) DO↲ daily_activity(date,month)↲ ↲ ↲ ┆b0┆┆a1┆5.5.2 Loop Statement↲ ↲ The loop statement constitutes an unconditional repetitive ↓ control structure, which may be used to define an "infinite" ↓ main loop of a program, only terminated in case of a fault ↓ or parent enforced process termination.↲ ↲ ↲ ↲ ↲ ↲ The loop statement specifies repeated execution of the ↓ statement sequence in the stated order. The loop may be left ↓ as the result of the execution of a jump statement (cf. ↓ section 5.7).↲ ↲ ┆a1┆Example:↲ LOOP↲ next_b:=read_next_buffer;↲ prepare_buffer(next_b);↲ send_buffer(next_b)↲ ENDLOOP↲ ↲ ↲ ┆b0┆┆a1┆5.5.3 While Statement↲ ↲ Conditional repetition of a statement where the condition is ↓ checked before each execution may be achieved by means of a ↓ while statement.↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆f8┆↓ The value of the boolean_expression is evaluated before each ↓ execution of the statement. The test-and-execute sequence ↓ goes on as long as the evaluation yields true, when the ↓ result becomes false, possibly the first time, execution of ↓ the while statement terminates.↲ ↲ The while statement:↲ WHILE exp DO st↲ is equivalent to following combination of loop, if and ↓ exitloop statements:↲ LOOP IF NOT exp THEN EXITLOOP; st ENDLOOP↲ ↲ ┆a1┆Example:↲ current_index:=first_index;↲ WHILE table(current_index) <> sought_element DO↲ currfent_index:=current_index+1↲ ↲ ↲ ┆b0┆┆a1┆5.5.4 Repeat Statement↲ ↲ Execution of a sequence of statements until some condition ↓ is satisfied may be achieved by means of a repeat statement.↲ ↲ ↲ ↲ ↲ ↲ Every time the sequence of statements has been executed, the ↓ value of the boolean expression is evaluated and execution ↓ of the repeat statement terminates when the evaluation ↓ yields true.↲ ↲ The repeat statement↲ REPEAT s1; ..; sn UNTIL exp↲ is equivalent to the following special form of the loop ↓ statement:↲ LOOP s1; ...; sn; IF exp THEN EXITLOOP ENDLOOP↲ ↲ ┆8c┆┆83┆┆c8┆↓ ┆a1┆Example:↲ REPEAT↲ wait(main_mailbox, ref);↲ final_message:=do_process(ref);↲ return(ref)↲ UNTIL final_message↲ ↲ ↲ ┆b0┆┆a1┆5.6 Procedure Call↲ ↲ A procedure call serves to establish a binding between ↓ actual and formal parameters, to allocate locally declared ↓ variables, and to invoke execution of the compound statement ↓ of the procedure block in its proper surroundings. A ↓ procedure call consists of the procedure name followed by a ↓ list of actual parameters. If the procedure is declared ↓ without formal parameters, the call consists of the ↓ procedure name only.↲ ↲ ↲ ↲ ↲ ↲ The execution of a procedure call takes place in two steps:↲ ↲ 1) ┆84┆The actual parameters are evaluated in the order of ↓ ┆19┆┆83┆┄┄occurrence.↲ ↲ 2) ┆84┆An activation of the block associated with the procedure ↓ ┆19┆┆83┆┄┄name is created, including parameter passing, and the ↓ ┆19┆┆83┆┄┄action part of the block is executed (cf. chapter 6). ↓ ┆19┆┆83┆┄┄When the execution terminates the procedure call is ↓ ┆19┆┆83┆┄┄completed.↲ ↲ Detailed rules for actual parameters are decribed in section ↓ 6.1.↲ ↲ ↲ ┆8c┆┆83┆┆c8┆↓ ┆b0┆┆a1┆5.7 Jump Statements↲ ↲ The statements described in this section serve to explicitly ↓ modify the order of execution of statements by transferring ↓ control to an implicitly or explicitly indicated statement.↲ ↲ ↲ ┆b0┆┆a1┆5.7.1 Exitloop Statement↲ ↲ Execution of an exitloop statement causes the execution of ↓ an enclosing repetitive statement (cf. section 5.5) to ↓ terminate.↲ ↲ ↲ ↲ ↲ The repetition exited is the innermost one. An exitloop ↓ statement may only appear within a repetitive statement, ↓ i.e. repeat, for, while or loop statement.↲ ↲ ┆a1┆Example:↲ The generalized loop control structure may be constructed as ↓ a combination of a loop statement, an if statement, and an ↓ exitloop statement:↲ ↲ LOOP↲ s_1_1; ...; s_1_n;↲ IF bool_condition THEN EXITLOOP;↲ s_2_1; ...; s_2_m↲ ENDLOOP↲ ↲ ↲ ┆b0┆┆a1┆5.7.2 Continueloop Statement↲ ↲ The continueloop statement specifies that the remaining part ↓ of an iterationof a loop is to be skipped.↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆e0┆↓ The statement applies to the innermost enclosing repetitive ↓ statement which must therefore exist. Depending on the kind ↓ of repetition statement (cf. section 5.5) the specific ↓ effect of the continueloop statement is:↲ ↲ ┆a1┆for statement:↲ Step 4 terminates, and execution continues at step 5.↲ ↲ ┆a1┆loop statement:↲ Execution continues with the first statement after LOOP.↲ ↲ ┆a1┆while statement:↲ The remainder of the statement following DO is skipped. ↓ Execution continues with the evaluation of the loop ↓ condition.↲ ↲ ┆a1┆repeat statement:↲ The remainder of the statement sequence up to UNTIL is ↓ skipped. Execution continues with the evaluation of the loop ↓ condition.↲ ↲ ↲ ┆b0┆┆a1┆5.7.3 Exit Statement↲ ↲ An exit statement has the effect of a jump to the END of the ↓ compound statement of the enclosing block.↲ ↲ ↲ ↲ ↲ Executionof an exit statement causes termination of the ↓ execution of the action part of the nearest enclosing ↓ routineor program block as if the compound statement had ↓ been exhausted.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆Example:↲ BEGIN (* main program *)↲ ...↲ IF errors-detected THEN (* terminate the process *)↲ EXIT;↲ ...↲ END↲ ↲ ↲ ┆b0┆┆a1┆5.7.4 Goto and Labelled Statement↲ ↲ The execution of a goto statement results in an explicit ↓ transfer of control to another statement specified by a ↓ label.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ A labelled statement introduces the label name as denoting a ↓ label of the 'statement' following:.↲ ↲ A labelled statement is executed by executing the ↓ 'statement'.↲ ↲ Execution of a goto statement causes the normal order of ↓ execution of the statements within a compound statement to ↓ be broken. Executionis resumed at the labelled statement ↓ whose 'label_name' is identical to the one occurring in the ↓ goto statement. The label must be visible at the point where ↓ the goto statement occurs.↲ ↲ A goto statement cannot be used to transfer control from the ↓ outside into or from the inside out of the statement ↓ following DO of a for, with, lock, or region statement.↲ ↲ ┆a1┆Note:↲ Goto into or out of a block is impossible.↲ ↲ ↲ ┆8c┆┆83┆┆f8┆↓ ┆b0┆┆a1┆5.8 With Statement↲ ↲ A with statement may be used for three purposes:↲ ↲ - shorthand notation for field access in a record object,↲ - object renaming,↲ - object retyping.↲ ↲ The latter is the facility allowing a programmer-defined ↓ type to be superimposed on a buffer when applied in a lock ↓ statement.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The denoted object is called the ┆a1┆with-object┆e1┆. It must not be ↓ an irregular object (cf. section 3.9). The type specified by ↓ the 'common type specification', if present, is called the ↓ ┆a1┆local type┆e1┆. The type of the with-object must not be ↓ protected, nor may the local type. The size of the local ↓ type must be less than or equal to the size of the with-↓ object.↲ ↲ If the AS-part of a with statement is empty several with-↓ objects may be listed. More specifically↲ WITH d┆82┆1┆81┆, d┆82┆2┆81┆, ..., d┆82┆n┆81┆ DO st↲ is acceptable as shorthand for↲ WITH d┆82┆1┆81┆ DO WITH d┆82┆2┆81┆ DO ... WITH d┆82┆n┆81┆ DO st↲ where the d┆82┆1┆81┆ are object denotations.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ A with statement is executed in three steps:↲ a. ┆84┆the denotation of the with-object is evaluated as an ↓ ┆19┆┆83┆┄┄object expression, i.e. the address of the object is ↓ ┆19┆┆83┆┄┄established;↲ 2. the local type, if present, is established;↲ 3. ┆84┆the statement following DO is executed observing the ↓ ┆19┆┆83┆┄┄rules described below.↲ ↲ ┆a1┆field access:↲ If the type of the with-object is a record tye and fname is ↓ a field name of this record type then↲ fname↲ may be used as shorthand for↲ obj.fname↲ where obj is an object denotation denoting the with-object.↲ ↲ ┆a1┆renaming:↲ a non-empty AS-part is equivalent to a local declaration of ↓ an object, called the ┆a1┆local object┆e1┆, with the same address as ↓ the with-object. The 'local_name' denotes the local object.↲ ↲ ┆a1┆retyping:↲ The type of the local object is the local type, if ↓ specified; otherwise it is the type of the with-object.↲ ↲ ┆a1┆Notes:↲ the with-object is not restricted to be of a record type, ↓ even (structured) constants are allowed.↲ ↲ The address of the object is evaluated only once before the ↓ statement following DO is executed.↲ ↲ The retyping of an object is a low-level facility of the ↓ language, intended for use in connection with buffers whose ↓ exact type is not known beforehand (some of the type ↓ information may be part of the buffer contents). But the ↓ facility may be used freely to achieve a relaxation of the ↓ otherwise rigorous object typing, which is one of the basic ↓ features of the language. this method demands an explicit ↓ ┆8c┆┆83┆┆d4┆↓ and clear retyping stated where it is used in the program, ↓ in contrast to the standard Pascal solution using variant ↓ records.↲ ↲ The effect of assignment of exchange between partially ↓ overlapping objects is undefined.↲ ↲ ┆a1┆Example:↲ Let rec_var be a record with a field named rec_field, and ↓ let local_type contain a field named loc_rec_field, then the ↓ fields may be accessed in the following ways in the ↓ statement following DO:↲ ↲ 1) ┆84┆WITH rec_var DO (* the well-known standard Pascal form *)↲ rec_var.rec_field or↲ rec_field↲ ↲ 2) WITH rec_var AS loc_var DO (* simple renaming *)↲ rec_var.rec_field or↲ rec_field or↲ loc_var.rec_field↲ ↲ 3) WITH rec_var AS loc_var: local_type DO↲ (* renaming and retyping *)↲ rec_var.rec_field or↲ rec_field or↲ loc_var.loc_rec_field↲ ↲ ┆a1┆Exampel:↲ TYPE↲ cat_record= RECORD ↲ title: ....↲ ╞ ╞ author: ....↲ ╞ ╞ END;↲ VAR↲ b_catalog: ARRAY(1..cat_size) OF cat_record;↲ search_object: cat_record;↲ ...↲ ┆8c┆┆83┆┆c8┆↓ WITH search_object AS s_o DO↲ WHILE NOT found DO↲ WITH b_catalog(current_index) DO↲ IF author(* of b_catalog *) <> s_o.author then↲ current_index:=current_index+1↲ ELSE↲ ...↲ ↲ ↲ ┆b0┆┆a1┆5.9 Lock Statement↲ ↲ The lock statement is the language construct which provides ↓ access to the actual contents of a buffer, i.e. to the top ↓ non-empty buffer in a buffer stack.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The denoted object must be a variable of type reference or ↓ chain. If it is a reference its value must not be NIL, and ↓ if it is a chain it must not be empty. Otherwise a fault ↓ occurs. The buffer designated by the reference, or the ↓ current buffer of the chain, whichever applies, may be ↓ accessed in the statement following DO as an implicitly ↓ declared variable the name of which is specified by the ↓ 'buffer_name'. Either the whole buffer or only its data is ↓ accessible, depending on the 'lockword'.↲ ↲ If the 'lockword' is LOCK the data area is accessible as a ↓ variable of a type belonging to the predefined family↲ dataarea(offset, top: 0..maxint)=↲ ╞ ╞ ╞ PACKED AREA(offset..top-1) OF byte ↓ where the parameter values are equal to the buffer ↓ attributes with the same names. The address of the variable ↓ ┆8c┆┆83┆┆c8┆↓ as well as the parameter values are evaluated before the ↓ statement following DO is executed.↲ ↲ If the 'lockword' is LOCKBUF the whole buffer is accessible ↓ as a variable of a type belonging to the predefined family↲ buffer(bufsize: 1..maxint)= ↲ PACKED ARRAY(0..bufsize-1) OF byte↲ where the value of the parameter equals the size of the ↓ buffer.↲ ↲ If a lock statement is applied to a buffer stack with no ↓ non-empty buffer a fault occurs.↲ ↲ The following restrictions are imposed on the use of the ↓ locked variable while the statement following DO is being ↓ executed, including any routine calls made: If a reference, ↓ it must not be used as part of an exchange statement or as a ↓ parameter to signal, return, or putbuf (cf. chapter 9), or ↓ be delivered to the IMC (cf. chapter 11). Whether a chain or ↓ a reference, it must not be used as a parameter to any of ↓ the buffer stack or chain manipulation routines (cf. chapter ↓ 10). However, it is legal to (cynamically) apply multiple ↓ locks to the same reference or chain (e.g. in a routine ↓ called from within a lock statement).↲ ↲ ┆a1┆Example:↲ LOCK ref TO data_part DO↲ WITH data_part AS data : my_buffer_type DO↲ ...↲ ↲ ↲ ┆b0┆┆a1┆5.10 Region Statement↲ ↲ The region statement provides access to shared variables and ↓ it is ensured that the access is exclusive.↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆d4┆↓ The denoted object must be a shared variable. Associated ↓ with every shared variable is an ┆a1┆access count┆e1┆ which is ↓ initially zero. A region statement is executed in three ↓ steps.↲ ↲ 1. ┆84┆Unless the process executing the region statement is ↓ ┆19┆┆83┆┄┄already executing (dynamically inside) a region statement ↓ ┆19┆┆83┆┄┄accessing the same shared variable it waits (is ↓ ┆19┆┆83┆┄┄suspended) until the access countof the variable is zero. ↓ ┆19┆┆83┆┄┄Subsequently the access count is incremented. If several ↓ ┆19┆┆83┆┄┄processes wait for access to the same shared variable ↓ ┆19┆┆83┆┄┄they observe a fifo discipline.↲ ↲ 2. ┆84┆The statement following DO is executed. In this statement ↓ ┆19┆┆83┆┄┄the shared variable may be accessed in the same fashion ↓ ┆19┆┆83┆┄┄as an ordinary (private) variable.↲ ↲ 3. The access count of the shared variable is decremented.↲ ↲ ┆a1┆Example:↲ ↲ VAR↲ route_table: RECORD↲ ...↲ PROCEDURE close_down(node: node_ident);↲ ...↲ REGION route_table DO↲ route_table.open_routes(node):=closed;↲ ...↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆6. PROGRAMS AND ROUTINES↲ ↲ Programs and routines are very similar. Both have the ↓ general form of a heading followed by a block. Incarnations ↓ of program and routine blocks also exhibit fundamental ↓ similarities. In both cases the life of an incarnation has ↓ three stages: parameter passing, elaboration of ↓ declarations, and execution of an action part. The ↓ differences have to do with two aspects: control and ↓ environment.↲ ↲ An incarnation of a program block is a process on its own ↓ which lives autonomously except for the control exercised by ↓ its parent, whereas an incarnation, or ┆a1┆activation┆e1┆, of a ↓ routine block is merely an episode in the life of a process. ↓ The activation, unless it chooses to loop infinitely or ↓ commits a fault, has no choice but to return to the point ↓ where it was called.↲ ↲ A process has no environment of data to acces apart from ↓ predefined items and its parameters. A routine block ↓ activation, in addition to these, has its static ↓ surroundings: all the stack-allocated objects (including ↓ formal parameters) declared in enclosing blocks, except ↓ those which have been made invisible by redeclaration of ↓ their names, cf. chapter 8.↲ ↲ A program declaration may appear at the outer level of a ↓ 'compilation unit', cf. section 8.2, or in the delcaration ↓ part of a program block. It serves to name and define a ↓ program.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆e0┆↓ The heading specifies the name of the program and its formal ↓ parameters, if any.↲ ↲ A routine declaration may also appear at the outer level of ↓ a 'compilation unit', or in the declaration part of a block. ↓ It serves to name and define a routine.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The initial keyword in a routine heading specifies whether ↓ the routine is a function or a procedure. In addition the ↓ declaration specifies the name of the routine, its formal ↓ parameters, if any, and in the case of a function: its ↓ result type, which must be an ordinal, machine or pointer ↓ type. The 'routine block' unless specified by one of the ↓ keywords EXTERNAL or FORWARD (see blow) is associated with ↓ the function of procedure name.↲ ↲ The parameters and blocks of programs as well as routines ↓ are described in the following two sections.↲ ↲ ┆a1┆Example:↲ PROGRAM router (INSPECT routs: route_table)↲ FUNCTION search_name(name: name_node): boolean↲ PROCEDURE insert_name(VAR position: table_index↲ ╞ ╞ name: name_record)↲ ↲ ┆b0┆┆a1┆↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆6.1 Parameters↲ ↲ The 'formal parameters' of a program or routine heading ↓ specify the names, kinds and types of the formal arametersof ↓ the program or routine.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ Each 'formal_name' introduceds one parameter. Several ↓ parameters may be named in a list, separated by commas. Such ↓ parameters have the same kind and type.↲ ↲ The kind of a parameter, which may be ┆a1┆variable┆e1┆, ┆a1┆inspect┆e1┆, ↓ ┆a1┆shared┆e1┆ or ┆a1┆value┆e1┆, is specified by the (possible) keyword ↓ preceding its name. In the block of the program or routine ↓ each parameter acts as an object. The parameter kind ↓ determines how this object may be used:↲ ↲ ┆a1┆keyword╞ parameter kind╞ use of object╞ ╞ ╞ ╞ ╞ ↲ VAR╞ ╞ variable╞ ╞ as a private variable↲ INSPECT╞ inspect╞ ╞ as a constant↲ SHARED╞ shared╞ ╞ as a shared variable↲ none╞ value╞ ╞ as a private variable↲ ↲ The type of each parameter, i.e. of the object which can be ↓ accessed in the block of the rogram or routine, is ↓ determined by the 'formal type specification' following the ↓ name of the parameter. If the 'formal type specification' is ↓ a 'parameterized-type_name', i.e. the name of a family of ↓ conformant types, the type of the formal parameter is ↓ determined for each incarnation of the program or routine by ↓ the type of the actual parameter.↲ ↲ ┆8c┆┆83┆┆d4┆↓ An incarnation of a program or routine is created as a ↓ result of a 'create call', 'function call', or 'procedure ↓ call' being evaluated or executed. The call contains a ↓ description of the actual parameters to be bound to the ↓ formal parameters for the particular incarnation of the ↓ program or routine.↲ ↲ ↲ ↲ ↲ ↲ ↲ Each actual parameter corresponds to the formal parameter in ↓ the same position in the 'formal parameters'. The number of ↓ actual parameters must equal the number of formal ↓ parameters. An actual parameter of kind variable, inspect, ↓ or shared must be of the same type as the corresponding ↓ formal parameter. An actual parameter of kind value need ↓ only be assignable to the formal parameter (cf. section ↓ 3.10). When the type of a formal parameter is specified as ↓ the name of a family of types the type of the corresponding ↓ actual parameter may be any type in that family.↲ ↲ The symbol ? may be used in place of an actual parameter ↓ expression when the parameter is not of kind value, ↓ regardless of the type of the formal parameter.↲ ↲ The binding of an actual parameter to the corresponding ↓ formal parameter takes place either by a value transfer ↓ ("call by value"), or by an address transfer ("call by ↓ reference") depending on the kind of the parameter. Value ↓ parameters are passed by value transfer, all other kinds by ↓ address transfer.↲ ↲ ┆a1┆value transfer:↲ The value of the actual parameter becomes the initial value ↓ of the formal parameter which is allocated on the stack as ↓ an object local to the incarnation.↲ ↲ ┆8c┆┆83┆┆d4┆↓ ┆a1┆address transer:↲ The actual parameter is an object expression, cf. chapter 4. ↓ It must not denote an irregular object (cf. section 3.9). ↓ Evaluation of the actual parameter yields the address of an ↓ object of the parameter type. Throughout the life of the ↓ incarnation of the program or routine the formal parameter ↓ name will denote this object.↲ ↲ An actual parameter object passed to a process must be ↓ declared at the outer block level of the parent process, ↓ i.e. either it must itself be a process parameter or it must ↓ be declared in the program declaration part.↲ ↲ If the actual parameter is specified as ? there is no ↓ parameter object. If an attempt is made to access such a ↓ non-existing parameter object a fault occurs.↲ ↲ If the kind of the formal parameter is varialbe the actual ↓ parameter object must be a private variable or component of ↓ a private variable. If the kind of the formal parameter is ↓ shared the actual parameter object must be a shared ↓ variable. Conversely, if the actual parameter is shared, the ↓ kind of the formal parameter must also be shared.↲ ↲ The following restrictions apply to process parameters, i.e. ↓ to the formal parameters which occur in a program heading:↲ - ┆84┆parameters of kind variable must be of type pool, mailbox, ↓ ┆19┆┆82┆┄┄or port;↲ - ┆84┆parameters (or components thereof) of pointer types must ↓ ┆19┆┆82┆┄┄have mailbox as their base type, regardless of kind.↲ ↲ ┆a1┆Notes:↲ An actual process parameter of kind inspect may be a ↓ variable, and thus it may be changed by the parent process.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆Example:↲ TYPE↲ list= ARRAY(1..max_list_length) OF list_element;↲ ↲ PROCEDURE handle_list(INSPECT 1st: list);↲ -- 1st is of kind inspect to save time and space, and to↲ -- allow the handling of constant lists↲ ↲ ↲ ┆b0┆┆a1┆6.2 Incarnations of Blocks↲ ↲ A block, whether program or routine, consists of a ↓ declaration part and an action part which has the form of a ↓ compound statement.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ Blocks specified by one of the keywords EXTERNAL and FORWARD ↓ are described in subsection 6.2.2.↲ ↲ The declaration parts of program and routine blocks are ↓ slightly different in that certain forms of declarations may ↓ not occur in a routine block; see subsection 6.2.1.↲ ↲ An incarnation, whether of a program or routine, is created ↓ in the following three steps.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ 1) ┆84┆Allocation of the necessary (initial) amount of stack and ↓ ┆19┆┆83┆┄┄heap. In the case of a program this means a whole new ↓ ┆19┆┆83┆┄┄stack; in the case of a routine it means an ┆a1┆activation ↓ ┆19┆┆83┆┄┆84┆record┆e1┆ in the stack of the calling process.↲ ↲ 2) Parameter passing, cf. section 6.1.↲ ↲ 3) ┆84┆Elaboration of the declarations of the blocks, as ↓ ┆19┆┆83┆┄┄described below.↲ ↲ When an incarnation has been created the actions part of the ↓ block can be executed, cf. function call (section 4.2), ↓ procedure call (section 5.6), and create call (section 9.1).↲ ↲ When execution of the action part of a routine terminates ↓ the values of all local reference variables must be NIL, ↓ otherwise a fault occurs.↲ ↲ ↲ ┆b0┆┆a1┆6.2.1 The Declaration Part↲ ↲ The declaration part of a block names and defines types, ↓ objects, routines and programs which are local to the block, ↓ i.e. not visible outside the block. The names introduced in ↓ the declarations may be used within the block to refer to ↓ the defined entities, cf. chapter 8.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆83┆┆e0┆↓ Variables of shielded types, except reference, and variables ↓ which have components of these types may not be declared in ↓ a routine declaration part, i.e. such variables can only be ↓ declared in the outer block of a program.↲ ↲ The declarations in the declaration part of a block are ↓ elaborated in the order of occurrence. Elaboration of type ↓ declarations is described in section 3.2, elaboration of ↓ variable and shared declarations is described in subsection ↓ 3.12.2, and constant declarations need no elaboration at ↓ run-time.↲ ↲ The elaboration of a routine or program declaration causes ↓ all types defined in the 'formal parameters' to be ↓ established. When a program declaration is elaborated a ┆a1┆sub-↓ ┆19┆┄┄┆84┆program object┆e1┆ is allocated in the stack of the process ↓ being created, and associated with the program name ↓ specified in the declaration. Unless the program block is ↓ external, the sub-program object is linked (as if by an ↓ implicit link call, cf. chapter 9) to the block; otherwise ↓ it is initialized as having state unlinked.↲ ↲ The elaboration of the declaration part is performed for ↓ each incarnation of a block, and the names introduced in the ↓ declarations, when occurring in the remainder of the block, ↓ refer to those instances of the named entities which have ↓ been established or allocated when the particular ↓ incarnation of the block was created.↲ ↲ In the case of a function block elaboration of the ↓ declaration part, even if it is empty, includes ↓ establishment of the result type and allocation on the stack ↓ of an implicitly declared ┆a1┆result object┆e1┆. The initial value ↓ of the result object is undefined.↲ ↲ ┆a1┆Note:↲ The static environment of an internal program block is the ↓ same as that of the enclosing program block, i.e. only names ↓ ┆8c┆┆83┆┆c8┆↓ in contexts specified for the compilation unit, cf. chapter ↓ 8, predefined names, and the names of formal parameters are ↓ known from the start of the block.↲ ↲ Elaboration of declarations is not the only time types may ↓ be established. Further types may be established when for, ↓ with, and lock statements are executed.↲ ↲ ┆b0┆┆f0┆┆a1┆Example (of nested routines):↲ ↲ TYPE parity= (even, odd);↲ ↲ FUNCTION byte_parity(arg: byte): parity;↲ ↲ FUNCTION even4bits(arg: 0..15): boolean;↲ CONST table= (. 0,3,5,6,9,10,12,15 .);↲ BEGIN even4bits:=arg IN table END;↲ ↲ BEGIN (* byte parity *)↲ IF even4bits(int(arg SHIFT (-4))) -- left half byte↲ =even4bits(int(arg AND HF)) -- right half byte↲ THEN byte_parity:=even↲ ELSE byte_parity:=odd↲ END↲ ↲ ↲ ┆b0┆┆a1┆6.2.2 Forward and External Blocks↲ ↲ A forward announcement of a declaration containing the ↓ actual block of a routine may be given by using the keyword ↓ FORWARD in place of the routine block. When a forward ↓ announcement is used a declaration with an identical routine ↓ heading, i.e. all lexical elements identical, and an actual ↓ routine block (i.e. constisting of declaration part, which ↓ may be empty, and action part) must appear later in the same ↓ 'declaration part'. In this way it is possible to observe ↓ the rule of declaration before use, even for mutually ↓ recursive routines.↲ ↲ ┆8c┆┆83┆┆d4┆↓ The block of a program or routine may be specified as ↓ external, i.e. separately compiled (cf. chapter 8), by the ↓ keyword EXTERNAL. This may only be used in the declaration ↓ part of a block appearing at the outermost block level of a ↓ compilation unit, cf. section 8.2. An external program or ↓ routine y possibly be written in another programming ↓ language and compiled by a compiler for that language ↓ provided it is object code format compatible with the Real-↓ Time Pascal compiler in question.↲ ↲ Due to the differences between routines and programs the ↓ linking of a program to a separately compiled block is ↓ somewhat different in the two cases.↲ ↲ During the execution of an incarnation of a program ↓ containing an external program declaration the linking ↓ between the resulting sub-program object and the block of a ↓ separately compiled program is established as a result of ↓ the evaluation of an explicit link call, cf. chapter 9.↲ ↲ The association between the block of a separately compiled ↓ routine and the function or procedure name specified in an ↓ external routine delcaration, i.e. the linking of the ↓ routine block to the program in which the external ↓ declaration occurs, must be established by a linkage editor ↓ before an incarnation of the program can be created. This ↓ can be done during a separate link-phase following ↓ compilation, or it can be done as a by-effect of program ↓ linking at run-time.↲ ↲ The amount and kind of checking of the agreement between the ↓ 'formal parameters' of an external program or routine ↓ declaration and the corresponding formal parameter ↓ specificationof the separately compiled block, which is ↓ performed during linking, is implementation dependent. This ↓ is true for both cases of linking. In order to facilitate ↓ linking with programs written in other languages the ↓ parameter and result passing formats used by an ↓ ┆8c┆┆83┆┆c8┆↓ implementation must be appropriately chosen and thoroughly ↓ documented.↲ ↲ ┆a1┆Example (of mutually recursive routines):↲ ↲ PROCEDURE first(par1, par2: type1); FORWARD;↲ ↲ PROCEDURE second(par: par_type);↲ ...↲ BEGIN↲ ...↲ first(act1, ct2);↲ ...↲ END;↲ ↲ PROCEDURE first(part1, par2: type1);↲ ...↲ BEGIN↲ ...↲ second(act);↲ ...↲ END↲ ↲ ↲ ┆b0┆┆a1┆6.2.3 The Action Part↲ ↲ Execution of the actions of a block means execution of its ↓ compound statement. This is described in chapter 5. ↓ Executionis ┆a1┆terminated┆e1┆ when the compound statement is ↓ exhausted, when an exit statement is executed, or when a ↓ fault occurs. When a process terminates it goes into a ↓ passive state where it remains until removed by its parent. ↓ When a procedure activation terminates its activation record ↓ is deallocated and a return is made to the caller, i.e. the ↓ procedure call is completed. When a function activation ↓ terminates its activation record is deallocated and the ↓ final value of the implicit result object is the value of ↓ the function call whose evaluation caused the activation.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆7. FAULT HANDLING↲ ↲ A number of violationsof the rules of Real-Time Pascal are ↓ referred to in this document as faults. Faults are errors ↓ which cannot, at least not in call cases, be detected at ↓ compile-time. Faults which are detected at compile-time ↓ cause the compiler to reject the source program. When a ↓ fault occurs at run-time, during the execution of an ↓ incarnation of a program, the following happens:↲ ↲ 1. ┆84┆The ┆a1┆exception procedure┆e1┆ of the program is called with a ↓ ┆19┆┆83┆┄┄fault code parameter indicating the kind of fault which ↓ ┆19┆┆83┆┄┄occurred.↲ 2. ┆84┆When (if) the exception procedure returns the process ↓ ┆19┆┆83┆┄┄terminates and goes into a passive state as if execution ↓ ┆19┆┆83┆┄┄of its action part had been completed.↲ ↲ Fault codes are implementation dependent and must be ↓ documented for each implementation.↲ ↲ ↲ ┆b0┆┆a1┆7.1 Default Exception Procedure↲ ↲ Every implementation must include a default exception ↓ procedure which outputs a snapshot of the stack of the ↓ calling process and the fault code.↲ ↲ The default exception procedure may also be called to ↓ provide trace information about a process. Such an explicit ↓ call does not cause the process to terminate. The heading of ↓ the default exception procedure is:↲ ↲ PROCEDURE trace(fault: integer)↲ ↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆7.2 Programmer-defined Exception Procedure↲ ↲ When a procedure with the name exception and one integer-↓ type parameter, i.e.↲ ↲ PROCEDURE exception(fault: integer)↲ ↲ is declared (internally) at the outer block level of a ↓ program, this procedure becomes the exception procedure of ↓ the program.↲ ↲ ┆a1┆Note:↲ An ordinary call of a programmer-defined exception procedure ↓ does not cause a process to terminate.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆8. NAMING ENVIRONMENTS↲ ↲ The rules described in this chapter serve to define for ↓ every point in a Real-Time Pascal source text the ┆a1┆naming ↓ ┆19┆┄┄┆84┆environment┆e1┆ which is valied at that point. A naming ↓ environment it must have an independent meaning, i.e. an ↓ occurrence of the name must denote a ┆a2┆┆e2┆┆a1┆program entity┆e1┆ ↓ irrespective of the syntactic context. A program entity is a ↓ value, a type, a family of conformant types, an object ↓ (which may in particular be a formal parameter), a label, a ↓ routine, or a (sub-)program. The visibility rules ensure ↓ that the entity denoted by a name is always uniquely ↓ determined.↲ ↲ In other words, the purpose of this chapter is to answer the ↓ question: When a name occurs at some point in a source text, ↓ what does it mean? and to ensure that the meaning is ↓ uniquely defined.↲ ↲ The unit of compilation for a Real-Time Pascal compiler is ↓ basically a sequence of routine and/or program declarations, ↓ referred to in the following as a ┆a1┆source text┆e1┆. The ↓ visibility rules for names introduced in a source text are ↓ described in section 8.1, and the precise syntactic form of ↓ a compilation unit is described in section 8.2 along with a ↓ discussion of the role played by predefined names and names ↓ introduced in so-called contexts.↲ ↲ ↲ ┆b0┆┆a1┆8.1 Visibility Rules↲ ↲ All names which occur in a source text must hve one or more ↓ points of ┆a1┆introduction┆e1┆ each of which defines a program ↓ entity which can be denoted by the name within some region ↓ of the text, called the ┆a1┆visibility region┆e1┆ of the entity. The ↓ point of introduction may be a declaration, a formal ↓ parameter specification, a labelled statement, the AS-part ↓ of a with statement, the iteration description of a for ↓ ┆8c┆┆83┆┆c8┆↓ statement, or a 7buffer_name' in a lock statement. Every ↓ introduction of a name has a ┆a1┆scope┆e1┆, i.e. a region of text ↓ over which the introduction has an effect. The concept of ↓ scope serves as a tool in determining the visibility region ↓ of a named program entity.↲ ↲ Once the visibility regions of all program entities are ↓ known the determination of a naming environment proceeds as ↓ follows: Consider a name occurring at some point in a ↓ program. If the point is within the visibility region of a ↓ program entity whose name is the name under consideration, ↓ then the name denotes that program entity. Otherwise it has ↓ no meaning, i.e. it is not part of naming environment.↲ ↲ There are two kinds of names which have no independent ↓ meaning, but whose meaning is dependent on the syntactic ↓ context, viz. the names of record fields and formal type ↓ parameters. However, because of the shorthand form of record ↓ field access allowed in with statements (cf. section 3.8) ↓ the names of fields of a with-object of a record type are ↓ treated as if introduced in the 'with definition'. Apart ↓ from this special case the names of record fields and type ↓ parameters are not members of naming environments.↲ ↲ Three kinds of rules which together make up the visibility ↓ rules are given below:↲ ↲ - uniqueness rules: ┆84┆rules which serve only to prevent ↓ ┆19┆┆94┆┄┄ambiguous meanings of names,↲ - scope rules: ┆84┆rules which determine the scope of an ↓ ┆19┆┆94┆┄┄introduction of a name,↲ - exclusion rules: ┆84┆rules which determine the visibility ↓ ┆19┆┆94┆┄┄region of a program entity by explicit ↓ ┆19┆┆94┆┄┄exclusion of sub-regions from the scope ↓ ┆19┆┆94┆┄┄of the introduction of the name of the ↓ ┆19┆┆94┆┄┄entity.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆Uniqueness rules↲ ↲ The following names are said to be introduced ┆a1┆initially┆e1┆ in a ↓ block:↲ ↲ - ┆84┆the names of the formal parameters specified in the ↓ ┆19┆┆82┆┄┄heading of the block,↲ - ┆84┆the names of program entities introduced in the ↓ ┆19┆┆82┆┄┄declaration part of the block exclusing the formal ↓ ┆19┆┆82┆┄┄parameter lists and blocks of enclosed program and routine ↓ ┆19┆┆82┆┄┄declarations, and↲ - ┆84┆the names of labels appearing in the compound statement of ↓ ┆19┆┆82┆┄┄the block.↲ ↲ 1) ┆84┆All names introduced initially in a block must be ↓ ┆19┆┆83┆┄┄distinct.↲ 2) ┆84┆All names introduced in the 'with definition' of a with ↓ ┆19┆┆83┆┄┄statement must be distinct.↲ ↲ ┆a1┆Scope rules↲ ↲ 1) ┆84┆The scope of a label or variable name is the compound ↓ ┆19┆┆83┆┄┄statement of the block in which it is introduced.↲ 2) ┆84┆The scope of any other name introduced initially in a ↓ ┆19┆┆83┆┄┄block extends from the point of introduction to the end ↓ ┆19┆┆83┆┄┄of the block. This is the rule which implies that in ↓ ┆19┆┆83┆┄┄general a name must be introduced before use.↲ 3) ┆84┆The scope of the 'for_name' introduced in a for ↓ ┆19┆┆83┆┄┄statement, or of a name introduced in a lock statement is ↓ ┆19┆┆83┆┄┄the 'statement' following DO in the for, with, or lock ↓ ┆19┆┆83┆┄┄statement.↲ 4) ┆84┆The scope of a record field name introduced as field ↓ ┆19┆┆83┆┄┄access shorthand in a with statement is the statement ↓ ┆19┆┆83┆┄┄following DO.↲ ↲ ┆a1┆Exclusion rules↲ ↲ An introduction of a name which occurs within the stope of a ↓ previous introduction of the same name is called a ↓ ┆a1┆reintroduction┆e1┆.↲ ↲ ┆8c┆┆83┆┆ec┆↓ The visibility region of a named program entity is the scope ↓ of the introduction of its name with the following possible ↓ exceptions:↲ ↲ 1) Any inner program blocks.↲ 2) ┆84┆The scope(s) of any reintroduction(s) of the name, i.e. ↓ ┆19┆┆83┆┄┄reintroduction hides the entity denoted by the outer ↓ ┆19┆┆83┆┄┄occurrence of the name.↲ ↲ ┆a1┆Example:↲ ↲ Hiding of an entity by reintroductionof its name is ↓ illustrated below:↲ ↲ PROCEDURE p;↲ CONST↲ n=2;↲ ...↲ PROCEDURE q;↲ CONST↲ m=n; (* 2 *)↲ n=5;↲ BEGIN↲ ... n ... (* has value 5 *)↲ ...↲ END↲ ↲ ↲ ┆b0┆┆a1┆8.2 Contexts and Predefined Names↲ ↲ The initial naming environment of a compilation consists of ↓ the predefined names and entities and those introduced in ↓ contexts.↲ ↲ The unit of compilation is a sequence of program and/or ↓ routine declarations optionally preceded by one or more ↓ contexts. A compiler must allow contexts to be supplied as ↓ files separate from the source text proper.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ┆8c┆┆84┆┆f0┆↓ All names introduced in one context must be distinct. The ↓ names introduced in contexts and theprogram entities defined ↓ at their points of introduction are treted as if they were ↓ introduced in a block surrounding the outer block(s) of the ↓ source text proper with one exception: the exclusion rule ↓ for inner program blocks does not apply. The scope of a name ↓ introduced in a context extends from the point of ↓ introduction to the end of the compilation unit. Routines ↓ declared in a context must be external, i.e. the actual ↓ block of a routine cannot be specified in a context.↲ ↲ The scope of names predefined as part of the language, cf. ↓ Appendix C, is the complete compilation unit. As with ↓ contexts the exclusion rule for inner program blocks does ↓ not apply to predefined entities. However, a predefined name ↓ may be hidden by reintroduction.↲ ↲ ┆a1┆Note:↲ the exclusion rule for inner program blocks implies that ↓ types, constants, and routines which are to be common for ↓ several programs compiled as one unit must be specified in a ↓ context.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆14┆┆b3┆┆b0┆┆06┆┆0b┆↲ ┆b0┆┆a1┆9. PROCESS CONTROL AND INTER-COMMUNICATION↲ ↲ This chapter describes the predefined language constructs ↓ available for control of offspring processes and for ↓ exchange of information between processes.↲ ↲ An incarnation of a sub-program is called a child of a ↓ (parent) process which is an incarnation of the program ↓ containing the sub-program declaration.↲ ↲ The navel string between the parent and the child is a ↓ variable of type process belonging to the parent. An ↓ arbitrary number of incarnations of a sub-program may be ↓ born; they are all controlled by the parent.↲ ↲ When a child is born it is supplied with actual parameters ↓ according to the formal parameter specifiction of the ↓ declaration, cf. section 6.1. Processes communicate via ↓ mailboxes or shared variables. A mailbox or a shared ↓ variable known by a parent may be made known as a paramter ↓ to its children (such a variable may either be owned by the ↓ parentor one of its ancestors). In this way a parent ↓ determines the communication paths of its children without, ↓ however, necessarily participating in the communication ↓ itself. Refer to section 5.10 for communication by means of ↓ shared variables and section 9.2 for mailbox communication.↲ ↲ ↲ ┆b0┆┆a1┆9.1 Process Control↲ ↲ A sub-program declaration in a program implies the ↓ allocation of a sub-program object in the stack of an ↓ incarnation of theprogram. The states of a sub-program ↓ object are ┆a1┆linked┆e1┆ and ┆a1┆unlinked┆e1┆, cf. section 6.2.1 for the ↓ initial state of a subprogram object.↲ ↲ The linking (i.e. change of state from unlinked to linked) ↓ is performed by a link call which is similar to a function ↓ call.↲ ↲ ↲ ↲ ↲ ┆8c┆┆84┆┆84┆↓ The type of the result of alink call is an implementation ↓ dependend predefined enumeration type↲ link_result= (link_ok, already_linked, external_not_found, ↓ ...).↲ ↲ The purpose of a link call is to find a suitable program ↓ block matching the sub-program declaration. The value of the ↓ expression, which must be of a string type, is used to ↓ search for the program block in a fashion which is ↓ implementation dependent. the 'formal parameters' of the ↓ sub-program declaration may also be used in the match. If a ↓ program block is found it is linked to the sub-program ↓ object denoted by the 'program_name'.↲ ↲ The result of a link call indicates that the linking was ↓ successful or why it went wrong.↲ ↲ If the implementation and installation allows dynamic ↓ program load, the executionof a link call may involve the ↓ loading of a suitable program as well as the necessary ↓ linkage editing.↲ ↲ If a new program block is to be linked to a sub-program ↓ object, the former link must be broken, i.e. the state of ↓ the sub-program object has to be changed from linked to ↓ unlinked. This is done by means of an unlink call, which is ↓ similar to a function call:↲ ↲ ↲ ↲ ↲ The result of an unlink call is of the implementation ↓ dependent predefined enumeration type↲ unlink_result= (unlink_ok, no_program_linked,↲ ╞ ╞ existing_incarnations, ...)↲ ↲ After the call, if successful, the sub-program object may be ↓ linked anew (link call).↲ ↲ ┆8c┆┆83┆┆d4┆↓ Processes may be created as incarnations of sub-programs in ↓ the linked state. When a process has been created it will ↓ begin to execute its actions. A process may become ↓ temporarily unable to execute actions for two reasons, which ↓ are independent of each other. It may be ┆a1┆waiting┆e1┆ for an ↓ event, cf. subsection 9.2.2, or ┆a1┆stopped┆e1┆, cf. the predefined ↓ procedures stop and resume described below. A process is ↓ only able to execute actions if it is neither waiting nor ↓ stopped. The dynamic allocation of processor time to ↓ processes with the latter property is the scheduling ↓ function performed by the operating system or language-↓ supporting nucleus.↲ ↲ A process is created by means of a create call.↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ ↲ The evaluation of a create call causes an incarnation of the ↓ program block linked to the sub-program object denoted by ↓ 'program_name' to be created as described in section 6.2. If ↓ the state of the sub-program object is unlinked a fault will ↓ occur. When a process has just been created it is neither ↓ stopped nor waiting.↲ ↲ The value of the 'name_expression', which must be of a ↓ string type, is attached to the created process for ↓ diagnostic purposes.↲ ↲ The 'process_object denotation' denotes the variable through ↓ which the calling process will control the child; it must be ↓ ┆8c┆┆83┆┆c8┆↓ of type process. The value of this variable must be NIL ↓ before the call, otherwise a fault occurs. After the call it ↓ will be a reference to the child process. ↓ ↲ The 'actual parameters' of the program call are bound to the ↓ corresponding formal parameters as part of the evaluation of ↓ the create call.↲ ↲ The initial size of the stack which is allocated for the ↓ created procedss is determined by the value of the ↓ 'size_expression' which must be of type 0..maxint. Size 0 ↓ means allocation of an area according to a value defined for ↓ the sub-program at compile-time, cf. chapter 12. The unit of ↓ measurement for stack size is implementation dependent.↲ ↲ The value of the 'priority_expression' determines the ↓ execution priority of the created process. This quantity ↓ affects the way in which the process is scheduled for ↓ executionin a fashion which depends on the implementation. ↓ The type required of the expression also depends on the ↓ implementation.↲ ↲ The result of a create call has an implementation dependent ↓ predefined enumeration type↲ create_result= (create_ok, no_memory, ...).↲ ↲ If the create call was unsuccessful the result will indicate ↓ the reason. In this case no process will have been created ↓ and the value of the process variable will still be NIL.↲ ↲ The predefined procedures stop, resume, and remove may be ↓ used to control a child, designated by a process variable ↓ passed as a parameter. If one of the procedures is called ↓ with this variable equal to NIL a fault will occur.↲ ↲ PROCEDURE stop(VAR pr: process)↲ ↲ ┆8c┆┆83┆┆bc┆↓ The child process becomres stopped. If it is already stopped ↓ before the call there is no effect.↲ ↲ PROCEDURE resume(VAR pr: process)↲ ↲ If the child process is stopped a call of resume makes it ↓ not stopped; otherwise the call has no effect.↲ ↲ PROCEDURE remove(VAR pr: process)↲ ↲ A call of remove causes the child process to be removed, ↓ i.e. execution of its action part is terminated and all ↓ resources owned by the child are released and become free ↓ memory. The resources include stack, heap, and pools. Any ↓ ports owned by the process are closed (cf. section 11.1). ↓ Pools and buffers are handled as follows:↲ ↲ 1. ┆84┆All buffers which have a pool owned by the child process ↓ ┆19┆┆83┆┄┄as their home pool are marked for deallocation. A special ↓ ┆19┆┆83┆┄┄treatment is given to a buffer stack whose top buffer is ↓ ┆19┆┆83┆┄┄marked for deallocation, in the following situations:↲ ↲ - ┆84┆A process calls putbuf (cf. section 3.8) attempting to ↓ ┆19┆┆85┆┄┄put the buffer in its home pool (in this case the ↓ ┆19┆┆85┆┄┄buffer must be alone in the stack), ↓ ↲ - ┆84┆A process calls return (cf. subsection 9.2.2) ↓ ┆19┆┆85┆┄┄attempting to place the stack in the return address ↓ ┆19┆┆85┆┄┄mailbox of the top buffer,↲ ↲ - ┆84┆An attempt is made to place the stack in the return ↓ ┆19┆┆85┆┄┄address mailbox of the top buffer as an IMC event (cf. ↓ ┆19┆┆85┆┄┄chapter 11) or as described below.↲ ↲ ┆84┆In all three cases the special treatment is the ↓ ┆19┆┆83┆┄┄following. First the top buffer is removed from the stck ↓ ┆19┆┆83┆┄┄and released to become free memory. Then the remainder of ↓ ┆19┆┆83┆┄┄the stack, if non-empty, is placed in the return address ↓ ┆8c┆┆83┆┆c8┆↓ ┆19┆┆83┆┄┄mailbox of the new top buffer, except if this buffer is ↓ ┆19┆┆83┆┄┄also marked for deallocation in which case the rule ↓ ┆19┆┆83┆┄┄applies recursively. The event kind attribute of a buffer ↓ ┆19┆┆83┆┄┄returned in this fashion becomes process_removed.↲ ↲ 2. ┆84┆All buffer stacks accessed through reference or chain ↓ ┆19┆┆83┆┄┄variables or presently placed in mailboxes owned by the ↓ ┆19┆┆83┆┄┄child process are placed in the return address mailbox of ↓ ┆19┆┆83┆┄┄the top buffer with the event kind attribute equal to ↓ ┆19┆┆83┆┄┄process_removed. If the top buffer is marked for ↓ ┆19┆┆83┆┄┄deallocation the above rule applies.↲ ↲ If the process to be removed has any children, these are ↓ removed before the process itself. This rule applies ↓ recursively. Thus, in effect, removal of a process means ↓ removal of that subtree of the complete process three of ↓ which the process is the root.↲ ↲ After a call of remove the value of the parameter is NIL.↲ ↲ If a process shares a pool with a child, i.e. if the pool ↓ was passed as a process parameter when the child process was ↓ created, the process must not remove that child. If an ↓ attempt is made a fault occurs. However, if the process ↓ itself is removed, the child will also be removed by the ↓ recursion described above.↲ ↲ It is illegal to remove a child process while it is ↓ executing a region statement. An attempt to do so causes a ↓ fault.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆Example:↲ ↲ link_res:=link("child1", my_child);↲ IF link_res <> link_ok THEN link_error(link_res);↲ create_res:=create("child_1_1", my_child(mbx1), process1, 0, ↓ std_prio);↲ IF create_res <> create_ok THEN create_error(create_res);↲ create_res:=create(Wchild_1_2", my_child(mbx2), process2, 0, ↓ std_prio);↲ IF create_res <> create_ok THEN create_error(create_res);↲ ...↲ stop(process6);↲ ...↲ resume(process6);↲ ...↲ remove(process4);↲ create_res:=create("child_2_4", my_child(alternative_mbx),↲ process4, 200, high_prio);↲ IF ...↲ ...↲ ↲ ↲ ┆b0┆┆a1┆9.2 Mailbox Communication↲ ↲ Messages may be passed among processes via mailboxes. A ↓ message is the contents of a stack of buffers, which is ↓ accessed through a variable of type reference or chain. At ↓ most one reference or chain variable holds a reference to a ↓ buffer at any time; thus mutually exclusive access to ↓ buffers is ensured.↲ ↲ Access to the data contained in a buffer is only possible in ↓ a lock statement (cf. section 5.9).↲ ↲ The access right is exchanged between processes by means of ↓ the predefined procedures signal, wait, waitdelay, and ↓ return as described in subsection 9.2.2.↲ ↲ ↲ ┆8c┆┆83┆┆d4┆↓ ┆b0┆┆a1┆9.2.1 Mailbox States↲ ↲ A mailbox may be regarded as a waiting room in one of the ↓ states passive, open or locked:↲ ↲ passive:↲ ┆a1┆ mbx ↲ Neither buffers to be accessed nor processes ↓ ┆a1┆ ┆e1┆ asking for access at the mailbox.↲ ↲ open:↲ ┆a1┆ mbx ┆e1┆ A list of buffers (actually buffer stacks) are ↲ buf1 ready for access, the first one will be removed↲ buf2 from the list when a process asks for a buffer,↲ buf3 and the process will be given the access right.↲ ┆a1┆ buf4 ↲ ↲ locked:↲ ┆a1┆ mbx ┆e1┆ A list of processes are waiting for access to a ↲ proc1 buffer; the first one will get the access right to↲ proc2 the next buffer arriving at the mailbox and will↲ proc3 subsequently be removed from the list.↲ ┆a1┆ proc4 ↲ ↲ There are three predefined boolean functions to inspect the ↓ state of a mailbox. However, it is not mandatory that these ↓ functions be implemented.↲ ↲ FUNCTION open(VAR mbx: mailbox): boolean↲ FUNCTION locked(VAR mbx: mailbox): boolean↲ FUNCTION passive(VAR mbx: mailbox): boolean↲ ↲ ↲ ┆b0┆┆a1┆9.2.2 Communication and Synchronization Primitives↲ ↲ There are four predefined communication/synchronization ↓ primitives: signal, return, wait, and waitdelay. In addition ↓ the delay primitive may be used for purposes of ↓ synchronization or temporary process suspension.↲ ↲ ┆8c┆┆83┆┆e0┆↓ Signal is performed by a call of the predefined procedure ↓ signal:↲ ↲ PROCEDURE signal(VAR mbx: mailbox; VAR ref: reference)↲ The value of ref must not be NIL or the reference locked ↓ (cf. section 5.9), otherwise a fault occurs. After the call, ↓ the buffer designated by ref is entered as the last element ↓ of the list of buffers belonging to mbx. If the mailbox is ↓ locked, the first process is removed from the list of ↓ waiting processes. This process is now allowed to complete ↓ the call of wait/waitdelay which caused its insertion in the ↓ list of the mailbox. The event kind attribute of the ↓ designated buffer becomes message_event.↲ ↲ The language provides two kinds of events which can be ↓ waited for:↲ - the arrival of a buffer at a specified mailbox.↲ - ┆84┆the expiry of a delay, specified as a number of ↓ ┆19┆┆82┆┄┄milliseconds. An implementation need not, however, support ↓ ┆19┆┆82┆┄┄such fine granularity. If the delay is specified as zero, ↓ ┆19┆┆82┆┄┄the call (delay, waitdelay, or getbufdelay) will return ↓ ┆19┆┆82┆┄┄immediately.↲ ↲ A process may wait for one specific event or for the first ↓ one of two, one of each kind. It does so by calling one of ↓ the following routines.↲ ↲ PROCEDURE wait(VAR mbx: mailbox; VAR ref: reference)↲ The value of ref must be NIL prior to a call, otherwise a ↓ fault occurs. If the mailbox mbx is open, the first buffer ↓ stack in the list is removed and ref will designate this ↓ stack. If the mailbox state is locked or passive the process ↓ is suspended until one of the events eventually occurs. The ↓ result indicates the reason why the process is activated; ↓ its type is the predefined enumeration type↲ wait_result= (a_buffer, a_delay).↲ ↲ ┆8c┆┆83┆┆bc┆↓ Getting a buffer from a pool, cf. section 3.8, is similar to ↓ receiving a buffer from a mailbox. A special version of ↓ getbuf is therefore available which allows the specification ↓ of a maximum delay which a process will tolerate.↲ ↲ FUNCTION getbufdelay(VAR p: pool; VAR ra: mailbox;↲ VAR r: reference; no_of_msecs: 0..maxint): ↓ wait_result↲ ↲ The description of getbuf, cf. section 3.8, applies also to ↓ getbufdelay with the modification that in case the delay ↓ specified by no_of_msecs expires before the calling process ↓ obtains a buffer the call will return the result a_delay and ↓ otherwise have no effect. If a buffer is obtained the result ↓ will be a_buffer.↲ ↲ Return is performed by a call of the predefined procedure ↓ return:↲ ↲ PROCEDURE return(VAR ref: reference)↲ The call:╞ ╞ return(ref)↲ is equivalent to:╞ signal(ret_address, ref)↲ where ret_address denotes the return address of the buffer ↓ designated by ref, cf. section 3.8, except for the value of ↓ the event kind attribute which becomes answer_event.↲ ↲ ┆a1┆Notes:↲ A mailbox may be inspected without hving to wait if it is ↓ empty by calling waitdelay with zero delay.↲ ↲ An implementation must secure indivisibility of the ↓ communication primitives.↲ ↲ ┆a1┆Example:↲ The following communication flow is possible by means of ↓ signal and return. Each process p┆82┆i┆81┆ must know the (mailbox) ↓ address of process pi+1┆81┆. However, process p┆82┆n┆81┆ does not know ↓ process p┆82┆1┆81┆.↲ ↲ ┆8c┆┆83┆┆d4┆↓ signal╞ signal╞ ╞ signal↲ ↲ ↲ p┆82┆1┆81┆ p┆82┆2┆81┆ ... p┆82┆n┆81┆↲ ↲ ╞ ╞ return↲ ↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆10. BUFFER MANIPULATION↲ ↲ Two structures for organizaing buffers are supported by the ↓ language: stacks and chains. A buffer stack is the general ↓ form of a message, where a stack with only one buffer is a ↓ special case. Access to a stack may be transferred between ↓ processes via a mailbox (cf. section 9.2). The chain ↓ structure is intended for local organization of buffers in ↓ aprocess. The elementsof a chain are buffer stacks. They are ↓ accessed by a handle: a variable of type chain. The elements ↓ of a buffer stack are buffers. They are accessed by a ↓ handle: a reference variable (or directly by a chain in the ↓ case of the current buffer). The manipulation of buffer ↓ stacks is described in section 10.1 and of chains in section ↓ 10.2.↲ ↲ ↲ ┆b0┆┆a1┆10.1 Buffer Stacks↲ ↲ A stack is one or more buffers, organized as a lifo list so ↓ that manipulation affects the youngest member only. Access ↓ to the data in a stack of buffers is achieved by means of a ↓ lock statement, possibly giving access to several members of ↓ the stack (cf. secion 5.9).↲ ↲ Access to the attributes of buffers in a stack can only be ↓ made to those of the top (youngest) member. A special ↓ treatment is given to the size and data description ↓ attributes when empty buffers are pushed onto or popped from ↓ a stack, ensuring that these attributes will apply to the ↓ topmost non-empty buffer in the stack, since only non-empty ↓ buffers can be accessed in a lock statement.↲ ↲ A stack may be manipulated by calling the predefined ↓ procedures push and pop. The parameters to these procedures ↓ must not be locked. Otherwise a fault will occur at the time ↓ of call.↲ ↲ ┆8c┆┆83┆┆c8┆↓ PROCEDURE push(VAR stack_handle, new_top: reference)↲ ↲ The parameter new_top must designate a buffer stack with ↓ only one element, otherwise a fault occurs. The buffer stack ↓ designated by stack_handle, possibly an empty stack (i.e. ↓ the handle is NIL), is extended with the buffer designated ↓ by new_top as the new top element. After the call ↓ stack_handle will designate the new stack, and the value of ↓ new_top will be NIL.↲ ↲ If the new top buffer is empty, and the stack was not empty ↓ before pushing, the size and data area description (offset, ↓ top, and byte count) are copied from the old to the new top ↓ buffer.↲ ↲ PROCEDURE pop(VAR stack_handle, popped_buf: reference)↲ ↲ The value of popped_buf must be NIL, and the value of ↓ stack_handle must not be NIL; otherwise a fault occurs. The ↓ result of a call of pop is: the top buffer in the stack is ↓ removed, popped_buf will designate a stack consisting of the ↓ removed buffer only, and stack_handle will designate the ↓ remaining part of the stack. If the stack had only one ↓ element its value will be NIL.↲ ↲ If the popped buffer is empty, its size and data area ↓ description attributes (offset, top, and byte count) are all ↓ set to zero.↲ ↲ The depth of a buffer stack as well as the number of actual ↓ data buffers can be obtained by using the predefined ↓ functions stckdepth and bufcount.↲ ↲ FUNCTION stackdepth(VAR stack: reference): 0..maxint↲ FUNCTION bufcount(VAR stack: reference): 0..maxint↲ ↲ The value returned by stackdepth is the total number of ↓ buffers in the designated stack, including empty ones, ↓ ┆8c┆┆83┆┆c8┆↓ whereas bufcount yields only the number of non-empty buffers ↓ (cf. lock statement, section 5.9). Both functions return the ↓ value 0 if the parameter has value NIL.↲ ↲ ┆a1┆Example:↲ The following flow of buffers may be achieved by means of ↓ the paired operations: (push, signal) and (pop, return).↲ ↲ ╞ (signal)╞ ╞ (push, signal)╞ (push, signal)↲ ↲ ↲ p╞ ╞ p ...╞ p╞ ╞ p↲ ┆81┆1 2 n-1 n↲ ↲ ╞ (pop, return)╞ (pop, return)╞ (return)↲ ↲ ↲ ┆b0┆┆a1┆10.2 Buffer Chains↲ ↲ The initial state of a chain object is empty, i.e. the ↓ length of the chain is 0. Cyclic lists are built and ↓ manipulated by means of predefined routines only. The ↓ following actions may be performed on chains: insert an ↓ element, extract an element, change current buffer, update ↓ start point, and read the length.↲ ↲ Two elements of a chain have a special status:↲ ↲ - ┆84┆the ┆a1┆start point┆e1┆ of the chain is the first element put into ↓ ┆19┆┆82┆┄┄the chain or an element explicitly selected as the start ↓ ┆19┆┆82┆┄┄point.↲ ↲ - ┆84┆the ┆a1┆current buffer (stack)┆e1┆ is the element which may be ↓ ┆19┆┆82┆┄┄extracted or accessed in a lock statement and the only ↓ ┆19┆┆82┆┄┄element whose buffer attributes may be read or changed.↲ ↲ The predefined routines eventkind, resetevent, u1, u2, u3, ↓ u4, setu1, setu2, setu3, setu4, bufsize, offset, top, ↓ ┆8c┆┆83┆┆c8┆↓ bytecount, setoffset, settop, and setbytecount which are ↓ described in section 3.8 may all be called with a chain ↓ object as parameter, in which case they apply to the current ↓ stack (top buffer) of the chain.↲ ↲ The length of a chain is read by means of a call of the ↓ function chainlength:↲ ↲ FUNCTION chainlength(VAR ch: chain): 0..maxint↲ ↲ For all the routines described in the remainder of this ↓ section the parameter (chains and references) must not be ↓ locked. Otherwise a fault occurs at the time of call.↲ ↲ A buffer stack is inserted into a chain by means of a call ↓ of chaininsert:↲ ↲ PROCEDURE chaininsert(VAR ch: chain; VAR ref: reference)↲ ↲ The value of ref must not be NIL, otherwise a fault occurs. ↓ The stack designated by ref becomes the new current buffer f ↓ the list, the element is inserted as the successor of the ↓ element which was the current buffer prior to the call, and ↓ the value of ref becomes NIL.↲ ↲ The current buffer may be removed from a list by meansof a ↓ call of chainextract:↲ ↲ PROCEDURE chainextract(VAR ch: chain; VAR ref: reference)↲ ↲ The value of ref must be NIL, otherwise a fault occurs. If ↓ the length of the chain ch is 0 a fault occurs. The current ↓ buffer is removed from the chain and will be designated by ↓ ref. the successor of the removed element becomes the new ↓ current buffer. If the start point is removed from a list ↓ with more than one element the successor of the removed ↓ element becomres the new start point as well as the new ↓ current buffer.↲ ↲ ┆8c┆┆83┆┆d4┆↓ The current buffer may be moved one step up or down the ↓ list, or moved to the start point by calling the procedures ↓ chainup, chaindown and chainstart respectively:↲ ↲ PROCEDURE chainup(VAR ch: chain)↲ PROCEDURE chaindown(VAR ch: chain)↲ PROCEDURE chainstart(VAR ch: chain)↲ The result of a call of chainup/chaindown/chainstart is that ↓ the successor/predecessor/start point becomes the new ↓ current buffer of the list.↲ ↲ The current buffer of a list may be made the new start point ↓ of a list by a call of chainreset:↲ ↲ PROCEDURE chainreset(VAR ch: chain)↲ ↲ ┆a1┆Example:↲ Let ch be the handle of a sorted chain of buffers:↲ ↲ chainstart(ch);↲ FOR count:=1 TO chainlength(ch) DO↲ BEGIN↲ chainextract(ch, work_ref);↲ push(result_stack, work_ref)↲ END(*FOR*);↲ signal(mail_center, result_stack)↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆11. IMC FUNCTIONS↲ ↲ The concept of a resident module is introduced in (4) as a ↓ well defined entity, which is self-contained in terms of ↓ resources. In Real-Time Pascal a resident is thus a tree of ↓ processes whose root does not enherit any resources. That ↓ is, no pool or port is made known to the root of the ↓ resident as a process parameter. However, the concept of ↓ resident is not reflected in the syntax of Real-Time Pascal ↓ or in rules enforced by the language.↲ ↲ Residents exist in a destributred environment and ↓ communicate with eachother by using the standard inter ↓ module communication (IMC) services (5). The embedding of ↓ these services into Real-Time Pascal is the scope of the ↓ present chapter. In the remainder of the chapter the ↓ software components at the IMC nodes plus the physical ↓ interconnection media which together provide the IMC ↓ services are referred to as the IMC network or just the IMC.↲ ↲ A resident gains access to IMC services via objects of the ↓ type port. Port names, in turn, establish the identification ↓ of residents towards the IMC network and towards one ↓ another. Port names consist of a maximum of 12 graphic ↓ characters. Communication between two residents takes place ↓ as transfers of strings of bytes from buffers belonging to a ↓ sender to buffers belonging to a receiver. an actual ↓ transfer within the IMC network takes place when both ↓ residents have delivered a buffer to the IMC.↲ ↲ The principal means of communication is connections between ↓ two ports. On a connection the IMC perform flow control, ↓ correct sequencing, and undamaged data transfer.↲ ↲ The relationship between invokation and completion of IMC ↓ functions is asynchronous. IMC services are invoked by calls ↓ of predefined service request routines. In most cases a call ↓ of a rquest routine causes the transfer of a buffer (or two) ↓ ┆8c┆┆83┆┆c8┆↓ from the calling resident to the IMC. When the requested ↓ function has been carried out this buffer, called an ┆a1┆event ↓ ┆19┆┄┄┆84┆buffer┆e1┆, will be returned, i.e. to its return address ↓ mailbox, with relevant result information andpossibly ↓ containing received data. The return of an event buffer to a ↓ resident is called an ┆a1┆IMC event┆e1┆, or just an event. The ↓ interface between residents and the IMC has been designed so ↓ that no change, which is of significance to a resident, in ↓ the state of a port or connection end-point can take place ↓ without the occurrence of an event, unless it occurs during ↓ a call of a request routine and as a direct consequence of ↓ this call. In other words, despite the asynchronous nature ↓ of the interface, residents always have complete up-to-date ↓ information about their ports and connections.↲ ↲ During the time-span from an event buffer has been ↓ transferred to the IMC until it is eventually returned it is ↓ said to be outstanding. An outstanding event buffer may be ↓ further characterized by the kind of event it is intended to ↓ retrieve. All IMC events correspond to values of the ↓ predefined enumeration type event_type which is given in ↓ section 3.8. All IMC events are described in the following ↓ sections.↲ ↲ In some cases the IMC will return an event buffer even ↓ though the intended event has not occurred, most often ↓ because circumstances change so that it never will. This is ↓ called a dummy event. As an example, an outstanding data ↓ buffer is returned as a dummy event when the connection to ↓ which it pertains is unexpectedly removed. A number of ↓ event_type values are used exclusively for dummy events. ↓ Each of these values indicates the event which the dummy ↓ event buffer had been set up to retrive. The correspondence ↓ between dummy event kinds and intended event kinds is shown ↓ below:↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆dummy event╞ ╞ intended event┆05┆↲ dummy_letter╞ ╞ letter_arrived↲ dummy_lcnct╞ ╞ local_connect↲ dummy_rcnct╞ ╞ remote_connect↲ dummy_rindic╞ ╞ reset_indication↲ dummy_rcmpl╞ ╞ reset_completion↲ dummy_credit╞ ╞ credit↲ dummy_sent╞ ╞ data_sent↲ dummy_arrived╞ ╞ data_arrived↲ ↲ In addition to request routines Real-Time Pascal provides ↓ routines which can decode event information by inspecting ↓ the IMC buffer attributes used to carry this information.↲ ↲ The IMC service request routines are described in the ↓ following three sections. With a single exception (connect, ↓ see subsection 11.3.2) the reference type parameters to ↓ these routines must not have value NIL or be locked when a ↓ call is made; otherwise a fault will occur. These parameters ↓ are used to transfer event buffer to the IMC, and they ↓ always have value NIL after a call.↲ ↲ The IMC never changes the size, offset, top, or u-attributes ↓ of an event buffer. With the exception of actual data ↓ buffers (sendletter, receiveletter, send, receive, ↓ receiveall) is always placed in the data area of the receive ↓ buffer, and the number of bytes it comprises is assigned to ↓ the byte count attribute.↲ ↲ The data area description of the buffer passed by a call of ↓ a data transfer routine must be consistent, cf. section 3.8. ↓ Otherwise a fault occurs.↲ ↲ ↲ ┆b0┆┆a1┆11.1 Ports↲ ↲ An IMC port is represented in Real-Time Pascal as a variable ↓ of type port. The state of a port is either open, in which ↓ ════════════════════════════════════════════════════════════════════════ ↓ case the port is known in the IMC network by a name which is ↓ puslished according to its scope, or closed (or closing, see ↓ under closeport below).↲ ↲ An open port contains a number of connection end-points (cf. ↓ section 11.3). The number must not be greater than an ↓ implementation dependent maximum, cf. section 11.5).↲ ↲ The attributes of a port, i.e. name, scope, and number of ↓ endpoints, are defined when it is opened by a call of ↓ openport:↲ ↲ PROCEDURE openport(VAR p: port; VAR closebuf: reference;↲ ╞ ╞ INSPEC name: string; scope: scope_type;↲ ╞ ╞ no_of_cons: 0..maxint; rcv_all: boolean)↲ where p is the port to be opened. The parameter closebuf ↓ designates the port_closed event buffer which will be ↓ outstanding while the port is open. The values of the name ↓ and scope parameters specify the name of the port and the ↓ range within the IMC network in which to publish the name. ↓ The value of no_of_cons is the number of connection end-↓ points requested for the port. If this number is greater ↓ than the maximum allowed or if the length of the name is ↓ greater than 12 a fault will occur.↲ ↲ The type of the scope parameter is the predefined ↓ enumeration type↲ ╞ scope_type= (anonymous, local, regional, global).↲ For a further discussion of scopes, see (5).↲ ↲ The call causes the port to be opened as requested. The ↓ state of the port must be closed when the call is made, ↓ otherwise a fault occurs. After the call the state of the ↓ port is open. The port_closed event will occur when it is ↓ eventually closed with one of the following reasons (cf. ↓ section 11.4):↲ ↲ ╞ reason_ok:╞ the resident called closeport↲ ╞ reason_name:╞ a name-conflict arose↲ ╞ reason_resource:╞ ┆84┆resource problem somewhere in the ↓ ┆19┆┆98┆┄┄IMC network.↲ ↲ ┆8c┆┆83┆┆f8┆↓ If the value of the parameter rcv_all is true, the general ↓ receive feature (cf. receiveall, subsection 11.3.2) is ↓ enabled for the port; otherwise it is not.↲ ↲ A port is withdrawn from the IMC network by a call of ↓ closeport:↲ ↲ PROCEDURE closeport(VAR p: port)↲ ↲ where p is the port to be closed. If the port is already ↓ closed the call has no effect. Otherwise it proceeds as ↓ follows. All connections on the port are removed with ↓ graceful completion of any feasible data transfers as ↓ described for disconnect, cf. subsection 11.3.2. The ↓ disconnected events occur with reason_closed. However, at ↓ the remote end of a connection the disconnected event occurs ↓ with reason_ok. Then all general receive and letter receive ↓ buffer are returned as dummy events, and finally the ↓ port_closed event occurs with reason_ok. The port is made ↓ unknown to the IMC network, its state changes to closed, and ↓ it may subsequently be re-opened, possibly with a different ↓ set of attributes. While connections are being removed and ↓ buffers returned the port is said to be closing.↲ ↲ ↲ ┆b0┆┆a1┆11.2 Letters↲ ↲ The most primitive form of data transfer supported by the ↓ IMC is a letter which may be transferred directly to a ↓ destination port without the overhead of establishing a ↓ connection, without flow control or end-to-end control, and ↓ without the guarantee of delivery.↲ ↲ In order to receive a letter a resident must call ↓ receiveletter:↲ ↲ PROCEDURE receiveletter(VAR p: port; VAR databuf: reference)↲ ↲ ┆8c┆┆83┆┆c8┆↓ where p is the receiving port and databuf designates the ↓ receive buffer. If theport is closed or closing the receive ↓ buffer is returned as a dummy event and the call has no ↓ further effect. Otherwise the receive buffer will be ↓ outstanding until a letter arrives and then be returned as ↓ letter_arrived. Letters are truncated to fit into a receive ↓ buffer, if necessary.↲ ↲ A letter is sent by means of a call of sendletter:↲ ↲ PROCEDURE sendletter(INSPECT destination: string;↲ ╞ ╞ VAR databuf: reference)↲ ↲ where databuf designates the send buffer containing the ↓ letter to be sent, and the destination parameter is the name ↓ of the receiving port.↲ ↲ When a letter is sent towards a receiving resident, the send ↓ buffer is returned as letter_sent. This does not imply that ↓ the letter will actually be delivered, only that an attempt ↓ will be made. The letter may be lost due to buffer shortage ↓ in the IMC network, because the receiver has no outstanding ↓ buffer for arriving letters, or because the port name is ↓ unknown.↲ ↲ If the size of a letter is greater than an implementation ↓ dependent maximum, cf. maxlettersize (section 11.5), it may ↓ be truncated during transfer through the IMC network. ↓ Neither sender nor receiver will be notified in this case.↲ ↲ ↲ ┆b0┆┆a1┆11.3 Connections↲ ↲ Connections are the principal means of data transfer between ↓ residents. A connection joins two connection end-points, ↓ each contained in an open port. Before a connection can be ↓ established one of the two residents must make a connection ↓ end-point available by calling getconnection (cf. subsection ↓ ┆8c┆┆83┆┆c8┆↓ 11.3.2). The resident which calls getconnection is the ↓ passive part in the establishment of the connection and need ↓ not know the name of the remote port. The other resident is ↓ the active part which must specifically request that a ↓ connection be established by calling connect (cf. subsection ↓ 11.3.2).↲ ↲ An end-point within a port is identified in a request call ↓ by a pair (p, index) where p is a port and index is a number ↓ in the range 1..n, where n equals the value of no_of_cons ↓ given when the port was opend. This fact accounts for the ↓ first two parameters of all the rquest routines described in ↓ this section (except receiveall). If a request call is made ↓ iwth an index parameter which is out of range a fault ↓ occurs.↲ ↲ Notice that end-point indices are local to a port and not ↓ related to indices or even known at the remote end-points of ↓ connections.↲ ↲ Each kind of request call which may be made concerning a ↓ connection end-point is only permitted provided the end-↓ point is in an appropriate state. The applicable states are:↲ ↲ free:╞ ┆84┆the end-point is free for use by calling ↓ ┆19┆┆8f┆┄┄connect or getconnection. Free is the initial ↓ ┆19┆┆8f┆┄┄state of connection end-points contained in a ↓ ┆19┆┆8f┆┄┄newly opened port,↲ accept_remote: ┆84┆getconnection has been called. The end-point ↓ ┆19┆┆8f┆┄┄will leave this state when a connection is ↓ ┆19┆┆8f┆┄┄established from a remote port, or when ↓ ┆19┆┆8f┆┄┄disconnect is called,↲ connected:╞ ┆84┆a connection has been or is being ↓ ┆19┆┆8f┆┄┄established, and data transfer may take ↓ ┆19┆┆8f┆┄┄place,↲ resetting:╞ ┆84┆reset has been called while the state was ↓ ┆19┆┆8f┆┄┄connected. The state will revert to connected ↓ ┆19┆┆8f┆┄┄when the resetting procedures have been ↓ ┆19┆┆8f┆┄┄completed,↲ ┆8c┆┆83┆┆d4┆↓ disconnecting: ┆84┆disconnect has been called, and the process ↓ ┆19┆┆8f┆┄┄of removing a previous connection is under ↓ ┆19┆┆8f┆┄┄way. The state will subsequently become free.↲ ↲ If the end-point identification (p, index) given in a ↓ request call is such that the port is closed or closing, or ↓ the state of the end-point is free, the connection to which ↓ the call pertains is said to be ┆a1┆absent┆e1┆. This phenomenon may ↓ occur if the event which informs the resident about the ↓ removal of a connection or the closing of a port has not ↓ been processed at the time of call.↲ ↲ It is a general rule that if a request call is made ↓ concerning a connection end-point which is in a wrong state ↓ for the call a fault occurs, except if the connection is ↓ absent.↲ ↲ ↲ ┆b0┆┆a1┆11.3.1 Connection Administration↲ ↲ A connection end-point is made available for remotely ↓ initiated connection establishment by a call of ↓ getconnection:↲ ↲ PROCEDURE getconnection(VAR p: port; index: 1..maxint;↲ ╞ ╞ ╞ VAR compl, disc: reference)↲ If the port is closed or closing the buffer designated by ↓ compl is returned as a dummy event and the buffer designated ↓ by disc as a disconnected event with reason_closed, and the ↓ call has no further effect. Otherwise a call of ↓ getconnection is only permitted if the state of the end-↓ point is free; after the call it is remote_accpet. The ↓ buffer designated by compl will be returned as a ↓ remote_connect event when a connection has been established. ↓ The buffer designated by disc will be the disconnected ↓ buffer of the connection end-point. It will be outstanding ↓ until the end-point becomes free again.↲ ↲ ┆8c┆┆83┆┆c8┆↓ In order to establish a connection between a local ↓ connection end-point and a remote end-point, which has been ↓ made available as described above, a resident must call ↓ connect:↲ ↲ PROCEDURE connect(VAR p: port; index: 1..maxint;↲ ╞ ╞ VAR compl, disc: reference;↲ ╞ ╞ INSPECT remote_name: string:↲ ╞ ╞ service: conn_service)↲ If the port is closed or closing the buffer designated by ↓ compl is returned as a dummy event and the buffer designated ↓ by disc as a disconnected event with reason_closed, and the ↓ call has no further effect. Otherwise the call is only ↓ accepted if the state of the indicated end-point is free.↲ ↲ The value of remote_name is the name of the remote port to ↓ which a connection is requested. If the length of the name ↓ is greather than 12 a fault occurs. The state of the (local) ↓ end-point becomes connected, i.e. data transfer calls may be ↓ made immediately following the call of connect. This does ↓ not imply that the actual path through the IMC network has ↓ been established at this time, nor in fact that it ever will ↓ be.↲ ↲ The value of the parameter compl may be NIL, i.e. the ↓ designated buffer is optional. If it is present it will be ↓ used to generate a local_connect event when the actual ↓ connection has been successfully established. This event is ↓ purely informative and not associated with any change of ↓ state. If the local_connect buffer is present, but ↓ establishment of the connection fails, the buffer will be ↓ returned as a dummy event.↲ ↲ The buffer designated by disc is the disconnected event ↓ buffer. It will be outstanding until the state of the ↓ connection end-point eventually reverts to free or the port ↓ is closed. If this happens because it turns out to be ↓ impossible to establish the actual connection the reason ↓ ┆8c┆┆83┆┆c8┆↓ will be either reason_name, if a port with the specified ↓ name could not be found, or reason_resource, if the ↓ necessary resources were not available in the IMC network or ↓ at the remote port (no end-point with state accept_remote).↲ ↲ The service parameter selects the service class of the ↓ connection. Two service classes are defined: normal and ↓ high. The treatment of service classes depends on the ↓ implementation of the IMC network. The type of the service ↓ parameter is the predefined enumeration type↲ ╞ conn_service= (cs_normal, cs_high).↲ ↲ A connection end-point may always be freed by a call of ↓ disconnect:↲ ↲ PROCEDURE disconnect(VAR p: port; index: 1..maxint)↲ ↲ If the indicated connection is absent or if the state of the ↓ connection end-point is disconnecting the call has no ↓ effect. Otherwise if the connection end-point is engaged in ↓ a connection, i.e. if its state is connected or resetting, ↓ the connection will be removed. This will be done ↓ gracefully, i.e. all data transfers for which credit is ↓ available are completed before the remaining oustanding ↓ buffers are returned. At both ends of the connection all ↓ outstanding buffers ecept the disconnected event buffers are ↓ then returned as dummy events. While this takes place the ↓ state of the (local) end-point is disconnecting. Finally the ↓ disconnected events occur (at both ends) with reason_ok, and ↓ the state becomes free.↲ ↲ If the state of the connection end-point is accept_remote ↓ when disconnect is called the remote_connect buffer will be ↓ returned as a dummy event, the disconnected event will occur ↓ with reason_ok, and the state of the end-point becomes free.↲ ↲ The only reason for removal of a connection which has not ↓ been discussed above (this includes removal when a port is ↓ ┆8c┆┆83┆┆c8┆↓ closed, cf. section 11.1) is failure in some component of ↓ the IMC network. If a connection is broken for this reason ↓ the disconnected event will occur with reason_network after ↓ all other outstanding buffers have been returned as dummy ↓ events.↲ ↲ ↲ ┆b0┆┆a1┆11.3.2 Connection-based Data Transfer↲ ↲ The routines for data transfer on connections and for ↓ control of data buffers: send, receive, receiveall, ↓ getcredit, reset, and getreset, are described in this ↓ subsection.↲ ↲ The following rule holds for calls of all these routines ↓ except receiveall: If the connection indicated by the first ↓ two parameters is absent the buffer designated by the third ↓ parameter is returned as a dummy event and the call has no ↓ further effect. Otherwise the call is only permitted if the ↓ state of the end-point is connected (or resetting in the ↓ case of getreset).↲ ↲ A receive buffer is made available for a specific connection ↓ by a call of receive:↲ ↲ PROCEDURE receive(VAR p: port; index: 1..maxint;↲ ╞ ╞ VAR databuf: reference)↲ ↲ The designated buffer becomes an outstanding receive buffer ↓ for the connection. At the remote end of the connection the ↓ call may cause either a credit or a data_sent event to ↓ occur. If both kinds of event buffer are outstanding only ↓ the data_sent event will occur. When a unit of data has been ↓ transferred from a remote send buffer to the receive buffer ↓ the latter is returned as a data_arrived event. If ↓ necessary, the received data unit is truncated to fit into ↓ the data area of the receive buffer, and in this case the ↓ event will be data_overrun.↲ ↲ ┆8c┆┆83┆┆d4┆↓ If the general receive feature is enabled for a port (cf. ↓ the rcv_all parameter of openport, section 11.1) a general ↓ receive buffer for the whole port, not dedicated to a ↓ particular connection, may be delivered to the IMC by a call ↓ of receiveall:↲ ↲ PROCEDURE receiveall(VAR p: port; VAR databuf: reference)↲ ↲ If the port is closed or closing the designated buffer is ↓ returned as a dummy event and the call has not further ↓ effect. If the general receive feature is not enabled a ↓ fault occurs. Otherwise the buffer becomes an outstanding ↓ general receive buffer. It may be used for any connection ↓ within the port. It will eventually be returned as ↓ data_arrived or data_overrun, depending on whether the ↓ received data unit had to be trancated to fit into the ↓ receive data area. The index of the connection end-point to ↓ which the data belong will be an attribute of the buffer ↓ (cf. section 11.4). In case of network failure which causes ↓ a connection on the port to be removed the buffer may be ↓ returned as a dummy event.↲ ↲ A send buffer containing a unit of data to be sent on a ↓ specified connection is delivered to the IMC network by a ↓ call of send:↲ ↲ PROCEDURE send(VAR p: port; index: 1..maxint;↲ ╞ ╞ VAR databuf: reference)↲ ↲ The designated buffer becomes an outstanding send buffer. If ↓ a receive buffer is available at the remote end or when one ↓ becomes available (call of receive or receiveall) the ↓ indicated data unit is transferred to the receive data area. ↓ Then the send buffer is returned as data_sent, and the ↓ receive buffer at the remote end as data_arrived (or ↓ data_overrun).↲ ↲ ┆8c┆┆83┆┆bc┆↓ Flow control information pertaining to a specified ↓ connection can be obtained from the IMC by a call of ↓ getcredit:↲ ↲ PROCEDURE getcredit(VAR p: port; index: 1..maxint;↲ ╞ ╞ VAR credbuf: reference)↲ ↲ The designated buffer becomes an outstanding credit buffer. ↓ It is returned as a credit event when there is one or more ↓ outstanding receive buffers at the remote end of the ↓ connection (call of receive) for which credit has not been ↓ given previously. The number of such receive buffers is ↓ passed as the buffer attribute credit count (cf. section ↓ 11.4). However, a credit event can only occur provided there ↓ is at least one outstanding reset_indication buffer at the ↓ connection end-point, cf. getreset.↲ ↲ Data and credit buffers which are outstanding at an end-↓ point of a connection may be taken back without breaking the ↓ connection by calling reset:↲ ↲ PROCEDURE reset(VAR p: port; index: 1..maxint;↲ ╞ ╞ VAR compl: reference)↲ ↲ In the same graceful fashion as when a connection is removed ↓ all data transfers for which credit is available are carried ↓ out first. Then the remaining data and credit buffers are ↓ returned as dummy events, but only at the local end-point. ↓ The return of receive buffers may amount to the taking back ↓ of credit which has already been given to the remote ↓ resident. In this case the resulting negative credit is ↓ passed as the credit count attribute of a reset_indication ↓ event.↲ ↲ Following a call of reset the state of the (local) ↓ connection end-point will be resetting. The buffer ↓ designated by compl is the reset_completion event buffer. ↓ This event occurs after all outstanding data and credit ↓ ┆8c┆┆83┆┆c8┆↓ buffers have been returned. When it occurs the state of the ↓ end-point reverts to connected.↲ ↲ When a connection end-point has been reset the IMC has also ↓ reset its account of credit previously passed to the ↓ resident. Credit information obtained before resetting is ↓ therefore no longer valid.↲ ↲ If credit information is used it is necessary to know when ↓ credit is taken back as a result of resetting of the remote ↓ end-point. A reset_indication buffer which is used to carry ↓ this information is made available to the IMC by a call of ↓ getreset.↲ ↲ PROCEDURE getreset (VAR p: port; index: 1..maxint;↲ ╞ ╞ VAR indic: reference)↲ ↲ The call is permitted if the state of the connection end-↓ point is connected or resetting, but does not change the ↓ state. The buffer designated by indic becomes an outstanding ↓ reset_indication event buffer. That is, when a reset occurs ↓ at the remote end of the connection causing loss of credit ↓ this buffer is returned as reset_indication with a credit ↓ count equal to the number of credits that have been taken ↓ back.↲ ↲ At least one reset_indication buffer must be outstanding ↓ before a credit event can occur, cf. getcredit. Therefore a ↓ call of getreset may trigger a credit event.↲ ↲ ↲ ┆b0┆┆a1┆11.4 IMC Buffer Attribute Decoding↲ ↲ Whenever a buffer is returned as an event the event kind ↓ attribute is set to indicate the kind of event. This ↓ attribute may be read using the predefined function ↓ eventkind, cf. section 3.8. Depending on the event kind the ↓ attributes index, credit count, and reason may be ↓ ┆8c┆┆83┆┆c8┆↓ meaningful. These attributes may be read using the three ↓ functions described below. A fault will occur if one of ↓ these functions is called with a parameter with value NIL.↲ ↲ FUNCTION index(VAR r: reference): 0..maxint↲ gives the index in the relevant port of the connection end-↓ point to which the event pertains. It is defined for buffers ↓ with event kind local_connect, remote_connect, disconnected, ↓ reset_completion, reset_indication, data_sent, data_arrived, ↓ data_overrun, credit, and for fummy events. If the event is ↓ dummy and there is no applicable index the result will be 0.↲ ↲ FUNCTION reason(VAR r: reference): reason_type↲ gives the reason for an event. It is relevant for buffers ↓ with event kind port_closed or disconnected. The result is ↓ of the predefined enumeration type↲ ╞ reason_type= (reason_ok, reason_name, reason_resource,↲ ╞ ╞ reason_closed, reason_network).↲ ↲ All uses of reason values are explained in the preceding ↓ sections.↲ ↲ FUNCTION creditcount(VAR r: reference): 0..maxint↲ If the event kind is credit the result is the numer of ↓ receive buffers available at the remote end-point of the ↓ connection. If the event kind is reset_indication the ↓ resultis the number of credits which have been taken back by ↓ a call of reset at the remote end-point.↲ ↲ ↲ ┆b0┆┆a1┆11.5 Miscellaneous Routines↲ ↲ At teach node in an IMC network, the IMC imposes certain ↓ restrictions on users of the IMC services, namely a maximum ↓ size for a letter and a maximum number of connections to any ↓ ════════════════════════════════════════════════════════════════════════ ↓ one port. these two limitations can be obtained by calling ↓ the predefined routines maxlettersize and maxconnections:↲ ↲ FUNCTION maxlettersize: 0..maxint↲ FUNCTION maxconnections: 0..maxint↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆12. COMPILER DIRECTIVES↲ ↲ Directives to a Real-Time Pascal compiler may be regarded as ↓ lexical separators. They have the general form:↲ ╞ $ directive-name parameters end-of-line↲ given on a separate line and with parameters, if present, ↓ enclosed in parantheses. Alternatively directives may be ↓ supplied as parameters in the call of the compiler. Some of ↓ them must be specified before the first line of actual ↓ source text is met, viz. either in the compiler call or as ↓ $-directive lines in front of the outermost program/routine ↓ heading.↲ ↲ The following table lists the mandatory directives. An ↓ implementation may support additional directives. The first ↓ three directives which are all used to control the ↓ appearance of a compiler listing must appear before the ↓ first line of actual source text.↲ ↲ ┆a1┆name╞ parameters╞ description┆05┆↲ PAGELENGTH╞ number╞ ╞ maximum number of lines ↲ (default 45)╞ ╞ ╞ per page of listing,↲ ↲ PAGEWIDTH╞ number╞ ╞ maximum number of ↲ (default 120)╞ ╞ ╞ ┆84┆characters per line of ↓ ┆19┆┆a2┆┄┄listing,↲ ↲ TITLE╞ "char.string"╞ ┆84┆the character string is ↓ ┆19┆┆a2┆┄┄placed in the title field ↓ ┆19┆┆a2┆┄┄of the header line of each ↓ ┆19┆┆a2┆┄┄page of the listing,↲ ↲ SUBTITLE╞ "char.string"╞ ┆84┆the character string is ↓ ┆19┆┆a2┆┄┄placed in the subtitle ↓ ┆19┆┆a2┆┄┄line of each page of the ↓ ┆19┆┆a2┆┄┄listing,↲ ↲ ┆8c┆┆83┆┆bc┆↓ ┆a1┆name╞ parameters╞ description┆05┆↲ CODE╞ none╞ ╞ ┆84┆causes code generated for ↓ ┆19┆┆a2┆┄┄the following lines of ↓ ┆19┆┆a2┆┄┄source text to be listed,↲ ↲ NOCODE╞ none╞ ╞ suppresses listing of ↲ (default)╞ ╞ ╞ generated code,↲ ↲ CREATESIZE╞ number╞ ╞ ┆84┆determines stack size of ↓ ┆19┆┆a2┆┄┄incarnations of the ↓ ┆19┆┆a2┆┄┄following program(s) if ↓ ┆19┆┆a2┆┄┄the value of the ↓ ┆19┆┆a2┆┄┄size_expression of the ↓ ┆19┆┆a2┆┄┄careate call is 0, cf. ↓ ┆19┆┆a2┆┄┄section 9.1,↲ ↲ INDEXCHECK╞ none╞ ╞ causes checking of sub-↲ (default)╞ ╞ ╞ ┆84┆range constraints before ↓ ┆19┆┆a2┆┄┄indexing to be included in ↓ ┆19┆┆a2┆┄┄code generated for the ↓ ┆19┆┆a2┆┄┄following lines of source ↓ ┆19┆┆a2┆┄┄text,↲ ↲ NOINDEXCHECK╞ none╞ ╞ ┆84┆switches off index ↓ ┆19┆┆a2┆┄┄checking,↓ ↲ LIST╞ none╞ ╞ ┆84┆causes the following lines ↓ ┆19┆┆a2┆┄┄of source text to be ↓ ┆19┆┆a2┆┄┄listed,↲ ↲ NOLIST╞ none╞ ╞ suppresses listing of↲ (default)╞ ╞ ╞ source text,↲ ↲ RANGECHECK╞ none╞ ╞ causes checking of sub-↲ (default)╞ ╞ ╞ ┆84┆range constraints before ↓ ┆19┆┆a2┆┄┄assignment to be included ↓ ┆19┆┆a2┆┄┄in code generated for the ↓ ┆19┆┆a2┆┄┄following lines of source ↓ ┆19┆┆a2┆┄┄text,↲ ↲ ┆8c┆┆83┆┆e0┆↓ ┆a1┆name╞ parameters╞ description┆05┆↲ NORANGECHECK╞ none╞ ╞ ┆84┆switches off range ↓ ┆19┆┆a2┆┄┄checking,╞ ↲ ↲ ACCESSCHECK╞ none╞ ╞ ┆84┆causes code to be ↓ ┆19┆┆a2┆┄┄generated for every access ↓ ┆19┆┆a2┆┄┄to a formal parameter ↓ ┆19┆┆a2┆┄┄object which is not of ↓ ┆19┆┆a2┆┄┄kind value, to check the ↓ ┆19┆┆a2┆┄┄existence of the actual ↓ ┆19┆┆a2┆┄┄parameter (not specified ↓ ┆19┆┆a2┆┄┄as ?).↲ ↲ NOACCESSCHECK╞ none╞ ╞ switches off access ↲ (default)╞ ╞ ╞ checking.↲ ↲ SET╞ ╞ switch assign-╞ see below,↲ ╞ ╞ ment list↲ ↲ IF╞ ╞ expression╞ see below,↲ ↲ ENDIF╞ none╞ ╞ see below,↲ ↲ ELSE╞ none╞ ╞ see below,↲ ↲ ELSEIF╞ expression╞ see below,↲ ↲ Switches are compile-time variables which can only be used ↓ in the expressions occurring in IF and ENDIF directives. A ↓ switch assignment list consists of one or more switch ↓ assignments separated by commas. A switch assignment has the ↓ form (number must be integer, no radix allowed):↲ ╞ name = number↲ ↲ A switch assignment either introduces and sets the value of ↓ a switch, or, if the switch has been introduced in a ↓ previous switch assignment (SET directive), merely changes ↓ the value.↲ ↲ ┆8c┆┆83┆┆d4┆↓ The directives IF, ELSE, ELSEIF, and ENDIF provide the ↓ capability for conditional compilation. The expressions ↓ occurring in IF and ELSEIF directive must be boolean ↓ expressions obeying the standard rules of the language. The ↓ operands must be switches and integer numbers. The following ↓ operators may be used: <, <=, >=, >, =, <>, AND, OR, XOR, ↓ NOT.↲ ↲ The directives for conditional compilations may be used to ↓ selectively exclude blocks of lines of source text from ↓ compilation, i.e. to cause such lines to be created as ↓ comments. When listed, each excluded line will be marked ↓ with -- appearing at the beginning of the line.↲ ↲ The directive IF and ENDIF must always be used in matching ↓ pairs. ELSE and ELSEIF may optionally be used in conjunction ↓ with IF and ENDIF. A use of conditional compilation takes ↓ the following form:↲ ↲ $IF expr┆82┆1↲ s1┆82┆1↲ $ELSEIF expr┆82┆2↲ s1┆82┆2↲ $ELSEIF expr┆82┆3↲ s1┆82┆3↲ ...↲ $ELSEIF expr┆82┆n↲ s1┆82┆n↲ $ELSE↲ s1┆82┆n+1↲ $ENDIF↲ ↲ The only mandatory parts are the IF and ENDIF directive ↓ lines and the source line(s) s1┆82┆1┆81┆. The effect is as follows: ↓ If the values of all the expressions are false then the ↓ source lines s1┆82┆1┆81┆, s1┆82┆2┆81┆, ..., s1┆82┆n┆81┆ are excluded from ↓ compilation. Otherwise let k be the smallest number such ↓ that the value of expr┆82┆k┆81┆ is true. Then s1┆82┆1┆81┆, ..., s1┆82┆k-1┆81┆, ↓ ┆8c┆┆83┆┆c8┆↓ s1┆82┆k+1┆81┆, ..., s1┆82┆n┆81┆, and s1┆82┆n+1┆81┆ (if present) are excluded from ↓ compilation.↲ ↲ Conditional compilation may be used at several nested ↓ levels. In the above terminology any of the s1┆82┆i┆81┆ may thus ↓ include repeated use of conditional compilation.↲ ↲ ┆a1┆Notes:↲ Switches and variables in the program text belong to ↓ separate name spaces and cannot be confused. The same names ↓ may be used.↲ ↲ Directives occurring in comments are ignored, in particular ↓ those occurring in source lines excluded from compilation.↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆A. REFERENCES↲ ↲ (1) The Programming Language Pascal↲ ╞ Acta Informatica, 1, 35-63, 1971↲ ╞ N. Wirth↲ ↲ (2)╞ ISO International Standard ISO/IS 7185:↲ ╞ Specification for Computer Programming Language Pascal↲ ↲ (3)╞ ISO International Standard ISO/IS 646:↲ ╞ 7-bit Coded Character Set for Information Processing↲ ╞ Interchange↲ ↲ (4) RCSL No 42-i1982:↲ ╞ Distributed System Architecture↲ ╞ A Conceptual Framework for Systems Design↲ ↲ (5)╞ RCSL No 42-i1983:↲ ╞ DSA Inter Module Communication↲ ╞ Functional Description↲ ↲ (6)╞ Platon, A High Level Language for Systems Programming↲ ╞ RECAU, R-75-59↲ ╞ Jørgen Staunstrup and Sven Meiborg Sørensen↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆B. SYNTAX DIAGRAMS↲ ↲ This appendix contains all the syntax diagrams of the ↓ definition of Real-Time Pascal in an attempted natural top-↓ down reading order. Each diagram contains a reference to the ↓ section where it is introduced and where the associated ↓ semantics are explained.↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆C. PREDEFINED ENTITIES↲ ↲ In section C.1 a list of predefined entities is given in ↓ alphabetical order and with reference to the sections where ↓ the entities are described. The types and pseudo-functions ↓ which are intrinsic to the language, denoted by keywords ↓ rather than predefined names, are listed in sections C.2 and ↓ C.2.↲ ↲ ↲ ┆b0┆┆a1┆C.1 Predefind Routines, Types, Type Families, and Constans↲ ↲ ╱04002d4e0a0006000000000301433100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ╱04002d4e0a00060000000003013c3100000000000000000000000000000000000000000000000000050f19232d37414b555f69737d8791ff04╱ ↓ ┆a1┆section kind╞ ╞ definition┆05┆↲ 3.4.3 FUNCTION abs(n: integer): 0..maxint↲ 3.8╞ FUNCTION allocpool (VAR p: pool;↲ ╞ ╞ no_of_bufs: 1..maxint): 0..maxint↲ 5.9 TYPE buffer(bufsize: 1..maxint)=↲ ╞ ╞ ╞ PACKED ARRAY(0..bufsize-1) OF byte↲ 10.1 FUNCTION bufcount(VAR stack: reference): 0..maxint↲ 3.8 FUNCTION bufsize(VAR r: reference): 0..maxint↲ 3.8 FUNCTION bufsize(VAR ch: chain: 0..maxint↲ 3.5 FUNCTION byt(v:integer): byte↲ 3.8 FUNCTION bytecount(VAR r: reference): 0..maxint↲ 3.8 FUNCTION bytecount(VAR ch: chain): 0..maxint↲ 10.2 PROCEDURE chaindown(VAR ch: chain)↲ 10.2 PROCEDURE chainextract(VAR ch: chain; VAR ref: reference)↲ 10.2 PROCEDURE chaininsert(VAR ch: chain; VAR ref: reference)↲ 10.2 FUNCTION chainlength(VAR ch: chain): 0..maxint↲ 10.2 PROCEDURE chainreset(VAR ch: chain)↲ 10.2 PROCEDURE chainstart(VAR ch: chain)↲ 10.2 PROCEDURE chainup(VAR ch: chain)↲ 3.4.2 FUNCTION chr(n: 0..255): char↲ 11.1.2 PROCEDURE closeport(VAR p: port)↲ 11.3.1 PROCEDURE connect(VAR p: port; index: 1..maxint;↲ ╞ ╞ ╞ VAR compl, disc: reference;↲ ╞ ╞ ╞ INSPECT remote_name: string;↲ ╞ ╞ ╞ service: conn_service)↲ 11.3.1 TYPE╞ conn_service= (cs_normal, cs_high)↲ ┆8c┆┆83┆┆c8┆↓ ┆a1┆section kind╞ ╞ definition┆05┆↲ 9.1 TYPE create_result= (create_ok, no_memory, ...)↲ 11.4 FUNCTION creditcount(VAR r: referenc): 0..maxint↲ 5.9 TYPE dataarea(offset, top: 0..maxint) =↲ ╞ ╞ ╞ PACKED ARRAY(offset..top-1) OF byte↲ 3.5 PROCEDURE dec(VAR v: mtype)↲ 9.2.2 PROCEDURE delay(no_of_msecs: 0..maxint)↲ 11.3.1 PROCEDURE disconnect(VAR p: port;↲ ╞ ╞ ╞ index: 1..maxint)↲ 3.8 FUNCTION eventkind(VAR r: reference): event_type↲ 3.8 FUNCTION eventkind(VAR ch: chain): event_type↲ 3.8 TYPE event_type= (not_event, message_event,↲ ╞ ╞ ╞ answer_event, process_removed,↲ ╞ ╞ ╞ port_closed, disconnected,↲ ╞ ╞ ╞ letter_sent, letter_arrived,↲ ╞ ╞ ╞ local_connect, remote_connect,↲ ╞ ╞ ╞ reset_indication, reset_completion,↲ ╞ ╞ ╞ credit, data_sent, data_arrived,↲ ╞ ╞ ╞ data_overrun, dummy_letter,↲ ╞ ╞ ╞ dummy_lcnct, dummy_rcnct,↲ ╞ ╞ ╞ dummy_rindic, dummy_rcmpl,↲ ╞ ╞ ╞ dummy_credit, dummy_sent,↲ ╞ ╞ ╞ dummy_arrived)↲ 3.8 PROCEDURE getbuf(VAR p: pool;↲ ╞ ╞ ╞ VAR ra: mailbox, VAR r: reference)↲ 9.2.2 FUNCTION getbufdelay(VAR p: pool; VAR ra: mailbox;↲ ╞ ╞ ╞ VAR r: reference;↲ ╞ ╞ ╞ no_of_msecs: 0..maxint): wait_result↲ 11.3.1 PROCEDURE getconnection(VAR p: port; index: 1..maxint;↲ ╞ ╞ ╞ VAR compl, disc: reference)↲ 11.3.2 PROCEDURE getcredit(VAR p: port; index: 1..maxint;↲ ╞ ╞ ╞ VAR credbuf: reference)↲ 11.3.2 PROCEDURE getreset(VAR p: port; index: 1..maxint;↲ ╞ ╞ ╞ VAR indic: reference)↲ 3.8 FUNCTION hometest(VAR p: pool;↲ ╞ ╞ ╞ VAR ref: reference): boolean↲ 3.5 PROCEDURE inc(VAR v: mtype)↲ 11.4 FUNCTION index(VAR r: reference): 0..maxint↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆a1┆section kind╞ ╞ definition┆05┆↲ 3.8 FUNCTION initpool(VAR p: pool;↲ ╞ ╞ ╞ no_of_bufs, bufsize: 0..maxint↲ ╞ ╞ ╞ mem: mem_type): 0..maxint↲ 3.5 FUNCTION int(v:mtype): integer↲ 9.1 TYPE link_result= (link_ok, already_linked,↲ ╞ ╞ ╞ external_not_found, ...)↲ 9.2.1 FUNCTION locked(VAR mbx: mailbox): boolean↲ 11.5 FUNCTION maxconnections: 0..maxint↲ 3.4.3 CONST maxint↲ 11.5 FUNCTION maxlettersize: 0..maxint↲ 3.8 TYPE mem_type= (...)↲ 3.4.3 CONST minint↲ 3.7 PROCEDURE new(VAR ptr: ptrtype)↲ 3.7 FUNCTION nil(VAR ptr: ptrtype): boolean↲ 3.8 FUNCTION nil(VAR pr: process): boolean↲ 3.8 FUNCTION nil(VAR ref: reference): boolean↲ 3.8 FUNCTION offset(VAR r: reference): 0..maxint↲ 3.8 FUNCTION offset(VAR ch: chain): 0..maxint↲ 9.2.1 FUNCTION open(VAR mbx: mailbox): boolean↲ 11.1 PROCEDURE openport(VAR p: port; VAR closebuf: reference;↲ ╞ ╞ ╞ INSPECT name: string; scope: scope_type;↲ ╞ ╞ ╞ no_of_cons: 0..maxint; rcv_all: boolean)↲ 3.4 FUNCTION ord(v: otype): integer↲ 9.2.1 FUNCTION passive(VAR mbx: mailbox): boolean↲ 10.1 PROCEDURE pop(VAR stack_handle, popped_buf: reference)↲ 3.4 FUNCTION pred(v: otype): otype↲ 10.1 PROCEDURE push(VAR stack_handle, new_top: reference)↲ 3.8 PROCEDURE putbuf(VAR r: reference)↲ 11.4 FUNCTION reason(VAR r: reference): reason_type↲ 11.4 TYPE reason_type= (reason_ok, reason_name,↲ ╞ ╞ ╞ reason_ressource, reason_closed,↲ ╞ ╞ ╞ reason_network)↲ 11.3.2 PROCEDURE receive(VAR p: port; index: 1..maxint↲ ╞ ╞ ╞ VAR databuf: reference)↲ 11.3.2 PROCEDURE receiveall(VAR p: port; VAR databuf: reference)↲ 11.2 PROCEDURE receiveletter(VAR p: port;↲ ╞ ╞ ╞ VAR databuf: reference)↲ 3.8 FUNCTION releasepool(VAR p: pool;↲ ╞ ╞ ╞ no_of_bufs: 1..maxint): 0..maxint↲ ┆8c┆┆83┆┆e0┆↓ ┆a1┆section kind╞ ╞ definition┆05┆↲ 9.1 PROCEDURE remove(VAR pr: process)↲ 11.3.2 PROCEDURE reset(VAR p: port; index: 1..maxint;↲ ╞ ╞ ╞ VAR compl: reference)↲ 3.8 PROCEDURE resetevent(VAR r: reference)↲ 3.8 PROCEDURE resetevent(VAR ch: chain)↲ 9.1 PROCEDURE resume(VAR pr: process)↲ 9.2.2 PROCEDURE return(VAR ref: reference)↲ 11.1 TYPE scope_type= (anonymous, local,↲ ╞ ╞ ╞ regional, global)↲ 11.3.2 PROCEDURE send(VAR p: port; index: 1..maxint;↲ ╞ ╞ VAR databuf: reference)↲ 11.2 PROCEDURE sendletter(INSPECT destination: string;↲ ╞ ╞ ╞ VAR databuf: reference)↲ 3.8 PROCEDURE setbytecount(VAR r: reference; val: 0..maxint)↲ 3.8 PROCEDURE setbytecount(VAR ch: chain; val: 0..maxint)↲ 3.8 PROCEDURE setoffset(VAR r: reference; val: 0..maxint)↲ 3.8 PROCEDURE setoffset(VAR ch: chain; val: 0..maxint)↲ 3.8 PROCEDURE settop(VAR r: reference; val: 0..maxint)↲ 3.8 PROCEDURE settop(VAR ch: chain; val: 0..maxint)↲ 3.8 PROCEDURE setu1(VAR r: reference; b: 0..255)↲ 3.8 PROCEDURE setu1(VAR ch: chain; b: 0.255)↲ 3.8 PROCEDURE setu2(VAR r: reference; b: 0..255)↲ 3.8 PROCEDURE setu2(VAR ch: chain; b: 0..255)↲ 3.8 PROCEDURE setu3(VAR r: reference; b: 0..255)↲ 3.8 PROCEDURE setu3(VAR ch: chain; b: 0..255)↲ 3.8 PROCEDURE setu4(VAR r: reference; b: 0..255)↲ 3.8 PROCEDURE setu4(VAR ch: chain; b: 0..255)↲ 9.2.2 PROCEDURE signal(VAR mbx: mailbox; VAR ref: reference)↲ 10.1 FUNCTION stackdepth(VAR stack: reference): 0..maxint↲ 9.1 PROCEDURE stop(VAR pr: process)↲ 3.9.4 TYPE string(length: 0..255)=↲ ╞ ╞ ╞ ╞ ARRAY(1..length) OF char↲ 3.4 FUNCTION succ(v: otype): otype↲ 3.8 FUNCTION top(VAR r: reference; 0..maxint)↲ 3.8 FUNCTION top(VAR ch: chain; 0..maxint)↲ 7.1 PROCEDURE trace(fault: integer)↲ 9.1 TYPE unlink_result= (unlink_ok, no_program_linked,↲ ╞ ╞ ╞ ╞ existing_incarnations, ...)↲ ┆8c┆┆83┆┆d4┆↓ ┆a1┆section kind╞ ╞ definition┆05┆↲ 3.8 FUNCTION u1(VAR r: reference): 0..255↲ 3.8 FUNCTION u1(VAR ch: chain): 0..255↲ 3.8 FUNCTION u2(VAR r: reference): 0..255↲ 3.8 FUNCTION u2(VAR ch: chain): 0..255↲ 3.8 FUNCTION u3(VAR r: reference): 0..255↲ 3.8 FUNCTION u3(VAR ch: chain): 0..255↲ 3.8 FUNCTION u4(VAR r: reference): 0..255↲ 3.8 FUNCTION u4(VAR ch: chain): 0..255↲ 9.2.2 PROCEDURE wait(VAR mbx: mailbox; VAR ref: reference)↲ 9.2.2 FUNCTION waitdelay(VAR mbx: mailbox; VAR ref: reference;↲ ╞ ╞ ╞ no_of_msecs: 0..maxint): wait_result↲ 9.2.2 TYPE wait_result= (a_buffer, a_delay)↲ 3.5 FUNCTION wrd(v: integer): word↲ ↲ ↲ ┆b0┆┆a1┆C.2 Language Intrinsic Types↲ ↲ ┆a1┆section╞ name↲ 3.4.1╞ boolean↲ 3.5╞ ╞ byte↲ 3.8, 10.2╞ chain↲ 3.4.2╞ char↲ 3.4.3╞ integer↲ 3.8╞ ╞ mailbox↲ 3.8╞ ╞ pool↲ 3.8, 11╞ port↲ 3.8, 9.1╞ process↲ 3.8╞ ╞ reference↲ 3.5╞ ╞ word↲ ↲ ↲ ════════════════════════════════════════════════════════════════════════ ↓ ┆b0┆┆a1┆C.3 Language Intrinsic Pseudo-function↲ ↲ ┆a1┆section╞ description↲ 9.1╞ ╞ create(INSPECT inc_name: string; program call;↲ ╞ ╞ VAR pr: process; size: 0..maxint;↲ ╞ ╞ ╞ priority: prio_type): create_result↲ 9.1╞ ╞ link(INSPECT name: string;↲ ╞ ╞ VAR prog: program): link_result↲ 3.2╞ ╞ typesize(type_name): 0..maxint↲ 3.12.2╞ varsize(variable_name): 0..maxint↲ 9.1╞ ╞ unlink(VAR prog: program): unlink_result↲ ↲ ┆1a┆┆1a┆╞ ╞ ╞ VAR compl: reference)↲