From: sds on 12 Aug 2010 17:14 http://www.lispworks.com/documentation/HyperSpec/Body/f_cmp_fi.htm compile-file input-file &key output-file verbose print external-format output-file---a pathname designator. output-file can be used to specify an output pathname; the actual pathname of the compiled file to which compiled code will be output is computed as if by calling compile-file-pathname. this seems to suggest that if output-stream is an open file stream, its content is overwritten, not appended to. however, both clisp and sbcl treat an open file stream given as the output-file as the stream where the binary is written: (let* ((l "path-tst-compile-file-pathname.lisp") (f (compile-file-pathname l))) (with-open-file (ls l :direction :output :if-exists :supersede) (format ls "(defun f () t)~%")) (list (with-open-file (fs f :direction :output :if-exists :supersede) (format fs #1="first line") (terpri fs) (compile-file l :output-file fs) (prin1-to-string fs)) (with-open-file (fs f :direction :input) (string= #1# (read-line fs))))) ==> (T T) Is this the "correct" (most useful? required by the standard?) behavior? Thanks. Sam.
From: Joshua Taylor on 12 Aug 2010 18:57 On 2010.08.12 5:14 PM, sds wrote: > http://www.lispworks.com/documentation/HyperSpec/Body/f_cmp_fi.htm > compile-file input-file &key output-file verbose print external-format > output-file---a pathname designator. > output-file can be used to specify an output pathname; the actual > pathname of the compiled file to which compiled code will be output is > computed as if by calling compile-file-pathname. > > this seems to suggest that if output-stream is an open file stream, > its content is overwritten, not appended to. > > however, both clisp and sbcl treat an open file stream given as the > output-file as the stream where the binary is written: > > (let* ((l "path-tst-compile-file-pathname.lisp") > (f (compile-file-pathname l))) > (with-open-file (ls l :direction :output :if-exists :supersede) > (format ls "(defun f () t)~%")) > (list > (with-open-file (fs f :direction :output :if-exists :supersede) > (format fs #1="first line") (terpri fs) > (compile-file l :output-file fs) > (prin1-to-string fs)) > (with-open-file (fs f :direction :input) > (string= #1# (read-line fs))))) Output-file is a pathname designator. If you provide a file-stream as output-file, the designated pathname is that of the file. I wouldn't expect compile-file to do anything at all with the stream except find out what pathname it designates, and then to do something with the associated file. You're opening a file-stream A, writing some things to it, then calling a function that will open a file-stream B, write some things to it, close B, return, and then you're writing more things to A. I think any issues you're observing are probably related to that, rather than anything specific to COMPILE-FILE. It seems like it would be similar to the following: (defun test (&optional (pathname #p"~/testing" pathnamep)) (with-open-file (out pathname :direction :output :if-exists :supersede :if-does-not-exist :create) (write-line "hello" out) (if pathnamep (write-line "recursive call" out) (test (pathname pathname))) (write-line "goodbye" out))) After running (test) (in LispWorks 6.0.1), the contents of ~/testing are: hello goodbye e call goodbye I don't expect that that's a portable result, but it shows some of the issues with having multiple open output file-streams associated with a file at a given time. //JT
From: sds on 13 Aug 2010 12:23 On Aug 12, 6:57 pm, Joshua Taylor <tay...(a)cs.rpi.edu> wrote: > On 2010.08.12 5:14 PM, sds wrote: > > >http://www.lispworks.com/documentation/HyperSpec/Body/f_cmp_fi.htm > > compile-file input-file &key output-file verbose print external-format > > output-file---a pathname designator. > > output-file can be used to specify an output pathname; the actual > > pathname of the compiled file to which compiled code will be output is > > computed as if by calling compile-file-pathname. > > > this seems to suggest that if output-stream is an open file stream, > > its content is overwritten, not appended to. > > > however, both clisp and sbcl treat an open file stream given as the > > output-file as the stream where the binary is written: > > > (let* ((l "path-tst-compile-file-pathname.lisp") > > (f (compile-file-pathname l))) > > (with-open-file (ls l :direction :output :if-exists :supersede) > > (format ls "(defun f () t)~%")) > > (list > > (with-open-file (fs f :direction :output :if-exists :supersede) > > (format fs #1="first line") (terpri fs) > > (compile-file l :output-file fs) > > (open-stream-p fs)) > > (with-open-file (fs f :direction :input) > > (string= #1# (read-line fs))))) clisp and abcl return (T T) gcl lacks open-stream-p but, apparently, would return (T NIL) if it had it. what about other lisps? > Output-file is a pathname designator. If you provide a file-stream as > output-file, the designated pathname is that of the file. I wouldn't > expect compile-file to do anything at all with the stream except find > out what pathname it designates, and then to do something with the > associated file. Yes, this is my understanding of the standard too. However, it appears that _both_ SBCL and CLISP who have very different origins but both "purport to conform" to the ANSI standard (and both are known to take a huge effort to actually comform) interpret an open stream output-file argument the _same_ way which is _different_ from what you and I expect: namely, they just write to the stream. I.e., (compile-file f :output-file o) == (with-open-file (s o :direction :output) (compile-file f :output-file s)) So, I was wondering if this behavior is somehow more useful? natural? than my interpretation of the standard. Or maybe this behavior is actually what the standard demands? :-) Have anyone here ever passed an open stream as the :output-file argument to compile-file on purpose? > I don't expect that that's a portable result, but it shows some of the > issues with having multiple open output file-streams associated with a > file at a given time. CLISP can actually catch attempts to do that and (if you so desire) prevent it. http://clisp.cons.org/impnotes/open.html#reopen Sam.
From: Joshua Taylor on 13 Aug 2010 14:27 On 2010.08.13 12:23 PM, sds wrote: > On Aug 12, 6:57 pm, Joshua Taylor <tay...(a)cs.rpi.edu> wrote: >> On 2010.08.12 5:14 PM, sds wrote: >> >>> http://www.lispworks.com/documentation/HyperSpec/Body/f_cmp_fi.htm >>> compile-file input-file &key output-file verbose print external-format >>> output-file---a pathname designator. >>> output-file can be used to specify an output pathname; the actual >>> pathname of the compiled file to which compiled code will be output is >>> computed as if by calling compile-file-pathname. >> >>> this seems to suggest that if output-stream is an open file stream, >>> its content is overwritten, not appended to. >> >>> however, both clisp and sbcl treat an open file stream given as the >>> output-file as the stream where the binary is written: >> >>> (let* ((l "path-tst-compile-file-pathname.lisp") >>> (f (compile-file-pathname l))) >>> (with-open-file (ls l :direction :output :if-exists :supersede) >>> (format ls "(defun f () t)~%")) >>> (list >>> (with-open-file (fs f :direction :output :if-exists :supersede) >>> (format fs #1="first line") (terpri fs) >>> (compile-file l :output-file fs) >>> (open-stream-p fs)) >>> (with-open-file (fs f :direction :input) >>> (string= #1# (read-line fs))))) > > clisp and abcl return (T T) > gcl lacks open-stream-p but, apparently, would return (T NIL) if it > had it. > what about other lisps? Interestingly, look what happens if a (FORCE-OUTPUT fs) is added (in SBCL, at least, on OS X): (let* ((l "path-tst-compile-file-pathname.lisp") (f (compile-file-pathname l))) (with-open-file (ls l :direction :output :if-exists :supersede) (format ls "(defun f () t)~%")) (list (with-open-file (fs f :direction :output :if-exists :supersede) (format fs #1="first line") (terpri fs) (force-output fs) (compile-file l :output-file fs) (open-stream-p fs)) (with-open-file (fs f :direction :input) (string= #1# (read-line fs))))) => (T NIL) I don't think SBCL is using the stream directly. I'm not an SBCL hacker, but I think the relevant portions of the source (1.0.30) are: (defun sb!xc:compile-file (input-file &key ... (output-file (cfp-output-file-default input-file)) ... ) ... (let* (... (output-file-name nil) ... ) ... (when output-file (setq output-file-name (sb!xc:compile-file-pathname input-file :output-file output-file)) (setq fasl-output (open-fasl-output output-file-name (namestring input-pathname)))) ...)) The value of cfp-output-file-default is produced by make-pathname which returns a pathname: (defun cfp-output-file-default (input-file) (let* ((defaults (merge-pathnames input-file *default-pathname-defaults*)) (retyped (make-pathname :type *fasl-file-type* :defaults defaults))) retyped)) And sb!xc:compile-file-pathname returns either a value from cft-output-file-default or merge-pathnames, and each of those return a pathname: (defun sb!xc:compile-file-pathname (input-file &key (output-file nil output-file-p) &allow-other-keys) #!+sb-doc "Return a pathname describing what file COMPILE-FILE would write to given these arguments." (if output-file-p (merge-pathnames output-file (cfp-output-file-default input-file)) (cfp-output-file-default input-file))) It doesn't look like SBCL is using the stream directly, but rather getting a pathname and opening the file again. //JT
From: Joshua Taylor on 13 Aug 2010 15:31 On 2010.08.13 2:27 PM, Joshua Taylor wrote: > On 2010.08.13 12:23 PM, sds wrote: >> On Aug 12, 6:57 pm, Joshua Taylor <tay...(a)cs.rpi.edu> wrote: >>> On 2010.08.12 5:14 PM, sds wrote: >>> >>>> http://www.lispworks.com/documentation/HyperSpec/Body/f_cmp_fi.htm >>>> compile-file input-file &key output-file verbose print external-format >>>> output-file---a pathname designator. >>>> output-file can be used to specify an output pathname; the actual >>>> pathname of the compiled file to which compiled code will be output is >>>> computed as if by calling compile-file-pathname. >>> >>>> this seems to suggest that if output-stream is an open file stream, >>>> its content is overwritten, not appended to. >>> >>>> however, both clisp and sbcl treat an open file stream given as the >>>> output-file as the stream where the binary is written: >>> >>>> (let* ((l "path-tst-compile-file-pathname.lisp") >>>> (f (compile-file-pathname l))) >>>> (with-open-file (ls l :direction :output :if-exists :supersede) >>>> (format ls "(defun f () t)~%")) >>>> (list >>>> (with-open-file (fs f :direction :output :if-exists :supersede) >>>> (format fs #1="first line") (terpri fs) >>>> (compile-file l :output-file fs) >>>> (open-stream-p fs)) >>>> (with-open-file (fs f :direction :input) >>>> (string= #1# (read-line fs))))) >> >> clisp and abcl return (T T) >> gcl lacks open-stream-p but, apparently, would return (T NIL) if it >> had it. >> what about other lisps? > > Interestingly, look what happens if a (FORCE-OUTPUT fs) is added (in > SBCL, at least, on OS X): .... I decided to take a look at what CLISP does too. (defun compile-file (file &key (output-file 'T) listing ((:warnings *compile-warnings*) *compile-warnings*) ((:verbose *compile-verbose*) *compile-verbose*) ((:print *compile-print*) *compile-print*) (external-format :default) &aux liboutput-file (*coutput-file* nil) input-file (*compile-file-directory* (if (eq t output-file) nil (make-pathname :name nil :type nil :defaults output-file))) (new-output-stream nil) (new-listing-stream nil)) (multiple-value-setq (output-file input-file) (compile-file-pathname-helper file output-file)) .... (unwind-protect (let* (... (*fasoutput-stream* ; a Stream or NIL (if new-output-stream (open output-file :direction :output) (if (streamp output-file) output-file nil))) ...) It looks like CLISP (2.49) will actually return the stream: ;; Common part of COMPILE-FILE and COMPILE-FILE-PATHNAME. ;; Returns two values: ;; 1. the output file (pathname or stream or NIL), ;; 2. the input file pathname. (defun compile-file-pathname-helper (file output-file) (let ((input-file (or (and (not (logical-pathname-p (pathname file))) (first (search-file file *source-file-types*))) (merge-pathnames file #.(make-pathname :type "lisp"))))) (values (if (or (null output-file) (and (streamp output-file) (open-stream-p output-file) (output-stream-p output-file))) output-file ...) ...) I'm not a CLISP maintainer either, but it looks like passing an output stream to COMPILE-FILE will cause the fasl to be written directly to the stream (without opening up another output-stream associated with the file). //JT
|
Next
|
Last
Pages: 1 2 Prev: AVG Internet Security 9.0 key till 2018 Next: Richard P Gabriel's home page |