There is a great macro in ECL called Clines which allows me to paste C
code into the ECL C output file and then other parts of ECL allow me to
access and call that code once its compiled. What Im trying to do is
write a function which allows me to read a file and puts its contents
into Clines rather than having the C embedded as strings in the Lisp
source. However I am a clueless newbie :-( I have the following function :
(defun clines-from-file (filename)
(with-open-file (stream filename :direction :input)
(loop for line = (read-line stream nil stream)
until (eql line stream) do
(Clines line))))
which I would think does what I want, however it generates an error when
I load the file. ECL says:
The argument to CLINES, LINE, is not a string.
which is confusing because it 'looks' like a string if I change (Clines
line) to (print line).
Can anyone help? I have a feeling that clines-from-file needs to be a
macro like Clines but Im still learning macros.
Best regards, Bunny
xbunny <······@eidosnet.co.uk> writes:
> There is a great macro in ECL called Clines which allows me to paste C
> code into the ECL C output file and then other parts of ECL allow me
> to access and call that code once its compiled. What Im trying to do
> is write a function which allows me to read a file and puts its
> contents into Clines rather than having the C embedded as strings in
> the Lisp source. However I am a clueless newbie :-( I have the
> following function :
>
> (defun clines-from-file (filename)
> (with-open-file (stream filename :direction :input)
> (loop for line = (read-line stream nil stream)
> until (eql line stream) do
> (Clines line))))
>
> which I would think does what I want, however it generates an error
> when I load the file. ECL says:
>
> The argument to CLINES, LINE, is not a string.
>
> which is confusing because it 'looks' like a string if I change
> (Clines line) to (print line).
>
> Can anyone help? I have a feeling that clines-from-file needs to be a
> macro like Clines but Im still learning macros.
The problem is that clines is not a function. It's a macro. It
doesn't evaluate its arguments, and therefore expects a string literal
at macro-expansion time (compilation time), not a variable bound at
run-time to a string value.
You could somewhat code calling eval:
(eval `(clines ,line))
but this would be meaningless if you called clines-form-file at run-time.
You'll have to ensure that it's called at macroexpansion time:
(eval-when (:compile-toplevel)
(defun clines-from-file ...
... (eval `(clines ,line)) ...))
...
(eval-when (:compile-toplevel)
(clines-from-file "some-file.c"))
Perhaps a cleaner way to do this would be to define clines-from-file
as macro itself:
(defmacro clines-from-file (filename)
"Reads the filename at macroexpansion time, and generates a clines
with the contents of the file."
`(clines ,@(with-open-file (stream filename :direction :input)
(loop :for line = (read-line stream nil nil)
:while line :collect line))))
Note that the with-open-file is executed at macroexpansion time, for
the comma. If clines doesn't put each string on a different line,
you'll have to append a newline to each line:
... :collect (format nil "~A~%" line)
--
__Pascal Bourguignon__ http://www.informatimago.com/
Grace personified,
I leap into the window.
I meant to do that.
Pascal Bourguignon wrote:
> (defmacro clines-from-file (filename)
> "Reads the filename at macroexpansion time, and generates a clines
> with the contents of the file."
> `(clines ,@(with-open-file (stream filename :direction :input)
> (loop :for line = (read-line stream nil nil)
> :while line :collect line))))
>
> Note that the with-open-file is executed at macroexpansion time, for
> the comma. If clines doesn't put each string on a different line,
> you'll have to append a newline to each line:
> ... :collect (format nil "~A~%" line)
>
Hey thats great, needed the second bit but it works fine, thank you very
much. Bunny
xbunny <······@eidosnet.co.uk> writes:
> There is a great macro in ECL called Clines which allows me to paste
> C code into the ECL C output file and then other parts of ECL allow
> me to access and call that code once its compiled. What Im trying to
> do is write a function which allows me to read a file and puts its
> contents into Clines rather than having the C embedded as strings in
> the Lisp source. However I am a clueless newbie :-( I have the
> following function :
Too complicated. Try
(clines "#include \"some-file.c\"")
--
Johan Bockgård
Johan Bockgård wrote:
> xbunny <······@eidosnet.co.uk> writes:
>
>
>>There is a great macro in ECL called Clines which allows me to paste
>>C code into the ECL C output file and then other parts of ECL allow
>>me to access and call that code once its compiled. What Im trying to
>>do is write a function which allows me to read a file and puts its
>>contents into Clines rather than having the C embedded as strings in
>>the Lisp source. However I am a clueless newbie :-( I have the
>>following function :
>
>
> Too complicated. Try
>
> (clines "#include \"some-file.c\"")
>
thats just cheating ;-) slapping myself for not thinking of it. Bunny