Let's first repeat the complete SysRPL ROM code
for xSUBST (the UserRPL SUBST command):
( ~xSUBST ROMPTR 314 2)
::
CK2&Dispatch
BINT4
FPTR 6 1D9=^FLAGLISTEXEC
BINT9
FPTR 6 1DA=^FLAGSYMBEXEC
BINT6
FPTR 6 1DB=^FLAGIDNTEXEC
BINT7
FPTR 6 1DB=^FLAGIDNTEXEC
;
On 12/4/2013 3:26 PM, Dante wrote:
> Checking out the (#1DB006h FLASHEVAL) pointer
> for global (type 6) and local (type 7) variable names,
> knowing that my 2 arguments are (type 9)...
STOP! -- a "type 9" (algebraic) object may _contain_
some local and/or global variable names,
as well as a bunch of other stuff,
but it is NOT the same type of object
as just _one isolated variable name_ (a/k/a ID),
so if you have called the function intended for
ID objects when the actual object was an algebraic
(composite) object, and your memory didn't get wiped out,
then count yourself lucky!
Although the CK2&Dispatch in the above
is making sure that at least two stack arguments exist,
it also matches object types against those BINTs
in the code above, which happen to be matched against
the type of only the level 1 argument,
to decide which "deeper" internal function to call.
A very compressed chart of those "object dispatch type codes"
(which need not match the return values of the UserRPL TYPE command,
although, by coincidence, some of them do) appears below,
in a program that I keep in my HOME directory
to display this chart on my own calculator (this fixed-width text,
exactly 33 characters per line, will look right only when displayed
in a fixed-width font, such as on the calc screen itself):
\<<
" Object Dispatch Type Codes
1 % 7 LAM D TAG 4F C%% AF LDT
2 C% 8 ::; E UNIT 5F L[] BF ACP
3 $ 9 ALG 0F ROMP 6F CHR CF FON
4 [] A SYC 1F # 7F COD DF MFO
5 {} B HXS 2F RRP 8F LIB EF EX4
6 ID C GRO 3F %% 9F BKP FF INT"
SCROLL \>> HOME 'TYC' STO
So we see that if your level 1 argument is type 9
(algebraic object), regardless of the type of level 2,
you should be invoking #1DA006h FLASHEVAL (^FLAGSYMBEXEC)
rather than #1DB006h FLASHEVAL (^FLAGIDNTEXEC)
If there is any chance that the type of level 1 argument
upon which you want SUBST to act is not absolutely always
guaranteed to be the same exact object type, then you should
abandon any thought of trying to replace SUBST by a single FLASHEVAL,
and just let the UserRPL SUBST command do its job, which is
to call the right inner function for each different object type,
as well as to abort on either too few arguments
or an unallowed object type on level 1 (CKn&Dispatch
also handles "automatic list processing," although this
is slightly outside the scope of our main lesson here).
> BTW, how can I build those SYSEVALS, LIBEVALS, and FLASHEVALS?
(SysRPL <-> UserRPL)
PTR <-> #address(h) SYSEVAL
ROMPTR <-> #LLLnnn(h) LIBEVAL
FPTR <-> #nnnbbb(h) FLASHEVAL
The Advanced User's Reference Manual (AUR)
is of course a bit more detailed than this,
and of course you also need to know
the argument values (ROM address, library#,
function#, flash bank#) for each command,
which you have to discover either in ROM,
or in a table of entry points such as
Joe Horn's cross-reference lists,
or in some book about SysRPL programming, etc.,
and if you publish or share anything, it had better
be "supported" or absolutely "stable" (i.e.
no variations whatsoever between ROM versions).
One past hero, however, whom we might think of
as "Admiral" (rather than Prof. Wolfgang) Rautenberg
was famous for saying "Damn the non-supported entry points,
full speed ahead!" -- and his resulting world-record setting
code has crashed in many a later ROM, but there's always been
someone around to update his libraries again for each new ROM,
so be thankful that there won't be any more of those ;-)
[r->] [OFF]