Re: clines-from-file - The argument to CLINES, LINE, is not a string



xbunny <xbunny@xxxxxxxxxxxxxx> 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.
.



Relevant Pages