Здравствуйте, Oyster, Вы писали:
O>А ведь ты прав! Очень даже изящное решение получается, спасибо!
Удалил старое сообщение? Видимо заметил пример в конце. Ну да ладно.
O>Интересненько? А точно получится использовать унарный постфиксный (не префиксный) оператор?
Точно. Это в общем-то фича языка — нет разницы между постфиксными и префиксными операторами.
using Nemerle.English;
def yoda = true not;
def reallyObfuscated = yoda !;
def ohmy = 23 ~;
O>Кстати, в таком случае встаёт вопрос генерации макроса внутри макроса чтобы не хардкодить.
Боюсь, что генерация это слишком сложный путь. Одно дело сгенерировать код, а другое дело его скомпилировать. Можно конечно компилировать "настройки" в отдельную сборку и оттуда использовать.
Но есть идея и более простая. И макрос, и оператор можно зарегистрировать вручную через API компилятора(см. модуль MacroRegistry). Макрос это по сути экземпляр некого класса, реализовывающего интерфейс IMacro. Нужно просто написать собственную реализацию IMacro вручную(т.е. не использовать встроенную в компилятор генерацию этого класса), которая в зависимости от того как ее инициализируют будет вести себя как разные макросы(т.е. с разными именами и генерировать различный код).
Вот дамп кода(на псевдо-немерле
, выглядит жутко конечно, но понять можно ) методов макро-оператора kg. Кстати стоит обратить внимание, что по сути это вполне обычный макрос, а оператором его делает атрибут сборки. В модуле LibrariesLoader есть функции которые сканируют сборку на предмет нахождения в ней макросов и таких атрибутов, и регистрируют их в MacroRegistry.
Public, Sealed, Macro, SpecialName My.Phys.kgMacro : System.Object, Nemerle.Compiler.IMacro {
Private, Static method My.Phys.kgMacro..cctor() : void {
{
def customs = typeof (kgMacro).GetCustomAttributes (false);
foreach (in ((x is MacroUsageAttribute), customs)) my_usage = x;
keywords = []
}
Public, SpecialName method My.Phys.kgMacro.get_IsInherited() : bool {
my_usage != null && my_usage.Inherited
}
Public, SpecialName method My.Phys.kgMacro.get_Keywords() : list[string] {
keywords
}
Public, SpecialName method My.Phys.kgMacro.get_Usage() : Nemerle.MacroUsageAttribute {
my_usage
}
Public, SpecialName method My.Phys.kgMacro.get_IsTailRecursionTransparent() : bool {
false
}
Public method My.Phys.kgMacro.GetName() : string {
"kg"
}
Public method My.Phys.kgMacro.GetNamespace() : string {
"My.Phys"
}
Public method My.Phys.kgMacro.SyntaxExtension() :
(Nemerle.Compiler.GrammarElement * list[Nemerle.Compiler.Parsetree.SyntaxElement]
-> list[Nemerle.Compiler.Parsetree.SyntaxElement]) {
(null, ((Nemerle.Utility.Identity.[list[SyntaxElement], list[SyntaxElement]] () : object)
:> list[SyntaxElement] -> list[SyntaxElement]))
}
Public method My.Phys.kgMacro.Run(_N_944 : Nemerle.Compiler.Typer, parms :
list[Nemerle.Compiler.Parsetree.SyntaxElement]) : Nemerle.Compiler.Parsetree.PExpr {
match (parms) {
| [SyntaxElement.Expression (val)] =>
<[ do_something_crazy_with_kg ($(val)) ]>
| _ =>
def len = List.Length (parms);
def types = parms.ToString (", ");
Message.FatalError ("macro `" + "kg" + "' expects following list of arguments: (" +
"PExpr" + ") got some " + len.ToString () + " parameters [" + types + "]")
}
}
Public method My.Phys.kgMacro.CallTransform(trans_p : list[Nemerle.Compiler.Parsetree.PExpr]) :
list[Nemerle.Compiler.Parsetree.SyntaxElement] {
{
mutable trans_res = [];
match (trans_p) {
| x :: trans_p =>
{
trans_res = SyntaxElement.Expression (x) :: trans_res;
match (trans_p) {
| x :: _ =>
trans_res = SyntaxElement.Expression (x) :: trans_res
| [] => () }
}
| [] => ()
};
List.Rev (trans_res)
}
}