gregspurrier / shen-ruby

ShenRuby is a port of the Shen programming language to Ruby
Other
76 stars 7 forks source link

Exception raised by Shen-YACC #13

Open gregspurrier opened 9 years ago

gregspurrier commented 9 years ago
Shen, copyright (C) 2010-2015 Mark Tarver
www.shenlanguage.org, Shen 17
running under Ruby, implementation: ruby 2.2.0
port 0.13.0 ported by Greg Spurrier

(0-) (defcc <a> a := [/.];)
undefined method `hd' for nil:NilClass

This works in both the SBCL and chibi-scheme ports. The latter is important because, like ShenRuby, chibi-shen raises an error when hd is applied to the empty list. This suggests this is a ShenRuby bug rather than a case of Shen accidentally relying on (hd []) returning [] as it does in the CL ports.

tizoc commented 9 years ago

Do you treat symbols that end in . differently? because thats when it fails for me here.

Also, it fails inside shen.elim-def:

faust ~/p/s/shen-ruby git:master✓ > ./bin/srrepl 
Loading.... Completed in 4.02 seconds.

Shen, copyright (C) 2010-2015 Mark Tarver
www.shenlanguage.org, Shen 17
running under Ruby, implementation: ruby 2.0.0
port 0.13.0 ported by Greg Spurrier

(0-) (read-from-string "(defcc <a> a := [/.];)")
[[defcc <a> a := [cons /. []] ;]]

(1-) (shen.elim-def (hd (read-from-string "(defcc <a> a := [/.];)")))
undefined method `hd' for nil:NilClass

(2-) (shen.elim-def [/.])
[/.]

(3-) (shen.elim-def (hd (read-from-string "(defcc <a> a := [a.];)")))
undefined method `hd' for nil:NilClass

(4-) (shen.elim-def (hd (read-from-string "(defcc <a> a := [/.a];)")))
[defun <a> [V583] [if [and [cons? [hd V583]] [= a [hd [hd V583]]]] [shen.pair [hd [shen.pair [tl [hd V583]] [shen.hdtl V583]]] [cons /.a []]] [fail]]]
tizoc commented 9 years ago

Ok, I know why it fails. It doesn't break on chibi-shen because I use my own overwritten version of shen.grammar_symbol?.

This is a bug in Shen, I would suggest that for now you use your own custom version of shen.grammar_symbol?.

The problem (in yacc.shen):

(define grammar_symbol?
  S -> (and (symbol? S) 
            (let Cs (strip-pathname (explode S)) 
                (and (= (hd Cs) "<") (= (hd (reverse Cs)) ">")))))                          

(define strip-pathname
  Cs -> Cs      where (not (element? "." Cs))
  [_ | Cs] -> (strip-pathname Cs))

strip-pathname doesn't take into account that some symbols may end with . and still considers those as namespaced, this breaks for /.. In that case it returns an empty list and thats why it ends doing (hd []).

I'm going to report this to Mark using the bug submission form.

For reference, here is the super ugly version I'm using in chibi-shen:

(define (scm.shen-grammar_symbol? val)
  (and (symbol? val)
       (let* ((s (symbol->string val))
              (end (string-cursor-end s))
              (start (string-cursor-start s))
              (c (string-cursor-prev s end)))
         (and (equal? #\> (string-cursor-ref s c))
              (or (equal? #\< (string-cursor-ref s start))
                  (let loop ((c (string-cursor-prev s c)))
                    (if (or (string-cursor<? c start)
                            (equal? #\. (string-cursor-ref s c)))
                        (equal? #\< (string-cursor-ref s (string-cursor-next s c)))
                        (loop (string-cursor-prev s c)))))))))
gregspurrier commented 9 years ago

Oh. Interesting. So my initial suspicion about it being the behavior of (hd []) was correct after all. Thanks for debugging this and reporting it to Mark.

For now I can work around it with (defcc <a> a := [(intern "/.")];).

tizoc commented 9 years ago

Ok, good. If you decide to override Shen's code my suggestion is to re-use shen.grammar_symbol? as-is, with an extra check for /.. Somthing like:

(define grammar_symbol?
  S -> (and (symbol? S) (not (= S /.))
            (let Cs (strip-pathname (explode S))
                (and (= (hd Cs) "<") (= (hd (reverse Cs)) ">")))))