RPLMAN
RPLMAN
RPLMAN
1. Introduction......................................
2. RPL Principles....................................
2.1 Origins.....................................
2.2 Mathematical Control........................
2.3 Formal Definitions .........................
2.4 Execution...................................
2.4.1
EVAL...............................
2.4.2
Data Class Objects.................
2.4.3
Identifier Class Objects...........
2.4.4
Procedure Class Objects............
2.4.5
Object Skipover and SEMI...........
2.4.6
RPL Pointers.......................
2.5 Memory Management...........................
2.6 User RPL and System RPL.....................
2.7 Programming in System RPL...................
2.8 Sample RPL Program..........................
2.8.1
The Source File....................
2.8.2
Compiling the Program..............
2
2
3
5
6
8
9
9
10
10
11
11
13
14
16
16
18
3. Object Structures.................................
3.1 Object Types................................
3.1.1
Identifier Object..................
3.1.2
Temporary Identifier Object........
3.1.3
ROM Pointer Object.................
3.1.4
Binary Integer Object..............
3.1.5
Real Number Object.................
3.1.6
Extended Real Number Object........
3.1.7
Complex Number Object..............
3.1.8
Extended Complex Number
Object.............................
3.1.9
Array Object.......................
3.1.10 Linked Array Object................
3.1.11 Character String Object............
3.1.12 Hex String Object..................
3.1.13 Character Object...................
3.1.14 Unit Object........................
3.1.15 Code Object........................
3.1.16 Primitive Code Object..............
3.1.17 Program Object.....................
3.1.18 List Object........................
3.1.19 Symbolic Object....................
3.1.20 Directory Object...................
3.1.21 Graphics Object....................
3.2 Terminology and Abbreviations...............
19
19
19
19
20
20
20
21
22
4. Binary Integers...................................
4.1 Built-in Binary Integers....................
4.2 Binary Integer Manipulation.................
4.2.1
Arithmetic Functions...............
4.2.2
Conversion Functions...............
32
32
34
34
35
5. Character Constants...............................
36
22
23
23
25
25
25
26
26
27
27
28
28
29
29
30
37
- i -
6.1
6.2
Character Strings...........................
Hex Strings.................................
37
39
7. Real Numbers......................................
7.1 Built-in Reals..............................
7.2 Real Number Functions.......................
41
41
41
8. Complex Numbers...................................
8.1 Built-in Complex Numbers....................
8.2 Conversion Words............................
8.3 Complex Functions...........................
46
46
46
46
9. Arrays............................................
48
49
51
52
54
55
57
59
60
61
62
63
66
68
68
70
70
71
16. Error
16.1
16.2
16.3
16.4
73
73
73
74
75
76
76
77
78
79
80
17.3 If/Then/Else................................
17.4 CASE words..................................
83
84
87
89
89
- ii -
89
91
92
93
94
94
95
96
97
97
98
98
99
99
101
102
102
103
104
104
105
105
109
109
110
111
112
113
114
115
116
116
117
117
119
120
120
121
- iii -
1. Introduction
The HP 48 calculator was designed to be a customizable
mathematical scratchpad for use by students and
professionals in technical fields. In many respects it is a
descendent of the HP 41, providing a much broader and more
sophisticated computation capability than the HP 41, but
preserving its RPN/key-per-function orientation.
The HP 48 uses the so-called Saturn architecture, named by
the code name of the original CPU designed for the HP 71B
handheld computer. It also uses a custom operating
system/language called RPL, which was designed to provide
symbolic mathematical capabilities, executing from ROM in a
limited RAM environment (it is today still the only symbolic
system that can run in ROM). The combination of specialized
hardware and firmware makes it relatively difficult to
develop application software for the HP48, and accordingly
the HP48 is not positioned as a primary external application
vehicle. The orientation of the product and its user
programming language is towards simple customization by the
primary user.
Despite these barriers, the price and physical configuration
of the HP48 make it a desirable application platform for
many software developers, especially those who want to
target customers in the HP48's normal markets. The user
language is suitable for simple programs, but for elaborate
systems, the intentional error protection and other overhead
can result in substantial performance penalties compared
with the programs using the full range of system calls.
Page 1
2. RPL Principles
(The following material was excerpted from "RPL: A
Mathematical Control Language", by W. C. Wickes, published
in "Programming Environments", Institute for Applied Forth
Research, Inc., 1988)
2.1 Origins
In 1984, a project was started at Hewlett-Packard Corvallis
Division to develop a new software operating system to
streamline calculator development and support a new
generation of hardware and software. Previously, all HP
calculators were implemented entirely in assembly language,
a process that was becoming increasingly cumbersome and
inefficient as the memory sizes of the calculators
increased. The objectives for the new operating system were
as follows:
+ To provide execution control and memory management,
including plug-in memory;
+ To provide a programming language for rapid prototyping
and application development;
+ To support a variety of business and technical
calculators;
+ To execute identically out of RAM and ROM;
Page 2
sin
Page 3
Page 4
Page 5
Page 6
Self address
Test for direct execution
Correct O
Correct I
Page 7
Page 8
object itself.
Execution of a temporary identifier object (by the DOLAM
prologue), entails locating the referenced temporary object
and pushing it on the data stack. Non-location is an error
condition.
Page 9
Page 10
Page 11
Page 12
Page 13
Page 14
Page 15
2.8.1 The_Source_File
This program removes
decomposing the list
creating a new empty
into the new list if
( *Req. 1 argument* )
(
(
(
(
Page 16
Page 17
<-<-<-<-<-<--
Page 18
3. Object Structures
This chapter provides additional information about some of
the RPL object types supported by the HP 48. Although the
information is primarily relevant to assembly language
programming, a knowledge of object structure can often help
in understanding performance and efficiency issues in RPL
programming.
Unless explicitly stated otherwise, all specifically-defined
fields within an object body are assumed to be 5 nibbles,
the CPU address width.
3.1 Object Types
3.1.1 Identifier_Object
An identifier object is atomic, has the prologue DOIDNT, and
a body which is an ID Name form.
+---------------+
| -> DOIDNT
| Prologue Address
+---------------+
| ID NAME FORM | Body
+---------------+
Identifier
Object
Temporary
Identifier
Object
Page 19
3.1.3 ROM_Pointer_Object
A ROM pointer object, or XLIB name, is atomic, has the
prologue DOROMP, and a body which is a ROM-WORD identifier.
+------------------+
| -> DOROMP
| Prologue Address
+------------------+
|
|
|
Command
| Body
| Identifier
|
|
|
+------------------+
ROM
Pointer
Object
Page 20
EEEMMMMMMMMMMMMMMMS
(low mem)
EEEEEMMMMMMMMMMMMMMMS
Page 21
3.1.7 Complex_Number_Object
A complex number object is atomic, has the prologue DOCMP,
and a body which is a pair of real numbers.
+------------------+
|
-> DOCMP
| Prologue Address
+------------------+
|
|
Complex
| Real Number
|
Object
|
--------| Body
| Real Number
|
|
|
+------------------+
The use of this object type is to represent single-precision
complex numbers, where the real part is interpreted as the
first real number in the pair.
3.1.8 Extended_Complex_Number_Object
An extended complex number object is atomic, has the
prologue DOECMP, and a body which is a pair of extended real
numbers.
+------------------+
|
-> DOECMP
| Prologue Address
+------------------+
|
|
| Extended Real |
|
Number
|
|
---------| Body
| Extended Real |
|
Number
|
|
|
+------------------+
Extended
Complex Number
Object
The use of this object type is to represent extendedprecision complex numbers in the same way as for the complex
object.
Page 22
3.1.9 Array_Object
An array object is atomic, has the prologue DOARRY, and a
body which is a collection of the array elements. The body
also includes a length field (indicating the length of the
body), a type indicator (indicating the object type of its
elements), a dimension count field, and length fields for
each dimension.
+------------------+
| -> DOARRY
| Prologue Address
+------------------+
|
|
| Length Field
|
| ------------ |
| Type Indicator |
| ------------ |
| Dimension Count |
| ------------ |
|Dimension 1 Length|
| ------------ |
|Dimension 2 Length|
| ------------ |
|
.
|
Array
|
.
|
|
.
| Body
| ------------ |
|Dimension N Length|
| ------------ |
|
|
|
Elements
|
|
|
+------------------+
Object
Page 23
|
.
| Body
| ------------ |
|Dimension N Length|
| ------------ |
|
|
| Pointer Table |
|
|
| ------------ |
|
|
|
Elements
|
|
|
+------------------+
The array elements are object bodies of the same object
type. The type indicator is a prologue address (think of
this prologue address as applying to each element of the
array).
Linked array "OPTION BASE" is always 1. A null linked array
is designated by any dim limit having the value zero. There
is no assumption on the ordering of the elements of a linked
array object, nor on their presence; absence of an element
lying on an allocated dimension is indicated by the value
zero occupying the corresponding pointer table element.
Page 24
3.1.11 Character_String_Object
A character string object is atomic, has the prologue
DOCSTR, and a body which is a character string (a byte
sequence). The body also includes a length field (indicating
the length of the body).
+-------------------+
| -> DOCSTR
| Prologue Address
+-------------------+
|
|
Character
| Length Field
|
String
| -----------| Body
Object
| Byte Sequence |
|
|
+-------------------+
3.1.12 Hex_String_Object
A hex string object is atomic, has the prologue DOHSTR, and
a body which is a nibble sequence. The body also includes a
length field (indicating the length of the body).
+-------------------+
| -> DOHSTR
| Prologue Address
+-------------------+
|
|
Hex
| Length Field
|
String
| -----------| Body
Object
| Nibble Sequence |
|
|
+-------------------+
A typical use for this object type is a buffer or table.
Hex string objects of 16 nibbles or fewer are used to
represent user RPL binary integer objects.
3.1.13 Character_Object
A character object is atomic, has the prologue DOCHAR, and a
body which is a single byte.
+-------------------+
|
-> DOCHAR
| Prologue Address
+-------------------+
|
|
Character
|
Byte
| Body
Object
|
|
+-------------------+
This object type is used to represent one-byte quantities,
such as ASCII or ROMAN8 characters.
Page 25
3.1.14 Unit_Object
A unit object is composite, has the prologue DOEXT, and
a body which is a sequence consisting of a real number
followed by unit name strings, prefix characters, unit
operators, and real number powers, tail delimited by a
pointer to SEMI.
+-------------------+
|
-> DOEXT
|
+-------------------+
| Object Sequence |
|
|
|
->SEMI
|
+-------------------+
3.1.15 Code_Object
A code object is atomic, has the prologue DOCODE, and a body
which is an assembly language slice. The body also includes
a length field (indicating the length of the body). When
executed, the prologue places the system program counter at
the assembly language slice within the body.
+--------------------+
| -> DOCODE
| Prologue Address
+--------------------+
|
|
Code Object
| Length Field
|
| -----------| Body
| Assembly Language |
|
Slice
|
|
|
+--------------------+
The major applications for this object type are assembly
language procedures which can be directly embedded in
composite objects or exist in RAM.
Page 26
3.1.16 Primitive_Code_Object
A primitive code object is a special case of a code object,
used to represent code primitives in built-in libraries.
The prologue of a primitive code object is its body, which
is an assembly language slice; thus, when executed, the body
executes itself.
+------------------+
+----------------| Prologue Address
|
+------------------+
+----->|
|
Primitive
| Assembly Language| Body
Code Object
|
Slice
|
|
|
+------------------+
The primary purpose of this object type is more rapid
execution of code objects in built-in libraries, that is,
these objects are executed without the extra level inherent
in separate prologue execution. However, their structure
implies that (1) they can only exist in built-in libraries
(never in RAM or mobile libraries) since the body must exist
at a fixed address, (2) they cannot be skipped, and (3) they
cannot exist in any situation where traversal may be
required, such as an element of an array or an object within
any composite object.
Note that this object type is an exception to the object
type classification scheme presented at the beginning of
this document. However, an object is a primitive code object
if and only if the prologue address equals the object
address plus 5. In addition, the prologues for this object
type (that is, the object bodies) need not contain logic to
test for direct verses indirect execution since, by
definition, they cannot be executed directly.
3.1.17 Program_Object
A program object (secondary) is composite, has the prologue
DOCOL, and a body which is a sequence of objects and object
pointers, the last of which is an object pointer whose
pointee is the primitive code object SEMI.
+------------------+
| -> DOCOL
| Prologue Address
+------------------+
|
|
|
Object/
|
Secondary
| Object Pointer |
Object
|
Sequence
|
|
-------| Body
|
-> SEMI
|
|
|
+------------------+
Page 27
3.1.18 List_Object
A list object is composite, has the prologue DOLIST, and a
body which is a sequence of objects and object pointers, the
last of which is an object pointer whose pointee is the
primitive code object SEMI.
+------------------+
| -> DOLIST
| Prologue Address
+------------------+
|
|
|
Object/
|
List
| Object Pointer |
Object
|
Sequence
|
|
-------| Body
|
-> SEMI
|
|
|
+------------------+
3.1.19 Symbolic_Object
A symbolic object is composite, has the prologue DOSYMB, and
a body which is a sequence of objects and object pointers,
the last of which is an object pointer whose pointee is the
primitive code object SEMI.
+------------------+
| -> DOSYMB
| Prologue Address
+------------------+
|
|
|
Object/
|
Symbolic
| Object Pointer |
Object
|
Sequence
|
|
-------| Body
|
-> SEMI
|
|
|
+------------------+
This object type is used to represent symbolic objects for
symbolic math applications.
Page 28
3.1.20 Directory_Object
A directory (RAMROMPAIR) object is atomic, has the prologue
DORRP and a body which consists of a Library ID number and a
RAMPART (linked list of variables--object/name pairs.
+----------------+
| -> DORRP
| Prologue Address
+----------------+
|
|
RAMROMPAIR
| ROMPART ID
|
Object
|
-------| Body
|
RAMPART
|
+----------------+
3.1.21 Graphics_Object
A graphics object is atomic, has the prologue DOGROB and a
body which consists of the following:
+ A 5 nibble length field for the data which follows.
+ A five nibble quantity that describes the height of the
graphic in pixels.
+ A five nibble quantity that describes the width of the
graphic in pixels.
+ The data.
The actual row dimension in nibbles (W) is always even for
hardware reasons, hence each row of pixel data is padded
with anywhere from 0-7 bits of wasted data.
+----------------+
| -> DOGROB
| Prologue Address
+----------------+
|
Len(nibs) |
+----------------+
| Height (pixels)|
Graphics
+----------------+ Body
Object
| Width (pixels) |
+----------------+
| Grob Data
|
|
...
|
+----------------+
Page 29
Page 30
CORE:
of a character string: the core of a character string
object is the character data in
the body.
of a hex string: the core of a hex string object is the
nibble sequence in the body.
of a composite: the core of a composite object is the
element sequence in the body not
including the trailing object pointer
to semi.
LENGTH:
of a character string: the length of a character string
object is the number of characters
in the core.
of a hex string: the length of a hex string object is the
number of nibbles in the core.
of a composite: the length of a composite object is the
number of elements in the core.
NULL:
character string: a null character string object is one
whose length is zero.
hex string: a null hex string object is one whose length
is zero.
composite: a null composite object is one whose length
is zero.
INTERNAL:
an internal of a composite object is any object in the
Page 31
4. Binary Integers
Internal binary integers have a fixed size of 20 bits, and
are the most often used type for counting, loops, etc.
Binary integers offer advantages of size and speed.
NOTE: User level binary integers are implemented as hex
strings, so a user's object #247d is actually a hex
string, and should not be confused with a binary
integer whose prologue is DOBINT.
4.1 Built-in Binary Integers
The RPLCOMP compiler interprets a decimal number in a source
file as a directive to produce a binary integer object using a prologue and a body. Built-in binary integers can
be accessed with just an object pointer. For instance, " 43
" (no quotes) in the source file produces a binary object:
CON(5) =DOBINT
CON(5) 43
The object takes five bytes, but can be replaced by the word
"FORTYTHREE", which is a supported entry point which would
generate the following code:
CON(5) =FORTYTHREE
One pitfall to be aware of in binary integer naming
conventions is the difference between the entries FORTYFIVE
and FOURFIVE. In the former case, the value is decimal 45,
but the latter is decimal 69. Names like 2EXT and IDREAL,
where the values are not obvious, are used in conjunction
with the CK&Dispatch family of argument checking commands.
The names for the CK&Dispatch family are equated to the same
places as other bints. This has been done for readability.
For instance, the word SEVENTEEN, for decimal 17, has the
names 2REAL and REALREAL equated to the same location. A
trailing "d" or "h" on a name such as BINT_122d or BINT80h
indicates the base associated with the value.
Words such as ONEONE, ZEROONE, etc. put more than one binary
integer on the stack. These are indicated by a tiny stack
diagram in parentheses, such as (--> #1 #1 ) for ONEONE.
Page 32
FORTYNINE
FORTYONE
FORTYSEVEN
FORTYSIX
FORTYTHREE
FORTYTWO
FOUR
FOURFIVE
FOURTEEN
FOURTHREE
FOURTWO
FOURTY
IDREAL (#61)
INTEGER337
LISTCMP (#52)
LISTLAM (#57)
LISTREAL (#51)
MINUSONE(#FFFFF)
NINE
NINETEEN
ONE
SYMREAL (#A1)
SYMSYM (#AA)
TAGGEDANY (#D0)
TEN
THIRTEEN
THIRTY
THIRTYEIGHT
THIRTYFIVE
THIRTYFOUR
THIRTYNINE
THIRTYONE
THIRTYSEVEN
THIRTYSIX
THIRTYTHREE
THIRTYTWO
THREE
TWELVE
TWENTY
TWENTYEIGHT
TWENTYFIVE
TWENTYFOUR
EIGHTEEN
EIGHTY
EIGHTYONE
ELEVEN
EXT (#E)
EXTOBOB (#E00)
EXTREAL (#E1)
EXTSYM (#EA)
FIFTEEN
FIFTY
FIFTYEIGHT
FIFTYFIVE
FIFTYFOUR
FIFTYNINE
FIFTYONE
FIFTYSEVEN
FIFTYSIX
FIFTYTHREE
FIFTYTWO
FIVE
FIVEFOUR
FIVESIX
FIVETHREE
FORTY
FORTYEIGHT
FORTYFIVE
FORTYFOUR
ONEHUNDRED
TWENTYNINE
ONEONE(--> #1 #1) TWENTYONE
REALEXT (#1E)
TWENTYSEVEN
REALOB (#10)
TWENTYSIX
REALOBOB (#100) TWENTYTHREE
REALREAL (#11) TWENTYTWO
REALSYM (#1A)
TWO
ROMPANY (#F0)
XHI
SEVEN
XHI-1 (#82)
SEVENTEEN
ZERO
SEVENTY
ZEROZERO (--> #0 #0 )
SEVENTYFOUR
ZEROZEROONE (--> #0 #0 #1 )
SEVENTYNINE ZEROZEROTWO (--> #0 #0 #2 )
SIX
ZEROZEROZERO (--> #0 #0 #0 )
SIXTEEN
char (#6F)
SIXTY
id (#6)
SIXTYEIGHT
idnt (#6)
SIXTYFOUR
infreserr (#305)
SIXTYONE
intrptderr (#a03)
SIXTYTHREE
list (#5)
SIXTYTWO
ofloerr (#303)
SYMBUNIT (#9E) real (#1)
SYMEXT (#AE)
seco (#8)
SYMID (#A6)
str (#3)
SYMLAM (#A7)
sym (#A)
SYMOB (#A0)
symb (#9)
Page 33
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
#2 #1
#2 #1
#2 #1
#2 #1
#2 #1
#2 #1
#2 #1
# -->
# -->
# -->
# -->
# -->
# -->
# -->
# -->
# -->
--> #2*#1 )
--> #2+#1 )
--> #2+#1-1 )
--> #2-#1 )
--> (#2-#1)/2 )
--> (#2-#1)+1 )
--> #remainder #quotient )
#+1 )
#+1 and quotes next runstream object
#+1 #+1 )
#-1 )
#*10 )
#+10 )
#+12 )
#*2 )
#+2 )
#2#2/
#3+
#3#4+
#4#5+
#5#6*
#6+
#7+
#8*
#8+
#9+
#MAX
#MIN
2DUP#+
DROP#1DUP#1+
DUP#1DUP3PICK#+
OVER#+
OVER#ROT#+
ROT#+SWAP
ROT#ROT#1+
ROT+SWAP
SWAP#SWAP#1+
SWAP#1+SWAP
SWAP#1SWAP#1-SWAP
SWAPOVER#-
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
# --> #-2 )
# --> FLOOR(#/2) )
# --> #+3 )
# --> #-3 )
# --> #+4 )
# --> #-4 )
# --> #+5 )
# --> #-5 )
# --> #*6 )
# --> #+6 )
# --> #+7 )
# --> #*8 )
# --> #+8 )
# --> #+9 )
#2 #1 --> MAX(#2,#1) )
#2 #1 --> MIN(#2,#1) )
#2 #1 --> #2 #1 #1+#2 )
# ob --> #-1 )
# --> # #+1 )
# --> # #-1 )
#2 #1 --> #2 #1 #1+#2 )
#2 #1 --> #2 #1+#2 )
#2 #1 --> #2 #1-#2 )
#2 ob #1 --> ob #1+#2 )
#2 ob #1 --> #1+#2 ob )
#2 ob #1 --> ob #1-#2 )
# ob ob' --> ob ob' #+1 )
#2 ob #1 --> #1+#2 ob )
#2 #1 --> #1-#2 )
# ob --> ob #+1 )
# ob --> #+1 ob )
# ob --> ob #-1 )
# ob --> #-1 ob )
#2 #1 --> #1 #2-#1 )
Page 34
4.2.2 Conversion_Functions
COERCE
Page 35
5. Character Constants
The following words are useful for converting between
character objects and other object types:
CHR>#
( chr --> # )
#>CHR
CHR>$
( # --> chr )
( chr --> $ )
CHR_*
CHR_4
CHR_>
CHR_J
CHR_T
CHR_d
CHR_n
CHR_x
CHR_+
CHR_5
CHR_A
CHR_K
CHR_U
CHR_e
CHR_o
CHR_y
CHR_,
CHR_6
CHR_B
CHR_L
CHR_V
CHR_f
CHR_p
CHR_z
CHR_CHR_7
CHR_C
CHR_M
CHR_W
CHR_g
CHR_q
CHR_.
CHR_8
CHR_D
CHR_N
CHR_X
CHR_h
CHR_r
CHR_/
CHR_9
CHR_E
CHR_O
CHR_Y
CHR_i
CHR_s
CHR_0
CHR_:
CHR_F
CHR_P
CHR_Z
CHR_j
CHR_t
CHR_1
CHR_;
CHR_G
CHR_Q
CHR_a
CHR_k
CHR_u
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
$
"R\80\80" "R<angle><angle>"
"R\80Z" "R<angle>Z"
"XYZ"
"ABBB"
"{}"
"[]"
"''"
"::"
"()"
""""""
"ECHO"
"EXIT"
"Undefined"
"RAD"
"GRAD"
"\0a"
" "
Page 36
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
CHR_2
CHR_<
CHR_H
CHR_R
CHR_b
CHR_l
CHR_v
( $1 $2 --> $3 )
Appends $2 to $1
( $1 $2 --> $3 )
Same as &$, except that it will attempt the concatenati
on
"in place," if there is not enough memory for the new
string, and the target is in tempob.
$name --> Id )
Converts string object to name object
ob $1 $2 --> $3 ob )
Appends $2 to $1, then swaps result with ob )
$ # --> $' )
Where $' = chars 1 thru #-1 of $
$ chr --> $' )
Prepends chr to $
$ chr --> $' )
Appends chr to $
$1 $2 --> $1 AND $2 )
Bitwise logical AND of two strings
$ --> $' )
Appends space to $
# --> $ )
Creates a string of # spaces
$ --> chr | $ )
Returns 1st chr of $ or NULL$ if $ is null
$ --> $' )
$' is $ minus first character. Returns NULL$ if $ is n
$>ID
&$SWAP
1-#1-SUB$
>H$
>T$
AND$
APPEND_SPACE
Blank$
CAR$
CDR$
COERCE$22
( $ --> $' )
If $ longer than 22 chars., truncates to 21 chars &
appends "..."
( ob --> $ )
Decompiles object for stack display
( ob --> $ )
Internal version of ->STR
( ob --> NULL$ )
Drops object, returns zero-length string
( $name --> $name Id )
Dups, converts string object to name object
( $ --> $ #length )
Returns $ and its length
( $ --> $ flag )
Returns TRUE if $ is zero-length
( ob --> $ )
Decompile object for editing
( # --> $ )
Fetches message from message table
( ID --> $name )
Converts name object to a string
( $ # --> $' )
Returns last # chrs of $
ull
DECOMP$
DO>STR
DROPNULL$
DUP$>ID
DUPLEN$
DUPNULL$?
EDITDECOMP$
JstGETTHEMESG
ID>$
LAST$
Page 37
LEN$
NEWLINE$&$
NULL$
NULL$?
NULL$SWAP
NULL$TEMP
OR$
OVERLEN$
POS$
POS$REV
PromptIdUtil
SEP$NL
SUB$
SUB$1#
SUB$SWAP
SWAP&$
TIMESTR
XOR$
a%>$
a%>$,
palparse
( $ --> #length )
Returns length of $
( $ --> $' )
Appends "\0a" to $
( --> $ )
Returns empty string
( $ --> flag )
Returns TRUE if $ is zero-length
( ob --> $ ob )
Swaps empty string into level 2
( --> $ )
Creates empty string in TEMPOB
( $1 $2 --> $3 )
Bitwise logical OR of two strings
( $ ob --> $ ob #length )
Returns length of $ in level 2
( $search $find #start --> #pos )
Returns #pos (#0 if not found) of $find
within $search starting at head of $search
( $search $find #start --> #pos )
Returns #pos (#0 if not found) of $find
within $search starting at tail of $search
( id ob -> $ )
Returns string in the form "id: ob"
( $ --> $2 $1 )
Separate $ at newline character
( $ #start #end --> $' )
Returns substring of $
( $ #pos --> # )
Returns bint with value of character
in $ at position #pos
( ob $ #start #end --> $' ob )
Returns substring of $ and swaps with ob
( $1 $2 --> "$2$1" )
Appends $1 to $2
( %date %time --> "WED 03/30/90 11:30:15A" )
Returns string time and date
(like user word TSTR)
( $1 $2 --> $3 )
Bitwise logical XOR of two strings
( % --> $ )
Converts % to $ using current display mode
( % --> $ )
Converts % to $ using current display mode
Same as a%>$, but with no commas
( $ --> ob TRUE
)
( $ --> $ #pos $' FALSE )
Parse a string into an object and TRUE, or
returns position of error and FALSE
Page 38
HXS#HXS
HXS>#
HXS>$
HXS>%
HXS<HXS
HXS>HXS
HXS>=HXS
HXS<=HXS
LENHXS
NULLHXS
SUBHXS
( hxs --> % )
Converts hxs to real
( % --> hxs )
Converts real to hxs
( hxs1 hxs2 --> hxs3 )
Appends hxs2 to hxs1
( { hxs1 hxs2 } --> #1 #2 )
Converts list of two hxs into two bints
Generates Bad Argument Value error for
invalid input
( hxs1 hxs2 --> %flag )
Returns %1 if hxs1 <> hxs2, otherwise %0
( hxs --> # )
Converts lower 20 bits of hxs into a bint
( hxs --> $ )
Does hxs>$, then appends base character
( hxs --> % )
Converts hex string to real number
( hxs1 hxs2 --> %flag )
Returns %1 if hxs1<hxs2, otherwise %0
( hxs1 hxs2 --> %flag )
Returns %1 if hxs1>hxs2, otherwise %0
( hxs1 hxs2 --> %flag )
Returns %1 if hxs1>=hxs2, otherwise %0
( hxs1 hxs2 --> %flag )
Returns %1 if hxs1<=hxs2, otherwise %0
( hxs --> #length )
Returns # of nibbles in hxs
( --> hxs )
Returns zero-length hex string
( hxs #m #n --> hxs' )
Returns substring
Page 39
bitAND
( hxs1 hxs2 --> hxs3 )
Bitwise logical AND bitASR
( hxs --> hxs' )
Arithmetic shift right one bit
bitOR
( hxs1 hxs2 --> hxs3 )
Bitwise logical OR bitNOT
( hxs1 hxs2 --> hxs3 )
Bitwise logical NOT bitRL
( hxs
--> hxs' )
Circular left shift by 1 bit
bitRLB
( hxs --> hxs' )
Circular
left shift by 1 byte bitRR
( hxs --> hxs' )
Circular right shift by 1 bit
bitRRB
( hxs --> hxs' )
Circular
right shift by 1 byte bitSL
( hxs --> hxs' )
Shift left by 1 bit bitSLB
( hxs
--> hxs' )
Shift left by 1 byte
bitSR
( hxs --> hxs' )
Shift
right by 1 bit bitSRB
( hxs --> hxs' )
Shift right by 1 byte bitXOR
(
hxs1 hxs2 --> hxs3 )
Bitwise logical XOR
Wordsize control:
WORDSIZE
( --> # )
Returns user
binary integer wordsize dostws
( # --> )
Stores binary wordsize hxs>$
(
hxs --> $ )
Converts hex string to chr
string using the
current display mode and
wordsize
Page 40
7. Real Numbers
Real numbers are written with %, and extended real numbers
are written with %%.
7.1 Built-in Reals
The following real and extended real numbers are built in:
%%.1
%%.4
%%.5
%%0
%%1
%%10
%%12
%%2
%%2PI
%%3
%%4
%%5
%%60
%%7
%-2
%-3
%-4
%-5
%-6
%-7
%-8
%-9
%-MAXREAL
%-MINREAL
%.1
%.5
%0
%1
%10
%100
%11
%12
%13
%14
%15
%16
%17
%180
%2
%20
%21
%22
%23
%24
%25
%26
%27
%3
%360
%4
%5
%6
%7
%8
%MAXREAL
%MINREAL
%PI
%e
%-1
reals
%%3 ob1 )
reals,
reals,
%%*UNROT
%%+
%%%%ABS
%%ACOSRAD
%%ANGLE
%%ANGLEDEG
Page 41
%%ANGLERAD
%%ASINRAD
%%CHS
%%COS
%%COSDEG
%%COSH
%%COSRAD
%%EXP
%%FLOOR
%%H>HMS
%%INT
%%LN
%%LNP1
%%MAX
%%P>R
%%R>P
%%SIN
%%SINDEG
%%SINH
%%SQRT
%%TANRAD
%%^
%+
%+SWAP
%%1+
%1-
Page 42
%>#
%>%%
%>%%%>%%1
%>%%ANGLE
%>%%SQRT
%>%%SWAP
%>C%
%>HMS
%ABS
%ABSCOERCE
%ACOS
( % --> hxs )
Converts real to binary integer
( % --> %% )
Converts real to extended real
( %1 %2 --> %%3 )
Converts 2 % to %%, then subtracts
( %x --> %% )
Converts % to %%, then does 1/x
( %x %y --> %%angle )
Angle in current angle mode
( % --> %% )
Converts % to %%, then sqrt(x)
( ob % --> %% ob )
Converts % to %%, then SWAP
( %real %imag --> C% )
Real to complex conversion
( % --> %hh.mmss )
Decimal hours to hh.mmss
( % --> %' )
Absolute value
( % --> # )
Absolute value, convert to bint
( % --> %' )
Arc cosine
%ACOSH
%ALOG
%ANGLE
%ASIN
%ASINH
%ATAN
%ATANH
%CEIL
%CH
%CHS
%COMB
%COS
%COSH
%D>R
%EXP
%EXPM1
( % --> %' )
Hyperbolic arc cosine
( % --> %' )
10^x
( %x %y --> %angle )
Angle using current angle mode from %x %y
( % --> %' )
Arc sine
( % --> %' )
Hyperbolic arc sine
( % --> %' )
Arc tangent
( % --> %' )
Hyperbolic arc tangent
( % --> %' )
Next greatest integer
( %1 %2 --> %3 )
Percent change
( % --> %' )
Change sign
( %m %n -> %COMB(m,n) )
Combinations of m items taken n at a time
( % --> %' )
Cosine
( % --> %' )
Hyperbolic cosine
( % --> %' )
Degrees to radians
( % --> %' )
e^x
( $ --> %' )
e^x-1
Page 43
%EXPONENT
%FACT
%FLOOR
%FP
%HMS+
%HMS%HMS>
%IP
%IP>#
( % --> %' )
Returns exponent
( % --> %! )
Factorial
( % --> %' )
Greatest integer <= x
( % --> %' )
Fractional part
( %1 %2 --> %3 )
HH.MMSS addition
( %1 %2 --> %3 )
HH.MMSS subtraction
( % --> %' )
Convert hh.mmss to decimal hours
( % --> %' )
Integer part
( % --> # )
IP(ABS(x) converted to binary integer
%LN
%LNP1
%LOG
%MANTISSA
%MAX
%MAXorder
%MIN
%MOD
%NFACT
%NROOT
%OF
%PERM
%POL>%REC
%R>D
%RAN
%RANDOMIZE
%REC>%POL
%SGN
%SIN
( % --> %' )
ln(x)
( % --> %' )
ln(x+1)
( % --> %' )
Common log
( % --> %' )
Returns mantissa
( %1 %2 --> % )
Returns larger of two reals
( %1 %2 --> %larger %smaller )
Orders two numbers
( %1 %2 --> % )
Returns smaller of two reals
( %1 %2 --> %3 )
Returns %1 MOD %2
( % --> %' )
Factorial
( %1 %2 --> %3 )
Nth root
( %1 %2 --> %3 )
Returns percantage of %1 that is %2
( %m %n --> %PERM(%m,%n) )
Returns permutations of %m items
taken %n at a time
( %x %y --> %radius %angle )
Rectangular to polar conversion
( %radians --> %degrees )
Radians to degrees
( --> %random )
Random number
( %seed --> )
Updates random number seed, uses the
system clock if %=0
( %radius %angle --> %x %y )
Polar to rectangular conversion
( % --> %' )
Sign: -1, 0 or 1 returned depending
on the sign of the argument
( % --> %' )
Page 44
%SINH
%SPH>%REC
%SQRT
%T
%TAN
%TANH
Sine
( % --> %' )
Hyperbolic sine
( %r %th %ph --> %x %y %z )
Spherical to rectangular conversion
( % --> %' )
Square root
( %1 %2 --> %3 )
Percent total
( % --> %' )
Tangent
( % --> %' )
%^
2%%>%
2%>%%
C%>%
DDAYS
DORANDOMIZE
RNDXY
TRCXY
SWAP%>C%
Hyperbolic tangent
( %1 %2 --> %3 )
Exponential
( %%1 %%2 --> %1 %2 )
Extended real to real conversion
( %1 %2 --> %%1 %%2 )
Real to extended real conversion
( C% --> %real %imag )
Complex to real conversion
( %date1 %date2 --> %diff )
Days between dates in DMY format
( % --> )
Updates random number seed
( %number %places --> %number' )
Rounds %number to %places
( %number %places --> %number' )
Truncates %number to %places
( %imag %real --> C% )
Real to complex conversion
Page 45
8. Complex Numbers
Complex numbers are represented by C%, extended complex
numbers by C%%.
(0,0)
(1,0)
(-1,0)
(%%1,%%0)
(
(
(
(
(
(
(
(
(
(
( C% --> C%' )
Inverse
( C% --> % )
Returns SQRT(x^2+y^2) from (x,y)
( C% --> C%' )
Arc cosine
( C% --> C%' )
Common antilog
( C% --> %)
Returns ANGLE(x,y) from (x,y)
( C% --> C%' )
Arc sine
( C% --> C%' )
Arc tangent
( C%1 C%2 --> C%3 )
Power
( C% --> C%' )
Change sign
( C%% --> C%%' )
Change sign
( C% --> C%' )
Conjugate
( C%% --> C%%' )
Conjugate
Page 46
C%COS
C%COSH
C%EXP
C%LN
C%LOG
C%SGN
C%SIN
C%SINH
C%SQRT
C%TAN
C%TANH
( C% --> C%' )
Cosine
( C% --> C%' )
Hyperbolic cosine
( C% --> C%' )
e^z
( C% --> C%' )
Natural logarithm
( C% --> C%' )
Common logarithm
( C% --> C%' )
Returns (x/SQRT(x^2+y^2),y/SQRT(x^2+y^2)
( C% --> C%' )
Sine
( C% --> C%' )
Hyperbolic sine
( C% --> C%' )
Square root
( C% --> C%' )
Tangent
( C% --> C%' )
Hyperbolic tangent
Page 47
9. Arrays
The notation [array] represents a real or complex array.
[arry%] and [arryC%] represent real and complex arrays,
respectively. {dims} means a list of array dimensions,
which may be either { #cols } or { #rows #cols }.
Unless otherwise indicated, the following words do NOT check
for out-of-range conditions (i.e. elements specified that
are not within the range of the current array).
ARSIZE
( [array] --> #elements )
( [array] --> {dims} )
GETATELN
( # [array] --> ob TRUE )
( # [array] --> FALSE ) (no such element)
MAKEARRY
( {dims} ob --> [array] )
Creates an unlinked array having the same
element type as ob. All elements are
initialized to ob.
MATCON
( [arry%] % --> [arry%]' )
( [arryC%] C% --> [arryC%]' )
Sets all elements in array to % or C%.
MATREDIM
( [array] {dims} --> [array]' )
MATTRN
( [array] --> [array]' )
MDIMS
( [1-D array] --> #m FALSE )
( [2-D array] --> #m #n TRUE )
MDIMSDROP
( [2-D array] --> #m #n )
Don't use MDIMSDROP on a vector!
OVERARSIZE
( [array] ob --> [array] ob #elements )
PULLREALEL
( [arry%] # --> [arry%] % )
PULLCMPEL
( [arryC%] # --> [arryC%] C% )
PUTEL
( [arry%] % # --> [arry%]' )
( [arryC%] C% # --> [arryC%] )
PUTREALEL
( [arry%] % # --> [arry%]' )
PUTCMPEL
( [arryC%] C% # --> [arryC%]' )
Page 48
(
(
(
(
>TCOMP
CARCOMP
(
(
(
CDRCOMP
(
(
DUPINCOMP
DUPLENCOMP
DUPNULLCOMP?
DUPNULL{}?
EQUALPOSCOMP
(
(
(
(
(
Embedded?
INCOMPDROP
INNERCOMP
INNERDUP
LENCOMP
NEXTCOMPOB
(
(
(
(
(
(
NTHCOMDDUP
NTHCOMPDROP
NTHELCOMP
(
(
(
(
NTHOF
NULL::
NULL{}
(
(
(
Page 49
ONE{}N
Ob>Seco
POSCOMP
( ob --> { ob } )
( ob --> :: ob ; )
( comp ob pred --> #i | #0 )
If the specified object "matches" an element
of the specified composite, where "match" is
defined as the specified predicate returning
TRUE when applied to an element of the comp
and the object, then POSCOMP returns the leftto- right index of the element within the
composite, or zero. For instance, to find the
first real less than 5 in a list of reals:
:: {list} 5 ' %< POSCOMP ;
PUTLIST
SUBCOMP
SWAPINCOMP
THREE{}N
TWO{}N
{}N
apndvarlst
matchob?
p
Page 50
( ob % --> tagged )
Tags ob with %
>TAG
( ob $ --> tagged )
Tags ob with $
ID>TAG
STRIPTAGS
( tagged --> ob )
Removes all tags
STRIPTAGSl2
TAGOBS
( ob $ --> tagged )
( ob1 ... obn { $1 ... $n }
--> tagged1 ... taggedn )
Tags one object, or several objects
if a list of tags is in level 1
USER$>TAG
( ob $ --> tagged )
Tags ob with $ (up to 255 chrs valid)
Page 51
UM>U
UM%
UM%CH
UM%T
UM+
UMUM*
UM/
UM^
UM1/
UMABS
UMCHS
UMCONV
UMCOS
UMMAX
Page 52
UMMIN
UMSI
UMSIN
UMSQ
UMSQRT
UMTAN
UMU>
UMXROOT
UNIT>$
Page 53
Page 54
Note that the RPL compiler does not check to see if there is
an ABND to match each BIND. You can include the two within
a single program, or put them in separate programs as you
like with no restrictions other than the requirements of
good structured programming practice. This also means that
you must remember to include the ABND at some point,
otherwise you may leave unnecessary environments around
after a program has completed execution. (In user RPL, you
do not have such freedom. The structure word -> has BIND
built into it, and the command line parser demands that
there be a matching >> or ' that includes ABND.)
13.1 Structure of the Temporary Environment Area
The structure of the temporary environment area is shown
below.
-------------------------|
Link Field
|-----+
---------------------------------|
|
| First Temporary Environment |
|
---------------------------------|
|
-------------------------|
+------------|
Link Field
|<----+
|
---------------------------------|
|
| Second Temporary Environment |
|
---------------------------------.
.
.
.
.
.
|
------------------------+-----------> |
Link Field
|-----+
---------------------------------|
|
|
Last Temporary Environment |
|
---------------------------------|
|
------------------------|
|
0
|<----+
-------------------------
(The first
temporary
environment
is that most
recently
created)
(high memory)
Page 55
Page 56
Page 57
Page 58
( ob --> lamob ob )
Does :: 1GETLAM ABND SWAP ;
( --> lamob )
Does :: 1GETLAM ABND ;
1GETLAM
...
22GETLAM
( --> ob )
Returns contents of Nth lam
1GETSWAP
1LAMBIND
1NULLLAM{}
1PUTLAM
...
22PUTLAM
2GETEVAL
@LAM
ABND
BIND
CACHE
( ob --> lamob ob )
Does :: 1GETLAM SWAP ;
( ob --> )
Does :: 1NULLLAM{} BIND ;
( --> { NULLLAM } )
Returns list with one null lam
( ob --> )
( Stores ob into Nth lam
( --> ? )
Recalls & evaluates ob in 2nd lam
( id --> ob TRUE )
( id --> FALSE )
Recalls lam by name, returns ob and
TRUE if id exists; FALSE otherwise
( --> )
Abandons topmost temp var env.
( ob ... { id ... } --> )
Creates new temp var env.
( obn ... ob1 n lam --> ) Saves away n objects plus the c
ount
n in a temporary environment, each object being bound t
o the
DUMP
e of
CACHE, BUT: it ONLY works with NULLLAM as the cached na
me,
DUP1LAMBIND
DUP4PUTLAM
DUPTEMPENV
GETLAM
NULLLAM
PUTLAM
STO
STOLAM
Page 59
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
} BIND
...
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
NULLLAM
With:
NULLLAM TWENTYFOUR NDUPN
{}N BIND
The first method takes 67.5 bytes, whereas the latter method
takes 12.5 bytes, so there's a savings of 55 bytes!
You can also use TWENTYFOUR ' NULLLAM CACHE, which is
shorter yet and does not require building the list of null
identifiers in tempob. Note, however, that CACHE adds an
extra temporary variable (to hold the count), so all of the
variable position numbers differ by one from the previous
methods.
Page 60
that use the two words instead of the combined form, but all
algebraic functions must use CK<n>&Dispatch since these
words also serve to identify the argument count used by a
function.
If an object is not intended as a library command, then it
should have the following structure:
:: CK0NOLASTWD ... ; for 0 argument programs, or
:: CK<n>NOLASTWD CK<n>&DISPATCH1 type1 action1
type2 action2
...
typen actionn
;
for <n> argument programs, or
:: CKNNOLASTWD ... ; for programs that take
arguments as specified
in level 1.
Page 61
CK0NOLASTWD
CK1NOLASTWD
CK2NOLASTWD
CK3NOLASTWD
CK4NOLASTWD
CK5NOLASTWD
No arguments required
One argument required
Two arguments required
Three arguments required
Four arguments required
Five arguments required
Each word CK<n>... "marks" the stack below the <n>th argument, and
if argument recovery is in effect, saves a copy of the <n> arguments in t
he
last argument save area. If an error
occurs that is handled by the outer loop error handler, then the stack
is cleared to the marked level (this removes any stray objects that
were not put there by the user). If the argument recovery system is acti
ve,
For objects that take a stack specified number of arguments, the analogs
to CK<n> and CK<n>NOLASTWD are CKN and CKNNOLASTWD. Both words check
for a real number in level 1, then check if there are that many additiona
l
objects on the stack. The stack is marked at level 2, and only the
real number is restore by LAST ARG.
Page 62
dispatching):
...
CK&DISPATCH1
action2
action3
;
#type1 action1
...
#type2
#typen
Page 63
The word CK&DISPATCH0 does not perform the second pass which
strips tags. This word should only be used where it is
important to find a tagged object. The general behavior of
the HP 48 is to regard tags as being auxiliary to the tagee,
and thus CK&DISPATCH1 should be used in most cases.
Level
Level
Level
Level
Level
1
2
3
4
5
argument
argument
argument
argument
argument
type
type
type
type
type
Argument
---------------Any Object
Real Number
Complex Number
Character String
Array
List
Global Name
Local Name
Secondary
Symbolic
Symbolic Class
Hex String
Graphics Object
Tagged Object
Unit Object
ROM Pointer
Binary Integer
Directory
Extended Real
Extended Complex
Page 64
5F
Linked Array
23
6F
7F
8F
9F
AF
BF
CF
DF
EF
Character
Code Object
Library
Backup
Library Data
External object1
External object2
External object3
External object4
24
25
16
17
26
27
28
29
30
Page 65
14.3 Examples
Built-in commands and other words provide good examples of
the check-and- dispatching scheme. The following is the
definition of the user command STO:
:: CK2&Dispatch
THIRTEEN XEQXSTO
( 2:any object
SIX
:: STRIPTAGSl2 ?STO_HERE ; ( 2:any
SEVEN
:: STRIPTAGSl2 STO ;
( 2:any
NINE
:: STRIPTAGSl2 SYMSTO ;
( 2:any
# 000c8 PICTSTO
( 2:grob
1:tagged object)
1:id )
1:lam )
1:symb )
1:program [PICT]
)
# 009f1
# 008f1
LBSTO
LBSTO
;
Since STO is a command, it starts with CK2&Dispatch, which
verifies that there are two arguments present, saves those
arguments and the command STO for error handling, then
dispatches to one of the action objects listed in the
dispatch table. If the level one object is tagged, STO
dispatches to the word XEQSTO. For a global name (id), STO
executes :: STRIPTAGSl2 ?STO_HERE ;, which is directly
embedded in the STO program. And so forth, down to the last
choice, which is a dispatch to LBSTO when the arguments are
a library in level 2, and a real number in level 1.
The TYPE command provides an example of dispatching at a
point other than the start of a command. TYPE is a command,
but its argument counting and argument type dispatching are
separated so that the latter part can be called by other
system words that don't want to mark the stack:
::
CK1
:: CK&DISPATCH0
real
%0
cmp
%1
str
%2
arry
XEQTYPEARRY
list
%5
id
%6
lam
%7
seco
TYPESEC ( 8, 18, or 19 )
symb
%9
hxs
%10
grob
% 11
TAGGED
% 12
unitob
% 13
rompointer
% 14
THIRTYONE ( # ) % 20
rrp
% 15
# 3F ( %% )
% 21
# 4F ( C%% )
% 22
# 5F ( LNKARRY ) % 23
# 6F ( CHR )
% 24
# 7F ( CODE )
% 25
library
% 16
Page 66
backup
# AF
any
% 17
% 26 ( Library Data )
% 27 ( external )
;
SWAPDROP
;
CK&DISPATCH0 is used here, although CK&DISPATCH1 would work
as well since tagged objects are explicitly listed in the
dispatch table. Notice also that the last typei is "any",
meaning that type 27 is returned for any object type not
previously listed.
The "inner" program (starting after the CK1) is the body of
the system word XEQTYPE.
Page 67
Page 68
BEGIN
<test clause>
WHILE
:: ob1 ... obn ;
REPEAT
Another common indefinite loop is the BEGIN...UNTIL:
BEGIN
<loop clause>
UNTIL
This loop executes at least once, as opposed to the WHILE
loop, which does not execute its loop object if the initial
test is false. The word UNTIL expects a flag (TRUE or
FALSE).
The BEGIN...AGAIN loop has no test:
BEGIN
<loop clause>
AGAIN
Terminating this loop requires an error event, or a direct
manipulation of the return stack.
Page 69
( #finish --> )
Equivalent to #1+ ONE DO; commonly used to execute a lo
op
DO
DROPLOOP *
DUP#0_DO *
DUPINDEX@
#finish times.
( #finish #start --> )
Begins DO loop
( ob --> )
Performs DROP, then LOOP
( # --> # )
Begins # ... #0 DO loop
( ob --> ob ob #index )
Does DUP, then returns value of index in topmost DoLoop
env.
ExitAtLOOP
( --> )
Stores zero in stopping value of topmost DoLoop environ
INDEX@
( --> #index )
Returns index of topmost DoLoop environment
( # --> #' )
Subtracts index value of topmost
ment
INDEX@#-
Page 70
INDEXSTO
ISTOP@
ISTOPSTO
JINDEX@
LOOP
NOT_UNTIL *
ONE_DO *
OVERINDEX@
SWAPINDEX@
SWAPLOOP *
ZEROISTOPSTO
ZERO_DO *
toLEN_DO
e
#number-of-elements+1.
15.2.2 Examples
FIVE ZERO
DO
INDEX@
LOOP
This returns the values:
#00000 #00001 #00002 #00003 #00004
The following sequence displays each of the elements (up to 8) of
a list of strings on a separate display line.
DUPLENCOMP
ONE_DO (DO)
DUP INDEX@ NTHCOMPDROP
INDEX@ DISPN
LOOP
Page 71
INNERCOMP
#1+_ONE_DO (DO)
INDEX@ DISPN
LOOP
This version displays the elements in reverse order relative to the previ
ous
versions.
Page 72
Page 73
Page 74
ERRBEEP
ERRJMP
ERROR@
ERRORCLR
ERROROUT
ERRORSTO
ERRTRAP
( --> )
Does ERRORCLR and ERRJMP
( msg# --> )
Stores a new error number and executes ERRJMP;
also executes AtUserStack
Puts the object ERRJMP on the stack
( --> )
Generates an error beep
( --> )
Invokes error handling subsystem
( --> # )
Returns the current error number
( --> )
Stores zero as the error number
( # --> )
Stores a new error number and does ERRJMP
( # --> )
Stores new error number
( --> )
Skips next object in runstream.
Page 75
FalseFalse
TrueTrue
XOR
( flag1 flag2 --> flag )
If both flag1 and flag2 are either TRUE or FALSE then FALSE, else TRUE.
COERCEFLAG
( TRUE --> %1 )
( FALSE --> %0 )
Converts a system flag to a real number flag.
Page 76
17.1.1 General_Object_Tests
The following words test object type and equality:
EQ
EQUAL
( ob1 ob2 --> flag )
where ob1 and ob2 are not primitive code objects. If objects ob1 and
ob2 are the same then TRUE else FALSE (this word is the system
equivalent of the user RPL command SAME)
2DUPEQ
( ob1 ob2 --> ob1 ob2 flag )
Returns TRUE if ob1 and ob2 have the same physical address.
EQOR
( flag1 ob1 ob2 --> flag2 )
Does EQ, then logical OR.
EQUALOR
( flag1 ob1 ob2 --> flag2 )
Does EQUAL, the logical OR.
EQOVER
( ob1 ob2 ob3 --> ob1 flag ob1 )
Does EQ, then OVER.
EQUALNOT
( ob1 ob2 --> flag )
Returns FALSE if ob1 is equal to ob2.
The following words test an object's type. Words of the
form TYPE...? have a stack diagram ( ob --> flag ); those
of the form DTYPE...? or DUPTYPE...? duplicate the object
first ( ob --> ob flag ).
Test Words
Object type
TYPEARRY?
DTYPEARRY?
DUPTYPEARRY?
array
TYPEBINT?
DUPTYPEBINT?
binary integer
TYPECARRY?
complex array
TYPECHAR?
DUPTYPECHAR?
character
TYPECMP?
DUPTYPECMP?
complex number
TYPECOL?
DTYPECOL?
DUPTYPECOL?
program
Page 77
TYPECSTR?
DTYPECSTR?
DUPTYPECSTR?
string
TYPEEXT?
DUPTYPEEXT?
unit
TYPEGROB?
DUPTYPEGROB?
graphics object
TYPEHSTR?
DUPTYPEHSTR?
hex string
TYPEIDNT?
DUPTYPEIDNT?
TYPELAM?
DUPTYPELAM?
TYPELIST?
DTYPELIST?
DUPTYPELIST?
list
TYPERARRY?
real array
TYPEREAL?
DTYPEREAL?
DUPTYPEREAL?
real number
TYPEROMP?
DUPTYPEROMP?
TYPERRP?
Directory
DUPTYPERRP?
TYPESYMB?
DUPTYPESYMB?
Symbolic
TYPETAGGED?
DUPTYPETAG?
Tagged
17.1.2 Binary_Integer_Comparisons
The following words compare binary integers, returning TRUE
or FALSE. Equality is tested in the sense of EQUAL (not EQ).
Ordering treats all binary integers as unsigned. Some of
these words are also available in combination with case
words (see below).
#=
TRUE if # = #'.
#<>
#0=
( # --> flag )
TRUE if # = 0
Page 78
#0<>
( # --> flag )
TRUE if # <> 0
#<
#>
TRUE if # = #0
TRUE if # = #1
TRUE if # <> #0
TRUE if # = #1
TRUE if # < #7
TRUE if % = %0
ONE#>
TRUE if # > #1
( # --> flag )
TRUE if # is ONE
TRUE if # = #'
17.1.3 Decimal_Number_Tests
The following words compare real, extended real, and complex
numbers, returning TRUE or FALSE.
%<
%<=
%<>
%=
TRUE if % = %'
%>
%>=
%0<
( % --> flag )
TRUE if % < 0
Page 79
%0<>
( % --> flag )
TRUE if % <> 0
%0=
( % --> flag )
TRUE if % = 0
%0>
( % --> flag )
TRUE if % > 0
%0>=
( % --> flag )
TRUE if % >= 0
%%0<=
%%0<>
( %% --> flag )
TRUE if %% <> 0
%%0=
( %% --> flag )
TRUE if %% = 0
%%0>
( %% --> flag )
TRUE if %% > 0
%%0>=
( %% --> flag )
TRUE if %% >= 0
%%>
%%>=
%%<=
C%%0=
C%0=
( C% --> flag )
TRUE if C% = (0,0)
and
Page 80
'R ( --> ob )
If the object pointed to by the top pointer on the return
stack (i.e. the first element in the second body in the
runstream) is an object, then 'R pushes this object onto
the data stack, and advances the pointer to the next
object in the same composite. If the pointer points to an
object pointer whose pointee is not SEMI, then pushes the
pointee onto the data stack, and similarly advances the
return stack pointer. If the pointee is SEMI, then If the
first element in the second body in the runstream is an
object pointer to SEMI, then pushes a null secondary onto
the data stack and does not advance the return stack
pointer. 'R is useful in defining prefix operators. For
example, assume that PREFIXSTO is defined as :: 'R STO ;
Page 81
RDROP ( --> )
Pops the return stack.
IDUP ( --> )
Duplicates the top body in the runstream. (That is, pushes
the RPL variable I onto the return stack).
COLA ( --> )
factpair:
( flag --> )
Page 82
17.3 If/Then/Else
The fundamental RPL if/then/else capability is provided by
If flag is TRUE then drop flag and ob2 and EVALuate ob1,
else drop flag and ob1 and EVALuate ob2. The RPL
expression
' <foo> ' <bar> RPITE
is equivalent to the FORTH expression
IF <foo> ELSE <bar> THEN
RPIT
( flag ob --> ? )
If flag is TRUE then drop flag and EVALuate ob, else just
drop flag and ob. The RPL expression
' <foo> RPIT
is equivalent to the FORTH expression
IF <foo> THEN
However, prefix versions of these words are also available,
and are more commonly used than the postfix forms:
IT
( flag --> )
If flag is TRUE then execute the next object in the
runstream; otherwise skip that object. For example,
DUPTYPEREAL? IT :: %0 %>C% ;
converts a real number to a complex number; does nothing
if the argument is not a real number.
ITE
( flag --> )
Page 83
The converse of IT is
?SKIP ( flag --> )
If flag is TRUE, skip the next object in the runstream;
otherwise, execute it.
There is also an unconditional skip:
SKIP ( --> )
Skips over the next object in the runstream and continues
execution beyond it. The sequence SKIP ; is a NOP.
Combination Words:
Word
#0=ITE
#<ITE
#=ITE
#>ITE
ANDITE
DUP#0=ITE
EQIT
EQITE
DUP#0=IT
SysITE
UserITE
Stack
(
(
(
(
(
(
(
(
(
# --> )
# --> )
# --> )
# --> )
flag flag' --> )
# --> # )
ob1 ob2 --> )
ob ob' --> )
# --> # )
Equivalent
#0= ITE
#0< ITE
#= ITE
#> ITE
AND ITE
DUP #0=
EQ IT
EQ ITE
DUP #0=
( # -->
( # -->
ITE
IT
)
)
Page 84
( # # --> )
( # #' --> # )
Should be named OVER#=casedrop.
%1=case
( % --> )
%0=case
( % --> flag )
ANDNOTcase
ANDcase
case2drop
casedrop
( ob TRUE --> )
( FALSE --> )
DUP#0=case
( # --> # )
( # -->
) # = #0
( ob ob' --> )
Page 85
NOTcase
( flag --> )
NOTcasedrop
( ob FALSE --> )
( TRUE --> )
ORcase
OVER#=case
( # #' --> # )
Case words that either exit or continue with the next object:
caseDoBadKey ( flag --> ) Exit via DoBadKey
caseDrpBadKey ( ob TRUE --> ) Exit via DoBadKey
( FALSE --> )
case2DROP
caseDROP
( ob TRUE --> )
( FALSE --> )
caseFALSE
caseTRUE
casedrpfls
case2drpfls
casedrptru
DUP#0=csDROP (
(
NOTcaseTRUE (
(
#0 --> )
# --> # ) # <> 0.
FALSE --> TRUE )
TRUE --> )
Page 86
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob1
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
ob2
...
...
...
...
...
...
...
...
...
...
...
...
...
-->
-->
-->
-->
ob3
-->
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob3
ob5
ob5
ob5
ob5
ob5
ob6
ob6
ob6
ob7
ob7
ob7
ob8
ob8
)
#0 #0 )
FALSE )
ob1 ob2
--> ob2
ob1 ob2
ob4 -->
ob4 -->
--> )
--> ob1
--> ob1
--> ob1
--> ob1
--> ob3
ob4 -->
ob4 -->
ob4 -->
ob4 -->
ob4 -->
ob4 -->
ob4 -->
ob4 -->
ob4 -->
--> )
--> ob1
--> ob2
--> ob2
--> ob5
--> )
--> ob1
--> ob2
--> )
--> ob1
--> ob2
--> ob1
--> ob2
ob1
ob3
ob2
ob1
ob3
ob2
ob2
ob1
ob2
ob4
)
ob3 ob1 )
)
ob3 ob4 ob1 ob2 )
ob1 ob2 )
ob2
ob2
ob2
ob2
ob1
)
ob1
ob1
ob1
ob2
ob4
ob4
ob4
ob4
ob3
ob3
ob3
ob1
ob2
ob1
ob1
ob1
ob3
)
)
ob2 )
ob3 )
)
...
ob2
ob2
ob3
ob1
)
ob1
ob3
ob4
ob3
ob3
ob4
ob2
ob1
ob4
ob1
ob1
ob3
...
...
...
ob1
ob5
ob5
ob5
...
ob1 )
ob1 )
)
ob4 )
ob7
ob7
ob8
ob8
)
ob1 ob4 )
ob4 )
)
)
ob1
ob1
ob1
ob1
)
)
)
)
8UNROLL
DEPTH
DROP
DROPDUP
DROPFALSE
DROPNDROP
DROPONE
DROPOVER
DROPRDROP
DROPROT
DROPSWAP
DROPSWAPDROP
DROPTRUE
DROPZERO
DUP
DUP#1+PICK
DUP3PICK
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
ob7 )
objects
)
1 return stk level
ob1 )
Page 87
DUP4UNROLL
DUPDUP
DUPONE
DUPPICK
DUPROLL
DUPROT
DUPTWO
DUPUNROT
DUPZERO
N+1DROP
NDROP
NDUP
NDUPN
ONEFALSE
ONESWAP
OVER
OVER5PICK
OVERDUP
OVERSWAP
OVERUNROT
PICK
ROLL
ROLLDROP
ROLLSWAP
ROT
ROT2DROP
ROT2DUP
ROTDROP
ROTDROPSWAP
ROTDUP
ROTOVER
ROTROT2DROP
ROTSWAP
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
SWAP
SWAP2DUP
SWAP3PICK
SWAP4PICK
SWAPDROP
SWAPDROPDUP
SWAPDROPSWAP
SWAPDROPTRUE
SWAPDUP
SWAPONE
SWAPOVER
SWAPROT
SWAPTRUE
UNROLL
UNROT
UNROT2DROP
UNROTDROP
UNROTDUP
UNROTOVER
UNROTSWAP
ZEROOVER
reversym
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
Page 88
( ob --> ob' )
If ob is in TEMPOB, is not embedded
in a composite object, and is not
referenced, then does nothing. Otherwise
copies ob to TEMPOB and returns the copy.
INTEMNOTREF?
( ob --> ob flag )
If the input object is in TEMPOB area,
is not embedded in a composite object,
and is not referenced, returns ob and
TRUE, otherwise returns ob and FALSE.
TOTEMPOB
( ob --> ob' )
Copies ob into TEMPOB and returns pointer
to the new ob.
Page 89
(
(
(
(
id --> ob TRUE )
id --> FALSE )
lam --> ob TRUE )
lam --> FALSE )
In the lam case, @ attempts to match lam to the temporary
identifier object part of a binding in the Temporary
Environment area (searching from the first temporary
environment to the last). If successful, then the object
bound to lam is returned along with a TRUE flag; else, a
FALSE flag is returned. In the id case, @ attempts to
match id to the name part of a global variable, starting
in the current directory, and working up through parent
directories if necessary. If the resolution is
unsuccessful, then a FALSE flag is returned. Otherwise,
the object part of the resolved variable is returned with
a TRUE flag.
Page 90
Page 91
UPDIR ( --> )
Switches context to the parent of the current directory.
XEQORDER ( { id1 id2 ... } --> )
ORDERs current directory.
XEQPGDIR ( id --> )
Purges a directory while respecting reference/garbage collection conven
tions.
19.3 The Hidden Directory
There is a hidden, nullnamed directory at the beginning of
the home directory, that contains the user key definitions
and alarm information. Application programs may use this
directory as well. However, remember that the user has no
way to detect or remove variables from this directory, so an
application should either remove such variables before
finishing, or to provide a command that lets the user remove
specific variables from the hidden directory.
These words provide store, recall and purge capabilities for
the hidden directory:
PuHiddenVar ( id --> ) Purges the hidden variable named id.
RclHiddenVar ( id --> ob TRUE )
( id --> FALSE )
Recalls (@) a hidden variable.
StoHiddenVar
( ob id --> )
Stores ob in hidden variable
Page 92
GARBAGE ( --> )
Forces garbage collection.
MEM( --> # )
Returns the amount of free memory (a garbage collection is not forced)
OCRC ( ob --> #nibbles checksum(hxs) Returns size of object in nibbles a
nd
a hex string checksum
getnibs ( hxsDATA hxsADDR --> hxsDATA' ) Internal RPL version of PEEK
putnibs ( hxsDATA hxsADDR --> ) Internal RPL version of POKE
Page 93
Grob
Location
---------------- ---------
+--------------+
HARDBUFF2 -> | Menu labels | (Low Mem)
+--------------+
ABUFF
-> | text grob |
+--------------+
GBUFF
-> | graph grob | (Hi Mem)
+--------------+
The text grob and graph grob may be enlarged, and may be
scrolled.
The word TOADISP switches makes the text grob visible;
TOGDISP switches the LCD to the graph grob.
The following words are useful for returning display grobs
to the stack:
ABUFF ( --> textgrob )
GBUFF ( --> graphgrob )
HARDBUFF ( --> HBgrob )
Returns whichever of the text or graph grob is currently displayed.
HARDBUFF2 ( --> menugrob )
HBUFF_X_Y( --> HBgrob #x1 #y1 )
A ram pointer named VDISP indicates which grob is currently
shown in the display. VDISP may point to either the text
grob or the graph grob. VDISP is not directly accessible the word HARDBUFF returns the current display grob to the
stack (see below). Remember that ABUFF and GBUFF just
return pointers, so if the grob is being recalled for
modification and later return to the user, TOTEMPOB should
be used to create a unique copy in temporary memory.
Page 94
Page 95
Freeze
Freeze
Freeze
Freeze
Freeze
Redraw
display area 1
display area 2a
display area 2b
display area 3
all display areas
the entire lcd when program ends
Page 96
SetRightAnn
Page 97
20.6.1 Window_Coordinates
(
(
(
(
Page 98
( --> grob )
Equivalent words that save the top eight rows or rows 8-15
are not in the HP 48, but can be written as follows:
:: TOP8 SUBGROB ; ( --> grob ) ( *Saves the top 8 rows* )
:: TOP8-15 SUBGROB ; ( --> grob ) ( *Saves the top 8-15 rows* )
20.7 Displaying Text
There are three fonts available in the HP 48, distinguished
by size. The smallest font is variable width; the medium
and large fonts are fixed width.
The words described below display text using the medium and
large fonts in specific areas. Use of the small fonts, and
other placement options for the medium and large fonts must
be done in graphics, which is described later.
20.7.1 Standard_Text_Display_Areas
When the text grob is the current display AND has not been
scrolled, the following words may be used to display text in
the medium (5x7) font. Long strings are truncated to 22
characters with a trailing ellipsis (...), and strings
shorter than 22 characters are blank filled.
DISPROW1
DISPROW2
DISPROW3
DISPROW4
DISPROW5
DISPROW6
DISPROW7
DISPN
DISP5x7
(
(
(
(
(
(
(
(
(
$
$
$
$
$
$
$
$
$
--> )
--> )
--> )
--> )
--> )
--> )
--> )
#row --> )
#start #max )
(0,0)
(130,0)
+--------------------+
|
|
+--------------------+
(0,7)
(130,7)
(0,8)
(130,8)
+--------------------+
|
|
+--------------------+
(0,15)
(130,15)
(etc.)
Page 99
(
(
(
(
(
$
$
$
$
$
--> )
--> )
--> )
--> )
#row --> )
(0,17)
(130,0)
+--------------------+
|
|
+--------------------+
(0,26)
(130,26)
(0,27)
(130,27)
+--------------------+
|
|
+--------------------+
(0,36)
(130,36)
(etc.)
Page 100
20.7.2 Temporary_Messages
Sometimes it is convenient to display a warning, then return
the display to its previous state. There are several
techniques and tools available for this. The easiest way to
do this is with the word FlashWarning. The code for
FlashWarning looks like this:
FlashWarning
::
ERRBEEP
Save16
SWAP DISPSTATUS2
VERYVERYSLOW
( $ --> )
(
(
(
(
Restore16
;
Variations on FlashWarning can be constructed using words
like TOP16 or a version suggested above that saves fewer
rows. The example below saves the top 8 rows and displays a
one line message for about .6 second:
::
TOP8 SUBGROB
SWAP DISPROW1*
VERYSLOW VERYSLOW
Restore8
(
(
(
(
;
NOTE: It is important to use DISPROW1* and DISPROW2* instead
of DISPROW1 and DISPROW2 if there is any chance that
HARDBUFF has been scrolled. There are no corresponding
words for other display lines.
Page 101
20.8.1 Warnings
Here are two warnings:
1. The term "bang-type operation" refers to an operation
performed directly upon an object without making a
copy. The naming convention for words which perform
this kind of operation often have an exclamation point
to denote a "bang" operation, such as GROB! or
GROB!ZERO.
You must remember two things when using "bang"
operations:
+ Since the object itself is modified, any pointers
on the stack that refer to that object will now
point to a changed object. The word CKREF may be
used to ensure that an object is unique.
+ These operations have no error checking, so
improper or out-of-range parameters may corrupt
memory beyond recovery.
2. In practice, it is best to use the word XYGROBDISP to
place a grob into the display grob. The word
XYGROBDISP is conservative in nature - if the graphic
to be placed in HARDBUFF would exceed the boundaries
of HARDBUFF, the HARDBUFF grob is enlarged to
accomodate the new grob.
Page 102
20.8.2 Graphics_Tools
The following words create or modify graphics objects:
$>BIGGROB
( $ --> grob ) ( 5x9 font )
$>GROB
( $ --> grob ) ( 5x7 font )
$>grob
( $ --> grob ) ( 3x7 font )
DOLCD>
( --> 64x131grob )
GROB!
( grob1 grob2 #col #row --> )
Stores grob1 into grob2. This is a
bang-type word with no error checks!
GROB!ZERO
( grob #x1 #y1 #x2 #y2 --> grob' )
Zeros out a rectangular section of a
grob. NOTE: Bang-type operation.
GROB!ZERODRP
( grob #x1 #y1 #x2 #y2 --> )
Zeros out a rectangular section of a
grob. NOTE: Bang-type operation!
GROB>GDISP
( grob --> )
Stores graph grob with new grob.
HARDBUFF
( --> HBgrob (the current display grob) )
HEIGHTENGROB
( grob #rows --> )
Adds #rows to grob, unless grob is null.
NOTE: Assumes text grob or graph grob!
INVGROB
( grob --> grob' )
Invert grob data bits - bang-type.
LINEOFF
( #x1 #y1 #x2 #y2 --> )
Clears pixels in a line in text grob
Note: #x2 must be > #x1 (use ORDERXY#)
LINEOFF3
( #x1 #y1 #x2 #y2 --> )
Clears pixels in a line in graph grob
Note: #x2 must be > #x1 (use ORDERXY#)
LINEON
( #x1 #y1 #x2 #y2 --> )
Sets pixels in a line in text grob
Note: #x2 must be > #x1 (use ORDERXY#)
LINEON3
( #x1 #y1 #x2 #y2 --> )
Sets pixels in a line in graph grob
Note: #x2 must be > #x1 (use ORDERXY#)
MAKEGROB
( #height #width --> grob )
ORDERXY#
( #x1 #y1 #x2 #y2 --> #x1 #y1 #x2 #y2 )
Orders two points for line drawing
PIXOFF
( #x #y --> )
Clears a pixel in the text grob
PIXOFF3
( #x #y --> )
Clears a pixel in the graph grob
PIXON
( #x #y --> )
Sets a pixel in the text grob
PIXON?
( #x #y --> flag )
Returns TRUE if text grob pixel is set
PIXON?3
( #x #y --> flag )
Returns TRUE if graph grob pixel is set
PIXON3
( #x #y --> )
Sets a pixel in the graph grob
SUBGROB
( grob #x1 #y1 #x2 #y2 --> subgrob )
Symb>HBuff
( symb --> )
Displays symb in HARDBUFF in EquationWriter form. May enlarge HARDBUFF, so
do RECLAIMDISP afterwards.
Page 103
TOGLINE
TOGLINE3
( #x1 #y1
Toggles
( #x1 #y1
Toggles
)
line in text grob
)
line in graph grob
20.8.4 Built-in_Grobs
The following words refer to built-in grobs:
BigCursor
CROSSGROB
CURSOR1
CURSOR2
MARKGROB
MediumCursor
SmallCursor
5x9
5x5
5x9
5x9
5x5
5x7
3x5
Page 104
20.8.5 Menu_Display_Utilities
Menu labels are grobs which are 8 rows high and 21 pixels
wide. The columns for menu key labels in HARDBUFF2 are:
ZERO
TWENTYTWO
# 0002C
# 00042
# 00058
# 0006E
Softkey
Softkey
Softkey
Softkey
Softkey
Softkey
1
2
3
4
5
6
Seco>Menu
Str>Menu
(
(
(
(
$
$
$
$
-->
-->
-->
-->
grob
grob
grob
grob
)
)
)
)
(
(
(
(
*Scroll
*Scroll
*Scroll
*Scroll
JUMPBOT
JUMPLEFT
JUMPRIGHT
JUMPTOP
(
(
(
(
*Move
*Move
*Move
*Move
window
window
window
window
to
to
to
to
Page 105
*
HARDBUFF
75 50 "SCROLLING"
( HBgrob 75 150 "SCROLLING" )
150 CENTER$3x5
( HBgrob )
75 100 "EXAMPLE"
( HBgrob 75 100 "EXAMPLE" )
150 CENTER$3x5
( HBgrob )
DROPFALSE
( FALSE )
{ LAM Exit } BIND
( *Bind POL exit flag* )
' NOP
( *No display action* )
' ::
( *Hard key handler* )
kpNoShift #=casedrop
::
kcUpArrow
?CaseKeyDef
:: TakeOver SCROLLUP ;
Page 106
kcLeftArrow ?CaseKeyDef
:: TakeOver SCROLLLEFT ;
kcDownArrow ?CaseKeyDef
:: TakeOver SCROLLDOWN ;
kcRightArrow ?CaseKeyDef
:: TakeOver SCROLLRIGHT ;
kcOn
?CaseKeyDef
:: TakeOver
TRUE ' LAM Exit STO ;
kcRightShift #=casedrpfls
DROP 'DoBadKeyT
;
kpRightShift #=casedrop
::
kcUpArrow
?CaseKeyDef
:: TakeOver
kcLeftArrow ?CaseKeyDef
:: TakeOver
kcDownArrow ?CaseKeyDef
:: TakeOver
kcRightArrow ?CaseKeyDef
:: TakeOver
kcRightShift #=casedrpfls
DROP 'DoBadKeyT
;
2DROP 'DoBadKeyT
;
TrueTrue
NULL{}
ONEFALSE
' LAM Exit
' ERRJMP
ParOuterLoop
TURNMENUON
RECLAIMDISP
;
(
(
(
(
(
(
(
(
JUMPTOP ;
JUMPLEFT ;
JUMPBOT ;
JUMPRIGHT ;
Page 107
SCROLL
SCROLL.LR
XR
ENTRIES.O
SCROLL.O
Page 108
kpNoShift
kpLeftShift
kpRightShift
kpANoShift
kpALeftShift
kpARightShft
ONE
TWO
THREE
FOUR
FIVE
SIX
Page 109
ONE
TWO
THREE
FOUR
FIVE
SIX
SEVEN
EIGHT
NINE
FORTYNINE
FLUSHKEYS
GETTOUCH
KEYINBUFFER?
ATTN?
ATTNFLGCLR
WaitForKey
Page 110
21.3 InputLine
The word InputLine is the core of the user word INPUT as
well as the prompt for equation names (NEW). InputLine does
the following:
+ Displays the prompt in display area 2a,
+ Sets the keyboard entry modes,
+ Initializes the edit line,
Page 111
#1
#2
21.3.1 InputLine_Example
The example call to InputLine shown below prompts the user
for a variable name. If the user enters a valid name, the
name and TRUE are returned, otherwise FALSE is returned.
( --> Ob TRUE | FALSE )
::
"Enter name:" (
NULL$
(
ONEONE
(
ONEONE
(
NULL{}
(
ONE
(
FALSE
(
ONE
(
InputLine
(
NOTcaseFALSE (
SWAP NULL$? (
casedrop FALSE
DUPTYPEIDNT? (
caseTRUE
(
DROPFALSE
(
*Prompt string* )
*No default name* )
*Initial edit line & cursor pos* )
*Insert mode & prog/immed. entry* )
*No edit menu* )
*Menu row* )
*Attn clears edit line* )
*Return edit line and parsed ob* )
($editline ob TRUE) | (FALSE) )
*Exit if Attn pressed* )
*Exit if blank edit line* )
*Check if ob is id* )
*Yes, exit true* )
*No, drop ob and FALSE* )
Page 112
Page 113
21.4.1 The_Parameterized_Outer_Loop_Utilities
The parameterized outer loop word "ParOuterLoop" consists
entirely of calls (with proper error handling) to its four
RPL utility words, in order:
POLSaveUI Saves the current user interface in a temporary
environment. Takes no arguments and returns no
results.
POLSetUI Sets the current user interface according to
the same parameters required by "ParOuterLoop".
Returns no results.
POLKeyUI Displays, reads and evaluates keys, handles
errors, and exits according to the user
interface specified by "POLSetUI". Takes no
arguments and returns no results.
POLRestoreUI Restores the user interface saved by
"POLSaveUI" and abandons the temporary
environment. Takes no arguments and returns no
results.
(In addition to the four utilities above. utility
"POLResUI&Err" is used to protect the saved user interface
in the event of an error that's not handled within the
parameterized outer loop. Refer to "Parameterized Outer
Loop Operation" and "Handling Errors with the Utilities",
below.)
These utilities can be used by applications that require
greater control over the user interface. For example:
+ For optimum performance an application can create a
temporary environment with null-named temporary
variables after calling "POLSaveUI", then access the
null-named variables "within" "POLKeyUI", since only
"POLSaveUI" creates a parameterized outer loop
temporary environment and only "POLRestoreUI" accesses
the same environment.
+ To avoid unnecessary and time-consuming overhead, an
application that uses multiple consecutive (not nested)
parameterized outer loops can call "POLSaveUI" at the
start of the application, then call "POLSetUI" and
"POLKeyUI" multiple times throughout the application,
then finally call "POLRestoreUI" at the end of the
application.
Page 114
21.4.2 Overview_of_the_Parameterized_Outer_Loop
The parameterized outer loop operates as outlined below.
("POLSaveUI")
Save the system or current application's
user interface
If error in
("POLSetUI")
Set the new application's user interface
("POLKeyUI")
While "ExitCond" evaluates to FALSE {
Evaluate "AppDisplay"
If error in
Read and evaluate a key
Then
Evaluate "AppError"
}
Then
Restore the saved user interface and
ERRJMP
("POLRestoreUI")
Restore the saved user interface
The parameterized outer loop creates one temporary
environment when it saves the current user interface, and it
abandons this environment when it restores a saved user
interface. This means that words that operate on the
topmost temporary environment, such as "1GETLAM", should NOT
be used "within" the parameterized outer loop (e.g., in a
key definition or the application display update object)
UNLESS the desired temporary environment is created AFTER
calling "POLSaveUI" and abandoned before calling
"POLRestoreUI". For temporary environments created before
calling the parameterized outer loop, applications should
set up and operate on NAMED temporary variables.
Page 115
21.4.3 Handling_Errors_with_the_Utilities
To insure that it can properly restore a saved user
interface if an error occurs within an application, the
parameterized outer loop protects the saved user interface
by setting an error trap immediately after its call to
"POLSaveUI", as shown below:
::
POLSaveUI
ERRSET
::
POLSetUI
POLKeyUI
;
ERRTRAP
POLResUI&Err
POLRestoreUI
;
The purpose of supported utility "POLResUI&Err" is to
restore the user interface saved by "POLSaveUI" and then to
error.
Any applications that use the parameterized outer loop
utilities instead of "ParOuterLoop" are REQUIRED to include
this same level of error handling protection of the saved
user interface.
21.4.4 The_Display
There is no default display in the parameterized outer loop;
the application is responsible for setting up the initial
display and updating it.
There are two ways that an application can update the
display: with outer loop parameter "AppDisplay" or with key
assignments. For example, if the user presses the right-
Page 116
21.4.5 Error_Handling
The error-handling outer loop parameter "AppError" is
responsible for processing any errors generated during key
evaluation within the parameterized outer loop. If an error
occurs, "AppError" is evaluated. "AppError" should
determine the specific error and act accordingly. If an
application can not handle any errors, then "AppError"
should be specified as "ERRJMP".
21.4.6 Hard_Key_Assignments
Any HP 48 key, in any of the six planes (unshifted, leftshifted, right-shifted, alpha-unshifted, alpha-left-shifted,
and alpha-right-shifted) can be assigned for the duration of
the parameterized outer loop. The outer loop parameter
"AppKeys" specifies the keys to assign and their new
assignments.
If a key is not assigned by an application, and outer loop
parameter "NonAppKeyOK?" is TRUE, then standard or default
key processing occurs, according to outer loop parameter
"DoStdKeys?". For example, if user keys mode is on and the
key has a user key assignment, then the user key is
processed if "DoStdKeys?" is FALSE, or the standard key is
processed if "DoStdKeys?" is TRUE. If "NonAppKeyOK?" is
FALSE, then all non-application keys issue a canceled key
warning beep and do nothing else.
In general, NonAppKeyOK? should be FALSE to maintain total
control.
Page 117
Page 118
in any of three planes (unshifted, left-shifted, and rightshifted), to be initialized when the parameterized outer
loop is started. The outer loop parameter "AppMenu"
specifies the initialization object (a list or secondary)
for the application's menu, or FALSE, indicating that the
current menu is to be left intact. When the parameterized
outer loop is exited, the previous menu is restored
automatically.
If "AppMenu" is a null list, then a set of six null menu key
assignments are made. If "AppMenu" is FALSE, then the menu
present when the parameterized outer loop is called is
maintained.
NOTE: hard key assignments have priority over menu key
assignments. This means that the hard key handler must
include the following line if menu keys are to be processed:
DUP#<7 casedrpfls
The parameter AppMenu takes the following form:
{
Menu Key 1 Definition
Menu Key 2 Definition
...
Menu Key n Definition
}
Where each menu key definition takes one of three
following forms:
Page 119
NullMenuKey
{ LabelObj :: TakeOver (Action) ; }
{ LabelObj {
:: TakeOver (Primary Action) ;
:: TakeOver (LeftShifted Action) ;
}
{ LabelObj {
:: TakeOver (Primary Action) ;
:: TakeOver (LfShifted Action) ;
:: TakeOver (RtShifted Action) ;
}
}
A LabelObj may be any object, but is usually a string or an
8x21 grob. See the example below for an illustration of
21.4.8 Preventing_Suspended_Environments
An application may need to allow arbitrary commands and user
objects to be evaluated, but don't want the current
environment to be suspended by the "HALT" or "PROMPT"
commands. If the outer loop parameter "SuspendOK?" is
FALSE, then any command that would suspend the environment
generates a "HALT not Allowed" error, allowing "AppError" to
handle it. If "SuspendOK?" is TRUE, then the application
must be prepared to handle the consequences. The dangers
here are many and severe.
For all foreseeable applications, "SuspendOK?" should be
FALSE.
21.4.9 Specifying_an_Exit_Condition
The outer loop parameter "ExitCond" is an object that
evaluates to TRUE when the outer loop is to exited, or FALSE
otherwise. "ExitCond" is evaluated before each key
evaluation.
Page 120
21.4.10 ParOuterLoop_Example
*--------------------------------------------------------*
* Include the header file KEYDEFS.H, which defines words
* like kcUpArrow at physical key numbers.
*
INCLUDE KEYDEFS.H
*
* Include the eight characters needed for binary download
*
ASSEMBLE
NIBASC /HPHP48-D/
RPL
*
* Begin the secondary
*
::
RECLAIMDISP
( *Claim the alpha display* )
ClrDA1IsStat
( *Temporarily disable clock* )
*
( *Try removing ClrDA1IsStat* )
ZEROZERO
( #0 #0 )
150 150 MAKEGROB
( #0 #0 150x150grob )
XYGROBDISP
( )
*
* Draw diagonal lines. Remember that LINEON requires
* requires #x2>#x1!
*
ZEROZERO
( #x1 #y1 )
149 149
( #x1 #y1 #x2 #y2 )
LINEON
( *Draw line* )
ZERO 149
( #x1 #y1 )
149 ZERO
( #x1 #y1 #x2 #y2 )
LINEON
( *Draw line* )
*
* Place text
*
HARDBUFF
75 50 "SCROLLING"
( HBgrob 75 150 "SCROLLING" )
150 CENTER$3x5
( HBgrob )
75 100 "EXAMPLE"
( HBgrob 75 100 "EXAMPLE" )
150 CENTER$3x5
( HBgrob )
DROPFALSE
( FALSE )
{ LAM Exit } BIND
( *Bind POL exit flag* )
' DispMenu.1
( *Display Action shows menu* )
' ::
( *Hard key handler* )
kpNoShift #=casedrop
::
DUP#<7 casedrpfls ( *Enable softkeys* )
kcUpArrow
?CaseKeyDef
:: TakeOver SCROLLUP ;
kcLeftArrow ?CaseKeyDef
:: TakeOver SCROLLLEFT ;
kcDownArrow ?CaseKeyDef
:: TakeOver SCROLLDOWN ;
Page 121
kcRightArrow ?CaseKeyDef
:: TakeOver SCROLLRIGHT ;
kcOn
?CaseKeyDef
:: TakeOver
TRUE ' LAM Exit STO ;
kcRightShift #=casedrpfls
DROP 'DoBadKeyT
;
2DROP 'DoBadKeyT
;
TrueTrue
( *Key control flags* )
{
{ "TOP" :: TakeOver JUMPTOP ; }
{ "BOT" :: TakeOver JUMPBOT ; }
{ "LEFT" :: TakeOver JUMPLEFT ; }
{ "RIGHT" :: TakeOver JUMPRIGHT ; }
NullMenuKey
{ "QUIT" :: TakeOver TRUE ' LAM Exit STO ; }
}
ONEFALSE
( *1st row, no suspend* )
' LAM Exit
( *App exit condition* )
' ERRJMP
( *Error handler* )
ParOuterLoop
( *Run the ParOuterLoop* )
RECLAIMDISP
( *Resize and clear display* )
SetDAsBAD
( *Redraw display* )
;
The above code, if stored in a file SCRSFKY.S, can be
compiled as follows:
RPLCOMPILE SCRSFKY.S
SASM SCRSFKY.A
SLOAD -H SCRSFKY.M
This example also assumes that the file KEYDEFS.H is either
in the same directory or the source file has been modified
to reflect the location of KEYDEFS.H. The loader control
file SCRSFKY.M looks like this:
OU
LL
SU
SE
RE
SCRSFKY
SCRSFKY.LR
XR
ENTRIES.O
SCRSFKY.O
Page 122
ClrSysFlag
ClrUserFlag
DATE
DOBEEP
DOBIN
DODEC
DOENG
DOFIX
DOHEX
DOOCT
DOSCI
DOSTD
DPRADIX?
SETDEG
SETGRAD
SETRAD
SLOW
TOD
TestSysFlag
TestUserFlag
VERYSLOW
VERYVERYSLOW
( --> flag )
Returns TRUE if an alarm is due
( --> )
Declares user ownership of all objects
on the stack.
( --> hxs )
Returns 13 nibble hex string reflecting
the number of ticks since 01/01/0000.
There are 8192 ticks per second.
( # --> )
Clears system flag from #1 to #64
( # --> )
Clears user flag from #1 to #64
( --> %date )
Returns real number date
( %freq %duration --> )
BEEP command
( --> )
Set base mode to BINary
( --> )
Set base mode to DECimal
( # --> )
Set ENG display with # (0-11) digits
( # --> )
Set FIX display with # (0-11) digits
( --> )
Set base mode to HEXadecimal
( --> )
Set base mode to OCTal
( # --> )
Set SCI display with # (0-11) digits
( --> )
Set STD display mode
( --> flag )
Returns TRUE if current radix is .
Returns FALSE if current radix is ,
( --> )
Set DEGREES angle mode
( --> )
Set GRADS angle mode
( --> )
Set RADIANS angle mode
( --> )
15msec delay
( --> %time )
Returns time of day in h.ms form
( # --> flag )
Returns TRUE if system flag # is set
( # --> flag )
Returns TRUE if user flag # is set
( --> )
300 msec delay
( --> )
Page 123
WORDSIZE
dostws
dowait
3 sec delay
( --> # )
Returns binary wordsize
( # --> )
Stores binary wordsize
( %seconds --> )
Waits for %seconds in light sleep
Page 124