LIPS-scheme / lips

Scheme based powerful lisp interpreter in JavaScript
https://lips.js.org
Other
414 stars 34 forks source link

Unexpected behaviour with nested backquotes #362

Closed mayerrobert closed 4 months ago

mayerrobert commented 4 months ago

When experimenting with nested backquote edgecases the following forms entered into the REPL at https://lips.js.org/ seem to give wrong results:

(define x '(1 2 3))
(define y '(11 22 33))
(define l '(x y))

(eval ``(,@,@l)) 
; => (1 2 3 11 22 33)
; correct

(eval ``(,@,@l ,@,@l))
; => error message:
Cannot read properties of undefined (reading 'use_dynamic')
Call (stack-trace) to see the stack
Thrown exception is in global exception variable,
use (display exception.stack) to display JS stack trace

; (press F5 to reload LIPS)
(define x '(1 2 3))
(define y '(11 22 33))
(define l '(x y))

(eval ``(,@,@l ,@,@l))
; => (1 2 3 11 22 33)
; IMO this should be (1 2 3 11 22 33 1 2 3 11 22 33)

(eval ``(foo ,@,@l ,@,@l ,@,@l xyxxy))
; => (foo 1 2 3 11 22 33)
; should be (foo 1 2 3 11 22 33 1 2 3 11 22 33 1 2 3 11 22 33 xyxxy)

The "should be" results were verified using Gauche v0.9.10 at https://www.tutorialspoint.com/execute_scheme_online.php

jcubic commented 4 months ago

Thanks for the report. I didn't check quasiquote for quite a while, I was sure it was correct.

I based the implementation on the paper "Quasiquotation in Lisp" by Alan Bawden. I need to investigate what is happening.

jcubic commented 4 months ago

There are two issues here, second call to eval throws exception in REPL and stuff after splice-splice are ignored.

jcubic commented 4 months ago

LIPS returns:

``(,@,@l ,@,@l)
(quasiquote ((unquote-splicing x y)))

It should be:

(quasiquote ((unquote-splicing x y) (unquote-splicing x y)))
jcubic commented 4 months ago

And there is also another bug the x list from your code is mutated to include the y.

(define x '(1 2 3))
(define y '(11 22 33))
(define l '(x y))

(eval ``(,@,@l)) 
; => (1 2 3 11 22 33)
x
(1 2 3 11 22 33)
jcubic commented 4 months ago

So the actual error is StackOverflow because it creates a weird cycle. But there is also an error in display-error function that is thrown when attempting to print stack overflow error.

(print x)
(1 2 3 . #0=(11 22 33 . #0#))
jcubic commented 4 months ago

The issue is fixed on devel branch. It will be released in next beta version