www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Will macros work with expressions?

reply Bill Baxter <dnewsgroup billbaxter.com> writes:
A question about the upcoming macros:
Will they work for expressions as well as statements?

The examples in WalterAndrei.pdf all show complete statements,
like
    macro foo(e) { e=3; }

But will it be possible to have:
    macro foo(e) { e+3 }

I hope expressions will be allowed.  Not for things like e+3 but for 
making local shortcuts where aliases don't cut it:

    macro call_func( arg ) {
       $this.some_member.a_really_long_named_template_member(arg);
    }
    ...
    writefln(call_func(1));
    writefln(call_func("hi"));

And I'm sure there'd be any number of other uses for expression macros.

--bb
Sep 02 2007
next sibling parent reply Xinok <xnknet gmail.com> writes:
I agree that macro expressions should be allowed. However, I think a 
better syntax would be:

macro foo(e) = e + 3;

Bill Baxter wrote:
 A question about the upcoming macros:
 Will they work for expressions as well as statements?
 
 The examples in WalterAndrei.pdf all show complete statements,
 like
    macro foo(e) { e=3; }
 
 But will it be possible to have:
    macro foo(e) { e+3 }
 
 I hope expressions will be allowed.  Not for things like e+3 but for 
 making local shortcuts where aliases don't cut it:
 
    macro call_func( arg ) {
       $this.some_member.a_really_long_named_template_member(arg);
    }
    ...
    writefln(call_func(1));
    writefln(call_func("hi"));
 
 And I'm sure there'd be any number of other uses for expression macros.
 
 --bb

Sep 02 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Xinok wrote:
 Bill Baxter wrote:
 A question about the upcoming macros:
 Will they work for expressions as well as statements?

 The examples in WalterAndrei.pdf all show complete statements,
 like
    macro foo(e) { e=3; }

 But will it be possible to have:
    macro foo(e) { e+3 }

 I hope expressions will be allowed.  Not for things like e+3 but for 
 making local shortcuts where aliases don't cut it:

    macro call_func( arg ) {
       $this.some_member.a_really_long_named_template_member(arg);
    }
    ...
    writefln(call_func(1));
    writefln(call_func("hi"));

 And I'm sure there'd be any number of other uses for expression macros.


 I agree that macro expressions should be allowed. However, I think a
 better syntax would be:

 macro foo(e) = e + 3;

I like that. But what about an expression with a few preliminary statements setting up temp variables and such? --bb
Sep 03 2007
parent reply Reiner Pope <some address.com> writes:
Bill Baxter wrote:
 Xinok wrote:
 Bill Baxter wrote:
 A question about the upcoming macros:
 Will they work for expressions as well as statements?

 The examples in WalterAndrei.pdf all show complete statements,
 like
    macro foo(e) { e=3; }

 But will it be possible to have:
    macro foo(e) { e+3 }

 I hope expressions will be allowed.  Not for things like e+3 but for 
 making local shortcuts where aliases don't cut it:

    macro call_func( arg ) {
       $this.some_member.a_really_long_named_template_member(arg);
    }
    ...
    writefln(call_func(1));
    writefln(call_func("hi"));

 And I'm sure there'd be any number of other uses for expression macros.


> I agree that macro expressions should be allowed. However, I think a > better syntax would be: > > macro foo(e) = e + 3; > I like that. But what about an expression with a few preliminary statements setting up temp variables and such? --bb

If it's going to be "pasted" into the call-site, then how can that work? I imagine you'd have to set it up as a function call. Of course, a nicer solution is a syntax where (nearly) everything is an expression, like many functional languages. -- Reiner
Sep 03 2007
parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Reiner Pope Wrote:

 Bill Baxter wrote:
 Xinok wrote:
 Bill Baxter wrote:
 A question about the upcoming macros:
 Will they work for expressions as well as statements?

 The examples in WalterAndrei.pdf all show complete statements,
 like
    macro foo(e) { e=3; }

 But will it be possible to have:
    macro foo(e) { e+3 }

 I hope expressions will be allowed.  Not for things like e+3 but for 
 making local shortcuts where aliases don't cut it:

    macro call_func( arg ) {
       $this.some_member.a_really_long_named_template_member(arg);
    }
    ...
    writefln(call_func(1));
    writefln(call_func("hi"));

 And I'm sure there'd be any number of other uses for expression macros.


> I agree that macro expressions should be allowed. However, I think a > better syntax would be: > > macro foo(e) = e + 3; > I like that. But what about an expression with a few preliminary statements setting up temp variables and such? --bb

If it's going to be "pasted" into the call-site, then how can that work? I imagine you'd have to set it up as a function call. Of course, a nicer solution is a syntax where (nearly) everything is an expression, like many functional languages. -- Reiner

Walter discussed this during his talk I believe. Indeed, macros will do syntax-tree substitution and variable declarations are becoming expressions, so you'll be able to insert temporary variables, etc. My worry is that macros used inside expressions will not be able to contain statements. This is a shame, since this means that macros and function calls won't be interchangeable. Looks like macros will be slightly more powerful than their C counterparts, which I've never used.
Sep 03 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Robert Fraser wrote:
 Reiner Pope Wrote:
 
 Bill Baxter wrote:
 Xinok wrote:
 Bill Baxter wrote:
 A question about the upcoming macros:
 Will they work for expressions as well as statements?

 The examples in WalterAndrei.pdf all show complete statements,
 like
    macro foo(e) { e=3; }

 But will it be possible to have:
    macro foo(e) { e+3 }

 I hope expressions will be allowed.  Not for things like e+3 but for 
 making local shortcuts where aliases don't cut it:

    macro call_func( arg ) {
       $this.some_member.a_really_long_named_template_member(arg);
    }
    ...
    writefln(call_func(1));
    writefln(call_func("hi"));

 And I'm sure there'd be any number of other uses for expression macros.


> better syntax would be: > > macro foo(e) = e + 3; > I like that. But what about an expression with a few preliminary statements setting up temp variables and such? --bb

I imagine you'd have to set it up as a function call. Of course, a nicer solution is a syntax where (nearly) everything is an expression, like many functional languages. -- Reiner

Walter discussed this during his talk I believe. Indeed, macros will do syntax-tree substitution and variable declarations are becoming expressions, so you'll be able to insert temporary variables, etc.

Variable declarations will become expressions!? That's interesting. I wonder what the scope will be for such things.
 My worry is that macros used inside expressions will not be able to
 contain statements. This is a shame, since this means that macros and
 function calls won't be interchangeable. Looks like macros will be
 slightly more powerful than their C counterparts, which I've never
 used.

I dunno about their "power", but At least they'll be significantly safer and more robust than their C counterparts. --bb
Sep 03 2007
parent reply Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
Bill Baxter wrote:

 Robert Fraser wrote:

 Walter discussed this during his talk I believe. Indeed, macros will
 do syntax-tree substitution and variable declarations are becoming
 expressions, so you'll be able to insert temporary variables, etc.

Variable declarations will become expressions!? That's interesting. I wonder what the scope will be for such things.
 My worry is that macros used inside expressions will not be able to
 contain statements. This is a shame, since this means that macros and
 function calls won't be interchangeable. Looks like macros will be
 slightly more powerful than their C counterparts, which I've never
 used.

I dunno about their "power", but At least they'll be significantly safer and more robust than their C counterparts.

I would say they have less expressiveness than C counterparts unless all statements suddenly become expressions. However, there is no real need to do this. Another way could be to introduce a new compile time metaexpression/statement type. Maybe the "D code string" does exactly this? After this another problem pops up: the reflection system isn't really designed for this low level operations. I'm not saying this is wrong direction though, quite opposite. It just shows how broken the C-based language core is for metaprogramming. One more problem I see in the new macro feature is that it's basically (or is it - the proposal is a bit short on details) a generic cut'n'paste function. Is it possible to control (i.e. is it a Turing complete compile time function call) the output of a macro ? Pseudo code example: macro(foo) { metaif (foo == bar) { metareturn runtimecode{ while(foo.next !is null) { print(foo.next); foo = foo.next; } } metaelse { runtimecode ret; metaforeach(a; foo) { ret ~= runtimecode{ a.bar *= 2; } } metareturn ret; } } ( this is basically CTFE+mixins, but on the AST level, not with strings. I could do this even today by implementing a D compiler with AST macros on top of D with metaprogramming :P ) If I understood it correctly, the macros only do a simple substitution using their parameters, hide symbols when necessary (hygiene) and then attach the generated code to the AST.
Sep 04 2007
parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Jari-Matti Mäkelä Wrote:

 I would say they have less expressiveness than C counterparts unless all
 statements suddenly become expressions. 

You can add statements, as long as they're not used in an expression, as in the C pre-processor. You can even add declarations (what template mixins are used for now. I do hope template mixins don't go, though, since templates can be used either for the mixins or instantiated as needed interchangeably.)
 However, there is no real need to
 do this. Another way could be to introduce a new compile time
 metaexpression/statement type. Maybe the "D code string" does exactly this?
 After this another problem pops up: the reflection system isn't really
 designed for this low level operations. I'm not saying this is wrong
 direction though, quite opposite. It just shows how broken the C-based
 language core is for metaprogramming. 
 
 One more problem I see in the new macro feature is that it's basically (or
 is it - the proposal is a bit short on details) a generic cut'n'paste
 function. Is it possible to control (i.e. is it a Turing complete compile
 time function call) the output of a macro ? Pseudo code example:
 
 macro(foo) {
   metaif (foo == bar) {

Static if - it's already part of the language.
     metareturn runtimecode{ while(foo.next !is null) { print(foo.next); foo
 = foo.next; }
   } metaelse 
     runtimecode ret;
 
     metaforeach(a; foo) {
       ret ~= runtimecode{ a.bar *= 2; }
     }
 
     metareturn ret;
   }
 }
 
 ( this is basically CTFE+mixins, but on the AST level, not with strings. I
 could do this even today by implementing a D compiler with AST macros on
 top of D with metaprogramming :P )
 
 If I understood it correctly, the macros only do a simple substitution using
 their parameters, hide symbols when necessary (hygiene) and then attach the
 generated code to the AST.

I think that's about right, but remember that their parameters can specialize on any pattern and extract parts of the expression, which I think is the most exciting feature.
Sep 04 2007
parent reply Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
Robert Fraser wrote:
 Jari-Matti Mäkelä Wrote:

 If I understood it correctly, the macros only do a simple substitution
 using their parameters, hide symbols when necessary (hygiene) and then
 attach the generated code to the AST.

I think that's about right, but remember that their parameters can specialize on any pattern and extract parts of the expression, which I think is the most exciting feature.

Ah, good point. That would make overloading and recursive calls the primary control flow constructs then. Given enough power they could surely handle the task. Let's just hope the size and time complexity of macro invocations won't get too large.
Sep 05 2007
parent reply Reiner Pope <some address.com> writes:
Jari-Matti Mäkelä wrote:
 Robert Fraser wrote:
 Jari-Matti Mäkelä Wrote:

 If I understood it correctly, the macros only do a simple substitution
 using their parameters, hide symbols when necessary (hygiene) and then
 attach the generated code to the AST.

specialize on any pattern and extract parts of the expression, which I think is the most exciting feature.

Ah, good point. That would make overloading and recursive calls the primary control flow constructs then.

Such an environment is not pleasant as it involves large code overheads. It's what's required in C++ template metaprogramming; D made this *much* nicer by introducing static if. Please don't take a step backwards with macros. -- Reiner
Sep 05 2007
parent reply Don Clugston <dac nospam.com.au> writes:
Reiner Pope wrote:
 Jari-Matti Mäkelä wrote:
 Robert Fraser wrote:
 Jari-Matti Mäkelä Wrote:

 If I understood it correctly, the macros only do a simple substitution
 using their parameters, hide symbols when necessary (hygiene) and then
 attach the generated code to the AST.

specialize on any pattern and extract parts of the expression, which I think is the most exciting feature.

Ah, good point. That would make overloading and recursive calls the primary control flow constructs then.

Such an environment is not pleasant as it involves large code overheads. It's what's required in C++ template metaprogramming; D made this *much* nicer by introducing static if.

And even better (perfect in many cases) with CTFE.
 Please don't take a step backwards with macros.

This was the reaction I had too. There's really no need for macros to provide new functionality, they just need to provide syntax sugar for what we can already do with string mixins.
Sep 06 2007
parent reply Reiner Pope <some address.com> writes:
Don Clugston wrote:
 Reiner Pope wrote:
 Jari-Matti Mäkelä wrote:
 Robert Fraser wrote:
 Jari-Matti Mäkelä Wrote:

 If I understood it correctly, the macros only do a simple substitution
 using their parameters, hide symbols when necessary (hygiene) and then
 attach the generated code to the AST.

specialize on any pattern and extract parts of the expression, which I think is the most exciting feature.

Ah, good point. That would make overloading and recursive calls the primary control flow constructs then.

Such an environment is not pleasant as it involves large code overheads. It's what's required in C++ template metaprogramming; D made this *much* nicer by introducing static if.

And even better (perfect in many cases) with CTFE.
 Please don't take a step backwards with macros.

This was the reaction I had too. There's really no need for macros to provide new functionality, they just need to provide syntax sugar for what we can already do with string mixins.

But the hygiene of macros is certainly appealing, no?
Sep 06 2007
parent Don Clugston <dac nospam.com.au> writes:
Reiner Pope wrote:
 Don Clugston wrote:
 Reiner Pope wrote:
 Jari-Matti Mäkelä wrote:
 Robert Fraser wrote:
 Jari-Matti Mäkelä Wrote:

 If I understood it correctly, the macros only do a simple 
 substitution
 using their parameters, hide symbols when necessary (hygiene) and 
 then
 attach the generated code to the AST.

specialize on any pattern and extract parts of the expression, which I think is the most exciting feature.

Ah, good point. That would make overloading and recursive calls the primary control flow constructs then.

Such an environment is not pleasant as it involves large code overheads. It's what's required in C++ template metaprogramming; D made this *much* nicer by introducing static if.

And even better (perfect in many cases) with CTFE.
 Please don't take a step backwards with macros.

This was the reaction I had too. There's really no need for macros to provide new functionality, they just need to provide syntax sugar for what we can already do with string mixins.

But the hygiene of macros is certainly appealing, no?

Definitely. But I was hoping that the inability to have hygienic string mixins was a temporary aberration.
Sep 07 2007
prev sibling parent Don Clugston <dac nospam.com.au> writes:
Bill Baxter wrote:
 A question about the upcoming macros:
 Will they work for expressions as well as statements?
 
 The examples in WalterAndrei.pdf all show complete statements,
 like
    macro foo(e) { e=3; }
 
 But will it be possible to have:
    macro foo(e) { e+3 }
 
 I hope expressions will be allowed.  Not for things like e+3 but for 
 making local shortcuts where aliases don't cut it:
 
    macro call_func( arg ) {
       $this.some_member.a_really_long_named_template_member(arg);
    }
    ...
    writefln(call_func(1));
    writefln(call_func("hi"));
 
 And I'm sure there'd be any number of other uses for expression macros.

If I understand it correctly, that should work, since macros operate via syntax tree substitution. Unfortunately, it seems that macros will be far less powerful than text mixins. I was hoping that I'd be able to replace most of my uses of text mixins with macros, but found very few places where it is possible :(. Sadly, I think I'll only be using macro + .stringof for a syntax sugar wrapper around a text mixin. Assuming .stringof will work, which is not guaranteed. Hopefully this will work: macro ASSERT(e) { assert(e, e.stringof ~ " failed"); }
Sep 03 2007