From: Scott Graham on
Hello

I'm writing a small machine simulator in CL, using tagbody/go to
define the outer-most structure.

Each instruction looks something like this:

:state-instruction4
(some-debugging-code)
(... implementation of instruction using 'go' to make state
transitions ...)

My question is: How can I define a macro to replace that by something
like:

(state instruction4)
(... implementation of instruction ...)

where the 'state' defmacro should return two things: a symbol for the
target of the 'go', and a form of debugging code.

I wasn't able to find a way to return multiple values such that one of
them would be outside of forms. I thought perhaps of wrapping the
whole tagbody in a macro and walking and rewriting all the code
inside, but that seemed overly complex. (And made me feel like I was
missing something obvious when I started to try to write it!)

Thank you for any suggestions. Noob-ishly yours,
Scott
From: Pascal J. Bourguignon on
Scott Graham <scott.cll(a)h4ck3r.net> writes:

> Hello
>
> I'm writing a small machine simulator in CL, using tagbody/go to
> define the outer-most structure.
>
> Each instruction looks something like this:
>
> :state-instruction4
> (some-debugging-code)
> (... implementation of instruction using 'go' to make state
> transitions ...)
>
> My question is: How can I define a macro to replace that by something
> like:
>
> (state instruction4)
> (... implementation of instruction ...)
>
> where the 'state' defmacro should return two things: a symbol for the
> target of the 'go', and a form of debugging code.

This is not possible.

That's what makes lisp macros so powerful: they generate a single
form, therefore they can be expanded blindly in any expression
context, therefore you can do whatever you want _in_ your macros, and
it will work.

If it wasn't the case, lisp macros would be subject to code injection
like any PHP script.


> I wasn't able to find a way to return multiple values such that one of
> them would be outside of forms. I thought perhaps of wrapping the
> whole tagbody in a macro and walking and rewriting all the code
> inside, but that seemed overly complex. (And made me feel like I was
> missing something obvious when I started to try to write it!)


That's the correct way to do it. It's not too hard to do, and thanks
to the above property, it's actually possible: you don't have to know
what each macro expands to to be able to process them safely.


--
__Pascal Bourguignon__ http://www.informatimago.com/
From: Scott Graham on
On May 26, 11:51 pm, p...(a)informatimago.com (Pascal J. Bourguignon)
wrote:
> Scott Graham <scott....(a)h4ck3r.net> writes:
> > I wasn't able to find a way to return multiple values such that one of
> > them would be outside of forms. I thought perhaps of wrapping the
> > whole tagbody in a macro and walking and rewriting all the code
> > inside, but that seemed overly complex. (And made me feel like I was
> > missing something obvious when I started to try to write it!)
>
> That's the correct way to do it.  It's not too hard to do, and thanks
> to the above property, it's actually possible: you don't have to know
> what each macro expands to to be able to process them safely.

OK, thank you. I had made it harder for myself by attempting to rename
the symbol that the 'go' was jumping to. That seems to make it
necessary to understand the structure of "everything" to be able to
find the go's.

If I just walk the top level though, it isn't too complex.

Scott
From: Pascal J. Bourguignon on
Scott Graham <scott.cll(a)h4ck3r.net> writes:

> On May 26, 11:51�pm, p...(a)informatimago.com (Pascal J. Bourguignon)
> wrote:
>> Scott Graham <scott....(a)h4ck3r.net> writes:
>> > I wasn't able to find a way to return multiple values such that one of
>> > them would be outside of forms. I thought perhaps of wrapping the
>> > whole tagbody in a macro and walking and rewriting all the code
>> > inside, but that seemed overly complex. (And made me feel like I was
>> > missing something obvious when I started to try to write it!)
>>
>> That's the correct way to do it. �It's not too hard to do, and thanks
>> to the above property, it's actually possible: you don't have to know
>> what each macro expands to to be able to process them safely.
>
> OK, thank you. I had made it harder for myself by attempting to rename
> the symbol that the 'go' was jumping to. That seems to make it
> necessary to understand the structure of "everything" to be able to
> find the go's.
>
> If I just walk the top level though, it isn't too complex.

Notice that in the top level macro, you can use macrolet and
flet/labels to provide operators to the inferior lexical levels as
deep as needed.

(defmacro state-machine (&body state-clauses)
`(macrolet ((goto (state) `(go ,(generate-state-symbol state))))
,@(expand-state-clauses state-clauses)))


so that you can write:

(state-machine
(state init
...
(cond cond
(goto term))
...)

(state term
...
(cond cond
(goto term))
...))

even if state-machine looks only at the toplevel forms.


--
__Pascal Bourguignon__ http://www.informatimago.com/
From: Scott Graham on
On May 27, 1:06 am, p...(a)informatimago.com (Pascal J. Bourguignon)
wrote:

> > If I just walk the top level though, it isn't too complex.
>
> Notice that in the top level macro, you can use macrolet and
> flet/labels to provide operators to the inferior lexical levels as
> deep as needed.

Aha, of course! Thank you for your patient explanation. :)

Scott
 |  Next  |  Last
Pages: 1 2
Prev: member and defparameter
Next: Common Lisp for Mac OS X