Algol (562407), страница 6
Текст из файла (страница 6)
PROCEDURE (a: ANYPTR) FINALIZE-, NEW, EMPTY;
The FINALIZE procedure can be implemented for any pointer type. The method is called at some unspecified time after an object of that type (or a base type of it) has become unreachable via other pointers (not globally anchored anymore) and before the object is deallocated.
It is not recommended to reanchor an object in its finalizer and the finalizer is not called again when the object repeatedly becomes unreachable. Multiple unreachable objects are finalized in an unspecified order.
11. Modules
A module is a collection of declarations of constants, types, variables, and procedures, together with a sequence of statements for the purpose of assigning initial values to the variables. A module constitutes a text that is compilable as a unit.
Module | = | MODULE ident ";" |
ImportList | = | IMPORT Import {"," Import} ";". |
Import | = | [ident ":="] ident. |
The import list specifies the names of the imported modules. If a module A is imported by a module M and A exports an identifier x, then x is referred to as A.x within M. If A is imported as B := A, the object x must be referenced as B.x. This allows short alias names in qualified identifiers. A module must not import itself. Identifiers that are to be exported (i.e. that are to be visible in client modules) must be marked by an export mark in their declaration (see Chapter 4).
The statement sequence following the symbol BEGIN is executed when the module is added to a system (loaded), which is done after the imported modules have been loaded. It follows that cyclic import of modules is illegal. Individual exported procedures can be activated from the system, and these procedures serve as commands .
Variables declared in a module are cleared prior to the execution of the module body. This implies that all pointer or procedure typed variables are initialized to NIL.
The statement sequence following the symbol CLOSE is executed when the module is removed from the system.
Example:
MODULE Trees;
(* exports: Tree, Node, Insert, Search, Write, Init *)
IMPORT StdLog;
TYPE
Tree* = POINTER TO Node;
Node* = RECORD (* exports read-only: Node.name *)
name-: POINTER TO ARRAY OF CHAR;
left, right: Tree
END;
PROCEDURE (t: Tree) Insert* (name: ARRAY OF CHAR);
VAR p, father: Tree;
BEGIN
p := t;
REPEAT father := p;
IF name = p.name THEN RETURN END;
IF name < p.name THEN p := p.left ELSE p := p.right END
UNTIL p = NIL;
NEW(p); p.left := NIL; p.right := NIL;
NEW(p.name, LEN(name$)+1); p.name := name$;
IF name < father.name THEN father.left := p ELSE father.right := p END
END Insert;
PROCEDURE (t: Tree) Search* (name: ARRAY OF CHAR): Tree;
VAR p: Tree;
BEGIN
p := t;
WHILE (p # NIL) & (name # p.name) DO
IF name < p.name THEN p := p.left ELSE p := p.right END
END;
RETURN p
END Search;
PROCEDURE (t: Tree) Write*;
BEGIN
IF t.left # NIL THEN t.left.Write END;
StdLog.String(t.name); StdLog.Ln;
IF t.right # NIL THEN t.right.Write END
END Write;
PROCEDURE Init* (t: Tree);
BEGIN
NEW(t.name, 1);
t.name[0] := 0X; t.left := NIL; t.right := NIL
END Init;
BEGIN
StdLog.String("Trees loaded"); StdLog.Ln
CLOSE
StdLog.String("Trees removed"); StdLog.Ln
END Trees.
Appendix A: Definition of Terms
Character types | SHORTCHAR, CHAR |
Integer types | BYTE, SHORTINT, INTEGER, LONGINT |
Real types | SHORTREAL, REAL |
Numeric types | integer types, real types |
String types | Shortstring, String |
Basic types | BOOLEAN, SET, character types, numeric types |
Same types
Two variables a and b with types Ta and Tb are of the same type if
-
Ta and Tb are both denoted by the same type identifier, or
-
Ta is declared in a type declaration of the form Ta = Tb, or
-
a and b appear in the same identifier list in a variable, record field, or formal parameter declaration.
Equal types
Two types Ta and Tb are equal if
-
Ta and Tb are the same type, or
-
Ta and Tb are open array types with equal element types, or
-
Ta and Tb are procedure types whose formal parameter lists match.
-
Ta and Tb are pointer types with equal base types.
Matching formal parameter lists
Two formal parameter lists match if
-
they have the same number of parameters, and
-
they have either equal function result types or none, and
-
parameters at corresponding positions have equal types, and
-
parameters at corresponding positions are both either value, IN, OUT, or VAR parameters.
Type inclusion
Numeric and character types include (the values of) smaller types of the same class according to the following hierarchies:
REAL >= SHORTREAL >= LONGINT >= INTEGER >= SHORTINT >= BYTE
CHAR >= SHORTCHAR
Type extension (base type)
Given a type declaration Tb = RECORD (Ta) ... END, Tb is a direct extension of Ta, and Ta is a direct base type of Tb. A type Tb is an extension of a type Ta (Ta is a base type of Tb) if
-
Ta and Tb are the same types, or
-
Tb is a direct extension of an extension of Ta, or
-
Ta is of type ANYREC.
If Pa = POINTER TO Ta and Pb = POINTER TO Tb, Pb is an extension of Pa (Pa is a base type of Pb) if Tb is an extension of Ta.
Assignment compatible
An expression e of type Te is assignment compatible with a variable v of type Tv if one of the following conditions hold:
-
Te and Tv are equal and neither abstract or extensible record nor open array types;
-
Te and Tv are numeric or character types and Tv includes Te;
-
Te and Tv are pointer types and Te is an extension of Tv;
-
Tv is a pointer or a procedure type and e is NIL;
-
Tv is an integer type and e is a constant expression whose value is contained in Tv;
-
Tv is an array of CHAR, Te is String or Shortstring, and LEN(e) < LEN(v);
-
Tv is an array of SHORTCHAR, Te is Shortstring, and LEN(e) < LEN(v);
-
Tv is a procedure type and e is the name of a procedure whose formal parameters match those of Tv.
Array compatible
An actual parameter a of type Ta is array compatible with a formal parameter f of type Tf if
-
Tf and Ta are equal types, or
-
Tf is an open array, Ta is any array, and their element types are array compatible, or
-
Tf is an open array of CHAR and Ta is String, or
-
Tf is an open array of SHORTCHAR and Ta is Shortstring.
Parameter compatible
An actual parameter a of type Ta is parameter compatible with a formal parameter f of type Tf if
-
Tf and Ta are equal types, or
-
f is a value parameter and Ta is assignment compatible with Tf, or
-
f is an IN or VAR parameter and Tf and Ta are record types and Ta is an extension of Tf, or
-
f is an OUT parameter and Tf and Ta are pointer types and Tf is an extension of Ta.
Expression compatible
For a given operator, the types of its operands are expression compatible if they conform to the following table. The first matching line gives the correct result type. Type T1 must be an extension of type T0:
Operator | First operand | Second operand | Result type |
+ - * DIV MOD | <= INTEGER | <= INTEGER | INTEGER |
integer type | integer type | LONGINT | |
+ - * / | numeric type | numeric type | REAL |
SET | SET | SET | |
+ | Shortstring | Shortstring | Shortstring |
string type | string type | String | |
OR & ~ | BOOLEAN | BOOLEAN | BOOLEAN |
= # < <= > >= | numeric type | numeric type | BOOLEAN |
character type | character type | BOOLEAN | |
string type | string type | BOOLEAN | |
= # | BOOLEAN | BOOLEAN | BOOLEAN |
SET | SET | BOOLEAN | |
NIL, pointer type T0 or T1 | NIL, pointer type T0 or T1 | BOOLEAN | |
procedure type T, NIL | procedure type T, NIL | BOOLEAN | |
IN | integer type | SET | BOOLEAN |
IS | T0 type | T1 | BOOLEAN |
Appendix B: Syntax of Component Pascal
Module | = | MODULE ident ";" [ImportList] DeclSeq [BEGIN StatementSeq] [CLOSE StatementSequence] END ident ".". |
ImportList | = | IMPORT [ident ":="] ident {"," [ident ":="] ident} ";". |
DeclSeq | = | { CONST {ConstDecl ";" } | TYPE {TypeDecl ";"} | VAR {VarDecl ";"}} |
ConstDecl | = | IdentDef "=" ConstExpr. |
TypeDecl | = | IdentDef "=" Type. |
VarDecl | = | IdentList ":" Type. |
ProcDecl | = | PROCEDURE [Receiver] IdentDef [FormalPars] |
ForwardDecl | = | PROCEDURE "^" [Receiver] IdentDef [FormalPars]. |
FormalPars | = | "(" [FPSection {";" FPSection}] ")" [":" Type]. |
FPSection | = | [VAR | IN | OUT] ident {"," ident} ":" Type. |
Receiver | = | "(" [VAR | IN] ident ":" ident ")". |
Type | = | Qualident |
FieldList | = | [IdentList ":" Type]. |
StatementSeq | = | Statement {";" Statement}. |
Statement | = | [ Designator ":=" Expr |
Case | = | [CaseLabels {"," CaseLabels} ":" StatementSeq]. |
CaseLabels | = | ConstExpr [".." ConstExpr]. |
Guard | = | Qualident ":" Qualident. |
ConstExpr | = | Expr. |
Expr | = | SimpleExpr [Relation SimpleExpr]. |
SimpleExpr | = | ["+" | "-"] Term {AddOp Term}. |
Term | = | Factor {MulOp Factor}. |
Factor | = | Designator | number | character | string | NIL | Set | "(" Expr ")" | " ~ " Factor. |
Set | = | "{" [Element {"," Element}] "}". |
Element | = | Expr [".." Expr]. |
Relation | = | "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS. |
AddOp | = | "+" | "-" | OR. |
MulOp | = | " * " | "/" | DIV | MOD | "&". |
Designator | = | Qualident {"." ident | "[" ExprList "]" | " ^ " | "$" | "(" Qualident ")" | "(" [ExprList] ")"}. |
ExprList | = | Expr {"," Expr}. |
IdentList | = | IdentDef {"," IdentDef}. |
Qualident | = | [ident "."] ident. |
IdentDef | = | ident [" * " | "-"]. |
Appendix C: Domains of Basic Types
Type | Domain |
BOOLEAN | FALSE, TRUE |
SHORTCHAR | 0X .. 0FFX |
CHAR | 0X .. 0FFFFX |
BYTE | -128 .. 127 |
SHORTINT | -32768 .. 32767 |
INTEGER | -2147483648 .. 2147483647 |
LONGINT | -9223372036854775808 .. 9223372036854775807 |
SHORTREAL | -3.4E38 .. 3.4E38, |
REAL | -1.8E308 .. 1.8E308, |
SET | set of 0 .. 31 |
Appendix D: Mandatory Requirements for Environment
The Component Pascal definition implicitly relies on three fundamental assumptions.
-
There exists some run-time type information that allows to check the dynamic type of an object. This is necessary to implement type tests and type guards.
-
There is no DISPOSE procedure. Memory cannot be deallocated manually, since this would introduce the safety problem of dangling pointers, i.e. premature deallocation. Except for those embedded systems where no dynamic memory is used or where it can be allocated once and never needs to be released, an automatic garbage collector is required.
-
Modules and at least their exported procedures (commands) and exported types must be retrievable dynamically. If necessary, this may cause modules to be loaded. The programming interface used to load modules or to access the mentioned meta information is not defined by the language, but the language compiler needs to preserve this information when generating code.
Except for fully linked applications where no modules will ever be added at run-time, a linking loader for modules is required. Embedded systems are important examples of applications that can be fully linked.