Corner case 地獄その2

…と思ったけど (もっと大きな test の一部だったので)、どうもただの gauche の…バグ? でもないのか。

やっぱりバグと判断したので Wiliki に移動。固定 link 機能が欲しいな。

jun@debian /dvl/gauche/current
$ gosh
gosh> (let-syntax
          ((macro (syntax-rules ()
                    ((_ . _) 'mismatch))))
        (list (macro 0 1 2 . 3)))
*** ERROR: Compile Error: proper list required for function application: (macro 0 1 2 . 3)
"(stdin)":1:(let-syntax ((macro (syntax-rules () ...

Stack Trace:
_______________________________________

R5RS には ( ...) と書いてあるので、一応これが正当な動作らしい。
しかし guile, STklos, Scheme48 は普通に展開してくれる。うーむ。大体 R5RS の synopsis てちょこちょこボロがあるしな…

とか思ってたがやっぱりバグらしい。(list ) をとると普通に受け付けるようになる。

gosh> (let-syntax
          ((macro (syntax-rules ()
                    ((_ . _) 'mismatch))))
        (macro 0 1 2 . 3))
mismatch

そんで patch (おお、今回は瞬殺だ)。

--- compile.scm	2005-12-24 18:20:50.000000000 -0800
+++ compile.scm.mutilated	2006-01-20 19:20:34.000000000 -0800
@@ -1401,21 +1401,23 @@
   ;; main body of pass1
   (cond
     ((pair? program)                    ; (op . args)
-     (unless (list? program)
-       (error "proper list required for function application:" program))
-     (if (variable? (car program))
-       (let1 head (cenv-lookup cenv (car program) SYNTAX)
-         (cond
-          ((identifier? head)
-           (pass1/global-call head))
-          ((lvar? head)
-           (pass1/call program ($lref head) (cdr program) cenv))
-          ((macro? head) ;; local macro
-           (pass1 (call-macro-expander head program (cenv-frames cenv)) cenv))
-          (else
-           (error "[internal] unknown resolution of head:" head))))
-       (pass1/call program (pass1 (car program) (cenv-sans-name cenv))
-                   (cdr program) cenv)))
+     (let1 head (if (variable? (car program))
+                    (cenv-lookup cenv (car program) SYNTAX)
+                    #f)
+       (cond
+        ((macro? head) ;; local macro
+         (pass1 (call-macro-expander head program (cenv-frames cenv)) cenv))
+        ((not (list? program))
+         (error "proper list required for function application:" program))
+        ((identifier? head)
+         (pass1/global-call head))
+        ((lvar? head)
+         (pass1/call program ($lref head) (cdr program) cenv))
+        ((not head)
+         (pass1/call program (pass1 (car program) (cenv-sans-name cenv))
+                     (cdr program) cenv))
+        (else
+         (error "[internal] unknown resolution of head:" head)))))
     ((variable? program)                 ; variable reference
      (let1 r (cenv-lookup cenv program LEXICAL)
        (cond ((lvar? r) ($lref r))

#f とかちょっと苦しい。あと多分 compile time 増加。