Re[3]: еще один вариант построения DSL
От: Ziaw Россия  
Дата: 26.06.10 00:56
Оценка:
Здравствуйте, VladD2, Вы писали:

Z>>у нас есть грамматика, есть некий ast который она создает. не зря ли мы смешиваем грамматики и ast? может быть грамматика отдельно, AST отдельно?


VD>Задача макроса — вернуть некоторый АСТ. Так что я вообще не понимаю о чем идет речь.


Речь идет о том, что вместо конкретного макроса в синтаксисе можно указывать их подмножество, которое можно потом расширять макросами, которые неизвестны на этапе разработки.

Z>>
Z>>    macro XmlAttr: Xml.Attr
Z>>    syntax name '=' value
Z>>    where name : PExpr.Ref, value : PExpr.Expr
Z>>    {
Z>>       Xml.Attr(name.Name, value);
Z>>    }
Z>>


VD>Я вижу тут банальное задание типов для элементов грамматики. В этом нет смысла, так как типы и так известны. Ведь каждое имя — это имя макроса у которого и так известен возвращаемый им тип.


Я предлагаю задавать элементы не только именами макросов, но и типами AST. Впрочем синтаксис задания их именами я толком не продумывал, можно во where двоеточие оставить для имени, а is для типа. Это пока неважно, важна идея указывать открытое подмножество макросов.

Z>>Где <()> антицитата, уточнение типа потребуется парсеру. Идея в том, чтобы PExpr'ы генерили код, а остальной Ast генерил обычные конструкторы, что то типа expression tree в C#.


VD>PExpr — это тоже "обычные конструкторы".


Да, но они не генерят в код свой собственный вызов.

Z>>Либо вариант, с возможностью выбора подходящего возвращаемого значения:


VD>Зачем это все?


Способы протащить AST в код, это уже другая идея, слабо связанная с первой. Может быть и не особо востребованная.
Re[3]: еще один вариант построения DSL
От: Тролль зеленый и толстый  
Дата: 26.06.10 23:13
Оценка:
VD>Задача макроса — вернуть некоторый АСТ.

Кстати, а нельзя это АСТ генерировать автоматически, используя информацию из грамматики?

Ведь в этом примере тела макросов это просто boilerplate, который мог бы делаться автоматически:

macro class Xml
{
  macro tagOpen(lt, _, id, attrs, gt, _) : XmlAst.TagOpen
  syntax: '<' s identifier attr* '>' s
  {
    TagOpen(lt.StartPos, gt.EndPos, id.Value, attrs.Map(x => x.Value :> Attr))
  }

  macro attr(id, _, _, value) : XmlAst
  syntax: identifier '=' s attrValue;
  {
    Attr(id.StartPos, value.EndPos, id, value)
  }
}


Пример мог бы стать таким:

language Xml
{
  TagOpen = '<' id:Identifier attrs:Attr* '>';
  Attr = id:Identifier '=' value:AttrValue;
}


Из этого описания в пространстве имен Xml.Ast будет создан класс TagOpen с полями id и attrs, и класс Attr с полями id и value.

Конечно, бывают случаи, где нужна какие-то преобразования, но для только них и можно сделать какую-то поддержку, чтобы все остальные тривиальные случаи обрабатывались автоматически.
Re[4]: еще один вариант построения DSL
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.06.10 14:32
Оценка:
Здравствуйте, Тролль зеленый и толстый, Вы писали:

ТЗИ>Конечно, бывают случаи, где нужна какие-то преобразования,


Бывают. И чаще чем кажется. Многие макры содержат весьма сложную логику.

ТЗИ>но для только них и можно сделать какую-то поддержку, чтобы все остальные тривиальные случаи обрабатывались автоматически.


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

ТЗИ>Пример мог бы стать таким:


ТЗИ>
ТЗИ>language Xml
ТЗИ>{
ТЗИ>  TagOpen = '<' id:Identifier attrs:Attr* '>';
ТЗИ>  Attr = id:Identifier '=' value:AttrValue;
ТЗИ>}
ТЗИ>


Тут сразу встает несколько вопросов.
1. Для работы интеграции (да и для компилятора) нужны местоположения всех "токенов". В данном примере нужны местоположения для '<', '>' и '=', не говоря уже о именованных полях (id, attrs, id, value). Не ясно в каком виде все это дело представлять.
2. AST обычно генерируется не из классов, а из вхождений вариантных типов. Не ясно как вводить эти вариантные типы (или иными словами как группировать элементы AST?)?
3. В новой версии Nemerle планируется ввести в AST информацию о типах. Она будет заполняться по мере типизации. Сейчас в процессе типизации создается отдельное типизированное AST. Этот подход создает ряд сложностей. Кроме того такое преобразование так же является ручным процессом, что приводит к массе ошибок.
4. Так как AST должно быть расширяемым, нужно подумать о том как сопрягать разные виды AST и как расширять отдельные его виды.

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

Если подумать, то в одном пакете (назовем это так) можно располагать множество декларативных (назовем это так) макросов и ряд рукописных (которые будут осуществлять какие-то действия).

Но для этого нужно как-то решить описанные выше вопросы.

ТЗИ>Из этого описания в пространстве имен Xml.Ast будет создан класс TagOpen с полями id и attrs, и класс Attr с полями id и value.


Как я уже говорил выше, создавать нужно не классы, а variant-ы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: еще один вариант построения DSL
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.06.10 18:03
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Речь идет о том, что вместо конкретного макроса в синтаксисе можно указывать их подмножество, которое можно потом расширять макросами, которые неизвестны на этапе разработки.


Для расширения предусмотрены точки расширения. Это почти то о чем ты говоришь. Они описывают места и правила подстановки расширений.

Z>Я предлагаю задавать элементы не только именами макросов, но и типами AST. Впрочем синтаксис задания их именами я толком не продумывал, можно во where двоеточие оставить для имени, а is для типа. Это пока неважно, важна идея указывать открытое подмножество макросов.


Опять ничего не понял. Приведи примеры.

Z>>>Где <()> антицитата, уточнение типа потребуется парсеру. Идея в том, чтобы PExpr'ы генерили код, а остальной Ast генерил обычные конструкторы, что то типа expression tree в C#.


VD>>PExpr — это тоже "обычные конструкторы".


Z>Да, но они не генерят в код свой собственный вызов.


Бррр. Не странно но что мы не можем с тобой ни о чем договориться. Казалось бы в этой теме я должен понимать все, но я опять не понимаю твоих слов.

Z>>>Либо вариант, с возможностью выбора подходящего возвращаемого значения:


VD>>Зачем это все?


Z>Способы протащить AST в код, это уже другая идея, слабо связанная с первой. Может быть и не особо востребованная.


Я не телепат.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: еще один вариант построения DSL
От: Ziaw Россия  
Дата: 28.06.10 19:07
Оценка:
Здравствуйте, VladD2, Вы писали:

Z>>Речь идет о том, что вместо конкретного макроса в синтаксисе можно указывать их подмножество, которое можно потом расширять макросами, которые неизвестны на этапе разработки.


VD>Для расширения предусмотрены точки расширения. Это почти то о чем ты говоришь. Они описывают места и правила подстановки расширений.


А можно подробнее про точки расширения?

Z>>Я предлагаю задавать элементы не только именами макросов, но и типами AST. Впрочем синтаксис задания их именами я толком не продумывал, можно во where двоеточие оставить для имени, а is для типа. Это пока неважно, важна идея указывать открытое подмножество макросов.


VD>Опять ничего не понял. Приведи примеры.


Допустим кто-то разработал грамматику для Xml
macro XmlElement : Xml.Element
syntax start children:subNode* end // children это алиас для списка вложенных тегов
where start : XmlStartTag, subNode : XmlElement, end : XmlEndTag // уточняем парсеру типы элементов грамматики, XmlStartTag, XmlElement, XmlEndTag
{
  Xml.XmlElement(start.Name, start.Attrs, children)
}


Добавить в такой синтаксис элемент вида <node a="1"/> становится не так просто (это просто пример не заложенной изначально в синтаксис конструкции), но если мы сделаем так:

macro XmlElement : Xml.Element
syntax start children:subNode* end 
where start : XmlStartTag, subNode is Xml.Element, end : XmlEndTag // теперь subNode может быть любым макросом возвращающим Xml.Element
{
  Xml.XmlElement(start.Name, start.Attrs, children)
}

// то сможем расширить синтаксис примерно так
macro XmlEmptyElement : Xml.Element
syntax '<' name attrs:attr* '/>'
where name : XmlName, attr is Xml.Attr
{
  Xml.XmlElement(name.Name, attrs, [])
}



VD>Бррр. Не странно но что мы не можем с тобой ни о чем договориться. Казалось бы в этой теме я должен понимать все, но я опять не понимаю твоих слов.

VD>Я не телепат.

В этой части я думал над тем, как передавать бесшовно аст из макросов в выполняемый код и обратно. Но что-то сыро получается На примере того же XML — хотелось бы иметь возможность сгенерить пачку атрибутов в рантайме и бесшовно подсунуть в грамматику.

def attrs = [Xml.Attr("a", "1"), Xml.Attr("b", "2")];

def xml = <foo $(attrs : list[Xml.Attr]) />; // сахар для Xml.XmlElement("foo", attrs, []), уточнение типа понадобится парсеру


Вобщем черт его знает, как-то все сыро. Давай пока эту тему отложим.
Re[6]: еще один вариант построения DSL
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.06.10 22:31
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>А можно подробнее про точки расширения?


В двух словах — мы позволяет пометить некоторое правило как расширяемое, а компилятор для такого макроса сгенерит такую грамматку:
rule = extPoint1 / ruleImpl / extPoint2;

Это в дальнейшем позволит позволит создавать другие макросы указывая что они расширяют точки расширения extPoint1 и/или extPoint2. Далее когда компилятор будет читать список открытых пространств имен, если в них встречаются макросы расширяющие точки расширения считанные к данному моменту, то они встраивают эти макросы вместо этих точек. При этом так же должны учитываться зависимости приоритеты. Это даст возможность сформировать желаемый порядок выполнения расширений (попыток разбора грамматик определяемых макросами вставляемых в точки расширения).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.