Pascal Syntax v101
Pascal Syntax v101
All products are owned by MikroElektronika and protected by copyright law and interna-
tional copyright treaty. Therefore, you should treat this manual as any other copyright
material. It may not be copied, partially or as a whole without the written consent of
MikroElektronika. Manual PDF – edition can be printed for private or local use, but not
for distribution. Modifying manual is prohibited.
LICENSE AGREEMENT:
By using our products you agree to be bound by all terms of this agreement. Copyright
by MikroElektronika 2003 – 2008.
3
Whitespace
Whitespace is the collective name given to spaces (blanks), horizontal and vertical tabs,
newline characters and comments. Whitespace can serve to indicate where tokens start
and end, but beyond this function, any surplus whitespace is discarded. For example,
two sequences
var i : char;
j : word;
and
var
i : char;
j : word;
are lexically equivalent and parse identically to give the nine tokens:
var
i
:
char
;
j
:
word
;
4
Whitespace in Strings
The ASCII characters representing whitespace can occur within string literals, thus being
protected from the normal parsing process (they remain part of the string). For example,
some_string
:=
'mikro foo'
;
Tokens
Token is the smallest element of a Pascal program that is meaningful to the compiler. The
parser separates tokens from the input stream by creating the longest token possible
using input characters in a left–to–right scan.
Literals
Literals are tokens representing fixed numeric or character values. The data type of a
constant is deduced by the compiler using such clues as numeric values and the format
used in the source code.
Integer Literals
Integral values can be represented in decimal, hexadecimal or binary notation.
11 // decimal literal
$11 // hex literal, equals decimal 17
0x11 // hex literal, equals decimal 17
%11 // binary literal, equals decimal 3
Decimal integer;
Decimal point ;
Decimal fraction; and
e or E and a signed integer exponent (optional).
Negative floating constants are taken as positive constants with the unary operator minus
(-) prefixed.
0. // = 0.0
-1.23 // = -1.23
23.45e6 // = 23.45 * 10^6
2e-5 // = 2.0 * 10^-5
3E+10 // = 3.0 * 10^10
.09E34 // = 0.09 * 10^34
Character Literals
Character literal is one character from extended ASCII character set, enclosed with apos-
trophes. Character literal can be assigned to variables of byte and char type (variable of
byte will be assigned the ASCII value of the character). Also, you can assign a character
literal to a string variable.
Note: Quotes ("") have no special meaning in mikroPascal.
String Literals
String literal is a sequence of up to 255 characters from extended ASCII character set,
written in one line and enclosed with apostrophes. Whitespace is preserved in string lit-
erals, i.e. parser does not “go into” strings but treats them as single tokens.
The length of string literal is the number of characters it consists of. String is stored inter-
nally as a given sequence of characters plus a final null character (ASCII zero). This
appended “stamp” does not count against the string’s total length. String literal with noth-
ing in between the apostrophes (null string) is stored as a single null character.
You can assign string literal to a string variable or to an array of char.
Here are several string literals:
Keywords
Keywords are words reserved for special purpose, and cannot be used as normal iden-
tifier names. Apart from the standard Pascal keywords, all relevant SFRs are defined as
global variables and represent reserved words that cannot be redefined. Here is the
alphabetical listing of keywords in Pascal:
Identifiers
Identifiers are arbitrary names of any length given to functions, variables, symbolic con-
stants, user-defined data types and labels. Identifiers can contain the letters a to z and A to
Z, the underscore character “_” and digits 0 to 9. First character must be a letter or an under-
score. Pascal is not case sensitive, so that it considers Sum, sum, and suM equivalent iden-
tifiers. Although identifier names are arbitrary (within the rules stated), errors occur if the
same name is used for more than one identifier within the same scope.
temperature_V1
Pressure
no_hit
dat2string
SUM3
_vtext
Punctuators
The mikroPascal punctuators (also known as separators) are:
[] - Brackets
() - Parentheses
, - Coma
; - Semicolon
: - Colon
. - Dot
Brackets
Brackets [ ] indicate single and multidimensional array subscripts:
Parentheses
Parentheses ( ) are used to group expressions, isolate conditional expressions and indi-
cate function calls and function declarations:
Comma
Comma (,) separates the arguments in function calls, identifiers in declarations and ele-
ments of array in initialization lists:
Lcd_Out(1, 1, txt);
var i, j, k: byte;
const MONTHS: array [1..12] of byte = (31,28,31,30,31,30,31,31,30,31,30,31);
Semicolon
Every statement in Pascal must be terminated by a semicolon. The only exception is the
last (outer most) end statement in program which is terminated by dot.
Colon
Colon (:) is used in declarations to separate identifier list from type identifier. For example:
var
i, j : byte;
k : word;
start: nop;
...
goto start;
Dot
Dot (.) indicates access to a field of a record. For example:
person.surname := 'Smith';
Dot is a necessary part of floating point literals. Also, dot can be used for accessing indi-
vidual bits of registers in mikroPascal.
9
Program Organization
Pascal imposes quite strict program organization. Below you can find models for writing
legible and organized source files. For more information on file inclusion and scope,
refer to Units, Scope and Visibility.
//********************************************************
//* Declarations (globals):
//********************************************************
{ constants declarations }
const ...
{ variables declarations }
var ...
{ labels declarations }
label ...
{ procedures declarations }
procedure procedure_name
{ local declarations }
begin
...
end;
{ functions declarations }
function function_name
{ local declarations }
begin
...
end;
//********************************************************
//* Program body:
//********************************************************
begin
{ write your code here }
end.
10
{ constants declarations }
const ...
{ variables declarations }
var ...
{ procedures prototypes }
procedure procedure_name(...);
{ functions prototypes }
function function_name(...);
//********************************************************
//* Implementation:
//********************************************************
implementation
{ constants declarations }
const ...
{ variables declarations }
var ...
{ labels declarations }
label ...
{ procedures declarations }
procedure procedure_name
{ local declarations }
begin
...
end;
{ functions declarations }
function function_name
{ local declarations }
begin
...
end;
end.
11
Scope
The scope of identifier is a part of the program in which the identifier can be used to
access its object. There are different categories of scope depending on how and where
identifiers are declared:
Visibility
The visibility of an identifier is the region of the program source code from which legal
access can be made to the identifier’s associated object.
Scope and visibility usually coincide, although there are circumstances under which an
object becomes temporarily hidden by the appearance of a duplicate identifier: the object
still exists but the original identifier cannot be used to access it until the scope of the
duplicate identifier is ended.
Technically, visibility cannot exceed scope, but scope can exceed visibility.
Units
In mikroPascal, each project consists of a single project file and one or more unit files.
Project file contains information about the project, while unit files, with extension .mpas,
contain the actual source code.
break large programs into encapsulated parts that can be edited separately;
create libraries that can be used in different projects; and
distribute libraries to other developers without disclosing the source code.
Each unit is stored in its own file and compiled separately. Compiled units are linked to
create an application. To build a project, the compiler needs either a source file or a com-
piled unit file for each unit.
12
Uses Clause
mikroPascal includes units by means of the uses clause. It consists of the reserved word
uses, followed by one or more comma-delimited unit names, followed by a semicolon.
Extension of the file should not be included. There can be at most one uses clause in each
source file, and it must appear immediately after the program (or unit) name. Here’s an
example:
When encountering a given unit name, compiler will check for the presence of .mcl and
.mpas files, in the order specified by the search paths.
If both .mpas and .mcl files are found, compiler will check their dates and include
newer one in the project. If the .mpas file is newer than the .mcl, a new library will be
recompiled over the old one;
If only .mpas file is found, compiler will create the .mcl file and include it in the project;
If only .mcl file is present, i.e. no source code is available, compiler will include it as found;
If none found, compiler will issue a “File not found” warning.
Main Unit
Every project in mikroPascal requires a single main unit file. The main unit file is identi-
fied by the keyword program at the beginning; it instructs the compiler where to “start”.
After you have successfully created an empty project with Project Wizard, Code Editor
will display a new main unit. It contains the bare-bones of Pascal program:
program MyProject;
{ main procedure }
begin
{ Place program code here }
end.
Except for comments, nothing should precede the keyword program. After the program
name, you can optionally place the uses clause. Place all global declarations (constants,
variables, labels, routines) before the keyword begin.
Other Units
Other units start with the keyword unit. Newly created blank unit contains the bare-bones:
unit MyUnit;
implementation
end.
Except for comments, nothing should precede the keyword unit. After the unit name, you
can optionally place an uses clause.
13
Interface Section
Part of the unit above the keyword implementation is referred to as interface section. Here,
you can place global declarations (constants, variables, and labels) for the project. You can-
not define routines in the interface section. Instead, state the prototypes of routines (from
implementation section) that you want to be visible outside the unit. Prototypes must fully
match the declarations.
Implementation Section
Implementation section hides all the irrelevant innards from other units, allowing encapsulation of
code. Everything declared below the keyword implementation is private, i.e. has its scope limit-
ed to the file. When you declare an identifier in the implementation section of a unit, you cannot
use it outside the unit, but you can use it in any block or routine defined within the unit. By plac-
ing the prototype in the interface section of the unit (above the implementation) you can make the
routine public, i.e. visible outside of unit. Prototypes must fully match the declarations.
Variables
Variable is an object whose value can be changed during the runtime. Every variable is
declared under unique name which must be a valid identifier. Variables are declared in
the declaration part of the file or routine — each variable needs to be declared before it
can be used. Global variables (those that do not belong to any enclosing block) are
declared below the uses statement, above the keyword begin. Specifying a data type for
each variable is mandatory. Basic syntax for variable declaration is:
The identifier_list is a comma-delimited list of valid identifiers and type can be any data
type. Pascal allows shorthand syntax with only one keyword var followed by multiple vari-
able declarations. For example:
var i, j, k : byte;
counter, temp : word;
samples : array [100] of word;
Labels
Labels serve as targets for goto statements. Mark a desired statement with label like this:
label_identifier : statement
Before marking a statement, you must first declare the label. It is declared in declaration part of
unit or routine, similar to variables and constants. Declare labels using the keyword label:
Constants
Constant is a data whose value cannot be changed during the runtime. Using a constant
in a program consumes no RAM memory. Constants can be used in any expression, but
cannot be assigned a new value. Constants are declared in the declaration part of pro-
gram or routine. Declare a constant in the following way:
Every constant is declared under unique constant_name which must be a valid identifi-
er. Constant names are normally written in uppercase. Constant requires you to specify
value, i.e. a literal appropriate for the given type. The type is optional; in the absence of
type, compiler assumes the “smallest” type that can accommodate value. Pascal allows
shorthand syntax with only one keyword const followed by multiple constant declarations.
Here’s an example:
const
MAX : longint = 10000;
MIN = 1000; // compiler will assume word type
SWITCH = 'n'; // compiler will assume char type
MSG = 'Hello'; // compiler will assume string type
MONTHS : array [1..12] of byte = (31,28,31,30,31,30,31,31,30,31,30,31);
Functions
Function is declared as follows:
The function_name represents a function’s name and can be any valid identifier. Within parenthe-
ses, parameter_list is a formal parameter list very similar to variable declaration. In Pascal, param-
eters are always passed to function by value — to pass the argument by address, add the key-
word var ahead of identifier. Local declarations are optional declarations of variables and/or con-
stants, local for the given function. Function body is a sequence of statements to be executed upon
calling the function.
15
Calling a function
A function is called by its name, with actual arguments placed in the same sequence as
their matching formal parameters. The compiler is able to coerce mismatching argu-
ments to the proper type according to implicit conversion rules. After function call, all for-
mal parameters are created as local objects initialized by values of actual arguments.
After return from a function, temporary object is created in the place of the call, and it is
initialized by the expression of return statement. This means that the function call as an
operand in complex expression is treated as the function result.
Here’s a simple function which calculates xn based on input parameters x and n (n > 0):
Procedures
Procedure is declared as follows:
procedure procedure_name(parameter_list);
{ local declarations }
begin
{ procedure body }
end;
procedure_name represents a procedure’s name and can be any valid identifier. Within
parentheses, parameter_list is a formal parameter list very similar to variable declaration.
In Pascal, parameters are always passed to procedure by value — to pass the argument
by address, add the keyword var ahead of identifier. Local declarations are optional dec-
laration of variables and/or constants, local for the given procedure. Procedure body is a
sequence of statements to be executed upon calling the procedure.
Calling a procedure
A procedure is called by its name, with actual arguments placed in the same sequence
as their matching formal parameters. Upon procedure call, all formal parameters are cre-
ated as local objects initialized by values of actual arguments.
16
Types
Pascal is strictly typed language, which means that every variable and constant need to
have a strictly defined type, known at the time of compilation. The type serves:
mikroPascal supports many standard (predefined) and user-defined data types, includ-
ing signed and unsigned integers of various sizes, arrays, strings and pointers. Types
can be built from other types by the type declaration. For example:
var mynumber:MyType2;
Simple Types
Simple types represent types that cannot be divided into more basic elements, and are
the model for representing elementary data on machine level. Here is an overview of sim-
ple types in mikroPascal:
Arrays
An array represents an indexed collection of elements of the same type (called the base
type). As each element has a unique index, arrays can meaningfully contain the same
value more than once.
Array Declaration
Array types are denoted by constructions of the form:
Each of the elements of an array is numbered from index_start through the index_end.
Specifier index_start can be omitted along with dots, in which case it defaults to zero.
Every element of an array is of type and can be accessed by specifying array name fol-
lowed by element’s index within brackets. Here are a few examples:
var
weekdays : array [1..7] of byte;
samples : array [50] of word;
begin
// Now we can access elements of array variables, for example:
samples [0] := 1;
if samples [37] = 0 then ...
Constant Arrays
Constant array is initialized by assigning it a comma-delimited sequence of values with-
in parentheses. For example:
The number of assigned values must not exceed the specified length, but can be less
than the specified length, when the trailing “excess” elements are to be assigned zeroes.
18
Multi-dimensional Arrays
An array is one-dimensional if it is of scalar type. One-dimensional arrays are sometimes
referred to as vectors.
Multidimensional arrays are constructed by declaring arrays of array type. These arrays
are stored in memory in a way that the right most subscript changes fastest, i.e. arrays
are stored “in rows”. Here is a sample 2-dimensional array:
Variable m is an array of 50 elements, which in turn are arrays of 20 bytes each. Thus,
we have a matrix of 50x20 elements: the first element is m[0][0] and the last one is
m[49][19]. The first element of the 4th row would be m[0][4].
This is a commonly used technique when passing arrays as function parameters:
var
m: array [50] of array [20] of byte; // 2-dimensional array of size 50x20
n: array [4] of array [2] of array [7] of byte; // 3-dimensional array of
size 4x2x7
begin
...
func(m);
end.
Strings
A string represents a sequence of characters and is equivalent to an array of char. It is
declared as:
The string_name needs to be a valid identifier. Specifier length is a number of characters the
string consists of. String is stored internally as the given sequence of characters plus a final
null character (zero). This appended “stamp” does not count against string’s total length.
The null string ('') is stored as a single null character.
19
You can assign string literals or other strings to string variables. String on the right side of an
assignment operator has to be the shorter one of two or of equal length. For example:
var
msg1 : string [20];
msg2 : string [19];
begin
msg1 := 'This is some message';
msg2 := 'Yet another message';
msg1 := msg2; // this is ok, but vice versa would be illegal
String Splicing
mikroPascal allows you to splice strings by means of plus character. This kind of concatena-
tion is applicable to string variables/literals and character variables/literals. For control charac-
ters, use the non-quoted hash sign and a numeral (e.g. #13 for CR). Here is an example:
Pointers
A pointer is a data type which holds a memory address. While a variable accesses that
memory address directly, a pointer can be thought of as a reference to that memory
address. To declare a pointer data type, add a carat prefix (^) before type. For example,
if you are creating a pointer to an integer, you should write:
^integer;
To access the data at the pointer’s memory location, add a carat after the variable name.
For example, let’s declare variable p which points to a word, and then assign the point-
ed memory location value 5:
var p : ^word;
...
p^ := 5;
A pointer can be assigned to another pointer. However, note that only the address, not
the value, is copied. Once you modify the data located at one pointer, the other pointer,
when dereferenced, also yields modified data.
@ Operator
The @ operator returns the address of a variable or routine; that is, @ constructs a point-
er to its operand. The following rules apply to @:
Records
A record (analogous to a structure in some languages) represents a heterogeneous set
of elements. Each element is called a field; the declaration of a record type specifies a
name and type for each field. The syntax of a record type declaration is
where recordTypeName is a valid identifier, each type denotes a type, and each fieldList
is a valid identifier or a comma-delimited list of identifiers. The scope of a field identifier
is limited to the record in which it occurs, so you don’t have to worry about naming con-
flicts between field identifiers and other variables. Note that in mikroPascal, you cannot
use the record construction directly in variable declarations, i.e. without type.
21
For example, the following declaration creates a record type called TDot:
type
TDot = record
x, y : real;
end;
Each TDot contains two fields: x and y coordinates; memory is allocated when you
instantiate the record, like this:
var m, n: TDot;
Accessing Fields
You can access the fields of a record by means of dot (.) as a direct field selector. If we
declare variables circle1 and circle2 of previously defined type TCircle:
circle1.radius := 3.7;
circle1.center.x := 0;
circle1.center.y := 0;
Types Conversions
Conversion of object of one type is changing it to the same object of another type (i.e.
applying another type to a given object). mikroPascal supports both implicit and explicit
conversions for built-in types.
Implicit Conversion
Compiler will provide an automatic implicit conversion in the following situations:
statement requires an expression of particular type (according to language defini-
tion), and we use an expression of a different type;
operator requires an operand of particular type and we use an operand of a different
type;
function requires a formal parameter of particular type and we pass it an object of a
different type; and
result does not match the declared function return type.
Promotion
When operands are of different types, implicit conversion promotes a less complex to
more complex type taking the following steps:
byte/char ĺ word
short ĺ integer
short ĺ longint
integer ĺ longint
integral ĺ real
Higher bytes of extended unsigned operand are filled with zeroes. Higher bytes of
extended signed operand are filled with bit sign (if number is negative, fill higher bytes
with one, otherwise with zeroes). For example:
Clipping
In assignments, and statements that require an expression of particular type, destination
will store the correct value only if it can properly represent the result of expression (that
is, if the result fits in destination range). If expression evaluates to a more complex type
than expected, excess data will be simply clipped (higher bytes are lost).
Explicit Conversion
Explicit conversion can be executed at any point in expression by inserting type keyword (byte,
word, short, integer, longint, or real) ahead of the expression to be converted. The expression
must be enclosed in parentheses. Explicit conversion can be performed only on the operand
left of the assignment operator. Special case is conversion between signed and unsigned
types. Explicit conversion between signed and unsigned data does not change binary repre-
sentation of data — it merely allows copying of source to destination. For example:
You can’t execute explicit conversion on the operand left of the assignment operator:
c := a + b; // equals 113
c := word(a + b); // equals 369
cc := a + b; // equals 369
Arithmetic Conversions
When you use an arithmetic expression, such as a + b, where a and b are of different
arithmetic types, mikroPascal performs implicit type conversions before the expression is
evaluated. These standard conversions include promotions of “lower” types to “higher”
types in the interests of accuracy and consistency. Assigning a signed character object
(such as a variable) to an integral object results in automatic sign extension. Objects of
type short always use sign extension; objects of type byte always set the high byte to
zero when converted to int. Converting a longer integral type to a shorter type truncates
higher order bits and leaves low-order bits unchanged.
Converting a shorter integral type to a longer type either sign-extends or zero-fills the
extra bits of new value, depending on whether the shorter type is signed or unsigned,
respectively.
Note: Conversion of floating point data into integral value (in assignments or via explicit
typecast) produces correct results only if the float value does not exceed the scope of des-
tination integral type.
24
In details:
Here are the steps mikroPascal uses to convert operands in an arithmetic expression:
First, any small integral types can be converted according to the following rules:
The result of the expression is of the same type as that of the two operands.
Operators
Operators are tokens that trigger some computation when applied to variables and other
objects in an expression.
There are 4 precedence categories in mikroPascal. Operators in the same category have
equal precedence with each other. Each category has an associativity rule: left-to-right
(), or right-to-left (). In the absence of parentheses, these rules resolve the grouping
of expressions with operators of equal precedence.
Arithmetic Operators
Arithmetic operators are used to perform mathematical computations. They have numer-
ical operands and return numerical results. As char operators are technically bytes, they
can be also used as unsigned operands in arithmetic operations. All arithmetic operators
associate from left to right.
Division by Zero
If 0 (zero) is used explicitly as the second operand (i.e. x div 0), compiler will report an
error and will not generate code. But in the event of implicit division by zero : x div y,
where y is 0 (zero), result will be the maximum value for the appropriate type (for exam-
ple, if x and y are words, the result will be $FFFF).
b := -a;
26
Relational Operators
Use relational operators to test equality or inequality of expressions. All relational opera-
tors return TRUE or FALSE.
All relational operators associate from left to right.
Operator Operation
= equal
<> not equal
> greater than
< less than
>= greater than or equal
<= less than or equal
Bitwise Operators
Use the bitwise operators to modify individual bits of numerical operands.
Bitwise operators associate from left to right. The only exception is the bitwise comple-
ment operator not which associates from right to left.
Operator Operation
bitwise AND; compares pairs of bits and generates an 1 result if
and
both bits are 1, otherwise it returns 0.
bitwise (inclusive) OR; compares pairs of bits and generates an 1
or
result if either or both bits are 1, otherwise it returns 0.
bitwise exclusive OR (XOR); compares pairs of bits and generates
xor
an 1 result if the bits are complementary, otherwise it returns 0.
not bitwise complement (unary); inverts each bit.
bitwise shift left; moves the bits to the left, it discards the far left bit
shl
and assigns 0 to the right most bit.
bitwise shift right; moves the bits to the right, discards the far right
shr bit and if unsigned assigns 0 to the left most bit, otherwise sign
extends.
27
Expresions
An expression is a sequence of operators, operands and punctuators that returns a
value. The primary expressions include: literals, constants, variables and function calls.
From these, using operators, more complex expressions can be created. Formally,
expressions are defined recursively: subexpressions can be nested up to the limits of
memory. The way operands and subexpressions are grouped does not necessarily spec-
ify the actual order in which they are evaluated by mikroPascal.
Statements
Statements define algorithmic actions within a program. Each statement needs to be ter-
minated by a semicolon (;). In the absence of specific jump and selection statements,
statements are executed sequentially in the order of appearance in the source code.
Assignment Statements
Assignment statements have the form:
variable := expression;
The statement evaluates the expression and assigns its value to a variable. All rules of
the implicit conversion apply. Variable can be any declared variable or array element, and
expression can be any expression. Do not confuse the assignment with relational oper-
ator = which tests for equality.
begin
statements
end
Syntactically, a block is considered to be a single statement which allows using it when Pascal
syntax requires a single statement. Blocks can be nested up to the limits of memory. For exam-
ple, while loop expects one statement in its body, so we can pass it a compound statement:
while i < n do
begin
temp := a [i];
a [i] := b [i];
b [i] := temp;
n := n + 1;
end;
end.
In mikroPascal, the end. statement (the closing statement of every program) acts as an endless loop.
29
Conditional Statements
Conditional or selection statements select from alternative courses of action by testing
certain values.
If Statement
Use if to implement a conditional statement. Syntax of if statement has the form:
Nested if statements
Nested if statements require additional attention. General rule is that the nested condi-
tionals are parsed starting from the innermost conditional, with each else bound to the
nearest available if on its left:
if expression1 then
if expression2 then statement1
else statement2
if expression1 then
begin
if expression2 then statement1
else statement2
end
To force the compiler to interpret our example the other way around, we would have to
write it explicitly:
if expression1 then
begin
if expression2 then statement1
end
else statement2
30
Case Statement
Use the case statement to pass control to a specific program branch, based on a certain
condition. The case statement consists of a selector expression (a condition) and a list
of possible values. The syntax of case statement is:
case selector of
value_1 : statement_1
...
value_n : statement_n
[else default_statement]
end
The selector is an expression which should evaluate as integral value. The values can
be literals, constants, or expressions, and statements can be any statements.
The else clause is optional. When using the else branch, note that there should never be
a semicolon before the keyword else.
First, the selector expression (condition) is evaluated. The case statement then com-
pares it against all available values. If the match is found, the statement following the
match evaluates, and case statement terminates. In case there are multiple matches, the
first matching statement will be executed. If none of the values matches the selector, then
the default_statement in the else clause (if there is one) is executed.
Here’s a simple example of case statement:
case operator of
'*' : result := n1 * n2;
'/' : result := n1 / n2;
'+' : result := n1 + n2;
'-' : result := n1 - n2
else result := 0;
end;
Also, you can group values together for a match. Simply separate the items by commas:
case reg of
0: opmode := 0;
1,2,3,4: opmode := 1;
5,6,7: opmode := 2;
end;
Iteration Statements
Iteration statements let you loop a set of statements. You can use the statements break
and continue to control the flow of a loop statement. The break terminates the statement
in which it occurs, while continue begins executing the next iteration of the sequence.
For Statement
The for statement implements an iterative loop and requires you to specify the number
of iterations. The syntax of for statement is:
The counter is a variable which increments (or decrements if you use downto) with each iter-
ation of the loop. Before the first iteration, counter is set to the initial_value and will increment
(or decrement) until it reaches the final_value. With each iteration, a statement will be exe-
cuted. The initial_value and final_value should be expressions compatible with the counter;
statement can be any statement that does not change the value of counter. Here is an exam-
ple of calculating scalar product of two vectors, a and b, of length n, using for statement:
s := 0;
for i := 0 to n-1 do s := s + a [i] * b [i];
Endless Loop
The for statement results in an endless loop if the final_value equals or exceeds the range
of counter’s type. For example, this will be an endless loop, as counter can never reach 300:
More legible way to create an endless loop in Pascal is to use the statement while TRUE do.
While Statement
Use the while keyword to conditionally iterate a statement. Syntax of while statement is:
The statement is executed repeatedly as long as the expression evaluates true. The test
takes place before the statement is executed. Thus, if expression evaluates false on the
first pass, the loop is not executed. Probably the easiest way to create an endless loop
is to use the statement:
Repeat Statement
The repeat statement executes until the condition becomes false. The syntax of repeat state-
ment is:
The statement is executed repeatedly until the expression evaluates false. The expression
is evaluated after each iteration, so the loop will execute statement at least once. Here is an
example of calculating scalar product of two vectors, using the repeat statement:
s := 0; i := 0;
...
repeat
begin
s := s + a [i] * b [i];
i := i + 1;
end;
until i = n;
Jump Statements
A jump statement, when executed, transfers control unconditionally.
Break Statement
Sometimes, you might need to stop the loop from within its body. Use the break state-
ment within loops to pass control to the first statement following the innermost loop (for,
while or repeat block). For example:
Continue Statement
You can use the continue statement within loops to “skip the cycle”:
Exit Statement
The exit statement allows you to break out of a routine (function or procedure). It pass-
es the control to the first statement following the routine call.
procedure Proc1();
var error: byte;
... // we're doing something here
if error = TRUE then exit;
... // some code, which won't be executed if error is true
Goto Statement
Use the goto statement to unconditionally jump to a local label — for more information,
refer to Labels. The syntax of goto statement is:
This will transfer control to the location of a local label specified by label_name. The goto
goto label_name;
line can come before or after the label. The label declaration, marked statement, and
goto statement must belong to the same block. Hence it is not possible to jump into or
out of a procedure or function.
You can use goto to break out from any level of nested control structures. Never jump
into a loop or other structured statement, since this can have unpredictable effects. The
use of goto statement is generally discouraged as practically every algorithm can be real-
ized without it, resulting in legible structured programs. One possible application of goto
statement is breaking out from deeply nested control structures:
for (...) do
begin
for (...) do
begin
...
if (disaster) then goto Error;
...
end;
end;
.
.
.
Error: // error handling code
34
asm Statement
mikroPascal allows embedding assembly in the source code by means of asm state-
ment. Note that you cannot use numerals as absolute addresses for register variables in
assembly instructions. You may use symbolic names instead (listing will display these
names as well as addresses).
asm
block of assembly instructions
end
Pascal comments are allowed in embedded assembly code. Also, you may use one-line
assembly comments starting with semicolon:
program test
var myvar : word;
begin
myvar := 0;
asm
MOVLW 10
MOVLW test_main_global_myvar_1
end;
end.
Directives
Compiler Directives
mikroPascal treats comments beginning with a “$” immediately following the opening
brace as a compiler directive; for example, {$ELSE}. You can use conditional compilation
to select particular sections of code to compile while excluding other sections. All com-
piler directives must be completed in the source file in which they begun.
{$DEFINE Extended_format}
Directives $IFDEF..$ELSE
Conditional compilation is carried out by the $IFDEF directive. The $IFDEF tests whether
a flag is currently defined or not; that is, whether a previous $DEFINE directive has been
processed for that flag and is still in force. Directive $IFDEF is terminated by the $ENDIF
directive, and can have an optional $ELSE clause:
{$IFDEF flag}
<block of code>
{$ELSE}
<alternate block of code>
{$ENDIF}
First, $IFDEF checks if flag is defined by means of $DEFINE. If so, only <block of code>
will be compiled. Otherwise, <alternate block of code> will be compiled. The $ENDIF
ends the conditional sequence. The result of the preceding scenario is that only one sec-
tion of code (possibly empty) is passed on for further processing. The processed section
can contain further conditional clauses, nested to any depth; each $IFDEF must be
matched with a closing $ENDIF. Here is an example:
{$IFDEF resolution10}
// <code specific to 10-bit resolution>
{$ELSE}
{$IFDEF resolution12}
// <code specific to 12-bit resolution>
{$ELSE}
// <default code>
{$ENDIF}
{$ENDIF}
$I is compiler directive for inserting content of given file into place where this directive is
called. Here is an example:
{$I filename.txt}
Predefined Flags
mikroPascal has predefined flags which can be used to compile different sources for dif-
ferent platforms. For example, if target chip is P18F4520 you can use the P18F4520 flag
for conditional compiling:
{$IFDEF P18F4520}
// put some code for 18F4520
{$ELSE}
// put some code for other chips
{$ENDIF}
36
Linker Directives
mikroPascal uses internal algorithm to distribute objects within memory. If you need to
have a variable or a routine at specific predefined address, use the linker directives
absolute and org.
Directive absolute
Directive absolute specifies the starting address in RAM for variable. If variable is multi-
byte, higher bytes will be stored at the consecutive locations. Directive absolute is
appended to the declaration of a variable:
Directive org
Directive org specifies the starting address of a routine in ROM. It is appended to the dec-
laration of routine. For example:
Constant agregates (struct, array) also can be put on specified address in ROM by
means of the org directive.
Directive org can be applied to any routine except the interrupt procedure. Interrupt will
always be located at address $4 (or $8 for P18), Page0.
Directive orgall
This directive also specifies the starting address in ROM but it refers to all routines.
Directive volatile
Directive volatile gives variable possibilty to change without intervention from code.
Function Pointers
Function pointers are allowed in mikroPascal. The example shows how to define and use a
function pointer: Example demonstrates the usage of function pointers. It is shown how to
declare a procedural type, a pointer to function and finally how to call a function via pointer.
// Now, define few functions which will be pointed to. Make sure that
// parameters match the type definition.
function Func1(p1, p2: byte; p3: word): word;
begin
result := p1 and p2 or p3; // return something
end;
// Another function of the same kind. Make sure that parameters match
// the type definition
// Yet another function. Make sure that parameters match the type definition
// main program:
begin
// MyPtr now points to Func1
MyPtr := @Func1;
// Perform function call via pointer, call Func1, the return value is 3
Sample := MyPtr^(1, 2, 3);
// MyPtr now points to Func2
MyPtr := @Func2;
// Perform function call via pointer, call Func2, the return value is 5
Sample := MyPtr^(1, 2, 3);
// MyPtr now points to Func3
MyPtr := @Func3;
// Perform function call via pointer, call Func3, the return value is 0
Sample := MyPtr^(1, 2, 3);
end.
38
A function can return a complex type. Follow the example bellow to learn how to declare
and use a function which returns a complex type.
This example shows how to declare a function which returns a complex type.
begin
result.CenterX := x;
result.CenterY := y;
result.Radius := r;
end;
begin
// Get a Record via function call
MyCircle := DefineCircle(100, 200, 30);
MikroElektronika provides this manual “as is” without warranty of any kind, either
expressed or implied, including, but not limiting to implied warranties or conditions of
merchantability or fitness for a particular purpose.
Specification and information contained in this manual are furnished for internal use only,
and are subject to change at any time without notice, and should be construed as a com-
mitment by MikroElektronika.
Product and corporate names appearing in this manual may or may not be registered
trademarks or copyrights of their respective companies, and are only used for identifica-
tion or explanation and to the owners’ benefit, with no intent to infringe.