qwertie / ecsharp

Home of LoycCore, the LES language of Loyc trees, the Enhanced C# parser, the LeMP macro preprocessor, and the LLLPG parser generator.
http://ecsharp.net
Other
172 stars 25 forks source link

How to control parameter type with a macro? #66

Closed j4m3z0r closed 5 years ago

j4m3z0r commented 5 years ago

Have been experimenting with letting LeMP handle yet more of my code generation and stumbled onto this case:

define TypeForArg($T1) {
    static if($T1 `code==` Int) int;
    else $T1;
}

public static void F(TypeForArg(Int) i);

This will output the following:

public static void F(int);

Note that the i has been dropped from the output.

j4m3z0r commented 5 years ago

Actually, looking more closely, LeMP reports "Syntax error in argument list" when the i is included in the input, so I presume that's why it is being omitted from the output. However I don't understand why it's considered invalid input. Will see if I can get the same effect with some variation of replace / replacePP.

j4m3z0r commented 5 years ago

Ok, this works:

define TypeForArg($T1) {
    static if($T1 `code==` Int) int;
    else $T1;
}
replacePP(ArgType => TypeForArg(Int)) {
    public static void F(ArgType i);
}

That's an ok workaround for me for the time being, so this is lower priority. It would be good to understand if this is intended behavior or not though.

qwertie commented 5 years ago

That's intended behavior. The entire file is parsed before the macro processor starts, so the input syntax must be valid EC# and an expression like x(y) z is not a valid expression.

However there is a macro designed for this kind of situation. An expression of the form $(Type) x is treated as a variable declaration; with that in mind, I made a "no-op" macro used like this: $(out expr). It replaces $(out expr) with expr, so instead of

public static void F(TypeForArg(Int) i);

you can write

public static void F($(out TypeForArg(Int)) i);

You can use this macro in other syntactically restricted locations too, such as method names and return types.

j4m3z0r commented 5 years ago

Ok, got it. I keep having this mental disconnect with the idea that the input file needs to be parseable as EC#. Since it's a pass that occurs before the C# compiler I think I assume that it works like C++'s preprocessor, which it doesn't.

Thanks for the helpful answer.