Introductory HP48 - Main | Networked Software Systems...
Transcript of Introductory HP48 - Main | Networked Software Systems...
Introductory HP48
The HP48 simulator is a model of a powerful scientific calculator. It enables,
beyond others, these features:
Basic arithmetic: .
Trigonometric functions: .
The full set of hyperbolic functions:
.
Logarithmic and power functions: .
Various data types:
o Double
o Integer (limited usage)
o Complex (limited set of operations)
o String
o Algebraic expression
o Program
o List (not implemented)
o Vector (not implemented)
Advanced stack architecture.
Working with algebraic expressions.
Possibility to define and store objects of all the types.
Programming features:
o Block structure
o If structures
o Loop structures
1
Basic Operation
The display is divided into three or four sections, as shown below:
The status area
The status area displays the annunciators:
Right shift is active Left shift is active
α Alpha keyboard is active (you can type letters and other
characters)
RAD Radians mode is active
GRA Grads mode is active (400 grads = 2π radians)
DEG Degrees mode is active
The stack
The stack is a series of storage locations for numbers and other objects. The
locations are called levels 1, 2, 3 etc. The number of levels changes according
to how many objects are stored on the stack: from none to hundreds. As you
use data from the stack, the number of levels decreases as the data moves down
to lower levels. As you enter new numbers or other objects, the stack grows to
accommodate them: the new data moves into level 1, while older data is
“bumped” to higher levels.
The stack shows level 1 and up to 3 additional levels. Any other levels are
stored in memory, but aren’t displayed.
The command line
The command line appears, whenever you start keying in or editing objects.
The stack lines move up to make room. If there is not enough space in the line
for the text you enter, the ellipsis sign (…) appears, telling you “there is more
information in that direction”.
2
Menu labels
Menu labels across the bottom of the display show the operations associated
with six keys across the top of the keyboard. In the Simulator these associations
are hard-coded.
3
Organization of the Keyboard
The HP48 keyboard has 6 layers of functions:
Primary keyboard.
Represented by the labels on the key faces, for example
ENTER , + , 8 , +/– , ▲ , ON .
Left-shift keyboard.
Represented by labels printed in purple, activated by key. To execute
the arcsine function, for example, press followed by SIN key.
Right-shift keyboard.
Activated by pressing key. The labels are green. To execute x-th root
of y, for example, press key, followed by the key.
Alpha keyboard
Activated by pressing the α key. Alpha keys are labeled in white and
are located to the right to the primary keys. Alpha keys are all capital
letters. To generate N, for example, press α STO .
Note, in Alpha mode the number pad still generates numbers. α α
locks the mode, then α releases to primary keyboard.
Alpha left-shift keyboard.
Activated by α followed by key. It generates all the lowercase
letters and some special characters.
Alpha right-shift keyboard.
Activated by α followed by key. It generates Greek letters and some
special characters.
Note, that α, and annuciators show the current keyboard layer.
Cursor keys
The cursor keys’ behaviour depends on whether the cursor is currently being
displayed.
4
Behaviour while cursor is being displayed
◄ Moves cursor to the left.
► Moves cursor to the right.
▲ ▼ Navigates in the stack.
Deletes the previous character.
DEL Deletes current character (inactive).
Behaviour while cursor is not being displayed
◄ Starts editing.
► Inactive.
▲ Slides the stack window up.
▼ Slides the stack window down; if the lower line is stack level 1,
it is recalled for editing.
( DROP ) Drops the object on level 1 from the stack.
DEL ( CLEAR ) Clears the stack.
CANCEL key
The ON key has also CANCEL function.
To delete the command line, press CANCEL .
To cancel a running program, press CANCEL .
5
Entering and Editing Objects
The basic items of information in the Simulator are called objects. For
example, real number, an equation and a program are each an object. An object
occupies a single level on the stack and may be stored in a variable.
The Simulator works with many types of objects, including real and complex
numbers, algebraic expressions, programs, text strings and more. Most of
operations apply only to particular type of objects, while others work on all
types.
Keying in numbers
Use 1 , …, 9 , . , +/– keys.
In order to enter the number as a mantissa and exponent, press EEX
key (it will type E for exponent).
Press CANCEL to delete the command line.
Keying in characters
To key in a single character, press α followed by a key with the
desired character.
To key in several characters, press α α , key in characters and press
α again.
Use and to enter low-case, Greek letters and special symbols.
The Simulator does not support HP48’s low-case lock and insert modes
and chars facility.
Keying in objects with delimiters
The real numbers represent one type of objects. Most other types of objects
require special delimiters to indicate which type of object they are. Here is a
list of different types of objects and their corresponding delimiters.
6
Object Delimiters Keys Examples
Real numbers none 14.75
Complex number ( ) ( ) (8.25, –12.1)
String " " " " "Hello, EE!"
Program « » « » «DUP NEG »
Algebraic ' ' ' ' SIN(5X–0.1π) '
Built-in command none SIN
Variable none X
Variable name ' ' ' 'X'
Definition ' ' ' 'DSIN(X) = SIN(X)SIN(X)'
Note: the Simulator does not support some of HP48’s built-in types, like
vectors, arrays, lists, units.
Press the delimiter key. It will type both delimiters. Use keys to enter
characters; use ► to move past the closing delimiter.
More about the command line
A few objects may be entered in the same command line if they are
separated by space ( SPC ). For example, you can key in
1 2 SPC 3 4 to enter two numbers — 12 and 34.
When you type a character while there are several characters to the right,
the character is inserted, and any trailing part of the string moves to the
right.
If algebraic expression or a program is being entered, the editor enters
Program Entry Mode. In this mode most of keys don’t cause editor to
finish the entering and proceed the entered object. For example, in
Normal Entry Mode, SIN causes the Simulator to take an object from
the stack level 1, calculate its sine and put the result on the stack level 1.
7
In Program Entry Mode, pressing SIN types SIN at current cursor
position.
Differences between the Simulator and HP48
Picking an object from stack, EDIT submenu, commands history,
Algebraic Entry Mode, Program/Algebraic Entry Mode,
ENTRY command — all are unsupported.
8
Stack
The stack is a series of storage locations for numbers and other objects. In
general, you will use the Simulator by entering objects onto stack and then
executing commands that operates on the data from stack.
Using the stack for calculations
The fundamental concepts of stack operations are these:
A command that requires arguments (objects the command act upon)
takes the arguments from the stack. Therefore, the arguments must be
present before you execute the command.
The arguments for command are normally removed from the stack when
the command is executed.
Results are normally returned to the stack, so you can see them, edit or
use them in other operations.
Making calculations
When you execute a command, any arguments in the command line are
automatically put onto stack before the command is executed. This means that
you don’t always have to press ENTER key to put the arguments on the stack.
Nevertheless you should think of the arguments as already being on the stack.
To use an one-argument command:
1. Enter the argument into the level 1.
2. Execute the command.
For example, to execute key in:
3 . 7 ENTER LN 1/X or 3 . 7 LN 1/X .
To use a two-argument command:
1. Enter the first argument and then the second argument. The first
argument should be in level 2, and the second in level 1 (or in the
command line).
9
2. Execute the command.
For example, to calculate ,
key in: 8 ENTER 5 ENTER –
or: 8 ENTER 5 –
or: 8 SPC 5 ENTER –
or: 8 SPC 5 –
Another example: calculate
key in 1 0 2 4 SPC 5 .
Manipulating the stack
To swap the objects in levels 1 and 2, press SWAP (or key in the
command SWAP). This command is important and useful with
commands where the order of the arguments is important like /, –,
POW.
To duplicate the object in level 1, press ENTER key (when no
command line is present). The DUP command clones the object from
level 1 and bumps the rest of stack up one level.
To delete the object in level 1, press DROP (or when no
command line is present). All the remaining objects on the stack drop
down one level.
To clear the entire stack press CLEAR (or DEL when no
command line is present).
To see the higher levels of the stack, use the navigation keys ( and
).
10
Stack commands
DROP
DUP
CLEAR
SWAP
11
Modes
The HP48 operates in many modes, some of them are chosen automatically
depending on the operation being executed; others may be customized by user.
The Simulator does not implement the original Modes Application, though it
enables to change the angle format.
Setting the angle mode
The angle mode determines how the calculator interprets angle arguments and
how it returns angle results.
Angle modes
Mode Definition Annuciator
Degrees 1/360 of a circle DEG
Radians 1/2π of a circle RAD
Grads 1/400 of a circle GRA
To set the desired angle mode, press repeatedly RAD keys until the
desired mode appears.
Unsupported features
The simulator does not support these features: system flags, numbers
representation, fraction mark customizing, clock and alarms, beeps and other
sounds, coordinates mode, flag browsing and more.
12
Memory
The simulator realizes the HP48’s User Memory, which can store user’s data.
The size of User Memory is only limited by system memory of the device
running the simulator.
Creating new variables
Variable names can contain up to 63 characters, and can contain letters, digits
and any special characters, except these:
Characters that separate objects: space, period, dot, comma, @
Object delimiters: # [ ] " ' { } ( ) « » : _
Mathematical function symbols: +, –, , *, /, ∫, ∂, ^, √, =, <, >, ≤, ≥,
≠, !
Note, uppercase and lowercase letters are not equivalent.
The variable names must also follow these restrictions:
Names cannot begin with a digit.
You cannot use the names of commands (for example, SIN)
There are several predefined names, you can use them, but remember
that some commands use them as an implicit argument, altering there
contents may cause these commands to behavior incorrectly.
EQ, PICT, CST, ΣDAT, ALRMDAT, ΣPAR, PPAR, VPAR, PRTRAR,
IOPAR, s1, s2, …, n1, n2, …, names beginning with “der”.
NOTE: All of the above variable names are not used by the
simulator, but the usage can hurt the compatibility with HP48.
13
Manipulating variables
To store an object in the User Memory
1. Put the object on the stack.
2. Enter object’s name according to the rules above, while it’s
surrounded by single quotes ( ' ).
3. Press STO .
For example, let’s store the complex number 1+i in the variable named
U.
Key in ( 1 , 1 ENTER ' α U ENTER STO .
Note: If an object with the specified name already exists in the User
Memory, its content is deleted and a new value is assigned.
To use an object from the User memory
1. Key in the variable’s name.
2. Press ENTER .
The object will be evaluated — constant put onto stack, function
calculated etc.
To recall the variable to the stack
1. Press ' followed by variable’s name.
2. Press RCL .
Variable’s content is put onto stack (level 1). It’s ready editing,
evaluation, storing under different name. RECALL operation does not
remove the object from the user memory.
To purge the variable from the User Memory
1. Press ' followed by variable’s name.
2. Press PURGE .
To show the content of the User Memory press MEMORY . All the
variable names separated by spaces are shown encapsulated into a string.
14
Defining variables
The HP48’s DEFINE command can create variables from equations (see later).
If stack level 1 has an expression of form
'name=expression' or
'name(name1, name2, …)=expression',
executing DEFINE stores that expression in that name.
To create a variable from a symbolic definition
1. Enter an equation of the form 'name=expression'.
2. Press DEF (the DEFINE command)
15
Using Mathematical Functions
Built-in functions and commands
Built-in functions and commands are subset of HP48 operations. An operation
is any action the calculator may perform. But not all the operations are
equivalent to one other. They are classified into the following categories:
Operation. Any built-in action represented by a name or a key.
Command. Any programmable operation.
Function. Any command that may be included in algebraic objects.
Analytic function. Not supported by the Simulator.
SIN, for example, is a function; it can be included in algebraic object. SWAP
can be included in a program, but not in algebraic expression, thus SWAP is a
command. RAD changes the angle mode, but it cannot be included neither in
programs nor in algebraic objects, since that it’s an operation but not a
command.
Built-in functions and built-in commands describe the HP48 Simulator’s
command set. You can think of them as built-in program objects.
Expressing functions: algebraic syntax
The difference between functions and other commands is that functions can be
included in algebraic expression. The functions can be classified into three
types based on their syntax:
Prefix: SIN(x), MAX(x,y)
Infix: x + y, x < y
Postfix: x!
Note: In the expression A(X+Y), A is thought as a prefix function and not as a
multiplicative argument. If multiplication is intended, use explicit
multiplication operator, .
16
Algebraic objects use algebraic syntax and use the normal rules of algebraic
precedence to determine the order in which the functions are executed.
Functions with higher precedence are performed first.
Note: Unlike usual algebraic notation rules, the Simulator has a limitation on
the order of execution of functions with the same precedence — they are
executed right to left. While this is O’k with power function and order-
insensitive functions (+, ), this feature causes the expression '1–2–3' to be
evaluated to 2 instead of correct answer –4. You should use parentheses to get
the right answer.
HP48’s functions have the following algebraic precedence, from the highest to
lowest:
1. Expressions within parentheses. Expressions within nested
parentheses are evaluated from inner to outer.
2. Prefix functions (as SIN, prefix +, prefix –).
3. Postfix functions (such as factorial).
4. Multiplication ( ) and division ( / ).
5. Addition (infix +) and subtraction (infix –).
6. Comparison operators (such as = =, < ).
7. Equals ( = ).
Expressing functions: stack syntax
All the functions in HP48 can be executed in postfix form using stack. Stack
syntax is postfix syntax, where arguments are entered first, followed by
function name. Postfix syntax is usually more efficient way of evaluating, since
minimal expression parsing is involved.
Example: the sine function may be evaluated either as 'SIN(X)' or 'X'
SIN.
Example: addition of 5 and 6 can be performed either as '5+6' or 5 6 +.
Note: Unless you surround the function in single quotes, the Simulator assumes
that you are using postfix stack syntax, and tries to use objects from stack as
function arguments.
17
User-defined functions
You can add your own user-defined functions. They behave like built-in
functions in means that they can take parameters either in algebraic or in stack
syntax.
Creating a user-defined function.
1. Enter an equation of form 'name(arguments)=expression'. On
the left side, use commas to separate the arguments.
2. Press DEF (or use DEFINE command).
Example: Use DEFINE to create CMB, a user-defined function, that
calculates the number of combinations, C on n different items taken 1, 2,
3, … at a time:
Step 1. Enter the equation for CMB:
' α α C M B ( ) N α ► =
( ) 2 , α N ► – 1 ENTER .
Step 2. Execute DEFINE: DEF .
Executing a user-defined function.
A user-defined function is executed just like a user-defined function. It
can take arguments either from stack or in algebraic syntax.
18
Built-in Functions
Arithmetic and general math functions
Key Programmable
command
Description
1/X INV Prefix. Inverse (reciprocal).
SQRT Prefix. Square root.
SQ Prefix. Square.
+/– NEG Prefix. Changes the sign.
+ + Infix. Level 2 + level 1.
– – Infix. Level 2 – level 1.
Infix. Level 2 level 1.
/ / Infix. Level 2 / level 1.
POW Prefix. Level 2 raised to level 1
power.
XROOT Prefix. The x-th root of y.
Exponential and logarithmic functions
Key Programmable
command
Description
ALOG Prefix. Base 10 antilogarithm.
LOG LOG Prefix. Base 10 logarithm.
EXP Prefix. Base e antilogarithm.
LN LN Prefix. Base e logarithm.
Trigonometric functions
Key Programmable Description
19
command
SIN SIN Prefix. Sine.
ASIN ASIN Prefix. Arcsine.
COS COS Prefix. Cosine.
ACOS ACOS Prefix. Arccosine.
TAN TAN Prefix. Tangent.
ATAN ATAN Prefix. Arctangent.
Hyperbolic functions
Key Programmable
command
Description
SINH Prefix. Hyperbolic sine.
ASINH Prefix. Inverse hyperbolic sine.
COSH Prefix. Hyperbolic cosine.
ACOSH Prefix. Inverse hyperbolic cosine.
TANH Prefix. Hyperbolic tangent.
ATANH Prefix. Inverse hyperbolic tangent.
Probability
Key Programmable
command
Description
α DEL ! Postfix. Factorial of a positive
real number. Returns .
GAMMALN Prefix.
Other number functions
Key Programmable
command
Description
ABS Prefix. Absolute value.
20
CEIL Prefix. Smallest integer greater
than or equal to the argument.
FLOOR Prefix. Greatest integer less than
or equal to the argument.
% Infix. Modulus. (Currently
unsupported).
Other non-number commands
Key Programmable
command
Description
→NUM TONUM Postfix. Accepts an algebraic
expression and returns its
numeric value.
21
Programming the HP48
This chapter is an introduction to some of the programming compatibilities of
the HP48 Simulator. HP48 has a reach set of programming tools in various
levels — from low-level Assembly-like language and system-specific flags to
high-level language that supports elements of Object Oriented Programming.
The Simulator implements only a small subset of the original HP48
programming capabilities. Nevertheless, it is fully equivalent to Turing
Machine.
Understanding programming
An HP48 program is an object with « » delimiters, containing a sequence of
numbers, commands or other objects you want to execute automatically to
perform a task.
For example, if you want find the negative square root of a number that’s in
level 1, you may enter the following program: « SQRT NEG ».
The contents of a program
As mentioned above, a program contains a sequence of objects. As each object
is processed in the program, the action that results depends on the type of
object, as summarized below:
Actions for certain objects in programs
Object Action
Command Executed
Number Put on the stack
Algebraic Put on the stack
String Put on the stack
Program Put on the stack
Global name (quoted) Put on the stack
22
Global name (unquoted) Program is executed
Name evaluated
Other object put on stack
Local name (quoted) Put on the stack
Local name (unquoted) Contents put on the stack
Examples of program actions
Program Result
« 1 2 » 2: 1.00000
1: 2.00000
«"Hello!"» 1: "Hello!"
«'1 + 2'» 1: '1 + 2'
«'1 + 2' TONUM» 1: 3.00000
««1 2 +»» 1: «1 2 +»
««1 2 +» EVAL» 1: 3.00000
Structures
Actually, a program can contain more than just objects — it can also contain
structures. A structure is a program segment with a defined organization. The
Simulator supports only one sort of structure types — branching structures.
(HP48 has also so-called “local variable structure”. It can be replaced be the
supported FOR structure.)
Using branching structures
IF … THEN … ELSE … END
The syntax is:
«…IF «test-clause» THEN «true-clause» END…», or
«…IF «test-clause» THEN «true-clause» ELSE «false-clause» END…».
23
First, the test-clause is evaluated. If it’s true, the true-clause is executed. Else, if
the false-clause is present, it’s executed.
Note: another form of test-clause is also permitted: 'test-clause'. In this form the
test clause uses the algebraic notation, which is more familiar for programmers.
For example, the test-clause may be « X Y < » or ' X < Y '.
FOR…NEXT
The syntax is:
«…start finish FOR counter « loop-clause » NEXT…».
FOR…NEXT executes the loop-clause one time for each number in the range
start to finish, using a local variable counter as a loop counter. You can use this
variable in the loop-clause. The loop-clause is always executed at least once.
FOR takes start and finish from stack as a beginning and ending values for the
loop counter. Then the loop-clause is executed; counter can be used within
loop-clause. NEXT increments the loop counter by one, and then checks
whether its value is less then or equal to finish. If so, the loop-clause is repeated
(with the new value of counter), otherwise, execution resumes following
NEXT. When loop is exited, counter is purged.
FOR…STEP
The syntax is:
«…start finish FOR counter « loop-clause increment» STEP…».
FOR…STEP executes the loop clause just like FOR…NEXT does — except
that the program specifies the increment value for counter, which is taken from
the stack each time STEP is processed.
The increment value can be positive or negative. If the increment is positive,
the loop is executed again if counter is less than or equal to finish. If increment
is negative, the loop is executed again if counter is greater or equal to finish.
Otherwise, the counter is purged and execution resumes following STEP.
Note: A trick may be used to work with local variables: a dummy FOR loop.
24
Example. Let a number is in the stack level 1, and we want to work with it
referencing as a local variable. Following program demonstrates the technique:
«… DUP FOR var-name « commands » NEXT…».
The commands can use the var-name for calculations.
Note: All the structures may be nested as many times, as the memory enables.
25
Appendix A
Simulator structure
The HP48 Simulator is a highly complicated application, which uses many
programming techniques and paradigms, and it was written using a few
different computer languages.
Basically, the simulator is divided into 2 main parts: one deals with Graphical
User Interface, multithreaded environment, the multilayered keyboard and the
editor; the second solves the problems of parsing the user’s input, executing
commands and functions, working with nested local and global variables and
other tasks.
The development environment — Visual Studio for Windows CE — dictated
some constraints during writing the Simulator that needed to be overcome.
The compiler does not support the Standard Template Library, despite
the fact that is an integral part of C++ language. Instead, we have built
our own reduced version of STL, see below.
The compiler does not support C++ exceptions. This is a very arduous
restriction, which forces us to use the C error-code returning techniques,
and this, of course, leads to more tangled and less reliable code.
The GUI part consists of the projects named “Calculator” and “Characters”.
The second part includes the projects “CE_STD” and “Calc”.
26
The relationship between the projects
27
Calculator
Characters CE_STD
Calc
A BMeans A uses B
Projects descriptions
CE_STD project
This project is a partial implementation of a Standard Template Library. The
name o the project reflects the fact, that unlike STL all the names are defined in
the CE_STD namespace.
Main components
ce_string. Includes the definition and implementation for most of the
string operations: Various constructors, assignment functions,
comparison functions (“compare”, “= =”, “<”, “<=” etc.), single
character access operators (“[]”), insertion functions, appending
operators (“+=” – heavily used throughout the Simulator) and query
functions (“length”, “empty”, “size”).
Implementation. ce_string uses variable sized array as a container, and
changes its size upon string length change.
ce_stream. Includes a relatively small subset of STL’s stream concept.
Streams are used by the tokenizer, and we implemented only the refered
components. The classes hierarchy uses virtual multiple inheritance. The
most used class is stringstream and its methods <<, >> and constructor /
destructor.
The stream is able to accept strings (from the ce_string library), doubles
and integers. All the other types that are normally processed by streams
have to be previously transformed to string.
ce_deque. This is almost the full implementation of STL’s deque library.
It can hold objects of virtually any type (with default constructor), since
it is a template class (and consequently the implementation resides in a
header file). Note: The push_front method is not as efficient as standard
states — O(n) instead of O(const) an average. This is fully acceptable,
since we use only the push_back method in performance-sensible
28
places, and we provide the second function for compatibility purposes
only. The algorithm is described in the source code.
ce_map. This is also almost the full implementation of STL’s map
library. It’s based on deque and is not as efficient as the standard states
— most operations take O(n) instead of the standard O(log(n)). This fact
is acceptable, because the containers in the simulator are small, almost
only the look-up tables (global and local, see below).
ce_algorithm. Here the implementation of two functions, find_if and
for_each, is found. These functions ca nbe applied upon any container
from CE_STD.
ce_utility. Includes the definition of standard pair class and its related
function — make_pair. This, apart from common usage, is a necessary
element of map implementation.
29
Character project
Windows CE uses wide characters to represent textual information. The
tokenizer (see below) urged us to use the one byte characters throughout the
program. This project includes the mappings between two datatypes.
30
Calc project
Most of the ”thinking” program are concentrated in this project — from the
basic HP48 types definitions through command line parsing and to commands
execution. Taking care of the variables and error recovery facilities are also in
this project.
Main components
calc_complex. A very basic class taking care of the complex numbers. It
also includes the casting from double operator.
define.h is a configuration file, used for debug purposes. It enables
selection of which STL should be used: the built-in or CE_STD.
errors.h defines a function CALC_THROW, which accepts a string.
When the compiler is upgraded to deal with exceptions, this should be
redefined:
#define CALC_THROW throw
Currently it displays a window with an error description. Since
CALC_THROW returns to the calling function, it’s necessary to include
an abortion command at the returning point.
Value. This class represents HP48’s main datatype. Using C notation,
this is a union, which can hold a double or integer number, string, and
algebraic expression, a program, variable name or a special error type.
The class has the inspectors (is_ functions, get_ functions), modifiers
(set_ function) and the set of constructor / destructor.
Utils. This is a collection of components that cannot be put into another
category. It includes the function is_double (returns true if the string
argument represents a double constant) and the to_dec function, which
returns the string representation of the numeric argument.
Param_list. This class is a Value container used to store all the
arguments during execution of HP48’s function call. The function
reverse should be noted. The function call for 'f(x,y,z)' assumes
31
taking x from the stack level 3, y from 2 and z from level 1. But popping
values from stack leads to back order. The method reverse fixes the
problem.
src.l. This is one of the most complicated parts of the program. It is built
using the FLEX tokenizer generator.
o Building. The special build configuration should be used to get
the object file.
Custom build:echo off
flex -+ -o1.cpp src.l
findstr /v /c:”istream” 1.cpp > 2.cpp
findstr /v /c:”#include <unistd.h>” 2.cpp >
3.cpp
copy /y lex_header.h + 3.cpp lex_anal.cpp
del 1.cpp 2.cpp 3.cpp
OutputsLex_anal.cpp
Here we replace all the incompatibilities with Windows CE by
“domestic” counterparts.
o The file exports three functions:
parse_expression_to_tree, proceed, and
parse_definition. The first one parses an algebraic
expression and returns a string, which represents an evaluation
tree (see below) for that expression. The second function parses
the user’s command line and applies the action upon every object
entered. The third one deals with user-defined functions.
o Algorithm. The FLEX program supplies tokenizer.
Unfortunately, we cannot use the YACC program to built a
powerful bottom-up parser due to compatibility problems. Hence
we built the parser by up-down recursive descent technique.
Since this algorithm parses LL1 grammar, it cannot deal properly
with left to right operator associativity. For more details, see
32
chapter 6 (Using Mathematical Functions), paragraph
“Expressing functions: algebraic syntax”. The class source
encapsulates the tokenizer and has a placeholder for one token to
be pushed back — a basic operation in the recursive descent
parser.
o There are 3 header files associated with src.l
FlexLexer.h is an internal part of FLEX tokenizer
generator.
lex_anal.h is the exported header; it includes the exported
functions.
lex_header.h is the patch to the C++ file generated by
FLEX. It tunes the source file to work with Windows CE.
eval_tree and node_info. These files consist of the implementation of the
so-called “syntax tree”. Syntax tree is a tree data structure generated by
a parser, where each node contains the operation and each son contains
one argument for the operation. Our version of syntax tree is more
complicated than most standard implementations. Besides the ordinary
container of sons, it incorporates a container of local variables along
with functions for data retrieval.
o Algorithm. To find a node’s value we evaluate all the sons, from
the first to last, and then apply the current node’s function to the
son’s values. If the current node is a variable, we recursively ask
the father for its value. The topmost node has the values of all the
formal (local) variables.
Example: Let’s define a function .
The resulting syntax tree is:
33
Note, the leaves in the leaves in the syntax tree are always either
constants or variables.
o Implementation consideration. STL’s deque class was used to
represent node’s sons and formal variables. The parameters to the
node transferred during evolution request are stored in a class
member of Param_list type. A string “user-friendly” remembers
the user’s definition of the function and this enables editing of the
function later.
o Generally, Eval_tree class is responsible for proper tree structure,
while Node_info is the “data cell”, specific to our application.
o These classes have debugging aptitudes, they can work with
different implementations of STL, containers, the classes supply
functions that print the current object state in human readable for
etc.
Look_up_table. This is conceptual conglomerate of a standard look-up
table and implementation of built-in calculator functions. Such program
structure simplified building at the cost of some performance penalty.
Let’s see some of its exported methods.
o get_num_of_params — returns the number of parameters for the
specified function name, or 0 if the name is a variable.
34
/List of formal parameters
x,y
sin g
x x
x y
10
o execute. Accepts the name of the function and the Param_list —
values for the formal arguments. Returns the result of applying
the function to the arguments.
o insert_loc, insert_glob — inserts a new name into the local or the
global look-up table.
o enter_frame, leave_frame — define a stack frame.
o defined — returns true if the name can be evaluated.
o from_string, to_string — saves the whole look-up table into a
special internal format and then reads it. This facility lets the user
save the Simulator’s state to disk and load it later.
o increment_angle_mode, get_angle_mode define how the
trigonometric functions should treat their arguments.
Implementation details:
o The look-up table is a singleton object, and we chose to
implement it as a static class. In order to initialize the lookup
table, a special object of the class Local_LUtable_initializer is
built, which defines a new stack frame, sets the angle mode and
inserts the π constant during its construction.
The_stack. The HP48 has a stack as a main infrastructure for storing the
objects and operating on them. In the Simulator there is a singleton
object of the type The_stack, representing the abstraction of the
calculator’s stack. This class differs from classical stack
implementations in that it has a random member-access operator (“[ ]”).
This operator is unusual in that it returns the string with the symbolic
representation of the object, or an empty string if such object does not
exists.
Implementation. A class member of type deque is used hold the objects.
35
Calculator project
The Calculator project is a GUI of the program; it uses all of the program
components. It consists of four components.
Main components
SCREEN. Displays all the output on Calculator screen. SCREEN structure.
The screen has six lines to present data. The topmost line displays current
status, i.e. angle mode, alpha, left or right shift mode. Four lines to present
four Stack lines of Calculator. The first line can also display line Editor.
And the last line is permanently shows function's keys, i.e. load and save.
Implementation: SCREEN has six buffers to hold data for six lines. It also
has functions to fill data into its buffers and to print it to the window
context. While initialization the SCREEN allocates memory for its buffers
and releases it while is destructed.
KEYBOARD. Treats all keyboard functionality. It draws keyboard's
bitmap, taken from resource file, emulates buttons clicks and maps codes to
buttons. After initialization every button generates code. It is serial number
of button. Implementation: array of 49 buttons.
KeyDispatcher. Uses serial number of button to map it to button's code
regarding to current mode. Also sets the Calculator's mode. Implementation.
It consists of 12X49 array that holds all buttons codes (49 buttons, 12
modes). On initialization stage it fills the array with values from resource
file. When mapCode function is called with serial number, it sends message
with appropriate button's code.
Editor. Line editor used for typing and editing expressions. It supports DEL
and Backspace keys. Implementation: Editor has one buffer to hold typing
data and one buffer for displaying status line. It provides functions to add
values to editor's buffer, to clear buffer, to stop and start editor.
36
Appendix B
Examples of program execution
GeneralAll the events in the system are processed by WndProc function. This also
includes our custom messages, which are treated by WM_COMMAND
message.
The system generates messages about the pressed key, which are translated by
mapCode function and a new messages are sent.
Let's take a look on the example:
Example 1: pressing a key 8 .
Function name Description
WndProc Dispatches the message.
parseMenu Treats the relevant message;
IDM_BUTTON_CLICKED message runs
mpCode, and invokes displayStatus and
writeToScreen.
mapCode Accepts the serial number of a button and
translates it into the code, depending on the
current keyboard layer. Also, sends a message
with 8 's code.
WndProc Dispatches the message WM_COMMAND.
parseMenu Treats IDM_GET_BTN_CODE. Creates a new
thread which processes the actions on 8 .
th_parseMenu Wrapper, invokes processButtonCode, after
that delates the parameters. RUNS IN A NEW
THREAD.
processButtonCode The button 8 has a property "start_editor",
37
since that the function startEdit is invoked.
After that, the function addValue is called,
after which the function displayEditor and
writeToScreen are each called in turn.
addValue Accepts the button 8 code, and appends the
string "8" (taken from the table
"unikeybcode.txt") to the current position in the
editor's buffer.
displayEditor Displays current buffer in the first raw of the
screen and the three lowest stack positions in
the rows 2 — 4. Also, it prepares the
annunciators row according to the current
keyboard layer and angle mode.
The_stack::operator [ ] Returns human-readable representation of the
corresponding stack position.
SCREEN::prepareScreenData Fills the cells of the screen with their real
values.
SCREEN::writeToScreen Displays on the screen the data prepared by
previous function, according to the physical
dimensions, colors and other paramerters.
If a button pressed has the "stop_editor" property, the editor is terminated
before the screen is updated. If it has also a "call_eval" property, then just after
calling addValue the editor's buffer is passed to the function proceed.
Example 2: pressing a key SIN .
The user pressed the key SIN or the user typed "SIN" and pressed
ENTER .
We'll skip all the above stages.
Function name Description
38
proceed Accepts the string "SIN", passes it to
the parser, which returns the token's
code "Var".
Source::Source Accepts an input stream and
initializes the tokenizer.
Source::get_token Requests the encapsulated tokenizer
for the next token.
Look_up_table::defined Accepts variable's or function's name
and returns true if that name can be
evaluated.
Look_up_table::is_unary_built_in Returns "true" for "SIN".
Look_up_table::get_num_of_params Returns 1 for "SIN".
The_stack::top Returns the argument for "SIN".
pl.add Adds the argument to the parameters
list.
Look_up_table::execute Accepts the function "SIN" and the
list of parameters; return the sine. It
tries to find the name "SIN" in local
and global look-up tables, and
executes "execute_unary_built_in"
Look_up_table::execute_unary_built_in Finally does the calculations of SIN,
just after it converts the angle
argument to radians.
39
Appendix C
Alpha Keyboard Layout
40