Thread overview
Ubermacros a la Nemerle
Jun 08, 2004
Andy Friesen
Jun 08, 2004
Ivan Senji
Jun 09, 2004
Brad Anderson
June 08, 2004
Nemerle (http://nemerle.org) is a hybrid functional/imperative language that targets .NET.  It's a sort of melding of C# and ML.

What makes it stand out is its macro facilities, which more or less cover any sort of language extension that I can even imagine.

Nemerle macros effectively boil down to functions that are run by the compiler.  They accept parse trees as arguments, and return a parse tree  element which is injected into the code.  It is my understanding that Lisp macros work on the same principle, but this is the first time I've seen it in a form that doesn't seem magical. (maybe I just haven't read enough Lisp yet)

Currently, Nemerle macros are compiled into separate DLLs, which, while somewhat klunky, allows closed-source people to use them for libraries and such.  It also makes it abundantly clear when things are happening and what dependancies exist. (macros are needed by the compiler, not the resulting binary)

Hypothetical example:

    import std.compiler;

    Expression print(Expression args) {

        // would presumably raise a SyntaxError if 'args' is not an
        // argument list
        auto Expression[] argList = decomposeArgumentList(args);

        Expression[] result
        foreach (Expression arg; args) {

            // <[ stuff ]> is an Expression object representing the
            // enclosed hunk of code.

            // $arg is used to denote that the argument is inserted into
            // the block, as opposed to literally inserting the symbol
            // 'arg'.  Maybe there's a nicer looking alternative.
            result ~= <[ stdio.write($arg) ]>;
        }

        result ~= <[ stdio.write('\n') ]>;

        // Convert the Expression[] into a single { ... } block and return it.
        return composeBlock(result);
    }

This would expand the expression 'print(x,y,z,blah,"thing", 3.141596, 2+4i)' to a {} block containing a bunch of of stdio.write() calls, ending with a newline.

Something tells me this is just a hair too ambitious for D 1.0, but it does look to be implementable enough, and has a pretty big impact on what can be conveniently expressed within the language. (if I'm reading the source correctly, almost all of Nemerle's syntax is implemented via its own macros)

Thoughts?

 -- andy
June 08, 2004
Lately i have been trying to put my finger on a feature that would give ability to generate code at compile time (inspired by VHDL's generate) but i had no idea how this would work.But it could be a Very powerful feature.

D 2.0?

"Andy Friesen" <andy@ikagames.com> wrote in message news:ca56h1$2k4h$1@digitaldaemon.com...
> Nemerle (http://nemerle.org) is a hybrid functional/imperative language that targets .NET.  It's a sort of melding of C# and ML.
>
> What makes it stand out is its macro facilities, which more or less cover any sort of language extension that I can even imagine.
>
> Nemerle macros effectively boil down to functions that are run by the
> compiler.  They accept parse trees as arguments, and return a parse tree
>   element which is injected into the code.  It is my understanding that
> Lisp macros work on the same principle, but this is the first time I've
> seen it in a form that doesn't seem magical. (maybe I just haven't read
> enough Lisp yet)
>
> Currently, Nemerle macros are compiled into separate DLLs, which, while somewhat klunky, allows closed-source people to use them for libraries and such.  It also makes it abundantly clear when things are happening and what dependancies exist. (macros are needed by the compiler, not the resulting binary)
>
> Hypothetical example:
>
>      import std.compiler;
>
>      Expression print(Expression args) {
>
>          // would presumably raise a SyntaxError if 'args' is not an
>          // argument list
>          auto Expression[] argList = decomposeArgumentList(args);
>
>          Expression[] result
>          foreach (Expression arg; args) {
>
>              // <[ stuff ]> is an Expression object representing the
>              // enclosed hunk of code.
>
>              // $arg is used to denote that the argument is inserted into
>              // the block, as opposed to literally inserting the symbol
>              // 'arg'.  Maybe there's a nicer looking alternative.
>              result ~= <[ stdio.write($arg) ]>;
>          }
>
>          result ~= <[ stdio.write('\n') ]>;
>
>          // Convert the Expression[] into a single { ... } block and
> return it.
>          return composeBlock(result);
>      }
>
> This would expand the expression 'print(x,y,z,blah,"thing", 3.141596,
> 2+4i)' to a {} block containing a bunch of of stdio.write() calls,
> ending with a newline.
>
> Something tells me this is just a hair too ambitious for D 1.0, but it does look to be implementable enough, and has a pretty big impact on what can be conveniently expressed within the language. (if I'm reading the source correctly, almost all of Nemerle's syntax is implemented via its own macros)
>
> Thoughts?
>
>   -- andy


June 09, 2004
If it truly is like Lisp's macros, it would be a feature of D that not many languages have, and would truly be for power programmers. (According to Paul Graham).

If Walter implemented this, he would be able to point people to this capability and tell them to try it themselves instead of having them/us wait for a new release.

BA

Andy Friesen wrote:

> Nemerle (http://nemerle.org) is a hybrid functional/imperative language that targets .NET.  It's a sort of melding of C# and ML.
> 
> What makes it stand out is its macro facilities, which more or less cover any sort of language extension that I can even imagine.
> 
> Nemerle macros effectively boil down to functions that are run by the compiler.  They accept parse trees as arguments, and return a parse tree  element which is injected into the code.  It is my understanding that Lisp macros work on the same principle, but this is the first time I've seen it in a form that doesn't seem magical. (maybe I just haven't read enough Lisp yet)
> 
> Currently, Nemerle macros are compiled into separate DLLs, which, while somewhat klunky, allows closed-source people to use them for libraries and such.  It also makes it abundantly clear when things are happening and what dependancies exist. (macros are needed by the compiler, not the resulting binary)
> 
> Hypothetical example:
> 
>     import std.compiler;
> 
>     Expression print(Expression args) {
> 
>         // would presumably raise a SyntaxError if 'args' is not an
>         // argument list
>         auto Expression[] argList = decomposeArgumentList(args);
> 
>         Expression[] result
>         foreach (Expression arg; args) {
> 
>             // <[ stuff ]> is an Expression object representing the
>             // enclosed hunk of code.
> 
>             // $arg is used to denote that the argument is inserted into
>             // the block, as opposed to literally inserting the symbol
>             // 'arg'.  Maybe there's a nicer looking alternative.
>             result ~= <[ stdio.write($arg) ]>;
>         }
> 
>         result ~= <[ stdio.write('\n') ]>;
> 
>         // Convert the Expression[] into a single { ... } block and return it.
>         return composeBlock(result);
>     }
> 
> This would expand the expression 'print(x,y,z,blah,"thing", 3.141596, 2+4i)' to a {} block containing a bunch of of stdio.write() calls, ending with a newline.
> 
> Something tells me this is just a hair too ambitious for D 1.0, but it does look to be implementable enough, and has a pretty big impact on what can be conveniently expressed within the language. (if I'm reading the source correctly, almost all of Nemerle's syntax is implemented via its own macros)
> 
> Thoughts?
> 
>  -- andy