Re[27]: Снова о Nemerle или профанация не пройдет :)
От: Vermicious Knid  
Дата: 22.02.06 05:36
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А можно ли как-то в генерируемом классе использовать другие макросы?


Макросы внутри кода функций однозначно использовать можно. Насчет совсем других макросов я не знаю, надо поинтересоваться на досуге.

VD>Ведь реализация свойств по полям уже реализована в макросе Nemerle.Utility.Accessor. А реализация конструктора для всех полей в макросе Record.


Record это только для публичных полей(т.е. строго говоря для описания конструкторов структур). Accessor у меня использовать не получилось. Он его почему-то не опознает. Возможно это из-за того, что он обычно выполняется на более раннем этапе компиляции, или по другим причинам. Нужно спросить разработчиков языка.

VD>Так что если бы эти макросы можно было бы задействовать, то осталось бы только сформировать класс и список полей. Если при этом вынести в универсальный модуль такую байду как выскребание описания свойств, то код такого макроса был бы совсем небольшим и весьма понятным.


В универсальный модуль можно вынести. Есть еще пара мест где код можно упростить. Собственно местами я сделал лишнее и не заметил как можно сократить составление списка свойств. Если бы Accessor работал, то код выглядел бы так:
using Nemerle.Compiler;
using Nemerle.Collections;
using Nemerle.Macros;

namespace Oyster
{
    macro metaclass(className, body)
    syntax ("metaclass", className, body)
    {
        def ctx = ImplicitCTX();
        def builder = ctx.Env.Define(<[ decl: public class $(className.ToString() : usesite) {} ]>);
        mutable constrParams = [];
        mutable constrCode = [];
        match (body)
        {
            | <[ { .. $props } ]> =>
                foreach(<[ $(n : name) : $(t : name) ]> in props)
                {
                    builder.Define(<[ decl:
                                        [Nemerle.Utility.Accessor]
                                        mutable $(n : name) : $(t : name) ;
                                   ]>);
                    def paramType = ctx.BindType(<[ $(t : name) ]>);
                    constrParams = <[ parameter: $(n : name) : $(paramType : typed) ]> :: constrParams;
                    constrCode = <[ this.$(n.NewName("_" + n.Id) : name) = $(n : name); ]> :: constrCode;
                }
            | _ => Message.FatalError($"Invalid metaclass syntax, expected properties definition, got $body");
        }                
        builder.Define(<[ decl: public this(.. $(constrParams.Reverse())) { .. $constrCode } ]>);
        builder.Compile();
        <[ () ]>
    }
}


А вообще-то и неупрощенный код это всего полсотни строчек. И учитывая, что он делает работу сразу трех макросов это очень хороший результат. Но насчет выноса частоиспользуемых вещей в универсальный модуль ты пожалуй прав. Я сам думал над этим неоднократно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.