Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!philabs!seismo!hao!hplabs!sri-unix!DLW@SCRC-TENEX From: DLW%SCRC-TENEX@sri-unix.UUCP Newsgroups: net.micro.pc Subject: IQLISP Message-ID: <2679@sri-arpa.UUCP> Date: Sat, 25-Jun-83 21:00:00 EDT Article-I.D.: sri-arpa.2679 Posted: Sat Jun 25 21:00:00 1983 Date-Received: Sat, 2-Jul-83 07:25:38 EDT Lines: 164 From: Daniel L. Weinreb Bob Cassels and I saw an advertisement in Byte for a Lisp implementation that runs on the IBM PC. The ad said that it had lots of features and power. Our curiosity was particularly engaged by the mention of an an interactive debugger, a package system, windows, and the presence of both call-by-value and call-by-name (!?). So I tried it out, courtesy of Software Arts, which has a copy. The product is named IQLISP, from a company named Integral Quality (Box 31970, Seattle WA 98103, 206-527-2918). We used IQLISP 1.1 on an IBM PC with 128K and DOS 1.1. The author's name (found in a READ.ME file on the diskette) is Robert Rorschach; the manual (no author mentioned, but presumably the aforementioned) also credits a Dr. Jeanne L Martin and a Dr. W. L. Ruzzo. (None of these names rung any bells for me.) So I booted it, typed nil, got an unbound variable error and a 1-> prompt. I've used new Lisps before, and this usually happens. It tells you two things: (1) the implementation is case-sensitive, and (2) you'll have to use the manual to figure out how to get out of the debugger. Off to the usual start. I turned to the documentation and started reading. It's a pretty conventional Lisp. He pretty clearly based it on Maclisp (the document recommends the Winston and Horn text, too), but he made all kinds of little syntactic improvements here and there. For example, it includes functions named FLATSIZE and FLATSIZEC, PRINT and PRINTC. The function definition syntax (every Lisp that isn't explicitly being compatible with someone else has its own unique one) looks like (defun foo (lambda (a b c) ...)) There are a few Interlisp-isms, including square brackets, so he knew about that too. In short, completely incompatible with everything else, but a translator would be easy to write. Data types include fixnums (short ones are implemented as inums), floating point (two formats, one with six digits and one with 13 digits of mantissa; it supports the 8087 if you have one), arrays (of objects, small integers, integers, one or two other types; the types are named 1, 2, 3 ... in typical small-computer style), strings (distinct from arrays, one- and two-character strings are immediate data, I think you can't store into strings, a la Multics Maclisp), file objects, and compiled code objects. There is no compiler. However, there is an extensive section of the manual giving you details of the implementation, and a set of primitives that build compiled code objects, so that you can write your own assembler and try to write your own compiler. Arrays are referenced Maclisp style (with apply) and stored into with the crufty Maclisp STORE. It has macros like Maclisp (the syntax is different, of course, but it's the same thing). It also has reader macros, splicing and non-splicing, in a simple form. I looked eagerly for an explanation of the "call-by-name" feature, prepared to find some totally confused and weird language feature that would do something very strange. Unfortunately, "call-by-name" turns out to just mean FEXPRs (as in "COND is another function that uses Lisp's call-by-name feature"). What a letdown. Oh, well. The documentation is not particularly enlightened about the true nature of Lisp as expounded in Bernie's "Notes" and Wechler's Lisp course. It uses the term "ID" to mean a Lisp pointer, and tells you that a cons contains two IDs. This is clearly an implementor talking. The manual promulgates the confusion about the sense of "bound to"; in fact, he tells you explicitly that "bound to" works both ways, that "A is bound to 5 means that 5 is bound to A", and that the statement "A is bound to B" is ambiguous. This is one of the most self-defeating things I've ever seen in a manual! Throughout the rest of the manual, he uses "bound to" interchangably in both ways, and it's sure confusing. He also has the usual confused explanation of "quoted arguments". Particularly bad was his comparison of macros and fexprs, although it's good that he even tried to have one at all. He compared a macro implementation of PUSH to a fexpr implementation. His FEXPR implementation didn't work, as he pointed out in the text (he intentionally had the bug of forgetting to call EVAL on the variable), but the text left you with the impression that the difference is that there's no way to write PUSH as a FEXPR because it doesn't work! This was the only thing in the manual to which I'd apply the descriptive term "brain damaged". Let me point out that I don't want to be too harsh on him. I expected rather more sleaze from a microcomputer implementation; I was just waiting to see a eight-character limit on symbol names or something like that (the limit is 32000). In general, IQLISP is quite reasonable for what it's trying to be. IQLISP has a save/restore feature (like our disk-save and disk-restore but without saving the Lisp system itself), and the standard diskette comes with a saved environment called DEVELOP.SYS, which the manual documents in a separate section. We are told that this is a saved environment containing program development tools, and that since you don't need when you're actually running a program, they aren't in the core Lisp system. So I loaded this up and started reading the document. Here was the "package system". It turns out to be a very simple version of the Interlisp "FILES package". You can have a list of "commands" for a file, that say which functions should be written out, which variables, etc, give forms to be evaluated at load-time, and all that stuff, like Interlisp. There is also a structure editor, much like the old one in Interlisp, somewhat more powerful than Maclisp's "Kludgey Binford Editor". There is also a pretty-printer, which I didn't look into in too much detail. There were also a bunch of what he calls "utility functions", including APPEND, NCONC, REVERSE, PUSH, and others. Putting these into DEVELOP.SYS is clearly silly, since you'd use them in programs and need them at runtime. I suspect that they're there because they're written in Lisp, not in assembly language. There is a backquote facility! The syntax is |"(A @B @C D) That is, backquote is |" and comma is @. It's not clear why backquote has to be two characters; vertical bar isn't used for anything else. And there isn't any way to say comma-atsign. But it's definitely a backquote, and he tells you that it's particularly intended for the writing of macros. I kept trying to guess what sources he was working from, and at this point began to suspect that he might have a Lisp Machine manual. The next thing I saw was a way to do displacing macros such that you leave the old definition behind so that the pretty-printer can see it, working EXACTLY the same way as the one in the Lisp Machine! At this point, I really began to suspect that he had a Lisp Machine manual, but I got no more evidence one way or the other. There were also a bunch of useful macros, like SELECTQ (compatible with us), LET (incompatible syntax (let (var1 val1 var2 val2) ...) for some reason), := (i.e. SETF), FOR (for x from 1 to 3 ...), REPEAT (repeat n ...), and even a keyword-oriented LOOP (not compatible, sort of like (loop (while ...) (do ...) ...), and not nearly as featureful as ours). He makes so many random syntax changes that it's hard to know where he was copying this from; I rather suspect Interlisp, though. There was also a very simple TRACE and a simple BREAKON (called BREAK), and an infix arithmetic syntax implemented as a reader macro. The "window" facility turns out to be a simple thing similar to what the Lisp Machine had in the early days (the "piece of paper" functions). You can define a little area on the screen, and scrolling happens within that area. It's sort of like the windowing built into the Concept 100 terminal. You cannot move windows, for example. The only thing that uses it is the interactive debugger, which has one window that displays information and another that's a Lisp interactor. You can move up and down the stack and see what form was being evaluated at each step, although it doesn't show you the values of the variables. You can return from a frame, retry a frame, and one or two other things. On the whole, it's a nice toy, and probably useful for people who just want to learn basic Lisp, although I doubt it's any good for getting work of any serious size accomplished. I thought it was a good hack. IQLISP is pretty reasonable for a micro.