On 03/22/2012 08:12 PM, F i L wrote:
Timon Gehr wrote:
I think that would necessitate the addition of AST macros.

You mean passing DMD's actual AST tree object? Only a stripped down
version?

We have the macro keyword. I envision something like:

macro replaceAggregate(macro newAggregate, macro loop : foreach(x; aggr){statements}, macro x, macro aggr, macro statements) {
    foreach(x; newAggregate){statements}
}

void main(){
    int[] a = [1,2,3];
    int[] b = [2,3,4];
    replaceAggregate(b, foreach(x;a){writeln(x);});
}

(The syntax looks horrible, but you get the idea: AST walking by pattern matching)

Ideally, such macros would allow introducing local helper variables inside the macro that are not accessible from outside and introducing variables/enums in the context the macro is used. (prefixing identifiers that should interfere with the enclosing context with $ would be an option). Another idea:

macro someFancyDSL(string dsl){
    mixin(someFancyDSLtoD(dsl);
}

void main(){
    int n = 5;
    someFancyDSL {
        import n;
        let x = 1 : x
        let y = product (take n) x
        export y;
    }
    writeln(y);
}
// this would also enable less fancy but useful stuff:
macro until(macro condition, string str){
    while(!condition){
        mixin(str); // string and mixin not strictly necessary,
                    // maybe enable the feature on macro params too
    }
}

void main(){
    bool done = false;
    int x;
    until(done){
        done = foo(x++);
    }
}

This is just a very rough sketch though, we would need a much more refined design. I think getting the symbol scoping right is most important.

Reply via email to