Externals, Functions and Procedures

Anything QL Software or Programming Related.
Tinyfpga
Gold Card
Posts: 295
Joined: Thu Sep 27, 2018 1:59 am

Externals, Functions and Procedures

Post by Tinyfpga »

I have been faffing around trying to understand, within my SMSQE/SMS2/Qlib systems, Externals, Functions and Procedures.

I have written many more test programs that fail than test programs that work, in a not completely futile attempt to learn by experiment. I have, of course read the instruction manuals concerning these concepts, but can understand only about 70% of the documentation and thus cannot workout by myself what I am doing wrong.

An example of my problem is note 4, page 154 of the BASIC ref. manual:-
"Although a sub-set of a simple string (what is a complex string?) is an expression (what is an expression?) and therefore will not be altered within a function, a sub-set of a string array (my translation of DIM string) is not treated as an expression and will therefore be altered!!"

What does the above mean? In my opinion coded examples are the best way to explain the use of an instruction.
My problem is that I use the ancient programming environment of SMS2 adapted for SMSQE and so I have to navigate around references to Interpreted BASIC and programming with line numbers to create my own method of creating test programs.

I am developing a standard way of testing BASIC instructions within a moveable windowing environment as can be seen in my JPG.
The four programs use a procedure compiled as an external that generates the image (EP_Mkw that takes a string parameter that is displayed in the title box). The programs then test passing an integer, a floating point number, a string and an array to a function called F_doit.

One can see that my attempt to pass and return an integer fails and my attempt to pass and return an array produces a strange result. The two others work correctly.

What am I doing wrong?
Externals, Functions  & Procedures.jpg


User avatar
desin
Brittle Membrane
Posts: 102
Joined: Mon May 10, 2021 10:33 am

Re: Externals, Functions and Procedures

Post by desin »

1 CLEAR : CLS
3 DIM A_x$(0,5)
5 A_x$(0,1)="a"
6 A_x$(0,2)="p"
9 :
17 :
20 b$=F_doit$ ("querty")
25 PRINT b$
27 :
28 B_x$=A_x$(0,TO 2)
30 c_x$=G_doit$ (B_x$)
35 PRINT A_x$(0,TO 2),c_x$
37 :
40 b% =doit%(3)
45 PRINT b%
47 :
50 b%= doit(4)
55 PRINT b%
57 :
99 :
100 DEFine FuNction F_doit$ (x$)
110 x$=x$&"12345"
120 RETurn x$
130 END DEFine
140 :
200 DEFine FuNction G_doit$ (z$)
210 z$=z$&"1234"
220 RETurn z$
230 END DEFine
240 :
300 DEFine FuNction doit% (x%)
310 x%=x%*10
320 RETurn x%
330 END DEFine
340 :
400 DEFine FuNction doit (x)
410 x=x*10
420 RETurn x
430 END DEFine

Hope it helps

Greetings from Switzerland
Markus


Tinyfpga
Gold Card
Posts: 295
Joined: Thu Sep 27, 2018 1:59 am

Re: Externals, Functions and Procedures

Post by Tinyfpga »

Thank you Markus,
When I get home this evening I will go through your code and see if I can test it on my system.


stevepoole
Aurora
Posts: 874
Joined: Mon Nov 24, 2014 2:03 pm

Re: Externals, Functions and Procedures

Post by stevepoole »

Hi TinyFpga,
Be wary when using float, integer% or string$ variables, parameters , procedures or functions under QDOS.
They were never properly implemented until SMSQ/E came along:
Take a look at the parameters_bug program attatched : Just Unzip it and LRUN it on your system.

Under QDOS you get an error at line 110, whereas under SMSQ/E the error is correctly at 100 as you would expect...
Under QDOS, the routine parameter's type depends on the calling variable's type !
This was hardly ever explained in documentation... Steve.
parameters_bug.zip
(359 Bytes) Downloaded 58 times
_______________________________________________________


User avatar
RalfR
QL Wafer Drive
Posts: 1140
Joined: Fri Jun 15, 2018 8:58 pm

Re: Externals, Functions and Procedures

Post by RalfR »

stevepoole wrote: Fri Feb 28, 2025 2:46 pm Under QDOS you get an error at line 110, whereas under SMSQ/E the error is correctly at 100 as you would expect...
No, under SMSQ/E it says "At line 150:4 error in expression" and shows "1" at #1.

fnbug.jpg

But I don't understand the error message.


7000 4E75
stevepoole
Aurora
Posts: 874
Joined: Mon Nov 24, 2014 2:03 pm

Re: Externals, Functions and Procedures

Post by stevepoole »

Hi again,
Yes, under SMSQ the floats parameter is defined as floating-point. So when the calling variable is 'e'', SMSQ/E signals an error line 150.
But, under QDOS, floats accepts that the variable 'e' is sring-type, and tries to pass the value to the local variable f, which is by default a floating point type. Without delving into (expressions), the interpreter cannot convert 'e' to floating point, so signals an error on line 160....!
As mentioned last time, under QDOS this is a bug, in that routine parameters get their type from the calling expression.
Corrected under SMSQ/E, the error is correctly signalled on line 150... All rather confusing under QDOS, so prefer SMSQ/E every time ! Steve.
_____________________________


martyn_hill
QL Wafer Drive
Posts: 1048
Joined: Sat Oct 25, 2014 9:53 am

Re: Externals, Functions and Procedures

Post by martyn_hill »

Hi Tinyfpga!

Probably a moot point now, but taking one of your earlier questions, in case you still had any doubts:
An example of my problem is note 4, page 154 of the BASIC ref. manual:-
"Although a sub-set of a simple string (what is a complex string?) is an expression (what is an expression?) and therefore will not be altered within a function, a sub-set of a string array (my translation of DIM string) is not treated as an expression and will therefore be altered!!"
A 'simple string' is an un-DIMensioned string, e.g. a$, and a 'sub-set' (more properly, a 'sub-string') might be a$(1 TO 5). The term 'complex string' isn't used, but is, as you imagine, a DIMensioned string array (or 'vector' vs 'scalar', to use alternative terms for the same things.)

An expression is a compound, literal or computed value, like a$ & '_bas', a$ & b$, or just '_bas'

Technically, the example above a$(1 TO 5) is such a computed value or expression and, as such, is passed to the FN/PROC call by 'value' instead of by 'reference.' Being passed by value, any changes made to the 'formal' variable (what it's called within the scope of the procedure) during the procedure is dropped on return to the calling code (after all, how can you assign a value back to an expression?)

What that explanation is trying to highlight is that, when instead passing a sub-range of a DIMensioned array, e.g. a$(1 TO 5), where a$ was previously dimensioned as, say, DIM a$(5,10), then it is instead passed by reference and thus, any changes made to the formal parameter during the procedure will be reflected back to the original 'actual' array variable, a$() on return from the procedure call.

Thus, you can't readily tell whether passing a$(1 TO 5) will be treated as 'by-reference' or 'by-value', without knowing whether or not a$ was previously DIM'd.

Not sure that's any clearer than the original text :-)

S*BASIC tends to default to passing parameters by reference, except in the case of expressions. This point often catches-out programmers starting-out with the TURBO compiler, which will always pass by value unless you explicitly state by REFERENCE - and, as arrays MUST be passed by reference, any passed arrays need to have the REFERENCE keyword added ahead of the relevant FN/PROC... But I digress...

Enjoy the journey!


Tinyfpga
Gold Card
Posts: 295
Joined: Thu Sep 27, 2018 1:59 am

Re: Externals, Functions and Procedures

Post by Tinyfpga »

Probably a moot point now
It's not moot as you have answered my question and I find it useful. My experience with the forum is that if I ask a number of questions in a single post, I generally do not receive responses to all of them. It seems better to post one problem at a time. (see next post!)


Tinyfpga
Gold Card
Posts: 295
Joined: Thu Sep 27, 2018 1:59 am

Re: Externals, Functions and Procedures

Post by Tinyfpga »

Hope it helps. Greetings from Switzerland. Markus
I have modified your code to suit my environment and have then interpreted and compiled your code.
The interpreted result is in the window to the left of the screen and the compiled result is on the right.

One can see that there is a difference. The compiled code produces erroneous results.
Functiontest.jpg


martyn_hill
QL Wafer Drive
Posts: 1048
Joined: Sat Oct 25, 2014 9:53 am

Re: Externals, Functions and Procedures

Post by martyn_hill »

Hi again Tinyfpga

Out of interest, which compiler did you use to generate the executable with output on the right?

[Scratch that - you mentioned QLib previously in this thread]

Which version of QLib? Seems you're running this latest test in SMS2 - I wonder if there is some compatibility issue between the two - or rather, between QLib and the SBASIC interpreter version you're running in SMS2.

Bear in mind that QLib continued to be developed long after the first (only?) release of SMS2 and, likely as not, was tested primarily on QDOS and later SMSQe, so any potential incompatibilities with SMS2 are unlikely to have been spotted (until now...)

The second numeric error looks to be some Maths stack error within the compiled code, but what is causing the first string error isn't at all clear.

What happens if you replace the sub-string range with (1 TO 2)?


Post Reply