Re[25]: Снова о Nemerle или профанация не пройдет :)
От: Vermicious Knid  
Дата: 21.02.06 19:03
Оценка: 25 (2)
Здравствуйте, Oyster, Вы писали:

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


Очень неплохо для первого опыта. Хотя и не без ляпов конечно. Сразу становится понятно, что Nemerle достаточно простой в освоении язык.

O>Конструктор вот только пока что не создаётся (уже домой бежать надо — завтра, надеюсь...).


С конструктором вообще и параметрами функций там все не так просто. В общем я добавил создание конструктора и упростил/улучшил некоторые моменты. Вот пример того, как это все работает:
using Oyster;
using Nemerle.IO;

metaclass zuper
{
    test : int;
    anotherProperty : string;
}

def z = zuper(1, "crazy test");
printf("%d %s\n", z.Test, z.AnotherProperty);


Вот улучшенный код(комментировать было лень, да и код в общем недалеко ушел):
using Nemerle.Collections;
using Nemerle.Macros;
using PT = Nemerle.Compiler.Parsetree;

namespace Oyster
{
    macro metaclass(className, body)
    syntax ("metaclass", className, body)
    {
        def props = match (body) {
            | <[ { .. $props } ]> =>
                props.Map(fun(_) { | <[ $(n : name) : $(t : name) ]> => (n, t) })
            | _ => []
        };
                
        def ctx = ImplicitCTX();
        def builder = ctx.Env.Define(<[ decl: public class $(className.ToString() : usesite) {} ]>);

        mutable constrParams = [] : list[PT.Fun_parm];
        mutable constrCode = [] : list[PT.PExpr];

        foreach((n, t) in props)
        {
            def prop = n.NewName("_" + n.Id);
            def accessor = n.NewName(n.Id.Substring(0, 1).ToUpper() + n.Id.Substring(1));
            builder.Define(<[ decl: mutable $(prop : name) : $(t : name) ; ]>);
            builder.Define(
                <[ decl:
                    public $(accessor : name) : $(t : name)
                    {
                        get { $(prop : name) }
                    };
                ]>);
            def paramType = ctx.BindType(<[ $(t : name) ]>);

            constrParams = <[ parameter: $(n : name) : $(paramType : typed) ]> :: constrParams;
            constrCode = <[ this.$(prop : name) = $(n : name); ]> :: constrCode;
        }
        builder.Define(
            <[ decl:
                public this(.. $(constrParams.Reverse())) { .. $constrCode }
            ]>);
        builder.Compile();
        <[ () ]>
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.