[Nemerle] Интроспективная программа
От: PhantomIvan  
Дата: 21.06.06 09:02
Оценка:
1. В какой форум писать вопросы по немерле?
2. Я тут начал знакомство с немерле со следующей программы, печатающей свой текст:
 def l = '\\';
 def q = '\"';
 def b = '\$';
 def n = '\n';

 def introspect(s)
 {
  System.Console.WriteLine($" def l = '$l$l';$n def q = '$l$q';$n def b = '$l$b';$n def n = '$(l)n';$n$n def introspect(s)$n {$n  System.Console.WriteLine($b$q$s$q);$n }$n$n                 introspect($q$s$q);");
 }

                 introspect(" def l = '$l$l';$n def q = '$l$q';$n def b = '$l$b';$n def n = '$(l)n';$n$n def introspect(s)$n {$n  System.Console.WriteLine($b$q$s$q);$n }$n$n                 introspect($q$s$q);");


макрос $"..." очевидно, раскрывается в момент компиляции
а есть ли возможность перенести это раскрытие в рантайм?
чтобы еще упростить программу:
 ...
 
 def introspect(s)
 {
  System.Console.WriteLine(Runtime_$_MegaMacro(s));
 }

 introspect(" def l = '$l$l';$n def q = '$l$q';$n def b = '$l$b';$n def n = '$(l)n';$n$n def introspect(s)$n {$n  System.Console.WriteLine($b$q$s$q);$n }$n$n introspect($q$s$q);");
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>

21.06.06 15:33: Перенесено из 'Философия программирования'
30.01.07 18:27: Перенесено модератором из 'Декларативное программирование' — IT
Re: [Nemerle] Интроспективная программа
От: Mamut Швеция http://dmitriid.com
Дата: 21.06.06 10:28
Оценка:
PI>1. В какой форум писать вопросы по немерле?

Скорее всего в "Декларативное программирование"
От чего, от чего, от чего тах хорошо?
Потому что кто-то любит программиста
<< RSDN@Home 1.2.0 alpha rev. 647>>


dmitriid.comGitHubLinkedIn
Re: [Nemerle] Интроспективная программа
От: Андрей Хропов Россия  
Дата: 21.06.06 11:18
Оценка:
Здравствуйте, PhantomIvan, Вы писали:

PI>1. В какой форум писать вопросы по немерле?

В Декларативное программирование. Ну или сюда
если speak English или mowie po polsku.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: [Nemerle] Интроспективная программа
От: Oyster Украина https://github.com/devoyster
Дата: 21.06.06 11:40
Оценка: 5 (1)
Здравствуйте, PhantomIvan, Вы писали:

PI>макрос $"..." очевидно, раскрывается в момент компиляции

PI>а есть ли возможность перенести это раскрытие в рантайм?

В Nemerle макрос — не более чем обычный класс, реализующий интерфейс IMacro. Этот класс принимает на вход кусок AST, а на выход выдаёт другой кусок AST. Соответственно, вызывать макрос в рантайме можно, но смысла в этом особого нет — что ты потом с этим куском AST делать будешь? "Всунуть" его куда-то в уже выполняемый код ты не сможешь...

Поэтому в Nemerle макросы используются (т.е. вызываются) только на этапе компиляции, когда на руках ещё есть код в виде AST, а не в виде инструкций CIL. В общем-то, вполне резонно для языка со статической типизацией.
Re: [Nemerle] Интроспективная программа
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.06.06 23:21
Оценка: :)
Здравствуйте, PhantomIvan, Вы писали:

Можно написать спростой макрос выводящий переданное в него код на консоль и за одно генерирующий код для него.

Выглядить это будет примерно так:
using System.Console;

macro TestMacro(expr)
{
  WriteLine(expr);
  <[ $expr ]>;
}

Использование в программе:
TestMacro(1 + 2);
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
отцы, помогайте
От: PhantomIvan  
Дата: 04.07.06 11:07
Оценка:
Здравствуйте, Oyster, Вы писали:

O>В Nemerle макрос — не более чем обычный класс, реализующий интерфейс IMacro. Этот класс принимает на вход кусок AST, а на выход выдаёт другой кусок AST. Соответственно, вызывать макрос в рантайме можно, но смысла в этом особого нет — что ты потом с этим куском AST делать будешь? "Всунуть" его куда-то в уже выполняемый код ты не сможешь...


O>Поэтому в Nemerle макросы используются (т.е. вызываются) только на этапе компиляции, когда на руках ещё есть код в виде AST, а не в виде инструкций CIL. В общем-то, вполне резонно для языка со статической типизацией.


это все понятно, но давайте все-таки попробуем
я хочу переписать программу, скажем, так:
 def l = '\\';
 def q = '\"';
 def b = '\$';
 def n = '\n';
 screw def s = " def l = '$l$l';$n def q = '$l$q';$n def b = '$l$b';$n def n = '$(l)n';$n screw def s = $q$s$q;$n$n def introspect()$n {$n  System.Console.WriteLine(nut s);$n }$n$n introspect();";

 def introspect()
 {
  System.Console.WriteLine(nut s);
 }

 introspect();


для этого я определил макросы:
using System.Collections.Generic;
using Nemerle.IO;

module ScrewsAndNuts
{
    public Values : Dictionary[string, string] = Dictionary();
}

macro megamacro_screw(screw_def)
syntax ("screw", screw_def)
// usage: screw def s = "bugaga $muahaha";
{
    match (screw_def)
    {
        | <[ def $variable = $(literal: string) ]> =>
            WriteLine($"Screwing variable [ $variable ]");
            def expression = <[ def $variable = $(literal: string) ]>;
            if (ScrewsAndNuts.Values.ContainsKey(variable.ToString()))
                Message.Warning("variable has been already screwed!");
            else
                ScrewsAndNuts.Values.Add(variable.ToString(), literal);
            expression
        | e => Message.FatalError($"Incorrect screw: $e");
    }
}

macro megamacro_nut(variable)
syntax ("nut", variable)
// usage: nut s
{
    WriteLine($"Nutting variable [ $variable ]");
    def literal = <[ $(ScrewsAndNuts.Values[variable.ToString()]: string) ]>;
    <[ sprint($literal) ]>
}


но он не хочет вставить такую простую вещь как sprint($"... bla bla bla ...") в код в месте вызова последнего макроса
ох уж эта гигиена... пишет вот что:
Screwing variable [ s ]
Nutting variable [ s ]
Screwing variable [ s ]
self3.n:5:2:5:7: warning: variable has been already screwed!
Nutting variable [ s ]
self3.n:9:28:9:31: error: unbound name `l'
self3.n:9:28:9:31: error: unbound name `l'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:31: error: unbound name `l'
self3.n:9:28:9:31: error: unbound name `q'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:31: error: unbound name `l'
self3.n:9:28:9:31: error: unbound name `b'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:29: error: unbound name `l'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:31: error: unbound name `q'
self3.n:9:28:9:31: error: unbound name `s'
self3.n:9:28:9:31: error: unbound name `q'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:31: error: unbound name `n'
self3.n:9:28:9:31: error: unbound name `n'


ну допустим гигиена, ладно, ну а как тогда все же извратиться
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: отцы, помогайте
От: Oyster Украина https://github.com/devoyster
Дата: 07.07.06 14:28
Оценка: +1
Здравствуйте, PhantomIvan, Вы писали:

PI>ну допустим гигиена, ладно, ну а как тогда все же извратиться


Честно говоря, я в коде практически ничего не понял Зато могу сказать, как избавиться от гигиены:

// Наш макрос, который не любит гигиену
macro MeDontWashHands()
{
    <[ $("x" : dyn) = 1; ]>
}

// ...

// Тут в x попадёт единичка
mutable x = 7;
MeDontWashHands();
System.Console.WriteLine(x);

Ещё можно почитать Re[5]: Критика Nemerle
Автор: Oyster
Дата: 09.05.06
— там рассказывается, как можно во всём выражении сразу задавить гигиену.
Re[2]: отцы, помогайте
От: PhantomIvan  
Дата: 13.07.06 13:39
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Честно говоря, я в коде практически ничего не понял

так я объясню с удовольствием, а что непонятно

O>Ещё можно почитать Re[5]: Критика Nemerle
Автор: Oyster
Дата: 09.05.06
— там рассказывается, как можно во всём выражении сразу задавить гигиену.

тот способ не помог, зато я все же разобрался со встроенным sprint-ом
и сделал так:

macro megamacro_nut(variable)
syntax ("nut", variable)
// usage: nut s
{
    WriteLine($"Nutting variable [ $variable ]");
    def literal = ScrewsAndNuts.Values[variable.ToString()].ToString();
    def sequence = List.RevMap(MyHelper.my_make_splice_distribution(literal, Macros.ImplicitCTX().Env),
        fun (x) { <[ ignore (result.Append ($x)) ]> });
    <[
        def result = StringBuilder ();
        { ..$sequence };
        result.ToString ()
    ]>
}


это я его фактически переписал внутрь моего макра
а MyHelper.my_make_splice_distribution это из io.n один-в-один

в общем-то прога заработала на ура:
 def l = '\\';
 def q = '\"';
 def b = '\$';
 def n = '\n';
 screw def s = " def l = '$l$l';$n def q = '$l$q';$n def b = '$l$b';$n def n = '$(l)n';$n screw def s = $q$s$q;$n$n def introspect()$n {$n  System.Console.WriteLine(nut s);$n }$n$n introspect();";

 def introspect()
 {
  System.Console.WriteLine(nut s);
 }

 introspect();

хотя конечно, т.к. я использовал макросы, за полноценное решение исходной задачи это засчитать нельзя
зато подразобрался с макросами

вот возник вопрос в связи с этим:
если есть как минимум 3 уровня (макрос-сборка, макрос-сборка, сборка)
то вроде как возникают проблемы с отключением гигиены...
на данном примере: хотя в макросе sprint используются $(x : usesite) модификаторы, но применить его в моем макросе нельзя
он пишет, что мои переменные unbound...
вышеописанным действием я фактически удалил один уровень (stage)
так вот не будут ли с этим проблемы с применением многоуровневой макросистемы в проекте?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: отцы, помогайте
От: Oyster Украина https://github.com/devoyster
Дата: 13.07.06 13:53
Оценка:
Здравствуйте, PhantomIvan, Вы писали:

PI>вот возник вопрос в связи с этим:

PI>если есть как минимум 3 уровня (макрос-сборка, макрос-сборка, сборка)
PI>то вроде как возникают проблемы с отключением гигиены...

У меня никогда никаких проблем не возникало.

PI>на данном примере: хотя в макросе sprint используются $(x : usesite) модификаторы, но применить его в моем макросе нельзя

PI>он пишет, что мои переменные unbound...

Ты ведь знаешь, что "usesite" не отключает гигиену, правда? Это "dyn" отключает гигиену.

PI>вышеописанным действием я фактически удалил один уровень (stage)


Опять не понял но объяснять не надо — я не настроен сегодня на понимание

PI>так вот не будут ли с этим проблемы с применением многоуровневой макросистемы в проекте?


Re[4]: отцы, помогайте
От: PhantomIvan  
Дата: 13.07.06 14:07
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Здравствуйте, PhantomIvan, Вы писали:


PI>>вот возник вопрос в связи с этим:

PI>>если есть как минимум 3 уровня (макрос-сборка, макрос-сборка, сборка)
PI>>то вроде как возникают проблемы с отключением гигиены...

O>У меня никогда никаких проблем не возникало.


а сколько у тебя stage-ей было?

PI>>на данном примере: хотя в макросе sprint используются $(x : usesite) модификаторы, но применить его в моем макросе нельзя

PI>>он пишет, что мои переменные unbound...

O>Ты ведь знаешь, что "usesite" не отключает гигиену, правда? Это "dyn" отключает гигиену.


нет, особо не улавливаю разницы пока...

вообще в условиях отсутствия нормальной документации, видимо придется изучать сорцы компилятора
чтобы понять как эффективно макросы писать... правда?
сначала хотелось верить что в компилятор особо лезть не нужно будет... впрочем так ведь и не нужно было... пока я до макросов не дошёл
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: отцы, помогайте
От: Oyster Украина https://github.com/devoyster
Дата: 13.07.06 14:26
Оценка:
Здравствуйте, PhantomIvan, Вы писали:

PI>а сколько у тебя stage-ей было?


Столько же было.

O>>Ты ведь знаешь, что "usesite" не отключает гигиену, правда? Это "dyn" отключает гигиену.


PI>нет, особо не улавливаю разницы пока...


Разница очень простая и чёткая: "usesite" не нарушает гигиену (с чего ты взял обратное?), "dyn" нарушает.

PI>вообще в условиях отсутствия нормальной документации, видимо придется изучать сорцы компилятора

PI>чтобы понять как эффективно макросы писать... правда?

Ну вообще-то так дела сейчас и обстоят — я очень часто заглядывал в сорцы, когда копался с Nemerle.
Re[6]: отцы, помогайте
От: Vermicious Knid  
Дата: 14.07.06 03:44
Оценка: 41 (2) +1
Здравствуйте, Oyster, Вы писали:

O>Разница очень простая и чёткая: "usesite" не нарушает гигиену (с чего ты взял обратное?), "dyn" нарушает.

Они оба нарушают гигиену, но с различной "разрушительной силой".

В качестве иллюстрации.
macro testHygiene(otherCode = <[ ]>)
{
    <[ def n = 1; $otherCode ]>
}

macro testHygiene2()
{
    <[ def n = 3; breakHygiene() ]>
}

macro completelyBreakHygiene(id : string = "n")
{
    <[ System.Console.WriteLine($(id : dyn)) ]>
}

macro breakHygiene(id : string = "n")
{
    <[ System.Console.WriteLine($(id : usesite)) ]>
}

testHygiene(breakHygiene()); // не скомпилируется - unbound name 'n'
testHygiene(completelyBreakHygiene()); // выведет в консоль 1
def n = 2; breakHygiene(); // выведет 2
testHygiene2(); // выведет 3

В каких еще случаях проявляется разница между dyn и usesite я честно говоря не знаю. Но думаю, что они есть. Судя по всему usesite все таки подчиняется каким-то правилам, а вот dyn игнорирует все правила, которые можно игнорировать.

O>Ну вообще-то так дела сейчас и обстоят — я очень часто заглядывал в сорцы, когда копался с Nemerle.

Все зависит от сложности и специфики задачи. Очень часто вполне достаточно заглядывать в сорцы стандартных макросов(это не совсем одно и тоже, что сорцы компилятора ). Да и та документация по макросам, которая есть тоже не совсем бесполезна.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.