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.