masak / bel

An interpreter for Bel, Paul Graham's Lisp language
GNU General Public License v3.0
26 stars 1 forks source link

(2:or nil '(a b c)) from the language guide actually fails #438

Closed masak closed 8 months ago

masak commented 10 months ago

This fails:

Language::Bel 0.63 -- darwin.
> (2:or nil '(a b c))
Error: ('unboundb a)
> ((compose 2 or) nil '(a b c))
Error: ('unboundb a)

Which bellanguage.txt says should return b. I don't know who's right here, bellanguage.txt or this implementation. There's obviously something happening here when we apply or as a function.

> (apply or nil '(a b c) nil)
Error: ('unboundb a)

Is this the right result? I don't know. I'd need to re-read the specification and think for a bit. Maybe there's a bug in there.

This works:

> (2 (or nil '(a b c)))
b
masak commented 8 months ago

Is this the right result? I don't know. I'd need to re-read the specification and think for a bit.

Here's what bellanguage.txt has to say on the matter:

Now to continue with our own depth-first traversal of the interpreter, back up in applylit, which we're halfway through. The next clause is for macros. The difference between applying a macro and an ordinary macro call is that when you apply an operator, the arguments have already been evaluated. But you can generate a macro call easily by consing the macro onto the front of a list of quoted arguments. So you just call applym on that. (You could send it to mev, but you know it will end up in applym, so you might as well go straight there.)

The relevant clause in applylit is this one:

(case tag
  prim ..
  clo  ..
  mac  (applym f (map [list 'quote _] args) a s r m)
  cont ..

But I can see from the Perl implementation of this that it doesn't do the [list 'quote _] wrapping:

        elsif ($tag_name eq "mac") {
            my @stack;
            while (!is_nil($args)) {
                push @stack, $self->car($args);
                $args = $self->cdr($args);
            }
            my $quoted_args = SYMBOL_NIL;
            while (@stack) {
                $quoted_args = make_pair(
                    pop(@stack),
                    $quoted_args,
                );
            }

            $self->applym($f, $quoted_args, $aa);
        }

So...

Maybe there's a bug in there.

...this now seems to be the case. Going to re-run the test suite with fix applied.

masak commented 8 months ago

Going to re-run the test suite with fix applied.

Good news: fix applied, all tests still pass (!), and the following works in the REPL:

Language::Bel 0.63 -- darwin.
> (2:or nil '(a b c))
b
> ((compose 2 or) nil '(a b c))
b
> (apply or nil '(a b c) nil)
(a b c)

Going to push up a PR for this now.