s-expressionists / Eclector

A portable Common Lisp reader that is highly customizable, can recover from errors and can return concrete syntax trees
https://s-expressionists.github.io/Eclector/
BSD 2-Clause "Simplified" License
109 stars 9 forks source link

Issues with #S reader from eclector #63

Closed kpoeck closed 4 years ago

kpoeck commented 4 years ago

I just changed clasp to also use eclectors #S reader. This allows

The details of the tests are here:

(defstruct syntax-test-struct-1
    a b c)

;;; SYNTAX.SHARP-S.3
(let ((v (read-from-string "#s(syntax-test-struct-1 \"A\" x)")))
    (values
     (not (not (typep v 'syntax-test-struct-1)))
     (syntax-test-struct-1-a v)
     (syntax-test-struct-1-b v)
     (syntax-test-struct-1-c v)))

(let ((v (read-from-string "#S(syntax-test-struct-1 #\\A x)")))
    (values
     (not (not (typep v 'syntax-test-struct-1)))
     (syntax-test-struct-1-a v)
     (syntax-test-struct-1-b v)
     (syntax-test-struct-1-c v)))

(let ((v (read-from-string "#s(syntax-test-struct-1 a x c y b z :a :bad :b bad2 :c bad3)")))
    (values
     (not (not (typep v 'syntax-test-struct-1)))
     (syntax-test-struct-1-a v)
     (syntax-test-struct-1-b v)
     (syntax-test-struct-1-c v)))

(let ((v (read-from-string "#S(syntax-test-struct-1 #:a x #:c y #:b z)")))
    (values
     (not (not (typep v 'syntax-test-struct-1)))
     (syntax-test-struct-1-a v)
     (syntax-test-struct-1-b v)
     (syntax-test-struct-1-c v)))
kpoeck commented 4 years ago

sbcl basically says: the use of non-keywords as slot specifiers is deprecated, but executes the code

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (defstruct syntax-test-struct-1
    a b c)
SYNTAX-TEST-STRUCT-1
* (let ((v (read-from-string "#s(syntax-test-struct-1 \"A\" x)")))
    (values
     (not (not (typep v 'syntax-test-struct-1)))
     (syntax-test-struct-1-a v)
     (syntax-test-struct-1-b v)
     (syntax-test-struct-1-c v)))
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: "A".
See also:
  The ANSI Standard, Section 2.4.8.13
T
X
NIL
NIL
* (let ((v (read-from-string "#S(syntax-test-struct-1 #\\A x)")))
    (values
     (not (not (typep v 'syntax-test-struct-1)))
     (syntax-test-struct-1-a v)
     (syntax-test-struct-1-b v)
     (syntax-test-struct-1-c v)))
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: #\A.
See also:
  The ANSI Standard, Section 2.4.8.13
T
X
NIL
NIL
* (let ((v (read-from-string "#s(syntax-test-struct-1 a x c y b z :a :bad :b bad2 :c bad3)")))
    (values
     (not (not (typep v 'syntax-test-struct-1)))
     (syntax-test-struct-1-a v)
     (syntax-test-struct-1-b v)
     (syntax-test-struct-1-c v)))
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: A.
See also:
  The ANSI Standard, Section 2.4.8.13
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: A.
See also:
  The ANSI Standard, Section 2.4.8.13
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: A.
See also:
  The ANSI Standard, Section 2.4.8.13
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: A.
See also:
  The ANSI Standard, Section 2.4.8.13
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: A.
See also:
  The ANSI Standard, Section 2.4.8.13
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: A.
See also:
  The ANSI Standard, Section 2.4.8.13
T
X
Z
Y
* (let ((v (read-from-string "#S(syntax-test-struct-1 #:a x #:c y #:b z)")))
    (values
     (not (not (typep v 'syntax-test-struct-1)))
     (syntax-test-struct-1-a v)
     (syntax-test-struct-1-b v)
     (syntax-test-struct-1-c v)))
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: #:A.
See also:
  The ANSI Standard, Section 2.4.8.13
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: #:A.
See also:
  The ANSI Standard, Section 2.4.8.13
WARNING:
   in #S SYNTAX-TEST-STRUCT-1, the use of non-keywords as slot specifiers is deprecated: #:A.
See also:
  The ANSI Standard, Section 2.4.8.13
T
X
Z
Y
kpoeck commented 4 years ago

2.4.8.13 says the following, so i believe that eclector is wrong here:

2.4.8.13 Sharpsign S

s(name slot1 value1 slot2 value2 ...) denotes a structure. This is valid only if name is the name of a structure type already defined by defstruct and if the structure type has a standard constructor function. Let cm stand for the name of this constructor function; then this syntax is equivalent to

.(cm keyword1 'value1 keyword2 'value2 ...)

where each keywordj is the result of computing

(intern (string slotj) (find-package 'keyword)) The net effect is that the constructor function is called with the specified slots having the specified values. (This coercion feature is deprecated; in the future, keyword names will be taken in the package they are read in, so symbols that are actually in the keyword package should be used if that is what is desired.)

Whatever object the constructor function returns is returned by the #S syntax.

For information on how the Lisp printer prints structures, see Section 22.1.3.12 Printing Structures.

kpoeck commented 4 years ago

Fix looks easy, if you agree to the interpretation, I'll do a pull request

scymtym commented 4 years ago

In a branch, I had already changed the reader macro function to accept string designators. As I mentioned, I want to complete other changes first. However, I can add the commit in question to the wip-reader-implementation-documentation branch for the time being.

kpoeck commented 4 years ago

This does not really solve the issue. The test for alexandria:string-designator, but the value is no transformed to a keyword. As a consequence, make-structure-instance is called with (MAKE-STRUCTURE SYNTAX-TEST-STRUCT-1 ("A" X)). I'd expect the "A" to be a ":a"

scymtym commented 4 years ago

I try to leave handling of symbols and conversion to symbols to the client where it makes sense.

For example, some clients do not represent symbols as objects of type cl:symbol so doing the conversion in the reader macro is not possible in general.

In this particular case, the client may also want handle the deprecated ways of designating slots in a special manner such as signaling a warning (like SBCL does). If the slot designators were coerced to keywords in the reader macro (or around the make-structure-instance method invocation), the client would have no way of knowing whether a warning should be signaled.

In summary, the client is expected to do the (intern (string slotj) (find-package 'keyword)) part itself. I should change the documentation to state this clearly.

kpoeck commented 4 years ago

Fair point, so please document

scymtym commented 4 years ago

Done.