The Museum of HP Calculators

HP Forum Archive 16

[ Return to Index | Top of Index ]

50g system software
Message #1 Posted by Ron on 8 Nov 2006, 5:33 p.m.

Hi, my hp 50g shows 50-c and revision #2.08 when interrogated. The ROM version offered by download is for build 92 I assume the download makes the 50 and 49 compatible and fixes outstanding bugs.

HELP PLEASE!

AND - DOES THE FOLLOWING SOUND FAMILIAR?

Practicing development of user DEFINED FUNCTIONS and attempting to extend scope of local variable one level. While trying several ways to circumvent constraints on "compiled local variables" the system freezes up requring removal of a battery letting what appears to be a drain on a charged capacitance happen (usually overnight). Hope build 92 fixes it !

Thanks!

Ron

Edited: 8 Nov 2006, 8:59 p.m.

      
Re: 50g system software
Message #2 Posted by James M. Prange (Michigan) on 9 Nov 2006, 6:21 a.m.,
in response to message #1 by Ron

Update any 50g or 49g+ to build 92; that will put your ROM at revision 2.09. There may still be remaining bugs of course; see http://bugs.hpcalc.org/, or follow the comp.sys.hp48 usenet group.

For the freeze up, have you tried the CANCEL operation (invoked by pressing the ON key)?

Have you tried a warmstart (invoked by holding down ON while pressing and releasing C and then releasing ON)?

In case a warmstart can't be invoked from the keyboard, have you tried invoking one by inserting a partially straightened small paper-clip or something similar straight into the reset hole in the back of the calculator?

For more information on warmstarts (compared to clearing memory), see this post

Maybe post an example of (preferably commented) code that's giving you a problem?

What do you mean by constraints on compiled local variables? The documentation really should've called them "compiled local names" instead of "compiled local variables". A compiled local name (48GX/G and newer only) is one that starts with a left arrow (character 142), which the compiler treats as the source code for a local name, even when a local variable with that name isn't being created and doesn't already exist. The idea is to make it easier for a called program to use local variables defined for the calling program.

But the existence of a local name doesn't mean that a local variable with that name exists, any more than the existence of a global name means that a global variable with that name exists. With last arguments saves enabled (flag -55 clear) and no programs HALTed, try running the following program (use a different name if you already have a variable named 'A' on your path):

\<< 0 \-> A \<< 'A' \>> \>>
Now you have 'A' (a local name) left on the stack. Key in A on the command line and press ENTER to put the global name 'A' on the stack (as a global name because there's no reason for the compiler to treat it as anything else). Press EVAL and the global name 'A' will simply be returned to the stack. Execute the TYPE command, and it will take the global name 'A' from the stack and return 6., indicating that is was indeed a global name. DROP the 6. so that the local name 'A' is on level one, and press EVAL again; this time it will error out with "EVAL Error: Undefined Local Name" and the local name 'A' will be returned to the stack as the last argument. Execute the TYPE command again, and this time it will take the local name 'A' from the stack and return 7., indicating that it was indeed a local name.

How are you trying to "extend scope of local variable one level?". A local variable is, well, "local", and for UserRPL, its scope is restricted to its defining procedure, a program or algebraic object, or certain commands such as FOR and the summation command use a named local variable with a limited scope for the index. Ending the defining procedure automatically abandons all local variables created for it. Outside of the defining procedure, its local variables simply don't exist, although a local name may exist.

That's all by design; if I use a local name within its defining procedure, it means only the local variable with that name defined for that procedure, not, for example, a local variable with the same name defined for some other procedure, or a global variable, library command, or built-in command or function that happens to have the same name. And of course, if I use the same name outside of a procedure defining that local variable, it doesn't mean that local variable.

But a local variable doesn't cease to exist within a sub-program or algebraic object within the local variable's defining procedure; you can still use a local variable defined for an "outer procedure" within an "inner procedure". That said, another local variable with the same name can be created within the inner procedure, in which case the local variable defined for the outer procedure can't be accessed while the one in the inner procedure exists.

If more than one local variable with the same name exists, only the most recently created one with that name is accessible.

Inner procedures can use any local variable defined for any of their outer procedures, as long as a new local variable with the same name hasn't been defined, but an outer procedure can never access a local variable defined only for its inner procedures.

Here's the idea behind compiled local names. First off, local names and global names are two different object types. In the 28 series and 48SX/S, when source code (as in the command line) is parsed, a series of characters that could be a local name is compiled to a local name object only if it's between the "Create Local Variables Command" (the right arrow character standing alone) and a defining procedure (program or algebraic object), or it's within a defining procedure for which a matching local name is defined, or it matches the name of a local variable that currently exists within local memory (any suspended procedures), or it's the name of an index local variable within the scope of the structure or command that it's defined for.

But suppose that I have a program that creates a local variable x, and I have it call another program by name, and further suppose that I want to have the called program use the local variable x. Ordinarily, when I compile the called program, x will be compiled as a global name object. I could have another local variable structure that defines x within the called program, but if I did, it would be a new local variable x, and the local variable x in the calling program wouldn't be accessible as long as the more recent local variable x in the called program was in existence.

What does work is to have the calling program put the contents of its local variable x on the stack before calling the other program, and then have the called program use a local variable structure to create a new local variable x with the same contents, put that's inefficient and seems clumsy.

Another method that works is to execute a program like

\<< 0 \-> x \<< HALT \>>
so that I have a local variable named x in a local memory, and then compile the called program that uses x, and since a local variable named x already exists in the suspended environment, any occurrence of x in the called program is compiled as a local name. Then I can press CONT to finish the suspended program, abandoning the local variable. That works, but isn't very convenient. Perhaps worst, if I later decide to edit the called program, I have to remember to create a local variable named x in a suspended environment again, or else any occurrence of x will be compiled as a global name instead of a local name. I expect that that's caused a lot of puzzling bugs; a user edits a working program, and then it no longer works for no very obvious reason, and even after editing the source code back to exactly the same as the working version, it still doesn't work.

So starting with the 48GX/G, there's a very simple new rule when source code is parsed. If a series of characters is presumed to be a name, the first rule is that if it starts with a left arrow, then it's compiled to a local name object.

Why the left arrow? Well, first off, it would be undesirable to do anything that would be likely to be incompatible with existing source code, and existing source code with names starting with the left arrow seemed rather improbable (although certainly possible), and second, the left arrow should be easy to remember because the right arrow was already associated with local names; it's still a horizontal arrow, just pointing in the opposite direction. Of course there were already command names starting with the right arrow, and no doubt a lot of global names and library names starting with the right arrow were already in use, so that would've been a very bad choice.

Note that the above applies to UserRPL. With SysRPL, local names are called lams, and local variables (also called lambda variables) are created with commands such as BIND, and have to be abandoned with commands such as ABND. Also, you can use "nullnamed" local variables, which are referenced by position, because they all have the same empty name. But I wouldn't recommend starting with SysRPL until you're comfortable working with UserRPL.

Regards,
James

Edited: 9 Nov 2006, 6:31 a.m.

            
Re: 50g system software
Message #3 Posted by Brad Barton on 9 Nov 2006, 4:29 p.m.,
in response to message #2 by James M. Prange (Michigan)

Thank you for your detailed explanation of the sublteties of declaring local vs declaring global entities. As a relative newbie to UserRPL, I have a few questions.

Quote:
What do you mean by constraints on compiled local variables? The documentation really should've called them "compiled local names" instead of "compiled local variables". A compiled local name (48GX/G and newer only) is one that starts with a left arrow (character 142), which the compiler treats as the source code for a local name, even when a local variable with that name isn't being created and doesn't already exist.

I'm not clear on the difference between a local variable and a local name. Do you mean that a local name is just an empty pointer?

Quote:
With last arguments saves enabled (flag -55 clear) and no programs HALTed, try running the following program (use a different name if you already have a variable named 'A' on your path):
\<< 0 \-> A \<< 'A' \>> \>>
Now you have 'A' (a local name) left on the stack.


By this I think you are telling us that the 'A' on the stack is just the pointer that tells us where the value (0 in this case) is stored. How is this different from the variable 'A'?
Quote:
Key in A on the command line and press ENTER to put the global name 'A' on the stack (as a global name because there's no reason for the compiler to treat it as anything else). Press EVAL and the global name 'A' will simply be returned to the stack. Execute the TYPE command, and it will take the global name 'A' from the stack and return 6., indicating that is was indeed a global name. DROP the 6. so that the local name 'A' is on level one, and press EVAL again; this time it will error out with "EVAL Error: Undefined Local Name" and the local name 'A' will be returned to the stack as the last argument. Execute the TYPE command again, and this time it will take the local name 'A' from the stack and return 7., indicating that it was indeed a local name.
It's clear here that the EVAL error occured because the local variable was abandoned at the close of the sub-program. Good example.

Quote:
...Outside of the defining procedure, its local variables simply don't exist, although a local name may exist.
Here's where you lose me. Are you saying that you can attempt to call a local variable using the local name, but this will only result in the aforementioned error? It seems trivial, since I can call any random local name, and get the same error. That's why I'm questioning my (admittedly limited) understanding here.
Quote:
But a local variable doesn't cease to exist within a sub-program or algebraic object within the local variable's defining procedure; you can still use a local variable defined for an "outer procedure" within an "inner procedure".
So I could get away with the following:

\<< \->A \<< A SQ \<< A 4 + \>> EVAL * \>> \>>

Yes or no? (Never mind. I just answered my own question, it's YES)

Quote:
That said, another local variable with the same name can be created within the inner procedure, in which case the local variable defined for the outer procedure can't be accessed while the one in the inner procedure exists.
Not sure why I'd want to except as an exercise to understand all this. Otherwise seems like sloppy programming.

Quote:
Here's the idea behind compiled local names. First off, local names and global names are two different object types. In the 28 series and 48SX/S, when source code (as in the command line) is parsed, a series of characters that could be a local name is compiled to a local name object only if it's between the "Create Local Variables Command" (the right arrow character standing alone) and a defining procedure (program or algebraic object),
Yes, this is clear from the above.
Quote:
or it's within a defining procedure for which a matching local name is defined,
My confusion over the significance of local names keeps me from comprehending what your saying in this instance.
Quote:
or it matches the name of a local variable that currently exists within local memory (any suspended procedures),
Yes, you show that with your HALT example, below.
Quote:
or it's the name of an index local variable within the scope of the structure or command that it's defined for.
Uhh yeah, not ready for that either.
Quote:
But suppose that I have a program that creates a local variable x, and I have it call another program by name, and further suppose that I want to have the called program use the local variable x. Ordinarily, when I compile the called program, x will be compiled as a global name object. I could have another local variable structure that defines x within the called program, but if I did, it would be a new local variable x, and the local variable x in the calling program wouldn't be accessible as long as the more recent local variable x in the called program was in existence.

What does work is to have the calling program put the contents of its local variable x on the stack before calling the other program, and then have the called program use a local variable structure to create a new local variable x with the same contents, put that's inefficient and seems clumsy.


Nice trick.
Quote:
Another method that works is to execute a program like
\<< 0 \-> x \<< HALT \>>
so that I have a local variable named x in a local memory, and then compile the called program that uses x, and since a local variable named x already exists in the suspended environment, any occurrence of x in the called program is compiled as a local name. Then I can press CONT to finish the suspended program, abandoning the local variable. That works, but isn't very convenient. Perhaps worst, if I later decide to edit the called program, I have to remember to create a local variable named x in a suspended environment again, or else any occurrence of x will be compiled as a global name instead of a local name. I expect that that's caused a lot of puzzling bugs; a user edits a working program, and then it no longer works for no very obvious reason, and even after editing the source code back to exactly the same as the working version, it still doesn't work.

So starting with the 48GX/G, there's a very simple new rule when source code is parsed. If a series of characters is presumed to be a name, the first rule is that if it starts with a left arrow, then it's compiled to a local name object....


Really good stuff here, and if I can be made to understand what a "local named object" is, I think I can make better use of what you're telling me. Thanks for the assistance.
            
Re: 50g system software
Message #4 Posted by Ron Allen on 10 Nov 2006, 1:42 a.m.,
in response to message #2 by James M. Prange (Michigan)

James, thanks for sharing your great knowledge of these calcs. Brad, thanks for participating and for your intelligent well-organized questions.

James, I might owe you an apology. We don't know each other well enough for me to joust with you about such things as geographic pride. I think that my only saving grace is that I had identified my bride's allegience to her native Michigan and the Spartans by which I could claim some license. I therefore apologize to you and other Michiganders for some careless remarks. BTW, I learned long ago to ignore comments which suggest that my cousins and I are models for those cave men in the Geico ads having grown up in Alabama.

I'll try to give you both a flavor of my "big-picture thinking while I ponder both your comments. Having far less knowledge of the hp design, it is possible that my willingness to expose my ignorance in exchange for your knowledge will serve as some benefit to us all.

I did try a few resets like the warm start. Since the problem consistently cures itelf in a relatively short time I didn't try all for fear of losing memory. I was hoping that you were in touch with tech support enough to say that those types of problems will be addressed in patches - near future.

My comments about constraints and uses of the compiled variable is based primarily on the AUG, the 48g documentation and some experiments of my own. The documents suggest that once defined at a given level and within a given nest starting with the identifying level, the identifying variable will stay alive within its nest. My trials partially support this. I started running into the freeze problem before I could check on full use of the variable name, but the use of the variable name to retrieve the constant stored there at definition time worked for one additional LEVEL BEYOND the defining level before giving way to a global by the same name when trying to recall from any level within and subordinate to that level.

I quit for this letter and will get back to you on specifics later.

Ron

                  
Re: 50g system software
Message #5 Posted by Ron Allen on 10 Nov 2006, 8:23 p.m.,
in response to message #4 by Ron Allen

WELL, I LEARNED A LOT ABOUT VARIABLES AND FREEZERS - THANKS FOR THE LESSONS!

The point of confusion is between RPL AND RPN. I frankly was under the impression that compiling as opposed to interpreter language began at another level and that "compiled" in this case referred to some fancy Hollywood type wording. DUH, the word compile was attached right there to see. The logic for RPL, especially in the organization and selection of variables would follow in most cases. Some really good lessons flowed from my error, I know that Brad expressed his new knowledge. Guess the cave man stigma will continue, after all.

I really did suffer a small (TIA) stroke in October. I remember the admonition, "The only stupid question is the one not asked. Thank you so much for the education. I'm sure you can follow the logic of some of my problems by thinking interpreter vs. compiler. Thanks again

Ron


[ Return to Index | Top of Index ]

Go back to the main exhibit hall