Free42 LSTO REGS
09-25-2019, 03:52 PM
Post: #1
 Epidiah Junior Member Posts: 7 Joined: Mar 2018
Free42 LSTO REGS
Greetings,

This is my first time posting. Generally, I've been content with just reading these forums, but I just discovered something about Free42's LSTO feature that I haven't seen mentioned anywhere and it's too exciting not to share!

This is how it started:

Code:
00 { 23-Byte Prgm } 01▸LBL "TstLSTO" 02 RCL "REGS" 03 LSTO "REGS" ...

If LSTO was used to create a local REGS, would all the commands that normally interact with REGS address that local REGS and leave the global REGS untouched?

I tried STO and RCL and their arithmetic, an assortment of STAT functions, ISG, DSE, printing the REGS, CLΣ and CLRG. I'm sure there's more, but all of these interacted with the local REGS and ignored the global one!

At the moment, I have no real need for this, but I rather like the idea that I can use the whole suite of REGS-related functions in a subroutine without worrying about their impact on previously stored data.
09-26-2019, 05:50 PM
Post: #2
 David Hayden Senior Member Posts: 336 Joined: Dec 2013
RE: Free42 LSTO REGS
Wow that's cool!

It might also mean that if you have an old program that uses lots of registers and stores it's results on the stack, then you might be able to run it cleanly by doing LSTO "REGS" and then calling the program.
09-26-2019, 08:10 PM
Post: #3
 Guenter Schink Senior Member Posts: 346 Joined: Dec 2013
RE: Free42 LSTO REGS
(09-26-2019 05:50 PM)David Hayden Wrote:  Wow that's cool!

It might also mean that if you have an old program that uses lots of registers and stores it's results on the stack, then you might be able to run it cleanly by doing LSTO "REGS" and then calling the program.

You even can create temporary "REGS" for use in manual mode only
Code:
 01 LBL "AREGS" 02 NEWMAT 03 LSTO "REGS" 04 STOP 05 RTN

Put your desired nRows and 1 on the STACK and run AREGS. After that you'll have that new set of registers available until you hit R/S, this will invoke RTN and thus reactivate the standard REGS.

But wait a minute. Before you hit R/S you could save your "local" REGS as a normal VAR e.g. "REGS1" for later use. Then when you sometime later want to reactivate "REGS1" just recall it and LSTO it to "REGS" but then to return to the original "REGS" you have to do a RTN. GTO .. does it also.

Cool? Günter
09-28-2019, 02:53 AM
Post: #4
 Thomas Okken Senior Member Posts: 1,056 Joined: Feb 2014
RE: Free42 LSTO REGS
You can also use LSTO from the keyboard; it is not program-only. Like in Günter's example, you end up with a variable that will go away when you do run-mode GTO, XEQ, RTN, BST, edit a program, etc. Specifically, all local variables are deleted by the same set of actions that cause the RTN stack to be cleared on the HP-42S.
09-28-2019, 03:19 AM
Post: #5
 Thomas Okken Senior Member Posts: 1,056 Joined: Feb 2014
RE: Free42 LSTO REGS
To elaborate a bit: every local variable is associated with a level of the RTN stack. LSTO creates variables on the current level, and when that level is popped, the associated variables are deleted. And, any action that clears the entire RTN stack, like GTO, XEQ, or RTN in RUN mode, clears all local variables.

There is one quirk to this: LSTO can also create variables when the RTN stack is already empty. It has to be able to do this, in order to work in a subroutine that is invoked from the keyboard. Say you do XEQ "FOO" from the keyboard with this in program memory:

Code:
01 LBL "FOO" 02 LSTO "X" 03 R↓ 04 LSTO "Y" [...]

When the LSTO instructions are performed, there is nothing on the RTN stack, unlike when the XEQ "FOO" is done from a program, but of course you'd want LSTO to work even in this scenario.

When a program performs RTN while the RTN stack is empty, this causes the empty-stack locals (referred to as "level 0" in the source code, the RTN stack "level" being the number of pending returns) to be deleted, so when the program "FOO" above ends with a RTN, its locals disappear, even though they were never associated with an actual RTN. And this same mechanism can be used in RUN mode.
10-04-2019, 12:34 PM (This post was last modified: 10-04-2019 12:36 PM by Namir.)
Post: #6
 Namir Senior Member Posts: 741 Joined: Dec 2013
RE: Free42 LSTO REGS
The technique of of using local REGS is wonderful! I wrote a short test where I stored values in regular registers, called a subroutine, created a local copy of REGS, and accessed the copies. This method allows you to pass values not only in the stack, but also though numbered registers to a subroutines. The called subroutine can return the result(s) in the stack OR in gobal named variables. Using local REGS allows the subroutine to use any numbered register, that does not supply it with input values, to store whatever intermediate results needed.

Thanks Thomas for making the feature of local REGS available!

Here is my short test program:

Code:
01▸LBL "AA" 02 100 03 STO 00 04 200 05 STO 01 06 XEQ "BB" 07 "X=" 08 ARCL 00 09 PROMPT 10 RTN 11▸LBL "BB" 12 RCL "REGS" 13 LSTO "REGS" 14 1 15 STO 00 16 "XS=" 17 ARCL 00 18 PROMPT 19 "YS=" 20 ARCL 01 21 PROMPT

Namir
10-05-2019, 08:46 AM
Post: #7
 Paul Dale Senior Member Posts: 1,645 Joined: Dec 2013
RE: Free42 LSTO REGS
The 34S introduced local variables that were allocated per return stack frame (thanks Marcus). These were initially used by some of the internal keystroke programmes (XROM). They are not at the same level of sophistication that Free42 now has. I suspect that there might be some middle ground between the two but why would anyone compromise?

The most important benefit is that the two major HP calculator projects have been learning from each other,

Pauli
10-21-2019, 09:31 AM
Post: #8
 SammysHP Member Posts: 102 Joined: Jul 2018
RE: Free42 LSTO REGS
Just came across one of my programs that uses DIM to create a matrix in memory without using another stack register. Haven't found a way to LSTO/LDIM this without creating a matrix on the stack first. Of course now I can save the stack content first.
10-21-2019, 03:07 PM
Post: #9
 Epidiah Junior Member Posts: 7 Joined: Mar 2018
RE: Free42 LSTO REGS
(10-21-2019 09:31 AM)SammysHP Wrote:  Just came across one of my programs that uses DIM to create a matrix in memory without using another stack register. Haven't found a way to LSTO/LDIM this without creating a matrix on the stack first. Of course now I can save the stack content first.

I think...

Code:
NEWMAT LSTO "MAT" DIM?

...should take your rows and columns from Y and X, make a new matrix, store it locally in REGS and then return your rows and columns to Y and X. That should account for everything but the LastX register, which would have your new matrix in it instead.

I was thinking you could even slap the "LDIM" label on it and make it a program, but that would be self-defeating since it would discard the LSTO'ed matrix once it returns to whatever called it.
10-23-2019, 12:01 PM
Post: #10
 Thomas Okken Senior Member Posts: 1,056 Joined: Feb 2014
RE: Free42 LSTO REGS
(10-21-2019 03:07 PM)Epidiah Wrote:  I was thinking you could even slap the "LDIM" label on it and make it a program, but that would be self-defeating since it would discard the LSTO'ed matrix once it returns to whatever called it.

Yes, this is a bit of a problem. It would be nice if you could create subroutines for preserving state, like preserving the entire stack, and right now, you can't.

One way to fix this would be to add a modified RTN instruction, let's call it LRTN for now, that has the effect of not popping local variables created at the current level, instead moving them one level up the stack, as if they had been created by the caller. So you could write a stack saver like

LBL "SPUSH" LSTO "X" R↓ LSTO "Y" R↓ LSTO "Z" R↓ LSTO "T" LASTX LSTO "L" LRTN

and restore the entire stack with

LBL "SPOP" RCL "L" STO ST L RCL "T" RCL "Z" RCL"Y" RCL "X" RTN

leaving the local variables to be popped automatically:

LBL "SOMEFUN" XEQ "SPUSH" <do something useful here> XEQ "SPOP" RTN

(Of course the sequence XEQ "FOO" RTN can be replaced by GTO "FOO" (tail call optimization) but that can make the code harder for humans to understand.)

Variations on the SPOP function could be created to mimic the behavior of unary or binary operators as well.

Thoughts? Would LRTN be a good name, or can someone suggest something better, i.e. a better name for that function, or an altogether better way to fix this LSTO limitation?
10-23-2019, 01:38 PM
Post: #11
 rprosperi Senior Member Posts: 4,323 Joined: Dec 2013
RE: Free42 LSTO REGS
Cool idea! This makes it trivial to save the stack state, go do 'whatever' and then restore it.

"LRTN" seems a good name, reinforcing the idea of preserving the local state.

I suppose this could lead to some confusion if the user forgets to LRTN, is adding a new "L" annunciator feasible?

This new capability would be nicely complemented by a pair of commands that get and save the state of all flags (user and system), perhaps GETF and SAVEF; using these in SPUSH and SPOP (also adding available commands to save the registers) would allow them to save the full machine state, from the user's perspective, while running 'whatever'.

It's possible that some system flags could be problematic here, but I imagine you would know about those and they could be 'skipped' if needed.

--Bob Prosperi
10-23-2019, 02:22 PM
Post: #12
 Epidiah Junior Member Posts: 7 Joined: Mar 2018
RE: Free42 LSTO REGS
(10-23-2019 12:01 PM)Thomas Okken Wrote:  Thoughts? Would LRTN be a good name, or can someone suggest something better, i.e. a better name for that function, or an altogether better way to fix this LSTO limitation?

Would a LXEQ be feasible? Something that would let the program doing the calling decide if it wanted to preserve the local variables from the subroutine?

I feel like that's more flexible, but LRTN does have the advantage of not having to remember which subroutines you want to recall the local variables from.
10-23-2019, 11:51 PM
Post: #13
 Thomas Okken Senior Member Posts: 1,056 Joined: Feb 2014
RE: Free42 LSTO REGS
Once you try to add functions that make it possible to truly emulate function-like behavior of subroutines, things seem to get messy pretty quickly. Even LRTN isn't as elegant as I first thought, because pushing locals into the caller's stack frame means possible name clashes, so now you have to make sure that the names of your locals don't collide with those used by your SPUSH function.

Bah. Back to the drawing board.
10-24-2019, 11:37 AM
Post: #14
 Thomas Okken Senior Member Posts: 1,056 Joined: Feb 2014
RE: Free42 LSTO REGS
A more thorough approach to the problem of creating subroutines that look and behave like built-in functions might go like this:

First, a special kind of label, let's call it FLBL. This works just like a regular LBL, the difference being that a call to FLBL "FOO" is displayed as FOO, not XEQ "FOO".

Second, an easy way to save and restore state. Saving state could be done by a new function FSAVE, possibly to be combined with FLBL, and it would save the stack registers, LASTx, ALPHA, and all flags. Restoring state would be done by a new function FRTN, with variants FRTN_U, FRTN_B, FRTN_E for functions that act like unary operators, binary operators, or return an error status, respectively. (Error status can also be used to implement conditionals; the special behavior of the "Yes" and "No" messages is part of the system already and it's how all the built-in conditionals are implemented.) Of course it gets more complicated, because what if a function is supposed to have multiple side effects?

Third, because all this encourages the creation of large function libraries, the flat program space becomes an issue and directories are back on the agenda. Those same directories that were supposed to be unnecessary once easy state file switching was implemented.

TL;DR Once you start thinking hard about extending RPN keystroke programming, all roads lead to RPL.
10-24-2019, 12:26 PM
Post: #15
 Paul Dale Senior Member Posts: 1,645 Joined: Dec 2013
RE: Free42 LSTO REGS
(10-24-2019 11:37 AM)Thomas Okken Wrote:  TL;DR Once you start thinking hard about extending RPN keystroke programming, all roads lead to RPL.

I realised this quite some years ago

The 34S has a pair of functions Xin and Xout which allow the internal keystroke programs to behave like builtin commands. Xin takes an argument that specifies the number of input and output arguments and the stack handling is done behind the scenes. There are a number of other features/complications involved.

Pauli
10-24-2019, 12:57 PM (This post was last modified: 10-24-2019 12:57 PM by Epidiah.)
Post: #16
 Epidiah Junior Member Posts: 7 Joined: Mar 2018
RE: Free42 LSTO REGS
It's a long, dark road, indeed!

Not to distract from any discussion about function-like routines--because if I'm honest, I find the prospect of a FLBL thrilling and looking at the 17 files states I've built around program themes it's clear this is the direction I'm naturally drifting toward--I wanted to sing the praises of LSTO REGS one more time.

This combo has made working with two matrices and moving data between them without disturbing the contents of REGS a bit of a breeze. Here's a quick one I whipped up that takes a vector and turns it into the main diagonal of a square matrix.

Code:
00 { 89-Byte Prgm } 01▸LBL "V→[\]" 02 LSTO "L" 03 LSTO "REGS" 04 R↓ 05 LSTO "Y" 06 R↓ 07 LSTO "Z" 08 R↓ 09 LSTO "T" 10 R↓ 11 DIM? 12 X<Y? 13 X<>Y 14 ENTER 15 NEWMAT 16 -1 17 RCL+ ST L 18 1ᴇ-3 19 × 20 LSTO "#" 21 R↓ 22 EDIT 23▸LBL 00 24 RCL IND "#" 25 → 26 ↓ 27 ISG "#" 28 GTO 00 29 EXITALL 30 RCL "L" 31 STO ST L 32 R↓ 33 RCL "T" 34 X<>Y 35 RCL "Z" 36 X<>Y 37 RCL "Y" 38 X<>Y 39 END

I'm throwing LSTO all over the place here to preserve the stack and the REGS, but the main thing is that I can have the program EDIT one matrix while another sits in REGS where I can pluck entries out of it at whim. That's so much easier than flopping back and forth, indexing one matrix after another, adjusting I and J each time.
10-25-2019, 01:50 AM
Post: #17
 Epidiah Junior Member Posts: 7 Joined: Mar 2018
RE: Free42 LSTO REGS
(10-21-2019 03:07 PM)Epidiah Wrote:  I think...

Code:
NEWMAT LSTO "MAT" DIM?

...should take your rows and columns from Y and X, make a new matrix, store it locally in REGS and then return your rows and columns to Y and X. That should account for everything but the LastX register, which would have your new matrix in it instead.

Wait! It's not nearly elaborate as all that!

All you need is:
Code:
LSTO "MAT" DIM "MAT"
The LSTO creates the local variable and the DIM turns it into what you want.

This has me thinking about getting into the habit of declaring local variables and then calling the subroutines that fill them.
10-25-2019, 06:21 AM
Post: #18
 Werner Senior Member Posts: 514 Joined: Dec 2013
RE: Free42 LSTO REGS
Barring the stack save-and-restore, that can be done a bit more easily:

Code:
>LBL "DIAG"  LSTO "X"  DIM?  +  ENTER  DSE ST X  DIM "X"  RCL "X"  TRANS  STO "X"  Rv  ENTER  DIM "X"  RCL "X"  END

Too bad DIM only works on named variables, or I could've done it all in the stack.

Cheers, Werner
10-25-2019, 02:02 PM
Post: #19
 Epidiah Junior Member Posts: 7 Joined: Mar 2018
RE: Free42 LSTO REGS
Oh, that's clever! I hadn't thought about redimensioning the matrix. It'll work to reverse it, too!

Code:
00 { 36-Byte Prgm } 01▸LBL "GAID" 02 LSTO "X" 03 DIM? 04 1 05 + 06 DIM "X" 07 RCL "X" 08 TRANS 09 STO "X" 10 R↑ 11 1 12 DIM "X" 13 RCL "X" 14 END

My search for an indispensable use of LSTO REGS continues...
10-25-2019, 07:17 PM (This post was last modified: 10-25-2019 07:17 PM by SammysHP.)
Post: #20
 SammysHP Member Posts: 102 Joined: Jul 2018
RE: Free42 LSTO REGS
(10-25-2019 01:50 AM)Epidiah Wrote:  All you need is:
Code:
LSTO "MAT" DIM "MAT"
The LSTO creates the local variable and the DIM turns it into what you want.

Thanks, didn't thought about storing whatever is on the stack just to declare the variable!
 « Next Oldest | Next Newest »

User(s) browsing this thread: 1 Guest(s)