ccl icon indicating copy to clipboard operation
ccl copied to clipboard

Non conformity: LOAD rewinds the file and LOAD stream doesn't work.

Open informatimago opened this issue 6 years ago • 0 comments

Here are two conformity bugs with LOAD in ccl.

  1. load file-stream loads the whole file instead of reading directly the stream from the current file-position.
  2. load stream doesn't work, while it's explicitely specified by clhs load.

There is a problem with the specification and implementation of CL:LOAD, when passed a stream: The description of LOAD in clhs may seem to be ambiguous, but it seems to me that it tries clearly enough to distinguish the use of a STREAM with a different semantics than the semantics implied when a FILE-STREAM is passed as a pathname designator.

When a FILE-STREAM is given as a pathname designator, then the pathname of the file is recovered with (PATHNAME FILE-STREAM) and used. Therefore the whole file is designated, thru its pathname.

clhs load states that:

filespec --- a STREAM, or a PATHNAME DESIGNATOR.

Since intersection of pathname designator and stream is non-empty, (it's file-stream), there's an apparent ambiguity, which seems to be further confirmed by the description, which contains both:

load loads the file named by filespec into the Lisp environment.

and:

If filespec is a stream, load determines what kind of stream it is and loads directly from the stream.

It seems to me that the intention was that if LOAD is passed a stream (be it a file-stream or some other kind of stream), then the forms would be read directly from that stream.

With a test.lisp file containing:

(PRINT "hello") 
(PRINT "world") 
(FINISH-OUTPUT)
(with-open-file (src "/tmp/test.lisp")
  (read-line src)
  (load src))

will print either both "hello" and "world" or just "world". The later is the prefered interpretation.

ccl interprets as: if the stream is a file-stream , then load the whole file, otherwise read directly from the stream.

Other implementations take the other interpretation: if given a stream, then read directly from the stream, otherwise load a file specified by a pathname designator (that is not a stream).

This second interpretation seems to be to be the intended specification, and to be the more useful interpretation, since this allows the user to easily open a file and read some non lisp header, and then to pass the file-stream with its current file-position to be read and loaded directly.

With the current ccl interpretation, we would have to copy and extract the lisp part of the file to be able to load it entirely, without a non-lisp header. Or, an alternative would be to wrap the file-stream into eg. a concatenated-stream, but this solution which is formally allowed by the specification of LOAD (filespec can be a stream or a pathname designator), signals an error in ccl:

cl-user> (with-open-file (src "/tmp/test.lisp")
           (read-line src)
           (load (make-concatenated-stream src)))
> Debug: The value #<concatenated-stream #x3020033C15FD> is not of the expected type file-stream.

which is a second conformity bug.

| Implementation | Direct stream | Whole file |
|----------------+---------------+------------|
| abcl           | X             |            |
| ccl            |               | X          |
| clisp          | X             |            |
| ecl            | X             |            |
| sbcl           | X             |            |
$ clall '(with-open-file  (*standard-output* "/tmp/test.lisp" 
                           :direction :output
                           :if-does-not-exist
                           :create
                           :if-exists :supersede)
            (prin1 (quote (print "hello")))
            (print (quote (print "world")))
            (print (quote (finish-output))))' \
         '(with-open-file (src "/tmp/test.lisp")
            (read-line src)
            (load src))'




Armed Bear Common Lisp:
--> (FINISH-OUTPUT)


Armed Bear Common Lisp:
"world" 
--> T


Clozure Common Lisp:
--> (FINISH-OUTPUT)


Clozure Common Lisp:
"hello" 
"world" 
--> #<BASIC-FILE-CHARACTER-INPUT-STREAM ("/tmp/test.lisp"/:closed #x3020005F52FD>


CLISP:
--> (FINISH-OUTPUT)


CLISP:
"world" 
--> #<CLOSED INPUT BUFFERED FILE-STREAM CHARACTER #P"/tmp/test.lisp" @3>


ECL:
--> (FINISH-OUTPUT)


ECL:;;; Loading #<input stream "/tmp/test.lisp">

"world" 
--> #<closed input stream "/tmp/test.lisp">


SBCL:
--> (FINISH-OUTPUT)


SBCL:
"world" 
--> T

========================================================================
$
$ clall '(with-open-file  (*standard-output* "/tmp/test.lisp" 
                           :direction :output
                           :if-does-not-exist
                           :create
                           :if-exists :supersede)
            (prin1 (quote (print "hello")))
            (print (quote (print "world")))
            (print (quote (finish-output))))' \
         '(with-open-file (src "/tmp/test.lisp")
            (read-line src)
            (load (make-concatenated-stream src)))'



Armed Bear Common Lisp:
--> (FINISH-OUTPUT)


Armed Bear Common Lisp:
"world" 
--> T


Clozure Common Lisp:
--> (FINISH-OUTPUT)


Clozure Common Lisp:
========================================================================
Implementation: Clozure Common Lisp Version 1.12-dev (v1.12-dev.4) DarwinX8664
    on Darwin 18.2.0
    on x86_64 iMac17,1 (despina.home)

Reading of: "(with-open-file (src \"/tmp/test.lisp\") (read-line src) (load (make-concatenated-stream src)))"
signaled no error

Evaluation of: (WITH-OPEN-FILE (SRC "/tmp/test.lisp") (READ-LINE SRC) (LOAD (MAKE-CONCATENATED-STREAM SRC)))
signaled the following error:
  #<TYPE-ERROR #x3020005F39FD>
  The value #<CONCATENATED-STREAM #x3020005F429D> is not of the expected type FILE-STREAM.
wrote nothing on *ERROR-OUTPUT*
wrote nothing on *TRACE-OUTPUT*
wrote nothing on *STANDARD-OUTPUT*
returned no value


CLISP:
--> (FINISH-OUTPUT)


CLISP:
"world" 
--> #<INPUT CONCATENATED-STREAM>


ECL:
--> (FINISH-OUTPUT)


ECL:;;; Loading #<concatenated stream 00000001102eed20>

"world" 
--> #<concatenated stream 00000001102eed20>


SBCL:
--> (FINISH-OUTPUT)


SBCL:
"world" 
--> T

========================================================================

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

informatimago avatar Jan 31 '19 16:01 informatimago