Prev: member and defparameter
Next: Common Lisp for Mac OS X
From: Scott Graham on 27 May 2010 01:48 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 27 May 2010 02:51 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 27 May 2010 03:41 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 27 May 2010 04:06 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 27 May 2010 04:14
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 |