When talking about safety in programming, it is memory safety that usually takes the spotlight. However, here we’ll touch on another common safety issue that typically causes application logic errors, meaning your program won’t function correctly. It’s about checking the status of any kind of statement that provides it. Not checking the status could mean that the result of a statement isn’t correct, yet your program is proceeding as if it were. Of course, this is bound to cause problems, and this is true for any programming language.
Golf now has a built-in mechanism to help prevent issues like this. The approach taken (at this time at least) is not to force the developer to check status for every statement. Rather if status isn’t checked, your program will stop in an orderly fashion and tell you exactly in which source file and which line number you didn’t check the status that may cause an issue. It’s a default fine line between code bloat and safety. Not every status needs to be checked. And this approach helps pinpoint the most pressing spots in your code where failure is the most likely to happen.
Another future enhancement is in the queue, which would allow (as an option) to force status checking on all statements.
Put the following code in file “file-name.golf” in a separate directory:
%% /file-name public
silent-header // don't output HTTP header
get-param fname // get file name we'll read
change-dir run-dir // change to directory we ran this program from
read-file fname to file_content // read file
// Transform file contents
match-regex "File: ([0-9]+).imp" in file_content replace-with "\1" result res cache
// Print out the result
p-out res
%%
This will take file name (“fname”) as an input parameter, read that file, and transform any text in it that starts with “File: ” followed by a file name that’s made up of digits (without an extension), and outputs those file names. So a bit contrived example, and arguably the point here has nothing to do with matching regex patterns. But it’s an example from a real-world application, so I plugged it in just the same.
So, let’s say the input file is “myfile” with contents:
File: 99281.imp
File: 3716243.imp
File: 124.imp
To test this, let’s create an application:
gg -k file-transform
Make the application:
gg -q
Run it:
gg -r --req="/file-name/fname=myfile" --exec
And the output is, as it should be:
99281
3716243
124
Okay, so far so good. But let’s run this program by specifying a non-existent file:
gg -r --req="/file-name/fname=nonexistent" --exec
The output is:
File [file-name.golf], line [5], Statement failed without status being obtained and/or checked [-1]
Aha! So your program will safely stop as soon there’s a failure in code where you didn’t check for status, namely this line (number 5) from the code above:
read-file fname to file_content // read file
Now, let’s add status and check it, so replace “file-name.golf” with this:
%% /file-name public
silent-header // don't output HTTP header
get-param fname // get file name we'll read
change-dir run-dir // change to directory we ran this program from
read-file fname to file_content status st// read file
if-true st not-equal GG_OKAY
@Sorry, cannot open file <<p-out fname>>!
end-if
// Transform file contents
match-regex "File: ([0-9]+).imp" in file_content replace-with "\1" result res cache
// Print out the result
p-out res
%%
Compile it and run again:
gg -q
gg -r --req="/file-name/fname=nonexistent" --exec
And the result is:
Sorry, cannot open file nonexistent!
So now you can see how useful the automatic “static checking” feature is. It prevented unsafe execution (logic-wise) from moving forward, and provided you with a clear clue as to how to fix the issue. For more on Golf, go to golf-lang.com .