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. 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. 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 Niklaus
Wirth designed into 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:

·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 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 theme 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 appear 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.

The second, but no less important theme in Pascaline, is
parallel language execution. Pascaline is a thoroughly parallel language, and
completes the idea that strong type security is a fundamental building block to
parallel language implementation. Indeed, Pascaline now exists as one of the
only languages that offers parallel execution security in a language, instead
of being added in as a library with security left to the user.

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 from the annexes, without exception.

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:

Block

(procedure or function)

Parameter

List

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

Block

(Module
or Class)

Constants

Variable
declarations

Procedures

…

Surrounding
Block

Each block can import declarations from the surrounding
block.

Pascal envisioned 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:

Block

Constants

Variable
declarations

Procedures

…

Block

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 or channel 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, channel, 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 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 the 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 an
instance of a module. Classes complete the idea of "object
orientation" which dictates that data exists as paired with the procedures
or functions that form its 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.

As a dynamic corollary to a module, classes also can have a
separate thread of execution as a thread class, and perform as a tasking
communications block as an atom or liaison class.

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.

A line comment uses a single character, “!”, that allows the
rest of the line to appear as a comment.

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 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, two new parameter
"modes" are implemented, the view
and out modes. The view mode is identical to value
parameter semantics, except that the parameter is protected from all
modification. This makes certain compiler optimizations possible. The out mode is identical to var mode, but flags to the
compiler that the parameter will be used only to pass out results.

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.

Read/readln can specify fields on read
variables, and can specify literal strings to be matched to the input. A
special mode allows the input 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.

Besides standard reals, there is a type that is smaller than
the standard real, and a type that is larger than the standard real. There are
new constants that give the maximum values in each real type.

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

Matrix mathematics is supported with one dimensional and two
dimensional arrays.

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.

Function results are extended to allow most types, including
structured, to be returned as a result.

Properties specify a program object that appears as a
variable, but has its read and write actions completely program defined.
Properties are also a building block to advanced multitasking structures.

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.

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.

As allowed in ISO7185 3.2 “extension”, the following additional spellings of identifiers
are prohibited because of their use as word-symbols in the Pascaline standard:

forwardmoduleusesprivateexternal

viewfixedprocessmonitorshare

classisxoroverloadoverride

referencejoinsstaticinheritedself

virtualtryexceptextendson

resultoperatorstartthreadatom

propertychannelliaisonout

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:

Annex E “Character Escapes”, if implemented by the target
system, can affect the behavior of character strings in an ISO 7185 implementation.
Although ISO 7185 does not specify the character set or contents of strings in
a complying program, it is reasonable for a given program to assume that all
visible characters are treated equally.

If the program contains the character ‘\’, the escape
sequence introduction character, this will be treated differently than other
characters. To use a Pascaline implementation that implements Annex E for such
programs, oneof three methods are used:

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 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 5.2 “processors” is neither allowed as a starting point for Pascaline,
nor carried forward into the language Pascaline.

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 extension to Pascaline.

Extensions to Pascaline are changes to language features in
this standard that do not cause a program complying with this standard to fail
to compile, interpret, run or otherwise function with the exception that one or
more additional spellings of symbols may be reserved to the processor. That is,
additional reserved word-symbols may be defined.

An example of an extension that does not comply with this
standard is a modal change such as redefining the functionality of the “mod”
operator. This would cause otherwise complying programs to fail to function.

<This processor> complies with the requirements of
Pascaline version X.X [and the annexes A, B, C…]

Where:

<This
processor> Is the name of the complying
processor

X.XIs the version number of the
Pascaline specification complied with.

[and the annexes A, B, C..]Is
an optional list of the annexes also compiled with]

There is no minimum requirement for the number of annexes
complied with. The processor may comply with any number from zero to all of
them. In some cases, it may be inappropriate for a particular implementation to
have compliance with a particular annex. For example, the graphical display
annex K in conjunction with a system that has no graphical display. Just as
compliance with the basic Pascaline standard implies that a program will or
will not run, the presence or absence of an annex a program relies on may cause
it to compile and run, or fail to do so.

If the processor complying with this standard contains extensions
(defined in 4.6
“Extensions to Pascaline”), it shall contain a switch for compliance with Pascaline
with the following characteristics:

3.Does not cause any program complying with the
Pascaline standard to fail to compile, interpret, run or otherwise function,
with the exception of restriction of spelling of identifiers (additional
reserved words).

Note that if the processor contains extensions that do not
comply with the Pascaline definition of extensions (4.6
“Extensions to Pascaline”), the processor will, by definition, not comply with
the “Off” switch requirement above.

In general much of the form and manner of the original ISO
7185 standard document was followed in this document. However, in one case
there is a distinct difference. The original ISO 7185 document does not distinguish
between errors at compile time and at runtime, which sometimes overlap. In this
standard, all runtime errors are represented as exceptions, and a list of
exceptions appears as an annex.

The use of “equivalent code” occurs many times in this
document. That is, a built-in or standard operation or statement is explained
in terms of other statements in ISO 7185 Pascal or Pascaline. This creates a
concrete and exact explanation of standard actions.

In 1972 A project was begun to
create a portable compiler that accepted and processed a subset of the original
Jensen and Wirth Pascal standard. This compiler went through several versions,
and ended as the Pascal-P4 compiler. In its final iteration, it still a subset
compiler, with several features of J&W left out. This compiler was
extensively documented by both the Zurich originators and in “Pascal
Implementation: the P4 Compiler” [S. Pemberton and M.C. Daniels].

In 1982, the ISO 7185 standard was
issued, and this was accompanied by the ISO 7185 compiler in A model
Implementation of Standard Pascal [Welsh], and by a BSI (British Standards
Institute) test suite designed to fully test existing compilers.

In 2009 a project was begun to
improve the original Zurich Pascal-P compiler to accept and process the ISO 7185
Pascal standard. This resulted in Pascal-P5, which replaces the model
implementation. It was accompanied by an extensive document and by a new test
suite designed to replace the BSI test suite, which is no longer available.

In 2011 a project was begun to
implement the Pascaline language as an increment to the Pascal-P5 compiler, and
create a new test suite to verify the result, and also a new working document
for the compiler.

The Pascal-P6 implementation
provides a freely available, public domain example implementation of Pascaline
whose test suite is also freely available. This can be used as an example for a
new Pascaline implementation, as a starting point for such an implementation,
and/or as a source of tests for such an implementation, or simply as a
reasonable implementation in its own right.

Pascal-P6 and its associated tests
provide the proving system for the Pascaline language. It is expected that when
the Pascal-P6 implementation is complete and tested, that this standard will
reach a 1.0 version.

The character ‘!’ introduces a “Line Comment”. All
characters up to and including the next end of line are ignored. This allows a
comment form that is short, and automatically terminated by the end of line:

!

! A simple program

!

program p;

begin

writeln(‘Hello, world’) ! print
to console

end.

Notes:

1.The ‘!’ character must appear between Pascaline
symbols and not within any symbol.

2.Any other comment characters within a line
comment are ignored, ‘{‘, ‘}’, ‘(*’, or ‘*)’.

Identifiers in Pascaline are identical to ISO 7185 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 ISO
7185 Pascal, identifiers are not case sensitive.

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

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.

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.

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 = packedarray [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 can 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 = packedarray [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.

An out parameter
is functionally identical to a var
parameter except that it indicates that the parameter will be used only to
return results to the caller, and that the contents of the variable passed will
not be initialized on entry. This allows the processor to check for accesses to
the variable before it has been assigned.

The specification of only fixed arrays in ISO 7185 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 = arrayof integer;

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

{ incorrect example }

program p;

type a = arrayof 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 three 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.

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. 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 = packedarray [1..100] of char;

and

type b = packedarrayof char;

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

and

type b = arrayofarrayof integer;

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

type string = packedarrayof char;

procedure x(var s: string);

And can use any mode.

As with ISO 7185 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= packedarrayof char;

var b: ap;

begin

new(b, 10);

b := 'hi there';

end.

The call of new
must specify the size of all indices, in the same order as the indices appear
in the declaration.

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 = packedarray [20..120] of char;

b = arrayof 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. The
equivalent of the above copy operation is:

program p;

type a = packedarray [20..120] of char;

b = arrayof char;

c = ^b;

var q: a;

x: c;

begin

new(x, 100);

{ x := q; }

for i := 1 to 100 do x^[i] := q[i+20-1];

{ q := x; }

for i := 1 to 100 do q[i+20-1] := x^[i]

end.

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 = arrayofarrayofarrayof 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);

Container arrays make it possible to have a type that
represents a string, or packed array of characters with a starting index of 1:

type string = packedarrayof char;

This is a standard system definition in Pascaline. In
addition, a pointer to a string is also standard:

Variables which are declared using containers use a
parameterized form that takes one or more expressions on the left side, which
are used to fulfill the indices 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 indices are processed from
the outermost declaration to innermost. If multiple dimension arrays exist, the
indices appear from major to minor.

Every index in the type must be matched. If there are more
or fewer index expressions that there are indices 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 is performed before
the code in the block for which the variable is declared is executed. The indices
do not vary during the execution of the declaring block. This means the
following variant of the above code would function correctly:

program p;

type z = arrayof integer;

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

var a(l): arrayof integer;

i: integer;

begin

l := 5;

for i := 1 to l do a[i] := v[i]+1

end;

var r(10): z;

i:integer;

begin

for i := 1 to 10 do r[i]
:= i+10;

q(10, r)

end.

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. This allows a container type to be used as a
“template” type to create static variables:

program p;

type z = arrayof integer;

var a(10): z; ! an array of
10 integers

b(20): z; ! an array of 20
integers

begin

end.

If the parameterized variable expression 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.

Parameterized variables allow the specification of fixed
types from abstract types. This allows both the use of types for general
classes of types, as well as moving the sizes of arrays out of type
descriptions.

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.

program p(output);

var i: integer;

begin

write(i:-10)

end.

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

The behavior of a fielded write for integers is equivalent
to:

program p(output);

procedure WriteInteger(var f: text; i: integer; fl: integer);

var c: integer;

p: integer;

begin

if fl < 0 thenbegin ! left justified

! determine the number of required
characters

c := 0;

if i < 0 then c := c+1; ! count sign

p =
maxint; ! set maximum power

! count digits

while p > 0 do

beginif abs(i) >= p then c := c+1; p := p div 10 end;

write(f, i:1); ! output
minimum format

if f > c then
write(f, ‘ ‘:fl-c) ! complete justification

endelse write(f, i:fl);
! output regular format

end;

begin

WriteInteger(output, 20, -10)

end.

For real values in the floating point format, there is no
change for left justified formatting. This occurs because there are no blanks
used to justify such a number. The precision of the fraction is simply extended
to fill the field. Thus:

program p(output);

var r: real;

begin

write(r:-20)

end.

Is equivalent to:

program p(output);

var r: real;

begin

write(r:20)

end.

There is no difference between the left justified format for
a floating point representation, but there is also no error.

For a real value output in fixed point format:

program p(output);

var r: real;

begin

write(r:-20:5)

end.

The equivalent code is:

program p(output);

procedure WriteRealFixed(var f: text; r: real; fl: integer;

fr: integer);

var c: integer;

p: real;

begin

if fl < 0 thenbegin ! left justified

! determine the number of
required characters

c := 2; ! minimum field
includes ‘0.’

if r < 0 then c :=
c+1; ! count sign

p = 10.0; ! set minimum for
extra digits

! calculate digits beyond
‘0.’

while p <= abs(r) do
begin c := c+1; p := p*10 end;

write(f, i:c:fr); ! output
minimum format

if f > c then
write(f, ‘ ‘:f-(c+fr)) ! complete justification

endelse write(f, i:f);
! output regular format

end;

begin

WriteRealFixed(output, r, -20,
5)

end.

A zero field parameter has practical use only with string
type and character type parameters. This is because integer and real types have
minimum output format sizes. An example of use with strings is:

read/readln statements are symmetrical
with their write/writeln
counterparts for text files. Variable parameters can accept field
specifications. String variables can be read. Constant string parameters can
appear, to be matched to input.

The net effect of symmetrical read/readln operations is to allow
files generated by write/writeln statements to also be
read by read/readln
statements.

If the end of line is encountered, it is read as a space and
the read operation continues. If end of file is encountered, it is an error.

For fielded read parameters, an integer value field, which
can be any expression, appears after the read parameter:

program p;

var f: text;

i: integer;

begin

read(f, i:10);

end.

The fielded read requires the input integer to be complete
within the specified number of characters, disregarding any leading or trailing
blanks.

The equivalent code to read an integer is:

program p;

var f: text;

i: integer;

procedure ReadInteger(var f: text; var i: integer; fl: integer);

var s: integer;

function NextChar: char;

begin

{ if past the field, terminate
with space }

if fl = 0 then NextChar
:= ‘ ‘

else NextChar := f^

end;

procedure GetChar;

begin

get(f);

fl := fl-1

end;

begin

s := +1; { set sign }

{ skip leading spaces }

while (NextChar = ‘ ‘) andnot eoln(f) do GetChar;

ifnot (NextChar in
[‘+’, ‘-‘, ‘0’..’9’]) then

throw(InvalidIntegerFormat);

if NextChar = ‘+’ then
GetChar

elseif NextChar = ‘-‘ thenbegin GetChar(f); s := -1 end;

ifnot (NextChar in
[‘0’..’9’]) thenthrow(InvalidIntegerFormat);

i := 0; { clear initial value }

while (NextChar in [‘0’..’9’]) dobegin { parse digit }

i :=
i*10+ord(NextChar)-ord(‘0’); { add in new digit }

GetChar

end;

{ make sure the rest of the
field is spaces }

while fl > 0 do begin

if NextChar <> ‘ ‘ then
throw(InvalidIntegerFormat);

GetChar

end

end;

begin

ReadInteger(f, i, 10)

end.

Reading a character with a field is similar

program p;

var f: text;

c: char;

begin

read(f, c:10);

end.

The equivalent code is:

program p;

var f: text;

c: char;

procedure ReadChar(var f:
text; var c: char; fl: integer);

begin

read(f, c); ! get the character

! make sure the rest of the
field is spaces

while fl > 0 dobegin

if f^ <> ‘ ‘ then
throw(FieldNotBlank);

get(f);

fl := fl-1

end

end;

begin

ReadChar(f, c, 10)

end.

When reading a string, the default field is equivalent to
the number of characters in the string. If a field is present, and is greater
than the number of characters in the string, then the string is expected to
appear with a number of leading blanks. To specify a number of trailing blanks,
a negative field is specified.

In both cases, if the field is smaller than the number of
characters in the string, only that number of characters will be read. There is
no initialization implied for characters in the string past the number of
characters in the field.

If the field is 0, the space padded string mode is entered.
In this mode, all characters that are present in the input before any end of
line or end of file are read into the string, then the remaining characters in
the string are set to blanks. In this mode it is an error if there are more
characters present before the end of line or end of file than there are
available in the string.

program p;

var f: text;

s: packed array [1..20] of
char;

begin

read(f, s:10);

end.

The equivalent code is:

program p;

var f: text;

s: packed array [1..20] of
char;

procedure ReadString(var f: text; var s: string; fl: integer);

var l: integer; { net length
of string }

i: integer;

procedure SkipSpaces(c:
integer);

begin

while c > 0 dobegin

if f^ <> ‘ ‘ then
throw(FieldNotBlank);

get(f);

c := c-1

end

end;

begin

if fl = 0 thenbegin { padded mode }

i := 1; { set start of
string }

whilenot eoln(f) and not eof(f) do begin

if i > max(s) do
throw(InputExceedsString);

read(s[i]);

end;

{ clear the rest of the
string to blanks }

while i < max(s) do
s[i] := ‘ ‘

endelsebegin

l := max(s); { find net
length of string }

if abs(fl) < l then l
:= fl;

{ skip leading spaces }

if -fl > max(s) then
SkipSpaces(max(s)+fl);

for i := 1 to l do
read(f, s[i]); { get string characters }

{ skip trailing spaces }

if fl > max(s) then
SkipSpaces(max(s)-fl)

end

end;

begin

ReadString(f, s, 10)

end.

For real variables, the results are similar to that of
integer:

program p;

var f: text;

r: real;

begin

read(f, r:10);

end.

The equivalent code is:

program p;

var f: text;

r: real;

procedure ReadReal(var f: text; var r: real; fl: integer);

var i: integer;

{ find power of ten efficiently }

function pwrten(e: integer): real;

var t: real; { accumulator }

p: real; { current power }

begin

p := 1.0e+1; { set 1st power }

t := 1.0; { initalize result }

repeat

if odd(e) then t := t*p;
{ if bit set, add this power }

e := e div 2; { index next
bit }

p := sqr(p) { find next
power }

until e = 0;

pwrten := t

end;

function NextChar: char;

begin

{ if past the field, terminate
with space }

if fl = 0 then NextChar
:= ‘ ‘

else NextChar := f^

end;

procedure GetChar;

begin

get(f);

fl := fl-1

end;

procedure ReadInteger(var i:
integer);

var s: integer;

begin

s := +1; { set sign }

ifnot (NextChar in
[‘+’, ‘-‘, ‘0’..’9’]) then

throw(InvalidRealFormat);

if NextChar = ‘+’ then
GetChar

elseif NextChar = ‘-‘ thenbegin GetChar(f); s := -1 end;

ifnot (NextChar in
[‘0’..’9’]) then throw(InvalidRealFormat);

i := 0; { clear initial value }

while (NextChar in [‘0’..’9’]) dobegin { parse digit }

i :=
i*10+ord(NextChar)-ord(‘0’); { add in new digit }

GetChar

end

end;

begin { ReadReal }

{ skip leading spaces }

while (NextChar = ‘ ‘) and
(fl > 0) do GetChar;

ReadInteger(i); { read integer
section }

r := i; { convert integer to
real }

if NextChar in ['.',
'e', 'E'] thenbegin { it's a real }

if NextChar = '.' thenbegin { decimal point }

GetChar; { skip '.' }

ifnot (NextChar in ['0'..'9']) then

throw(InvalidRealFormat');

p := 1.0; { initialize
power }

while NextChar in ['0'..'9']
dobegin { parse digits }

p := p/10.0; { find
next scale }

{ add and scale new
digit }

r := r+(p *
(ord(NextChar) - ord('0')));

GetChar { next }

end

end;

if NextChar in ['e',
'E'] thenbegin { exponent }

GetChar; { skip 'e' }

ifnot (NextChar in
['0'..'9', '+', '-']) then

throw(InvalidRealFormat);

ReadInteger(i); { get
exponent }

{ find with exponent }

if i < 0 then r :=
r/pwrten(i) else r := r*pwrten(i)

end

end;

{ make sure the rest of the
field is spaces }

while fl > 0 dobegin

if NextChar <> ‘ ‘ then
throw(InvalidRealFormat);

GetChar

end

end;

begin

ReadReal(f, r, 10)

end.

Constant strings are allowed to appear in the read/readln
parameter list:

program p;

var f: text;

i: integer;

begin

read(f, ‘The answer is: ‘,
a,‘ resulting in: ‘, b);

end.

The effect of such a constant is that each character of the
input is matched to the characters in the string, in turn, regardless of if the
end of line is true. If the character is matched, it is read and thrown away.
If the character is not matched, it is an error.

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 enumerated types "type
converter":

program p;

type a = (one, two, three);

var x: a;

begin

x := a(1);

end.

In the examplethe
result of a(1) is the enumerated type constant two.
Transfer from an integer to an enumerated type is the only new type conversion
defined in Pascaline.

A similar appearing construct is the “type restrictor”:

program p;

type a = 20..30;

var y: integer;

begin

y := a(y+1);

end.

The assignment y := a(y+1) 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.

The value within a type restrictor must be assignment
compatible with the type specified in the type restrictor.

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] ofpackedarray [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. A
value constructor is a series of constants or other value constructors
separated by ‘,’s. As in the case of character array constant assignment to
character array variables, a constant string can be used to specify the value
of a fixed character array, and must
have the same number of characters as the definition.

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.

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');

reset(f);

{ statements to use file f }

close(f)

end.

assign takes
any string (defined in ISO 7185 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 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','_'].

Notes:

1.These are the same conventions as used for
identifiers in Pascaline.

2.This is only a subset of implementation defined
filename conventions. The particular Pascaline implementation may have its own additional
requirements for the formatting of filenames that are a superset of the above
conventions.

The Pascaline standard library services
has a higher level structuring of filenames that are upward compatible with the
above conventions. See Annex G.

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 ISO 7185 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.

A file must be in the undefined state to have assign applied to it. The effect
of multiple assign operations applied to the
same file while in the undefined state is itself undefined.

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

program p;

var f: text;

names: array 5 of packedarray 10 of char = array

‘myfile‘,

‘thisfile‘,

‘thatfile‘,

‘nextfile‘,

‘lastfile‘

end;

i: integer;

begin

for i := 1 to 5 dobegin

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.

ISO 7185 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(output);

var f: fileof 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(output);

type fi: fileof integer;

var f: fi;

function length(var f: fi):
lcardinal;

var l, r, p: integer;;

begin

l := 0; { clear length }

r := 0; { clear remainder }

{ find remaining elements }

whilenot eof(f) dobegin
get(f); r := r+1 end;

{ rewind and count the total
elements }

reset(f);

whilenot eof(f) dobegin
get(f); l := l+1 end;

p := l-r; { find position from
length – remainder }

{ find original position }

reset(f);

while p > 0 dobegin get(f); p := p-1 end;

length := l { return length }

end;

begin

assign(f, ‘myfile’);

reset(f);

writeln(‘Length of myfile: ‘,
length(f))

close(f)

end.

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 implementation defined 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: fileof integer;

begin

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

end.

The function location
is equivalent to:

program p;

type fi: fileof integer;

var f: fi;

function location(var f: fi): lcardinal;

var l, r, p, c: integer;

begin

l := 0; { clear length }

r := 0; { clear remainder }

{ find remaining elements }

whilenot eof(f) dobegin
get(f); r := r+1 end;

{ rewind and count the total
elements }

reset(f);

whilenot eof(f) dobegin
get(f); l := l+1 end;

p := l-r; { find position from
length – remainder }

{ find original position }

reset(f);

c := p; { set count from
position }

while c > 0 dobegin get(f); c := c-1 end;

location := p { return location
}

end;

begin

assign(f, ‘myfile’);

reset(f);

writeln(‘Location of myfile: ‘,
location(f))

close(f)

end.

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

program p;

var f: fileof integer;

begin

assign(f, ‘myfile’);

reset(f);

position(f, 10)

{ statements to use f }

close(f)

end.

The procedure position
is equivalent to:

program p;

type fi: fileof integer;

var f: fi;

procedure position(var f: fi;
p: integer);

begin

reset(f);

while p > 1 dobegin get(f); p := p-1 end

end;

begin

assign(f, ‘myfile’);

reset(f);

position(f, 10);

{ statements to use f }

close(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.

It is an error to apply position
to an undefined file.

In ISO 7185 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: fileof integer;

begin

assign(f, 'myfile');

update(f);

{ statements to use f }

end.

The procedure update
for integers is equivalent to:

program p;

type fi: fileof integer;

procedure update(var f: fi);

var cpy: fi;

i:integer;

begin

! copy previous contents of
file

reset(f);

rewrite(cpy);

whilenot eof(f) dobegin
read(f, i); write(cpy, i) end;

! change modes and copy back to
original file

rewrite(f);

reset(cpy);

whilenot eof(cpy) dobegin
read(cpy, i); write(fi, i) end

end;

var f: fi;

begin

assign(f, 'myfile');

update(f);

! statements to use f

end.

The file that update
is applied to must exist.

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: fileof 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.

The procedure append
for text files is equivalent to:

program p;

procedure append(var f: text);

var cpy: text;

c:char;

begin

! copy previous contents of
file

reset(f);

rewrite(cpy);

whilenot eof(f) dobegin

if eoln(f) thenbegin readln(f); writeln(cpy) end

elsebegin read(f, c);
write(cpy, c) end

end;

! change modes and copy back to
original file

rewrite(f);

reset(cpy);

whilenot eof(cpy) dobegin

if eoln(cpy) thenbegin readln(cpy); writeln(f) end

elsebegin read(cpy, c);
write(f, c) end

end

end;

var f: text;

begin

assign(f, 'myfile');

append(f);

! statements to use f

end.

The file that append
is applied to must exist.

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

program p(output);

var f: text;

begin

if exists(‘thisfile’) then

{ operate on ‘thisfile’ }

end.

The exists function
takes a variable reference to a Pascaline 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:

program p(output);

begin

delete('oldfile')

end.

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:

program p(output);

begin

change('newname',
'oldname')

end.

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.

Besides the ISO 7185 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
by 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 the 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 to command file names. (See Annex C).

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.

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 Pascal function results). It cannot be used in conjunction with a ISO
7185 Pascal 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

result a+b

end;

But this example is legal:

program p;

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

function q: integer;

begin

y := a+b;

result 1

end;

begin

a := q

end;

The assignment to the function result y is legal in q, even though q is using the result method,
because the function y is using the
ISO 7185 named function result method.

Unnamed function results give a clear way to indicate the
function result, that obeys the single entry/single exit rule with the function
result formed at the exit. They are also required in order to indicate the
result of an operator overload function (See 6.25
“Operator
overloads”).

The attribute overload
can be used to specify that one procedure or function forms an overload group
with another:

program p;

procedure x(y: integer);

begin

{ statements to operate on
parameter y }

end;

overloadprocedure x(c: char);

begin

{ statements to operate on
parameter c }

end;

Any number of procedures or functions with the same name can
be joined this way into an overload group. When the procedure or function is
called, the compiler determines which of the procedures or functions in the
overload group is to be used to satisfy the call. Thus, both of these calls are
possible with the definitions above:

x(1);

x('c');

The compiler considers three things when determining which
procedure or function of an overload group is meant:

1.If the called context is a procedure or function
call.

2.The number of parameters.

3.The type compatibility of the parameters.

Overload groups are not allowed to be ambiguous. There
is no "preference" or "priority" involved with overloads.
If two overloads are ambiguous with respect to each other, then an error will
result at the time of the definition of the conflicting overload.

Two calls are ambiguous with each other if they match for
procedure/function status, have the same number of parameters, and the parameters
are compatible between lists, using the ISO 7185 definition of compatibility
according to 6.4.6 “Assignment-compatibility” (where either parameter could be
assignment compatible with the other), and also if one parameter is char while the other is a single
character string. This means, for example, that having one parameter of type real, and the other of type
integer, means those parameters are ambiguous with each other.

When parameter lists are compared, the mode of the
parameter, or its var, view or value status is ignored.

It is an error if two parameter lists "converge"
with different modes. Two parameter lists are said to converge at any point in
the list if that parameter and all parameters to the left of it are found to be
compatible using the rules above. An example of an overload declaration that is
invalid by this rule is:

! invalid program

program p;

procedure a(i: integer; c:
char; b: boolean);

begin

{ statements of first
overloadof a }

end;

overloadprocedure a(i: integer; var
c: char; b: boolean; r: real);

begin

{ statements of second overload
of a }

end;

begin

end.

Even though the two parameter lists would be distinct
because they differ in number, the lists are convergent at parameter c, and parameter c has conflicting modes, the
first being value, and the second being var.

The purpose of the convergence rule is to relieve compilers
from having to store all the parameters in a procedure or function call before
determining which routine of an overload group matches the call.

Overload groups must be completed within the same
declaration block. Different modules, classes, procedures and functions cannot
add to each other’s overload groups.

Besides overloading procedures and functions, it is also
possible to overload expression operators:

program p;

type string = packed array of integer;

pstring = ^string;

operator +(a, b: string):
pstring;

begin

{ code to concatenate strings a
and b }

end;

operator :=(a, b: string);

begin

{ code to assign string b to a }

end;

begin

end.

Where “+” and “:=”are the operators to overload. The
following operator overloads are possible:

Program p;

type x: record i, r: integer end;

operator +(a: x): x; begin result a end;

operator –(a: x): x; begin result a end;

operatornot (a: x): x; begin result a end;

operator +(a, b: x): x; begin result a end;

operator -(a, b: x): x; begin result a end;

operator *(a, b: x): x; begin result a end;

operator /(a, b: x): x; begin result a end;

operator div(a, b: x): x; begin result a end;

operator mod(a, b: x): x; begin result a end;

operator and(a, b: x): x; begin result a end;

operator or(a, b: x): x; begin result a end;

operator xor(a, b: x): x; begin result a end;

operator <(a, b: x): x; begin result a end;

operator >(a, b: x): x; begin result a end;

operator =(a, b: x): x; begin result a end;

operator <=(a, b: x): x; begin result a end;

operator >=(a, b: x): x; begin result a end;

operator in(a, b: x): x; begin result a end;

operator is(a, b: x): x; begin result a end;

operator :=(out a: x; b: x):
x; begin end;

begin

end.

The ‘-‘ and ‘+’ operators can be both unary and binary, and
they have different priorities. The exact type of operator is indicated by the
number of parameters that appear. There is only one operator procedure, which
is assignment (‘:=’).

The parameters to an operator function can be any type, but
cannot be var parameters.

The parameters to the operator procedure ‘:=’ can be any
type, but the first parameter must use out
mode.

The results of an operator
function cannot be established via a ISO 7185 by name function result
assignment. Instead, the unnamed result form is used (see 6.22
“Anonymous
function result”).

The existence of an operator overload does not change the
priority of the operator.

Operator overloads follow the same rules as standard
overloads. Specifically, operator overloads cannot be ambiguous with either
each other, or the parameters of standard , built in operators.

The types of built in operators with the exception of is appears in ISO 7185 6.7.2
“Operators”.

The existence of an operator overload will not cause the
built-in operator to be altered in any way. An operator overload simply adds
behavior where the built-in operator would indicate a type error.

Note that since the system definition for is is defined for any object, it
is not possible to overload the is
operator for objects.

The use of an operator overload function to introduce
so-called “side effects” will result in ambiguity as to when the side effect
occurs, since Pascaline does not specify expression evaluation order.

Pascaline defines a static
attribute that is used before any function or procedure to indicate that it is
used statically.

program p;

staticprocedure z;

var x, y: integer;

begin

{ statements of z }

end;

staticfunction y;

begin

{ statements of y }

end;

begin

end.

The static word-symbol
is used to indicate to the compiler that the procedure or function with that
attribute will not recursively call itself, nor be called by any subprocedure
or subfunction.

On some processors with limited addressing resources, using static
can result in smaller and faster executable programs, sometimes dramatically
so. Compilers targeting more advanced processors typically ignore the static word-symbol.

In the case where the procedure or function is contained entirely
within a module, and is not visible outside the module (it is within the
private section), the compiler can automatically determine the static status of a procedure or
function. However, if it is visible outside the module, the compiler must
assume it may be recursively called. In this case, the static attribute is required to
obtain the improved code.

Note:

1.The compiler may also detect that a static attributed procedure or
function calls itself, either directly or indirectly via another procedure or
function, and issue an error.

The declaration order in ISO 7185 Pascal of labels,
constants, types, variables, then procedures and functions is relaxed. These
constructs can appear in any order. However, the rule remains that each
identifier must be declared before its use, with the normal ISO 7185 Pascal
exception for pointer declarations.

Pointer forward references must resolve within the same var declaration.

Relaxing declaration order in Pascaline is a more natural
match for modular compilation.

The most common use for interprocedure gotos is to handle
error returns easily from deep nested procedures. Pascaline provides an
alternative structure. The try statement executes one or
more statements with an "exception guard":

program p;

var myexception: exception;

begin

try

{ ...
}

throw(myexception)

{ ... }

on myexception except {
statement to execute on myexception }

except { statement to be executed on any exception }

else { statement to be executed if no exception occurs }

end.

If anywhere within the guarded execution the statement:

throw(myexception);

or

throw;

is executed, any active procedures or nested statements are
removed, and execution resumes with the statement after either the exception
clause that matches the given exception, or the general exception statement. If
no exception occurs, execution continues either with the else statement, if specified, or
the next statement after the try statement.