External stack

Contributions to this software library are always welcome. Please ensure that you post program listings rather than .raw files. They give a reasonable idea of what your program does without having to load them into a DM42 and you can also include comments in your code. Check out the following link for a decoder/encoder: http://www.swissmicros.com/dm42/decoder/

You can then copy/paste the listing and post it in "code" tags.
rprosperi
Posts: 701
Joined: Mon Apr 24, 2017 5:48 pm
Location: New York

Re: External stack

Post by rprosperi » Fri Apr 05, 2019 12:48 pm

akaTB wrote:
Fri Apr 05, 2019 11:08 am
Thomas Okken wrote:
Fri Apr 05, 2019 7:51 am
The next release of Free42 will have local variables, which will make it possible to preserve the stack with no side effects at all. Stay tuned...
:shock:
Yeah... what he said...
--bob p

DM42: β00071 & 00282, DM41X: β00071, DM10L: 071/100

hsilop
Posts: 33
Joined: Thu Mar 14, 2019 12:35 am
Location: Canberra, Australia

Re: External stack

Post by hsilop » Sat Apr 06, 2019 12:48 am

Thomas Okken wrote:
Fri Apr 05, 2019 7:51 am
The next release of Free42 will have local variables, which will make it possible to preserve the stack with no side effects at all. Stay tuned...
That would totally rock! It'd be almost like a fully-fledged third generation language. Any chance for parameter passing and function return values too?

Keep up the good work!
DM42 SN: 03223

HP11C, HP12C, HP15C, HP16C, HP25, HP32S, HP33C, HP41CV, HP46, HP65

Thomas Okken
Posts: 674
Joined: Tue May 02, 2017 3:48 pm
Contact:

Re: External stack

Post by Thomas Okken » Sat Apr 06, 2019 1:12 am

There will be just one new function, LSTO, which works like STO except the variable it creates disappears when the current subroutine ends. (And of course it won't overwrite an existing variable with the same name; that variable is merely hidden while the local variable exists.)

You could use that mechanism to create parameters. For example, a function that takes a parameter X and uses a local A could look like this:

The call:
01 calculate parameter
02 LSTO "X"
03 XEQ "FN"

The function:
10 LBL "FN"
11 12345
12 LSTO "A"
13 RCL "X"
14 do something useful
15 RTN

Similarly, the caller could create a local variable in which the function stores a return value. The LSTO mechanism is pretty flexible -- or at least it will be once I get it to work, hopefully this weekend. It'll be interesting to see how people end up using it.

rprosperi
Posts: 701
Joined: Mon Apr 24, 2017 5:48 pm
Location: New York

Re: External stack

Post by rprosperi » Sat Apr 06, 2019 2:51 am

Thanks for the peek ahead Thomas, it looks interesting, and it should indeed be interesting to see how folks leverage it.

In the example you provided, if something were stored in "X" before the calling program is run, will there be any way to access the original contents from inside the program?

Also, will it support indirect stack and register targets?
--bob p

DM42: β00071 & 00282, DM41X: β00071, DM10L: 071/100

Thomas Okken
Posts: 674
Joined: Tue May 02, 2017 3:48 pm
Contact:

Re: External stack

Post by Thomas Okken » Sat Apr 06, 2019 9:49 am

rprosperi wrote:
Sat Apr 06, 2019 2:51 am
In the example you provided, if something were stored in "X" before the calling program is run, will there be any way to access the original contents from inside the program?
No. The hidden variable will be completely inaccessible, until the local variable that hides it disappears.
rprosperi wrote:
Sat Apr 06, 2019 2:51 am
Also, will it support indirect stack and register targets?
Yes. At first I thought I'd forbid LSTO IND because it will make programs hard to read, but there's certainly no problem implementing it, and there could be situations where it would be useful.

You won't be able to do LSTO ST or LSTO nn, and LSTO IND <foo> where <foo> contains something other than a string will raise an Invalid Type error.

You can do LSTO "REGS" to create a local set of numbered registers, which might be useful if you want to use the statistics functions locally, but as with locals in general, this will hide the original "REGS" while the local "REGS" exists.

As an example of how LSTO may be used, one of my test cases is this implementation of the Ackermann function, called with m in Y and n in X:

Code: Select all

00 { 91-Byte Prgm }
01▸LBL "ACK"
02 LSTO "N"
03 R↓
04 LSTO "M"
05 R↓
06 LSTO "Z"
07 R↓
08 LSTO "T"
09 RCL "M"
10 X=0?
11 GTO 00
12 1
13 -
14 RCL "N"
15 X=0?
16 GTO 01
17 1
18 -
19 RCL "M"
20 X<>Y
21 XEQ "ACK"
22 XEQ "ACK"
23 GTO 02
24▸LBL 00
25 RCL "N"
26 1
27 +
28 GTO 02
29▸LBL 01
30 CLX
31 1
32 XEQ "ACK"
33▸LBL 02
34 RCL "N"
35 STO ST L
36 R↓
37 RCL "T"
38 RCL "T"
39 RCL "Z"
40 R↑
41 END
Last edited by Thomas Okken on Sun Apr 07, 2019 1:24 am, edited 1 time in total.

User avatar
Walter
Posts: 1342
Joined: Tue May 02, 2017 9:13 am
Location: Close to FRA, Germany

Re: External stack

Post by Walter » Sat Apr 06, 2019 10:30 am

Fine added feature. Thanks!

If I understand it correctly, LSTO allocates space for a local variable of known dimension and data type, doesn't it?

So it looks like something similar to LocR on the WP34S where a specified amount of local registers is allocated (the WP34S couldn't support variables for space reasons).
DM42 SN: 00041 --- Follower of Platon.

HP-35, HP-45, ..., HP-50, WP 34S, WP 31S, DM16L

Thomas Okken
Posts: 674
Joined: Tue May 02, 2017 3:48 pm
Contact:

Re: External stack

Post by Thomas Okken » Sat Apr 06, 2019 10:47 am

Walter wrote:
Sat Apr 06, 2019 10:30 am
If I understand it correctly, LSTO allocates space for a local variable of known dimension and data type, doesn't it?
No, LSTO creates a named variable, like STO "name", just with some added trickery to handle hiding any previously existing variable with the same name, and cleaning up on RTN. The local variable can change type or dimension during its existence, just like any other named variable.

User avatar
Walter
Posts: 1342
Joined: Tue May 02, 2017 9:13 am
Location: Close to FRA, Germany

Re: External stack

Post by Walter » Sat Apr 06, 2019 11:00 am

Thomas Okken wrote:
Sat Apr 06, 2019 10:47 am
Walter wrote:
Sat Apr 06, 2019 10:30 am
If I understand it correctly, LSTO allocates space for a local variable of known dimension and data type, doesn't it?
No, LSTO creates a named variable, like STO "name", just with some added trickery to handle hiding any previously existing variable with the same name, and cleaning up on RTN. The local variable can change type or dimension during its existence, just like any other named variable.
Thanks for clarifying!
DM42 SN: 00041 --- Follower of Platon.

HP-35, HP-45, ..., HP-50, WP 34S, WP 31S, DM16L

rprosperi
Posts: 701
Joined: Mon Apr 24, 2017 5:48 pm
Location: New York

Re: External stack

Post by rprosperi » Sat Apr 06, 2019 1:38 pm

Thomas Okken wrote:
Sat Apr 06, 2019 9:49 am
You can do LSTO "REGS" to create a local set of numbered registers, which might be useful if you want to use the statistics functions locally, but as with locals in general, this will hide the original "REGS" while the local "REGS" exists.
This will be real handy to allow one to write programs that can use any/all registers willy nilly as they like, while still preserving the actual (global) values upon exit. Powerful and useful!

As a program can nest subroutine calls, can these local named variables nest as well, with each subroutine level seeing it's own instance?

I think there could be merit to let the current local instance access the global variables, perhaps with GRCL / GSTO, to pass parameters between the environments, though I presume this could add significant complexity to the design, so perhaps not worthwhile.

When exporting raw files that utilize LSTO, how does one handle this new 'unknown' function to flag the user that the resulting program will not work in prior (or other) versions of Free42, DM42, etc?

Thanks for sharing your ideas for this excellent extension to Free42 Thomas! A truly clever and creative way to expand the scope and usefulness of Free42, while preserving its familiar personality and feel.
--bob p

DM42: β00071 & 00282, DM41X: β00071, DM10L: 071/100

Thomas Okken
Posts: 674
Joined: Tue May 02, 2017 3:48 pm
Contact:

Re: External stack

Post by Thomas Okken » Sat Apr 06, 2019 4:19 pm

rprosperi wrote:
Sat Apr 06, 2019 1:38 pm
As a program can nest subroutine calls, can these local named variables nest as well, with each subroutine level seeing it's own instance?
Yes, so recursive algorithms can be implemented using these.
rprosperi wrote:
Sat Apr 06, 2019 1:38 pm
I think there could be merit to let the current local instance access the global variables, perhaps with GRCL / GSTO, to pass parameters between the environments, though I presume this could add significant complexity to the design, so perhaps not worthwhile.
It's unnecessary, too. If you know your function needs to access a certain global variable, then just don't use a local variable with the same name.
rprosperi wrote:
Sat Apr 06, 2019 1:38 pm
When exporting raw files that utilize LSTO, how does one handle this new 'unknown' function to flag the user that the resulting program will not work in prior (or other) versions of Free42, DM42, etc?
There is no friendly mechanism for alerting a user when this happens. In raw files, the LSTO function is encoded using the same kind of special strings (*) that are used by the HP-42S to encode its parameterized functions. (Parameter-less functions are encoded using XROM.) These are strings where the first character of the string text has a high bit of 1.

If you were to import a Free42 program containing LSTO into Emu42, it may warn you that the format you're trying to import is unrecognized, and if you go ahead anyway, you'd see weirdness instead of the LSTO commands (empty lines that change into a division symbol when they are highlighted, and don't do anything if you try to execute them). In older versions of Free42, you'd see meaningless strings instead of the LSTO commands, similar to what happens if you import an HP-42S program containing, say, CLV into an HP-41. Nothing terrible will happen, the calculator will certainly not crash, but nothing useful will happen, either.

(*) Specifically, Fn C7 followed by the name for LSTO "name", Fn CF followed by the name for LSTO IND "name", and F2 ED followed by the argument byte for LSTO IND nn and LSTO IND ST.

I just finished coding, but of course it's still crashing left and right. Going out for a walk to clear my head and enjoy the weather; hopefully I'll get it to behave later today!

Post Reply