.ce

THE LANGUAGE PASCALINE

Contents

1       Introduction. 6

2       Summary of Pascaline extensions to Pascal 9

3       EBNF and syntax used in this document 13

4       Relationship to ISO 7185. 15

4.1        Pascaline as a series of extentions. 15

4.2        Additional reserved word-symbols. 15

4.3        Lack of compliance with ISO 7185. 15

5       Language extensions for pascaline. 16

5.1        Word-symbols. 16

5.2        Special symbols. 16

5.3        Identifiers. 16

5.4        Labels. 16

5.5        Numeric constants. 17

5.6        Constant expressions. 18

5.7        Boolean integer operations. 18

5.8        View parameters. 19

5.9        Extended case statements. 20

5.10     Variant record case ranges. 22

5.11     Extended write/writeln statements. 23

5.12     Array type shorthand. 24

5.13     Container arrays. 24

5.14     Parameterized Variables. 28

5.15     Type converters/restrictors. 29

5.16     Fixed objects. 30

5.17     Extended file procedures and functions. 30

5.18     Files of files. 35

5.19     Added program header standard bindings. 36

5.20     Redeclaration of forwarded procedures and functions. 37

5.21     Unnamed function result 37

5.22     Extended Function results. 39

5.23     Overloading of procedures and functions. 40

5.24     Operator overloads. 42

5.25     Static procedures and functions. 43

5.26     Relaxation of declaration order 44

5.27     Exception handling. 45

5.28     Assert Procedure. 47

5.29     Extended range types. 47

5.30     Character limit determination. 49

5.31     Matrix mathematics. 49

5.32     Modularity. 51

5.32.1    Definition vs. implementation modules. 54

5.32.2    Overrides. 55

5.32.3    Parallel modules. 56

5.32.4    Monitor signaling. 59

5.33     Classes. 62

5.33.1    Static objects. 64

5.33.2    Dynamic objects. 64

5.33.3    Class parameters. 66

5.33.4    Inheritance. 67

5.33.5    Inherited class parameters. 68

5.33.6    Overrides for objects. 69

5.33.7    Self referencing. 70

5.33.8    Constructors and destructors. 71

A      Annex A: Collected syntax. 73

B      Annex B: Overview of standard libraries and modularity. 83

B.1       Basic Language Support 83

B.1.1    extlib. 83

B.1.2    strlib. 83

B.2       Advanced User I/O and Presentation Management 83

B.3       Advanced device libraries. 85

B.3.1    sndlib. 85

B.3.2    netlib. 85

B.4       Library procedure and function notation. 85

C      Annex C: Extention Library. 87

C.1       Filenames and Paths. 87

C.2       Predefined paths. 88

C.3       Time and Date. 88

C.4       Directory Structures. 90

C.5       File Attributes and Permissions. 91

C.6       Environment Strings. 91

C.7       Executing Other Programs. 92

C.8       Error Return Code. 93

C.9       Creating or Removing Paths. 93

C.10     Option Character 93

C.11     Path Character 93

C.12     Exceptions. 93

C.13     Functions and procedures in extlib. 94

D      Annex D: String Library. 101

D.1       Conventions. 101

D.2       Words. 101

D.3       Format Strings. 101

D.4       Recycling. 103

D.5       Procedures and functions in strlib. 104

E       Annex E: Terminal Interface Library. 115

E.1        Standard Output 115

E.2        Basic Cursor Positioning. 115

E.3        Automatic Mode. 116

E.4        Tabbing. 116

E.5        Scrolling. 116

E.6        Colors. 116

E.7        Attributes. 117

E.8        Multiple Surface Buffering. 118

E.9        Advanced Input 118

E.10     Timers. 121

E.11     Mouse. 121

E.12     Joysticks. 122

E.13     Function Keys. 122

E.14     Terminal objects. 122

E.15     Exceptions. 124

E.16     Procedures, functions and methods in trmlib. 124

F       Annex F: Graphical Interface Library. 131

F.1        Terminal model 131

F.2        Graphics Coordinates. 131

F.3        Character Drawing. 131

F.4        String Sizes and Kerning. 133

F.5        Justification. 133

F.6        Effects. 133

F.7        Tabs. 133

F.8        Colors. 133

F.9        Drawing Modes. 134

F.10     Drawing Graphics. 134

F.11     Figures. 135

F.12     Predefined Pictures. 135

F.13     Scrolling. 136

F.14     Clipping. 136

F.15     Mouse Graphical Position. 136

F.16     Animation. 136

F.17     Declarations. 137

F.18     Graphical Terminal Object Error! Bookmark not defined.

F.19     Procedures and functions in gralib. 141

G      Annex G: Windows Management Library. 148

G.1       Screen Appearance. 148

G.2       Window Modes. 148

G.3       Buffered Mode. 148

G.4       Unbuffered Mode. 149

G.5       Defacto transparency. 150

G.6       Delayed Window Display. 150

G.7       Window Frames. 150

G.8       Multiple Windows. 150

G.9       Parent/Child Windows. 151

G.10         Moving and Sizing Windows. 151

G.11         Z Ordering. 152

G.12         Class Window Handling. 152

G.13         Parallel Windows. 152

G.14         Menus. 153

G.15         Setting Menu Active. 154

G.16         Setting Menu States. 154

G.17         Standard Menus. 154

G.18         Menu Sublisting. 155

G.19         Advanced Windowing. 156

G.20         Events. 156

G.21         Procedure and Functions in manlib. 160

H      Annex H: Widget Library. 165

H.1       Tiles, Layers and Looks. 165

H.2       Background colors and placement 165

H.3       Sizes. 166

H.4       Logical Widget Identifiers. 166

H.5       Killing, Selecting, Enabling and Getting Text to and from Widgets. 166

H.6       Resizing and repositioning a widget 167

H.7       Types of widgets. 167

H.8       Z ordering. 167

H.9       Controls. 167

H.10         Components. 171

H.11         Dialogs. 172

H.12         Events. 174

H.13         Procedures and functions in widlib. 178

I        Annex I: Sound Library. 197

I.1         Ports. 197

I.2         Channels and Instruments. 199

I.3         Volume. 205

I.4         Time and the Sequencer 205

I.5         Effects. 206

I.6         Pitch Changes. 207

I.7         Prerecorded MIDI 207

I.8         Waveform Files. 207

I.9         Functions and Procedures in sndlib. 208

J        Annex J: Networking Library. 213

J.1         Functions and Procedures in netlib. 213

K      Annex K: Character sets. 215

K.1       ISO 8859-1 Character Set Encodings. 215

K.2       ISO 10646 Character Set Encodings. 215

K.3       Unicode text file I/O.. 215

K.4       Use of different character sets. 216

L       Annex L: Character escapes. 217

M     Annex M: Undefined program parameter binding. 221

N      Standard exceptions. 223

 


 

1       Introduction

------------

 

"Standards are great. Everyone should have one of their own" - Anon.

 

Pascaline is a formal statement of a language that was created over the period 1993 to 2008 in a series of extensions to ISO 7185 Pascal. The name "Pascaline" was chosen both to show that the language is designed to be %100 compatible with the original language, and to continue the language Pascal’s tribute to Blaise Pascal. The Pascaline being Pascal’s calculator, Pascaline the language is "The machine Pascal built", or the "Machine that runs Pascal".

 

In 2008, there are several defacto standards for an extended Pascal, and one official one, the ISO 10206 standard. I have been dissatisfied with these existing extensions for the simple reason that instead of extending Pascal, they are more akin to redesigns of the language. In particular, the addition of the ability to coin pointer addresses to any variable and perform "type escapes" at will remove at a stroke all of the type security Wirth designed into Pascal. I think a good definition of what I mean by "redesign" would be the introduction of a feature that is designed to replace or duplicate a construct of original Pascal.

 

At the same time, I wanted Pascaline to achieve a level of completeness that the language never achieved in its original form. My goal was not to create an instructional language, but a complete and practical implementation that could address current problems in computing without further extensions or special support packages.

 

To design Pascaline I have enumerated a set of goals for the language design:

 

.in 3

·         To be completely upward and downward compatible with ISO 7185 standard Pascal.

 

·         To be a "logical extension" of original Pascal. That is, to extend Pascal using the same working theories and means as the original language, and poses no element that does not interoperate completely with the original language.

 

·         To provide a reasonable upgrade to the language capability, that can be implemented using using an existing standard compiler with minor effort compared to the original implementation of the compiler.

 

·         To implement only features that could be implemented efficiently using existing computing hardware.

 

Pascaline was designed in a series of steps starting in 1993. For each feature, one or more proposals were made. Then, the proposals were evaluated, a winner chosen, and a test implementation in the compiler was made. Then, any adjustments required by the experience of actual use were performed. Every element in Pascaline is backed by a real implementation that is efficient and tested.

 

As for most modern languages, the major thrust of Pascaline is for extending the language via libraries, objects and code reuse. Pascaline will, and should, "obsolete itself" by allowing user written extensions to such a point that the major thrust of development with the language would become that of developing libraries of functions to cover new areas in computer applications.

 

This very ability to extend the language also forms the basis of a new problem in standard implementation that, although it has existed from the time Pascal was originally designed in the 1970s, has become ever more pressing. That is the definition of standard libraries and platforms. Towards this end, the Pascaline standard, as in the standard for most of today’s languages, is divided into the base standard and a "platform", consisting of a series of libraries that handle common I/O and support problems in a machine and system independent way.

 

These libraries are attached here as annexes. There is also a series of annexes covering issues such as character handling, string escapes and other "recommended practices" for Pascaline. The result should greatly aid the ability to write non-trivial Pascaline programs that are truly portable across machines, systems and implementations.

 

As I have offered in the past for Pascal, I extend the offer now, that I will evaluate Pascaline implementations for conformance to the Pascaline standard, no matter what the purpose of that implementation, public or private, profit or nonprofit. I only make the conditions that my access to the implementation be reasonable, that the authors provide me with a list of annexes that are complied with, and that an option exists in the implementation to enforce strict compliance with Pascaline regardless of any other extensions that might be present over and above Pascaline. This last is the same requirement that the ISO 7185 Pascal standard states.

 

This author further respectfully requests that the name "Pascaline" be applied only to an implementation that has been found to comply with the language specification here, and by the tests I provide free of charge or restriction. Further, unlike the ISO 7185 standard, I ask that no exceptions be allowed for the language (ISO 7185 5.1). A language may well comply with part of this specification, and be called a Pascal, or some other name. I only ask that it not be called "Pascaline" unless it can process the full language, aside fro the appendicies, without exception.

 

Scott A. Moore

 

July, 2008

 


2       Summary of Pascaline extensions to Pascal

 

Pascal defined a program as a series of nested blocks, one inside the other. The most basic block was the program block, which could contain any nested series of procedure and function blocks. Each block can contain a series of declarations containing labels, constants, types, variables, procedures and functions. Each block contains the code that executes the algorithms contained in the block.

 

The blocks of Pascal define a closed collection of these declarations with an interface that consists of a parameter list. In Pascaline terminology, this is a "top" interface, as the block communicates with the outside of the block via an interface at the "top" of the block:

 

.nf

    +-----<> Parameter list

    |

---------

|       |

| Block |

|       |

---------

.fi

 

Each block can also interface, informally, with declarations in the surrounding block. This is referred to in Pascaline terminology as the "side" interface:

 

.nf

--------------------------------------------

|                                          |

| Surrounding block                        |

|                                          |

|   ---------                              |

|   |       | ---< Variable declarations   |

|   | Block | ---< Procedures              |

|   |       | ---< ...                     |

|   ---------                              |

|                                          |

--------------------------------------------

.fi

 

Each block can import declarations from the surrounding block.

 

Pascal envisoned a program as a tower of blocks resting one atop the other. This paradigm is a good one, but views the program as a monolithic whole. The provision of fixed types without the ability to extend them with change also contributes to the model of a program created as a static structure of code.

 

Pascaline's main thrust is to add extensibility to Pascal, and this is done by greatly augmenting the methods to create side blocks. Pascaline views programs as a series of adjoining tiles:

 

.nf

---------                                   ---------

|       | ---<> Variable declarations <>--- |       |

| Block | ---<> Procedures            <>--- | Block |

|       | ---<> ...                   <>--- |       |

---------                                   ---------

.fi

 

In Pascaline, the program block is such an adjoining block, and adds several other block types that have this ability to export their declarations directly to other blocks. The primary of these is the module, which has all the powers of a program block, but adds the ability to specify both code that executes when the program starts, and code that executes when the program ends. In this way, modules appear as "service blocks" whose point is to provide constants, types, variables, procedures and functions to the program, along with a method both to set up such items as well as shut them down.

 

The program and module blocks form a group executing the same thread of execution for a program. Another module is the process, which defines a new thread of execution aside from the main program. Process modules cannot directly access program or module blocks, but the two can communicate via a monitor block, which automatically implements the multitasking primitives needed to coordinate such an exchange. A share block gives a way to define constants, types, procedures and functions that are usable by any task without the overhead of multitask coordination.

 

Pascaline also defines a new level of block that is an intermediate between a so-called "global" block such as a program, module, monitor, etc. Those blocks are static, with variables that are allocated for the duration of the program. This is a natural outermost block, since any program ultimately is rooted in such program constructs. The class block fits between the level of global blocks and procedure and function blocks. A class block has the ability to share its declarations via the "side", but also can have its variables created dynamically, or as part of the local variables in a block. Further, classes have the ability to be extended to any level. Any new class has the the ability to be based on a previously defined class, and to have that class accepted as compatible with the base class.

 

Because classes define both declarations such as constants and types that have no allocation, as well as variables that do, the class must be instantiated either as part of the variable data, or via a reference. Any number of instances of a class may exist associated with such references. The instance of a class is called an object, and it is a true dynamically created set of the data associated with a class. The class contains the declaration of the format of the object it creates, and thus it is a "class" or "kind" for all of the objects created using it.

 

Because a class defines both a series of constants, types, variables, and also procedures and functions that can operate on those declarations, which are known as "methods", An object forms a true dynamic instance of a module. Classes complete the idea of "object orientation" which dictates that data exists as paired with the procedures or functions, referred to as "methods", needed to manipulate that data. Because classes that inherit from each other also have references that are compatible, classes can extend each other to any number of levels to implement program concepts.

 

To allow the static idea of parameter lists in Pascal to be extended, Pascaline implements the "overload" concept. Procedures, functions and methods can form "groups" under the same name that are differentiated by kind, type and number such that calls to such procedures and functions are sent to the instance that has the correct interface to operate on them. Built in expression operators can be overloaded, thus completing a full circle of data abstraction.

 

The concept of extendibility is further enhanced by the ability to override existing procedures, functions and methods. New modules and classes can override the previous meaning of them, and also extend them by performing new operations and calling the original definitions.

 

Pascaline has "container" types for arrays that do not specify an exact size. These types can be used to form a template to create such arrays of a runtime determined size at runtime. This allows procedures and functions to accept arbitrarily sized arrays to any dimension, and allows such arrays to be dynamically created as variables and pointer types as well.

 

The common case of an integer indexed array can be specified by a short form, which also underscores the idea of container types.

 

Pascaline introduces the break character, "_", for both identifiers and numbers. This aids readability for long identifiers and numbers.

 

Goto labels are freed from the restriction that they must appear as numbers, and can assume the same form as an identifier. Goto labels both retain their status as an interprocedure deep nested branching, but also allow for intermodular branching via a procedure or function call.

 

Pascaline implements the method of structured exception handling to handle deep nested returns. This allows code to be written that delivers exceptions to higher level code without needing knowledge of the surrounding code. This further enhances extendibility, and finally allows for complete replacement of “goto”s.

 

Constant expressions can be used wherever constants were used in Pascal. This makes it possible to use formulas for these constants instead of precalculated numbers.

 

Boolean operations on integers are permitted, and a new operator, "xor", is implemented for both boolean and integer operands.

 

For procedures, functions and methods, a new parameter "mode" is implemented, the "view" mode. This is identical to value parameter semantics, except that the parameter is protected from all modification. This makes certain compiler optimizations possible.

 

Case statements now have an "else" clause, and ranges of case constants are possible.

 

Case variant declarations can also use ranges of case constants.

 

Write/writeln can specify left justified fields, and a special mode allows the output of right padded strings in their natural length.

 

A new declaration exists, "fixed", which can be used anywhere a variable can, but cannot be modified. This allows the compile time specification of fixed tables, and ameliorates the need to create blocks of assignments at the start of a program.

 

Pascaline introduces a limited type conversion/restriction operation to convert between scalar types. This relieves the need to produce special handling to convert enumerated types to integer. It also introduces the ability to directly specify the precision needed within integer expressions, instead of always promoting such operations to the full size of integer. This allows more efficient numeric processing on small word size processors and arbitrary word length processors.

 

Pascaline standardizes a series of procedures and functions for files, such as binding to external file names, opening and closing a series of files, indexing within files, finding the length of a file, updating existing files, and appending to the end of such files, checking the existence of a file, and deleting and changing the name of a file.

 

A few new standard header parameters are introduced, including an error output, a list (or print) output, and a command line or file input.

 

The strict order of declarations from Pascal is relaxed in Pascaline. label, const, type, var and fixed declarations can occur in any order. This aids in the modular structure of Pascaline.

 

When a forwarded procedure, function or method appears as the actual declaration, the parameter list can be repeated. It is checked for congruence with the original. This allows such declarations to be created by cut and paste, and is more readable than the original method of having the actual declarations far from their forwarded declarations.

 

Procedures and functions can be declared as static, or non-recursive. This allows the creation of more efficient code on some processors.

 

Asserts are implemented, allowing the incorporation of runtime checks for code being debugged that can be removed without modifying the source.

 

Pascaline allows "subrange" types to be created that are larger than the natural Pascal range of an integer (-maxint..maxint). This allows an implementation to implement types that utilize double more precision while taking longer to perform them, so called "extended range" types. It also implements a set of predefined types that give an implementation defined set of unsigned and signed extended range types.

 

There is a predefined constant for the maximum character value in an implementation.

 

A way to specify a function result that obeys the rule of single entry/single exit with the result formed at the end. This is also required for operator overloads.

 

Besides the extensions to the base Pascal language, Pascaline defines a set of optional extension modules that define the Pascaline "platform". This is a nod to the fact that the set of support calls for an implementation make as much difference to portability for a program as the base language does.

 


3       EBNF and syntax used in this document

 

For the purpose of describing syntax elements of Pascaline, the EBNF or Extended Backus-Naur Format as used in the ISO 7185 standard is used. The syntax that appears here consists of the syntax elements from the ISO 7185 standard as modified for Pascaline use.

 

name = syntax-description .

 

Describes the syntax expansion of the syntax element by name of "name", which is terminated by '.'.

 

 a | b

 

Either construct a or constructor b may appear, but not both.

 

{ a }

 

Construct a is repeated 0 or more times.

 

[ a ]

 

Construct a is repeated 0 or 1 times (it is optional).

 

'abc'

 

The characters "abc" appear literally.

 

( a b )

 

The elements a and b are grouped together.

 

The syntax expansions that appear in this document mirror the same by name in the ISO 7185 document. If a syntax element by name matches a name used in the document, and is different from the one contained there, then it represents a Pascaline extension to ISO 7185 Pascal, and replaces the original syntax definition.

 

Note the ISO 7185 use of ">" or "alternate" is not used here, because Pascaline does not use the "level 1" extensions of ISO 7185. The syntax for the level 1 extensions was removed.

 

Annex A contains a full syntax for Pascaline.

 


4       Relationship to ISO 7185

 

4.1      Pascaline as a series of extentions

 

The Pascaline standard accepts the entire language defined in the standard defined in ISO 7185 such that the set of features defined by Pascaline qualify as extentions under ISO 7185 3.2 “Extention”.

 

4.2      Additional reserved word-symbols

 

As allowed, the following particular spellings of identifiers are prohibited because of their use as word-symbols in the Pascaline standard:

 

forward                        module                        uses                 private             external

view                 fixed                process                        monitor                        share

class                 is                      overload          override           reference

joins                 static                inherited          self                  virtual

try                    except              extends                        on                    result

operator           instance           start

 

These word-symbols are all new word-symbols defined by Pascaline. The fact that certain identifiers are prohibited in Pascal may cause ISO 7185 compliant programs to fail to compile for this reason. To use a Pascaline implementation for such programs, one of two methods are used:

 

1.      The ISO 7185 compliance switch is enabled (see ISO 7185 5.1 “Processors” note 2).

2.      The identifiers in the program that overlap the above list are changed.

 

4.3      Lack of compliance with ISO 7185

 

ISO 7185 5.2 “Processors” allows an implementation to be considered compliant if it is accompanied by a list of the requirements for which it does not comply. Pascaline specifically does not allow such exceptions. A processor is not Pascaline compliant only if it has the following characteristics:

 

1.      The complete requirements of ISO 7185 are followed, without exception.

2.      The complete requirements of Pascaline, in this document, are followed without exception.

 

That is, the “list of requirements not complied with” from ISO 7185 is neither allowed as a starting point for Pascaline, nor carried forward into the language Pascaline.

 

Level 0 only

 

Pascaline is compliant with “level 0” Pascal only, as allowed for by the ISO 7185 standard (ISO 7185 5 “Compliance”). Conformant arrays are not specified in Pascaline, nor are they specified as an option under Pascaline. However, such conformant arrays could well be implemented as an extention to Pascaline.


 

5       Language extensions for pascaline

 

5.1      Word-symbols

 

word-symbol = 'and' | 'array' | 'begin' | 'case' | 'const' | 'div' | 'do' | 'downto' | 'else' | 'end' | 'file' | 'for' | 'function' | 'goto' | 'if' | 'in' | 'label' | 'mod' | 'nil' | 'not' | 'of' | 'or' | 'packed' | 'procedure' | 'program' | 'record' | 'repeat' | 'set' | 'then' | 'to' | 'type' | 'until' | 'var' | 'while' | 'with' | 'forward' | 'module' | 'uses' | 'private' | 'external' | 'view' | 'fixed' | 'process' | 'monitor' | ' share' | 'class' | 'is' | 'overload' | 'override' | 'reference | 'joins' | 'static' | 'inherited' | 'self' | virtual' | 'try' | 'except' | 'extends' | ‘on’ | ‘result’ | ‘operator’ | ‘instance’ | ‘start’ .

 

Note that the directives "external" and "forward" in standard Pascal are promoted to word-symbols in Pascaline.

 

5.2      Special symbols

 

special-symbol = '+' | '-' | '*' | '/' | '=' | '<' | '>' | '[' | ']' | '.' | ',' | ':' | ';' | '^' | '(' | ')' | '<>' | '<=' | '>=' | ':=' | '..' | '(.' | '.)' | '@' | word-symbol .

 

5.3      Identifiers

 

Identifiers in Pascaline are identical to Pascal, with the addition of the break character '_'. An identifier can start with any of 'a'..'z' or '_', and continue with 'a'..'z', '_' and '0'..'9'. As in original Pascal, identifiers are not case sensitive.

 

identifier = letter | '_' { letter | digit | '_' }.

 

Example identifiers:

 

one_more_time

 

_last_time

 

5.4      Labels

 

Labels, used for goto purposes, can use the same format as identifiers under Pascaline. The original "apparent value" numeric labels of Pascal are accepted as well.

 

label = digit-sequence | identifier .

 

Example label:

 

program p;

 

label exit;

 

{ declarations }

 

begin

 

   goto exit

 

   { statements to be skipped }

 

   exit:

 

end.

 

5.5      Numeric constants

 

unsigned-integer = decimal-integer | hex-integer | octal-integer | binary-integer .

 

decimal-integer = digit-sequence .

 

hex-integer = '$' hex-digit-sequence .

 

octal-integer = '&' octal-digit-sequence .

 

binary-integer = '%' binary-digit-sequence .

 

digit-sequence = digit { digit | '_' } .

 

hex-digit-sequence = hex-digit { hex-digit }

 

octal-digit-sequence = octal-digit { octal-digit }

 

binary-digit-sequence = octal-digit { binary-digit }

 

digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' .

 

hex-digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | '_' .

 

octal-digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '_' .

 

binary-digit = '0' | '1' | '_' .

 

Both standard integer and real specifications are available. In addition, three "radix specifier" formats are available:

 

$1234 - Specifies hexadecimal format

 

&1234 - Specifies octal format

 

%1010 - Specifies binary format

 

Each alternative format is specified with a "radix introduction" character. These formats can be specified anywhere the Pascal construct unsigned-constant is specified.

 

Pascaline accepts a "break character" within numeric constants. The "_" character can be used anywhere within a number:

 

123_456_789

 

It cannot be used as the first character of a number, which would make it an identifier.

 

The meaning of the number is considered without the break characters. Break characters can be used in any radix. They are useful for grouping digits so that the result is more readable:

 

12_334_222 { marked in thousands }

 

$5566_1212 { marked in 16 bit sections }

 

5.6      Constant expressions

 

constant = [ sign ] constant-term { adding-operator constant-term } .

 

constant-term = constant-factor { multiplying-operator constant-factor } .

 

constant-factor = '(' constant ')' | 'not' constant-factor | character-string | constant-identifier | unsigned-integer .

 

multiplying-operator = '*' | '/' | 'div' | 'mod' | 'and' .

 

adding-operator = '+' | '-' | 'or' | 'xor' .

 

Whenever a constant appears in Pascal, Pascaline is able to accept a constant expression. Constant expressions have a syntax that is similar, but not identical to standard expressions in Pascal. However, constants can only operate on other constants, and cannot include variables.

 

The new operator xor is defined in the next section.

 

5.7      Boolean integer operations

 

expression = simple-expression [ relational-operator simple-expression ] .

 

simple-expression = [ sign ] term { adding-operator term } .

 

term = factor { multiplying-operator factor } .

 

factor = variable-access | unsigned-constant | function-designator | type-identifier '(' expression ')' | set-constructor | '(' expression ')' | 'not' factor .

 

multiplying-operator = '*' | '/' | 'div' | 'mod' | 'and' .

 

adding-operator = '+' | '-' | 'or' | 'xor' .

 

Besides the use of and, or and not on Booleans in Pascal, Pascaline allows the use of and, or and not with integer operands. The result is the bitwise 'and', ‘or’ or ‘not’of the bits in the integer.

 

In addition, Pascaline defines a new operator, xor, which has the same precedence as and. It gives the bitwise exclusive or of integers. It can also be used on boolean types, but in that case is equivalent to the operation a <> b.

 

Boolean operations on negative values are not defined, and may be treated as errors, caught at either compile time or run time, by the implementation.

 

5.8      View parameters

 

formal-parameter-list = '(' formal-parameter-section { ';' formal-parameter-section } ')' .

 

formal-parameter-section = value-parameter-specification | variable-parameter-specification | view-parameter-specification | procedural-parameter-specification | functional-parameter-specification .

 

value-parameter-specification = identifier-list ':' type-identifier .

 

variable-parameter-specification = 'var' identifier-list ':' type-identifier .

 

view-parameter-specification = 'view' identifier-list ':' type-identifier .

 

procedural-parameter-specification = procedure-heading .

 

functional-parameter-specification = function-heading .

 

A parameter to a procedure or function has a type and a "mode", that indicates the method of its passage.

 

Besides the Pascal parameter modes of var and value, Pascaline adds a mode introduced by view:

 

program p;

 

type a = packed array [1..100] of char;

 

procedure x(view b: a);

 

begin

 

   { use, but don’t change, b }

 

end;

 

begin

end.

 

View parameters have the same characteristics as value parameters, and could in fact be treated identically to value parameters. A view parameter cannot be modified or "threatened" in the procedure or function it belongs to. The meaning of "threatened" is the same as for "for" index variables of ISO 7185 (6.8.3.9), and means that the parameter cannot be assigned, used as an index in a for loop, or passed to another routine as a var parameter.

 

View parameters enable the underlying implementation to create more efficient code in many cases. If the above example was:

 

program p;

 

type a = packed array [1..100] of char;

 

procedure x(b: a);

 

begin

 

   { code to use array b }

 

end;

 

begin

end.

 

The code would have to copy the actual parameter to b, which can be very inefficient for large arrays. The use of the view parameter allows the system to treat the parameter as a var parameter, but allow any expression to be passed as a value parameter would.

 

5.9      Extended case statements

 

case-statement = 'case' case-index 'of' case-list-element { ';' case-list-element } [ ';' ] 'end' .

 

case-list-element = case-list-statement | case-list-default .

 

case-list-statement = case-constant-list ':' statement .

 

case-list-default = 'else' statement .

 

case-constant-list = case-constant-range { ',' case-constant-range } .

 

case-constant-range = case-constant [ '..' case-constant ] .

 

case-index = expression .

 

A case statement can feature an "else" clause at the end of all case selects for a given case statement:

 

program p(output);

 

var y: integer;

 

begin

 

   { code that sets y }

 

   case y of

 

      1: write('one');

      2: write('two')

      else write('value unknown')

 

   end

 

end.

 

The statement indicated as "else" will be executed if the case select value does not match any of the values in the case list.

 

A case select value can appear as a range of values:

 

program x

 

var y: integer;

 

begin

 

   case x of

 

      1: write('one');

      2: write('two');

      3..5: write('three to five')

 

   end

 

end.

 

is shorthand for:

 

program p;

 

var y: integer;

 

begin

 

   { statements that set y }

   case y of

 

      1: write('one');

      2: write('two');

      3, 4, 5: write('three to five')

 

   end

 

end.

 

5.10    Variant record case ranges

 

The case constants on a variant record specification can appear as ranges:

 

record-type = 'record' field-list 'end' .

 

field-list = [ ( fixed-part [ ';' variant-part ] | variant-part ) [ ';' ] ] .

 

variant-part = 'case' variant-selector 'of' variant { ';' variant } .

 

variant = case-constant-list ':' '(' field-list ')' .

 

case-constant-list = case-constant-range { ',' case-constant-range } .

 

case-constant-range = case-constant [ '..' case-constant ] .

 

program p;

 

type sr = 1..5;

 

var r: record

 

          i: integer;

          case s: sr of

 

             1: (q: integer; b: boolean);

             2: (z: real; t: array 10 of integer);

             3..5: (o: set of char; j: integer)

 

       end;

 

begin { program p }

end.

 

For each case range, the starting constant must be less than or equal to the ending constant.

 

5.11    Extended write/writeln statements

 

Pascaline extends the meaning of field width parameters in ISO 7185 6.9.3.1 to include negative or zero field widths. The appearance of a negative value as a field width has the same effect as the absolute value of the field width, except that the resulting character translation is set left justified within its field. I.e., the spaces that are specified to pad each output format to the field width are output after the contents of the field, not before.

 

write(f, i:-10);

 

Would output to file f the integer i in 10 spaces at least, with any padding to the right side of the number.

 

A zero field parameter is only applicable for string-type parameters. Usually, the field width for a string parameter means to output exactly that many characters of the string, truncating or padding the string as required. The appearance of a zero field width with a string indicates that the number of characters output will be defined as the number of characters from the first index of the string (1), to the last non-blank character of the string. If there are no non-blank characters in the string, then no characters are output at all.

 

program p;

 

var f: text;

    s: packed array 30 of char;

 

begin

 

   write(f, s:0);

 

end.

 

The zero field parameter extension provides a simple method to output so called "space padded" strings, which are Pascal strings with padding added to the right side to make them effectively fixed character arrays.

 

5.12    Array type shorthand

 

array-type = 'array' [ dimension-specifier ] 'of' component-type .

 

dimension-specifier = index-specifier | range-specifier .

 

index-specifier = '[' index-type { ',' index-type } ']' .

 

range-specifier = unsigned-integer { ',' unsigned-integer } .

 

Pascaline features a special declaration format for the most common case of integer indexed arrays:

 

type x = packed array 10 of char;

type y = array 20,10 of integer;

 

are equivalent to:

 

type x = packed array [1..10] of char;

type y = array [1..20,1..10] of integer;

 

Denoting an array index by size, instead of by an index specification, uses a different syntax, without the '[' ']' characters, to make it clear what kind of array specification is being used.

 

5.13    Container arrays

 

array-type = 'array' [ demension-specifier ] 'of' component-type .

 

The specification of only fixed arrays in original Pascal caused several practical issues with the language. Pascaline has the concept of "container arrays", which are array types specified without index specifications.

 

type a = array of integer;

 

Container arrays are a "template type" which cannot be used to directly specify a static type. For example:

 

program p;

 

type a = array of integer;

 

var b: a;

 

begin

end.

 

Would not be correct because type a does not contain enough information, namely the size of the array, to define the static variable b.

 

The power of container arrays is their ability to be bound to a fully defined static array at a time later than when the program is compiled. This can happen in two different ways:

 

1.      When a parameter is accepted for a procedure or function.

2.      As a result of the creation of an anonymous array in dynamic storage.

3.      By use of a parameterized variable declaration (covered in the next section).

 

It is important to understand that Pascaline does not specify what are called "dynamic arrays", which is the ability to resize an array at runtime.  Rather, Pascaline simply provides the means to create fixed arrays of any size at runtime and bind to them, or to create generate purpose procedures or functions that can bind to any size array at runtime. This distinction may seem to be unnecessary, but in practice it dramatically simplifies implementation of the concept.

 

Container types can have multiple index levels:

 

type a = array of array of array of boolean;

 

Container array types are compatible with other container and fixed array types that:

 

1.      Have the same base types.

2.      Have the same packed/unpacked status.

3.      Have the same number of index levels.

 

Thus, the following types are compatible:

 

type a = packed array [1..100] of char;

 

and

 

type b = packed array of char;

 

type a = array [1..10, 1..100] of integer;

 

and

 

type b = array of array of integer;

 

A container array can be used for a procedure or function parameter:

 

type string = packed array of char;

 

procedure x(var s: string);

 

As with normal Pascal array parameters, if the parameter is passed by value, there can be considerable expense associated with copying the array to private location for the procedure or function.

 

When container arrays are used as parameters, they are simply serving as holders for an existing array. In the case of variable parameters, the array was created elsewhere in the code and the parameter simply points to it. In the case of value parameters, the array is created anew in a private location, and the existing array copied to it. In both cases, the information needed to complete the template for the array exists elsewhere.

 

Another way to allocate a container array is to use "new" to allocate it dynamically:

 

program p;

 

type ap = ^a;

     a  = packed array of char;

 

var b: ap;

 

begin

 

   new(b, 10);

   b := 'hi there  ';

 

end.

 

Container arrays have the interesting property that they are free of index typing. Container arrays are considered to be compatible with other arrays (standard or container) that have the same number of base elements.

 

This means that the following assignments are possible:

 

program p;

 

type a = packed array [20..120] of char;

     b = array of char;

     c = ^b;

 

var q: a;

    x: c;

 

begin

 

 

   new(x, 100);

 

   x := q;

 

   q := x;

 

end.

 

It does not matter what the first or last element of the array is. When elements are copied from or to a compatible container, or when a container is used to reference a standard array, the elements are matched up from the first to the last without regard to the exact number of the index used. In the last example, q[20] and x[1] refer to the same element.

 

When a container array is indexed, the method of specifying its indices is always the integers 1 to n, where n is last element of the array. The last element of a container array, which happens to also be its length, can be found by the predefined function:

 

max(a, l);

 

where a is the container array, and l is the indexing level. For example:

 

program p;

 

type a = array of array of array of integer;

     b = ^a;

 

var c: b;

    i: integer;

 

begin

 

   new(c, 10, 20, 30);

 

   i := max(c, 2);

 

end.

 

Finds the second level index length of b, which is 20.

 

Specifying a level for max is optional. The function call:

 

max(a);

 

is equivalent to:

 

max(a, 1);

 

5.14    Parameterized Variables

 

Although containers cannot be directly used as the type of a variable, or part of a variable, they can be used for the type of a parameterized variable declaration:

 

variable-declaration = identifier-list [ ‘(‘ expression { ‘,’ expression ‘)’ ] ':' type-denoter .

 

variable-declaration-part = [ 'var' variable-declaration ';' { variable-declaration ';' } ] .

 

program p;

 

type z = array of integer;

 

procedure q(i: integer; v: z);

 

var a(max(v)): array of integer;

 

begin

 

   for i := 1 to max(v) do a[i] := v[i]+1

 

end;

 

begin

end.

 

Variables which are declared using containers use a parameterized form that takes one or more expressions on the left side, which are used to fufil the indicies that appear in the type of the variable on the right side.

 

The parameter expressions must be integer.

 

Each expression will be used to match an index in the type. If the type is formed from a nested declaration, the indicies are processed from the outermost declaration to innermost. If multiple dimension arrays exist, the indicies appear from major to minor.

 

Every index in the type must be matched. If there are more or fewer index expressions that there are indicies in the type, it is an error.

 

The expression used for an index parameter is not limited. Variables, parameters and functions can be used, but all of the elements used must be fully defined.

 

The evaluation of the index parameters are evaluated before the code in the block for which the variable is declared exists. The indicies do not vary during the execution of the declaring block.

 

If a parameterized variable statement contains only constant parameters, the compiler may treat the variable as equivalent to a fixed type with the same parameters.

 

If the parameterized variable statement contains local variables, it is an error, since such variables are, by definition, undefined at the start of the block. Note that this does not apply to parameters, which are initialized externally to the procedure or function that contains the parameterized variable statement.

 

5.15    Type converters/restrictors

 

expression = simple-expression [ relational-operator simple-expression ] .

 

simple-expression = [ sign ] term { adding-operator term } .

 

term = factor { multiplying-operator factor } .

 

factor = variable-access | unsigned-constant | function-designator | type-identifier '(' expression ')' | set-constructor | '(' expression ')' | 'not' factor .

 

multiplying-operator = '*' | '/' | 'div' | 'mod' | 'and' .

 

adding-operator = '+' | '-' | 'or' | 'xor' .

 

Pascal defines the function "ord" to convert any scalar or character type to integer, and defines the function "chr" to convert integer to character. Pascaline extends this system to include any scalar type by use of a "type converter":

 

program p;

 

type a = (one, two, three);

     b = 20..30;

 

var x: a;

    y: integer;

 

begin

 

   x := a(1);

   y := b(y+1);

 

end.

 

The first assignment yields the value for "two" (Pascal enumerated types are defined as the integers from 0 to n). The second assignment would seem to have no function. However, the compiler can take this as a hint that instead of promoting the expression y+1 to the full size of an integer, that the operation can be performed in only the precision required for values within 20..30. This can enable more efficient processing of expressions on some machines.

 

When a type restrictor appears, the compiler can generate an error for values in the restricted value that cannot fit in the range of the target type. Type converters and restrictors never simply discard values.

 

5.16    Fixed objects

 

block = { declaration } [ 'private' declaration ] statement-part [ ';' statement-part ] .

 

declaration = label-declaration-part | constant-definition-part | type-definition-part | variable-declaration-part |fixed-declaration-part | procedure-declaration ';' | function-declaration ';' .

 

fixed-declaration-part = [ 'fixed' fixed-declaration ';' { fixed-declaration ';' } ] .

 

fixed-declaration = identifier-list ':' type-denoter '=' value-constructor.

 

value-constructor = array-value-constructor | record-value-constructor | constant .

 

array-value-constructor = 'array' value-constructor { ',' value-constructor } 'end' .

 

record-value-constructor = 'record' value-constructor { ',' value-constructor } 'end' .

 

In addition to declaring variables, Pascaline can declare a program construct that appears anywhere a variable can, but is defined completely at compile time:

 

program p;

 

fixed a: integer = 1;

      b: array [1..10] of integer =

            array 5, 6, 8, 2, 3, 5, 9, 1, 12, 85 end;

      c: record a: integer; b: char end = record 1, 'a' end;

      d: array [1..5] of packed array [1..5] of char = array

 

         'tooth',

         'trap ',

         'same ',

         'fall ',

         'radio'

 

      end;

 

begin

end.

 

The declaration of a fixed is similar to a var declaration, but each variable is given a "value" part that contains a value constructor.

 

Fixed types can be used anywhere a variable type can, but a fixed type cannot be "threatened" in the sense of the "for" variable threat of ISO 7185 (6.8.3.9).

 

5.17    Extended file procedures and functions

 

Pascaline defines several additional functions dealing with files. Files that are not declared as external via the program header are normally given the property that they are anonymous and may be deleted at the end of the program.  In Pascaline, such files can also be named using the function assign:

 

program p;

 

var f: text;

 

begin

 

   assign(f, 'myfile');

 

   { statements to use file f }

 

end.

 

Assign takes any string (defined in original Pascal as a packed array of characters with a starting index of 1 and any length). The format of the file name contained in the string is entirely implementation dependent, but most implementations will honor, at minimum, the conventions that:

 

1.      Leading and trailing spaces in the name are ignored, and removed if required.

2.      That the characters in the set ['a'..'z', 'A'..'Z', '0'..'9', '_'] are valid in a filename.

3.      The filename must begin with characters from the set ['a'..'z', 'A'..'Z','_'].

 

Note that this is only a subset of implementation defined filename conventions. The particular Pascaline implementation will have its own additional requirements for the formatting of filenames.

 

The Pascaline standard library extlib will has higher level structuring of filenames that are upward compatible with the above. See Annex C.

 

The existence of a named file implies, but does not require, that the file is not deleted at the end of the program run. It further implies that applying reset to a named file will allow its preexisting contents to be accessed.

 

As in standard Pascal, applying reset or rewrite to a file causes the file to change from the "undefined" state to "read" for reset, and "write" for rewrite. It is an error to apply assign to a file that is not in the undefined state, that is, to rename it while it is active.

 

To allow the processing of multiple files by name, the procedure close exists:

 

program p;

 

var f: text;

    names: array 5 of packed array 10 of char = array

 

       ‘myfile    ‘,

       ‘thisfile  ‘,

       ‘thatfile..’,

       ‘nextfile  ‘,

       ‘lastfile 

 

    end;

    i: integer;

 

begin

 

   for i := 1 to 5 do begin

 

      assign(f, names[i]);

 

      { statements that use file f }

 

      close(f)

 

   end

 

end.

 

Close causes bond between the file variable and the named file itself to be broken, and the file state to be returned back to undefined. In this state, it can have assign applied again. In this way, a sequence of named files can be processed. Close implies that if the file is anonymous, it is deleted, and that the file returns to being anonymous unless assigned again.

 

Because in Pascaline, a named file is implied to persist beyond the end of a program, it is also implied that each file that exists in a read or write state has a close performed on it automatically either when the program ends, or when the file variable falls out of activation, or some combination of both.

 

Standard Pascal defines files as a series of elements which can be examined in turn. Pascaline defines the standard function length to give the number of elements within a file:

 

program p;

 

var f: file of integer;

 

begin

 

   assign(f, ‘myfile’);

   writeln('The length of the file is: ', length(f));

   close(f)

 

end.

 

The function length is equivalent to:

 

program p;

 

type fi: file of integer;

 

function length(var f: fi): lcardinal;

 

var l: integer;

 

begin

 

   l := 0;

   reset(f);

   while not eof(f) do begin get(f); l := l+1 end;

 

   length := l { return length }

 

end;

 

begin

end.

 

Except that the built in Pascaline function does not change the location within the file. The length function cannot be applied to a file of type text, because the length of line endings is implementation defined, so the length of a text file is as well.

 

Each element of a Pascal file can be enumerated. In Pascaline, the elements of a file that is not of type text are numbered from 1 to n, where n is the last element of the file. The current location within the file is found with the built in function location:

 

program p(output);

 

var f: file of integer;

 

begin

 

   writeln('The location in the file is: ', location(f));

 

end.

 

The current location within a file can be set by the built in procedure "position":

 

program p;

 

var f: file of integer;

 

begin

 

   position(f, 10)

 

   { statements to use f }

 

end.

 

Position will work with any element from 1 to n+1, where n is the last element of the file. Position allows the location to be set one beyond the length of the file so that the file can be extended at the end.

 

As with length, there is no way to apply either location or position to a text file.

 

In standard Pascal, there is no way to update a preexisting file with new data. In Pascaline the procedure update can be used instead of rewrite:

 

program p;

 

var f: file of integer;

 

begin

 

   assign(f, 'myfile');

   update(f);

 

   { statements to use f }

 

end.

 

As for rewrite, update places the file in write mode. However, update does not clear the previous contents of the file. Update sets the location within the file at 1, just as reset does. If the common operation of updating a file at the end is wanted, the following code does this:

 

program p;

 

var f: file of integer;

 

begin

 

   assign(f, 'myfile');

   update(f);

   position(f, length(f)+1);

 

   { statements to use f }

 

end.

 

Update only works with non-text files. The built in procedure append performs the same action as above, but works with both text and non-text files:

 

program p(output);

 

var f: text;

 

begin

 

   assign(f, 'myfile');

   append(f);

   writeln(f, 'hi there');

 

end.

 

To determine if a file by name exists in the system, the function exists can be used:

 

if exists('thisfile') then { operate on ‘thisfile’ };

 

The exists function takes a variable reference to a Pascal string, and returns a boolean value that is true if the file exists.

 

The exists function can be used to determine beforehand if a reset will yield an error because of a non-existent file.

 

To delete a file by name, the delete procedure is used:

 

delete('oldfile');

 

Delete accepts a variable reference to a string, and causes the file to be removed from the system. It is an error if the file does not exist.

 

To change the name of an existing file, the change() procedure is used:

 

change('newname', 'oldname');

 

The file with the name of the second parameter is changed to be the first parameter. Both parameters are variable references to strings. It is an error if the second parameter does not exist in the system, and also if the first parameter exists before the change call. It is also an error if any differences exist in the names besides just their principal names. This rule forbids, for example, the changing of the location or system parameters of the file using the change call.

 

5.18    Files of files

 

ISO 7185 forbids files to contain any other files, either directly, or as part of a substructure (see ISO 7185 6.4.3.5 “File-types”). In Pascaline, this restriction is removed. File types can have as component-type either a file, or a structure containing a file at any level:

 

program p;

 

type textlist: file of text;

 

var fl: textlist;

 

procedure getfilelist(var l: textlist);

 

begin

 

   { get list of text files }

 

end;

 

begin

 

   getfilelst(fl);

   while not eof(fl) do begin { traverse files list }

 

      while not eof(fl^) do begin{ read file}

 

         if fl^^ > ‘ ‘ then { process non-space char };

         read(fl^, c) { next character }

 

      end;

      get(fl); { next text file }

 

   end

 

end.

 

Files of files are a convienent method to represent arbitrary lists of files. For example, a call to present a “user file dialog” which allows a user to select multiple files from a directory, could return the resulting list as a file of files.

 

5.19    Added program header standard bindings

 

Besides the standard Pascal textfile external bindings of input and output, there are three new external bindings defined by Pascaline:

 

error

 

This file can be used to output error messages or warnings to. It may be aliased to output on an implementation. The purpose of the error file is to provide a output file that will always go to the user's console, and cannot be redefined as routed to another display device.

 

list

 

This file is used to output for what is assumed to be printout from any attached hard copy device. The implementation may alias this file to the output file if such a device is not available, or if hard copy is not desired.

 

command

 

The command file is a text line or series of text line that deliver instructions to the running program. Most commonly, it carries a single line containing the remaining text of the command line that activated the running program, after the command name itself is discarded. However, it can contain any instruction line, and can even be directed to be an entire file containing such commands.

 

The exact format of the commands and parameters contained in file are implementation dependent. If the implementation has no concept of a command line, the file can be assigned to another file, or may appear empty.

 

Since on many systems a command line exists as a line of text in memory, not as part of a file system, it is understood that the implementation will simulate the access to such a line as a file, if that is required.

 

In this Pascaline specification, implementers are reminded of the requirements of ISO 7185 6.10 "Programs" wherein it is an error if a program parameter is acted on and cannot complete that action. This clause of ISO 7185 Pascal specifically forbids ignoring the program parameters.

 

Further, in Pascaline it is strongly suggested that the program parameters which are common text files be connected, or can be caused to connect, to external files by binding. See Annex M.

 

5.20    Redeclaration of forwarded procedures and functions

 

In Pascaline, the parameters of a forwarded procedure or function can be repeated. As in ISO 7185 Pascal, the names of the parameters are the same as the original names in the forwarded header. The new names, if they happen to be different in the repeated header, are ignored. However, the two parameter lists are checked for "congruency" using the same rules as procedure and function parameters in ISO 7185 6.6.3.6 “Parameter list congruity”.

 

Repeating the parameters in a forwarded procedure or function both increases the self documenting nature of a program, by keeping the parameters close to the actual body of the procedure or function, as well as making it easier to create such headers, by simple block copy.

 

5.21    Unnamed function result

 

Pascaline has an alternate method to indicate a function result:

 

function-declaration = function-heading ';'directive | function-identification ';' function-block | function-heading ';' function-block .

 

function-block = block .

 

block = { declaration } [ 'private' { declaration } ] statement-part [ ';' statement-part ] .

 

compound-statement = 'begin' statement-sequence [ ‘result’ expression ] 'end' .

 

At the end of the main block of a function, a result statement can appear:

 

program p;

 

function y(a, b: integer): integer;

 

begin

 

   result a+b

 

end;

 

The result statement is an alternative to the ISO 7185 arrangement of assigning the result to the name of a function that is active. It can only be used in a function, and it can only be used at the end of the function. It can only give the result of the enclosing function (in contrast to ISO 7185 function results). It cannot be used in conjunction with a ISO 7185 assignment to the name of the function appearing in either the block of the function whose result is to be set, nor any nested block. Thus, the following example is illegal:

 

{ illegal example }

 

program p;

 

function y(a, b: integer): integer;

 

procedure q;

 

begin

 

   y := 1

 

end;

 

begin