Re[24]: Снова о Nemerle или профанация не пройдет :)
От: Oyster КНДР  
Дата: 21.02.06 17:22
Оценка: 26 (3)
Здравствуйте, eao197, Вы писали:

E>Может не нужно сразу сложную, а проще что-нибудь, знакомое публике? Например, вот эта задача
Автор: AndrewVK
Дата: 13.07.05
.


E>Причем интересно как с парсингом XML-я (может быть даже в compile-time), так и создание специализированного DSL на макросах специально для этой задачи.


В общем, я решил попробовать написать такой макрос. Сильно не пинать — первый опыт, можно сказать.

Макрос генерит класс в compile-time в соответствии с постановкой задачи. Конструктор вот только пока что не создаётся (уже домой бежать надо — завтра, надеюсь...). Используется макрос вот так:

using Oyster;

metaclass TestClass {
    prop1 : int;
    prop2 : string
}

Код макроса (повторяю — писать на Nemerle я пока не умею, так что сильно не ругайте):

using Nemerle.Collections;

namespace Oyster
{
    macro metaclass(className, body)
    syntax ("metaclass", className, body)
    {
        // Тут я зачем-то вытаскиваю идентификатор, а потом его снова вставляю в AST.
        // Криво (?), но как иначе - не знаю
        def className = match (className) { | <[ $(x : name) ]> => x };
        
        // Разбираем "свойства"
        def props = match (body) {
            | <[ { .. $props } ]> => List.Map(props, fun(prop) { | <[ $(n : name) : $(t : name) ]> => (n, t) })
            | _ => []
        };
        
        // http://nemerle.org/Defining_types_from_inside_macros
        def ctx = Nemerle.Macros.ImplicitCTX();
        def builder = ctx.Env.Define(<[ decl: public class $(className : name) {} ]>);
        
        // Добавляем поля для начала.
        // Если я тут ничего не верну, то компилятор чего-то на меня обидится :(
        List.ForAll(props, fun(n, t) { builder.Define(<[ decl: mutable $(n.NewName("_" + n.Id) : name) : $(t : name) ; ]>); true });
        
        // Добавляем свойства
        List.ForAll(props, fun(n, t) {
            builder.Define(
                <[ decl:
                    public $(n.NewName(n.Id.Substring(0, 1).ToUpper() + n.Id.Substring(1)) : name) : $(t : name)
                    {
                        get { $(n.NewName("_" + n.Id) : name) }
                    };
                ]>);
            true });
            
        // Добавляем конструктор
        // TODO

        builder.Compile();
        <[ () ]>
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.