On 30/09/2016 2:18 AM, Jacob Carlborg wrote:
On 2016-09-29 14:57, rikki cattermole wrote:
Me and Cauterite were toying with the idea of AST macros but in a
completely new form a while ago.

Below is the usage of it.

Something you'll notice about it is that it could turn the asm block
into a library solution (which is clearly what we'd want anyway). Not to
mention Linq style queries.

In theory it shouldn't be too complex to implement since you are only
doing basic checks to determine if to parse the given statement / block
to a rewriter function.

```D
void main() {
    // \/ parsed by iasm.c by matches {}'s and sending contents to it
    asm {
        ...
    }

    import linq;
    @Linq
    DataSource source = ...;
    Tree[] trees = source.trees.where(name = "abc").limit(20);

    import Assembly_x86;

    asm {
        ...
    }
}

struct Linq {
    string __ast(OnType, ExpectedType)(string statement) {
        assert(statement == "source.trees.where(name =
"abc").limit(20);");
        static assert(OnType == DataSource);
        static assert(ExpectedType == Tree[]);
    }
}

// Assembly_x86.d

struct X86 {}
struct ASM {

    string __ast(OnType, ExpectedType)(string statement) {
        assert(statement == "asm {\n        ...\n    };");
        static assert(OnType == X86);
        static assert(ExpectedType == void);
    }
}

@ASM
X86 asm;
```

Hmm, I find this to be somewhat difficult to follow. You get the AST as
a string? Which means you need to implement a parser. How will the macro
invocation be transformed? Return a string from the macro which will be
reparsed by the compiler and inserted at the call site?

I'll expand on what I wrote above.

There are two kinds of invocations here. Blocks and statements.
Statements are the type of thing you expect from e.g. Linq. Where as blocks would be what asm would be defined as being.

The invocation defines where the start/end of the input file to be passed to __ast is and that is all it does.

In each case, if the first token (or for assignment statements the first token of the expression) is a variable that happens to have a UDA on it with __ast member it will pass said invocation text directly to it. What ever that may be.

As far as guarantees go for the input, it will always end in a semicolon. To determine if it was a statement vs a block just check if ExpectedType is void.

So something like:

```D
     @Linq
     DataSource source = ...;
     Tree[] trees = source.trees.where(name = "abc").limit(20);
```

Could be transformed into:

```D
    @Linq
    DataSource source = ...;
Tree[] trees = mixin(__traits(getAttributes, source)[0].__ast("source.trees.where(name = "abc").limit(20);"));
```

They key here is explicitly marking non-vanilla-D-code as such without adding syntax like ``macro{ stuff here }``.

Reply via email to