home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-04-04 | 22.5 KB | 542 lines | [TEXT/QNTA] |
-
- The Quinta Environment
-
- To some extent, the Quinta system can be self documenting.
- Messages and Responses are elements of the Quinta dictionary
- and may be pushed onto the stack as objects for examination. To
- push a message onto the stack, enclose it in underscores. For
- example, to push the message *,
-
- _*_
-
- Several important operations are possible for message objects.
- For example, with a message object on TOS, the message send
- will send that message as if it were typed into the Quinta
- interpreter. The message print will print information about the
- message including any comments attached to it and the classes
- which may respond to it. For a response object, the message
- print will print information about the response.
-
- A class may be pushed onto the stack by simply typing its name
- into the interpreter. The resulting object is an instance of class
- class.
-
- By pushing a list of classes onto the stack, and sending the
- message responses, a list of responses will be returned to the
- stack. This list contains the responses defined for that set of
- classes. Pushing a list of n classes specifies messages of order n.
- For example:
-
- integer float 2 >list
-
- The above line builds a list with 2 class objects.
-
- responses
-
- This message pushes a list of all responses to messages of order 2
- which are defined when the stack has an integer in level 1 and a
- float in level 2. Of course, this includes any response defined
- for any ordered combination of n subclasses of the n classes in
- the list.
-
- For a response object, the message msg pushes the message for
- which this response is the definition. The message home pushes
- the list of classes for which this response if the definition. To
- summarize: A message can be sent to the stack. A message of
- order n requires n receivers. The classes of these n receivers
- must have a response defined to that message. This response is a
- dictionary structure in itself. The home of this response is that
- set of classes.
-
- The message pdict will print all messages in the dictionary. This
- can be a very useful method for the Quinta interpreter to
- document itself.
-
- The Macintosh implementation of Quinta is an interactive
- interpreter with a text window used for all input and output.
- Upon executing the Quinta application, there is a pause as the
- dictionary is built. Then, it is your turn to act. The enter key is
- the significant key. Like MPW, Quinta will not process input
- until the enter key is pressed. The return key is not equivalent.
- Multiple lines may be sent by selecting all the lines and pressing
- enter. In fact, when processing input, Quinta first checks to see
- if the selection is just that. Is there is a region of text darkened ?
- If so, that text alone is processed. Otherwise, only the text on
- the current line is processed. Therefore, if a string of messages
- or response definition or other entry spans more than one line,
- the entire selection must be selected before pressing enter.
-
- The editor is a simple editor with no advanced features. Menus
- are available and the editor is capable of operating on multiple
- files, but the Worksheet is the primary window and file. To
- write a Quinta program, use the editor (or any editor) to store
- your message, class, and response definitions. Then, open that
- file from within Quinta. Copy your Quinta source into the
- worksheet. Select (highlight by dragging) all the lines you wish
- to be executed (entered into the dictionary). Then, press Enter
- (not Return), to process the source. The shortcut for all of the
- above is the Load entry under the Command menu. This will
- prompt you for a file of Quinta source, and it will execute all of
- the code contained in that file. Try this procedure on the
- example program sieve.q to see how it all works. In addition,
- there is a message called load. Given a filename in a string, this
- allows files to be loaded into the dictionary under Quinta
- control.
-
- The Class Hierarchy
-
- From the interpreter, the message classes will push a list on the
- stack containing all of the classes currently in the interpreter.
- Typing the name of any class will push that class object onto the
- stack.
-
- The most important class of all Quinta classes is generic.
- Generic is the parent class of all other object classes (analogous
- to Smalltalk's OBJECT). The responses defined for generic are
- for messages of a very general nature. These messages should
- be acceptable for receiving objects of any class. However,
- responses for class generic are not acceptable when the stack is
- empty. Furthermore, there will be times that we wish to
- perform certain actions regardless of the condition of the stack.
- For this reason, there is another "class" above generic, called
- control. There are no instances of class control which can be
- created. We think of the interpreter itself as the only object of
- class control. The interpreter is considered to always be on the
- bottom of the stack, for the purposes of receiving messages. In
- terms of a physical paradigm, it is most accurate to say that we
- consider the stack to be resting on the interpreter. We send
- messages to the stack, and the objects on TOS respond.
- However, when we send a message to the stack and the stack is
- empty or cannot respond, it comes to rest on the interpreter,
- which either responds appropriately or assumes the role of
- communicating an error message.
-
- An example of a message with a response for class control is
- pdict. This message simply prints every message in the
- dictionary. It requires no parameters or input. It does not
- examine or modify the stack. It simply provides information to
- the user about the interpreter itself.
-
- The class logical is used for conditionals. A logical object
- represents either true or false. The messages true and false push
- the only two unique instances of class logical.
-
- The class quantity is the parent class for all types of data which
- are manipulated using arithmetic operations. There are no
- instances of class quantity. There may be, however, a number
- of subclasses of class quantity. One such subclass is real. This
- class also has no instances. Subclasses of real include integer and
- float. These are general purpose classes for numerical
- computations and representations. Any token beginning with a
- digit or unary sign will be interpreted as a real. If it contains a
- decimal point, it is considered a float. Floating point operations
- in Quinta are always at extended precision. The interpreter
- recognizes integers and floating point numbers when entered.
- Exponential notation is ok for floating point numbers, but unless
- the number contains a decimal point, it is assumed to be an
- integer. Therefore,
-
- 345e56
-
- will be read by the interpreter incorrectly. However,
-
- 345.e56
-
- will work.
-
- The class date is used for manipulations of dates. It is a subclass
- of integer, and represents the number of seconds since 12:00 am
- January 1, 1904. The message today of class control will push
- the current date onto the stack. Since date is a descendant of
- integer, dates may be manipulated arithmetically. Keep in
- mind, that the units on date are seconds. So, to add one day to a
- date, add 86400, not 1.
-
- The class string is used for all data represented as strings of
- characters. Strings in Quinta may be essentially any length and
- are recognized by the interpreter when surrounded by double
- quotes.
-
- The class message is used to allow Quinta messages to operate
- on other messages as a construct of the dictionary. The class
- response is used to represent responses. Both respond to the
- message print, for the purpose of displaying information from
- the dictionary. A message object is recognized by the
- interpreter when surrounded by underscores. For any message
- on the stack, the message responses will push a list of all possible
- responses to that message.
-
- Class block is used for defining Quinta code. A block is a
- stream of tokens which can be stored in a response. A block is
- recognized by the interpreter when surrounded by [ brackets ].
- A block, once created, may be used to defined a response to a
- message for some set of classes. For examples, see above. In
- addition, a block may be executed by sending the message send.
- Blocks may be nested. Finally, blocks may be used in the dountil
- and whiledo loops. See below for a discussion of the looping
- constructs in Quinta.
-
- Class aggregation is the parent class for collections of objects.
- For example, class list is one of the subclasses in the aggregation
- class tree. Currently list is the only significant structure
- supported by aggregation.
-
- A list object is a list of other objects. They are represented
- internally in a manner similar to Lisp lists and respond to the
- messages car and cdr, as in Lisp. Car pushes the head of the list.
- Cdr pushes the tail of the list, which will ALWAYS be another
- list, even if the list has zero or one members. A subclass of list,
- called dim is used to specify dimensions of matrices. Two
- integers can respond to the message >dim to create a new dim
- object.
-
- Class matrix is used for matrix operations. Matrices are arrays
- of floating point numbers. For speed, it was decided that this
- implementation of matrices would only handle numbers, not
- general objects. Standard operations on matrices are supported
- including inversion, determinant, transverse, multiplication, dot
- product, etc.
-
- Class variable is used for operations on Quinta variables. A
- variable object is recognized by the interpreter when enclosed in
- single quotes. Any object my be stored in a variable, such as
-
- object 'var' sto
-
- Any variable my have its contents recalled using rcl and any
- variable may be purged from the dictionary using purge.
-
- Class member is used to represent member variables of class
- instances. Any user defined class may have member variables
- for encapsulation of data. Member variables, in general, act as
- regular variables, but their internal implementation is different.
- When an object of a user defined class with member variables is
- on TOS, sending the name of one of those member variables
- enclosed in single quotes will push the object of class member
- onto the stack. The object itself will be removed. Then, when
- something is stored into the member variable using sto, the
- surrounding object is returned to the stack.
-
- Class constant is a subclass of variable which does not allow
- modification of its contents. Any variable may be converted to a
- constant using the message >const.
-
- Messages
-
- The following is a summary of some of the messages of Quinta.
- The control response for the message messages will push a list of
- every message in the dictionary (this can be a rather large list).
-
- Any part of a line after a semicolon is considered a comment.
-
- selfdoc adds comments to a number of messages in the
- dictionary. These are not added at initialization to save
- memory. Any message will have its comment printed (if it has
- one) when the message itself is printed. All messages can be
- printed using the message pdict.
-
- >str converts an object to a string. If there is no response
- specially programmed for the class of the receiver, the name of
- the class of the receiver is the result.
-
- >float converts an integer to a float
-
- PI pushes the floating point approximation to pi
-
- allmsg pushes a list of every message in the dictionary.
-
- size pushes the size of the receiver. Defined for lists,
- matrices, and strings
-
- cos most standard trigonometric operations are defined.
- These functions as well as exponential functions and the like are
- defined only for class float. To define them for integers as well:
-
- float integer inherit
-
- (This uses the multiple inheritance feature of Quinta)
-
- beep A simple beep, using whatever beep is currently the
- system beep
-
- depth gives the integer depth of the stack
-
- if used for conditionals - not object oriented. the structure
- if-else-endif (else optional) can enclose code for decision
- making. Logical objects may respond. For example,
-
- 3 6 < if "no" else "yes" endif
-
- div integer division operator. normally, division of 2
- integers using /, yields a float. div yields an integer, discarding
- the remainder.
-
- dot dot products of matrices
-
- idn given an integer, pushes the identity matrix of that size
-
- norm normal distribution function approximation for floats
-
- polyfit polynomial curve fits - see example program fit.q
-
- rand random number
-
- recurse recursively send the message currently being
- executed. faster than sending the message itself
-
- today the current date, as a date object
-
- sl shifts an integer left, also sr, slb, srb
-
- sinv given a variable, inverts the contents, also sneg, sto+, sto-
-
- min minimum of two numbers, also max
-
- The Debugger
-
- Quinta has a source level debugger which is activated using the
- Command menu. When the debugger is on, user defined
- responses halt after every message, to allow the user to
- manipulate data and monitor the program. Once the debugger
- has halted a response, variables may be examined or modified.
- In fact, any Quinta operation is legal. The message step causes a
- single step. The message go turns the debugger off. Within a
- response being debugged, halt causes a breakpoint. If an error
- occurs while in the debugger, the debugger is turned off. The
- message rstk will attempt to print a trace of the Quinta return
- stack. This will give some indication of how the program has
- progressed.
-
- Loops
-
- Quinta supports several flavors of loops. They fall into two
- main kinds: object oriented, and structured. Structured loops
- are legal only within response definitions. The kinds of
- structured loops are: for-next, do-until, and while-repeat-end.
- Below, (flag) refers to a logical object. Their usages:
-
- (start) (end) (localname) for (contents of loop) (localvariable)
- next
-
- 1 5 "q" for q print 'q' next
-
- do (contents of loop) (flag) until
-
- do q 1 + 'q' sto q 5 > until
-
- while (flag) repeat (contents of loop) end
-
- while q 5 < repeat q 1 + 'q' sto end
-
- For the for-next loop, the local variable is a loop index. It is
- created when the for loop begins. It's value is not destroyed
- when the loop exits.
-
- Object oriented loops, as I call them, are much nicer when
- considered in a purely object oriented programming
- framework. There are currently two messages which work
- with object oriented loops: dountil and whiledo. Each of these
- expects two block objects to be on the stack. The block object in
- level 2 is the body of the loop; ie. the code to be executed on each
- pass. The block object in level 1 may contain any messages
- desired, but it must leave a logical object on the stack. This is
- used for the termination condition of the loop. The dountil loop
- checks for termination AFTER each pass. The whiledo loops
- checks for termination BEFORE each pass. Therefore, the
- dountil loop is guaranteed to executed its body at least once
- while the whiledo loop is not. An example:
-
- [ 1 "x" local [ 'x' ++ x print ] [ x 10 > ] dountil ]
- send
-
- This loop prints the numbers 2 through 11.
-
- Conditionals
-
- The best way to handle conditionals in Quinta is using the
- message cond. Cond is of order 3 and requires:
- 3: a block of code for the ELSE case
- 2: a block of code for the THEN case
- 1: a logical object
-
- If the logical is true, then the block in level 2 is sent. Otherwise,
- the block in level 3 is sent. Example,
-
- [ "Nope!" ] [ "OK" ] true cond
-
- Data Constants in Quinta Code
-
- Data constants are textual representations of objects which are
- recognized by the interpreter and automatically converted and
- pushed onto the stack. Currently, only integers, floats, strings,
- and blocks are recognized by the interpreter. The only way to
- construct other objects is to use messages defined for that
- purpose. For example, pushing n objects onto the stack and then
- pushing n as an integer allows one to use the message >str to
- build a list with those n objects. Also, the message new is
- defined for the class class. It creates a new object for the given
- class. The value of this new object is, in general, undefined. A
- builder response may be defined for a class to initialize the value
- of a newly created instance, using setbld. Builder responses are
- analgous to C++ constructor functions. Builder responses to
- NOT automatically execute the builder response of the parent
- class. Executing the builder response for any class can be
- accomplished by using the message bld sent to the desired class
- object. See sieve.q for examples of builder responses.
- Predefined Quinta classes do not currently have any builder
- responses.
-
- Multiple Inheritance
-
- Quinta supports multiple inheritance. However, the feature has
- not been tested extensively. All subclasses are created with a
- principle parent class. After that, two classes may establish a
- parent - child relationship using the message inherit. For
- example, to make integer a subclass of logical (thus allowing all
- integers to act as logical values, similar to C):
-
- logical integer inherit
-
- Note that this feature is best used with your own subclasses.
- Most Quinta predefined classes should not inherit messages in
- their current implementation. For example, the following is an
- invitation for a system crash:
-
- string integer inherit ; Don't do this
-
- Interacting with the Interpreter
-
- After each press of enter, Quinta prints the current status of the
- stack, including the depth and the objects in the first 4 levels.
- This is reconfigurable; see below. Quinta also will report a
- number of error messages. For example, consider the
- following message:
-
- wrong
-
- Quinta will respond by saying that the message wrong is not in
- the dictionary. Messages that occur within responses and user
- programs are handled similarly. Quinta always attempts to
- diagnose the location of the error and report this to the user.
-
- The Window menu may be used to switch back and forth
- between edit windows in the Quinta interpreter.
-
- Dictionary Memory Usage
-
- The Quinta dictionary uses a good deal of memory. The
- algorithms I have used for the interpreter are designed with
- priority given to speed of execution. The consequence of this
- decision was ENORMOUS memory usage. For each message,
- this memory usage is exponentially related to the order of the
- message. For this reason, Quinta does not allow messages of
- order greater than 3. A number of methods were used to keep
- memory usage minimal, and as a result, some insertions into the
- dictionary can be rather slow. For example, the creation of an
- order 3 message defined for three generic objects on the stack
- would require a great deal of memory and work. The reason is,
- this message would have to be inherited to all of the descendants
- of class generic in all combinations of 3. However, a message of
- order 3 defined for 3 logical objects would be more benign:
- logical has no subclasses (in the core version). Multiple
- inheritance can cause a delay as well. However, all algorithms
- have been designed to be as fast as possible at runtime. Extra
- work is done when manipulating the dictionary specifically so
- that the actual accesses to the dictionary will be more rapid.
-
- Because of the enormous memory usage involved with multiple
- order messages, sometimes it is best to keep the order of the
- message low and allow the possibility of stack underflow. For
- example, the message put is predefined in the interpreter and is
- used for modifying lists and matrices. For a list, it should
- require:
- 3: an object to be placed into the list
- 2: the list itself
- 1: the index into the list where the object should be put
- However, this would require a response definition for class
- integer:list:generic. This requires well over 100 kilobytes of
- storage for the response table of the put message! Instead, I
- have defined put to be of class 2. The implementation blindly
- assumes that there is an object in level 3. This dramatically
- reduces memory requirements.
-
- The message subclass and respond are even better examples. To
- be correctly implemented, they should be of order 4. Order 4
- messages require an unbelievable amount of storage.
-
- For any message, the amount of storage (in bytes) which it
- requires is printed when its message object is printed using the
- message print. The message pdict will, of course, include this
- info with every message it prints.
-
- Interpreter Configuration
-
- The interpreter has a number of limitations built into itself.
- These limitations are as follows:
-
- 1 Maximum length of a message or class name
- 32
- 2 # of levels of stack to print
- 4
- 3 Maximum members for user classes
- 128
- 4 Maximum total number of messages
- 1023
- 5 Maximum total number of classes
- 48
- 6 Maximum number of subclasses per class
- 64
- 7 Maximum main stack depth
- 1000
- 8 Maximum number of locals at one time
- 64
- 9 Maximum nesting of Quinta responses
- 64
- 10 Maximum number of messages in a response
- 128
- 11 First Quinta message to be sent
- Qmain
-
- All of these parameters are configurable from within Quinta.
- By sending the message getconfig, a list of these parameters will
- be pushed onto the stack. The user may modify this list and then
- send the message setconfig. Changes will take effect next time
- the interpreter application is opened. Be very careful setting
- these parameters ! In general, do not change the first Quinta
- message unless you are sure you know what you are doing.
-
- The length of the configuration list will probably be changed in
- future versions of Quinta. Currently the list contains 11 items,
- and all future versions will leave those 11 items intact. In other
- words, item 7 will always be the main stack depth. However, I
- may add an item 12, 13, etc.
-
- QCore
-
- Upon opening the Quinta application, the dictionary is built and
- then the interpreter looks for a file called Qcore. If this file is
- found, all of the Quinta source code inside it is executed. This
- can be a very powerful way to extend the interpreter in Quinta.
- Oft used messages and classes may be installed into this file and
- they will be available each time Quinta is used. Personalized
- messages may be installed.
-
- Origins
-
- The design of Quinta has been influenced by a number of
- different sources. It was originally designed to be an object
- oriented version of Forth. I have also included similarities to
- Lisp, Smalltalk and the HP-28 calculator programming
- language. However, although Quinta has received some
- inspiration from the excellent Hewlett Packard 28 calculator
- line, it is not intended to be an emulator for those products (or
- any other products/languages).
-
- Credits
-
- The user interface code for the Quinta interpreter is built on
- Transkel and TransEdit, by Paul Dubois. Although I have made
- some modifications to his code, the basic structure of his work
- remains.
-
-