The SRP PreCompiler is unlike any other stored procedure in the SRP Utilities collection. It is not a utility you explicitly call. It is, rather, a total enhancement to the BASIC+ language. Indeed, we've come to call the many syntax improvements it provides Enhanced BASIC+.
You do not need the SRP Editor to invoke the SRP PreCompiler. You simply need to include the following line of code at the top of your program:
This one line instructs the OpenInsight compiler to pass your program to SRP_PreCompiler before passing it on the standard BASIC+ compiler, given the SRP PreCompiler to ability to trans-compile new language features into fully supported ones. These new features are documented here.
Extended BASIC+ Syntax
For Each Loops
For each loops offer a convenient way to walk through a dynamic array from beginning to end. If you have an @FM delimited array, you can do this:
You no longer have to keep track of nesting iterators, extract the current element, and worry about nasty inefficiencies. This represents a massive increase in productivity and readability.
Custom delimiters are supported via the using keyword.
You can safely nest For Each loops as well.
Sometimes, we still need to know the position of the current element. In that case, you can use the setting keyword.
Conditional Return Statement
The SRP PreCompiler extends the Return statement to make it easy to perform a sanity check on the return value. Most people are familiar with the following syntax:
This code ensures we never accidentally return an unassigned variable. Now, with the help of SRP PreCompiler, we can do this in a single line:
Note that this syntax should only be used for the stored procedure's final Return statement, not for returning from a gosub.
SRP has been a big advocate for organizing code into Service Modules: stored procedures in which the first parameter identifies a service to execute. Normally, this involves branching to gosubs, mapping the input variables, and making sure the stored procedure has enough parameters to cover all the services' needs. Here is a traditional example:
The SRP PreCompiler reduces much of the ceremony involved in this architecture.
First, we save time using parameter placeholders, like so:
The @SERVICE parameter is required by the SRP PreCompiler to identify it as a service module. The @PARAMS placeholder negates the need to update the parameter list every time you add a new service. The SRP PreCompiler will take care of it for you.
Now, we can simply our branching logic from a long Case statement into a single one:
The GoToService keyword uses the @SERVICE parameter to determine what service to jump to. If the service does not exist, it gives you the chance to handle that via the else clause. If you don't want to handle it, you can certainly do it in one line.
Now, we write our services. In the past, we did this using standard gosub labels. Now, we use the Service keyword and we list the parameters the service expects:
Our services now look like tiny functions within the same stored procedure, complete with their own pass-by-value parameters. When the service is called, we can manipulate the parameters as we see fit without altering the original values passed into the service in the first place. This is good design as most callers expect their parameters to remain unchanged. In the rare case you need to pass back changes to a service parameter, like in the AddSalesTax example above, you can precede the parameter with the Ref keyword.
You will also notice the Options keyword. This is purely for documentation purposes and will prove
Here is the final code of our service module. It is arguably much cleaner.
The SRP PreCompiler also produces meta data about the service when you compile. This metadata can be used by tools such as the SRP Editor to give you coding hints. This makes you much more productive as you can get the information you need about each service as you program.
One such feature, which only the SRP Editor takes advantage of, is options. Options allow you to document a limited set of values for a parameter.
The Options keyword lets you name a set of options, ADDRESSTYPES in this case, and then assign that name a comma delimited list of quoted or unquoted values. Then, you assign the options, by name, to any parameter that uses those options. In the above example, we assign ADDRESSTYPE options to the AddressType parameter.
Again, this has no effect on how your code functions, but if you are in the SRP Editor, those options will appear in a drop down as you type.
Commuter modules have been around for some time, and they are structured very similarly to services. Typically, gosubs are created for each event, and a large case statement uses the current control and event to branch to the correct handler. Here is a typical example:
The SRP PreCompiler can clean this up quite nicely. First, we use parameter placeholders in at the top.
This placeholder will allow us to add new event handlers at will without having to remember how many parameters are needed at the top.
Next, we replace the large case statement with a simple branching statement.
The GoToEvent statement takes an event name and a control ID, and uses them to branch to the correct event handler. If the handler doesn't exist, then it jumps to the optional else clause. Omitting the else close is permitted.
Now, we can rewrite our event gosubs using the Event keyword and supplying named parameters.
With the SRP PreCompiler, we can rewrite the entire example as so:
Once again, we've simplified the usually tedious task of keeping our commuter module up to date. When a new event handler is need, just add the handler and the SRP PreCompiler will take care of the rest.
If you use the SRP Editor, you can take advantage of another productivity feature: event autofill. To use it, add the following line at the top of your code:
Replace MY_WINDOW_NAME with the window you want attached to your commuter module. Once you do this, you will get drop downs when writing event handlers.
Moreover, the SRP Editor will autofill the event's parameters, saving you valuable time.
Unit Test Modules
Unit Test Modules are stored procedures containing multiple related tests.
NOTE: Unit Test Modules are only really useful within the SRP Editor. When a Unit Test Module is compiled, metadata for tests are stored in the system and the tests appear within the SRP Editor UI. This allows you to run any number of unit tests and examine their results.
They have a similar syntax as Service Modules and Event Modules. Here's a sample:
The main feature of the Unit Test Module is the Assert statement. It has the following syntax:
This statement is key to making unit tests work. When the evaluation fails, the SRP Editor will display the two values side by side for easy comparison.
The SRP PreCompiler will work in any BASIC+ editor, but there is an important caveat to using Enhanced BASIC+ in anything other than the SRP Editor. The SRP Editor recognizes the new syntax and highlights code accordingly whereas the builtin OI Editor will not. Everything will still compile and run, but it will a little harder to read. Moreover, some features of the PreCompiler, such as the metadata, won't impede your code, but you also won't get the most out of your development outside of the SRP Editor.
Another issue with the SRP PreCompiler is that precompiling doesn't produce errors. Thus, if you make an error in the new syntax, the resulting error can be confusing.
Lastly, if you are using SRP PreCompiler, it's best to avoid using variable names that match the keywords Service, Test, and Event. The SRP Precompiler will do it's best to avoid confusing variables with keywords, but it's not bulletproof. It's better to avoid using them at all if you can help it.