-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path05-05-procedures.html
488 lines (385 loc) · 19 KB
/
05-05-procedures.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
<!doctype html>
<html lang="en">
<head>
<!--
This Amos Professional Manual is written by asymetrix for the Amiga community and should stay completely FREE FOREVER.
Created 2008. :)
It was created from the original AMOS Professional Manual by Europress Software Ltd.
It has been updated by Fredrik Rambris.
-->
<title>Procedures - AMOS Professional Manual</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="keywords" content="Amos Professional, Amiga, Programming, Basic, Francois Lionet, Europress Software Ltd, Amos, computing, code, AmigaDOS">
<meta name="author" content="asymetrix,Fredrik Rambris">
<link rel="GitHub" href="https://github.com/fredrik-rambris/amospromanual">
<meta property="og:site_name" content="AMOS Professional Manual">
<meta property="og:image" content="https://amospromanual.dev/images/cover.jpg">
<link rel="stylesheet" type="text/css" href="styles.css">
<link rel="canonical" href="https://amospromanual.dev/05-05-procedures.html">
</head>
<body>
<section>
<h1>Procedures</h1>
<P>
A procedure is a component of a computer program that allows the AMOS Professional
programmer to tackle one aspect of the program at a time, without becoming distracted or
side-tracked by other programming considerations. Procedures can be thought of as programming
modules, each with a specific purpose and sphere of operation. This Chapter explains how
procedures are created and fully exploited.</P>
</section>
<section id="01-creating-a-procedure">
<h2>Creating a procedure</h2>
<h3 class="command" id="str-procedure">PROCEDURE</h3>
<p><i>structure: create a procedure</i><BR>
<b>Procedure</b> NAME [list of optional parameters]</P>
<h3 class="command" id="str-end-proc">END PROC</h3>
<p><i>structure: end a procedure</i><BR>
<b>End Proc</b></p>
<p>
A procedure is created in exactly the same way as a normal variable, by giving it a name.
The name is then followed by a list of parameters and the procedure must be ended with an END
PROC command. PROCEDURE and END PROC commands must be placed on their own
individual lines. For example:</P>
<code class="prefix edit">Procedure HELLO
Print "Hello, I am a procedure!"
End Proc
</code>
<P>
If you try and run that program, nothing will happen. This is because a procedure must
be called up by name from inside your program before it can do anything. Now add the
following line at the start of that last example, and then [Run] it.</P>
<code class="prefix edit">HELLO</code>
<P>There is nothing preventing a procedure from calling itself, but this recursion is
limited by the
area of storage allocated for local variables. If this local variable space is full, it
can be increased
using the SET BUFFER command. Programs can also be held up if there is no more stack space
available, and this problem is cured by the following command.</P>
<h3 class="command" id="i-set-stack">SET STACK</h3>
<p><i>instruction: set stack space</i><BR>
<b>Set Stack</b> number</P>
<P>When AMOS Professional procedures call themselves, an "Out of stack space" error
message will be generated after about fifty loops. Use the SET STACK instruction by specifying the
new number of procedure calls that an be made.</P>
</section>
<section id="02-keeping-track-of-procedures">
<h2>Keeping track of procedures</h2>
<p>To help you find the starting positions of procedures in a very long program, there is
a simple short-cut that uses just two keys.</P>
<P>
By pressing <kbd>Alt</kbd> and <kbd>Down Arrow</kbd> together, the edit cursor automatically jumps to the
next procedure definition in your program. To jump to the previous procedure, press <kbd>Alt</kbd> and
<kbd>Up Arrow</kbd> together. This shortcut works equally well with labels and line numbers!</P>
<P>If you are using several procedures on the same line, you can avoid the risk of a
procedure being
confused with a label by adding an extra space at the end of each statement. For
example:</P>
<code class="prefix ex">HEY: HEY: HEY: <comment>Rem Perform HEY procedure three times</comment>
HEY: HEY: HEY: <comment>Rem Define label HEY and perform HEY procedure twice</comment>
</code>
<h3 class="command" id="str-proc">PROC</h3>
<p><i>structure: flag a procedure</i><BR>
<b>Proc</b> NAME</P>
<P>Another way to identify a procedure is to precede it with a PROC statement. Run the
following example:</P>
<code class="prefix edit"><comment>Rem Demonstrate that a procedure is being called not simply a command</comment>
Proc HELLO
<comment>Rem The same can be achieved without the Proc</comment>
HELLO
Procedure HELLO
Print "Hey!"
End Proc
</code>
<P>It is possible to place the procedure definition anywhere in your program. When AMOS
Professional encounters a procedure statement, the procedure is recognised and a jump is
made to the final End Proc. In this way, there is no risk of executing your procedure by
accident.</P>
</section>
<section id="03-opening-and-closing-procedures">
<h2>Opening and closing procedures</h2>
<p>If a great many procedures are used, your listings may appear cluttered and confused by
all of their definitions. Because of this problem, there is a simple method of "closing" a
procedure. Self-contained procedures can be neatly hidden away inside your main program if you need
to reduce the size and complexity of your listings.</P>
<P>Type in the following procedure on your editing screen:</P>
<code class="prefix edit">MAIN_TITLE
Procedure MAIN TITLE
Curs Off
Centre "Main Title"
Say "AMOS Professional presents."
Fade 5
End Proc
</code>
<P>Run that if you like, and then return to the Edit screen.</P>
<P>
Make sure that the edit cursor is over the procedure statement, select the [Procedures]
option rom the [Editor] menu and trigger the [Open/Close] option, or hit <kbd>F9</kbd> as a short-cut. The
procedure definition is neatly folded away from view, and in normal practice you would be
allowed to concentrate on your main program without the distraction of chunks of
procedures getting in the way. In other words, you can achieve greater programming clarity in your
listings by closing procedures from view. The last example should now look like this:</P>
<code class="prefix ex">MAIN TITLE
Procedure MAIN_TITLE
</code>
<P>To reveal the procedure at any time, simply move the cursor back to the procedure line
and reveal its definitions with <kbd>F9</kbd> or [Open/Close].</P>
<P>Closed procedures can be executed as normal, and saved or loaded along with an AMOS
Professional program listing. But a closed procedure cannot be deleted using the program
cursor, and a deletion can only be made if the procedure is opened again or by means of
the [Cut] option.</P>
<P>
To open and close all of the procedures in the current program, the [Open All] and
[Close All] options are provided. Alternatively, you can use the keyboard short-cuts <kbd>Amiga</kbd>+<kbd>Shift</kbd>
+<kbd>0</kbd> and <kbd>Amiga</kbd>+<kbd>Shift</kbd> + <kbd>C</kbd>, as already explained under the full list of Editor options in
<a href="04-01-the-editor.html">Chapter 4.1</a>.</P>
</section>
<section id="04-jumping-in-and-out-of-a-procedure">
<h2>Jumping in and out of a procedure</h2>
<p>You should be familiar with the use of ON for jumping to a GOSUB routine. It is just as
simple to use this structure with procedures.<BR>
<h3 class="command" id="str-on-proc">ON ... PROC</h3>
<p><i>structure: trigger a jump to a procedure</i><BR>
<b>On</b> variable value <b>Proc</b> NAME</P>
<P>In this case, if a variable holds a particular value, a system is automatically
triggered that forces a
jump to a named procedure. Of course you can have as many values triggering off as many
jumps to different procedures as you want. For example:</P>
<code class="prefix ex">On X Proc PROCEDURE1,PROCEDURE2</code>
<P>Which is exactly the same as saying:</P>
<code class="prefix ex">If X=1 Then PROCEDURE1</code>
<br>
<code class="prefix ex">If X=2 Then PROCEDURE2</code>
<P>Normally, procedures will only return to the main program when the END PROC instruction
is reached. But supposing you need to jump out of a procedure instantly.</P>
<h3 class="command" id="str-pop-proc">POP PROC</h3>
<p><i>structure: leave a procedure immediately</i><BR>
<b>Pop Proc</b></P>
<P>
The POP PROC instruction provides you with a fast getaway, if you ever find yourself in
need of escape. Try this:</P>
<code class="prefix edit">ESCAPE
Procedure ESCAPE
For PRISON=1 To 1000000000
If PRISON=10 Then Pop Proc
Print "I am abandoned."
Next PRISON
End Proc
Print "I'm free!"
</code>
<h3 class="command" id="str-on-break-proc">ON BREAK PROC</h3>
<p><i>structure: jump to a procedure when break in program</i><BR>
<b>On Break Proc</b> NAME</P>
<P>A jump can also be made to a specified procedure when the program is interrupted. For
example:</P>
<code class="prefix edit">On Break Proc BROKEN
Do
Print "Unbroken" : Wait 50
Loop
Procedure BROKEN
Print "I am the procedure"
End Proc
</code>
</section>
<section id="05-local-and-global-variables">
<h2>Local and global variables</h2>
<p>All of the variables that are defined inside a procedure work completely separately
from any other variables in your programs. We call these variables "local" to the procedure. All
local variables are automatically discarded after the procedure has finished executing, so that
in the following example the same value of 1 will always be printed, no matter how many times it
is called:</P>
<code class="prefix ex">Procedure PLUS
A=A+1 : Print A
End Proc
</code>
<P>
All the variables OUTSIDE of procedures are known as "global" variables, and they are
not affected by any instructions inside a procedure. So it is perfectly possible to have the
same variable name referring to different variables, depending on whether or not they are local
or global.</P>
<P>When the next example is run, it can be seen that the values given to the global
variables are different to those of the local variables, even though they have the same name.</P>
<p>Because the global variables cannot be accessed from inside the procedure, the procedure
assigns a value of zero to them no mater what value they are given globally.</p>
<code class="prefix edit">A=666 : B=999
EXAMPLE
Print A,B
Procedure EXAMPLE
Print A,B
End Proc
</code>
<p>To avoid errors, you must treat procedures as separate programs with their own sets of variables
and instructions. So it is very bad practice for the AMOS Professional programmer to use the
same variable names inside and outside a procedure, because you might well be confused into
believing that completely different variables were the same, and tracking down mistakes would
become a nightmare. To make life easy, there are simple methods to overcome such problems.</p>
<p>One method is to define a list of parameters in a procedure. This creates a group of local
variables that can be loaded directly from the main program. For example:</p>
<code class="prefix edit">Procedure HELLO[NAME$]
Print "Hello ";NAME$
End Proc
<comment>Rem Load N$ into NAME$ and enter procedure</comment>
Input "What is your name?",N$
HELLO[N$]
<comment>Rem Load string into NAME$ and call HELLO</comment>
HELLO["nice to meet you!]
</code>
<p>Note that the values to be loaded into NAME$ are entered between square brackets as part of
the procedure call. This system works equally well with constants as well as variables, but
although you are allowed to transfer integer, real or string variables, you may not transfer arrays
by this method. If you need to enter more than one parameter, the variables must be separated
by commas, like this:</p>
<code class="prefix ex">Procedure TWINS[A,B]
Procedure TRIPLETS[X$,Y$,Z$]
</code>
<p>Those procedures could be called like this:</p>
<code class="prefix ex">TWINS[6,9]
TRIPLETS["Xenon","Yak","Zygote"]
</code>
<h3 class="command" id="str-shared">SHARED</h3>
<p><i>structure: define a list of global variables</i><br>
<b>Shared</b> list of variables</p>
<p>There is an alternative method of passing data between a procedure and the main program.
When SHARED is placed inside a procedure definition, it takes a list of local variables separated
by commas and transforms them into global variables, which can be directly accessed from the
main program. Of course, if you declare any arrays as global using this technique, they must
already have been dimensioned in the main program. Here is an example:</p>
<code class="prefix edit">A=666: B=999
EXAMPLE
Print A,B
Procedure EXAMPLE
Shared A,B
A=B-A: B=B+1
End Proc
</code>
<p>EXAMPLE can now read and write information to the global variables A and B. If you need to
share an array, it should be defined as follows:</p>
<code class="prefix ex">Shared A(),B#(),C$()</code>
<p>In a very large program, it is often convenient for different procedures to share the same set of
global variables. This offers an easy way of transferring large amounts of information between
your procedures.</p>
<h3 class="command" id="str-global">GLOBAL</h3>
<p><i>structure: declare a list of global variables for procedures</i><br>
<b>Global</b> list of variables</p>
<p>GLOBAL sets up a list of variables that can be accessed from absolutely anywhere in your
program. This is a simplified single command, designed to be used without the need for an
explicit SHARED statement in your procedure definitions. Here is an example:</p>
<code class="prefix edit">A=6 : B=9
Global A,B
TEST1
TEST2
Print A,B
Procedure TESTI
A=A+1 : B=B+1
End Proc
Procedure TEST2
A=A+B : B=B+A
End Proc
</code>
<p>AMOS Professional programmers who are familiar with earlier versions of the AMOS system are
now able to employ the new facility of using strings in procedure definitions. As with disc
names, the "wild card" characters * and ? can also be included. In this case, the * character is</p>
<P>
used to mean "match this with any list of characters in the variable name, until the next
control character is reached", and the ? character means "match this with any single character in
the variable name". So the next line would define every variable as global:</P>
<code class="prefix ex">Global "*"</code>
<P>Now look at the following example:</P>
<code class="prefix ex">Shared A,"V*","VAR*END","A?0S*"</code>
<P>That line would declare the following variables as shared:</P>
<UL>
<LI>A, as usual.</LI>
<LI>Any variable beginning with the character V, followed by any other characters, or on
its own.
</LI>
<LI>Any variable beginning with the letters VAR, followed by any other characters, and
ending with the characters END.
</LI>
<LI>Any variable beginning with A, followed by any single letter, followed by OS,
followed by any other characters.
</LI>
</UL>
<P>
GLOBAL or SHARED should be employed before the first use of the variable, otherwise it
will have no effect on an interpreted program, although it will affect programs compiled with
the AMOS Professional Compiler.</P>
<P>
Only strings may be used for this technique. Global and shared arrays cannot be defined
using wild cards. These must be defined individually, using brackets. Also, if you try to use an
expression in this way, an error will be generated.<BR>
For example:</P>
<code class="prefix ex">A$="AM*"
Global A$
</code>
<P>
In that case, the A$ variable would be regarded as global, and it would not be taken as
a wild card for subsequent use.</P>
<P>With AMOS Professional, you are able to define global arrays from a procedure, even if
the array
is not created at root level, as follows:</P>
<code class="prefix ex">Procedure VARIABLES
Dim ARRAY(100,100)
Global ARRAY()
End Proc
</code>
</section>
<section id="06-returning-values-from-a-procedure">
<h2>Returning values from a procedure</h2>
<p>If you want to return a parameter from inside a procedure, that is to say, if you need
to send back a value from a local parameter, you need a way of telling your main program where to
find this local variable.</P>
<h3 class="command" id="fn-param">PARAM</h3>
<p><i>function: return a parameter from a procedure</i><BR>
<b>Param</b><BR>
<b>Param#</b><BR>
<b>Param$</b></P>
<P>
The PARAM function takes the result of an expression in an END PROC statement, and
returns it to the PARAM variable. If the variable you are interested in is a string variable, the
$ character is used. Also note how the pairs of square brackets are used in the next two examples:</P>
<code class="prefix edit">JOIN_STRINGS["one","two","three"]
Print Param$
Procedure JOIN_STRINGS[A$,B$,C$]
Print A$,B$,C$
End Proc[A$+B$+C$]
</code>
<P>For real number variables, the # character must be used as in the following example:</P>
<code class="prefix edit">JOIN_NUMBERS[1.5,2.25]
Print Param#
Procedure JOIN_NUMBERS[A#,B#]
Print A#,B#
End Proc[A#+B#]
</code>
</section>
<section id="07-local-data-statements">
<h2>Local data statements</h2>
<P>Any data statements defined inside your procedures are held completely separately from those
in the main program. This means that each procedure can have its own individual areas of data.
Let us end this Chapter with a modest example that calls the same procedure using different
parameters, and then sets up additional data in variables.</P>
<code class="prefix edit>">Curs Off : Paper 0
RECORD["Francois","Lionet",29,"Genius"]
RECORD["Mel","Croucher",44,"Unemployed"]
A$="Richard" : B$="Vanner" : AGE=25 : OCC$="Slave Driver"
RECORD[A$,B$,AGE,OCC$]
Procedure RECORD[NAME$,SURNAME$,AGE,OCC$]
Cls 0: Locate 0,3
A$=NAME$+" "+SURNAME$
Centre A$: Locate 0,6
A$="Age: "+Str$(AGE)
Centre A$: Locate 0,9
A$="Occupation: "+OCC$
Centre A$: Locate 0,16
Centre "Press a key" : Wait Key
End Proc
</code>
</section>
<footer>
<a href="05-04-control-structures.html" rel="prev">Control Structures</a>
<a href="./">Contents</a>
<a href="14-appendix-g-command-index.html">Index</a>
<a href="05-06-text.html" rel="next">Text</a>
</footer>
</body>
</html>