Part 1
A Crash Course in OPL
In which we'll introduce you to the language of OPL, give
you an idea of what variables and procedures are, how procedures
call other procedures, and introduce you to the versatile
DO... UNTIL... loop structure and the essential IF...ELSE...
ENDIF
Where to Start
To begin, you should obtain a copy of the OPL manual for the
Psion Series 5mx range. This is available in a ZIP file in
the OPL
Devkit. The majority of the language is unchanged from
ER5 to ER6, major exceptions are noted in the Porting Guide
supplied with the OPL ER6 SDK.
The important chapter is Chapter 15. This gives you the structure
of each command, and a short explanation of what it does.
You'll use this as a reference a lot during coding, keep it
close at hand.
First Steps
Think of OPL as a story in a language that is almost,
but not quite, English. It's easily readable by you, and if
you translate this OPL code, it is easily read by your Communicator.
Think of it as a halfway house between you and the computer.
As with any language, there are ways of speaking, and different
elements. English has sentences, paragraphs, nouns, verbs
and so on. OPL has it's own elements.
Procedures: Where you hang your Code.
When an OPL program is run, the frst procedure (here called
PROC main:) is opened. The lines are then read and processed
in the order they are listed, until ENDP is reached, at which
point the program ends.
Now within a procedure, you can call another procedure. Do
this by simply typing the name of the procedure you want to
run next. All procedure names must have a colon after them
(that's the two dots above each other).
PROC main:
setup_app:
do_something_nice:
save_status:
ENDP
PROC setup_app:
REM Do something interesting here
ENDP
etc...
So main: is opened, it calls three procedures in order, then
reaches ENDP, and the program closes. Note that each procedure
must start with PROC <a name>: and end with ENDP on
seperate lines. When the end of the first procedure is reached,
your OPL program stops. The only way t run other procedures
is to call them.
Procedure names cannot have spaces, hence the use of the
underscore. You'll see that underscore used a lot as a seperator!
Constants
Constants are exactly that. They are things that never change.
You can use them so code is easier to read, for example rather
than having to type the number 103782376892 every time you
need to use it (assuming it is something that appears a lot
in your app) you could put...
K_Big_Number%=103782376892
...at the start of your code, and then each time you need
to use the number, use K_Big_Number% instead. By convention,
you shuld prefix K_ in front of any contant name.
Once you see some example code, constants should be a lot
clearer. One thing to point out now is that there are a lot
of default constants. If you have the line...
INCLUDE "Const.oph"
...then these default constanst can all be used. They are
detailed in the documentation provided with the OPL Development
Kit from Symbian. You should print this out and keep it to
hand. it will be useful later!
Variables
A variable is somewhere where you can tell your computer to
remember a piece of information. This is normally a small
number, a big number, or a string of letters and numbers.
Each of these variables is given a name, and a small sign
to indicate what type of information it is. You should also
remember these names cannot have a space in them, which is
why you'll see so many names with the underscore character
in them!
Types of Variables
A small number (called an integer) is followed by a % sign.
For example, high_score% is an integer that stores a number
referred to as high_score. An integer has to be a whole number
(ie you can't have high_score%=2.5, but you can have high_score%=2
or high_score%=3).
A large number is followed by a & sign. For example,
big_number& is a large integer that stores a number referred
to as big_number. Large integers can be fractions (so you
could have high_score&=2.5).
A string of letters and numbers is called (funnilly enough)
a string, and is followed by a $ symbol, For example, name$
cold be "ewanspence"
Defining a Variable
Before you can use a variable, you need to have told your
program that you are going to use it. Think of it as making
a little space to store the number. There are two ways of
defining a variable.
A GLOBAL variable is a variable that ANY procedure can use.
A LOCAL procedures is a variable that only that specific
procedure can use. When you leave the procedure, the little
space for the number is reclaimed. Local variables are good
for temporary counters and bits of info that are only needed
for a few moments.
The command to set a variable needs to be the first lines
of a procedure. Global definitions must be the first lines
in your first procedure, and local procedure mus be the first
lines in the relevant procedure.
You can put more than one definition on a line. Seperate
them with a comma.
PROC main:
GLOBAL high_score%,big_number&
And...
PROC local:
LOCAL name$(20)
You'll note that after defining name$ we have a bracketed
number. This tells the computer the maximum length (in characters)
the string is going to be. You need to define the length of
a string or when you translate the program for your computer,
you'll get an error message.
Setting Variables
Variables are easy to set. Simply use the equals sign. For
example
high_score%=56
big_number&=1383512467
name$="rafe blandford"
Setting a variable should be done on a seperate line for
each command. Note that when setting a string, you have to
use quotation marks. These don't appear as part of the string.
Arrays - Making a bigger Variable
One other tool you have in variables is an array. An array
is a 'list of things. For example, if we wanted to have a
table of 10 numbers, then instead of
GLOBAL table1%,table2%,table3%
Which would work (but will cause problems later), you can
use
GLOBAL table%(10)
Which will create a table of 10 items. The first is called
table%(1), then table%(2) and so on.
If you have a string table, then do
GLOBAL name_table$(10,20)
Which is a table of 10 strings, each a maximum of 20 characters
long.
So why use name_table%(10) and not table1%,table2%, and so
on? Because if you have another variable (eg lookupthisnumber%)
then you can refer to name_table%(lookupthisnumber%). This
is very useful if you think about it, as we're about to show
you.
Loops
Loops are a great way to make your program do something over
and over again, maybe with a few changes. Look at this code.
PROC loop:
LOCAL foo%
foo%=0
DO
foo%=foo%+1
table%(foo%)=foo%
UNTIL foo%=10
ENDP
Make sure you understand this code. The DO... UNTIL loop
is a primary building block of code. Firstly we create a variable
to act as a counter. In this case foo%. You'll see me use
foo% (and gnu% and zsu%) as a temporary variable name a lot.
If you do see it, you can assume it's a counter or another
local variable.
Each time round the loop we add one to foo%, then make an
entry in an array called table (which must be a Global variable
as it's not listed as a local variable).
When foo% reaches ten, then the UNTIL stops the loop, and
carries on with the procedure. As there is nothing left to
do, ENDP will return the program back to wherever loop: was
called.
Decisions
At many points in your program, you'll have to check something
and do seperate commands depending on the outcome. To check
things you use the IF command.
IF guess%=1
guess_right:
ELSEIF guess%=2
guess_close:
ELSE
guess_wrong%
ENDIF
Again, this is pretty easy to read. If the variable guess%=1,
then goto a procedure called guess_right:. If guess%=2, then
goto a procedure called guess_close: If guess% is anything
else (a sort of catch all for any other condition, which is
good programming practice to get into), then goto a procedure
called guess_wrong:
The IF... ELSE... ENDIF is the second great building block
of computing languages.
Making Sure You Don't Forget
Througout code you'll see lines like this...
REM This routine calculates the cursor position
or...
REM foo_x% represents the temporary x co-ordinate
REM foo_y% represents the temporary y co-ordinate
The power of the REM statement is in the fact it does absolutely
nothing! Everything after the REM statement (until the next
line of code) is ignored by the computer.
This means you can use it to leave notes for yourself, or
to explain a bit of code to someone else who is going to read
it. And if you come back to some code 6 months after writing
it, wondering what PROC xyz_transposition: does, the REM statement
you added will prove invaluable.
Summary
So, pretty easy? Of course it is! Although it is a lot to
get around, so don't worry if it takes a few weeks to get
to grips with it. In the next part, we'll have a look at the
Event Core OPL code and see how it works. There's nothing
to stop you having a look at it at the moment, and you can't
break your machine by experimenting with the code. You'll
find you can read and understand quite a bit of it. Some of
it, especially the stuff dealing with getting keypresses and
events from the keyboard, can be quite daunting... but this
is the advantage of having a Core Framework to begin with,
rather than a blank canvas!
Got any questions or comments arising from this tutorial.
Need help with OPL. Head to the forums
for help from the friendly community.
|