home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ipo-101.zip
/
progref.txt
< prev
next >
Wrap
Text File
|
1999-02-17
|
177KB
|
5,714 lines
Copyright (c) 1998, 1999 Stuart King. All rights reserved.
Welcome to the Irie Pascal Programmer's Reference Manual
-----------------
Table Of Contents
-----------------
1 Introduction
1.1 Grammar Notation
2 Lexical Elements
2.1 Character Literals
2.2 String Literals
2.3 Integers
2.3.1 Decimal Integers
2.3.2 Hexadecimal Integers
2.3.3 Binary Integers
2.4 Reals
2.5 Special Symbols
2.6 Reserved Words
2.7 Identifiers
2.7.1 Directives
2.7.2 Built-in Identifiers
2.7.3 User Defined Identifiers
2.8 Comments
3 Labels
4 Constants
4.1 Boolean
4.2 MaxChar
4.3 MaxInt
4.4 Nil
4.5 Permission
4.6 Platform
4.7 FileMode
4.8 dir_bit
5 Types
5.1 Enumerated Types
5.2 Subrange Types
5.3 Pointer Types
5.4 Array Types
5.5 String Types
5.6 Record Types
5.7 Set Types
5.8 File Types
5.9 List Types
5.10 Type Identifiers
5.10.1 boolean
5.10.2 char
5.10.3 dir
5.10.4 filename
5.10.5 integer
5.10.6 real
5.10.7 text
6 Variables
6.1 Pointer Variables
6.2 Array Variables
6.3 String Variables
6.4 Record Variables
6.5 List Variables
7 Functions And Procedures
7.1 Built-in Functions
7.1.1 abs
7.1.2 arctan
7.1.3 chr
7.1.4 concat
7.1.5 copy
7.1.6 cos
7.1.7 cosh
7.1.8 eof
7.1.9 eoln
7.1.10 exp
7.1.11 fexpand
7.1.12 filepos
7.1.13 filesize
7.1.14 frac
7.1.15 getenv
7.1.16 hex
7.1.17 int
7.1.18 ioresult
7.1.19 isalpha
7.1.20 isalphanum
7.1.21 isdigit
7.1.22 islower
7.1.23 isprint
7.1.24 isspace
7.1.25 isupper
7.1.26 isxdigit
7.1.27 length
7.1.28 ln
7.1.29 log
7.1.30 locase
7.1.31 lowercase
7.1.32 odd
7.1.33 ord
7.1.34 paramcount
7.1.35 paramstr
7.1.36 pi
7.1.37 platform
7.1.38 pos
7.1.39 pred
7.1.40 random
7.1.41 reverse
7.1.42 round
7.1.43 sin
7.1.44 sinh
7.1.45 sqr
7.1.46 sqrt
7.1.47 succ
7.1.48 swap
7.1.49 system
7.1.50 tan
7.1.51 tanh
7.1.52 trim
7.1.53 trunc
7.1.54 upcase
7.1.55 uppercase
7.2 Built-in Procedures
7.2.1 append
7.2.2 assert
7.2.3 assign
7.2.4 chdir
7.2.5 close
7.2.6 closedir
7.2.7 dec
7.2.8 delete
7.2.9 dispose
7.2.10 erase
7.2.11 exec
7.2.12 exit
7.2.13 flush
7.2.14 fsplit
7.2.15 get
7.2.16 getdate
7.2.17 getfiledate
7.2.18 getfilemode
7.2.19 getfiletime
7.2.20 gettime
7.2.21 halt
7.2.22 inc
7.2.23 insert
7.2.24 mkdir
7.2.25 new
7.2.26 open
7.2.27 opendir
7.2.28 pack
7.2.29 page
7.2.30 put
7.2.31 randomize
7.2.32 rawread
7.2.33 rawwrite
7.2.34 read
7.2.35 readdir
7.2.36 readln
7.2.37 rename
7.2.38 reset
7.2.39 rewinddir
7.2.40 rewrite
7.2.41 rmdir
7.2.42 seek
7.2.43 setfiledate
7.2.44 setfiletime
7.2.45 sleep
7.2.46 str
7.2.47 unpack
7.2.48 val
7.2.49 write
7.2.50 writeln
8 Expressions
8.1 Operators
8.1.1 Not Operator
8.1.2 * Operator
8.1.3 / Operator
8.1.4 Div Operator
8.1.5 Mod Operator
8.1.6 And Operator
8.1.7 And_Then Operator
8.1.8 + Operator
8.1.9 - Operator
8.1.10 Or Operator
8.1.11 Or_Else Operator
8.1.12 Xor Operator
8.1.13 shl Operator
8.1.14 shr Operator
8.1.15 = Operator
8.1.16 <> Operator
8.1.17 < Operator
8.1.18 <= Operator
8.1.19 > Operator
8.1.20 >= Operator
8.1.21 In Operator
8.2 Compatible types
9 Statements
9.1 Empty Statement
9.2 Assignment Statement
9.2.1 Assignment Compatibility
9.2.1.1 Assignment compatibility with array indexing
9.2.1.2 Assignment compatibility with value parameters
9.2.1.3 Assignment compatibility with "read"
9.2.1.4 Assignment compatibility with assignment statements
9.2.1.5 Assignment compatibility with "for"
9.2.1.6 Transfer procedures
9.3 Procedure Statement
9.4 Goto Statement
9.5 Compound Statement
9.6 If Statement
9.7 Case Statement
9.8 Repeat Statement
9.9 While Statement
9.10 For Statement
9.11 With Statement
10 Program parameters
Appendix A. Irie Pascal Grammar
Appendix B. Extensions to Pascal as specified by ISO/IEC 7185
B.1 Relaxed declarations
B.2 Constant ranges
B.3 Otherwise
B.4 Relaxed parameter list congruity
B.5 Non-numeric statement labels
B.6 Underscores in identifiers
B.7 Binary integer constants
B.8 Hexadecimal integer constants
B.9 Input and Output automatically declared
B.10 Double-quoted literals
B.11 and_then operator
B.12 or_else operator
B.13 Bitwise operators
B.13.1 shl operator
B.13.2 shr operator
B.13.3 and (Bitwise) operator
B.13.4 or (Bitwise) operator
B.13.5 not (Bitwise) operator
B.13.6 xor (Bitwise) operator
B.14 Extended constants
B.14.1 maxchar
B.14.2 usr_r
B.14.3 usr_w
B.14.4 usr_x
B.14.5 grp_r
B.14.6 grp_w
B.14.7 grp_x
B.14.8 oth_r
B.14.9 oth_w
B.14.10 oth_x
B.14.11 dir_bit
B.14.12 platform_dos
B.14.13 platform_os2
B.14.14 platform_win32
B.14.15 platform_linux
B.14.16 platform_fbsd
B.14.17 platform_error
B.14.18 appendmode
B.14.19 readmode
B.14.20 writemode
B.15 Extended types
B.15.1 dir
B.15.2 filename
B.15.3 list
B.15.4 string
B.16 Extended variables
B.16.1 exitcode
----------------
1 Introduction
----------------
This is the Irie Pascal Programmer's Reference Manual, and describes
the Irie Pascal language. This manual is not a tutorial and does not
attempt to teach programming. If you are new to programming or new to
Pascal you may need additional information. Fortunately there are many
excellent books which teach programming in Pascal. If you decide to
purchase a Pascal book, you should look for one that covers Standard
Pascal. For information on how to install and use Irie Pascal, see the
Irie Pascal User's Manual which should accompany this manual.
--------------------
1.1 Grammar Notation
--------------------
Context-free grammars are often used to define the syntax of programming
languages because they produce short and precise definitions. A
context-free grammar breaks the syntax of a complex language into a
number of simpler elements called non-terminal symbols. The syntax of
each non-terminal symbol is defined by a production. Each production
consists of a non-terminal symbol followed by some sort of assignment
operator, and then followed by a sequence of special symbols, terminal
symbols and non-terminal symbols. The special symbols are used to describe
how the other symbols can be combined. The terminals symbols are literal
text that can occur in the language being defined. The full context-free
grammar takes the form of a sequence of productions for all the non-terminal
symbols in the language.
The context-free grammar used in this manual has the following notation.
The equal sign is used as the assignment operator in productions to
separate the non-terminal symbol being defined from it's definition.
The special symbols are |, {}, [], and (). The | symbol is used to separate
alternatives (i.e. the grammar allows either the symbols on it's left-hand
side or the symbols on it's right-hand side). The {} symbols are used to
enclose symbols that can be repeated zero, one, or more times. The []
symbols are used to enclose optional symbols (i.e. the grammar allows the
enclosed symbols to either occur once or not occur at all). The () symbols
are used to group symbols that are evaluated together.
The terminal symbols are enclosed in single quotes ('') to distinguish them
For example here are the productions that define the syntax for identifiers.
identifier = letter { letter | digit }
letter = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' |
'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' |
'u' | 'v' | 'w' | 'x' | 'y' | 'z' |
'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' |
'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' |
'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' |
'_'
digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
The productions mean:
An identifier is a letter followed by zero or more letter or digits.
A letter is a lower-case letter or an upper-case letter or an underscore.
A digit is one of the decimal numerals.
The complete grammar for Irie Pascal is given in Appendix A.
--------------------
2 Lexical Elements
--------------------
This chapter describes the elements that make up programs.
----------------------
2.1 Character Literals
----------------------
A character literal is a character enclosed in single quotes (') or
as an extension in double quotes ("). Two single quotes together can be
used to represent single quotes in character literals enclosed in single
quotes. Two double quotes together can be used to represent double quotes
in character literals enclosed in double quotes.
So "'" and '''' are both character literals containing single quotes.
And """" and '"' are both character literals containing double quotes.
Character literals are case-sensitive so 'X' is not equal to 'x'.
The syntax for character literals is as follows
character-literal = ''' string-element-one ''' |
'"' string-element-two '"'
string-element-one = '''' | printable-character
string-element-two = '""' | printable-character
printable-character = any character (including a space) that has a visual
representation.
NOTE: The production for printable-character doesn't follow the usual
notation because 1) its tedious to write out every possible printable
character and 2) the definition for a printable character depends on
the character set being used.
Here are some examples of valid character literals:
'A' '+' ' ' '''' '"'
"A" "+" " " "'" """"
-------------------
2.2 String Literals
-------------------
A string literal is a sequences of zero, two or more characters enclosed in
single quotes (') or as an extension in double quotes. Literals with
one character are character literals not string literals. Two single quotes
together can be used to represent single quotes in string literals enclosed
in single quotes. Two double quotes together can be used to represent
double quotes in string literals enclosed in double quotes. So
"Don't" and 'Don''t' are both string literals containing Don't.
String literals are case-sensitive, so 'Hello' is not equal to 'HELLO'.
There is no explicit limit on the length of string literals but since
string literals can not span more than one line, then the limit on the
length of a line (400) implicitly limits the length of string literals.
The syntax for string literals is as follows
string-literal = empty-string | other-string
empty-string = '''' | '""'
other-string =
''' string-element-one string-element-one {string-element-one ''' |
'"' string-element-two string-element-two {string-element-two '"'
string-element-one = '''' | printable-character
string-element-two = '""' | printable-character
printable-character = any character (including a space) that has a visual
representation.
NOTE: The production for printable-character doesn't follow the usual
notation because 1) its tedious to write out every possible printable
character and 2) the definition for a printable character depends on
the character set being used.
Here are some examples of valid string literals:
'' ' ' 'Don''t' 'Say "Hello"' '!@#$%^&*()'
"" " " "Don't" "Say ""Hello""" "!@#$%^&*()"
------------
2.3 Integers
------------
Integers are whole numbers (i.e. numbers with no fractional part).
Leading zeroes are not significant in integers.
The syntax for integers is
integer = decimal-integer |
hexadecimal-integer |
binary-integer
Irie Pascal supports integers with values between
-2147483647 and +2147483647
----------------------
2.3.1 Decimal Integers
----------------------
A decimal integer is a base 10 whole number.
The syntax for decimal integers is as follows:
decimal-integer = [sign] digit { digit }
sign = [ '+' | '-' ]
digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
Here are some examples of valid decimal integers
100 -0 +7453 000005
--------------------------
2.3.2 Hexadecimal Integers
--------------------------
As an extension Irie Pascal supports hexadecimal (base 16) integers.
The syntax for hexadecimal integers is as follows:
hexadecimal-integer = [sign] '$' hex-digit { hex-digit }
sign = [ '+' | '-' ]
digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
hexdigit = digit |
'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
'A' | 'B' | 'C' | 'D' | 'E' | 'F'
Here are some examples of valid hexadecimal integers
$64 -$0 +$FF -$000ab4
---------------------
2.3.3 Binary Integers
---------------------
As an extension Irie Pascal supports binary (base 2) integers.
The syntax for binary integers is as follows:
binary-integer = [sign] '%' bit { bit }
sign = [ '+' | '-' ]
bit = '0' | '1'
Here are some examples of valid binary integers
%01100110 -%0 +%11111111
---------
2.4 Reals
---------
Reals are numbers with fractional parts. Leading zeroes are not significant
in reals.
The syntax for reals is as follows
real = [sign] unsigned-real
sign = [ '+' | '-' ]
unsigned-real =
digit-sequence '.' fractional-part [ exponent scale-factor ] |
digit-sequence exponent scale-factor
digit-sequence = digit { digit }
fractional-part = digit-sequence
exponent = 'e' | 'E'
scale-factor = [ sign ] | digit-sequence
Here are some examples of real numbers:
-1.23456e2 which is equal to -123.456
-1.23456e02 which is also equal to -123.456
009863434455e-07 which is equal to 986.3434455
7e-1 which is equal to 0.7
Irie Pascal supports reals with values between
about 1e308 and about -1e308
-------------------
2.5 Special Symbols
-------------------
Special symbols have special meanings to the compiler.
The syntax for special symbols is given below:
special-symbol =
'+' | '-' | '*' | '/' |
'=' | '<>' | '<' | '<=' | '>' | '>=' |
'(' | ')' |
'[' | ']' | '(.' | '.)' |
':=' | '.' | ',' | ';' | '..' |
'^' | '@'
------------------
2.6 Reserved Words
------------------
Keywords have pre-defined and fixed meanings to the compiler.
The case of keywords is usually not significant so although the
syntax below uses all lowercase letters for keywords the compiler will
by default recognize keywords regardless of the case of the letters.
NOTE: There is a compiler option (-p) that will make identifiers
and keywords case-sensitive.
The syntax for keywords is given below:
keywords := 'and' | 'and_then' | 'array' |
'begin' |
'case' | 'const' |
'div' | 'do' | 'downto' |
'else' | 'end' |
'file' | 'for' | 'function' |
'goto' |
'if' | 'in' |
'label' | 'list'
'mod' |
'nil' | 'not' |
'of' | 'or' | 'or_else' | 'otherwise' |
'packed' | 'procedure' | 'program' |
'record' | 'repeat' |
'set' | 'shl' | 'shr' |
'then' | 'to' | 'type' |
'until' |
'var' |
'while' | 'with' |
'xor'
Attempts to declare an identifier with the same name as a keyword will
be rejected by the compiler.
---------------
2.7 Identifiers
---------------
Identifiers are sequences of letters and digits that start with a letter.
As an extension, Irie Pascal also supports identifiers that contain
and/or start with underscores (_). By default identifiers are not
case-sensitive so
x and X
are normally considered to be the same identifier. NOTE: There is a
compiler option (-p) that will make keywords and identifiers case-sensitive.
Some programmers prefer case-sensitive languages since these consider
identifiers that differ only in case to be different identifiers. This
is often used to allow strongly related identifiers to have the same
"spelling" (i.e. differ only in case).
For example consider the code fragment below.
type
STUDENT = record
name : string;
address : string;
grade : integer;
end;
var
student : STUDENT;
The use of the same "spelling" for the variable "student" and it's
type "STUDENT" emphasize the connection between the two.
You should use this compiler option with caution (or not at all) since
this feature of Irie Pascal is not supported by many (if any) other
Pascal compilers.
The syntax for identifiers is given below:
identifier = letter { letter | digit }
letter = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' |
'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' |
'u' | 'v' | 'w' | 'x' | 'y' | 'z' |
'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' |
'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' |
'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' |
'_'
digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
-----------------
2.7.1 Directives
-----------------
Directives are special identifiers that can be used to give the compiler
extra information about a declaration. The compiler recognizes directives
only at specific points in a declaration, and this recognition is not
affected by and does not affect, any meaning the directive's identifier may
have outside of these specific points. So for example the "forward"
directive is recognized even if the identifier "forward" has been declared
to have some other meaning, and the use of the "forward" directive does
not affect any meaning that "forward" has been declared to have.
NOTE: Irie Pascal currently supports only the "forward" directive
(see "7 Functions and Procedures" for more information).
---------------------------
2.7.2 Built-in Identifiers
---------------------------
Built-in identifiers are automatically declared by the compiler.
Unlike keywords, you can declare identifiers with the same name as
built-in identifiers, if you do then your declaration will override the
declaration made by the compiler. So for example the following declaration
type
boolean = (no, yes);
will override the declaration given by the compiler
type
boolean = (false, true);
Some built-in identifiers are extensions and are therefore only
declared when extensions are enabled.
-------------------------------
2.7.3 User Defined Identifiers
-------------------------------
User defined identifiers are created and bound to program entities using
declarations. You can then reference the entities using the identifiers.
Identifiers can be bound to the following kinds of entities:
Labels, Constants, Types, Variables, Procedures, and Functions.
------------
2.8 Comments
------------
Comments are sequences of characters enclosed in
{ or (*
and
} or *)
Comments are treated like spaces by the compiler and therefore have no
effect on your program except possible to separate identifiers
(e.g. the compiler treats i(* comment *)j like two separate
identifiers i j and not a single identifier ij).
By default comments can not be nested (i.e. by default comments can not
contain other comments). So comments like
(* outer (* inner comment *) comment *)
will be terminated at the first close comment marker, like below
(* outer (* inner comment *)
the last part
comment *)
will not be treated as part of the comment and will cause a syntax
error.
There is a compiler option (-nc) that causes the compiler to support
nested comments. When this compiler option is enabled the compiler
recognizes the end of comments only when the number of close comment
markers matches the number of open comment markers. So the example
comment above will terminate only after the second *).
Both open comment markers (* and { are considered to be equivalent,
and both close comment markers *) and } are considered to be equivalent.
So attempting to trick the compiler into accepting nested comments with
something like
(* outer { inner comment } comment *)
will not work.
Nested comments are disabled by default since in Standard Pascal comments
do not nest.
----------
3 Labels
----------
Labels are markers which you can place in front of statements so that
the statements can be referenced by "goto" statements. Labels can
be digit sequences or as an extension identifiers. Leading zeroes
are not significant in labels which are digit sequences, so "009" and "9"
are the same label.
Labels must be declared (in a label declaration group) before they can be
used.
The syntax for label declaration groups is given below:
label-declaration-group = 'label' label { ',' label } ';'
label = digit-sequence | identifier
-------------
4 Constants
-------------
Constants can be character literals, string literals, integers, reals,
or constant identifiers. Character and string literals, integers, and reals
have already been described in previous sections
(See "2.1 Character Literals", "2.2 String Literals", "2.3 Integers",
and "2.4 Reals").
Constant identifiers are identifiers that have been bound to a constant
using a constant declaration.
Constant declarations must be placed in constant declaration groups.
The syntax for constant declaration groups is given below:
constant-declaration-group =
'const' constant-declaration ';' { constant-declaration ';' }
constant-declaration = identifier '=' constant
constant = integer | real | character-literal | string-literal |
constant-identifier
Here is an example of a constant definition group:
const
Space = ' ';
message = 'Hello';
first = 1;
last = 10;
DaysInYear = 365.25;
minint = -maxint;
-----------
4.1 Boolean
-----------
Irie Pascal supports two built-in enumerated constants "false" and "true"
which are associated with the built-in type "boolean". The ordinal value
of "false" is zero and the ordinal value of "true" is one.
-----------
4.2 MaxChar
-----------
As an extension Irie Pascal supports the built-in character constant
"maxchar" which is equal to the largest character value supported by
Irie Pascal.
----------
4.3 MaxInt
----------
Irie Pascal supports the built-in integer constant "maxint" which is
equal to the largest supported integer value.
-------
4.4 Nil
-------
Irie Pascal supports a built-in constant "nil" associated with all pointer
types, this constant can be assigned to any pointer variable to indicate
that the variable doesn't point anywhere. Any pointer variable can also
be compared with "nil".
--------------
4.5 Permission
--------------
As an extension Irie Pascal supports nine built-in integer constants which
can be used with the built-in procedures "mkdir" and "getfilemode" to
specify or identify read, write, and execute permissions. Three constants
"usr_r", "usr_w", and "usr_x" specify or identify user read, write,
and execute permissions respectively (i.e. permissions associated with the
file or directories owner). Three constants "grp_r", "grp_w", and "grp_x"
specify or identify group read, write, and execute permissions
respectively (i.e. permissions associated with users belonging to the
file or directories owner's group). Three constants "oth_r", "oth_w",
and "oth_x" specify or identify other read, write, and execute permissions
respectively (i.e. permissions associated with users who do not belong
to the file or directory owner's group).
------------
4.6 Platform
------------
As an extension Irie Pascal supports four integer constants "platform_dos",
"platform_os2", "platform_win32", and "platform_linux" which can be
compared with the value returned by the built-in function "platform" to
determine the platform your program is running on.
------------
4.7 FileMode
------------
As an extension Irie Pascal supports three integer constants "readmode",
"writemode", and "appendmode" which can be used with the built-in "open"
procedure to specify the mode the file should be opened in.
See also "7.2.26 open".
-----------
4.8 dir_bit
-----------
As an extension Irie Pascal supports the integer constant "dir_bit",
which can be AND'd with "mode" returned by "getfilemode" to determine
if a file is a directory.
---------
5 Types
---------
Types specify sets of valid values, and every constant, variable and
function return value is associated with a specific type. Most types must
be defined before they can be used, the exceptions to this rule are pointer
types. Pointer types are allowed to be used before they are defined to
allow self-referencing structures (such as linked lists) to be built.
Irie Pascal supports the following types:
enumerated types, subrange types, pointer types, array types,
string types, record types, set types, file types, list types,
type-identifiers
Type identifiers are identifiers that have been bound to a type
using a type declaration.
Type declarations must be placed in type declaration groups.
The syntax for type declaration groups is given below:
type-declaration-group =
'type' identifier '=' type-declaration ';' { type-declaration ';' }
type-declaration = identifier '=' type-denoter
type-denoter = type-identifier | new-type
type-identifier = identifier
new-type = new-ordinal-type | new-structured-type | new-pointer-type
new-ordinal-type = enumerated-type | subrange-type
new-structured-type = [ 'packed' ] array-type |
[ 'packed' ] record-type |
[ 'packed' ] set-type |
[ 'packed' ] file-type |
[ 'packed' ] list-type |
string-type
new-pointer-type = '^' domain-type |
'@' domain-type
domain-type = type-identifier
Here is an example of a type declaration group:
type
symbols = record
name : string;
value : integer;
end;
SymbolTable = list of symbols;
color = (red, green, blue);
cardinal = 0..maxint;
IntegerList = array[1..100] of integer;
characters = set of char;
--------------------
5.1 Enumerated Types
--------------------
Enumerated types specify a finite set of ordered values. Each of these
ordered values is associated with an identifier (a enumerated constant)
and has integer type.
The syntax for enumerated types is given below:
enumerated-type = '(' identifier-list ')'
identifier-list = identifier { ',' identifier }
Here are some examples of enumerated types
(red, blue, green)
(low, medium, high)
(married, divorced, widowed, single)
------------------
5.2 Subrange Types
------------------
Subrange types specify a contiguous subset of an ordinal type. This
ordinal type is known as the host type and the values of a subrange
type have the same type as it's host type.
The syntax for subrange types is give below:
subrange-type = constant '..' constant
Here are some examples of subrange types:
-100..+100
true..true
'a'..'z'
-----------------
5.3 Pointer Types
-----------------
Pointer types specify the special value "nil" and a set of values
identifying variables associated with them. The built-in procedure
"new" creates a pointer variable and associates it with the variables type.
The built-in procedure "dispose" destroys a pointer variable and
disassociates it from the variables type.
The syntax for pointer types is given below:
pointer-type = '^' domain-type |
'@' domain-type
domain-type = type-identifier
Here are some examples of pointer types:
^integer
^real
---------------
5.4 Array Types
---------------
Array types specify collections of values of the same type (called
the array's component type) and associates an index type with the
collections. Each member of an array's collection is called an array
element and is identified by a value of the array's index type.
An array's component type may itself be an array, and the component
type of the component type may also be an array. It is sometimes
easier to think about an array of arrays as a multi-dimensional
array (i.e. an array specifying a collection with an axis for each
array component, where each element is identified by values from
each component arrays index type).
Packed arrays of char having a lower bound of one and an upper bound
of two or greater are fixed length strings and have special properties.
Normally values of array types can be tested for equality and inequality
but can not be tested to see whether one is less than the other. Fixed
length strings can be tested not only for equality and inequality but
also can be tested to see whether one is less than the other. Fixed
length strings unlike other arrays can also be read from and written to
text files as a unit using the built-in procedures "read",
"readln", "write", and "writeln".
The syntax for array types is given below
array-type = 'array' '[' index-type-list ']' 'of' component-type
index-type-list = index-type { ',' index-type }
index-type = ordinal-type
ordinal-type = enumerated-type |
subrange-type |
ordinal-type-identifier
component-type = type-denoter
Here are some examples of array types:
array[1..10] of real
array[char] of boolean
array[-456..-450] of integer
NOTE:
As a shorthand notation a multi-dimensional array type can be created
by listing the index types of each of the component arrays.
In other words
array[1..10, char, boolean] of integer
is a shorthand notation for
array[1..10] of array[char] of array[boolean] of integer
----------------
5.5 String Types
----------------
As an extension Irie Pascal supports variable length strings using the
built-in type "string". Variable length strings specify collections of
characters whose length does not exceed a maximum value.
The syntax for string types is given below:
string-type = 'string' |
'string' '[' size ']' |
'string' '(' size ')'
size = integer
where
size is an integer constant, between 1 and 1048576, which specifies the
maximum length of the string. If size is not specified the maximum
length used is 255.
For example to create a variable length string type called "name" with
a maximum length of 80 use
name = string[80];
or
name = string(80);
To create a variable length string type called 'address' with a maximum
length of 255 use
address = string;
or
address = string[255];
or
address = string(255);
----------------
5.6 Record Types
----------------
Record types specify collections of values. A record type may be empty
(i.e. specify a collection with no values). Each member of a record
type's collection is called a field and is identified by a field
identifier, with the possible exception of the variant selector which
sometimes does not have a field identifier. Each member in a record's
collection has a particular type (which can be a record type).
Sometimes groups of fields in a record type are mutually exclusive.
You can use a variant part in a record type to specify mutually
exclusive groups of fields (these mutually exclusive groups are
called variants). Each variant part contains a variant selector,
the value of the variant selector determines which variant if any
is active.
The syntax for record types is given below:
record-type = 'record' field-list 'end'
field-list = fixed-part ';' variant-part [ ';' ] |
fixed-part [ ';' ] |
variant-part [ ';' ] |
empty
fixed-part = record-section { ';' record-section }
record-section = id-list ':' type-denoter
id-list = identifier { ',' identifier }
variant-part = 'case' variant-selector 'of' variant-body
variant-selector = [ identifier ':' ] ordinal-type-identifier
variant-body = variant-list [ [;] variant-part-completer ] |
variant-part-completer
variant-list = variant { ';' variant }
variant = case-constant-list ':' '(' field-list ')'
case-constant-list = case-specifier { ',' case-specifier }
case-specifier = case-constant [ '..' case-constant ]
case-constant = ordinal-constant
variant-part-completer = 'otherwise' '(' field-list ')'
Here are some examples of valid record types:
record end
record ; end
The record types above are empty.
record
name : string;
grade : integer;
end
The record type above has two fields which are identified by
"name" of type "string" and "grade" of type "integer".
Given the type below
type
clothes = (shoe, pants, shirt);
the following record type is valid
record
price : real;
case kind : clothes of
shoe : ( size : integer; );
pants : ( waist, length : integer );
shirt : ( neck : integer; sleeve : integer )
end
and contain seven fields
"price", "kind", "size", "waist", "length", "neck", and "sleeve".
The fields "price" and "kind" are always present and the value of the
field "kind" determine which of the variants if any is present. The
variants are ("size") and ("waist" and "length") and ("neck" and "sleeve").
-------------
5.7 Set Types
-------------
Set types specify combination of values of the same ordinal type
(called the set's base type). The same value can not appear more
than once. A set can be empty (i.e. have no values).
The syntax for set types is given below:
set-type = 'set' 'of' ordinal-type
Here are some examples of set types
set of char
set of boolean
--------------
5.8 File Types
--------------
File types specify collections of values that are persistent (i.e. they
remain stored when your program is not running) and have the same type
(called the file's component type). File component types can not be file
types or types which contain file types.
The syntax for file types is given below:
file-type = 'file' 'of' component-type
--------------
5.9 List Types
--------------
As an extension Irie Pascal supports list types. List types are ordered
collections values of a single type (called the list's component type).
Each member of a list's collection is identified by it's position in
the list.
The syntax for list types is given below:
list-type = 'list' 'of' component-type
---------------------
5.10 Type Identifiers
---------------------
A type identifier is an identifier that is bound to a type with a type
definition.
The following built-in type identifiers are supported by Irie Pascal:
boolean, char, integer, real, filename, text, dir
--------------
5.10.1 boolean
--------------
"boolean" is a built-in enumerated type with two values "false" and "true".
The ordinal value of "false" is zero and the ordinal value of "true" is
one. The conditional statement "if" and the looping statements "while"
and "repeat/until" use boolean expressions. The operators "and", "or",
"not", "and_then", "or_else" operate on boolean expressions.
-----------
5.10.2 char
-----------
"char" is a built-in ordinal type with values of the current character
set.
----------
5.10.3 dir
----------
As an extension Irie Pascal supports the built-in type "dir" whose
values are directory handles
(See also "7.2.27 opendir", "7.2.35 readdir", "7.2.39 rewinddir",
and "7.2.6 closedir").
---------------
5.10.4 filename
---------------
As an extension Irie Pascal supports the built-in string type "filename"
which is the recommended type for variables used to store file and
directory names.
--------------
5.10.5 integer
--------------
"integer" is a built-in ordinal type whose values are whole numbers
(see also "2.3 Integers").
-----------
5.10.6 real
-----------
"real" is a built-in type whose values are numbers with fractional parts
(see also "2.4 Reals").
-----------
5.10.7 text
-----------
"text" is a built-in file type whose values are sequences of lines.
A line is a sequence of characters and every lines in a "text" file
is terminated by an end-of-line character except possibly the last line.
-------------
6 Variables
-------------
Variables are typed storage locations, and store values of their types.
Variables must be declared before they are used. Variable identifiers are
identifiers that have been bound to a variable using a variable
declaration. Variable declarations must occur in variable declaration
groups.
The syntax for variable declaration groups is given below:
variable-declaration-group =
'var' variable-declaration { ';' variable-declaration }
variable-declaration = identifier-list ':' type-denoter
identifier-list = identifier { ',' identifier }
---------------------
6.1 Pointer Variables
---------------------
Pointer variables store either the special value "nil" or a reference to
another variable. The built-in procedure "new" is used to create variables
referenced by pointer variables. The built-in procedure "dispose" is used
to destroy variables referenced by pointer variables.
-------------------
6.2 Array Variables
-------------------
Array elements can be accessed using the notation
ArrayName[Index]
where "ArrayName" is the name of the array variable and "Index" is an
expression whose value is one of the values specified by the array's
index type (see also "5.4 Array Types"). You can use either this notation
ArrayName[Index1][Index2]...[IndexN]
or this notation
ArrayName[Index1, Index2,...IndexN]
to access array elements in multi-dimensional array variables.
--------------------
6.3 String Variables
--------------------
The individual characters in a string variable can be accessed using
array notation. For example if "name" is a string variable then
name[2]
accesses the second character in the string stored in "name".
You can use the following built-in procedures and functions to
manipulate variables of string types:
concat, copy, length, lowercase, pos, reverse, trim, uppercase,
delete, insert, str, val
You can use the "+" operator to perform string concatenation.
For example here is a hello world program using string concatenation.
program good(output);
begin
writeln('hello' + ' ' + 'world' + '!')
end.
--------------------
6.4 Record Variables
--------------------
Record variable fields can be accessed using the following notation
RecordName.FieldName
where "RecordName" is the name of the record variable
and "FieldName" is the name of the field.
------------------
6.5 List Variables
------------------
You can use the following built-in procedures and functions with
variables of list types:
new, dispose, insert, delete, length
You can access the components of a list variable just like an array
variable. The syntax is
list-variable '[' integer-expression ']'
where
integer-expression is an expression of integer type that specifies
the position in the list of the component being accessed.
For example if "i" is an integer and "lv" is a list variable the
statement below will write each component of "lv".
for i := 1 to length(lv) do
writeln(lv[i])
----------------------------
7 Functions And Procedures
----------------------------
Pascal encourages modular programming (i.e. creating a complex
program from smaller and simpler modules). Ideally these modules
should resemble so called "black boxes" where the implementation
details about how a module performs its work is kept hidden inside
the module, the user of a module only needs to know "what" the
module does and not "how".
Pascal supports two kinds of modules, "functions" and "procedures".
The difference between functions and procedures is that functions
return a value to their callers and are used in expressions, while
procedures do not return a value to their callers and are used in
procedure statements. Since functions and procedures are so similar
the generic term subroutine will be used to refer to both.
The recommended way of passing information into and out of subroutines
is by use of parameters. Subroutines may have a list of formal parameters,
these formal parameters are used by the subroutine to access information
passed into it. When the subroutine is called the caller must supply
an actual parameter for each formal parameter in the subroutine. The
actual parameter is the information being passed into or out of the
subroutine.
Irie Pascal supports four kinds of parameters (value parameters,
variable parameters, function parameters, and procedure parameters).
Value parameters are passed by value (i.e. when the subroutine is called
the actual parameter is an expression, and the value of the expression
passed into the formal parameter). The subroutine can use the formal
parameter to access the value passed to it but any changes it makes
to the formal parameter will not affect the actual parameter.
Variable parameters are passed by reference (i.e. when the subroutine
is called the actual parameter is a variable, and a reference to this
variable is passed into the formal parameter). The subroutine can
use the formal parameter to access the variable (via the reference)
and any changes it makes to the formal parameter will immediately
affect the actual parameter.
Function parameters are references to functions (i.e. when the
subroutine is called the actual parameter is a function, and a
reference to this function is passed into the formal parameter).
The subroutine can use the formal parameter to call the function.
Procedure parameters are references to procedures (i.e. when the
subroutine is called the actual parameter is a procedure, and a
reference to this procedure is passed into the formal parameter).
The subroutine can use the formal parameter to call the procedure.
For example here is an example of a simple program with a procedure.
program simple(output);
procedure say (message : string);
begin
writeln(message)
end;
begin
say('Hello world')
end.
The program contains a procedure called "say" which takes a single
value parameter. When the procedure is called "say('Hello world')"
the actual parameter is the expression 'Hello world' which is passed
into the formal parameter "message". So "message" now has the value
'Hello world'. When writeln is used the value of "message"
(i.e. 'Hello world')
is written to the standard output stream.
Irie Pascal supports recursive function and procedure calls (i.e.
Irie Pascal allows functions and procedures to call themselves
either directly or indirectly). For example a procedure A
can call itself or it can call another procedure say B which in turn
calls procedure A.
Functions and procedures must be declared before they can be called.
This creates a problem when you have functions or procedures that
call each other. For example suppose you have the program below.
program test(output);
procedure a(x : integer);
begin
writeln(x);
b(x+1)
end;
procedure b(x : integer);
begin
writeln(x);
a(x+1)
end;
begin
a(1);
end.
If you try to compile this program the compiler will complain about
the call to "procedure b" that occurs in "procedure a" because this call
occurs before "procedure b" is declared.
You can try to correct this problem by moving the declaration of
"procedure b" before the declaration of "procedure a" like so
program test(output);
procedure b(x : integer);
begin
writeln(x);
a(x+1)
end;
procedure a(x : integer);
begin
writeln(x);
b(x+1)
end;
begin
a(1);
end.
but then the compiler will complain about the call to "procedure a"
that occurs in "procedure b", because this call now occurs before
"procedure a" is declared.
The "forward" directive can be used to solve this kind of problem as
illustrated by the program below:
program test(output);
procedure b(x : integer); forward;
procedure a(x : integer);
begin
writeln(x);
b(x+1)
end;
procedure b;
begin
writeln(x);
a(x+1)
end;
begin
a(1);
end.
You will notice that there are two declarations for procedure b.
The first declaration is called a forward declaration and includes
the name of the procedure and the formal parameter list
("x:integer" in this case) and the directive "forward", but does not
include the procedure block.
The second declaration includes the name of the procedure and the
procedure block but does not include the formal parameter list.
The syntax for function and procedure declarations is given below:
function-declaration =
function-heading ';' directive |
function-identification ';' function-block |
function-heading ';' function-block
procedure-declaration =
procedure-heading ';' directive |
procedure-identification ';' procedure-block |
procedure-heading ';' procedure-block
procedure-heading = 'procedure' identifier [ formal-parameter-list ]
procedure-identification = 'procedure' procedure-identifier
procedure-identifier = identifier
procedure-block = block
function-heading =
'function' identifier [ formal-parameter-list ] ':' result-type
function-identification = 'function' function-identifier
function-identifier = identifier
procedure-block = block
function-block = block
formal-parameter-list =
'(' formal-parameter-section { ';' formal-parameter-section } ')'
formal-parameter-section = value-parameter-specification |
variable-parameter-specification |
procedure-parameter-specification |
function-parameter-specification
value-parameter-specification = identifier-list ':' type-identifier
variable-parameter-specification =
'var' identifier-list ':' type-identifier
procedure-parameter-specification = procedure-heading
function-parameter-specification = function-heading
directive = 'forward'
result-type = type-identifier
----------------------
7.1 Built-in Functions
----------------------
Irie Pascal supports the following built-in functions.
---------
7.1.1 abs
---------
Purpose: Returns the absolute value of its input.
Syntax:
abs-call = 'abs' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: Yes
Example:
abs(-10) is equal to 10
Notes:
The type of the value returned by this function is always the
same as the type of its input.
------------
7.1.2 arctan
------------
Purpose: Returns the arctangent of its input
Syntax:
arctan-call = 'arctan' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always real.
---------
7.1.3 chr
---------
Purpose: Returns the character whose ordinal value is equal to its input.
Syntax:
chr-call = 'chr' '(' num ')'
num = integer-expression
Standard Pascal: Yes
Notes:
------------
7.1.4 concat
------------
Purpose: Returns a string formed by concatenating its input.
Syntax:
concat-call = 'concat' '(' s { ',' s } ')'
s = character-expression | string-expression
Standard Pascal: No
Notes:
For example you could do something like
message := concat('Hello', ' ', 'world', '!');
to make message equal to 'Hello world!'
You can also concatenate strings and characters using the "+"
operator like
message := 'Hello' + ' ' + 'world' + '!';
----------
7.1.5 copy
----------
Purpose: Returns a string formed by copying from an input string starting
from a specified position.
Syntax:
copy-call = 'copy' '(' s ',' p [ ',' n ')'
s = character-expression | string-expression
p = integer-expression
n = integer-expression
Standard Pascal: No
Notes:
"s" is the source of characters
"p" specifies the position from which to start copying characters
"n" specifies the number of characters to copy. If "n" is omitted or is
greater than the number of characters in "s" from "p" to the end,
then all characters in "s" starting from "p" to the end are copied.
For example
copy('Testing...', 5, 2) is equal to 'in'
and
copy('Testing...', 7) is equal to 'g...'
and
copy('Testing...', 1, 1000) is equal to 'Testing...'
---------
7.1.6 cos
---------
Purpose: Returns the cosine of its input (expressed in radians).
Syntax:
cos-call = 'cos' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always real.
----------
7.1.7 cosh
----------
Purpose: Returns the hyperbolic cosine of its input.
Syntax:
cosh-call = 'cosh' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: No
Notes:
The type of the value returned by this function is always real.
---------
7.1.8 eof
---------
Purpose: Returns "true" or "false" depending on whether its input
(which is a file variable) is at end-of-file.
Syntax:
eof-call = 'eof' [ '(' f ')' ]
f = file-variable
If "f" is omitted then the built-in file variable "input" shall be used as
input to this function.
Standard Pascal: Yes
Notes:
----------
7.1.9 eoln
----------
Purpose: Returns "true" or "false" depending on whether its input
(which is a file variable) is at end-of-line.
Syntax:
eoln-call = 'eoln' [ '(' t ')' ]
t = text-file-variable
If "t" is omitted then the built-in text file variable "input" shall be
used as input to this function.
Standard Pascal: Yes
Notes:
----------
7.1.10 exp
----------
Purpose: Returns the value of "e" raised to the power of its input.
Syntax:
exp-call = 'exp' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always real.
--------------
7.1.11 fexpand
--------------
Purpose: Returns the full pathname of its input (which is a filename).
Syntax:
fexpand-call = 'fexpand' '(' s ')'
s = character-expression | string-expression
Standard Pascal: No
Notes:
--------------
7.1.12 filepos
--------------
Purpose: Returns the value of the file position indicator of a file.
Syntax:
filepos-call = 'filepos' '(' f ')'
f = file-variable
Standard Pascal: No
Notes:
This function returns an integer value.
The file variable "f" must be open.
For a text file variable the value of the file position indicator may
not be equal to the number of characters read/written so far.
For a binary file the value of the file position indicator is equal to
the number of characters read/written so far.
---------------
7.1.13 filesize
---------------
Purpose: Returns the size of a file.
Syntax:
filesize-call = 'filesize' '(' f ')'
f = file-variable
Standard Pascal: No
Notes:
This function returns an integer value.
The file variable "f" must be open.
-----------
7.1.14 frac
-----------
Purpose: Returns the fractional part of a real expression.
Syntax:
frac-call = 'frac' '(' r ')'
r = real-expression
Standard Pascal: No
Notes:
For example frac(7.234) is equal to 0.234
The type of the value returned by this function is always real.
-------------
7.1.15 getenv
-------------
Purpose: Returns the environment variable specified by its input.
Syntax:
genenv-call = 'getenv' '(' s ')'
s = character-expression | string-expression
Standard Pascal: No
Notes:
If a string matching "s" can not be found in the environment list then an
empty string is returned.
----------
7.1.16 hex
----------
Purpose: Returns the hexadecimal representation of its input as a string.
Syntax:
hex-call = 'hex' '(' i ')'
i = integer-expression
Standard Pascal: No
Notes:
For example hex(16) is equal to '10'.
----------
7.1.17 int
----------
Purpose: Returns the integer part of a real expression.
Syntax:
int-call = 'int' '(' r ')'
r = real-expression
Standard Pascal: No
Notes:
For example int(7.234) is equal to 7.0
The type of the value returned by this function is always real.
---------------
7.1.18 ioresult
---------------
Purpose: Returns the error code of the last input/output operation.
Syntax:
ioresult-call = 'ioresult'
Standard Pascal: No
Notes:
By default (when I/O checking is enabled) your program automatically
checks for errors after each I/O operation and terminates with an error
message if any errors are detected. If you do not want this default
behavior you can disable I/O checking (either globally using the "i"
compiler option or locally using the "i" compiler directive) and call
this function to determine if any I/O errors occurred.
(See "Appendix F" of the "Irie Pascal Users Manual" for a list of the error
codes returned by this function.
This function resets the error code to zero after it is called, so if you
call this function twice after an I/O operation then the second call
will always return 0. If you need to refer to the error code more than once
you can save the error code into a variable.
For example:
errcode := IOResult;
if errcode <> 0 then
case errcode of
1: writeln('Error erasing file');
2: writeln('Error renaming file');
3: writeln('File is undefined')
end
--------------
7.1.19 isalpha
--------------
Purpose: Returns "true" or "false" depending on whether its input
is a alphabetic character.
Syntax:
isalpha-call = 'isalpha' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
-----------------
7.1.20 isalphanum
-----------------
Purpose: Returns "true" or "false" depending on whether its input
is a alphanumeric character.
Syntax:
isalphanum-call = 'isalphanum' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
--------------
7.1.21 isdigit
--------------
Purpose: Returns "true" or "false" depending on whether its input
is a digit character.
Syntax:
isdigit-call = 'isdigit' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
--------------
7.1.22 islower
--------------
Purpose: Returns "true" or "false" depending on whether its input
is a lower case letter.
Syntax:
islower-call = 'islower' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
--------------
7.1.23 isprint
--------------
Purpose: Returns "true" or "false" depending on whether its input
is a printable character.
Syntax:
isprint-call = 'isprint' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
--------------
7.1.24 isspace
--------------
Purpose: Returns "true" or "false" depending on whether its input
is a white space character.
Syntax:
isspace-call = 'isspace' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
--------------
7.1.25 isupper
--------------
Purpose: Returns "true" or "false" depending on whether its input
is an upper case letter.
Syntax:
isupper-call = 'isupper' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
---------------
7.1.26 isxdigit
---------------
Purpose: Returns "true" or "false" depending on whether its input
is a hexadecimal digit character.
Syntax:
isxdigit-call = 'isxdigit' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
-------------
7.1.27 length
-------------
Purpose: Returns the length of its input.
Syntax:
length-call = 'length' '(' v ')'
v = list-variable | string-variable
Standard Pascal: No
Notes:
---------
7.1.28 ln
---------
Purpose: Returns the natural logarithm of its input.
Syntax:
ln-call = 'ln' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always real.
----------
7.1.29 log
----------
Purpose: Returns the logarithm to the base 10 of its input.
Syntax:
log-call = 'log' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always real.
-------------
7.1.30 locase
-------------
Purpose: Returns the lowercase letter corresponding to its input.
If there is no lowercase letter corresponding to its input
then its input is returned.
Syntax:
locase-call = 'locase' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
----------------
7.1.31 lowercase
----------------
Purpose: Returns a string formed by converting all lower case characters
in its input to upper case characters and leaving all other
characters unchanged.
Syntax:
lowercase-call = 'lowercase' '(' s ')'
s = string-expression
Standard Pascal: No
Notes:
----------
7.1.32 odd
----------
Purpose: Returns "true" or "false" depending on whether its input
is an odd number.
Syntax:
odd-call = 'odd' '(' i ')'
i = integer-expression
Standard Pascal: Yes
Notes:
----------
7.1.33 ord
----------
Purpose: Returns the ordinal value of its input.
Syntax:
ord-call = 'ord' '(' o ')'
o = ordinal-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always integer.
-----------------
7.1.34 paramcount
-----------------
Purpose: Returns the number of arguments passed to the program.
Syntax:
paramcount-call = 'paramcount'
Standard Pascal: No
Notes:
For example the following is the sample program "args.pas".
program args(output);
begin
writeln('Number of program arguments =', paramcount)
end.
If you compile it and run it as follows
ipc args
ivm args this is a test
then the output would be
Number of program arguments = 4
---------------
7.1.35 paramstr
---------------
Purpose: Returns the ith program argument string where i is its input.
Syntax:
paramstr-cal = 'paramstr' '(' i ')'
i = integer-expression
Standard Pascal: No
Notes:
If there is no ith program argument an empty string is returned.
---------
7.1.36 pi
---------
Purpose: Returns the value of the mathematical constant pi.
Syntax:
pi-call = 'pi'
Standard Pascal: No
Notes:
---------------
7.1.37 platform
---------------
Purpose: Returns an integer indicating the platform the program is
running on.
Syntax:
platform-call = 'platform'
Standard Pascal: No
Notes:
As an extension Irie Pascal supports four integer constants "platform_dos",
"platform_os2", "platform_win32", and "platform_linux" which can be
compared with the value returned by this function.
----------
7.1.38 pos
----------
Purpose: Searches for one string in another.
Syntax:
pos-call = 'pos' '(' needle ',' haystack [ ',' start ')'
needle = character-expression | string-expression
haystack = character-expression | string-expression
start = integer-expression
Standard Pascal: No
Notes:
This functions searches "haystack" starting at position "start"
for "needle" and returns 0 if "needle" is not found or returns the
position of "needle" in "haystack". If "start" is omitted then the search
begins at position 1. If "start" is greater than the length of "haystack"
then 0 is returned.
For example
pos('o', 'Hello world') is equal to 5
pos('o', 'Hello world', 1) is equal to 5
pos('o', 'Hello world', 6) is equal to 8
pos('o', 'Hello world', 256) is equal to 0
-----------
7.1.39 pred
-----------
Purpose: Returns an ordinal value that is one less than its input.
Syntax:
pred-call = 'pred' '(' o ')'
o = ordinal-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always the same
as the type of its input.
-------------
7.1.40 random
-------------
Purpose: Returns a pseudo-random number.
Syntax:
random-call = 'random' [ '(' i ')' ]
i = integer-expression
Standard Pascal: No
Notes:
If "i" is not specified then "random" returns a real value between
0 and 1.
If "i" is specified then "random" returns an integer value
between 1 and "i"-1.
See also "7.2.31 randomize".
--------------
7.1.41 reverse
--------------
Purpose: Returns a string created by reversing the characters in its input.
Syntax:
reverse-call = 'reverse' '(' s ')'
s = character-expression | string-expression
Standard Pascal: No
Notes:
For example
reverse('Hello') is equal to 'olleH'
------------
7.1.42 round
------------
Purpose: Returns the integer value closes to its input.
Syntax:
round-call = 'round' '(' r ')'
r = real-expression
Standard Pascal: Yes
Notes:
For example round(7.234) is equal to 7.
The type of the value returned by this function is always integer.
----------
7.1.43 sin
----------
Purpose: Returns the sine of its input (expressed in radians).
Syntax:
sin-call = 'sin' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always real.
-----------
7.1.44 sinh
-----------
Purpose: Returns the hyperbolic sine of its input.
Syntax:
sinh-call = 'sinh' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: No
Notes:
The type of the value returned by this function is always real.
----------
7.1.45 sqr
----------
Purpose: Returns the square of its input
Syntax:
sqr-call = 'sqr' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always the same as
the type of its input.
-----------
7.1.46 sqrt
-----------
Purpose: Returns the square-root of its input
Syntax:
sqrt-call = 'sqrt' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always real.
-----------
7.1.47 succ
-----------
Purpose: Returns an ordinal value that is one more than its input.
Syntax:
succ-call = 'succ' '(' o ')'
o = ordinal-expression
Standard Pascal: Yes
Notes:
The type of the value returned by this function is always the same
as the type of its input.
-----------
7.1.48 swap
-----------
Purpose: Returns an integer value calculated by reversing the byte
ordering of its input.
Syntax:
swap-call = 'swap' '(' i ')'
i = integer-expression
Standard Pascal: No
Notes:
For example assuming 32 bit little endian integers then 256 is stored in
four bytes as follows:
0 0 1 0
So swap(256) results in the following integer:
0 1 0 0
which is equal to 65536
-------------
7.1.49 system
-------------
Purpose: Passes its input to the command processor, which will attempt to
execute it as a command.
Syntax:
system-call = 'system' '(' s ')'
s = string-expression
Standard Pascal: No
Notes:
If there is an error then "system" returns a non-zero value indicating
the kind of error.
If there is no error then "system" returns zero.
See also "7.2.11 Exec".
For example the sample program "batch.pas" below is a very primitive
batch processor. It sends each line in the input file to the command
processor to be executed.
program batch(f, output);
var
f : text;
s : string;
err : integer;
begin
reset(f); (* open input file or standard input file *)
while not eof(f) do
begin
readln(f, s);
writeln('Executing ', s);
err := system(s); (* Pass 's' to the command processor *)
writeln('Error code is ', err)
end
end.
----------
7.1.50 tan
----------
Purpose: Returns the tangent of its input (expressed in radians).
Syntax:
tan-call = 'tan' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: No
Notes:
The type of the value returned by this function is always real.
-----------
7.1.51 tanh
-----------
Purpose: Returns the hyperbolic tangent of its input.
Syntax:
tanh-call = 'tanh' '(' num ')'
num = integer-expression | real-expression
Standard Pascal: No
Notes:
The type of the value returned by this function is always real.
-----------
7.1.52 trim
-----------
Purpose: Returns a string created by removing all leading and trailing
spaces from its input.
Syntax:
trim-call = 'trim' '(' s ')'
s = string-expression
Standard Pascal: No
Notes:
For example
trim(' hello ') is equal to 'hello'
------------
7.1.53 trunc
------------
Purpose: Returns an integer value formed by removing the fractional
part of its input.
Syntax:
trunc-call = 'trunc' '(' r ')'
r = real-expression
Standard Pascal: Yes
Notes:
For example trunc(7.234) is equal to 7.
The type of the value returned by this function is always integer.
-------------
7.1.54 upcase
-------------
Purpose: Returns the uppercase letter corresponding to its input.
If there is no uppercase letter corresponding to its input
then its input is returned.
Syntax:
upcase-call = 'upcase' '(' c ')'
c = character-expression
Standard Pascal: No
Notes:
----------------
7.1.55 uppercase
----------------
Purpose: Returns a string formed by converting all upper case characters
in its input to lower case characters and leaving all other
characters unchanged.
Syntax:
uppercase-call = 'uppercase' '(' s ')'
s = string-expression
Standard Pascal: No
Notes:
-----------------------
7.2 Built-in Procedures
-----------------------
Irie Pascal supports the following built-in procedures.
------------
7.2.1 append
------------
Purpose: Opens a file for writing at the end of the file, and associates
a file variable with the opened file.
Syntax:
append-call = 'append' '(' f [',' s ] ')'
f = file-variable
s = filename
Standard Pascal: No
Notes:
If the file does not exist it is created. If the file exists its contents
are preserved. In either case all writes occur at the end of the file.
If a filename ("s") is specified then the filename is assigned to the
file variable before the file is opened (the file must be closed).
After the file is opened all writes will occur at the end of the file
regardless of calls to the built-in seek procedure (See "7.2.40 rewrite",
"7.2.3 assign", "7.2.38 reset", and "7.2.42 seek").
------------
7.2.2 assert
------------
Purpose: This procedure is based on the C language macro of the same name.
The assert procedure can be enabled/disabled using the -A compiler
option. When enabled this procedure evaluates its input, which is
a boolean expression and aborts the program if the expression
evaluates to false. If the expression evaluates to true nothing
happens.
The idea behind this procedure is that you use it during debugging
to verify that the variables in your program have the values you
expect, and after your program is debugged you don't have to
search your program and remove the calls to this procedure, instead
you just disable this procedure using a compiler option.
A common mistake in using this procedure is to test normal error
conditions (such as out of memory or invalid user input).
Syntax:
assert-call = 'assert' '(' b ')'
b = boolean-expression
Standard Pascal: No
Notes:
------------
7.2.3 assign
------------
Purpose: Assigns a name to a file variable.
Syntax:
assign-call = 'assign' '(' f ',' name ')'
f = file-variable
name = character-expression | string-expression
Standard Pascal: No
Notes:
The file variable "f" must be closed.
For example to open a file named 'README.TXT' for reading use
assign(f, 'README.TXT');
reset(f);
You can't use this function to rename a file, use the "rename" procedure
if you want to do that.
-----------
7.2.4 chdir
-----------
Purpose: Changes the current directory.
Syntax:
chdir-call = 'chdir' '(' name ')'
name = character-expression | string-expression
Standard Pascal: No
Notes:
"name" specifies the name of the directory that is to be the new
current directory.
-----------
7.2.5 close
-----------
Purpose: Flushes and then closes a file.
Syntax:
close-call = 'close' '(' f ')'
f = file-variable
Standard Pascal: No
Notes:
--------------
7.2.6 closedir
--------------
Purpose: Closes a directory.
Syntax:
closedir-call = 'closedir' '(' d ')'
d = directory-variable
Standard Pascal: No
Notes:
Irie Pascal allows you to open, read, rewind, and close directories
(See also "7.2.27 opendir", "7.2.35 readdir", "7.2.39 rewinddir").
---------
7.2.7 dec
---------
Purpose: Decrements an ordinal variable by a specified amount or by one.
Syntax:
dec-call = 'dec' '(' o [',' i ] ')'
o = ordinal-variable
i = integer-expression
Standard Pascal: No
Notes:
If "i" is omitted then "o" is decremented by one.
Using this function is slightly more efficient than using
o := o - i;
------------
7.2.8 delete
------------
Purpose: Deletes components from a list or a string.
Syntax:
delete-call = delete-list | delete-string
delete-list = 'delete' '(' l ',' start [',' count ] ')'
delete-string = 'delete' '(' s ',' start [ ',' count ] ')'
l = list-variable
start = integer-expression
count = integer-expression
s = string-variable
Standard Pascal: No
Notes:
"start" specifies the position in the list or string to start deleting from.
"count" specifies the number of components to delete. If "count" is omitted
then all components from "start" to the end are deleted.
-------------
7.2.9 dispose
-------------
Purpose: Releases memory allocated using "new".
Syntax:
dispose-call = dispose-pointer | dispose-list
dispose-pointer = 'dispose' '(' p ')'
dispose-list = 'dispose' '(' l ')'
p = pointer-variable
l = list-variable
Standard Pascal: Yes
Notes:
After the call to dispose the pointer variable or list variable is
undefined.
------------
7.2.10 erase
------------
Purpose: Deletes a file.
Syntax:
erase-call = 'erase' '(' f ')'
f = file-variable
Standard Pascal: No
Notes:
The file must be closed and have a name associated with it.
-----------
7.2.11 exec
-----------
Purpose: Executes a program.
Syntax:
exec-call = 'exec' '(' p ',' 'a' ')'
p = character-expression | string-expression
a = character-expression | string-expression
Standard Pascal: No
Notes:
"p" specifies the program to execute.
"a" specifies the arguments (if any) to be passed to the program
(see also "7.1.49 system", "7.1.34 paramcount" and "7.1.35 paramstr").
The code returned by the program if any is stored in the built-in
variable "exitcode".
-----------
7.2.12 exit
-----------
Purpose: Terminates the function/procedure/program in which it is used,
and optionally returns a value.
Syntax:
exit-call = 'exit' [ '(' e ')' ]
e = expression
Standard Pascal: No
Notes:
"i" if specifies is the value to be returned by the function or program
If used in a function then "exit" terminates the function.
If used in a function named "f" then "exit(e)" is equivalent to
f := e;
exit
If used in a procedure then "exit" terminates the procedure.
If used in a procedure then "exit(x)" is an error since you can
not return a value from a procedure.
If used not in a function or procedure but in the main program
then "exit" terminates the program.
If used not in a function or procedure but in the main program
then "exit(e)" is equivalent to:
ExitCode := e;
exit
(i.e. the program is terminated with "e" as the exit code).
See also "7.2.21 halt".
------------
7.2.13 flush
------------
Purpose: Flushes the a file's buffers (i.e. all data waiting to be written
to the file is written).
Syntax:
flush-call = 'flush' '(' f ')'
f = file-variable
Standard Pascal: No
Notes:
The file associated with "f" must be open.
-------------
7.2.14 fsplit
-------------
Purpose: Splits a filename into its component parts.
Syntax:
fsplit-call = fsplit '(' s ',' [ d ] ',' [ n ] ',' [ e ] ')'
s = character-expression | string-expression
d = string-variable
n = string-variable
e = string-variable
Standard Pascal: No
Notes:
"s" specifies the filename to be split.
"d" specifies a variable to store the directory part of the filename.
"n" specifies a variable to store the name part of the filename (minus
the extension.
"e" specifies a variable to store the extension part of the filename.
Although "d", "n", and "e" are optional at least one must be specified.
----------
7.2.15 get
----------
Purpose: Reads the next component in a file into the file variable's buffer.
Syntax:
get-call = 'get' '(' f ')'
f = file-variable
Standard Pascal: Yes
Notes:
--------------
7.2.16 getdate
--------------
Purpose: Retrieves the current system date.
Syntax:
getdate-call = 'getdate' '(' year ',' month ',' day ',' day_of_week ')'
year = integer-variable
month = integer-variable
day = integer-variable
day_of_week = integer-variable
Standard Pascal: No
Notes:
"year" stores the current year
"month" stores the current month (1 to 12).
"day" stores the current day of the month (1 to 31)
"day_of_week" stores the current day of the week
(0 to 6 counting from Sunday).
Suppose the current system date is Wednesday September 30, 1998 then after
GetDate(year, month, day, day_of_week)
year = 1998
month = 9
day = 30
day_of_week = 3
------------------
7.2.17 getfiledate
------------------
Purpose: Returns the date a file was last modified.
Syntax:
getfiledate-call = 'getfiledate' '(' name ',' year ',' month ',' day ')'
name = character-expression | string-expression
year = integer-variable
month = integer-variable
day = integer-variable
Standard Pascal: No
Notes:
"name" is the name of the file to test.
"year" stores the year the file was last modified.
"month" stores the month the file was last modified (1 to 12)
"day" stores the day of the month the file was last modified (1 to 31)
------------------
7.2.18 getfilemode
------------------
Purpose: Gets a file's mode.
Syntax:
getfilemode-call = 'getfilemode' '(' name ',' mode ')'
name = character-expression | string-expression
mode = integer-variable
Standard Pascal: No
Notes:
"name" is the name of the file to test.
"mode" stores the file mode.
After the call "mode" can be AND'd with the following built-in constants
to determine information about the file:
The constants "usr_r", "usr_w", and "usr_x" can be AND'd with "mode"
to determine the user read, write, and execute permissions for the file.
The constants "grp_r", "grp_w", and "grp_x" can be AND'd with "mode"
to determine the group read, write, and execute permissions for the file.
The constants "oth_r", "oth_w", and "oth_x" can be AND'd with "mode"
to determine the read, write, and execute permissions for persons other
than the files owner who are not part of the file owner group.
The "dir_bit" constant can be AND'd with "mode" to determine if the file
really is a directory.
------------------
7.2.19 getfiletime
------------------
Purpose: Returns the time a file was last modified.
Syntax:
getfiletime-call = 'getfiletime' '(' name ',' hour ',' min ',' sec ')'
name = character-expression | string-expression
hour = integer-variable
min = integer-variable
sec = integer-variable
Standard Pascal: No
Notes:
"name" is the name of the file to test.
"hour" stores the hour the file was last modified (0 to 23)
"min" stores the minute the file was last modified (0 to 59)
"sec" stores the second the file was last modified (0 to 61)
--------------
7.2.20 gettime
--------------
Purpose: Retrieves the current system time.
Syntax:
gettime-call = 'gettime' '(' hour ',' min ',' sec ')'
hour = integer-variable
min = integer-variable
sec = integer-variable
Standard Pascal: No
Notes:
"hour" stores the current hour (0 to 23)
"min" stores the current minute (0 to 59)
"sec" stores the current second (0 to 61)
-----------
7.2.21 halt
-----------
Purpose: Terminates the program and optionally returns an integer value
to the program's caller.
Syntax:
halt-call = 'halt' [ '(' i ')' ]
i = integer-expression
Standard Pascal: No
Notes:
"i" if specified is the value returned by the program.
----------
7.2.22 inc
----------
Purpose: Increments an ordinal variable by a specified amount or by one.
Syntax:
inc-call = 'inc' '(' o [ ',' amount ] ')'
o = ordinal-variable
amount = integer-expression
Standard Pascal: No
Notes:
If "amount" is omitted then "o" is incremented by one.
Using this function is slightly more efficient than using
o := o + amount;
-------------
7.2.23 insert
-------------
Purpose: Inserts a component into a string or a list.
Syntax:
insert-call = insert-list | insert-string
insert-list = 'insert' '(' v ',' l [ ',' p ] ')'
insert-string = 'insert' '(' s1 ',' s2 [ ',' p ] ')'
v = expression
l = list-variable
s1 = character expression | string-expression
s2 = string-variable
Standard Pascal: No
Notes:
"v" is the component to insert into the list "l", and must be assignment
compatible with the list's component type.
"l" is the list variable to insert into.
"s1" s the component to insert into the string "s2".
"s2" is the string variable to insert into.
"p" if specified indicates the position to perform the insertion. If "p" is
omitted the insertion is performed at the end of the string or list.
------------
7.2.24 mkdir
------------
Purpose: Makes a directory
Syntax:
mkdir-call = 'mkdir' '(' name ')'
name = character-expression | string-expression
Standard Pascal: No
Notes:
"name" is the name of the directory to create.
----------
7.2.25 new
----------
Purpose: Initializes a list or creates a variable for a pointer.
Syntax:
new-call = new-list | new-pointer
new-list = 'new' '(' l ')'
new-pointer = 'new' '(' p ')'
l = list-variable
p = pointer-variable
Standard Pascal: Yes
Notes:
-----------
7.2.26 open
-----------
Purpose: Open a file.
Syntax:
open-call = 'open' '(' fv ',' name ',' mode ')'
fv = file-variable
name = character-expression | string-expression
mode = integer-expression
Standard Pascal: No
Notes:
"name" is the name of the file to open.
"mode" is the file mode. You can use the built-in constants "readmode",
"writemode", and "appendmode" to specify the file mode. The "readmode"
and "writemode" constants can be added or or'd together to specify that
the file be opened for both reading and writing.
For example
open(f, "test.txt", readmode+writemode);
will open the file "test.txt" for both reading and writing. It is an
error if the file "test.txt" does not exist. If you wish to create a new
file for reading and writing you must create it first with "rewrite" or
using "open" with "writemode" only, and then close the filee, before
opening it again for reading and writing.
See also "7.2.1 append", "7.2.38 reset", "7.2.40 rewrite".
--------------
7.2.27 opendir
--------------
Purpose: Opens a directory.
Syntax:
opendir-call = 'opendir' '(' d ')'
d = directory-variable
Standard Pascal: No
Notes:
Irie Pascal allows you to open, read, rewind, and close directories
(See "7.2.6 closedir", "7.2.35 readdir", and "7.2.39 rewinddir").
-----------
7.2.28 pack
-----------
Purpose: Copies some or all of the contents of an unpacked array
into a packed array.
Syntax:
pack-call = 'pack' '(' u ',' x ',' p ')'
u = unpacked-array-variable
x = expression
p = packed-array-variable
where "u" is an unpacked array
and "x" is an expression that is assignment compatible
with the index type of "u" and specifies the first
element of "u" to copy.
and "p" is a packed array
Standard Pascal: Yes
Notes:
The elements of "u" and "a" must have the same type.
For example suppose you have the following arrays
p : packed array[1..10] of integer;
u : array[-10..10] of integer;
then
pack(u, 1, p)
copies elements 1 to 10 of "u" into elements 1 to 10 of "p".
Or in a more complicated example
pack(u, 9, p)
copies elements 9 to 10 of "u" into elements 1 to 2 of "p"
-----------
7.2.29 page
-----------
Purpose: This procedure is supposed to affect a text file in such
a way that subsequent output to the file appears on a new
page.
Syntax:
page-call = 'page' '(' t ')'
t = text-file-variable
Standard Pascal: Yes
Notes:
Currently this procedure simply writes a form-feed to the text file.
----------
7.2.30 put
----------
Purpose: Writes the contents of a file's buffer to a file and
empties the file's buffer leaving it undefined.
Syntax:
put-call = 'put' '(' f ')'
f = file-variable
Standard Pascal: Yes
Notes:
If "f" is a file variable then the file's buffer can be accessed
with "f^" or "f@".
----------------
7.2.31 randomize
----------------
Purpose: Initializes the random number generator with a seed.
Syntax:
randomize-call = 'randomize' [ '(' i ')' ]
i = integer-expression
Standard Pascal: No
Notes:
"i" if specified is the seed used to initialize the random number generator.
If "i" is omitted then the random number generated is initialized with a
seed derived from the current system date and time. Specifying "i" is useful
if you want a repeatable sequence of random numbers.
--------------
7.2.32 rawread
--------------
Purpose: Reads up to a specified number of characters into a
character buffer.
Syntax:
rawread-call = 'rawread' '(' f ',' buffer ',' count ',' actual ')'
f = file-variable
buffer = array-variable
count = integer-expression
actual = integer-variable
Standard Pascal: No
Notes:
"buffer" must be a packed array of char variable and stores the characters
read by this procedure.
"count" specifies the maximum number of characters to read.
"actual" stores the actual number of characters read by this procedure.
"actual" may be less than "count" if there was an I/O error (you can check
for this by disabling I/O checking and using the IOResult function) or if
end of file was reached.
---------------
7.2.33 rawwrite
---------------
Purpose: Writes up to a specified number of characters from a character
buffer to a file.
Syntax:
rawwrite-call = 'rawwrite' '(' f ',' buffer ',' count ',' actual ')'
f = file-variable
buffer = array-variable
count = integer-expression
actual = integer-variable
Standard Pascal: No
Notes:
"buffer" must be a packed array of char variable and stores the characters
to be written by this procedure.
"count" specifies the maximum number of characters to write.
"actual" stores the actual number of characters written by this procedure.
"actual" may be less than "count" if there was an I/O error (you can check
for this by disabling I/O checking and using the IOResult function).
-----------
7.2.34 read
-----------
Purpose: This procedure reads data from a file into one or more variables.
Syntax:
read-call = 'read' read-parameter-list
read-parameter-list =
'(' [ file-variable ',' ] variable-access { ',' variable-access } ')'
Standard Pascal: Yes
Notes:
If the file-variable is omitted then the built-in text file variable
"input" is used.
When this procedure reads from a text file it first attempts to convert
the text data into binary data suitable for storage in variables. In
addition when reading from a text file the variables in the variable list
must be of type real, string, integer, char, or subrange of integer.
--------------
7.2.35 readdir
--------------
Purpose: Reads a directory (i.e. retrieves the name of a file in the
directory).
Syntax:
readdir-call = 'readdir' '(' d ',' name ')'
d = directory-variable
name = string-variable
where "d" is a directory variable (i.e. a variable of the built-in
type "dir").
Standard Pascal: No
Notes:
"d" is the directory variable associated with the directory to read.
"name" stores the filename of the next file in the directory.
See also "7.2.6 closedir", "7.2.27 opendir", and "7.2.39 rewinddir".
-------------
7.2.36 readln
-------------
Purpose: This procedure reads a line of data from a text file into one or
more variables. Any data left on the line after the read is ignored.
Syntax:
readln-call = 'readln' readln-parameter-list
readln-parameter-list =
[ '(' ( file-variable | variable-access ) { ',' variable-access } ')' ]
Standard Pascal: Yes
Notes:
If the file-variable is omitted then the built-in text file variable
"input" is used.
When this procedure reads from a text file it first attempts to convert
the text data into binary data suitable for storage in variables. In
addition when reading from a text file the variables in the variable list
must be of type real, string, integer, char, or subrange of integer.
-------------
7.2.37 rename
-------------
Purpose: Renames the file a file.
Syntax:
rename-call = 'rename' '(' f ',' name ')'
f = file-variable
name = character-expression | string-expression
Notes:
This procedure changes the name of the file associated with the
file variable "f" to "name". This is more than just changing the name
associated with the file variable, the actual name of the file is changed.
------------
7.2.38 reset
------------
Purpose: Opens a file for reading.
Syntax:
reset-call = 'reset' '(' f [ ',' name ] ')'
f = file-variable
name = character-expression | string-expression
Standard Pascal: Yes
Notes:
If "name" is specified then "name" is assigned to the file variable before
the file is opened (the file must be closed). See also "7.2.1 append",
"7.2.40 rewrite", "7.2.3 assign", and "7.2.42 seek".
----------------
7.2.39 rewinddir
----------------
Purpose: Rewinds a directory so that reads start with the first
file in the directory.
Syntax:
rewind-call = 'rewinddir' '(' d ')'
d = directory-variable
Standard Pascal: No
Notes:
See also "7.2.6 closedir", "7.2.27 opendir", and "7.2.35 readdir".
--------------
7.2.40 rewrite
--------------
Purpose: Opens a file for writing.
Syntax:
rewrite-call = 'rewrite' '(' f [ ',' name ] ')'
f = file-variable
name = character-expression | string-expression
Standard Pascal: Yes
Notes:
If the file exists it's contents are deleted.
If the file does not exist it is created.
If a filename ("n") is specified then the filename is assigned to the
file variable before the file is opened (the file must be closed). See
also "7.2.1 append", "7.2.3 assign", "7.2.38 reset", and "7.2.42 seek".
------------
7.2.41 rmdir
------------
Purpose: Removes (deletes) a directory
Syntax:
rmdir-call = 'rmdir' '(' name ')'
name = character-expression | string-expression
Standard Pascal: No
Notes:
"name" is the name of the directory to delete.
-----------
7.2.42 seek
-----------
Purpose: Sets the position indicator for a file.
Syntax:
seek-call = 'seek' '(' f ',' offset ')'
f = file-variable
offset = integer-expression
Standard Pascal: No
Notes:
"offset" specifies the new position indicator for the file.
The file associated with "f" must be open.
------------------
7.2.43 setfiledate
------------------
Purpose: Sets a files date (i.e. last modification date).
Syntax:
setfiledate-call = 'setfiledate' '(' f ',' year ',' mon ',' day ')'
f = file-variable
year = integer-expression
mon = integer-expression
day = integer-expression
Standard Pascal: No
Notes:
"year" specifies the year.
"mon" specifies the month (1 to 12)
"day" specifies the day (1 to 31).
------------------
7.2.44 setfiletime
------------------
Purpose: Sets a files time (i.e. last modification time).
Syntax:
setfiletime-call = 'setfiletime' '(' f ',' hour ',' min ',' sec ')'
f = file-variable
hour = integer-expression
min = integer-expression
sec = integer-expression
Standard Pascal: No
Notes:
"hour" specifies the hour (0 to 23)
"min" specifies the minute (0 to 59)
"sec" specifies the second (0 to 61).
------------
7.2.45 sleep
------------
Purpose: Pauses execution of the program for a specified number of seconds.
Syntax:
sleep-call = 'sleep' '(' i ')'
i = integer-expression
Standard Pascal: No
Notes:
"i" specifies the number of seconds to sleep.
----------
7.2.46 str
----------
Purpose: Converts an integer or real expression into a string and
assigns the converted string to a variable.
Syntax:
str-call = str-integer | str-real
str-integer = 'str' '(' i [':' width] ',' s ')'
str-real = 'str' '(' r [ ':' width [ ':' frac ] ] ',' s ')'
i = integer-expression
width = integer-expression
s = string-variable
r = real-expression
frac = integer-expression
Standard Pascal: No
Notes:
"i" specifies the integer to convert
"s" stores the converted string.
"width" specifies the maximum width of the converted string
"frac" specifies the number of digits after the decimal point.
If "width" is omitted then eight is assumed for integer conversion
and nine is assumed for real conversions.
If "frac" is omitted then the real expression is converted into a
string in exponential form.
If "frac" is present then the real expression is converted into
a string in fixed form.
For example
str(1034:6, s) will store ' 1034' in "s"
str(3.1:8, s) will store '3.1E+001' in "s"
str(-3.14:6:2, s) will store ' -3.14' in "s"
The string value is padded on the left if necessary.
-------------
7.2.47 unpack
-------------
Purpose: Copies some or all of the elements of a packed array into
an unpacked array.
Syntax:
unpack-call = 'unpack' '(' p ',' u ',' x ')'
p = packed-array-variable
x = expression
u = unpacked-array-variable
Standard Pascal: Yes
Notes:
"x" must be assignment compatible with the index type of "u" and specifies
the position in "u" to receive the first array element.
The elements of "u" and "a" must have the same type.
For example suppose you have the following arrays
p : packed array[1..10] of integer;
u : array[-10..10] of integer;
then
unpack(p, u, 1)
copies elements -10 to -1 of "p" into elements 1 to 10 of "u".
----------
7.2.48 val
----------
Purpose: Converts a string expression into an integer or real value
and assigns the converted value to a variable.
Syntax:
val-call = val-integer | val-real
val-integer = 'val' '(' s ',' i ',' offset ')'
val-real = 'val' '(' s ',' r ',' offset ')'
s = character-expression | string-expression
i = integer-variable
r = integer-variable
Standard Pascal: No
Notes:
"i" stores the converted integer value
"r" stores the converted real value
"offset" stores the position of the first character in "s" that could not
be converted or zero if all characters where converted.
For example given integer variables "i" and "x" the following statement
val('123EB', i, x)
will store 123 in "i" and 4 in "x".
------------
7.2.49 write
------------
Purpose: This procedure writes data from one or more variables into a file
Syntax:
write-call = 'write' write-parameter-list
write-parameter-list =
'(' [ file-variable ',' ] write-parameter { ',' write-parameter } ')'
write-parameter = expression [ ':' expression [ ':' expression ] ]
Standard Pascal: Yes
Notes:
When this procedure writes to a non-text file then the write-parameters
are simply expressions, and the binary value of the expressions are
written to the file.
When this procedure writes to a text file it first attempts to convert
the binary data stored in the variables into text data. In addition
when writing to a text file the variables in the variable list must
must be of type boolean, real, string, integer, subrange of integer,
or char.
--------------
7.2.50 writeln
--------------
Purpose: This procedure writes a line of data from one or more variables
into a text file
Syntax:
writeln-call = 'writeln' writeln-parameter-list
writeln-parameter-list =
[ '(' ( file-variable | write-parameter ) { ',' write-parameter } ')' ]
write-parameter = expression [ ':' expression [ ':' expression ] ]
Standard Pascal: Yes
Notes:
When this procedure writes to a text file it first attempts to convert
the binary data stored in the variables into text data. In addition
when writing to a text file the variables in the variable list must
must be of type boolean, real, string, integer, subrange of integer,
or char.
-------------
8 Expressions
-------------
Expressions specify a sequence of operations to be performed that
result in a single value of a particular type.
The syntax for expressions is given below:
expression = shift-expression [ relational-operator shift-expression]
shift-expression = simple-expression [ shift-operator simple-expression]
simple-expression = term { adding-operator term }
term = factor { multiplying-operator factor }
factor = [sign] unsigned-constant |
[sign] variable-access |
[sign] '(' expression ')' |
function-designator |
'not' factor |
set-constructor
sign = '+' | '-'
unsigned-constant = unsigned-integer |
unsigned-real |
character-string |
constant-identifier |
'nil'
variable-access = entire-variable |
component-variable |
identified-variable |
buffer-variable
entire-variable = variable-identifier
component-variable = indexed-variable | field-designator
indexed-variable =
array-variable '[' index-expression { ',' index-expression } ']'
field-designator = record-variable '.' field-specifier |
field-designator-identifier
field-specifier = field-identifier
identified-variable = pointer-variable '^' | pointer-variable '@'
buffer-variable = file-variable '^' | file-variable '@'
set-constructor = '[' [ member-designator { ',' member-designator } ] ']'
member-designator = expression [ '..' expression ]
function-designator = function-identifier [ actual-parameter-list ]
actual-parameter-list = '(' actual-parameter { ',' actual-parameter } ')'
actual-parameter = expression |
variable-access |
procedure-identifier |
function-identifier
omitted-parameter
omitted-parameter =
relational-operator = '=' | '<>' | '<' | '<=' | '>' | '>=' | 'in'
shift-operator = 'shl' | shr'
adding-operator = '+' | '-' | 'or' | 'or_else' | 'xor'
multiplying-operator = '*' | '/' | 'div' | 'mod' | 'and' | 'and_then'
-------------
8.1 Operators
-------------
Below is a table of all the operators supported by Irie Pascal in
order of decreasing precedence. All operators on the same line have
the same precedence.
-----------------------------
not
-----------------------------
* / div mod and and_then
-----------------------------
+ - or or_else xor
-----------------------------
shl shr
-----------------------------
= <> < <= > >= in
-----------------------------
------------------
8.1.1 Not Operator
------------------
The "not" operator takes a single operand and specifies one of two
operations depending on the type of the operand. If the operand is
of type boolean then the "not" operator specifies a boolean NOT (i.e
if the value of the operand is true the result of the operation is false
and if the value of the operand is false the result of the operation is
true). If the operand is of type integer then the "not" operator specifies
a bitwise NOT (i.e. the result of the operation is calculated by flipping
all the bits in the operand).
----------------
8.1.2 * Operator
----------------
The "*" operator takes two operands and specifies one of two operations
depending on the type of the operands.
If the operands are of type integer or real then the "*" operator specifies
multiplication. If both operands are of type integer then the result of the
operation is of type integer. If both operands are of type real then the
result of the operation is of type real. If one operand is of type integer
and the other is of type real then the integer operand is converted to real
before the multiplication is performed and the result of the operation is of
type real.
If the operands are set-types then the "*" operator specifies set
intersection (i.e. the result of the operation is a set whose members
are those members common to both operands).
----------------
8.1.3 / Operator
----------------
The "/" operator takes two operands and specifies division. The type of
the operands must be integer or real, and the integer operands are first
converted to real before the division is performed. The result of the
operation is of type real.
------------------
8.1.4 Div Operator
------------------
The "div" operator takes two operands and specifies division. The type of
the operands must both be of type integer. The result of the operation is
of type integer (note: The remainder from the division is discarded).
------------------
8.1.5 Mod Operator
------------------
The "mod" operator takes two operands and specifies modulus. The type of
the operands must both be of type integer. When the operands are positive
then the result of the operation is the remainder from dividing the left
operand by the right operand. The result of the operation is of type
integer.
------------------
8.1.6 And Operator
------------------
The "and" operator takes two operands and specifies one of two operations
depending on the type of the operands.
If the operands are of type boolean then the "and" operator specifies
boolean AND. The result of the operation is of type boolean and is equal
to true of both operands are true, and false if either operand is false.
By default short circuit evaluation is used when performing the boolean
AND (i.e. The left operand is evaluated first and if it is false then
the right operand is not evaluated because the result of the operation
must be false). The "-sc" compiler option that can be used to
enable/disable short-circuit evaluation.
If the operands are of type integer then the "and" operator specifies
bitwise AND. The result of the operation is of type integer.
-----------------------
8.1.7 And_Then Operator
-----------------------
As an extension Irie Pascal supports the "and_then" operator, which takes
two boolean operands and specifies boolean AND. The result of the operation
is of type boolean. The difference between this operator and the "and"
operator is that this one can not be used to perform bitwise AND and
short circuit evaluation is always used when evaluating this operator.
----------------
8.1.8 + Operator
----------------
The "+" operator takes one or two operands and specifies one of three
operations depending on the type of the operands.
If there is only one operand and it is of type integer or real then
this operator specifies unary-plus and in fact has no effect.
If there are two operands and they are of type integer or real then the "+"
operator specifies addition. If both operands are of type integer then the
result of the operation is of type integer. If both operands are of type
real then the result of the operation is of type real. If one operand is of
type integer and the other is of type real then the integer operand is
converted to real before the addition is performed and the result of the
operation is of type real.
If there are two operands and they are of set type then the "+" operator
specified set union (i.e. the result of the operation is a set with all
the members from either operand).
As an extension Irie Pascal supports the use of the "+" to specify string
concatenation where there are two operands and they are of type string or
char.
----------------
8.1.9 - Operator
----------------
The "-" operator takes one or two operands and specifies one of two
operations depending on the type of the operands.
If there is only one operand and it is of type integer or real then
this operator specifies unary-minus and specifies unary-minus. The
result of this operation has the same type as it's operand and has the
same magnitude as it's operand but the opposite sign.
If there are two operands and they are of type integer or real then the "-"
operator specifies subtraction. If both operands are of type integer then
the result of the operation is of type integer. If both operands are of type
real then the result of the operation is of type real. If one operand is of
type integer and the other is of type real then the integer operand is
converted to real before the subtraction is performed and the result of the
operation is of type real.
If there are two operands and they are of set type then the "-" operator
specified set difference (i.e. the result of the operation is a set with
those members are in the left operand but not in the right operand).
------------------
8.1.10 Or Operator
------------------
The "or" operator takes two operands and specifies one of two operations
depending on the type of the operands.
If the operands are of type boolean then the "or" operator specifies
boolean OR. The result of the operation is of type boolean and is equal
to true of either operand is true, and false if both operands are false.
By default short circuit evaluation is used when performing the boolean
OR (i.e. The left operand is evaluated first and if it is true then
the right operand is not evaluated because the result of the operation
must be true). The "-sc" compiler option that can be used to
enable/disable short-circuit evaluation.
If the operands are of type integer then the "or" operator specifies
bitwise OR. The result of the operation is of type integer.
-----------------------
8.1.11 Or_Else Operator
-----------------------
As an extension Irie Pascal supports the "or_else" operator, which takes two
boolean operands and specifies boolean OR. The result of the operation is
of type boolean. The difference between this operator and the "or" operator
is that this one can not be used to perform bitwise OR and short circuit
evaluation is always used when evaluating this operator.
-------------------
8.1.12 Xor Operator
-------------------
As an extension Irie Pascal supports the "xor" operator, which takes two
operands and specifies one of two operations depending on the type of the
operands.
If the operands are of type boolean then the "xor" operator specifies
boolean XOR. The result of the operation is of type boolean and is equal
to true if one but not both operands are true, and false if both operands
are false.
If the operands are of type integer then the "xor" operator specifies
bitwise XOR. The result of the operation is of type integer.
-------------------
8.1.13 shl Operator
-------------------
As an extension Irie Pascal supports the "shl" operator, which takes two
operands of type integer and specifies bit-shift left. The result of the
operation is the left operand shifted left by the number of bits specified
by the right operand. The right operand must be greater than or equal to
zero.
-------------------
8.1.14 shr Operator
-------------------
As an extension Irie Pascal supports the "shr" operator, which takes two
operands of type integer and specifies bit-shift right. The result of the
operation is the left operand shifted right by the number of bits specified
by the right operand. The right operand must be greater than or equal to
zero.
-----------------
8.1.15 = Operator
-----------------
The "=" operator takes two operands and compares them for equality. If one
operand is of type integer and the other is of type real then the integer
operand is converted to real before the comparison is made. The result of
this operation is of type boolean and is true if the operands are equal
and false otherwise.
-----------------
8.1.16 <> Operator
-----------------
The "<>" operator takes two operands and compares them for equality. If one
operand is of type integer and the other is of type real then the integer
operand is converted to real before the comparison is made. The result of
this operation is of type boolean and is true if the operands are not equal
and true otherwise.
-----------------
8.1.17 < Operator
-----------------
The "<" operator takes two operands and compares them. If one operand is of
type integer and the other is of type real then the integer operand is
converted to real before the comparison is made. The result of this
operation is of type boolean and is true if the left operand is less than
the right operand.
------------------
8.1.18 <= Operator
------------------
The "<=" operator takes two operands and specifies one of two operations
depending on the type of the operands.
The operands are simple types or string types then this operator compares
them. If one operand is of type integer and the other is of type real then
the integer operand is converted to real before the comparison is made.
The result of this operation is of type boolean and is true if the left
operand is less than or equal to the right operand.
If the operands are set types then the "<=" operator specifies set
inclusion. The result of this operation is true if all the members
of the left operand are in the right operand.
-----------------
8.1.19 > Operator
-----------------
The ">" operator takes two operands and compares them. If one operand is of
type integer and the other is of type real then the integer operand is
converted to real before the comparison is made. The result of this
operation is of type boolean and is true if the left operand is greater
than the right operand.
------------------
8.1.20 >= Operator
------------------
The ">=" operator takes two operands and specifies one of two operations
depending on the type of the operands.
The operands are simple types or string types then this operator compares
them. If one operand is of type integer and the other is of type real then
the integer operand is converted to real before the comparison is made.
The result of this operation is of type boolean and is true if the left
operand is greater than or equal to the right operand.
If the operands are set types then the ">=" operator specifies set
inclusion. The result of this operation is true if all the members
of the right operand are in the left operand, and is false otherwise.
------------------
8.1.21 In Operator
------------------
The "in" operator takes two operands, the left operand is of set type
and the right operands of ordinal type. The result of this operation
is of type boolean and is true if the right operand is a member of the
left operand, and is false otherwise.
--------------------
8.2 Compatible types
--------------------
Irie Pascal implements the type compatibility rules defined by Standard
Pascal (ISO/IEC 7185), and adds one more to support variable length
string types. The first four rules below are taken from ISO/IEC 7185 and
the last one is the one added to support variable length string types.
Types T1 and T2 shall be designated compatible if any of the following
statements is true:
1. T1 and T2 are the same type.
2. T1 is a subrange of T2, or T2 is a subrange of T1, or both T1 and T2 are
subranges of the same host type.
3. T1 and T2 are set-types of compatible base-types, and either both T1 and
T2 are designated packed or neither T1 nor T2 is designated packed.
4. T1 and T2 are fixed-length-string-types with the same number of
components.
5. Either T1 is a variable-length-string-type and T2 is a
variable-length-string-type,
or T1 is a variable-length-string-type and T2 is a
fixed-length-string-type, and the number of components in T2 is less
than or equal to the maximum length of T1,
or T1 is a variable-length-string-type and T2 is the char-type
or T2 is a variable-length-string-type and T1 is a
fixed-length-string-type, and the number of components in T1 is less
than or equal to the maximum length of T2,
or T2 is a variable-length-string-type and T1 is the char-type.
------------
9 Statements
------------
The statements in a program specify the specific actions that the program
can perform. Programs perform their actions (or run) by executing the
statements that they contain. Pascal programs begin executing at the first
statement in the main program block. Program execution generally flows
from left to right and top to bottom, however there are a number of
statements which can alter this flow of execution.
Statements can be grouped in a number of ways. For example statements
can be separated into two groups, simple statement and structured statements,
where simple statements are statements that do not contain other statements,
while structured statements are statements that do contain other statements.
Other groups of statements include conditional statements and repetitive
statements. Conditional statements allow programs to make decisions (i.e.
they test a particular condition and change the flow of execution depending
on the result). Repetitive statements allow the program to loop (i.e.
execute one or more statements repeatedly).
Labels can be placed in front of statements to mark them as targets for
"goto" statements. As an extension Irie Pascal allows labels to be
identifiers as well as sequences of digits. See also "3 Labels".
The syntax for statements is given below:
statement = [ label ':' ] ( simple-statement | structured-statement )
label = digit-sequence | identifier
simple-statement = empty-statement |
assignment-statement |
procedure-statement |
goto-statement
structured-statement = compound-statement |
conditional-statement |
repetitive-statement |
with-statement
compound-statement = 'begin' statement-sequence 'end'
statement-sequence = statement { ';' statement }
conditional-statement = if-statement |
case-statement
repetitive-statement = repeat-statement |
while-statement |
for-statement
-------------------
9.1 Empty Statement
-------------------
Empty statements don't do anything and are usually created when Pascal
syntax requires a statement to exist but you don't specify one.
For example if you write
begin
end
then technically according to Pascal syntax there must be a statement
between the "begin" and the "end", and since there is nothing there the
empty statement is said to exist there. Empty statements also commonly
occur when statements sequences have a trailing semi-colon. In Pascal the
semi-colon is used as a statement separator and not a statement terminator
so the following statement sequence
a;
b;
actually contains three statements, the statement "a", the statement "b"
and an empty statement following "b". Since a semi-colon follows "b" then
it must separate "b" from another statement.
The syntax for the empty statement is given below:
empty-statement =
------------------------
9.2 Assignment Statement
------------------------
Assignments statements specify that an expression is to be evaluated and
the result stored in a variable. The value produced from evaluating the
expression must be assignment compatible with the type of the variable
(See "9.2.1 Assignment Compatibility" for details).
For example
x := 1+1
is a simple example. When this statement is executed the expression "1+1"
is evaluated, and the value "2" is placed in the variable "x".
The syntax for the assignment statement is given below:
assignment-statement = variable-access ':=' expression
variable-access = entire-variable |
component-variable |
identified-variable |
buffer-variable
entire-variable = variable-identifier
component-variable = indexed-variable | field-designator
indexed-variable =
array-variable '[' index-expression { ',' index-expression } ']'
field-designator = record-variable '.' field-specifier |
field-designator-identifier
field-specifier = field-identifier
identified-variable = pointer-variable '^' | pointer-variable '@'
buffer-variable = file-variable '^' | file-variable '@'
See "8 Expression" for the syntax of expressions.
------------------------------
9.2.1 Assignment Compatibility
------------------------------
Irie Pascal implements the assignment compatibility rules defined by
Standard Pascal (ISO/IEC 7185), and adds one more to support variable
length string types. The first five rules below are taken from ISO/IEC 7185
and the last one is the one added to support variable length string types.
A value "V" of type T2 is assignment compatible with a type T1 if any of
the following is true:
1. T1 and T2 are the same type, and that type is not a file type or a type
which contains a file type.
2. T1 is the real-type and T2 is the integer-type.
3. T1 and T2 are compatible ordinal-types, and V is in the closed interval
specified by T1.
4. T1 and T2 are compatible set-types, and all the members of V are in the
closed interval specified by the base-type of T1.
5. T1 and T2 are fixed length string types with the same length.
6. T1 is a variable length string type and either
T2 is a variable length string type
or T2 is a fixed length string type
or T2 is a char-type.
In addition the length of V must not be greater then the maximum
length of T1.
----------------------------------------------------
9.2.1.1 Assignment compatibility with array indexing
----------------------------------------------------
The value of an index-expression shall be assignment compatible with the
index-type of the array variable.
For example given:
var x : array[1..10] of integer;
and
x[i] := 20;
then "i" (the value of the index-expression) shall be assignment compatible
with "1..10" (the index-type of the array variable).
------------------------------------------------------
9.2.1.2 Assignment compatibility with value parameters
------------------------------------------------------
When passing a parameter by value the actual-parameter shall be
assignment compatible with the type of the formal-parameter.
For example given:
function IsDigit(c : char) : Boolean;
begin
if c in ['0'..'9'] then
IsDigit := true
else
IsDigit := false
end;
and
while not IsDigit(key) do
read(key)
then "key" (the actual-parameter in IsDigit(key) shall be
assignment compatible with "char" (the type of the formal-parameter).
--------------------------------------------
9.2.1.3 Assignment compatibility with "read"
--------------------------------------------
When using the built-in procedure "read" to store an input value into
a variable the input value shall be assignment compatible with the type of
the variable to which it is stored.
For example given:
var s : string[40];
and
read(s);
then the value read in by "read(s)" must be assignment compatible with
"string[40]".
-----------------------------------------------------------
9.2.1.4 Assignment compatibility with assignment statements
-----------------------------------------------------------
The value of the expression on the right-hand side of an assignment statement
shall be assignment compatible with the type of the left-hand side (i.e.
either the variable or the function-identifier on the left-hand side).
For example given:
var age : 0..100;
and
age := v;
then "v" (the right-hand side of the assignment statement) shall be
assignment compatible the "0..100" (the type of the left-hand side of the
assignment statement).
-------------------------------------------
9.2.1.5 Assignment compatibility with "for"
-------------------------------------------
The initial value and the final value in a for-statement shall be
assignment compatible with the type of the control variable if the
statement of the for-statement is executed (See "9.10 For Statement").
For example given:
for i := low to high do writeln(i);
then "low" (the initial value) and "high" (the final value) shall be
assignment compatible with the type of "i" (the control variable) if
"writeln(i)" is executed. NOTE: "writeln(i)" will get executed unless
"low" is greater than "high".
---------------------------
9.2.1.6 Transfer procedures
---------------------------
In the statement pack(a,i,z) and unpack(z,a,i) the value of "i" shall be
assignment compatible with the index-type of "a".
For example given:
var a : array[1..100] of real;
z : packed array[1..100] of real;
i : integer;
and
pack(a,i,z) or unpack(z,a,i)
then "i" shall be assignment compatible with "1..100"
(the index-type of "a").
-----------------------
9.3 Procedure Statement
-----------------------
Procedure statements specify that a procedure is to be executed and
that a list of arguments if any are to be passed into the procedure.
When procedures are executed program execution is transferred to the
first statement in the procedure's statement block. After the execution
of a procedure program execution resumes with the statement after the
procedure call (See "7 Functions And Procedures").
For example
writeln('1 + 1 = ', 1+1)
is a simple example. When this statement is executed the parameters "'1+1'"
and "1+1" are passed into the procedure and then it is executed. In this case
the "writeln" procedure prints the parameters to the standard output stream.
The syntax for procedure statements is given below:
procedure-statement = procedure-identifier
(
[ actual-parameter-list ] |
read-parameter-list |
readln-parameter-list |
write-parameter-list |
writeln-parameter-list
)
procedure-identifier = identifier
actual-parameter-list = '(' actual-parameter { ',' actual-parameter } ')'
actual-parameter = expression |
variable-access |
procedure-identifier |
function-identifier |
omitted-parameter
omitted-parameter =
read-parameter-list =
'(' [ file-variable ',' ] variable-access { ',' variable-access } ')'
readln-parameter-list =
[ '(' ( file-variable | variable-access ) { ',' variable-access } ')' ]
write-parameter-list =
'(' [ file-variable ',' ] write-parameter { ',' write-parameter } ')'
write-parameter = expression [ ':' expression [ ':' expression ] ]
writeln-parameter-list =
[ '(' ( file-variable | write-parameter ) { ',' write-parameter } ')' ]
------------------
9.4 Goto Statement
------------------
Goto statements specify that program execution is to be transferred to
the statement prefixed by the goto statement's label. Standard
(ISO/IEC 7185) Pascal describes the rules governing the use of
goto statements as follows:
A label, if any, of a statement S shall be designated as prefixing S.
The label shall be permitted to occur in a goto-statement G if and only
if any of the following three conditions is satisfied.
a) S contains G.
b) S is a statement of a statement-sequence containing G.
c) S is a statement of the statement-sequence of the compound-statement
of the statement-part of a block containing G.
To fully understand these rules you will probably need a copy of the
Standard (ISO/IEC 7185) but the fully explanation should suffice for
most people.
The rules are basically saying that you can't use a goto statement to
transfer execution into the middle of a statement. The first two rules
cover goto statements that refer to statements in the current block,
while the last rule covers goto statements that refer to statements in
an enclosing block.
If a goto statement transfers execution out of the current block then
the call-stack is unwound until the block containing the statement
referred to be the goto statement is reached.
So for example if the main program calls a procedure A, and procedure A
calls procedure B, and procedure B calls procedure C, and a goto statement
in procedure C transfers execution back to procedure A then procedures
C and B are terminated.
Below is a simple program illustrating the use of the goto statement
program ten(output);
label loop;
var
count : integer;
begin
count := 1;
loop: writeln(count);
count := count + 1;
if count <= 10 then goto loop
end.
NOTE: The label "loop" used in this program is declared before it is used
(which is a requirement for all labels).
The syntax for goto statements is given below:
goto-statement = 'goto' label
label = digit-sequence | identifier
----------------------
9.5 Compound Statement
----------------------
Compound statements are used to group a number of statements into a
single statement. When a compound statement is executed, program execution
is transferred to the first statement in the statement group and generally
continues left to right, top to bottom unless diverted by one of the
statements executed. You usually use compound statements when Pascal
syntax says that only one statement is allowed at a particular point but you
want to put more than one, so you put the statements in a compound statement
and Pascal syntax is happy because the compound statement is a single
statement.
For example look at the program fragment below:
write('Do you want to continue');
readln(answer);
if (answer = 'n') or (answer = 'N') then
begin
writeln('Program terminated by user');
halt
end
here we want to write a message to the screen and stop if the user
answers "n" or "N", but this requires two statements and the then part
of an if statement allows only a single statement. The solution as you
can see is just to put the two statements into a compound statement.
The syntax for compound statements is given below:
compound-statement = 'begin' statement-sequence 'end'
statement-sequence = statement { ';' statement }
----------------
9.6 If Statement
----------------
If statements conditionally execute one or two statements. If statements
contain a boolean expression, a "then-part", and may optionally contain an
"else-part". When an if statement is executed the boolean expression is
evaluated and what happens next depends on the result of the evaluation.
If the expression is evaluated and found to be true then the statement in
the "then-part" is executed, and program execution resumes at the statement
after the if statement.
If the expression is evaluated and found to be false then if an "else-part"
is present the statement in the "else-part" is executed and program control
resumes at the statement after the if statement, if an else part is not
present then program execution is transferred immediately to the statement
after the if statement.
For example
if x > y then
writeln('x is greater than y')
else
writeln('x is NOT greater than y')
is an if statement.
When this statement is executed the boolean expression "x > y" is evaluated
and if true the statement "writeln('x is greater than y')" is executed,
and if the boolean expression is false the statement
"writeln('x is NOT greater than y')" is executed.
The syntax for if statements is given below:
if-statement = 'if' boolean-expression then-part [ else-part ]
then-part = 'then' statement
else-part = 'else' statement
------------------
9.7 Case Statement
------------------
Case statements conditionally execute one, two, or more statements.
Case statements contain an ordinal expression, zero, one or more case list
elements, and optionally a case statement completer. Case list elements
contain one or more constants and a statement. Case statement completers
contain a statement sequence. When a case statement is executed the ordinal
expression is evaluated and the value used to conditionally execute either
the statement in one of the case list elements or the statement sequence in
the case statement completer. If the expression evaluates to a value equal
to one of the constants in a case list element then the statement in that
case list element is executed. If the expression evaluates to a value that
is not equal to one of the constants in a case list element then the
statement sequence in the case statement completer is executed (if there is
no case statement completer then this is an error). After executing either
the statement in the case list element or the statement sequence in the
case statement completer program execution resumes at the statement after
the case statement.
Constant ranges can be used to specify a number of contiguous constants
(for example 1..5 is the same as 1, 2, 3, 4, 5).
No two case list elements can contain the same constant, so
case x of
1, 2, 3 : write('1 to 3');
2 : write('2');
end
is an error since both case list elements contain "2".
For example the program fragment below shows an ordinal type and
a procedure with a case statement.
type
DayOfWeek =
(monday, tuesday, wednesday, thursday, friday, saturday, sunday);
procedure WriteDayOfWeek(day : DayOfWeek);
begin
case day of
monday: write('monday');
tuesday: write('tuesday');
wednesday: write('wednesday');
thursday: write('thursday');
friday: write('friday');
saturday: write('saturday');
sunday: write('sunday');
end
end;
When the case statement is executed the ordinal expression "day" is evaluated
and if it is equal to "tuesday" for example then since the second case list
element contains a constant equal to "tuesday" then the statement in the
second case list element is executed (i.e. write('tuesday')).
Below is a slightly more complex example.
program example(input, output);
var
c : char;
begin
write('Enter a digit :');
readln(c);
case c of
'0'..'9' : writeln('OK');
'a'..'z', 'A'..'Z' : writeln('That is a letter');
otherwise writeln('What is that?');
end
end.
When the case statement is executed the ordinal expression "c" is
evaluated and the value used as follows:
If the value is a digit then the statement in the first case list element is
executed.
If the value is a letter then the statement in the second case list elements
is executed.
If the value is not a digit or a letter then the statement sequence in the
case statement completer is executed.
Due to an implementation limit Irie Pascal handles case statements
differently depending on the type of the ordinal expression.
If the ordinal expression in the case statement has a type with less than or
equal to 1024 values then Irie Pascal implements the case statement using a
jump table and the rule that no two case list elements can have the same
constant is enforced. In addition with the table implementation the ordinal
expression is evaluated only once.
If the ordinal expression in the case statement has a type with more than
1024 values then Irie Pascal implements the case statement as a series of
if statements and the rule that no two case list elements can have the same
constant is NOT enforced. In addition with the if statement implementation
the ordinal expression is evaluated once for each case list element until
a match is found.
In practice the only integer expression are likely to have types with ranges
greater than 1024. You could create an enumerated type with more than
1024 values but that is unlikely.
The syntax for case statements is given below:
case-statement = 'case' case-index case-body [ ';' ] 'end'
case-index = ordinal-expression
case-body = case-list-elements [ [ ';' ] case-statement-completer ] |
case-statement-completer
case-list-elements = case-list-element { ';' case-list-element }
case-list-element = case-constant-list ':' statement
case-constant-list = case-specifier { ',' case-specifier }
case-specifier = case-constant [ '..' case-constant ]
case-constant = ordinal-constant
case-statement-completer = 'otherwise' statement-sequence
--------------------
9.8 Repeat Statement
--------------------
Repeat statements are used to repeatedly execute one or more statements
in a loop. Repeat statements contain a statement sequence and a loop
condition. When a repeat statement is executed the statement sequence is
executed as long as the loop condition is satisfied. The loop condition
is tested after the statement sequence is executed so the statement sequence
will always be executed at least once. The loop condition is a boolean
expression and is satisfied as long as the expression evaluates to false.
Usually the statement sequence will perform some action that will eventually
cause the loop condition to fail and thus terminate the loop. It is also
possible to use a goto statement to terminate the loop.
For example below is a very simple program which illustrates the use
of the repeat statement.
program ten(output);
var
count : 1..11;
begin
count := 1;
repeat
writeln(count);
count := count + 1
until count > 10
end.
The syntax for repeat statements is given below
repeat-statement = 'repeat' statement-sequence 'until' boolean-expression
-------------------
9.9 While Statement
-------------------
While statements are used to repeatedly execute a statement in a loop.
While statements contain a statement and a loop condition. When a while
statement is executed the statement is executed as long as the loop condition
is satisfied. The loop condition is tested before the statement is executed
so it is possible that the statement not be executed at all. The loop
condition is a boolean expression and is satisfied as long as the expression
evaluates to true. Usually the statement will perform some action that will
eventually cause the loop condition to fail and thus terminate the loop. It
is also possible to use a goto statement to terminate the loop.
For example below is a very simple program which illustrates the use
of the while statement.
program ten(output);
var
count : 1..11;
begin
count := 1;
while count <= 10 do
begin
writeln(count);
count := count + 1;
end
end.
The syntax for while statements is given below
while-statement = 'while' boolean-expression 'do' statement
------------------
9.10 For Statement
------------------
For statements are used to repeatedly execute a statement in a loop, while
at the same time counting each loop iteration. For statements contain a
control variable, an initial value, a final value, and a statement.
There are two kind of for statements, one kind counts upwards, and the
other kind counts downwards.
For statements that count upwards are executed as follows:
First initial value is compared with the final value, and if the initial
value is greater than the final value then the execution of the for
statement is terminated immediately and the statement contained in the
for statement is never executed. If the initial value is not greater than
the final value then the initial value is assigned to the control variable
and the looping begins. For each iteration of the loop the statement
contained in the for statement is executed and then the control variable
is incremented by one. The loop continues as long as the control variable
is less than or equal to the final value.
For statements that count downwards are executed as follows:
First initial value is compared with the final value, and if the initial
value is less than the final value then the execution of the for
statement is terminated immediately and the statement contained in the
for statement is never executed. If the initial value is not less than
the final value then the initial value is assigned to the control variable
and the looping begins. For each iteration of the loop the statement
contained in the for statement is executed and then the control variable
is decremented by one. The loop continues as long as the control variable
is greater than or equal to the final value.
You should not depend on the control variable having any particular value
after execution of a for statement unless the for statement was left
using a goto statement.
Normally when executing a for statement it is best if the value of the
control variable is changed only by the for statement. If another statement
alters the value of the control variable it usually means that there is
a bug somewhere in your program. In an apparent effort to protect
programmers from making that kind of mistake Standard (ISO/IEC 7185) Pascal
defines a number of rules that restrict how control variables are used.
Irie Pascal implements these rules.
The first rule is that control variables must be declared at the same
level as the for statement (i.e. if the for statement is in a function or
procedure then the control variable must be local to that function or
procedure, and if the for statement is in the main program block then the
control variable must be global). Keeping the control variable local
makes it easier to control access.
The second rule is that neither the for statement nor any function or
procedure local to the block containing the for statement shall contain
a statement that "threatens" the control variable.
A statement "threatens" the control variable if the execution of the
statement could possibly alter the control variable.
So for example
An assignment statement "threatens" the control variable if the control
variable is the variable being assigned to.
A function or procedure call "threatens" the control variable if the
control variable is being passed by reference.
A "read" or "readln" statement "threatens" the control variable is
used in the read-parameter-list or the readln-parameter-list.
A for statement "threatens" the control variable if it uses the
same control variable.
The syntax for the for statement is given below:
for-statement =
'for' control-variable ':=' initial-value ('to' | 'downto') final-value
'do' statement
control-variable = variable-identifier
initial-value = ordinal-expression
final-value = ordinal-expression
-------------------
9.11 With Statement
-------------------
With statements allow the fields of a record variable to be accessed
without specifying the record-variable each time. With statements contain
a record variable list and a statement. When a with statement is executed
the statement it contains is executed, however the fields in the record
variable can be accessed using the field identifier alone.
For example give the following type and variable
type
student = record
name : string;
address : string;
grade : integer;
end;
var
s : student;
then
with s do
begin
name := 'John';
address := 'main street';
grade := 20;
end
is equivalent to
begin
s.name := 'John';
s.address := 'main street';
s.grade := 20;
end
Since some record types can contain other record types
you can have nested with statements like
with record1 do
with record2 do
with record3 do
statement
or you can use the following shorthand
with record1, record2, record3 do
statement
The syntax for the with statement is given below:
with-statement = 'with' record-variable-list 'do' statement
record-variable-list = record-variable { ';' record-variable }
---------------------
10 Program parameters
---------------------
Program parameters are identifiers which appear after the program name
(placed between parentheses). In addition to appearing after the program
name, most program parameters must also appear in a global variable
declaration. Two special program parameters "input" and "output" are
the exceptions to this rule. The appearance of the two special program
parameters, after the program name, automatically declares them as two
special file variables which reference the standard-input and
standard-output streams.
You can use program parameters to access command-line arguments passed to
your program (see also extended procedures "paramcount" and "paramstr"). For
example suppose you want to write a program to append two files together,
writing the appended files to a third file, then you might write a program
similar to the sample program below.
(**********************************************************************
** This program appends two files together, writing the appended files
** out to a third file.
*)
program append(in1, in2, out, output);
type
char_file = file of char;
var
in1 : char_file; (* first input file *)
in2 : char_file; (* second input file *)
out : char_file; (* output file *)
(***************************************************************
** PURPOSE: Writes copies the contents of one file into another.
** ARGUMENTS:
** 'f' - the input file
** 'g' - the output file
** NOTES: It is up to the caller to open and close the files.
*)
procedure WriteFile(var f, g: char_file);
var
c : char;
begin
while not eof(f) do
begin
read(f, c);
write(g, c)
end
end;
(**********************************************
** PURPOSE: Writes a help screen and then halts
*)
procedure syntax;
begin
writeln('Appends two files together and writes the output to a third file');
writeln('Syntax');
writeln(' ivm append in1 in2 out');
writeln('where "in1" is the first input file');
writeln('and "in2" is the second input file');
writeln('and "out" is the output file');
halt
end;
begin
if paramcount <> 3 then
syntax;
rewrite(out);
reset(in1);
WriteFile(in1, out);
close(in1);
reset(in2);
WriteFile(in2, out);
close(in2)
close(out);
end.
The first thing to notice about this program is the line below:
program append(in1, in2, out, output);
Here four program parameters are being used "in1", "in2", "out", and "output".
The first program parameter "in1" accesses the first command-line argument
The second program parameter "in2" accesses the second command-line argument.
The third program parameter "out" accesses the third command-line argument.
The fourth program parameter "output" declares the special file variable
which references the standard-output stream, and has nothing to do with
command-line arguments. "output" does not have to be the last program
parameter, it can be used in the first, or second or any position. Since
"output" does not access any command-line arguments it can appear in any
position (not just the fourth and last position) without disturbing the
command-line arguments accessed by the other program parameters. In other
words all of the following are equivalent
program append(output, in1, in2, out);
or
program append(in1, output, in2, out);
or
program append(in1, in2, output, out);
or
program append(in1, in2, out, output);
And in each of the four cases "in1" accesses the first command-line argument
and "in2" accesses the second command-line argument
and "out" accesses the third command-line argument.
The second thing to notice about the program are the following lines.
var
in1 : char_file; (* first input file *)
in2 : char_file; (* second input file *)
out : char_file; (* output file *)
Here the program parameters (except for "output") appear in global variable
declarations as required. They are declared to be variables of type
"char_file" which has been declared to be "file of char". Now since they are
declared to be file variables it means that the command-line arguments
accessed specify the names of the external files associated with the file
variables. What this means is that if the file variables are opened (using
"reset", "rewrite", or "append") then the external file which is opened is
the one specified by the command-line argument accessed.
For example if the program is run with the line
ivm append x.txt y.txt a:\z.txt
then when "in1" is opened the file "x.txt" is opened
and when "in2" is opened the file "y.txt" is opened
and when "out" is opened the file "a:\z.txt" is opened.
The final thing to notice about the program are the following lines.
if paramcount <> 3 then
syntax;
These lines cause the procedure "syntax" to be called if the number of
command-line arguments is not 3. These lines are intended to prevent
problems if the user does not enter 3 command-line arguments.
Suppose for example that this program was run with no command-line arguments.
The first program argument "in1" will access the first command-line argument
which does not exist so the empty string will specify the external file
associated with this file variable. Similarly the empty string will specify
the external files associated with the file variables "in2" and "out".
You might ask what happens if you open a file variable associated with an
external file specified by an empty string? Well, if you open such a
file variable for reading (with "reset") then the external file opened
is the standard input stream. If you open such a file for writing
(with "rewrite" or "append") then the external file opened is the standard
output stream.
I didn't want this effect when I wrote the sample program above so I
inserted the lines
if paramcount <> 3 then
syntax;
to avoid this.
So far I have described how file-type program parameters are handled.
You can also use string-type program parameters. They also access the
command-line arguments, but in a different way. The command-line
argument accessed is simply assigned to the string-type program parameter.
If you use program parameters other than file-type or string-type then
the command-line argument is ignored. The compiler will issue a warning,
that the command-line argument has an invalid type, but otherwise do
nothing.
For example look at this rather strange program.
program strange(f, s1, dummy, s2);
var
f : text;
s1, s2 : string;
dummy : real;
begin
rewrite(f);
writeln(f, s1);
writeln(f, s2)
end.
If you compile it you will get some warnings but ignore them.
If you run the program with
ivm strange out.txt first skip second
then the first program parameter "f" will access "out.txt", and since
"f" is a file-type program argument when "rewrite" is used on "f" the
file "out.txt" will be opened for writing.
The second program parameter "s1" will access "first", and since this
is a string-type program argument then "first" will be assigned to "s1".
The third program parameter "dummy" is not a file-type or string-type
program parameter so the third command-line argument "skip" will be
ignored.
The fourth program parameter "s2" will access "second", and since this
is a string-type program argument then "second" will be assigned to "s2".
So the effect of the following three lines
rewrite(f);
writeln(f, s1);
writeln(f, s2)
is that a text file "out.txt" is opened and two lines are written to it.
The first line will be "first" and the second will be "second".
-------------------------------
Appendix A. Irie Pascal Grammar
-------------------------------
The start symbol for this grammar is "program".
actual-parameter = expression |
variable-access |
procedure-identifier |
function-identifier
omitted-parameter
actual-parameter-list = '(' actual-parameter { ',' actual-parameter } ')'
adding-operator = '+' | '-' | 'or' | 'or_else' | 'xor'
array-type = 'array' '[' index-type-list ']' 'of' component-type
assignment-statement = variable-access ':=' expression
block = declarative-part statement-part
buffer-variable = file-variable '^' | file-variable '@'
case-body = case-list-elements [ [ ';' ] case-statement-completer ] |
case-statement-completer
case-constant = ordinal-constant
case-constant-list = case-specifier { ',' case-specifier }
case-index = ordinal-expression
case-list-element = case-constant-list ':' statement
case-list-elements = case-list-element { ';' case-list-element }
case-specifier = case-constant [ '..' case-constant ]
case-statement = 'case' case-index case-body [ ';' ] 'end'
case-statement-completer = 'otherwise' statement-sequence
component-type = type-denoter
component-variable = indexed-variable | field-designator
compound-statement = 'begin' statement-sequence 'end'
conditional-statement = if-statement |
case-statement
constant = integer | real | character-literal | string-literal |
constant-identifier
constant-declaration = identifier '=' constant
constant-declaration-group =
'const' constant-declaration ';' { constant-declaration ';' }
control-variable = variable-identifier
declarative-part = { pre-declaration } { sub-block-declaration }
domain-type = type-identifier
else-part = 'else' statement
empty-statement =
entire-variable = variable-identifier
expression = shift-expression [ relational-operator shift-expression]
factor = [sign] unsigned-constant |
[sign] variable-access |
[sign] '(' expression ')' |
function-designator |
'not' factor |
set-constructor
field-designator = record-variable '.' field-specifier |
field-designator-identifier
field-designator-identifier = identifier
field-list = fixed-part ';' variant-part [ ';' ] |
fixed-part [ ';' ] |
variant-part [ ';' ] |
empty
field-specifier = field-identifier
file-type = 'file' 'of' component-type
final-value = ordinal-expression
fixed-part = record-section { ';' record-section }
for-statement =
'for' control-variable ':=' initial-value ('to' | 'downto') final-value
'do' statement
function-designator = function-identifier [ actual-parameter-list ]
goto-statement = 'goto' label
identified-variable = pointer-variable '^' | pointer-variable '@'
identifier-list = identifier { ',' identifier }
if-statement = 'if' boolean-expression then-part [ else-part ]
indexed-variable =
array-variable '[' index-expression { ',' index-expression } ']'
index-type = ordinal-type
index-type-list = index-type { ',' index-type }
initial-value = ordinal-expression
label = digit-sequence | identifier
label-declaration-group = 'label' label { ',' label } ';'
list-type = 'list' 'of' component-type
member-designator = expression [ '..' expression ]
multiplying-operator = '*' | '/' | 'div' | 'mod' | 'and' | 'and_then'
new-ordinal-type = enumerated-type | subrange-type
new-pointer-type = '^' domain-type |
'@' domain-type
new-structured-type = [ 'packed' ] array-type |
[ 'packed' ] record-type |
[ 'packed' ] set-type |
[ 'packed' ] file-type |
[ 'packed' ] list-type |
string-type
new-type = new-ordinal-type | new-structured-type | new-pointer-type
omitted-parameter =
ordinal-type = new-ordinal-type | ordinal-type-identifier
pre-declaration = label-declaration-group |
constant-declaration-group |
type-declaration-group |
variable-declaration-group
procedure-identifier = identifier
procedure-statement = procedure-identifier
(
[ actual-parameter-list ] |
read-parameter-list |
readln-parameter-list |
write-parameter-list |
writeln-parameter-list
)
program = 'program' program-name [ '(' program-args ')' ] ';' block '.'
program-args = identifier-list
read-parameter-list =
'(' [ file-variable ',' ] variable-access { ',' variable-access } ')'
readln-parameter-list =
[ '(' ( file-variable | variable-access ) { ',' variable-access } ')' ]
record-section = identifier-list ':' type-denoter
record-type = 'record' field-list 'end'
record-variable-list = record-variable { ';' record-variable }
relational-operator = '=' | '<>' | '<' | '<=' | '>' | '>=' | 'in'
repeat-statement = 'repeat' statement-sequence 'until' boolean-expression
repetitive-statement = repeat-statement |
while-statement |
for-statement
set-constructor = '[' [ member-designator { ',' member-designator } ] ']'
set-type = 'set' 'of' ordinal-type
shift-expression = simple-expression [ shift-operator simple-expression]
shift-operator = 'shl' | shr'
sign = '+' | '-'
simple-expression = term { adding-operator term }
simple-statement = empty-statement |
assignment-statement |
procedure-statement |
goto-statement
size = integer
statement = [ label ':' ] ( simple-statement | structured-statement )
statement-part = compound-statement
statement-sequence = statement { ';' statement }
string-type = 'string' |
'string' '[' size ']' |
'string' '(' size ')'
structured-statement = compound-statement |
conditional-statement |
repetitive-statement |
with-statement
term = factor { multiplying-operator factor }
then-part = 'then' statement
type-declaration = identifier '=' type-denoter
type-declaration-group =
'type' identifier '=' type-declaration ';' { type-declaration ';' }
type-denoter = type-identifier | new-type
type-identifier = identifier
unsigned-constant = unsigned-integer |
unsigned-real |
character-string |
constant-identifier |
'nil'
variable-access = entire-variable |
component-variable |
identified-variable |
buffer-variable
variable-declaration = identifier-list ':' type-denoter
variable-declaration-group =
'var' variable-declaration { ';' variable-declaration }
variant = case-constant-list ':' '(' field-list ')'
variant-body = variant-list [ [;] variant-part-completer ] |
variant-part-completer
variant-list = variant { ';' variant }
variant-part = 'case' variant-selector 'of' variant-body
variant-part-completer = 'otherwise' '(' field-list ')'
variant-selector = [ identifier ':' ] ordinal-type-identifier
while-statement = 'while' boolean-expression 'do' statement
with-statement = 'with' record-variable-list 'do' statement
writeln-parameter-list =
[ '(' ( file-variable | write-parameter ) { ',' write-parameter } ')' ]
write-parameter = expression [ ':' expression [ ':' expression ] ]
write-parameter-list =
'(' [ file-variable ',' ] write-parameter { ',' write-parameter } ')'
-------------------------------------------------------------
Appendix B. Extensions to Pascal as specified by ISO/IEC 7185
-------------------------------------------------------------
Irie Pascal supports a number of extensions to Standard Pascal.
Some of these extensions were added for compatibility with Turbo Pascal and
Extended Pascal, while others were added because I thought they might be
useful.
Extensions can be enabled/disabled using the -E compiler option.
------------------------
B.1 Relaxed declarations
------------------------
Standard Pascal requires that all declarations/definitions of the same
kind must be made together in a single group and that the groups must
appear in a specific order. The order required by Standard Pascal is:
Label declaration group
Constant definition group
Type definition group
Variable declaration group
sub-block declaration group
When "relaxed declarations" is enabled there can be more than one of each
kind of group and groups can appear in any order except that the
sub-block declaration group must be last.
So if "relaxed declarations" is enabled then the following program is legal,
program summing(output);
const
first = 1;
last = 100;
type
num = first..last;
var
i : num;
type
atype = array[first..last] of integer;
var
a : atype;
sum : integer;
begin
sum := 0;
for i := first to last do
begin
sum := sum + i;
a[i] := sum
end;
for i := last downto first do
writeln(i, a[i]);
end.
even though it has two type definition groups
"type num = first..last;"
and
"type atype = array[first..last] of integer;"
and two variable declaration groups
"var i : num;"
and
"var a : atype; sum : integer;"
In Standard Pascal or with "relaxed declarations" disabled you would have to
combine these groups so you would have the following
program summing(output);
const
first = 1;
last = 100;
type
num = first..last;
atype = array[first..last] of integer;
var
i : num;
a : atype;
sum : integer;
begin
sum := 0;
for i := first to last do
begin
sum := sum + i;
a[i] := sum
end;
for i := last downto first do
writeln(i, a[i]);
end.
-------------------
B.2 Constant ranges
-------------------
You can use constant ranges to specify a number of consecutive case
constants.
To use a constant range you specify the first constant, and the last
constant, separated by '..' as follows:
first..last
You could use the constant range
1..5
to specify the following constants
1, 2, 3, 4, 5
For example suppose "c" is a char variable and you want to use a
case statement to write the word "Letter" if "c" contains a letter, and
the word "Digit" if "c" contains a digit, then you could specify each
constant individually as follows:
case c of
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
: write('Letter');
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
: write('Digit');
end;
Or you could use constant ranges like the following:
case c of
'a'..'z', 'A'..'Z'
: write('Letter');
'0'..'9'
: write('Digit');
end;
Constant ranges can be used in case statements, like in the example above,
and in variant records.
-------------
B.3 Otherwise
-------------
You can use the keyword "otherwise" in case statements and variant records
to specify "all values that haven't been used yet". You can also use
"else" instead of "otherwise" (this feature was added in order to improve
compatibility with Turbo Pascal).
For example in the following variant record
type
character = record
case c : char of
'a'..'z', 'A'..'Z'
: (vowel : Boolean);
'0'..'9'
: (value : integer);
otherwise
();
end;
when "otherwise" is used, the following values have already been specified
'a'..'z', 'A'..'Z', and '0'..'9'
so otherwise specifies all character values except
'a'..'z', 'A'..'Z', and '0'..'9'
------------------------------------
B.4 Relaxed parameter list congruity
------------------------------------
Standard Pascal says the following parameter lists
(VAR a, b : integer)
and
(VAR c : integer; VAR d : integer)
are not congruous even though the individual parameters are congruous
because Standard Pascal compares formal parameter sections.
So in the example above the parameter lists are not congruous for two
reasons:
1) The first parameter list has one formal parameter section
"VAR a, b : integer"
while the second parameter list has two formal parameter section
"VAR c : integer" and "VAR d : integer"
2) The individual parameter sections are not congruous
(i.e.. "VAR a, b : integer" is not congruous with "VAR c : integer")
Irie Pascal checks for parameter list congruity by comparing the
individual parameters without regard to the formal-parameter-sections.
So the example above would be considered congruous since
"a" and "c" are both integer variable parameters
and
"b" and "d" are both integer variable parameters
Parameter list congruity becomes important when passing functions/procedures
since the parameter list of the actual function/procedure parameter must be
congruous with the parameter list of the corresponding formal
function/procedure parameter.
Relaxed parameter list congruity can not be disabled.
--------------------------------
B.5 Non-numeric statement labels
--------------------------------
Irie Pascal supports non-numeric statement labels.
For example in the following program "loop" is used as a statement label.
program name(output);
label loop;
var
i : integer;
begin
i := 1;
loop:
writeln(i);
i := i + 1;
if i <= 20 then goto loop;
end.
------------------------------
B.6 Underscores in identifiers
------------------------------
Irie Pascal supports identifiers which contain and/or start with
underscores ("_").
----------------------------
B.7 Binary integer constants
----------------------------
Binary integer constants begin with "%", and are followed by one or
more binary digits.
The following are examples of valid binary constants
%0 %1 %01110101010101010111101
The following are not valid binary constants
%2 % %151 %g
---------------------------------
B.8 Hexadecimal integer constants
---------------------------------
Hexadecimal integer constants begin with "$", and are followed by one or
more hexadecimal digits.
The following are examples of valid hexadecimal integer constants
$9 $A123 $ffff
The following is not a valid hexadecimal integer constant
$abgd
since "g" is not a hexadecimal integer constants.
-------------------------------------------
B.9 Input and Output automatically declared
-------------------------------------------
Standard (ISO/IEC 7185) Pascal specifies that whenever the required
identifiers "Input" and "Output" are referenced in a program that they
must by declared (i.e. appear as program parameters). However because
some Pascal compilers do not enforce this requirement many Pascal programs
do not meet this specification. In order to allow Irie Pascal to compile
these programs without requiring the user to insert "Input" and "Output"
into the program parameter list, I decided that by default Irie Pascal
should automatically declare Input and Output.
---------------------------
B.10 Double-quoted literals
---------------------------
You can use double quotation marks to form character and string literals.
For example you could use
"Hello world"
instead of
'Hello world'
Double-quoted literals can be useful if you want to create literals with
single quotes in them since you don't have to use two single quotes to
represent one single quote.
For example you could use
"Don't go away"
which is equivalent to
'Don''t do away'
----------------------
B.11 and_then operator
----------------------
The "and_then" operator is similar to the "and" operator except that
short-circuit evaluation is always used for "and_then" regardless of
the setting of the "sc" compiler option.
See "8.1.7 And_Then Operator" for more information.
---------------------
B.12 or_else operator
---------------------
The "or_else" operator is similar to the "or" operator except that
short-circuit evaluation is always used for "or_else" regardless of
the setting of the "sc" compiler option.
See "8.1.11 Or_Else Operator" for more information.
----------------------
B.13 Bitwise operators
----------------------
Irie Pascal defines several bitwise operators.
-------------------
B.13.1 shl operator
-------------------
The "shl" operator performs a left bit-shift, and returns the result of
this bit-shift. The left operand is the integer to be shifted, and the
right operand, which is also an integer, specifies the number of bits
to shift.
For example
4 shl 2
is equal to 16,
since 4 shifted left by 2 bits is 16.
-------------------
B.13.2 shr operator
-------------------
The "shr" operator performs a right bit-shift, and returns the result of
this bit-shift. The left operand is the integer to be shifted, and the
right operand, which is also an integer, specifies the number of bits
to shift.
For example
4 shr 2
is equal to 1, since 4 shifted right by 2 bits is 1.
-----------------------------
B.13.3 and (Bitwise) operator
-----------------------------
The bitwise "and" operator takes two integer operands and produces
an integer result. A bit in the result is 1 if the bit in the
corresponding position in the left operand is 1 AND the bit
in the corresponding position in the right operand is 1.
Otherwise the result bit is 0.
For example
5 and 3 = 1
Since
101 (which is 5 in binary)
and 011 (which is 3 in binary)
---------
= 001
---------
NOTE: Bit zero is 1 in the result since bit zero is one in both
the left and right operands. All other bits are zero.
----------------------------
B.13.4 or (Bitwise) operator
----------------------------
The bitwise "or" operator takes two integer operands and produces
an integer result. A bit in the result is 1 if the bit in the
corresponding position in the left operand is 1 OR the bit
in the corresponding position in the right operand is 1 OR
both bits are 1.
Otherwise the result bit is 0.
For example
5 or 3 = 7
Since
101 (which is 5 in binary)
or 011 (which is 3 in binary)
---------
= 111
---------
-----------------------------
B.13.5 not (Bitwise) operator
-----------------------------
The bitwise "not" operator takes an integer operand and produces
an integer result. A bit in the result is 1 if the bit in the
corresponding position in the operand is 0. A bit in the result
is 0 if the bit in the corresponding position in the operand is 1.
For example
not 1 = -2
Since
not 00000000 00000000 00000000 00000001 = 1
-----------------------------------------
11111111 11111111 11111111 11111110 = -2
-----------------------------
B.13.6 xor (Bitwise) operator
-----------------------------
The bitwise "xor" operator takes two integer operands and produces
an integer result. A bit in the result is 1 either the bit in the
corresponding position in the left operand is 1 OR the bit
in the corresponding position in the right operand is 1, but not
both. Otherwise the result bit is 0.
For example
5 xor 3 = 6
Since
101 (which is 5 in binary)
xor 011 (which is 3 in binary)
---------
= 110
---------
-----------------------
B.14 Extended constants
-----------------------
Irie Pascal defines a number of built-in constants which are
not part of Standard Pascal. The constants are referred to
here as extended constants.
--------------
B.14.1 maxchar
--------------
Irie Pascal defines "maxchar" which is a built-in character constant,
whose value is the maximum character value allowed.
Syntax: maxchar
------------
B.14.2 usr_r
------------
Irie Pascal defines "usr_r" which is a built-in integer constant.
You can use this constant with the "mkdir" procedure to specify
that the directory owner has read permission.
You can also "or" this constant with a file mode to determine
if the file owner has read permission.
Syntax: usr_r
------------
B.14.3 usr_w
------------
Irie Pascal defines "usr_w" which is a built-in integer constant.
You can use this constant with the "mkdir" procedure to specify
that the directory owner has write permission.
You can also "or" this constant with a file mode to determine
if the file owner has write permission.
Syntax: usr_w
------------
B.14.4 usr_x
------------
Irie Pascal defines "usr_x" which is a built-in integer constant.
You can use this constant with the "mkdir" procedure to specify
that the directory owner has execute permission.
You can also "or" this constant with a file mode to determine
if the file owner has execute permission.
Syntax: usr_x
------------
B.14.5 grp_r
------------
Irie Pascal defines "grp_r" which is a built-in integer constant.
You can use this constant with the "mkdir" procedure to specify
that the directory owner's group has read permission.
You can also "or" this constant with a file mode to determine
if the file owner's group has read permission.
Syntax: grp_r
------------
B.14.6 grp_w
------------
Irie Pascal defines "grp_w" which is a built-in integer constant.
You can use this constant with the "mkdir" procedure to specify
that the directory owner's group has write permission.
You can also "or" this constant with a file mode to determine
if the file owner's group has write permission.
Syntax: grp_w
------------
B.14.7 grp_x
------------
Irie Pascal defines "grp_x" which is a built-in integer constant.
You can use this constant with the "mkdir" procedure to specify
that the directory owner's group has execute permission.
You can also "or" this constant with a file mode to determine
if the file owner's group has execute permission.
Syntax: grp_x
------------
B.14.8 oth_r
------------
Irie Pascal defines "oth_r" which is a built-in integer constant.
You can use this constant with the "mkdir" procedure to specify
that (the world) everyone has read permission.
You can also "or" this constant with a file mode to determine
if (the world) everyone has read permission.
Syntax: oth_r
------------
B.14.9 oth_w
------------
Irie Pascal defines "oth_w" which is a built-in integer constant.
You can use this constant with the "mkdir" procedure to specify
that (the world) everyone has write permission.
You can also "or" this constant with a file mode to determine
if (the world) everyone has write permission.
Syntax: oth_w
-------------
B.14.10 oth_x
-------------
Irie Pascal defines "oth_x" which is a built-in integer constant.
You can use this constant with the "mkdir" procedure to specify
that (the world) everyone has execute permission.
You can also "or" this constant with a file mode to determine
if (the world) everyone has execute permission.
Syntax: oth_x
---------------
B.14.11 dir_bit
---------------
Irie Pascal defines "dir_bit" which is a built-in integer constant.
You can "or" this constant with a file mode to determine if the
file is a directory.
Syntax: dir_bit
--------------------
B.14.12 platform_dos
--------------------
Irie Pascal defines "platform_dos" which is a built-in integer constant.
You can compare this constant with the value returned by the "platform"
function to determine if your program is running under dos.
--------------------
B.14.13 platform_os2
--------------------
Irie Pascal defines "platform_os2" which is a built-in integer constant.
You can compare this constant with the value returned by the "platform"
function to determine if your program is running under OS/2.
----------------------
B.14.14 platform_win32
----------------------
Irie Pascal defines "platform_win32" which is a built-in integer constant.
You can compare this constant with the value returned by the "platform"
function to determine if your program is running under WIN32.
----------------------
B.14.15 platform_linux
----------------------
Irie Pascal defines "platform_linux" which is a built-in integer constant.
You can compare this constant with the value returned by the "platform"
function to determine if your program is running under Linux.
---------------------
B.14.16 platform_fbsd
---------------------
Irie Pascal defines "platform_fbsd" which is a built-in integer constant.
You can compare this constant with the value returned by the "platform"
function to determine if your program is running under FreeBSD.
----------------------
B.14.17 platform_error
----------------------
Irie Pascal defines "platform_error" which is a built-in integer constant.
You can compare this constant with the value returned by the "platform"
function to determine if the call to "platform" failed.
------------------
B.14.18 appendmode
------------------
Irie Pascal defines "appendmode" which is a built-in integer constant.
You can use this constant with the "open" function to specify that the
file should be opened in append mode.
----------------
B.14.19 readmode
----------------
Irie Pascal defines "readmode" which is a built-in integer constant.
You can use this constant with the "open" function to specify that the
file should be opened for reading (i.e. input). You can combine
(with "+" or "or") this constant with "writemode" to specify that the
file should be opened for both reading and writing.
-----------------
B.14.20 writemode
-----------------
Irie Pascal defines "writemode" which is a built-in integer constant.
You can use this constant with the "open" function to specify that the
file should be opened for writing (i.e. output). You can combine
(with "+" or "or") this constant with "readmode" to specify that the
file should be opened for both reading and writing.
-------------------
B.15 Extended types
-------------------
Irie Pascal defines a number of extended types
(i.e. built-in types that are not a part of Standard Pascal).
----------
B.15.1 dir
----------
Irie Pascal defines a type identifier called "dir" which is the
type of directory variables, which are used in the
directory manipulation procedures.
See "7.2.6 closedir", "7.2.27 opendir", "7.2.35 readdir", and
"7.2.39 rewinddir".
---------------
B.15.2 filename
---------------
Irie Pascal defines a type identifier called "filename" which is the
string type most suitable for variables used to store filenames.
Syntax: filename
For example to declare a variable to store filenames use
var
name : filename;
NOTE: You can also use string types such as
var
name : packed array[1..N] of char;
or
name : string;
But I recommend you use "filename" since this type is likely to be
the most suitable type for storing filenames.
-----------
B.15.3 list
-----------
Irie Pascal defines a new keyword "list" in order to provide support
for lists. To create a list type use the syntax below.
Syntax: [packed] list of Type
where
"Type" is the type of the components in the list.
If you use "packed" then the list is likely to be more efficient in
terms of memory but less efficient in terms of speed.
You must use "new" to initialize a list variable before you use it.
The syntax is:
new(list-variable)
You can use "dispose" to release the memory used by a list variable
after you have finished with it. The syntax is:
dispose(list-variable)
You can use "insert" to add components to a list variable.
You can use "delete" to remove components from a list variable.
You can use the "length" function to determine the number of components in a
list variable.
You can access the components of a list variable just like an array
variable. The syntax is
lv '[' p ']'
where
"lv" is the list variable being accessed
"p" is the position of the component being accessed
For example if "i" is an integer and "lv" is a list variable then the
statement below will write each component of "lv".
for i := 1 to length(lv) do
writeln(lv[i])
-------------
B.15.4 string
-------------
Standard Pascal considers packed arrays of char with a lower bound of 1 to
be strings. However these are fixed length strings (i.e.. the only text that
can be assigned to these strings is text of exactly the same length as the
length of the array).
Irie Pascal supports variable length strings using a new type "string".
For example to create a variable length string type called "name" with
a maximum length of 80 use
name = string[80];
or
name = string(80);
To create a variable length string type called "address" with a maximum length
of 255 use
address = string;
or
address = string[255];
or
address = string(255);
The advantage of variable length strings is that any string can be assigned
to them, whether fixed or variable length, as long as the length of the
string being assigned does not exceed the string's maximum length.
Even characters can be assigned to variable length strings.
You can use the "+" operator to perform string concatenation.
-----------------------
B.16 Extended variables
-----------------------
Irie Pascal defines one extended variable
(i.e. a built-in variable that is not a part of Standard Pascal).
---------------
B.16.1 exitcode
---------------
Irie Pascal defines "exitcode" which is a built-in integer variable,
whose value is returned to the calling program when your program exits.
Syntax: exitcode
For example suppose you want to return a value of 1 from your program
(perhaps to indicate that your program detected an error) then you can
use the following code
exitcode := 1;
halt;
NOTE: You can treat "exitcode" like any other integer variable
(i.e. you can assign to it, use it in an expression, pass it as an
argument to a function, etc).
END