Will macros just be syntactic sugar? [EXAMPLE]

Don Clugston dac at nospam.com.au
Wed Apr 25 06:35:50 PDT 2007


Davidl wrote:
> heh, mixin an assert is bad, compile time is even longer :p
?? It's no different to a static assert.
> Though you are kinda sticking with CTFE & mixin , I'm pretty
> sure you would vote my syntax of macro for macro, right? :)
No. It's nowhere near clean enough yet. The code below, works right now.
The challenge is to make it nicer.

//--------------------------
// This is a macro library, defining a 'vectorize' macro.
//--------------------------
module Blade;
import ExpressionParser; //common code for any macros which use D syntax
public import std.stdio;

// CTFE macro: returns the code to be mixed in.
// prints all symbols used in the expression
char [] describe(char [] expr, char [][3][] symbols)
{
     char [] result = "Expression:" ~ expr
	~ "\nSYMBOL \tTYPE\t\tVALUE\n";
     for (int i=0; i<symbols.length; ++i) {
         result ~= symbols[i][0] ~ " \t" ~ symbols[i][1]
	~ "  \t" ~ symbols[i][2] ~ \n;
     }
     return `printf("` ~ result ~ `");`;
}

// TO BE MIXED IN -- inserts the boilerplate code for parsing & type 
extraction,
// then gets the macro text from the named function.
char [] vectorize(char [] expr)
{
     return expressionMacro("describe", expr);
}

//--------------------------
// And this is how the user sees it.
//--------------------------
import Blade;

void main()
{
     auto a = [1.24, 5.35, 324, 2454];
     double [] big = [3.44, 5565, 1.45, 67.1];
     const yx=-2.354e-68Li;
     alias big c;

     mixin(vectorize("a  +=yx *big -c"));
}

===============================
OUTPUT
===============================

Expression:a  +=yx *big -c
SYMBOL  TYPE            VALUE
a       double[4]       a
yx      ireal           -2.354e-68i
big     double[]        big
c       double[]        big

Note that the constant has been evaluated, and the aliases resolved.

And if you change the last line to:

mixin(vectorize("a  +=yx *big -d"));

you get:

test.d(10): Error: undefined identifier d

That happens automatically. Note that the line number is correct.

That expressionMacro must be really horrible, right?
Actually, no. It just makes use of some trivial identifier and operator 
parsing routines, and applies the .stringof property.
-----------

// Given an expression string 'expr', make a string to mixin in,
// which will have an array of 3 strings for each symbol in the
// expression. [0]=symbol name, [1]=type, [2]=value
char[] getAllIdentifiers(char [] expr)
{
     char [] result;
     char [] rest;
     char [] a;
     char [] b;
     a = parseQualifiedName(expr, rest);
     result = "[[`" ~ a ~"`,typeof(" ~ a ~ ").stringof, " ~a ~ ".stringof]";
     while (rest!="") {
         b = parseOperator(rest, rest);
         char [] r;
         a = parseQualifiedName(rest, r);
         rest=r;
         result ~= "," ~"[`" ~ a ~"`,typeof(" ~ a ~ ").stringof, " ~a ~ 
".stringof]";
     }
     return result ~ "]";
}

// Actually it should process the arguments into a standard, convenient 
form. For now, just pass them on, together with the type information.
char [] expressionMacro(char [] macroname, char [] args)
{
     return "mixin ("~macroname ~"(`" ~ args ~"`," ~ 
getAllIdentifiers(args)~ "));";
}

-----------
IMHO, this is already pretty good, despite the fact that there's a 
couple of workarounds for compiler bugs in there.
I just can't believe how powerful this language is now.



More information about the Digitalmars-d mailing list