TURBO parameter names

Anything QL Software or Programming Related.
tcat
Super Gold Card
Posts: 633
Joined: Fri Jan 18, 2013 5:27 pm
Location: Prague, Czech Republic

TURBO parameter names

Post by tcat »

Hi,

I am making my first steps with Turbo, and stumbled over parameter names.

This code runs normally under S*BASIC, but when CHARGEd, it complains about Array operation not allowed.

Code: Select all

100 DIM x(3)
110 LET x(1)= 1: x(2)= 2: x(3)= 3
120 putout x(1): putout x(3)
140 DEFine PROCedure putout (x)
150  PRINT x
160 END DEFine putout
I know it may seem silly to name a parameter same as a global variable. Renaming it to e.g. xx or whatever else, will do and make it compile normally. But I am just curious, if there is a better way of doing that?

Many thanks in advance

TCAT


User avatar
tofro
Font of All Knowledge
Posts: 2702
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: TURBO parameter names

Post by tofro »

This is a clear "no-no".

DIM is "extremely" global to Turbo and makes turbo think everything that is DIMed is an array.

You can even get more weird error messages (that is, Turbo will complain about the assignments once you try that) when you put the arguments to our procedure in brackets like

Code: Select all

putout (x(1))
So simply don't do it. Turbo doesn't generally like it;)

BTW Q-Liberator will happily compile and run your program.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
pjw
QL Wafer Drive
Posts: 1315
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: TURBO parameter names

Post by pjw »

Im a bit rusty, but in SBasic, which is the SMSQ/E variant of SuperBASIC, once you have DIMmed a variable you cant use the same name again as a scalar variable or function or procedure name. I believe the same holds true for SupberBASIC. Also, once youve defined a proc/function, you cannot DIM an array with the same name.

Regarding Turbo, there was a time when you could not pass arrays via the parameter list, whether they be for procs/functions written in SB or in m/c. This is why I abandoned Turbo many years ago. However, I seem to recall that something was planned or even changed to accommodate this feature in Turbo. Youll need to check the manual to find out.

QLiberator is the most compatible compiler around. Sadly it is no longer being developed and it is not free. If youre starting from scratch,though, Id stick with Turbo as it is still being maintained, is open source or similar, and is free, and in all likelihood it will suffice for most of what you want it to do. The object code is also probably faster.

Per


Per
dont be happy. worry
- ?
User avatar
pjw
QL Wafer Drive
Posts: 1315
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: TURBO parameter names

Post by pjw »

PS: There is no problem otherwise in re-using a (scalar) variable name as a parameter. Basically, it works the same a declaring a variable LOCal within the proc/fn, and will have no effect on any global variable of the same name. Great! It would be a fiddly to keep a library of proc/fns if one had to maintain a separate namespace for parameters and variables.

P


Per
dont be happy. worry
- ?
tcat
Super Gold Card
Posts: 633
Joined: Fri Jan 18, 2013 5:27 pm
Location: Prague, Czech Republic

Re: TURBO parameter names

Post by tcat »

Per,

I see, and thanks for explaining to me.
DIM [identifier] (...), appears more like a procedure anyway, and its identifier shall not be reused for any other purpose. That also keeps it on speaking terms with SMSQ/E

Turbo seems to have evolved greatly since you stopped using it.
I have just discovered that arrays, strings can be passed to procedures/functions either by VALue or REFerence.

Code: Select all

100 LET a$= 'abc': b$='ced'
110 val a$: ref b$
120 PRINT a$, b$
130 :
140 DEFine PROCedure val (s$)
150  s$= 'done'
160 END DEFine putout
170 :
180 REFERENCE s$
190 DEFine PROCedure ref (s$)
200  s$= 'done'
210 END DEFine
Once CHARGEd, and EXecuted, it puts out
abc done

I have scanned an article of QLWorld October '86 back issue on QLib and Turbo review.
Also enclosed a very recent changes to Turbo by Turbo Team 2014.
Attachments
turbo_changes.zip
TURBO v5.08 - 26th March 2014
(13.56 KiB) Downloaded 170 times
QLWorld_1986-10p17
QLWorld_1986-10p17
QLWorld_1986-10p16
QLWorld_1986-10p16


User avatar
pjw
QL Wafer Drive
Posts: 1315
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: TURBO parameter names

Post by pjw »

TCAT, Thanks for the info. The article compares Qlib with SuperCharge. which, with its Lenslock technology was a real PITA. Turbo, its successor, is considerably better. However, I see that it still wont accept arrays as parameters for SB procs/fns, only m/c ones. That frequently doesnt work for me. Id like to use Turbo, for the reasons I gave, but with some of its counter-intuitive quirks, I dont really consider it SB-compatible*. Id have to hobble my style to comply. And with the speed of modern QL systems, including emulators on fast PCs, the difference in speed between Turbo and QLib isnt normally an issue.

* Eg: In QLib-compatible SBasic all parameters are handled in a consistent, logical way. They are always passed by reference unless you want them not to. In your latest example changing the line 110 to:

110 val (a$): ref b$

ie, feeding the s$ paramters with an expression, will achieve the same: 'abc done'. (In SuperBASIC you may have to use something like val a$ & ''). There are no array operators in SB (the only operation supported is slicing) so arrays are always passed by reference.

Could the following program (or something that achieves the same) be done in a Turbo-compatible way? (Lines < 100 are just a harness to fill two complex arrays, one string and one numeric, and then clone (EQUate) those arrays into other, corresponding, arrays. LRUN in the standard S*Basic 3-window interpreter.)

Code: Select all

1 DIM a$(2,2,2,2,6),b$(2,2,2,2,8)
2 DIM x(2,2,2,2),y(2,2,2,2)
3 FOR i%=0 TO 2:FOR j%=0 TO 2:FOR k%=0 TO 2:FOR l%=0 TO 2:a$(i%,j%,k%,l%)='L'&i%&j%&k%&l%
4 count%=0
5 FOR i%=0 TO 2:FOR j%=0 TO 2:FOR k%=0 TO 2:FOR l%=0 TO 2:x(i%,j%,k%,l%)=count%:count%=count%+1
6 :
10 CLS:PRINT a$,\
12 er=EQU(b$,a$)
14 CLS#0:CLS#2:PRINT#2;b$,\:PRINT#0;er
16 BEEP 2000,20:PAUSE
18 CLS:PRINT !x!\
20 er=EQU(y TO x)
22 CLS#2:PRINT#2!y!\:PRINT#0;er\
24 BEEP 2000,20
26 :
100 REMark EQU SBASIC function to
101 REMark EQUate two arrays of the
102 REMark same dimensions and type
103 REMark Requires tk2 or equivalent
104 :
105 REMark   ©PWitte, August 1998
106 REMark For "educational" purposes only
107 REMark Use at own risk. No warranties!
108 :
1000 DEFine FuNction EQU(a,b)
1010 LOCal er
1020 IF PARTYP(a)<>PARTYP(b):RETurn -15
1030 IF PARUSE(a)<>PARUSE(b):RETurn -17
1040 er=0
1050 IF PARTYP(a)=1 THEN
1060  RETurn EQS(a,b)
1070 ELSE
1080  RETurn EQN(a,b)
1090 END IF
1100 END DEFine
1110 :
2000 DEFine FuNction EQN(a,b)
2010 LOCal i%
2020 IF DIMN(a)<>DIMN(b):RETurn -4
2030 IF DIMN(a(0))=0 THEN
2040  FOR i%=0 TO DIMN(a):a(i%)=b(i%)
2050 ELSE
2060  FOR i%=0 TO DIMN(a)
2070   er=EQN(a(i%),b(i%)):IF er<0:EXIT i%
2080  END FOR i%
2090 END IF
2100 RETurn er
2110 END DEFine
2120 :
3000 DEFine FuNction EQS(a,b)
3010 LOCal i%
3020 IF DIMN(a)<>DIMN(b):RETurn -4
3030 IF DIMN(a(0,0))=0 THEN
3040  FOR i%=0 TO DIMN(a):a(i%)=b(i%)
3050 ELSE
3060  FOR i%=0 TO DIMN(a)
3070   er=EQS(a(i%),b(i%)):IF er<0:EXIT i%
3080  END FOR i%
3090 END IF
3100 RETurn er
3110 END DEFine
3120 :
Interestingly you will see,that the parameter variable names and types are irrelevant - its the type of the passed parameter that counts, and although the variable names a and b have been used to represent an array in the parameter list and function body, they arent 'tainted' in the token list and can be reused as a scalar variable in the same program.


Per
dont be happy. worry
- ?
tcat
Super Gold Card
Posts: 633
Joined: Fri Jan 18, 2013 5:27 pm
Location: Prague, Czech Republic

Re: TURBO parameter names

Post by tcat »

Per,

I just learnt a new trick from you, I can pass a string to a procedure or function by value in intepreted S*BASIC, when making up a dummy expression, E.G.

Code: Select all

my_proc string_by_value$ & ""
Would it hold true also for numeric variables, E.G.

Code: Select all

my_proc num_by_value + 0

I quote from Turbo official docs, please read on, it CAN take arrays by reference
Inside a single program, TURBO passes parameters by value unless you
tell it otherwise. This is generally fine, but in cases where you may
want to change an actual parameter you can indicate this by listing
appropriate formal names in a REFERENCE directive, immediately before
the DEFinition of the routine.
You can pass arrays by reference, but not by value. The interpreter
imposes this rule too, as it saves the need to allocate and fill big
'temporary areas'. It doesn't matter, and saves lots of time, as long
as you only change array parameters when you really WANT to do so.

This routine searches an array for the values 0 and 100, returning the
number of instances of each value in the last two parameters:

REFERENCE table(0),nulls%,tops%
DEFine PROCedure search(table,size%,nulls%,tops%)
LOCAL i%
i%=0: nulls%=0: tops%=0
REPeat scan
IF I%>size% THEN EXIT scan
IF table(i%)=0 THEN nulls%=nulls%+1
IF table(i%)=100 THEN tops%=tops%+1
END REPeat scan
END DEFine search

Notice that the 'dummy subscript' 0 is used in the reference statement,
to show that TABLE is a one-dimensional array. This is not needed (or
allowed!) in the SuperBASIC DEFinition - another reason why we need a
new REFERENCE directive. If TABLE was a three dimensional integer array
the line would contain TABLE%(0,0,0).
Tom


User avatar
tofro
Font of All Knowledge
Posts: 2702
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: TURBO parameter names

Post by tofro »

Per,

your example shows one of the few things that Turbo is still not (and maybe never will be) capable of doing (and also the example the QLiberator makers have always been using to show its "superiority" over other compilers):

Turbo wants to "know" the type of actual parameter to a PROCedure or FuNction at compile time, QLiberator (and the Interpreter) are happily determining the actual type at run time - This is one of the main reasons why Turbo can be so much faster- and not a feature you can find in many compiled (even modern) languages. Or, the other way round, why QLiberator is, on SMSQ/E not noticably faster than the SBASIC interpreter.

But I agree that speed is not so much an issue any more on QPC2 or other emulators - While it still very much is on the original QL.

It is definitely more of interest what you can actually have at hand to compile something. A legal copy of QLiberator isn't very easy to find nowadays.

And that is right - with actual versions of Turbo, you can chose whether you want parameters passed by reference or value (except arrays) as long as the actual type is determined at compile time. The documentation is still a bit unclear on that in places.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
stevepoole
Super Gold Card
Posts: 716
Joined: Mon Nov 24, 2014 2:03 pm

Re: TURBO parameter names

Post by stevepoole »

Yes, we must be very careful with names :
100 PRINT 1
110 Define Procedure dummy
120 LOCAL PRINT(1)
130 PRINT(1)=2
140 PRINT 1
150 END DEFine
Try this in on a QL! Briefly, Local names can use any global name in the name table. This could be used within a program , for example, to disable printed ouput within a demo.
This won't work with define procedure(params) and define function(params), because such parameters are automatically local, but do not appear in the name table.
Generally, the best advice is to treat all names as global. That avoids bugs in long programs, and makes for better naming... especially for beginners.


EmmBee
Trump Card
Posts: 240
Joined: Fri Jan 13, 2012 5:29 pm
Location: Kent

Re: TURBO parameter names

Post by EmmBee »

This is a very nice idea, to disable the printed output during a demo. I find in order to get this to work, I have to add in the following ...

125 WHEN ERRor : CONTINUE : END WHEN

About the use of global names, the Turbo Parser is a good example, here. There is an amazing use of global variables, and they are all highly descriptive, which makes the program quite easy to understand.


Post Reply