Status of my Joy implementation, ideas for uses of Joy, etc.

cpcogan — 2007-01-06 19:45:21

Hi.

Before I get to my main topics, I'd like to suggest some ideas for
thread topics (some of which may already have been used, but I haven't
yet gone over all the posts I've missed):

1. Joy and genetic programming (why it's such a good tool
for this, etc.).

2. Joy as a computer-aided-instruction language (an
alternative to Pilot, for example).

3. Joy as a model for a formal system notation (symbolic
logic, etc.)

4. Joy as a basis for a complete system of mathematical
Notation (like APL, Mathematica, etc.).

5. Joy as basis for the engine in a Mathematica-like package.

6. Joy as the basis for the engine in a general-purpose data-
manipulation tool (allowing the user to perform operations
for whatever he could write Joy code for or find a plug-in
for, like an APL or Mathematica environment, but far more
general).

7. Joy as the basis for a handwriting-recognition system
evolved by genetic programming (my ideas on this in a
future post, I hope).

8. Joy as a keystroke macro program (see below).

9. Joy as a macro language for other applications (i.e., a
macro language in IDE's, etc.) (see below).

10. Joy as a scripting language (for enabling a program to
interact with remote applications)(see below).


I have some thoughts (mostly half-baked -- or not even in the oven
yet) on these topics, but I admit I may never get around to posting
anything on them. I talk a little about some of them below, but I'm
sure there is much more to be said that others may be better qualified
than I to say (I haven't even actually written any significant code in
Joy much above the level of the required "Hello world" program, so I'm
definitely not the best person to talk about the actual Joy code for
anything).

==========================================

It's been over two years since I last posted. I haven't been keeping
up, either, sad to say, though I have taken a look a couple of times
to see what was going on. I've started two or three other messages
that I never finished. One showed how using local variables could
simplify the qroots code (and make it more readable, as well), which I
hope I still have on my computer at work (it doesn't seem to be on my
flash drive or my machine at home). I may finish and send it if
reading the posts on the quadratic question leads me to think that I
have anything to contribute. I have some other ideas about
representing mathematical formulas, but, again, I should go over what
has been posted about the qroots issue before I take up space with my
thoughts on this.

My implementation of Joy has over 200 "primitives." It uses a
"compiler" that creates what might be called "object threaded code" in
which each item in the thread is a Joy language code element object.
At execution-time, each element has a "delegate" (a fancied-up,
type-safe pointer) that is executed (actually, the function it points
to is executed), even if the code element is really just a string or
number. This produces a slow but uniform way of doing things (so that
the "interpreter" merely takes each code element and executes the
delegate, basically, and doesn't have to know anything about it).
Continuations are used (actually, the "compiled" code for each
function is copied onto a continuations stack, each with its own index
so it knows where to resume execution when a called function returns).
Copying is done so the code can be manipulated without changing the
dictionary entry, though I may change this so the code has to
explicitly copy any code it wants to manipulate.

Using my "object threaded code" approach also allows me to completely
reconstruct the executable portion of the source for any function
(without comments and original formatting). I used this latter feature
in the IDE to display a tree-structured representation of the code any
non-primitive function in the dictionary, and it means that the code
can be edited by other code even after it is "compiled" (for example,
I could have code that searches for a given stretch of code and then
replace it with another, even at run time, if I want). (In the tree
view, the user can collapse or expand parts of the tree, or view the
code for any function call (in a popup box that follows the mouse
cursor) just by moving the mouse over the corresponding node.)

I haven't actually used my implementation, except for basic testing (I
fed a bunch of the library stuff into it and tried a few functions,
etc.), so I'm sure there are many bugs still in it. At some point I
may convert it to C# or C++, but right now it's in Visual Basic (not
my favorite conventional programming language, but I got into using it
a work years ago because Basic was all I had access to), so I'm more
or less stuck with it -- and, for a regular programming language,
Visual Basic .NET is not too bad, and it has pretty much all the
features of the other languages, but in a less-concise form (for
example, ends of constructs are indicated with "End If," "End While,"
"Next," etc., instead of just the curly brackets of the C-derived
languages, which actually improves readability but not coding)).

I started this message to say that I'm successfully using Joy as a
macro language within a larger application (still being developed). I
wrote the entire Joy "engine" so it can be created as an object and
then accessed as needed, in several ways (each such instance can have
its own set of dictionaries and sub-dictionaries).

To enable the application to use the Joy engine, I wrote a bunch of
new application-specific "primitives" that are added to the Joy
dictionary at run time, by the application (using calls of the Joy
object's methods to do this, so the app doesn't have to know anything
about the Joy processor's innards). They can use other Joy primitives
or do their own thing, as needed. Right now, nearly all of them are
wrappers for application functions, written to make them parameterless
(in Visual Basic .NET terms, not Joy terms).

The application loads a table of scripts (which are currently Joy
source code without comments). When the user clicks a command button,
a small command processor retrieves the script for that command and
then passes it to Joy for execution. Here's a simple example (I don't
have any complex ones so far, but about a hundred simple ones):

[ "UDA" "Enter Last Name" "UDA Last name for UDA" "Last Name:"
PROMPT ] Ocmd

"UDA" is the name of a command in a mainframe application. The UDA
command takes a person's last name as a parameter, so, when the
content of the list is executed (by Ocmd at the end of the script), it
prompts the user for the person's last name, and then puts the name on
the stack.

When Ocmd is executed, it picks up all the parameters from the stack
down to a marker (automatically put on the stack prior to executing
the script), builds a command string which it then sends to a
mainframe front-end program called Extra! (the annoying exclamation
mark is actually part of its name), along with a carriage-return (to
tell the mainframe application to take what's been sent to it and
execute the corresponding command.

I think Joy is almost ideal for such scripting and for use as a macro
language (like those built into many programmers' editors and even
word processors like Word). The application-specific interfacing is
fairly easy, and the actual execution engine is so small that it need
not cause the app to be too bulky (as it probably would if you tried
to use many other languages of equal power, because of the high
overhead of processing source in nearly all languages except for
non-mainstream languages like Joy and Forth).

Another of the many things I've considered but have not yet done is
using Joy as a keystroke macro program, either within an app, or as a
general utility (functionally similar to Perfect Keyboard or other
such programs). Because of its strongly sequential nature, it should
be pretty easy to use it this way, I think. Because of its small
compiler/interpreter size, it would not be too large. The only
disadvantage that I've encountered is that strings in Joy are in
quotes, but in most keystroke macro programs, it's the language
constructs and non-string data that are somehow "quoted" (Perfect
Keyboard uses angle brackets, as in: <down>, for the down-arrow key,
and: <wx>(100), to tell the macro processor to pause for 100
milliseconds). However, using normal Joy conventions might actually be
an advantage in cases where there is a lot of Joy code and only a few
strings. Keystroke macro programs typically try to make strings the
default, but, since this is done at the expense of making the language
components annoying to use, it means that they discourage
more-sophisticated uses of such languages that might otherwise be made.

The work I do involves many forms, and I haven't yet developed an
interface for working with forms, but it doesn't seem especially hard
to do, except that I don't like the idea of writing bazillions of
little interface wrappers for the methods and properties of Visual
Studio forms (and their "controls," as Microsoft calls text boxes,
buttons, and the like that appear on forms), so I'm hoping to be able
to make a single general-purpose interface to such objects and use it
without having to write code for each individual item (and, for
complex forms, there can be many hundreds of things one might want to
have access to).

--Chris (Cogan, that is)