ELI (was Re: Tiny Lisp written in C)
Niels Mayer
mayer at hplabsz.HPL.HP.COM
Fri Jun 9 07:05:38 AEST 1989
I recently checked out the new version of ELI on expo.lcs.mit.edu by Bob
Glickstein to find out whether any of the bugs I have found had been fixed.
They weren't unfortunately.... here's some previous postiungs I've made
about ELI bugs, just so that you can know to avoid these problems with ELI.
ELI is a nifty package, and I'm not trying to denigrate BobG's work. I just
wanted to inform y'all of existing bugs in ELI before y'all go off and
waste your precious time tracking down anomalous behavior in ELI.
------- Forwarded Messages
To: info-andrew at andrew.cmu.edu
Subject: BGLISP/ELI -- question, contribution, bugs, and "features"
Organization: Hewlett-Packard Labs, Software Technology Lab, Palo Alto, CA.
X-Mailer: mh6.6
Date: Tue, 22 Nov 88 01:08:07 PST
Message-ID: <610.596192887 at hplnpm>
From: Niels P. Mayer <mayer at hplnpm>
Here are some bugs I've found using ELI/bglisp as released in the X11r3
tape (under contrib/toolkits/andrew/overhead/eli/). I'm running on a
HP9000s350 under HPUX 6.2.
An aside -- Are any of you out there using FLAMES and/or ELI/bglisp in
your applications? I'd love to hear what sort of mail processing you're
doing with FLAMES, and what kinds of user-customizable applications you've
dreamed up using ELI. Also, I'd like to hear reports of ELI's reliability,
scalability, speed, etc. Me? I'm using ELI to build a "widget interpreter"
using the HP Xwidgets. The widget iterpreter will be part of a hybrid
lisp/c development platform for a highly customizable CSCW/mail system that
I'm prototyping. It will NOT be based on AMS/FLAMES, though I might steal
EZ for displaying/editing multimedia messages.
Oh, and I also have added a few useful primitives to ELI -- lisp interfaces
to the unix subroutines popen(3S), pclose(3S), fopen(3S), fclose(3S),
fgets(3S), fputs(3S), and fscanf(3S). Anybody want these?
And finally, here's da bugs -- anybody got a fix?
- ------------------------------------------------------------------------------
(1) I found this bug in "let", while tracking down a misfeature in "do"
(see (2) below):
(setq a 666)
(progn
(printf "before let a = %S\n" a)
(let ((a 3))
(progn
(printf "in let, before setq, a = %S\n" a)
(setq a 5)
(printf "in let, after setq, a = %S\n" a)
)
)
(printf "after let, a = %S\n" a)
)
Evaling the above two expressions gives the following results.
> BGLisp> (666)
> BGLisp> before let a = 666
> in let, before setq, a = 3
> in let, after setq, a = 3
> after let, a = 5
> (T)
In other words, the setq within the let is being bound to the "a" outside
of the scope of the let. This pretty much makes "let" and "let*" useless
for creating local variables, since you can never change their values.
- ------------------------------------------------------------------------------
(2) The reason why I tried out what "let" was doing is because a simple
test program I was writing using "do" was failing for totally unexpected
reasons. The documentation for the "do" and "do*" functions indicates that
local variables of "do" retain their initializer values while in the do
loop unless a step value is given. Although this goes against all usages of
"do" that I've come across in the other dialects of lisp i've used, I
figured I could get by with a construct like the following in order
to allow variables declared in "do"'s varlist to act as local temporary
variables (as if declared in a "let" block just outside of the "do"):
(do
((i 0 i))
(<test> <return>)
<body>
)
Unfortunately, we see the same error here as we did in "let" above, namely
that if I try to do a (setq i 2) in <body>, I won't be setting the i that
was locally bound in "do". Within the scope of "do", variable i will always
stay at 0.
Ok, fine, so I figured that bglisp's "do" local variables insist on getting
set and altered through the <init> and <step> expressions in the varlist.
So I tried putting the local variables that need to be setq'd inside a
"let" that wraps the "do":
(let ((j 0))
(do
((i 0 (+ i 1)))
((equal j 100) j)
(progn
(setq j i)
(printf "%S\n" j))
))
The result is of course an infinite loop, with bglisp printing out "0\n"
until I ^C it. The reason for the behaviour is mentioned in (1) above.
Granted, the above is a contrived example that needn't be written the way
it is to achieve the desired effect. It is really just a simplification of
a problem I was having with a more complicated procedure that required the
ability to set and use local variables within the <body> of the "do".
- ------------------------------------------------------------------------------
(3) The following is probably less of a "bug" and more of a "feature" of
bglisp, eli. However, it will certainly cause much confusion for those that
know some of the well-known dialects of lisp such as common lisp, maclisp,
franzlisp, gnuemacs-lisp, etc:
All the lisps I've come across that take a <body> expression, such as "do",
"let", "cond", "defun", etc, allow <body> to be a sequence of expressions.
In bglisp/eli forces you to wrap any such sequence of expressions in a
progn as in the example above. Is this perhaps because bglisp is derived
from Gosling's mocklisp?
- -- Niels "tomorrow -- we'll work on closures and continuations! :-)" Mayer.
------- Message 2
To: Robert Steven Glickstein <bobg+ at andrew.cmu.edu>
Subject: Eli Bug?
Organization: Hewlett-Packard Labs, Software Technology Lab, Palo Alto, CA.
X-Mailer: mh6.6
Date: Sun, 27 Nov 88 18:39:48 PST
Message-ID: <7574.596687988 at hplnpm>
From: Niels P. Mayer <mayer at hplnpm>
I've gotten part of my "widget interpreter" (WINTERP) working using Eli,
and I think I may have found some memory allocation problems caused by
reading or evaling long strings.
to reproduce the problem, try the following:
create a file "foo.l" containing
(setq a
"1234567890....."
)
where "1234567890....." is really a >512 character string.
Startup bglisp and do
(read "foo.l")
Follow that by some other operation like
(+ 1 1)
On my system in bglisp, it will print out some character right after the
CRLF following (+ 1 1), for example:
BGLisp> (read "foo.l")
("12345678901234567890123456789012345678901234567890123456789012345678901234567
8901234567890123456789012345678901234567890123456789012345678901234567890123456
7890123456789012345678901234567890123456789012345678901234567890123456789012345
6789012345678901234561234567890123456789012345678901234567890123456789012345678
9012345678901234567890123456789012345678901234567890123456789012345678901234567
8901234567890123456789012345678901234567890123456789012345678901234567890123456
7890123456789012345678901234567890123456")
BGLisp> (+ 1 1)
9
BGLisp> 2
In this case, a spurious "9" was printed out, indicating that something
strange is going on.
In bglisp, this problem doesn't seem to cause any core dumps, and it's hard
for me to say what data is getting corrupted. However, in my widget
interpreter, the problem isn't so benign, since I always get a core dump
the next time an X Event is processed, or the next time WINTERP accepts a
socket connection from a widget interpreter client (lisp input to ELI in
WINTERP comes from a socket...). After many hours of tracking down false
leads in my server/client code, I finally arrived upon the problem caused
by long strings being loaded.
Any ideas on what's going wrong?
Also, do you have any suggestions for fixing the let/setq bug mentioned
in my info-andrew note?
Given the proper guidance, I'd be willing to help fix bugs in Eli.
I'm knee-deep in the code as is, and I need to fix the let/setq
problem before I start writing any serious applications with the widget
interpreter.
Thanks,
- -- Niels.
------- Comment on Above Message by Niels Mayer:
The above bug is caused by a LEX limitation:
from the lex manpage:
> WARNINGS
>
> The token buffer in the program built by lex is of fixed
> length,
>
> yytext[YYLMAX]
>
> where YYLMAX is defined to be 200 characters. Overflow of
> this array is not detected in the lex.yy.c program.
The value of "200" seems to correspond to the breakpoint in tokenlength
around which I was noticing strange behaviour, and indeed, in elil.c i find
> # define YYLMAX 200
A workaround to the problem of reading in long strings is to use strcat
instead of
"veryveryverylongstring......"
use
(strcat "very" "very" "very" "long" "string" "...")
------- Message 3
Date: Sat, 8 Apr 89 01:07:38 -0500 (CDT)
From: Bill Janssen <janssen%titan.sw.MCC.COM at mcc.com>
To: info-andrew-bugs at andrew.cmu.edu, info-andrew at andrew.cmu.edu
Subject: bug in eli "and"
[from the help entry for eli-functions:]
> The following standard Common LISP primitives are supported in eli. They
> should work exactly as they're supposed to work in Common LISP, and hence are
> not explained here. Consult a Common LISP manual for an explanation:
The "and" function in eli is documented to work as CommonLisp "and" does, but it
doesn't.
CL: (and t "foo") => "foo"
ELI: (and t "foo") => t
I imagine this is also true for "or".
Bill
------- Message 4
Date: Sat, 8 Apr 89 01:12:17 -0500 (CDT)
From: Bill Janssen <janssen%titan.sw.MCC.COM at mcc.com>
To: info-andrew-bugs at andrew.cmu.edu, info-andrew at andrew.cmu.edu
Subject: bug in eli "cond"
"cond" is documented to work like the "cond" in CommonLisp, but it doesn't.
CL: (cond ((boundp 'a) (+ 2 3) (+ 3 4)) (t nil)) => nil
ELI: (cond ((boundp 'a) (+ 2 3) (+ 3 4)) (t nil)) => *error*
where "*error*" indicates that the interpreter doesn't like the syntax of the
first cond clause.
Bill
------- Message 5
Date: Sat, 8 Apr 89 01:16:07 -0500 (CDT)
From: Bill Janssen <janssen%titan.sw.MCC.COM at mcc.com>
To: info-andrew-bugs at andrew.cmu.edu, info-andrew at andrew.cmu.edu
Subject: bug in ELI "let" and "let*"
The ELI functions "let" and "let*" are documented to work as their CommonLisp
version do. They don't. In CommonLisp, both let and let* establish an
implicit progn, so that a number of forms can be evaluated sequentially in the
body of the let. The value of the last form evaluated is returned as the value
of the let. ELI only allows one form in its "let".
Bill
------- End of Forwarded Messages
More information about the Comp.lang.c
mailing list