A procedure is a type of block. Every PsyScript script needs a procedure called main. When you hit the 'Run' button, PsyScript finds the main procedure, runs it, then stops. If your script has no proc main, PsyScript doesn't know what to do when you tell it to run your script.
Once your script gets bigger than a few lines you often end up with a series of commands you need to do, in the same sequence, in different places in a script. For instance, your experiment may have a set routine you use to display a fixation point for a few seconds, then remove it from the display. Doing this may take, for example, four lines of a PsyScript script. You may need to do it in three places in the script: once in a training section, again in a priming section, then again in the data-gathering section.
You could have three identical sequences of four lines in various places in the script. Anyone (including you) reading your script will need to repeately work out that those four lines do one thing. And if you later find you need to change how your fixation point works you have to find the three places and carefully make the same change three times. This gets annoying and is prone to errors, especially with a long script which does many things repeatedly.
So instead of making you do that PsyScript lets you put those lines together and call it a procedure. A procedure has a name and some lines of code. Once you have one all you need to do is 'call' the procedure and PsyScript breaks off what it's doing, executes those four lines of code, then continues where it left off. So the above setup might be …
(In the following, … is a convention for "There are some script lines here but I'm leaving them out for simplicity".)
Once you have this, if you need to change how your fixation point behaves, you only need to alter one set of code and it will change the way things are done in three separate parts of the script.
Once you find you can 'name' a section of your code, it turns out that procedures are useful not only for sections of your code you want to repeat, but also to divide up a long script into small managable parts. For instance, a script to run a complicated experiment might be 200 or 300 lines long. Looking down 300 lines of script to find the line that does a particular thing can be tedious. Instead you can divide your script up into named parts:
See how simple and clear the main procedure looks now ? It's a good explanation of what the script does and you don't have to read 400 lines of script to figure out what's going on.
As you can see from the above, you can have a procedure that calls another procedure which calls another procedure. There's no limit to the levels of nesting you can have. PsyScript keeps track of any number of points where it broke off to call another procedure, and will figure out where to return to each time it reaches the end of a procedure. When it reaches the end of the main procedure it knows it has finished running the script.
Looking at the above you may wonder what happens if you have a procedure which calls itself. If you haven't already, ponder this before you read on. You're back ? Okay, yes it would be a problem: each time you call the procedure it could just call itself again. The script would never end. Fortunately PsyScript tests for this and will stop it from happening, terminating the script with an error report. It does this even if the call is indirect, e.g. proc a calls proc b which calls proc c which calls proc a again.