Page 2 of 3

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Thu Apr 20, 2017 12:00 am
by EmmBee
ql_freak wrote:Is there a S(uper)BASIC-function which tests if a variable is set?

e.g.:

Code: Select all

REMark Turbo Toolkit required for END_CMD
IF NOT variableSet(a_%):END_CMD
REMark Alternative: IF NOT variableSet("a_%"):END_CMD
REMark Continue with command file only if a_% is set
REMark ... (your commands)
END_CMD
In SBASIC (SMSQ/E on QPC2) you can use:

IF NOT a_%:END_CMD

But this does unfortunately not (even) work on Minerva :-( It is also not what I want, cause if a_% is 0 the command file will always stop. But perhaps the command file should continue and use the value 0.
Hi ql_freak,

I believe there is a slight misunderstanding with how "END_CMD" works. What END_CMD actually does is to close the command file, so that everything is hunky dory with the operating system. It has no effect on command execution, and will not STOP any following commands from continuing. Therefore I can suggest you try placing just one single END_CMD as the first executable command, and replace all other occurrences of END_CMD with STOP.
EDIT:

Found a function from Turbo Toolkit: BASIC_INDEX%(name$) does it. Returns a value <0 if no such name exists.
Agreed, this does do it, yes, but there is an unforeseen forthcoming ... Suppose we have as our currently loaded program ...

Code: Select all

100 x% = 100
110 y% = 100
Now, both x% and y% are genuine names and BASIC_INDEX%() will return there actual index in the SuperBASIC name table, which will be a non negative integer.
However, suppose that the program has not been RUN yet! What this means is that both x% and y% will not have obtained any values. If PRINTed, both x% and y% will print out as "*"s, asterisks. There is the need to check for this UNSET status. Jan Bredenbeek has pointed out PARUSE, which I believe will still work outside of procedures and functions. There is also my own suggestion of the UNSET function from DIY toolkit Volume "P".

The above applies only to QDOS. Under SBASIC, x% and y% will have obtained default values of zero.
Perhaps a check is needed to test for version, e.g. IF VERS="JSL1" or IF VER$="HBA", etc.

It is perhaps a question of trial and error, and finding out which will work on your own systems. I personally find programming can be most frustrating even at the best of times. Nothing seems to work, at least at first, it is bug after bug after bug. The most simplest of problems can often turn out to be the most time-consuming. It can take an age to get a program to run as expected. I believe this to be true regardless of the language being used, not just SuperBASIC.

Best wishes,
EmmBee

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Thu Apr 20, 2017 12:22 am
by ql_freak
Hello EmmBee,
EmmBee wrote: Hi ql_freak,

I believe there is a slight misunderstanding with how "END_CMD" works. What END_CMD actually does is to close the command file, so that everything is hunky dory with the operating system. It has no effect on command execution, and will not STOP any following commands from continuing. Therefore I can suggest you try placing just one single END_CMD as the first executable command, and replace all other occurrences of END_CMD with STOP.
STOP has'nt worked here in command files (without line numbers) but END_CMD does, see my script, it's working very well now and I use it often. The END_CMD definitly closes the file and so the rest of the commands where not read, that's what I want.
EmmBee wrote:Agreed, this does do it, yes, but there is an unforeseen forthcoming ... Suppose we have as our currently loaded program ...

Code: Select all

100 x% = 100
110 y% = 100
Now, both x% and y% are genuine names and BASIC_INDEX%() will return there actual index in the SuperBASIC name table, which will be a non negative integer.
However, suppose that the program has not been RUN yet! What this means is that both x% and y% will not have obtained any values. If PRINTed, both x% and y% will print out as "*"s, asterisks. There is the need to check for this UNSET status. Jan Bredenbeek has pointed out PARUSE, which I believe will still work outside of procedures and functions. There is also my own suggestion of the UNSET function from DIY toolkit Volume "P".
Ah I didn't know that, I will try it with PARUSE or the UNSET function from DIY toolkit. Thank You.
EmmBee wrote:Best wishes,
EmmBee
I also wish you the best,

Peter

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Thu Apr 20, 2017 11:41 am
by Silvester
Re Moving SB windows:

Marcel recently created Toolkit 2.31 suitable for QDOS/Minerva platforms with latest versions of TK2 commands including extended WMON command which accepts WMON mode,x%,y% (see SMSQ/E manual for use).

Edit : WMON requires OUTLN set, ignore this-->
I've tried TK231.rom on UQLX and WMON only works with PE present. It neatly moves standard windows around screen, though it doesn't remove old contents (like SMSQmulator). But you can get around it on UQLX PE by doing this:

WINDOW#0;SCR_XLIM,SC_YLIM,0,0:CLS#0:WMON 4,x_%,y_%

Though problems arise if x/y puts windows partially out of bounds: SMSQmulator skews #1/#2 placement, whereas UQLX ignores WMON and leaves #0 as whole screen. Perhaps WMON (sbsext_ext_wind_asm) can be tweaked to avoid out of bounds beforehand. It would also be useful to have configurable default WMON parameters.


Re SMSQ/E BASIC unset variables:

As much as I love SMSQ/E Basic, I dislike the way unset variables default to zero. I have almost teared my hair out trying to find a bug in a large listing, only to eventually find it was a simple typo in a long variable name. Tempted to write procedure to list unset variables after program has run to catch that (TYPO_LIST[#ch]).

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Thu Apr 20, 2017 11:24 pm
by janbredenbeek
EmmBee wrote: However, suppose that the program has not been RUN yet! What this means is that both x% and y% will not have obtained any values. If PRINTed, both x% and y% will print out as "*"s, asterisks. There is the need to check for this UNSET status. Jan Bredenbeek has pointed out PARUSE, which I believe will still work outside of procedures and functions. There is also my own suggestion of the UNSET function from DIY toolkit Volume "P".
I can confirm that PARUSE works outside procedures. Of course there are alternatives but it's a TK2 function which is readily available on QDOS/Minerva and built-in on SMSQ/E.

Jan.

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Fri Apr 21, 2017 5:11 am
by ql_freak
janbredenbeek wrote:I can confirm that PARUSE works outside procedures. Of course there are alternatives but it's a TK2 function which is readily available on QDOS/Minerva and built-in on SMSQ/E.
Yes, I have tested it. PARUSE is also working outside functions. Unfortunately it has a bug (on Minerva and SMSQ/E):

It (sometimes/often) returns just 2, see Keyboard Reference Online Note2. I have tested it in my script, and got this error (albeit I have had tested it interactively before, where it seemed to work).

Maybe BASIC_INDEX% is not perfect, but it works at least in my script - live is full of risks ;-)

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Fri Apr 21, 2017 8:53 am
by Ralf R.
Aha, the same as with QLib? What a surprise.....

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Fri Apr 21, 2017 12:09 pm
by EmmBee
janbredenbeek wrote:If it has a value, it's name type (first byte of NT entry) will be 2, else 0.
ql_freak wrote: Yes, I have tested it. PARUSE is also working outside functions. Unfortunately it has a bug (on Minerva and SMSQ/E):
Because of the bug in PARUSE, we could instead use Jan's earlier formula, and have code such as ...

Code: Select all

IF BASIC_INDEX%("x_%")<0:PRINT#0,"x_% (or y_%) not set! Aborting":END_CMD
IF NOT BASIC_B%( BASIC_L(24)+BASIC_INDEX%("x_%")*8 ): PRINT#0,"x_% (or y_%) not set! Aborting":END_CMD
IF BASIC_INDEX%("y_%")<0:PRINT#0,"y_% (or x_%) not set! Aborting":END_CMD
IF NOT BASIC_B%( BASIC_L(24)+BASIC_INDEX%("y_%")*8 ): PRINT#0,"y_% (or x_%) not set! Aborting":END_CMD
EmmBee

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Fri Apr 21, 2017 1:20 pm
by EmmBee
Silvester wrote:Re SMSQ/E BASIC unset variables:

As much as I love SMSQ/E Basic, I dislike the way unset variables default to zero. I have almost teared my hair out trying to find a bug in a large listing, only to eventually find it was a simple typo in a long variable name. Tempted to write procedure to list unset variables after program has run to catch that (TYPO_LIST[#ch]).
Yes, I quite agree. This is a serious weakness of SMSQ/E as compared to QDOS. With QDOS any typos would produce a nice friendly error in expression along with the line number, to point out the error. Even when a program is finished and appears to be working correctly, one can never to certain that the code is typo free. This constant anxiety is always in the mind. I wish you could right a procedure to check for unset variables, this would be extremely useful for all users. Have you thought out how this could be done? One would have to check for assignments for local variables in procedures and functions. Possibly one way to do this would be to have code added to the Turbo parser, to give out a warning message if some variable is used before being assigned to. Such a check would be of great benefit to all.

EmmBee

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Sat Apr 22, 2017 11:00 am
by Silvester
Have you thought out how this could be done?
I was only considering just scanning SuperBASIC name table and list out names of unset variables. Easily done, soon...

Re: (Nearly) solved: FuNction which tests if a variable is set

Posted: Sat Apr 22, 2017 3:41 pm
by EmmBee
Silvester wrote:
Have you thought out how this could be done?
I was only considering just scanning SuperBASIC name table and list out names of unset variables. Easily done, soon...
I agree, this would be the easiest solution.
I've written a rough version. It scans through the name table looking for simple float or integer variables,
looks up the value, and if zero, prints out the name on #0.
Should be easy enough to modify if you want to include for strings as well.

Code: Select all

DEFine PROCedure typo
LOCal n_ptr, type, detail, ptr%, name$(127), vv
  FOR n_ptr = BASIC_L(24) TO BASIC_L(28) STEP 8
    type   = BASIC_B%(n_ptr)
    detail = BASIC_B%(n_ptr+1)
    ptr%   = BASIC_W%(n_ptr+2)
    IF ptr% > 0 AND type = 2 AND detail >= 2
      REMark simple float or integer variable
      name$ = BASIC_NAME$((n_ptr-BASIC_L(24))/8)
      vv = BASIC_L(n_ptr+4)
      IF vv >= 0
        IF detail=2 : IF BASIC_F (BASIC_L(40)+vv) = 0 : PRINT #0, ! name$ !!
        IF detail=3 : IF BASIC_W%(BASIC_L(40)+vv) = 0 : PRINT #0, ! name$ !!
      END IF
    END IF
  END FOR n_ptr
END DEFine typo
EmmBee