|
@@ -34,7 +34,7 @@
|
|
|
\latex{\usepackage{fpc}}
|
|
|
\latex{\usepackage{listings}\blankstringtrue%
|
|
|
\selectlisting{tp}\stringstyle{\ttfamily}\keywordstyle{\bfseries}
|
|
|
-\prelisting{\sffamily}}
|
|
|
+\prelisting{\sffamily\sloppy}}
|
|
|
\html{\input{fpc-html.tex}}
|
|
|
\usepackage{fancyheadings}
|
|
|
\pagestyle{fancy}
|
|
@@ -128,6 +128,8 @@ This means that both the first or second possibility are optional.
|
|
|
|
|
|
Of course, all these elements can be combined and nested.
|
|
|
|
|
|
+\part{The Pascal language}
|
|
|
+
|
|
|
%
|
|
|
% The Pascal language
|
|
|
%
|
|
@@ -1132,7 +1134,7 @@ Var p : array[0..Infinity] of Longint;
|
|
|
The difference is that the former declaration allocates memory for the
|
|
|
pointer only (not for the array), and the second declaration allocates
|
|
|
memory for the entire array. If you use the former, you must allocate memory
|
|
|
-yourself, using the \seef{Getmem} function.
|
|
|
+yourself, using the \seep{Getmem} function.
|
|
|
|
|
|
The reference \var{P\^{}} is then the same as \var{p[0]}. The following program
|
|
|
illustrates this maybe more clear:
|
|
@@ -1271,7 +1273,7 @@ An object is declared just as you would declare a record; except that you
|
|
|
can now declare procedures and fuctions as if they were part of the record.
|
|
|
|
|
|
Objects can ''inherit'' fields and methods from ''parent'' objects. This means
|
|
|
-that you can use these fields and methods as if the were included in the
|
|
|
+that you can use these fields and methods as if they were included in the
|
|
|
objects you declared as a ''child'' object.
|
|
|
|
|
|
Furthermore, you can declare fields, procedures and functions as \var{public}
|
|
@@ -1372,7 +1374,7 @@ It is also possible to use the \var{with} statement with an object instance:
|
|
|
\begin{listing}
|
|
|
With AnObject do
|
|
|
begin
|
|
|
- Afield := 12
|
|
|
+ Afield := 12;
|
|
|
AMethod;
|
|
|
end;
|
|
|
\end{listing}
|
|
@@ -1385,19 +1387,24 @@ identifiers. More about this in \sees{With}
|
|
|
|
|
|
As can be seen in the syntax diagram for an object declaration, \fpc supports
|
|
|
constructors and destructors. You are responsible for calling the
|
|
|
-destructor and constructor explicitly when using objects.
|
|
|
+constructor and the destructor explicitly when using objects.
|
|
|
|
|
|
The declaration of a constructor or destructor is as follows:
|
|
|
|
|
|
\input{syntax/construct.syn}
|
|
|
|
|
|
-A constructor is {\em required} if you use virtual methods.
|
|
|
+A constructor/destructor pair is {\em required} if you use virtual methods.
|
|
|
+
|
|
|
+In the declaration of the object type, you should use a simple identifier
|
|
|
+for the name of the constuctor or destructor. When you implement the
|
|
|
+constructor or destructor, you should use a qulified method identifier,
|
|
|
+i.e. an identifier of the form \var{objectidentifier.methodidentifier}.
|
|
|
|
|
|
\fpc supports also the extended syntax of the \var{New} and \var{Dispose}
|
|
|
-procedures. In case you want to allocate a dynamic varible of an object
|
|
|
+procedures. In case you want to allocate a dynamic variable of an object
|
|
|
type, you can specify the constructor's name in the call to \var{New}.
|
|
|
The \var{New} is implemented as a function which returns a pointer to the
|
|
|
-instantiated object. Given the following declarations :
|
|
|
+instantiated object. Consider the following declarations:
|
|
|
\begin{listing}
|
|
|
Type
|
|
|
TObj = object;
|
|
@@ -1408,7 +1415,7 @@ Type
|
|
|
|
|
|
Var PP : Pobj;
|
|
|
\end{listing}
|
|
|
-Then the following 3 calls are equivalent :
|
|
|
+Then the following 3 calls are equivalent:
|
|
|
\begin{listing}
|
|
|
pp := new (Pobj,Init);
|
|
|
\end{listing}
|
|
@@ -1444,11 +1451,10 @@ given.
|
|
|
|
|
|
\section{Method invocation}
|
|
|
Methods are called just as normal procedures are called, only they have a
|
|
|
-object instance identifier prepended to them
|
|
|
-\seec{Statements}.
|
|
|
+object instance identifier prepended to them (see also \seec{Statements}).
|
|
|
|
|
|
To determine which method is called, it is necessary to know the type of
|
|
|
-method:
|
|
|
+the method. We treat the different types in what follows.
|
|
|
|
|
|
\subsubsection{Static methods}
|
|
|
Static methods are methods that have been declared without a \var{abstract}
|
|
@@ -1460,19 +1466,19 @@ For example, consider the following declarations:
|
|
|
Type
|
|
|
TParent = Object
|
|
|
...
|
|
|
- procedure Method;
|
|
|
+ procedure Doit;
|
|
|
...
|
|
|
end;
|
|
|
- PPArent = ^TParent;
|
|
|
+ PParent = ^TParent;
|
|
|
TChild = Object(TParent)
|
|
|
...
|
|
|
- procedure Method;
|
|
|
+ procedure Doit;
|
|
|
...
|
|
|
end;
|
|
|
PChild = ^TChild;
|
|
|
\end{listing}
|
|
|
As it is visible, both the parent and child objects have a method called
|
|
|
-\var{Draw}. Consider now the following declarations and calls :
|
|
|
+\var{Doit}. Consider now the following declarations and calls:
|
|
|
\begin{listing}
|
|
|
Var ParentA,ParentB : PParent;
|
|
|
Child : PChild;
|
|
@@ -1481,16 +1487,16 @@ Var ParentA,ParentB : PParent;
|
|
|
ParentB := New(PChild,Init);
|
|
|
Child := New(PChild,Init);
|
|
|
|
|
|
- ParentA^.Method;
|
|
|
- ParentB^.Method;
|
|
|
- Child^.Method;
|
|
|
+ ParentA^.Doit;
|
|
|
+ ParentB^.Doit;
|
|
|
+ Child^.Doit;
|
|
|
\end{listing}
|
|
|
-Of the three invocations of \var{Method}, only the last one will call
|
|
|
-\var{TChild.Method}, the other two calls will call \var{TParent.Method}
|
|
|
+Of the three invocations of \var{Doit}, only the last one will call
|
|
|
+\var{TChild.Doit}, the other two calls will call \var{TParent.Doit}.
|
|
|
This is because for static methods, the compiler determines at compile
|
|
|
time which method should be called. Since \var{ParentB} is of type
|
|
|
-\var{TPArent}, the compiler decides that it must be called with
|
|
|
-\var{TParent.Method}, even though it will be created as a \var{TChild}.
|
|
|
+\var{TParent}, the compiler decides that it must be called with
|
|
|
+\var{TParent.Doit}, even though it will be created as a \var{TChild}.
|
|
|
|
|
|
There may be times when you want the method that is actually called to
|
|
|
depend on the actual type of the object at run-time. If so, the method
|
|
@@ -1502,18 +1508,19 @@ To remedy the situation in the previous section, \var{virtual} methods are
|
|
|
created. This is simply done by appending the method declaration with the
|
|
|
\var{virtual} modifier.
|
|
|
|
|
|
-Going back to the provious example, consider the following alterbative
|
|
|
+Going back to the previous example, consider the following alternative
|
|
|
declaration:
|
|
|
\begin{listing}
|
|
|
Type
|
|
|
TParent = Object
|
|
|
...
|
|
|
- procedure Method;virtual;
|
|
|
+ procedure Doit;virtual;
|
|
|
...
|
|
|
end;
|
|
|
+ PParent = ^TParent;
|
|
|
TChild = Object(TParent)
|
|
|
...
|
|
|
- procedure Method;virtual;
|
|
|
+ procedure Doit;virtual;
|
|
|
...
|
|
|
end;
|
|
|
PChild = ^TChild;
|
|
@@ -1528,46 +1535,46 @@ Var ParentA,ParentB : PParent;
|
|
|
ParentB := New(PChild,Init);
|
|
|
Child := New(PChild,Init);
|
|
|
|
|
|
- ParentA^.Method;
|
|
|
- ParentB^.Method;
|
|
|
- Child^.Method;
|
|
|
+ ParentA^.Doit;
|
|
|
+ ParentB^.Doit;
|
|
|
+ Child^.Doit;
|
|
|
\end{listing}
|
|
|
Now, different methods will be called, depending on the actual run-time type
|
|
|
of the object. For \var{ParentA}, nothing changes, since it is created as
|
|
|
-a \var{TPArent} instance. For \var{Child}, the situation also doesn't
|
|
|
+a \var{TParent} instance. For \var{Child}, the situation also doesn't
|
|
|
change: it is again created as an instance of \var{TChild}.
|
|
|
|
|
|
For \var{ParentB} however, the situation does change: Even though it was
|
|
|
-declared as a var{TPArent}, it is created as an instance of \var{TChild}.
|
|
|
-Now, when the program runs, before calling the \var{Method}, the program
|
|
|
+declared as a \var{TParent}, it is created as an instance of \var{TChild}.
|
|
|
+Now, when the program runs, before calling \var{Doit}, the program
|
|
|
checks what the actual type of \var{ParentB} is, and only then decides which
|
|
|
method must be called. Seeing that \var{ParentB} is of type \var{TChild},
|
|
|
-\var{TChild.Method} will be called.
|
|
|
+\var{TChild.Doit} will be called.
|
|
|
|
|
|
The code for this run-time checking of the actual type of an object is
|
|
|
inserted by the compiler at compile time.
|
|
|
|
|
|
-The \var{TChild.Method} is said to {\em override} the \var{TParent.Method}.
|
|
|
-It is possible to acces the \var{TPArent.Method} from within the
|
|
|
-var{TChild.Method}, with the \var{inherited} keyword:
|
|
|
+The \var{TChild.Doit} is said to {\em override} the \var{TParent.Doit}.
|
|
|
+It is possible to acces the \var{TParent.Doit} from within the
|
|
|
+var{TChild.Doit}, with the \var{inherited} keyword:
|
|
|
\begin{listing}
|
|
|
-TChild.Method;
|
|
|
+Procedure TChild.Doit;
|
|
|
|
|
|
begin
|
|
|
- inherited Method;
|
|
|
+ inherited Doit;
|
|
|
...
|
|
|
end;
|
|
|
\end{listing}
|
|
|
-In the above example, when var{TChild.Method} is called, the first thing it
|
|
|
-does is call \var{TPArent.Method}. You cannot use the inherited keyword on
|
|
|
+In the above example, when \var{TChild.Doit} is called, the first thing it
|
|
|
+does is call \var{TParent.Doit}. You cannot use the inherited keyword on
|
|
|
static methods, only on virtual methods.
|
|
|
|
|
|
\subsubsection{Abstract methods}
|
|
|
|
|
|
An abstract method is a special kind of virtual method. A method can not be
|
|
|
-abstract if it is not virtual. You cannot create an instance of an object
|
|
|
-that has an abstract method. The reason is obvious: there is no method where
|
|
|
-the compiler could jump to !
|
|
|
+abstract if it is not virtual (this is not obvious from the syntax diagram).
|
|
|
+You cannot create an instance of an object that has an abstract method.
|
|
|
+The reason is obvious: there is no method where the compiler could jump to !
|
|
|
|
|
|
A method that is declared \var{abstract} does not have an implementation for
|
|
|
this method. It is up to inherited objects to override and implement this
|
|
@@ -1576,13 +1583,13 @@ method. Continuing our example, take a look at this:
|
|
|
Type
|
|
|
TParent = Object
|
|
|
...
|
|
|
- procedure Method;virtual;
|
|
|
+ procedure Doit;virtual;abstract;
|
|
|
...
|
|
|
end;
|
|
|
PParent=^TParent;
|
|
|
TChild = Object(TParent)
|
|
|
...
|
|
|
- procedure Method;virtual;
|
|
|
+ procedure Doit;virtual;
|
|
|
...
|
|
|
end;
|
|
|
PChild = ^TChild;
|
|
@@ -1597,9 +1604,9 @@ Var ParentA,ParentB : PParent;
|
|
|
ParentB := New(PChild,Init);
|
|
|
Child := New(PChild,Init);
|
|
|
|
|
|
- ParentA^.Method;
|
|
|
- ParentB^.Method;
|
|
|
- Child^.Method;
|
|
|
+ ParentA^.Doit;
|
|
|
+ ParentB^.Doit;
|
|
|
+ Child^.Doit;
|
|
|
\end{listing}
|
|
|
First of all, Line 4 will generate a compiler error, stating that you cannot
|
|
|
generate instances of objects with abstract methods: The compiler has
|
|
@@ -1622,7 +1629,7 @@ For objects, only 2 visibility specifiers exist : \var{private} and
|
|
|
\var{public}. If you don't specify a visibility specifier, \var{public}
|
|
|
is assumed.
|
|
|
|
|
|
-both methods and fields can be hidden from a programmer by putting them
|
|
|
+Both methods and fields can be hidden from a programmer by putting them
|
|
|
in a \var{private} section. The exact visibility rule is as follows:
|
|
|
|
|
|
\begin{description}
|
|
@@ -1652,8 +1659,9 @@ The prototype declaration of a class is as follows :
|
|
|
|
|
|
\input{syntax/typeclas.syn}
|
|
|
|
|
|
-Again, You can repeat as many \var{private} and \var{public} blocks as you
|
|
|
-want. Methods are normal function or procedure declarations.
|
|
|
+Again, You can repeat as many \var{private}, \var{protected}, \var{published}
|
|
|
+and \var{public} blocks as you want.
|
|
|
+Methods are normal function or procedure declarations.
|
|
|
|
|
|
As you can see, the declaration of a class is almost identical to the
|
|
|
declaration of an object. The real difference between objects and classes
|
|
@@ -1720,14 +1728,14 @@ begin
|
|
|
ANobject.AMethod;
|
|
|
\end{listing}
|
|
|
|
|
|
-\subsection{Properties}
|
|
|
+\section{Properties}
|
|
|
|
|
|
Classes can contain properties as part of their fields list. A property
|
|
|
acts like a normal field, i.e. you can get or set it's value, but
|
|
|
allows to redirect the access of the field through functions and
|
|
|
procedures. They provide a means to assiciate an action with an assignment
|
|
|
of or a reading from a class 'field'. This allows for e.g. checking that a
|
|
|
-value is valid when assigning, or, when reading, it allows to constuct the
|
|
|
+value is valid when assigning, or, when reading, it allows to construct the
|
|
|
value on the fly. Moreover, properties can be read-only or write only.
|
|
|
|
|
|
The prototype declaration of a property is as follows:
|
|
@@ -1871,7 +1879,7 @@ As an example, see the following declaration:
|
|
|
\begin{listing}
|
|
|
Type TIntList = Class
|
|
|
Private
|
|
|
- Function GetInt (I : Longint);
|
|
|
+ Function GetInt (I : Longint) : longint;
|
|
|
Function GetAsString (A : String) : String;
|
|
|
Procedure SetInt (I : Longint; Value : Longint;);
|
|
|
Procedure SetAsString (A : String; Value : String);
|
|
@@ -1900,7 +1908,7 @@ AIntList.StrItems[26] := 'zero';
|
|
|
Because the index types are wrong.
|
|
|
|
|
|
Array properties can be declared as \var{default} properties. This means that
|
|
|
-it is not necessary to specifiy the property name when assigning or readin
|
|
|
+it is not necessary to specify the property name when assigning or reading
|
|
|
it. If, in the previous example, the definition of the items property would
|
|
|
have been
|
|
|
\begin{listing}
|
|
@@ -1924,7 +1932,7 @@ cannot redeclare the default property.
|
|
|
Expressions occur in assignments or in tests. Expressions produce a value,
|
|
|
of a certain type.
|
|
|
|
|
|
-Expressions are built with two ocmponents: Operators and their Operands.
|
|
|
+Expressions are built with two components: Operators and their operands.
|
|
|
Usually an operator is binary, i.e. it requires 2 operands. Binary operators
|
|
|
occur always between the operands (as in \var{X/Y}). Sometimes an
|
|
|
operator is unary, i.e. it requires only one argument. A unary operator
|
|
@@ -1991,7 +1999,7 @@ Factors are all other constructions:
|
|
|
|
|
|
\input{syntax/expfact.syn}
|
|
|
|
|
|
-\section{function calls}
|
|
|
+\section{Function calls}
|
|
|
|
|
|
Function calls are part of expressions (although, using extended syntax,
|
|
|
they can be statements too). They are constructed as follows:
|
|
@@ -2062,7 +2070,7 @@ How then, should one compare whether \var{F} points to the function
|
|
|
If F = @AddOne Then
|
|
|
WriteLn ('Functions are equal');
|
|
|
\end{listing}
|
|
|
-The left hand side of the boolean expression is an address. The right and
|
|
|
+The left hand side of the boolean expression is an address. The right hand
|
|
|
side also, and so the compiler compares 2 addresses.
|
|
|
|
|
|
How to compare the values that both functions return ? By adding an empty
|
|
@@ -2096,7 +2104,7 @@ The following are valid set constructors:
|
|
|
|
|
|
\begin{listing}
|
|
|
[today,tomorrow]
|
|
|
-[Monfay..Friday,Sunday]
|
|
|
+[Monday..Friday,Sunday]
|
|
|
[ 2, 3*2, 6*2, 9*2 ]
|
|
|
['A'..'Z','a'..'z','0'..'9']
|
|
|
\end{listing}
|
|
@@ -2131,14 +2139,14 @@ Word(@Buffer)
|
|
|
|
|
|
\section{The @ operator}
|
|
|
|
|
|
-The address operator \var{@} returns the address of a variable or function.
|
|
|
-It is used as follows:
|
|
|
+The address operator \var{@} returns the address of a variable, procedure
|
|
|
+or function. It is used as follows:
|
|
|
|
|
|
\input{syntax/address.syn}
|
|
|
|
|
|
The \var{@} operator returns a typed pointer if the \var{\$T} switch is on.
|
|
|
If the \var{\$T} switch is off then the address operator returns an untyped
|
|
|
-pointer, which is assignent compatible with all pointer types. The type of
|
|
|
+pointer, which is assigment compatible with all pointer types. The type of
|
|
|
the pointer is \var{\^{}T}, where \var{T} is the type of the variable
|
|
|
reference.
|
|
|
|
|
@@ -2201,7 +2209,7 @@ For binary operators, the result type will be integer if both operands are
|
|
|
integer type expressions. If one of the operands is a real type expression,
|
|
|
then the result is real.
|
|
|
|
|
|
-As an exception : division \var{/} results always in real values.
|
|
|
+As an exception : division (\var{/}) results always in real values.
|
|
|
|
|
|
\begin{FPCltable}{ll}{Unary arithmetic operators}{unaroperators}
|
|
|
Operator & Operation \\ \hline
|
|
@@ -2209,7 +2217,7 @@ Operator & Operation \\ \hline
|
|
|
\var{-} & Sign inversion \\ \hline
|
|
|
\end{FPCltable}
|
|
|
|
|
|
-For unary operators, the result type is always equal to th expression type.
|
|
|
+For unary operators, the result type is always equal to the expression type.
|
|
|
|
|
|
The division (\var{/}) and \var{Mod} operator will cause run-time errors if
|
|
|
the second argument is zero.
|
|
@@ -2293,7 +2301,7 @@ The following are valid string operations:
|
|
|
'This is ' + 'VERY ' + 'easy !'
|
|
|
Dirname+'\'
|
|
|
\end{listing}
|
|
|
-The folowwing is not:
|
|
|
+The following is not:
|
|
|
\begin{listing}
|
|
|
Var Dirname = Pchar;
|
|
|
...
|
|
@@ -2301,7 +2309,7 @@ Var Dirname = Pchar;
|
|
|
\end{listing}
|
|
|
Because \var{Dirname} is a null-terminated string.
|
|
|
|
|
|
-\subsection{Set operations}
|
|
|
+\subsection{Set operators}
|
|
|
|
|
|
The following operations on sets can be performed with operators:
|
|
|
Union, difference and intersection. The operators needed for this are listed
|
|
@@ -2313,7 +2321,7 @@ Operator & Action \\ \hline
|
|
|
\var{*} & Intersection \\ \hline
|
|
|
\end{FPCltable}
|
|
|
|
|
|
-The set typed of the operands must be the same, or an error will be
|
|
|
+The set type of the operands must be the same, or an error will be
|
|
|
generated by the compiler.
|
|
|
|
|
|
\subsection{Relational operators}
|
|
@@ -2336,7 +2344,7 @@ and real types in relational expressions.
|
|
|
Comparing strings is done on the basis of their ASCII code representation.
|
|
|
|
|
|
When comparing pointers, the addresses to which they point are compared.
|
|
|
-This also is troe for \var{PChar} type pointers. If you want to compare the
|
|
|
+This also is true for \var{PChar} type pointers. If you want to compare the
|
|
|
strings the \var{Pchar} points to, you must use the \var{StrComp} function
|
|
|
from the \file{strings} unit.
|
|
|
|
|
@@ -2349,7 +2357,7 @@ operand, otherwise it returns \var{False}
|
|
|
|
|
|
The heart of each algorithm are the actions it takes. These actions are
|
|
|
contained in the statements of your program or unit. You can label your
|
|
|
-statements, and jump to them (within certain limits) with var{Goto}
|
|
|
+statements, and jump to them (within certain limits) with \var{Goto}
|
|
|
statements.
|
|
|
|
|
|
This can be seen in the following syntax diagram:
|
|
@@ -2361,10 +2369,13 @@ A label can be an identifier or an integer digit.
|
|
|
\section{Simple statements}
|
|
|
|
|
|
A simple statement cannot be decomposed in separate statements. There are
|
|
|
-basically 3 kinds of simple statements:
|
|
|
+basically 4 kinds of simple statements:
|
|
|
|
|
|
\input{syntax/simstate.syn}
|
|
|
|
|
|
+Of these statements, the {\em raise statement} will be explained in the
|
|
|
+chapter on Exceptions (\seec{Exceptions})
|
|
|
+
|
|
|
\subsection{Assignments}
|
|
|
|
|
|
Assignments give a value to a variable, replacing any previous value the
|
|
@@ -3616,20 +3627,30 @@ serve to clean up memory or close files in case an exception occurs.
|
|
|
code.
|
|
|
\end{description}
|
|
|
|
|
|
+\subsection{The raise statement}
|
|
|
+
|
|
|
The \var{raise} statement is as follows:
|
|
|
-\begin{listing}
|
|
|
- Raise [ExceptionInstance [at Address]];
|
|
|
-\end{listing}
|
|
|
-This statement will raise an exception. If specified, \var{ExceptionInstance}
|
|
|
-must be an initialized instance of a class, which is the raise type. If
|
|
|
-specified, \var{Address} must be an expression that returns an address.
|
|
|
|
|
|
-If \var{ExceptionInstance} is omitted, then the Current exception is
|
|
|
+\input{syntax/raise.syn}
|
|
|
+
|
|
|
+This statement will raise an exception. If it is specified, the exception
|
|
|
+instance must be an initialized instance of a class, which is the raise
|
|
|
+type. The address exception is optional. If itis not specified, the compiler
|
|
|
+will provide the address by itself.
|
|
|
+
|
|
|
+If the exception instance is omitted, then the current exception is
|
|
|
re-raised. This construct can only be used in an exception handling
|
|
|
-block.
|
|
|
+block (see further).
|
|
|
+
|
|
|
+Remark that control {\em never} returns after an exception block. The
|
|
|
+control is transferred to the first \var{try...finally} or
|
|
|
+\var{try...except} statement that is encountered when unwinding the stack.
|
|
|
+If no such statement is found, the \fpc Run-Time Library will generate a
|
|
|
+run-time error 217 (see also \sees{exceptclasses}).
|
|
|
|
|
|
As an example: The following division checks whether the denominator is
|
|
|
zero, and if so, raises an exception of type \var{EDivException}
|
|
|
+
|
|
|
\begin{listing}
|
|
|
Type EDivException = Class(Exception);
|
|
|
|
|
@@ -3642,35 +3663,48 @@ begin
|
|
|
end;
|
|
|
\end{listing}
|
|
|
The class \var{Exception} is defined in the \file{Sysutils} unit of the rtl.
|
|
|
+(\sees{exceptclasses})
|
|
|
+
|
|
|
+\section{The try...except statement}
|
|
|
+
|
|
|
+A \var{try...except} exception handling block is of the following form :
|
|
|
+
|
|
|
+\input{syntax/try.syn}
|
|
|
+
|
|
|
+If no exception is raised during the execution of the \var{statement list},
|
|
|
+then all statements in the list will be executed sequentially, and the
|
|
|
+except block will be skipped, transferring program flow to the statement
|
|
|
+after the final \var{end}.
|
|
|
|
|
|
-An exception handling block is of the following form :
|
|
|
-\begin{listing}
|
|
|
- Try
|
|
|
- ...Statement List...
|
|
|
- Except
|
|
|
- [On [E:] ExceptionClass do CompoundStatement;]
|
|
|
- [ Default exception handler]
|
|
|
- end;
|
|
|
-\end{listing}
|
|
|
If an exception occurs during the execution of the \var{statement list}, the
|
|
|
-program flow fill be transferred to the except block. There, the type of the
|
|
|
-exception is checked, and if there is a \var{On ExcType} statement where
|
|
|
-\var{ExcType} matches the exception object type, or is a parent type of
|
|
|
-the exception object type, then the statements follwing the corresponding
|
|
|
+program flow fill be transferred to the except block. Statements in the
|
|
|
+statement list between the place where the exception was raised and the
|
|
|
+exception block are ignored.
|
|
|
+
|
|
|
+
|
|
|
+In the exception handling block, the type of the exception is checked,
|
|
|
+and if there is an exception handler where the class type matches the
|
|
|
+exception object type, or is a parent type of
|
|
|
+the exception object type, then the statement following the corresponding
|
|
|
\var{Do} will be executed. The first matching type is used. After the
|
|
|
\var{Do} block was executed, the program continues after the \var{End}
|
|
|
statement.
|
|
|
|
|
|
-The identifier \var{E} is optional, and declares an exception object. It
|
|
|
-can be used to manipulate the exception object in the exception handling
|
|
|
-code. The scope of this declaration is the statement block foillowing the
|
|
|
-\var{Do} keyword.
|
|
|
+The identifier in an exception handling statement is optional, and declares
|
|
|
+an exception object. It can be used to manipulate the exception object in
|
|
|
+the exception handling code. The scope of this declaration is the statement
|
|
|
+block foillowing the \var{Do} keyword.
|
|
|
|
|
|
If none of the \var{On} handlers matches the exception object type, then the
|
|
|
\var{Default exception handler} is executed. If no such default handler is
|
|
|
found, then the exception is automatically re-raised. This process allows
|
|
|
to nest \var{try...except} blocks.
|
|
|
|
|
|
+If, on the other hand, the exception was caught, then the exception object is
|
|
|
+destroyed at the end of the exception handling block, before program flow
|
|
|
+continues. The exception is destroyed through a call to the object's
|
|
|
+\var{Destroy} destructor.
|
|
|
+
|
|
|
As an example, given the previous declaration of the \var{DoDiv} function,
|
|
|
consider the following
|
|
|
\begin{listing}
|
|
@@ -3691,22 +3725,20 @@ A \var{Try...Finally} block ensures that the statements following the
|
|
|
\var{Finally} keyword are guaranteed to be executed, even if an exception
|
|
|
occurs.
|
|
|
|
|
|
-A \var{Try..Finally} block has the following form:
|
|
|
+\section{The try...finally statement}
|
|
|
|
|
|
-\begin{listing}
|
|
|
- Try
|
|
|
- ...Statement List...
|
|
|
- Finally
|
|
|
- [ Finally Statements ]
|
|
|
- end;
|
|
|
-\end{listing}
|
|
|
-If no exception occurs inside the \var{Statement List}, then the program
|
|
|
+A \var{Try..Finally} statement has the following form:
|
|
|
+
|
|
|
+\input{syntax/finally.syn}
|
|
|
+
|
|
|
+If no exception occurs inside the \var{statement List}, then the program
|
|
|
runs as if the \var{Try}, \var{Finally} and \var{End} keywords were not
|
|
|
present.
|
|
|
|
|
|
If, however, an exception occurs, the program flow is immediatly
|
|
|
-transferred to the first statement of the \var{Finally statements}.
|
|
|
-All statements of the \var{Finally Statements} will be executed, and then
|
|
|
+transferred from the point where the excepion was raised to the first
|
|
|
+statement of the \var{Finally statements}.
|
|
|
+All statements after the finally kayword will be executed, and then
|
|
|
the exception will be automatically re-raised. Any statements between the
|
|
|
place where the exception was raised and the first statement of the
|
|
|
\var{Finally Statements} are skipped.
|
|
@@ -3737,6 +3769,8 @@ was raised, and the \var{Close} statement.
|
|
|
If no exception occurred, all file operations will be executed, and the file
|
|
|
will be closed at the end.
|
|
|
|
|
|
+\section{Exception handling nesting}
|
|
|
+
|
|
|
It is possible to nest \var{Try...Except} blocks with \var{Try...Finally}
|
|
|
blocks. Program flow will be done according to a \var{lifo} (last in, first
|
|
|
out) principle: The code of the last encountered \var{Try...Except} or
|
|
@@ -3750,6 +3784,44 @@ handler is installed which ioll show the exception object message, and the
|
|
|
address where the exception occurred, after which the program will exit with
|
|
|
a \var{Halt} instruction.
|
|
|
|
|
|
+\section{Exception classes}
|
|
|
+\label{se:exceptclasses}
|
|
|
+
|
|
|
+The \file{sysutils} unit contains a great deal of exception handling.
|
|
|
+It defines the following exception types:
|
|
|
+\begin{listing}
|
|
|
+ Exception = class(TObject)
|
|
|
+ private
|
|
|
+ fmessage : string;
|
|
|
+ fhelpcontext : longint;
|
|
|
+ public
|
|
|
+ constructor create(const msg : string);
|
|
|
+ constructor createres(indent : longint);
|
|
|
+ property helpcontext : longint read fhelpcontext write fhelpcontext;
|
|
|
+ property message : string read fmessage write fmessage;
|
|
|
+ end;
|
|
|
+
|
|
|
+ ExceptClass = Class of Exception;
|
|
|
+
|
|
|
+ { mathematical exceptions }
|
|
|
+ EIntError = class(Exception);
|
|
|
+ EDivByZero = class(EIntError);
|
|
|
+ ERangeError = class(EIntError);
|
|
|
+ EIntOverflow = class(EIntError);
|
|
|
+ EMathError = class(Exception);
|
|
|
+\end{listing}
|
|
|
+
|
|
|
+The sysutils unit also installs an exception handler. If an exception is
|
|
|
+unhandled by any exception handling block, this handler is called by the
|
|
|
+Run-Time library. Basically, it prints the exception address, and it prints
|
|
|
+the message of the Exception object, and exits with a exit code of 217.
|
|
|
+If the exception object is not a descendent object of the \var{Exception}
|
|
|
+object, then the class name is printed instead of the exception message.
|
|
|
+
|
|
|
+It is recommended to use the Exception object or a descendant class for
|
|
|
+all raise statemnts, since then you can use the message field of the
|
|
|
+exception object.
|
|
|
+
|
|
|
\chapter{Using assembler}
|
|
|
|
|
|
\fpc supports the use of assembler in your code, but not inline
|
|
@@ -3811,7 +3883,8 @@ behaviour as Turbo Pascal.
|
|
|
% System unit reference guide.
|
|
|
%
|
|
|
%\end{document}
|
|
|
-\chapter{Reference : The system unit}
|
|
|
+\part{Reference : The System unit}
|
|
|
+\chapter{The system unit}
|
|
|
\label{ch:refchapter}
|
|
|
|
|
|
The system unit contains the standard supported functions of \fpc. It is the
|
|
@@ -4283,6 +4356,22 @@ of X. If the size of X is 4, then the high word is returned. If the size is
|
|
|
\latex{\inputlisting{refex/ex31.pp}}
|
|
|
\html{\input{refex/ex31.tex}}
|
|
|
|
|
|
+\function{High}{(Type identifier or variable reference)}{Longint}
|
|
|
+{ The return value of \var{High} depends on it's argument:
|
|
|
+\begin{enumerate}
|
|
|
+\item If the argument is an ordinal type, \var{High} returns the lowest value in the range of the given ordinal
|
|
|
+type when it gets.
|
|
|
+\item If the argument is an array type or an array type variable then
|
|
|
+\var{High} returns the highest possible value of it's index.
|
|
|
+\item If the argument is an open array identifier in a function or
|
|
|
+procedure, then \var{High} returns the highest index of the array, as if the
|
|
|
+array has a zero-based index.
|
|
|
+\end{enumerate}
|
|
|
+}{None.}{\seef{High}, \seef{Ord}, \seef{Pred}, \seef{Succ}}
|
|
|
+
|
|
|
+\latex{\inputlisting{refex/ex80.pp}}
|
|
|
+\html{\input{refex/ex80.tex}}
|
|
|
+
|
|
|
\procedure{Inc}{(Var X : Any ordinal type[; Increment : Longint])}
|
|
|
{\var{Inc} increases the value of \var{X} with \var{Increment}.
|
|
|
If \var{Increment} isn't specified, then 1 is taken as a default.}
|
|
@@ -4419,6 +4508,18 @@ occurred.}{None.}{\seef{SetJmp}}
|
|
|
|
|
|
For an example, see \seef{SetJmp}
|
|
|
|
|
|
+\function{Low}{(Type identifier or variable reference)}{Longint}
|
|
|
+{ The return value of \var{Low} depends on it's argument:
|
|
|
+\begin{enumerate}
|
|
|
+\item If the argument is an ordinal type, \var{Low} returns the lowest value in the range of the given ordinal
|
|
|
+type when it gets.
|
|
|
+\item If the argument is an array type or an array type variable then
|
|
|
+\var{Low} returns the lowest possible value of it's index.
|
|
|
+\end{enumerate}
|
|
|
+}{None.}{\seef{High}, \seef{Ord}, \seef{Pred}, \seef{Succ}}
|
|
|
+
|
|
|
+for an example, see \seef{High}.
|
|
|
+
|
|
|
\function{Lowercase}{(C : Char or String)}{Char or String}
|
|
|
{\var{Lowercase} returns the lowercase version of its argument \var{C}.
|
|
|
If its argument is a string, then the complete string is converted to
|
|
@@ -4515,11 +4616,10 @@ compiler.
|
|
|
\html{\input{refex/ex44.tex}}
|
|
|
|
|
|
|
|
|
-\function{Ord}{(X : Ordinal type)}{Byte}
|
|
|
+\function{Ord}{(X : Any ordinal type)}{Longint}
|
|
|
{\var{Ord} returns the Ordinal value of a ordinal-type variable \var{X}.}
|
|
|
{None.}
|
|
|
-{\seef{Chr}}
|
|
|
-
|
|
|
+{\seef{Chr}, \seef{Ord}, \seef{Pred}, \seef{High}, \seef{Low}}
|
|
|
|
|
|
\latex{\inputlisting{refex/ex45.pp}}
|
|
|
\html{\input{refex/ex45.tex}}
|
|
@@ -4582,6 +4682,18 @@ The function actually returns \var{Exp(expon*Ln(base))}
|
|
|
\latex{\inputlisting{refex/ex78.pp}}
|
|
|
\html{\input{refex/ex78.tex}}
|
|
|
|
|
|
+\function{Pred}{(X : Any ordinal type)}{Same type}
|
|
|
+{ \var{Pred} returns the element that precedes the element that was passed
|
|
|
+to it. If it is applied to the first value of the ordinal type, and the
|
|
|
+program was compiled with range checking on (\var{\{\$R+\}}, then a run-time
|
|
|
+error will be generated.
|
|
|
+}{Run-time error 201 is generated when the result is out of
|
|
|
+range.}{\seef{Ord}, \seef{Pred}, \seef{High}, \seef{Low}}
|
|
|
+
|
|
|
+for an example, see \seef{Ord}
|
|
|
+\latex{\inputlisting{refex/ex80.pp}}
|
|
|
+\html{\input{refex/ex80.tex}}
|
|
|
+
|
|
|
\function{Ptr}{(Sel,Off : Longint)}{Pointer}
|
|
|
{
|
|
|
\var{Ptr} returns a pointer, pointing to the address specified by
|
|
@@ -4906,6 +5018,16 @@ formatting of the string.}
|
|
|
\latex{\inputlisting{refex/ex68.pp}}
|
|
|
\html{\input{refex/ex68.tex}}
|
|
|
|
|
|
+\function{Succ}{(X : Any ordinal type)}{Same type}
|
|
|
+{ \var{Succ} returns the element that succeeds the element that was passed
|
|
|
+to it. If it is applied to the last value of the ordinal type, and the
|
|
|
+program was compiled with range checking on (\var{\{\$R+\}}, then a run-time
|
|
|
+error will be generated.
|
|
|
+}{Run-time error 201 is generated when the result is out of
|
|
|
+range.}{\seef{Ord}, \seef{Pred}, \seef{High}, \seef{Low}}
|
|
|
+
|
|
|
+for an example, see \seef{Ord}.
|
|
|
+
|
|
|
\function{Swap}{(X)}{Type of X}
|
|
|
{\var{Swap} swaps the high and low order bytes of \var{X} if \var{X} is of
|
|
|
type \var{Word} or \var{Integer}, or swaps the high and low order words of
|