Re: Help needed with macros: Brain turning to jelly



Jeremy Smith <jeremynospam@xxxxxxxxxxxxxx> writes:
[...]
The macro has this input: '(('string buf) ('string val))

Most probably NOT.

QUOTE is used to avoid evaluation of the following form (to take it as
data), and is needed when we want to pass that form as unevaluated
data (literal) to a FUNCTION, because functions receive their
arguments evaluated.

Macros don't receive their arguments evaluated, so you don't need to
QUOTE their argument, usually. If you want to quote the arguments of
a macro, it's a hint you are wanting a function.

'(('string buf) ('string val)) --> (((quote string) buf) ((quote string) val))

(remember, --> means "evaluates to")

I don't understand what these symbols QUOTE have to do in your data
structure. What are you trying to describe with this data? I gather
that you are describing a list of parameters, each with a name and a
type. So just write it:

( ; a list
; of parameters; we'll write each parameter as
( ; a list
; containing the name of the parameter:
buf
; and the type of the parameter:
string)
( ; a list
; containing the name of the parameter:
val
; and the type of the parameter:
string))

((buf string) (val string))

Why would you need to insert symbols named QUOTE in this data structure?

I simply want to take a list of arguments, each a 2-item list, and generate
code like this:

(cffi:defcallback mbox-add-field :pointer ((self :pointer) (args :pointer))
(with-parsetuple-arg 'string buf
(with-parsetuple-arg 'string val
(cffi:foreign-funcall "PyArg_ParseTuple" :pointer args :string
"ss" :pointer buf :pointer val)
(mbox-add-field (pygetarg buf) (pygetarg val))
)
)
(py_buildvalue "s" ""))


You should indent properly your code!!!

(cffi:defcallback mbox-add-field :pointer ((self :pointer) (args :pointer))
(with-parsetuple-arg 'string buf
(with-parsetuple-arg 'string val
(cffi:foreign-funcall "PyArg_ParseTuple"
:pointer args
:string "ss"
:pointer buf
:pointer val)
(mbox-add-field (pygetarg buf) (pygetarg val))))
(py_buildvalue "s" ""))


Now we can see clearly that we have to data structures:

((buf string) (val string))

and:

(cffi:defcallback mbox-add-field :pointer ((self :pointer) (args :pointer))
(with-parsetuple-arg (quote string) buf
(with-parsetuple-arg (quote string) val
(cffi:foreign-funcall "PyArg_ParseTuple"
:pointer args
:string "ss"
:pointer buf
:pointer val)
(mbox-add-field (pygetarg buf) (pygetarg val))))
(py_buildvalue "s" ""))

and assuming that all occurences of the symbols found in the first
tree are to be substituted in the places where they occur in the
second list, we can describe the transformation with the following
patterns:

((<name> <type>)...)

==>

(cffi:defcallback mbox-add-field :pointer ((self :pointer) (args :pointer))
(with-parsetuple-arg (quote <type>) <name>
...
(cffi:foreign-funcall "PyArg_ParseTuple"
:pointer args
:string "ss"
:pointer <name>
...)
(mbox-add-field (pygetarg <name>) ...))
(py_buildvalue "s" ""))


Now, that the problem is specified, can you write a function to do
this transformation between these two data structures?




(defun gen-callback (input)
(loop
:with body = `(progn
(cffi:foreign-funcall "PyArg_ParseTuple"
:pointer args
:string "ss"
,@(loop :for (<name> <ype>) :in input
:nconc `(:pointer ,<name>)))
(mbox-add-field ,@(loop :for (<name> <type>) :in input
:collect `(pygetarg ,<name>))))
:for (<name> <type>) :in (reverse input)
:do (setf body `(with-parsetyple-arg (quote ,<type>) ,<name> ,body))
:finally (return body)))



[90]> (gen-callback '((buf string) (val integer)))
(WITH-PARSETYPLE-ARG 'STRING BUF
(WITH-PARSETYPLE-ARG 'INTEGER VAL
(PROGN
(CFFI:FOREIGN-FUNCALL "PyArg_ParseTuple" :POINTER ARGS :STRING "ss" :POINTER
BUF :POINTER VAL)
(MBOX-ADD-FIELD (PYGETARG BUF) (PYGETARG VAL)))))



Now, if you want to avoid the ' in the gen-callback call, or if you
want to have the data generated be compiled, you can call gen-callback
from a macro:

(defmacro callback (input) (gen-callback input))


[92]> (macroexpand-1 '(callback ((buf string) (val integer))))
(WITH-PARSETYPLE-ARG 'STRING BUF
(WITH-PARSETYPLE-ARG 'INTEGER VAL
(PROGN
(CFFI:FOREIGN-FUNCALL "PyArg_ParseTuple" :POINTER ARGS :STRING "ss" :POINTER
BUF :POINTER VAL)
(MBOX-ADD-FIELD (PYGETARG BUF) (PYGETARG VAL))))) ;
T


I've handled pygetarg, which looks like this:

(defmacro pygetarg(variable)
`(cffi:foreign-string-to-lisp(cffi:mem-ref ,variable :string)))

What has this to do with the wanted macros? Can't you concentrate on
the job at hand?



I couldn't figure out how to generate the code without running it, so I
created a list of the code required and stuck an 'eval' there. There, I
said it.

So you can't figure how to avoid EVAL, therefore you add one more EVAL.
Logical.

Use MACROEXPAND-1 to expand a macro!
(But first, write a function to do the job!)


--
__Pascal Bourguignon__ http://www.informatimago.com/
The rule for today:
Touch my tail, I shred your hand.
New rule tomorrow.
.



Relevant Pages

  • Re: newbie question
    ... avoid memory allocations: the data can be swapped in-place. ... // modifies the contentes of 0-terminated 'buf' as described above ... string swapHalves ...
    (comp.lang.cpp)
  • Re: Why (long)NULL ?
    ... I just came upon this code snippet which parses a string stored in buf ... *buf is a char. ... NULL is a null pointer constant. ... Dan Pop ...
    (comp.lang.c)
  • Re: difference between casting and atol,atoi functions
    ... The first is ill-formed since buf may not be suitably ... character code 255 need not represent a digit ... or a text string ... Note that the size and representation of a signed long can ...
    (comp.lang.c)
  • Re: difference between casting and atol,atoi functions
    ... The first is ill-formed since buf may not be suitably ... character code 255 need not represent a digit ... or a text string ... Note that the size and representation of a signed long can ...
    (alt.comp.lang.learn.c-cpp)
  • Re: GetWindowText - Windows API
    ... GetWindowText has a third parameter, ie the length of the buffer where it ... string @lpClassName, string @WindowName ... local buf, nchars ...
    (microsoft.public.fox.programmer.exchange)