slviajero / tinybasic

A BASIC interpreter for Arduino, ESP, RP2040, STM32, Infineon XMC and POSIX with IoT and microcontroller features.
GNU General Public License v3.0
203 stars 31 forks source link

How to return a string as a function? #29

Closed Kongduino closed 1 year ago

Kongduino commented 2 years ago

I have in mind a function that would take no argument, but return a string (not the same one every time). I can't seem to make sense of things after reading the code. I have the feeling I need to push the length, and point ir2 towards the string but that's about it.

Could you confirm, or explain, please? Thanks.

If need be I could accept an argument, albeit bogus...

slviajero commented 2 years ago

That is the most complicated part of the code, and also admittedly the worst. I will give you a hint later and write something down. Struggling with this myself from time to time.

Am 25.08.2022 um 15:31 schrieb Kongduino @.***>:

I have in mind a function that would take no argument, but return a string (not the same one every time). I can't seem to make sense of things after reading the code. I have the feeling I need to push the length, and point ir2 towards the string but that's about it.

Could you confirm, or explain, please? Thanks.

— Reply to this email directly, view it on GitHub https://github.com/slviajero/tinybasic/issues/29, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACSY56F2FCQA7B7IZBYJTGTV25YSVANCNFSM57TECOXA. You are receiving this because you are subscribed to this thread.

slviajero commented 2 years ago

To return a string, there are two methods. One is generating a function and integrate it to the stringvalue() function.

In the version 1.3 code an example would be the STR function. The code looks like this:

} else if (token == TSTR) { 
    nexttoken();
    if ( token != '(') { error(EARGS); return FALSE; }
    nexttoken();
    expression();
    if (er != 0) return FALSE;

ifdef HASFLOAT

    push(writenumber2(sbuffer, pop()));

else

    push(writenumber(sbuffer, pop()));

endif

    ir2=sbuffer;
    x=1;
    if (er != 0) return FALSE;
    if (token != ')') {error(EARGS);return FALSE;   }

endif

}

As you have already written in your question, ir2 must have a pointer to the string and the length has to be pushed to the stack. STR uses sbuffer. This is a 32 byte general string handling buffer. It is originally used for keyword parsing but can be used at runtime of a program as a short lived buffer variable.

There is one other method. If you just want to return a string and need no argument, then using a special variable can be defined. Special variables has the form @, a letter and then $. Currently only @T$ is used for the time string. This is done like this:

In getstring there is a code segment that reads like this

/ the time string /

if !defined(ARDUINO) || defined(ARDUINORTC)

if ( c == '@' && d == 'T') {
    rtcmkstr();
    return rtcstring+b;
}

endif

Any string buffer can be returned here. So if you want to define a special variable @X$ to return the bugger mybuffer generated by myfunction() your code in getstring would be

if ( c == '@' && d == ‚X') {
    myfunction();
    return mybuffer+b;
}

The +b is needed for the substring evaluation.

In addition to this you have to make one more change. In lenstring() you need to add:

if (c == '@' && d == ‚X') {
    return mybufferlength;
}

where mybufferlegth is the exact number of bytes you want to return.

This would generate a read only string variable @X$ that calls myfunction() every time it is read and transfers the data back to the BASIC program.

Am 25.08.2022 um 15:31 schrieb Kongduino @.***>:

I have in mind a function that would take no argument, but return a string (not the same one every time). I can't seem to make sense of things after reading the code. I have the feeling I need to push the length, and point ir2 towards the string but that's about it.

Could you confirm, or explain, please? Thanks.

— Reply to this email directly, view it on GitHub https://github.com/slviajero/tinybasic/issues/29, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACSY56F2FCQA7B7IZBYJTGTV25YSVANCNFSM57TECOXA. You are receiving this because you are subscribed to this thread.

Kongduino commented 2 years ago

Oh this is excellent! Thanks a lot for this. I will try it this weekend, and see how it goes. The @x$ command looks like the best best. And lenstring() will be useful too: if there's nothing to return, it will return 0.

slviajero commented 2 years ago

I have just implemented and pushed the @x$ feature. If you like you can pull the newest basic.c and play with it. Best Regards, Stefan

Am 26.08.2022 um 07:26 schrieb Kongduino @.***>:

Oh this is excellent! Thanks a lot for this. I will try it this weekend, and see how it goes. The @x$ command looks like the best best. And lenstring() will be useful too: if there's nothing to return, it will return 0.

— Reply to this email directly, view it on GitHub https://github.com/slviajero/tinybasic/issues/29#issuecomment-1228068130, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACSY56B3VMMJM4TIUTFZYYLV3BIR7ANCNFSM57TECOXA. You are receiving this because you commented.

Kongduino commented 2 years ago

Hi! In between I managed to make it work, I have now a shiny @P$ read-only variable (thanks for that!) but I hit another issue, completely unrelated to strings. So I think I should close this, and start a separate issue (it is, I think, related to interrupts).

@P$ is for packet: I am compiling Tinybasic on a RAK4631 (nRF42840 + SX1262) and when a packet is received, a callback saves it into a buffer. But somehow the callback only fires when I try to access the variable. Weird. I'll detail this in a separate issue.

Meanwhile I'll have a look at your brand new basic.c.

slviajero commented 2 years ago

cool congrats!

Sent from my iPhone

On Aug 27, 2022, at 10:34 AM, Kongduino @.***> wrote:

 Hi! In between I managed to make it work, I have now a shiny @P$ read-only variable (thanks for that!) but I hit another issue, completely unrelated to strings. So I think I should close this, and start a separate issue (it is, I think, related to interrupts).

Meanwhile I'll have a look at your brand new basic.c.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.