# Changes between Version 2 and Version 3 of PIR Tutorial

Show
Ignore:
Timestamp:
03/22/09 15:29:43 (13 years ago)
Comment:

Added the rest of the content

Unmodified
Removed
Modified
• ## PIR Tutorial

v2 v3
7777Now we know how to store numbers and strings, let's do some operations on those values.
7878
79 == Calculating things ==
79=== Calculating things ===
8080
8181Calculating things is as trivial as you might expect. We'll give some full examples below, so you can copy+paste the code and run it yourself:
8282
83 === ABC formula ===
83==== ABC formula ====
8484
8585{{{

133133}}}
134134
135 The dot is short in PIR for the concat operation. It takes 2 strings and concatenates them. Just as the assignment operations in the ABC formula example (x2 /= \$N3), this can also be done with strings using the .= operator.
135The dot is short in PIR for the concat operation. It takes 2 strings and concatenates them. Just as the assignment operations in the ABC formula example `(x2 /= \$N3)`, this can also be done with strings using the `.=` operator.
136136
137137As mentioned, Parrot has many instructions. This tutorial will not list all of them, but instead you could take a look at [http://docs.parrot.org/parrot/latest/html/ops.html the list of ops by category].
138
139=== More on subroutines ===
140
141This section will discuss a little bit more on subroutines so you can do some useful stuff. Although there's much more to subroutines, we'll postpone that to a later section.
142Passing parameters
143
144In order to pass parameters to a sub, you'll need to define these parameters. This is easy:
145{{{
146  .sub foo
147    .param int n
148    .param string message
149    # do something useful
150  .end
151}}}
152
153Sometimes you want a subroutine that might take a parameter, depending on the situation. In that case you'd want to use optional parameters.
154Returning values
155
156If you remember the example in which we implemented the ABC formula, you could see that we calculated them, but only printed them. Usually, you'd like to have some subroutine calculate something and then return the answers. Instead of printing them, you could return the answers, as shown in this code snippet:
157{{{
158  .sub abc
159    .local num x1, x2
160    # do some calculations
161    .return (x1, x2)
162  .end
163}}}
164
165=== Invoking subroutines ===
166
167Now you know how to define parameters and return values, it's time to explore how to invoke your subroutine. Some examples:
168{{{
169  .sub main
170    # invoke 'foo' without parameters, no return values
171    foo()
172
173    # invoke 'bar' with parameters \$I0, 42, and "hi", no return values
174    \$N0 = 3.14
175    bar(\$I0, 42, "hi")
176
177    # invoke 'baz' with parameters \$N2, "hello yourself", and return values
178    .local int a
179    .local num b
180    .local string c
181    \$N2 = 2.7
182    (a, b, c) = baz(\$N2, "hello yourself")
183
184  .end
185
186  .sub foo
187    print "Foo!\n"
188  .end
189
190  .sub bar
191    .param num i
193    .param string message
194    print "Bar!\n"
195    print i
196    print "\n"
198    print "\n"
199    print message
200  .end
201
202  .sub baz
203    .param num e
204    .param string msg
205    print "Baz!\n"
206    print e
207    print "\n"
208    print msg
209    .return (1000, 1.23, "hi from baz")
210  .end
211}}}
212
213=== Controlling the flow of your program ===
214
215PIR as a few instructions to control the flow of your program. This section describes them.
216
217==== Goto statements ====
218
219The most basic one is of course the goto instruction. It's very simple:
220{{{
221    ...
222    goto L1
223  L1:
224    print "hi!\n"
225    ...
226}}}
227
228Although the use of goto is not adviced in high-level languages (HLLs), in PIR you are hardly able to write useful programs without it. Besides, PIR is assembly language after all, so that's ok.
229
230==== If statements ====
231
232PIR has a built-in if statement. It can take three forms:
233
234Evaluate an atomic expression:
235{{{
236    ...
237    .local int x
238    x = 1
239
240    if x goto L1
241    ...
242  L1:
243}}}
244
245Evaluate a binary expression:
246{{{
247  ...
248  .local int x
249  x = 1
250
251  if x == 2 goto L2
252  ...
253}}}
254
255Evaluate an object expression:
256{{{
257  ...
258  .local pmc obj
259
260  if null obj goto L3
261  ...
262}}}
263
264If obj is null, then the execution engine will continue at label L3. More on PMCs soon.
265
266==== Unless statements ====
267
268While an if statement is useful, it is sometimes more efficient to use the unless instruction. It's the opposite of the if statement, and jumps to the specified label unless its argument is true. Its format is exactly the same as the if statement, except the word if is replaced by unless. So you should be able to figure out how to write the unless instruction.
269Loop constructions
270
271PIR has no built-in while or for statement, but implementing a loop can be easily done using the if statement, some *goto*s and a couple of labels, like this:
272{{{
273    ...
274    .local int i
275    i = 0
276  loop_begin:
277    if i >= 10 goto loop_end
278    print i
279    print "\n"
280    i += 1
281    goto loop_begin
282  loop_end:
283    ...
284}}}
285
286this loop will print the numbers 0 to (but not including) 10 to the screen.
287
288==== Splitting your program into several files ====
289
290Sometimes it's easier to split up your program into multiple files. There are two ways to do this:
291 * use the .include directive
292 * compile the PIR files separately and load them using load_bytecode
293
294The first way is the simplest. Use the .include directive at a point in your main file where you'd like to pull in the contents of another file. The contents of the specified file is read and replaces the .include directive, just as the #include directive does in the C preprocessor.
295
296An example will show what happens:
297
298contents of the main file:
299{{{
300  .sub main
301    foo()
302  .end
303
304  .include "foolib.pir"
305}}}
306
307And the file foolib.pir contains:
308{{{
309  .sub foo
310    print "foo!\n"
311  .end
312}}}
313
314After processing the .include directive, the input to the PIR compiler looks like this:
315{{{
316  .sub main
317    foo()
318  .end
319
320  .sub foo
321    print "foo!\n"
322  .end
323}}}
138324