Re:
> I've not seen SPL before.
> IF < THEN
In addition to the info you found, here's a "gotch" to
watch out for.
integer
fid,
ktr;
integer array
my'fids (0 : 9);
...
OK uses:
fid := fopen (...)
if <> then
my'fids := fopen (...);
if <> then
(BTW, the file ID is stored in my'fids (0))
BAD uses:
my'fids (ktr) := fopen (...);
if <> then
Why should the above be bad? Because the index operation (using "ktr")
is done after the fopen ... and loading a value from memory
changes the condition code accordingly :)
It would be better practice to say:
fid := fopen (...);
if fid = 0 then
...
Except, sigh, for the stupid use of "0" as a valid file number in Unix ...
Because of them, MPE/iX uses 0 as "stdin", so if you close stdin and then
re-open it, you can legitimately get back 0 as a valid file #.
BTW, I don't blame the MPE lab for starting to use 0 on MPE XL ... because
the larger world was also doing that. It's just that it's annoying :)
Of course, they could have added an easy-to-call alternate FOPEN that
would return a status parameter, or "-1" for failure :)
(HPFOPEN doesn't quite qualify as 'easy-to-call' in this case.)
There are at least five basic uses of condition codes in SPL:
1) Checking intrinsic results
The Intrinsics Manual documents if a given intrinsic sets the
condition code. If not documented, don't assume that it uses it!
As ugly as condition code checking is, at least its implemented
better than UNIX "errno", where you have to know (for each call)
whether a particular call always sets errno, or only sets it if there
is an error.
2) Checking the stop condition of a SCAN or WHILE statement.
There are higher level ways of doing this, which take an extra
instruction or two ... but the cost of those extra instructions is
negligble...you'll waste more of your time determining how to read
a CARRY/NOCARRY check after a SCAN/MOVE than you'll *EVER* use
with the higher level stuff.
(In this case, CARRY/NOCARRY is the "condition code" (very loose usage
of the term, of course) that I'm referring to, not literally the
Classic 3000 architecture's 2-bit condition code field).
E.g., replace:
scan p' until " "; ! stop on blank or null
(or: scan p' until [8/0, 8/" "])
if carry then
... *I* don't remember whether this means "hit blank" or
"hit 0" (it does mean one of those two :)
with (as appropriate):
if p' (scan p' until " ") = " " then
...found a blank
else
...found a null
3) Checking the stopping condition of a byte-array "IF" expression:
if p' = buf', (20) then
... the arrays match
else if < then
p' is alphabetically "less" than buf'
else ! cc is >
p' is alphabetically "greater" than buf'
4) Checking if a variable is negative, 0, or positive:
tos := i;
del;
if < then
...i is negative
else if = then
...i is 0
else
...i is positive
(or: dummy := i; if < then ...)
I replace those with:
if i < 0 then
...
else if i = 0 then
...
else
...
Sure...that takes an extra load/compare, but WHO CARES? It's far
more efficient when you take into account the time it took to write the
code in the first place, and the time used in later reading of the
code.
5. Getting a non-functional / non-parameter result back from a procedure
(Intrinsic results are one example, of course.)
Some programmers have chosen to use the same *bad* mechanism as
some intrinsics: using a condition code.
Example:
procedure my'proc;
begin
logical my'status = q - 1;
...
I want to return CCL:
my'status.(06:02) := 1; ! 1 is CCL
call:
...
my'proc;
if < then
...
Hope that's of interest.
Stan
* To join/leave the list, search archives, change list settings, *
* etc., please visit http://raven.utc.edu/archives/hp3000-l.html *
|