From: dc
Subject: Macros calling macros
Date: 
Message-ID: <8f5fe487-9c3a-4b88-8d0c-092d0733b1a8@v22g2000pro.googlegroups.com>
Hi,

I have written a couple of small macros that does some text output and
needs to indent. It kind of looks like the following :-

(defmacro with-indent (&rest args)
  `(combine
     (indent+) ,@args (indent-)))

(defmacro gen-block (block-type block-name &rest args)
  `(combine
      (gen-begin block-type block-name)
      (with-indent ,@args)
      (gen-end block-type)))

; indent+/- just alter a variable which is indent level. gen-begin/end
make "begin/end blah" strings.

On the surface of it, this works fine. I can get gen-block to make
begin/end statements for home made scripting languages (which is what
this is for) by doing

(gen-block "block" "test block"
   (print "first line") (print "second line"))

...and getting

block "test block"
  print "first line"
  print "second line"
end block

However, if I do

(gen-block "block" "outer block" (gen-block "block" "inner block")
(print "hello"))

I get

block "outer block"
  block "inner block"     ; Everything is okay so far.
    print "hello"
    end block                ; Here is the problem.
end block

The indent level gets set and passed on to the next macro expansion
and I thought perhaps someone here might know of a way of getting the
desired result which would allow for unlimited nesting without mucking
up the trailing indents.

I'm wanting to use macros because I'll be transforming the statements
passed in.

Any ideas appreciated (would generating a closure with it's own level
around each block help?)

Cheers
DC

From: budden
Subject: Re: Macros calling macros
Date: 
Message-ID: <48c1d66a-e672-4dc4-a1ed-4300c25b4953@i18g2000prf.googlegroups.com>
Hi, dc
 I used to do something similar, and had a similar error.
I thing this is not related to macros. Anyway, you might use
(macroexpand-1 'your-code) too see the macroexpanded code.
 It looks like a error in a logic. E.g., sometimes you're swapping
generation of indentation and generation of a newline (this was in my
case). It is very easy to err this way.
From: Alex Mizrahi
Subject: Re: Macros calling macros
Date: 
Message-ID: <491016ed$0$90268$14726298@news.sunsite.dk>
 d> Any ideas appreciated (would generating a closure with it's own level
 d> around each block help?)

i guess your problem is that you're using variable *indent* in your macros.
do not do that -- use it only at run time, and it will be fine.

it is not a case where you need macros calling macros -- macros can
just do syntatic conversion for you, but you can do all computatations (such 
as computing indent amount)
at runtime with ordinary functions. 
From: William James
Subject: Re: Macros calling macros
Date: 
Message-ID: <d4d87fe7-ecdb-4d76-8413-e8dacde2c13d@j40g2000prh.googlegroups.com>
On Nov 4, 12:24 am, dc <··············@gmail.com> wrote:
> Hi,
>
> I have written a couple of small macros that does some text output and
> needs to indent. It kind of looks like the following :-
>
> (defmacro with-indent (&rest args)
>   `(combine
>      (indent+) ,@args (indent-)))
>
> (defmacro gen-block (block-type block-name &rest args)
>   `(combine
>       (gen-begin block-type block-name)
>       (with-indent ,@args)
>       (gen-end block-type)))
>
> ; indent+/- just alter a variable which is indent level. gen-begin/end
> make "begin/end blah" strings.
>
> On the surface of it, this works fine. I can get gen-block to make
> begin/end statements for home made scripting languages (which is what
> this is for) by doing
>
> (gen-block "block" "test block"
>    (print "first line") (print "second line"))
>
> ...and getting
>
> block "test block"
>   print "first line"
>   print "second line"
> end block
>
> However, if I do
>
> (gen-block "block" "outer block" (gen-block "block" "inner block")
> (print "hello"))
>
> I get
>
> block "outer block"
>   block "inner block"     ; Everything is okay so far.
>     print "hello"
>     end block                ; Here is the problem.
> end block
>
> The indent level gets set and passed on to the next macro expansion
> and I thought perhaps someone here might know of a way of getting the
> desired result which would allow for unlimited nesting without mucking
> up the trailing indents.

Macros aren't needed.  A single function
does it all.

Ruby:

def gen_block type, name, *stuff
  [ "#{type} \"#{name}\"",
    stuff.flatten.map{|x| "  #{x}"},
  "end #{type}" ].flatten
end

puts gen_block("block", "outer block",'print "hello"')

puts gen_block("block", "outer block",
  gen_block("block","inner block",'print "hello"'))

--- output ---
block "outer block"
  print "hello"
end block
block "outer block"
  block "inner block"
    print "hello"
  end block
end block
From: Raymond Wiker
Subject: Re: Macros calling macros
Date: 
Message-ID: <m263n3xl0e.fsf@RAWMBP.local>
William James <·········@yahoo.com> writes:

> On Nov 4, 12:24�am, dc <··············@gmail.com> wrote:
>> Hi,
>>
>> I have written a couple of small macros that does some text output and
>> needs to indent. It kind of looks like the following :-
>>
>> (defmacro with-indent (&rest args)
>> � `(combine
>> � � �(indent+) ,@args (indent-)))
>>
>> (defmacro gen-block (block-type block-name &rest args)
>> � `(combine
>> � � � (gen-begin block-type block-name)
>> � � � (with-indent ,@args)
>> � � � (gen-end block-type)))
>>
>> ; indent+/- just alter a variable which is indent level. gen-begin/end
>> make "begin/end blah" strings.
>>
>> On the surface of it, this works fine. I can get gen-block to make
>> begin/end statements for home made scripting languages (which is what
>> this is for) by doing
>>
>> (gen-block "block" "test block"
>> � �(print "first line") (print "second line"))
>>
>> ...and getting
>>
>> block "test block"
>> � print "first line"
>> � print "second line"
>> end block
>>
>> However, if I do
>>
>> (gen-block "block" "outer block" (gen-block "block" "inner block")
>> (print "hello"))
>>
>> I get
>>
>> block "outer block"
>> � block "inner block" � � ; Everything is okay so far.
>> � � print "hello"
>> � � end block � � � � � � � �; Here is the problem.
>> end block
>>
>> The indent level gets set and passed on to the next macro expansion
>> and I thought perhaps someone here might know of a way of getting the
>> desired result which would allow for unlimited nesting without mucking
>> up the trailing indents.
>
> Macros aren't needed.  A single function
> does it all.
>
> Ruby:
>
> def gen_block type, name, *stuff
>   [ "#{type} \"#{name}\"",
>     stuff.flatten.map{|x| "  #{x}"},
>   "end #{type}" ].flatten
> end
>
> puts gen_block("block", "outer block",'print "hello"')
>
> puts gen_block("block", "outer block",
>   gen_block("block","inner block",'print "hello"'))
>
> --- output ---
> block "outer block"
>   print "hello"
> end block
> block "outer block"
>   block "inner block"
>     print "hello"
>   end block
> end block

	Hey, Einstein... you may not have noticed, but this is
comp.lang.lisp, so posting Ruby code is not likely to help the OP. 
From: Tamas K Papp
Subject: Re: Macros calling macros
Date: 
Message-ID: <6nbs5eFkr5h4U1@mid.individual.net>
On Tue, 04 Nov 2008 22:02:25 +0100, Raymond Wiker wrote:

>>   block "inner block"
>>     print "hello"
>>   end block
>> end block
> 
> 	Hey, Einstein... you may not have noticed, but this is
> comp.lang.lisp, so posting Ruby code is not likely to help the OP.

Hey Heisenberg,

Most of us figured out how to filter him and his ilk out using our 
newsreaders, so we would not see a single post from them.  But some 
genius always has to reply to these idiots.

Tamas
From: Andrew Main
Subject: Re: Macros calling macros
Date: 
Message-ID: <4911622a$1@clear.net.nz>
Raymond Wiker wrote:

> 	Hey, Einstein... you may not have noticed, but this is
> comp.lang.lisp, so posting Ruby code is not likely to help the OP. 

You assume that William James is trying to help people. You're not the first 
person to tell him to stop with the ruby code in comp.lang.lisp
From: Kaz Kylheku
Subject: Re: Macros calling macros
Date: 
Message-ID: <20081105153654.113@gmail.com>
On 2008-11-04, William James <·········@yahoo.com> wrote:
> On Nov 4, 12:24�am, dc <··············@gmail.com> wrote:
>> (gen-block "block" "outer block" (gen-block "block" "inner block")
>> (print "hello"))
>>
>> I get
>>
>> block "outer block"
>> � block "inner block" � � ; Everything is okay so far.
>> � � print "hello"
>> � � end block � � � � � � � �; Here is the problem.
>> end block
>>
>> The indent level gets set and passed on to the next macro expansion
>> and I thought perhaps someone here might know of a way of getting the
>> desired result which would allow for unlimited nesting without mucking
>> up the trailing indents.
>
> Macros aren't needed.  A single function
> does it all.
>
> Ruby:
>
> def gen_block type, name, *stuff
>   [ "#{type} \"#{name}\"",
>     stuff.flatten.map{|x| "  #{x}"},
>   "end #{type}" ].flatten
> end
>
> puts gen_block("block", "outer block",'print "hello"')

But the input to the Lisp macro is this code:

  (gen-block "block" "outer block" (print "hello"))

This transliterates to Ruby like this:

  gen_block("block", "outer block", print("hello"))

Part of the problem is to take syntax like   print("hello")  expression and
destructure it by pulling out the print and "hello" atoms.  But in your Ruby,
you have cheated: you have 'print "hello"' as a string literal.

Can you make it work using the Ruby expression?

Here are two test cases:

  expression:

    gen_block("block", "outer block", print("hello"))

  output:

    block "block"
      print "hello"
    end block


  expression:

    gen_block("block", "outer block", 
              gen_block("foo", "inner", return("hello")))

  output:

    block "outer block"
      foo "inner"
         return "hello"
      end foo
    end block

Teach us, Ruby master.