Prograph Primitive
Volume Number: 7
Issue Number: 5
Column Tag: Programmers' Workshop
Prograph Primitives 
By Terry Kilshaw, British Columbia, Canada
Note: Source code files accompanying article are located on MacTech CD-ROM orsource code disks.
[Terry Kilshaw is a free-lance consultant, writer and programmer now living
in the Okanagan valley of British Columbia. He has been designing software and
programming all sorts of computers for 12 years, the last 3 1/2 of which he spent as
Manager of Software Development for TGS Systems. He can be reached at (604) 762
4451.]
Adding C Primitives to Prograph
Prograph is a very high-level, object-oriented, pictorial, data-flow
programming language and integrated development environment. For an introduction to
Prograph see Prograph Raises OOP to New Height MacTutor, July 1989 by Mark
Szpakowski. It is fairly straightforward to add your own primitives to Prograph. These
can be written in such a way that they can be called from both interpreted and compiled
code.
In this article I’ll describe a couple of useful primitives, written using THINK C.
One is for creating a sorted list of unique strings from an unsorted list whose strings
are not necessarily unique, and the other is for performing a binary search on a sorted
list. On the way we will take a look at some practical details of Prograph primitive
construction and finish with a detailed example of a simple Prograph program which
shows a useful string permutation generator and provides a test bed for the two new
primitives.
Readers who don’t use or intend to use Prograph will still be able to adapt the C
language binary search for their own purposes.
The Structure of Prograph Data Items
All Prograph data items are referred to by Macintosh Handles and begin with the
three data fields, type, save and use. For historical reasons the size of the save and use
fields, and indeed of all index fields in interpreted code, is an unsigned two byte integer
value. In compiled code, however, they are four byte unsigned integers. Index fields
include the maximum length of a string and the maximum number of elements in a list.
Because Handles are used for strings and lists they can be grown and shrunk
dynamically, a fact that we will make use of later. The reason for the difference in data
type definitions lies in the evolution of Prograph. In subsequent releases we can expect
these differences to disappear.
After the type, save and use, in fixed length data items, comes the actual data: an
integer, floating point or boolean value. Lists, strings and instances of classes can vary
in length and therefore also have a length field.
The Primitives
The two primitives which will be created are called binlist-sort and
binlist-find. A “binlist” is just a name for a sorted list of strings with no duplicates.
These primitives would appear in Prograph as follows:
binlist-sort expects a list of strings on its input. It discards any duplicate
entries and creates the sorted list as its output.
binlist-find expects a sorted list of strings, with no duplicates, on its first input
and the string to search for as its second input. binlist-find returns a boolean, on its
first output, indicating TRUE if the string was found in the list and, on its second
output, the list index where the string was found. If the string was not found, the value
of the first output will be FALSE and the second output will be the list index where the
string could be inserted into the binlist. So binlist-find can be used both for finding an
entry in a binlist and for maintaining new entries to the list.
Making Primitives for the Interpreter
The _INTERPRETER flag in X_includes.h (see below) should be set to 1. Each
group of primitives is compiled into a code resource whose resource type is defined as
TGSC. For each primitive in the code resource an STR# resource consisting of 3 strings
is created, giving the mnemonic names of input and output arguments, the types of
input and output arguments, and a description of what the primitive does. The resource
name is used as the primitive name. The TGSC and STR# resources are placed together
in a file whose creator type is TGSL and whose file type is TGSC. On startup Prograph
automatically searches its own folder for files of type TGSC, the code resources and the
primitive names are loaded into the interpreter, and the primitives are available for
use.
The STR# resources are shown, in RMaker format, in the listing of
binlist_prims_I.r at the end of the article. Obviously you can use ResEdit or whatever
resource creation tools are available to you. After running through RMaker an output
file called binlist_prims.p.rsrc is produced. If this file is placed in the same folder as
your THINK C project then the STR# resources will automatically be copied into the
code resource file when the Build Code Resource item of the Project menu is chosen. The
name of the file containing the finished primitives is binlist_prims.
The name of the STR# resource is used as the primitive’s name in Prograph. The
STR# resource’s number maps on to the first argument of the AddPrimitive call in the
main function as described below. The (32) which follows the STR# number indicates
that the resource is to be purgeable. The three strings which follow that are for display
by the Primitives item of Prograph’s Info menu.
Making Primitives for the Compiler
The _INTERPRETER flag in X_includes.h (see below) should be set to 0. In this
case no STR# resources are needed, since on-line help is only appropriate in the
interpreter. The primitives are then compiled and built into a THINK C library. That
library is then added to your Prograph project and linked in with the Prograph code
and libraries to form the finished stand-alone program.
Naming Conventions
Primitives can be named any way you like, but there is an important convention
for the names of the C language functions which those primitives call which must be
used if you want the compiler to recognize them. A primitive can be thought of as a sort
of Universal Method. In compiled code, primitives and Universal Methods are actually
indistinguishable. Consequently the naming conventions, for a primitive, start from
the name that it is called by in the interpreter and prefix it with the characters U_.
For example the primitive test would become U_test. The naming conventions of the C
language, however, allow only alpha-numeric characters and the underscore is legal
function names. In order to cope with names which include special characters such as
the hyphen, the plus sign and so on, each special character is replaced with its two digit
hexadecimal ASCII value and preceded and followed by underscores. For example
binlist-sort becomes U_binlist_2D_sort, because 2D is the ASCII equivalent for the
hyphen ( or minus sign, if you will ) in hex. form.
Now to the Code
The source for the C language examples can be found in the file binlist_prims.c
MacTypes.h is a standard header provided by THINK C. X_includes.h is supplied
as part of the Prograph product and provides type declarations for code called by both
the interpreter and the compiler. This file also defines the value of the preprocessor
symbol _INTERPRETER, with the possible values of 0 for FALSE and 1 for TRUE. The
value of _INTERPRETER is then used throughout the primitive’s code, for preprocessor
directives to allow the single source to be used for primitives which will work in
interpreted and compiled Prograph programs.
X_includes.h also provides typedefs for all of the usual C types, which map as
follows:
THINK C Type ·Prograph Typedef
char ÍInt1
unsigned char ÍNat1
int ÍInt2, Bool
unsigned int ÍNat2
long ÍInt4
unsigned long ÍNat4
Bool can have only two values, 0 & 1, defined as FALSE and TRUE respectively.
The data item typdefs all have a similar form. Here, for example is the one for
Prograph’s integer data item as used by the interpreter: