IP Pascal - Language

Language

IP Pascal starts with ISO 7185 Pascal (which standardized Niklaus Wirth's original language), and adds:

  • modules, including parallel task constructs process, monitor and share.
module mymod(input, output);
uses extlib; const one = 1;
type string = packed array of char;
procedure wrtstr(view s: string);
private
var s: string;
procedure wrtstr(view s: string);
var i: integer;
begin
for i := 1 to max(s) do write(s)
end;
begin { initialize monitor }
end;
begin { shutdown monitor }
end.

Modules have entry and exit sections. Declarations in modules form their own interface specifications, and it is not necessary to have both interface and implementation sections. If a separate interface declaration file is needed, it is created by stripping the code out of a module and creating a "skeleton" of the module. This is typically done only if the object for a module is to be sent out without the source.

Modules must occupy a single file, and modules reference other modules via a uses or joins statement. To allow this, a module must bear the same name as its file name. The uses statement indicates that the referenced module will have its global declarations merged with the referencing module, and any name conflicts that result will cause an error. The joins statement will cause the referenced module to be accessible via the referencing module, but does not merge the name spaces of the two modules. Instead, the referencing module must use a so-called "qualified identifier":

module.identifier

A program from ISO 7185 Pascal is directly analogous to a module, and is effectively a module without an exit section. Because all modules in the system are "daisy chained" such that each are executed in order, a program assumes "command" of the program simply because it does not exit its initialization until its full function is complete, unlike a module which does. In fact, it is possible to have multiple program sections, which would execute in sequence.

A process module, like a program module, has only an initialization section, and runs its start, full function and completion in that section. However, it gets its own thread for execution aside from the main thread that runs program modules. As such, it can only call monitor and share modules.

A monitor is a module that includes task locking on each call to an externally accessible procedure or function, and implements communication between tasks by semaphores.

A share module, because it has no global data at all, can be used by any other module in the system, and is used to place library code in.

Because the module system directly implements multitasking/multithreading using the Monitor concept, it solves the majority of multithreading access problems. Data for a module is bound to the code with mutexes or Mutually Exclusive Sections. Subtasks/subthreads are started transparently with the process module. Multiple subtasks/subthreads can access monitors or share modules. A share module is a module without data, which does not need the locking mechanisms of a monitor.

  • Dynamic arrays. In IP Pascal, dynamics are considered "containers" for static arrays. The result is that IP Pascal is perhaps the only Pascal where dynamic arrays are fully compatible with the ISO 7185 static arrays from the original language. A static array can be passed into a dynamic array parameter to a procedure or function, or created with new.
program test(output);
type string = packed array of char;
var s: string;
procedure wrtstr(view s: string);
var i: integer;
begin
for i := 1 to max(s) do write(s)
end;
begin
new(s, 12); s := 'Hello, world'; wrtstr(s^); wrtstr('That's all folks')
end.

Such "container" arrays can be any number of dimensions.

  • Constant expressions. A constant declaration can contain expressions of other constants.
const b = a+10;
  • Radix for numbers.
$ff, &76, %011000
  • Alphanumeric goto labels.
label exit; goto exit;
  • '_' in all labels.
var my_number: integer;
  • '_' in numbers.
a := 1234_5678;

The '_' (break) character can be included anywhere in a number except for the first digit. It is ignored, and serves only to separate digits in the number.

  • Special character sequences that can be embedded in constant strings:
const str = 'the rain in Spain\cr\lf';

Using standard ISO 8859-1 memnemonics.

  • Duplication of forwarded headers.
procedure x(i: integer); forward;
...
procedure x(i: integer);
begin
...
end;

This makes it easier to declare a forward by cut-and-paste, and keeps the parameters of the procedure or function in the actual header where you can see them.

  • 'halt' procedure.
procedure error(view s: string);
begin
writeln('*** Error: ', s:0); halt { terminate program }
end;
  • Special predefined header files.
program myprog(input, output, list);
begin
writeln(list, 'Start of listing:'); ... program echo(output, command);
var c: char;
begin
while not eoln(command) do begin
read(command, c); write(c)
end; writeln
end. program newprog(input, output, error);
begin
... writeln(error, 'Bad parameter'); halt ...

'command' is a file that connects to the command line, so that it can be read using normal file read operations.

  • Automatic connection of program header files to command line names.
program copy(source, destination);
var source, destination: text; c: char;
begin
reset(source); rewrite(destination); while not eof(source) do begin
while not eoln(source) do begin
read(source, c); write(destination, c)
end; readln(source); writeln(destination)
end
end.

'source' and 'destination' files are automatically connected to the parameters on the command line for the program.

  • File naming and handling operations.
program extfile(output);
var f: file of integer;
begin
assign(f, 'myfile'); { set name of external file } update(f); { keep existing file, and set to write mode } position(f, length(f)); { position to end of file to append to it } writeln('The end of the file is: ', location(f)); { tell user location of new element } write(f, 54321); { write new last element } close(f) { close the file }
end.
  • 'fixed' declarations which declare structured constant types.
fixed table: array of record a: integer; packed array of char end = array
record 1, 'data1 ' end, record 2, 'data2 ' end, record 3, 'data3 ' end, record 4, 'data4 ' end, record 5, 'data5 ' end
end;
  • Boolean bit operators.
program test;
var a, b: integer;
begin
a := a and b; b := b or $a5; a := not b; b := a xor b
end.
  • Extended range variables.
program test;
var a: linteger; b: cardinal; c: lcardinal; d: 1..maxint*2; ...

Extended range specifications give rules for scalars that lie outside the range of -maxint..maxint. It is implementation specific as to just how large a number is possible, but Pascaline defines a series of standard types that exploit the extended ranges, including linteger for double range integers, cardinal for unsigned integers, and lcardinal for unsigned double range integers. Pascaline also defines new limits for these types, as maxlint, maxcrd, and maxlcrd.

  • Semaphores
monitor test;
var notempty, notfull: semaphore; procedure enterqueue; begin while nodata do wait(notempty); ... signalone(notfull) end; ... begin end.

Semaphores implement task event queuing directly in the language, using the classical methods outlined by Per Brinch Hansen.

  • Overrides
module test1; virtual procedure x; begin ... end; program test; joins test1; override procedure x; begin inherited x end; begin end.

Overriding a procedure or function in another module effectively "hooks" that routine, replacing the definition for all callers of it, but makes the original definition available to the hooking module. This allows the overriding module to add new functionality to the old procedure or function. This can be implemented to any depth.

  • Overloads
procedure x; begin end; overload procedure x(i: integer); begin end; overload function x: integer; begin x := 1 end;

Overload "groups" allow a series of procedures and/or functions to be placed under the same name and accessed by their formal parameter or usage "signature". Unlike other languages that implement the concept, Pascaline will not accept overloads as belonging to the same group unless they are not ambiguous with each other. This means that there is no "priority" of overloads, nor any question as to which routine of an overload group will be executed for any given actual reference.

  • Objects
program test; uses baseclass; class alpha; extends beta; type alpha_ref = reference to alpha; var a, b: integer; next: alpha_ref; virtual procedure x(d: integer); begin a := d; self := next end; private var q: integer; begin end. var r: alpha_ref; begin new(r); ... if r is alpha then r.a := 1; r.x(5); ... end.

In Pascaline, classes are a dynamic instance of a module (and modules are a static instance of a class). Classes are a code construct (not a type) that exists between modules and procedures and functions. Because a class is a module, it can define any code construct, such as constants, types, variables, fixed, procedures and functions (which become "methods"), and make them public to clients of the class, or hide them with the "private" keyword. Since a class is a module, it can be accessed via a qualified identifier.

Classes as modules have automatic access to their namespace as found in C# and C++ in that they do not require any qualification. Outside of the class, all members of the class can be accessed either by qualified identifier or by a reference. A reference is a pointer to the object that is created according to the class. Any number of instances of a class, known as "objects" can be created with the new statement, and removed with the dispose statement. Class members that have instance data associated with them, such as variables (or fields) and methods must be accessed via a reference. A reference is a type, and resembles a pointer, including the ability to have the value nil, and checking for equality with other reference types. It is not required to qualify the pointer access with "^".

Pascaline implements the concept of "reference grace" to allow a reference to access any part of the object regardless of whether or not it is per-instance. This characteristic allows class members to be "promoted", that is moved from constants to variables, and then to "properties" (which are class fields whose read and write access are provided by "get" and "set" methods).

Both overloads and overrides are provided for and object's methods. A method that will be overridden must be indicated as virtual.

Object methods can change the reference used to access them with the "self" keyword.

Single inheritance only is implemented.

  • Structured exception handling
try ... except ... else ...; throw

The "try" statement can guard a series of statements, and any exceptions flagged within the code are routined to the statement after "except". The try statement also features an else clause that allows a statement to be executed on normal termination of the try block.

Exceptions are raised in the code via the throw procedure. Try statements allow the program to bail out of any nested block, and serve as a better replacement for intra-procedure gotos (which are still supported under Pascaline). Since unhandled exceptions generate errors by default, the throw procedure can serve as a general purpose error flagging system.

  • Asserts.
assert(expression);

The system procedure assert causes the program to terminate if the value tested is false. It is typically coupled to a runtime dump or diagnostic, and can be removed by compiler option.

  • Unicode.

IP Pascal can generate either ISO 8859-1 mode programs (8 bit characters) or Unicode mode programs by a simple switch at compile time (unlike many other languages, there is no source difference between Unicode and non-Unicode programs). The ASCII upward compatible UTF-8 format is used in text files, and these files are read to and from 8 or 16 bit characters internal to the program (the upper 128 characters of ISO 8859-1 are converted to and from UTF-8 format in text files even in an 8 bit character encoded program).

  • Constant for character high limit.

Similar to maxint, Pascaline has a maxchr, which is the maximum character that exists in the character set (and may not in fact have a graphical representation). The range of the type char is then defined as 0..maxchr. This is an important addition for dealing with types like "set of char", and aids when dealing with different character set options (such as ISO 8859-1 or Unicode).

Read more about this topic:  IP Pascal

Famous quotes containing the word language:

    There is no such thing as a language, not if a language is anything like what many philosophers and linguists have supposed. There is therefore no such thing to be learned, mastered, or born with. We must give up the idea of a clearly defined shared structure which language-users acquire and then apply to cases.
    Donald Davidson (b. 1917)

    Different persons growing up in the same language are like different bushes trimmed and trained to take the shape of identical elephants. The anatomical details of twigs and branches will fulfill the elephantine form differently from bush to bush, but the overall outward results are alike.
    Willard Van Orman Quine (b. 1908)

    Man, even man debased by the neocapitalism and pseudosocialism of our time, is a marvelous being because he sometimes speaks. Language is the mark, the sign, not of his fall but of his original innocence. Through the Word we may regain the lost kingdom and recover powers we possessed in the far-distant past.
    Octavio Paz (b. 1914)