Re[6]: Как сделать и найти метку в дереве AST
От: FDSC Россия consp11.github.io блог
Дата: 07.08.11 02:45
Оценка:
Здравствуйте, VladD2, Вы писали:

FDS>>Могу поучаствовать в документировании AST,


VD>Давай.


Что конкретно делать в смысле общественной полезности?

VD>Как я уже упоминал, лучшая методика тут — использование отладчика и просмотр примеров кода (из компилятора и библиотек).


Ещё можно попробовать дампить квазицитаты и AST в текстовый файл через рефлексию. Правда не знаю, возможно ли делать что-то такое:
def exp = "def y = 2 + 1";
Dump(exp, <[$(exp: string)]>); // Dump - нечто, что дампит строку в первом параметре и AST во втором



VD>В купе это ~ 150К кода. Причем кода довольно простого, так как это в основном декларации.


Ага, я его уже видел. На первый взгляд, кстати, сильно понятнее, чем gcc
Re[5]: Как сделать и найти метку в дереве AST
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.08.11 13:25
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>>>Я так понимаю, что в сумме получится для doing список

VD>>Э... а что значит doing?
FDS>При обработке метода doing тестового класса
FDS>>>
FDS>>>[FileStates.Opened, FileStates.Opened]
FDS>>>


А, да. Первый элемент ведь присоединен для универсальности.

FDS>>>Но зачем указывать $(name : usesite) ?

VD>>Для преобразования строки в имя с цветом таким как у места использования (usesite-а).
VD>>Как я уже написал выше, можно было обойтись без преобразования в строки и обратно.

FDS>Я вот не очень понял, что в этот момент происходит, что такое "цвет". Мне всегда казалось, что если я напишу

FDS>def name = "x";
FDS><[$(name: usesite) = 984]>

FDS>То вернётся что-то типа

FDS><[x_1 = 984]>

FDS>т.е. будет произведена подстановка на место переменной какой-то другой, чтобы скрыть её от повторения


Не совсем так. Есть так называемый глобальный цвет (за него принята единица). Он присваивается все объектам спарсеным из исходников. Если у имени этот цвет, то альфа-переименование не производится. Имена генерируемые в контексте макросов получают уникальные цвета. Даже одно и та же квази-цитата породит объекты разных цветов, если она будет вызвана в разных сессиях раскрытия макросов.

Далее есть понятие внешнего контекста. Скажем если у нас есть один макрос который пытается раскрыть другой макрос, то контекстом для этого другого макроса будет текущий макрос.
Если в таких условиях воспользоваться $(x : usesite), то цвет полученного имени будет таким же как во внешнем макросе.

Но большинство макросов раскрываются в контексте парсера. А у парсера цвет равен единице. Стало быть $(x : usesite) породит имя с цветом 1. Ну, а такое имя, как указывалось выше, не подвергается альфа-переименованию.

То что $(x : usesite) учитывает цвет внешнего контекста делает его предпочтительным. Это позволяет избежать перекрытия имен.

FDS>Но тогда непонятно, собственно, зачем это делать сейчас, ведь $name — это идентификатор состояния, например, "Opened", который подставляется к "FileStates." и с ним ничего такого не нужно делать. Или нет?


Если мы уже работаем с именем (как в переделанном примере), то с именем действительно делать ничего не надо, так как оно получено от парсера и имеет тот цвет что нужно (внешнего контекста). Но если мы имеем дело со строками (как в моем исходном примере), то строки нужно привести к цвету испольуемому во внешнем контексте. И $(x : usesite) позволяет это сделать.

В общем случае мы вообще не можем использовать строки в квази-цитатах (чтобы не произошло случайного захвата имен). Если мы хотим подставить строку вместо имени, то должны использовать одну из цитат:
$(x : usesite) // имя получит цвет внешнего контекста
$(x : dyn)     // имя будет совместимым с любым именем доступным в текущей области видимости
$(x : global)  // имя получит цвет глобального контекста (контекста парсера, т.е. 1)

Из всех вариантов usesite самый безопасный. Потому и используется по умолчанию.

VD>>Тут еще раз стоит упомянуть о том, что в Немерле нельзя игнорировать предупреждения. Если внимательно присмотреться к ним, то будет ясно, в чем проблема.

VD>>Происходит это потому, что компилятор воспринимает имена int и string за имена переменных. А так как эти переменные нигде не используются, то получается предупреждение.

FDS>Было у меня такое подозрение Только как-то это странно: непонятно, какой логикой он руководствуется. Здесь ему так нравится, тут — сяк...


Ну, в этом контексте можно объявлять только переменные. Так что парсер просто плюет на то, что это ключевое слово.
Парсер Н2 будет еще гибче, так как будет безлексерным.

FDS>Влад, а почему вот это не работает (этот кусок изначально был [немного его поправил], просто погряз в других math):

FDS>[Nemerle]
FDS> | <[ $vlsn: string ]> => (true, vlsn)
FDS> | <[ ($vlasList : list[string]) ]> => (true, vlasList)
FDS>Разве это не то самое?

Ну, это вообще какая-то чушь. Например, цитата <[ $vlsn: string ]> будет разбирать код вида "a : string" или "любое_имя : string".
Чтобы сматчить строковый литерал, нужно использовать цитату <[ $(vlsn : string) ]>. И это не матчинг по типу. Это матчинг именно строкового литерала. Т.е. последний паттерн спарсит "" или "другую строку". Паттерн <[ $(vlsn : list[string]) ]> вообще не имеет смысла, так как таких литералов не бывает.

VD>>Кстати, это отличная тренировочная задача! Решив ее, ты будешь знать о макросах намного больше!


FDS>Попытаюсь завтра


Но учти — это весьма сложная задача. Для ее решения нужно разобраться не только с азами квази-цитирования, но понимать как работать с типизацией. Так что не стесняйся советоваться.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Как сделать и найти метку в дереве AST
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.08.11 15:34
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>>>Могу поучаствовать в документировании AST,


VD>>Давай.


FDS>Что конкретно делать в смысле общественной полезности?


Ну, ты же сам сказал "поучаствовать в документировании AST". Тебе даже виднее, что и как документировать, так как мой глаз уже сильно замылен.

VD>>Как я уже упоминал, лучшая методика тут — использование отладчика и просмотр примеров кода (из компилятора и библиотек).


FDS>Ещё можно попробовать дампить квазицитаты и AST в текстовый файл через рефлексию. Правда не знаю, возможно ли делать что-то такое:

FDS>
FDS>def exp = "def y = 2 + 1";
FDS>Dump(exp, <[$(exp: string)]>); // Dump - нечто, что дампит строку в первом параметре и AST во втором
FDS>


Тут вообще не нужны рефлексия. Я немного посидел сегодня и создал такое приложение. Единственная проблема — макросы можно распечатывать только изнутри макро-сборки, так как для их лифтинга требуется макро-контекст.
Солюшен с этим делом можно взять здесь.
Солюшен состоит из трех проектов в каждом из которых по одному значимому файлу.
Первый макро-проект DumpImp, содержим реализацию макроса занимающегося непосредственно дампом (файл DumpPExpr.n):
  Скрытый текст
using Nemerle;
using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;

namespace DumpImp
{
  macro DumpPExpr(expr : PExpr)
  {
    def lifted = Macros.quoted_expr(expr).ToString();
    def source = expr.ToString();
 
    <[ ($(source : string), $(lifted : string)) ]>
  }
}

Второй маро-проект DumpContext нужен в следствии того, что лифтингу для работы требуется наличие макро-контекст. Это препятствует тому чтобы использовать DumpPExpr из обычного консольного приложения. Макрос DumpPExpr нужно использовать в рамках другого макро-проекта. Вот по этому и нужен DumpContex. Вот его основной файл:
Macro1.n
  Скрытый текст
using Nemerle;
using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Compiler.Typedtree;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;
using DumpImp;

namespace DumpContext
{
  macro PrintDump()
  {
    PrintDumpImpl.DoTransform(Macros.ImplicitCTX())
  }
  
  module PrintDumpImpl
  {
    public DoTransform(typer : Typer) : PExpr
    {
      Macros.DefineCTX(typer);
      mutable xs = [];
      xs ::= DumpPExpr("test string");
      xs ::= DumpPExpr($(a : dyn));
      xs ::= DumpPExpr($(x : usesite));
      xs ::= DumpPExpr(x + 1);
      xs ::= DumpPExpr(func_call());
      xs ::= DumpPExpr(func_call(arg1));
      xs ::= DumpPExpr(func_call($args));
      xs ::= DumpPExpr($f($args));
      
      def maxExprLen = xs.Max((expr, _) => expr.Length);
      def exprs = xs.RevMap((expr, lifted) => <[
        def expr = $(expr : string);
        System.Console.ForegroundColor = ConsoleColor.Cyan;
        System.Console.Write(expr);
        System.Console.ResetColor();
        def padding = $(maxExprLen : int) - expr.Length;
        System.Console.Write(":" + string(' ', padding));
        System.Console.WriteLine($(lifted : string));
        System.Console.ResetColor();
      ]>);

      <[ { ..$exprs } ]>
    }
  }
}

Ну, и чтобы все это дело запустить и что-то сгенерировать нужно консольное приложение, которое просто раскроет макрос PrintDump.
  Скрытый текст
using System.Console;
using DumpContext;

module Program
{
  Main() : void
  {
    PrintDump();
    _ = ReadLine();
  }
}


Выражения которые требуется раскрыть нужно задавать внутри макроса PrintDump следующим образом:
      xs ::= DumpPExpr("test string");
      xs ::= DumpPExpr($(a : dyn));
      xs ::= DumpPExpr($(x : usesite));
      xs ::= DumpPExpr(x + 1);
      xs ::= DumpPExpr(func_call());
      xs ::= DumpPExpr(func_call(arg1));
      xs ::= DumpPExpr(func_call($args));
      xs ::= DumpPExpr($f($args));

В результате выполнения этого дела на консоль будет выведено следующее:
"test string":     PExpr.Literal(Literal.String("test string", "\"test string\""))
$((a : dyn)):      PExpr.Ref(Name(a, -1, null))
$((x : usesite)):  PExpr.Ref(Name(x, ManagerClass.Instance.MacroColors.UseColor, ManagerClass.Instance.MacroColors.UseContext))
x + 1:             PExpr.Call(PExpr.Ref(Name.NameInCurrentColor("+", _N_MacroContexts.Get(1, ManagerClass.Instance))),
                   [PExpr.Ref(Name.NameInCurrentColor("x", _N_MacroContexts.Get(1, ManagerClass.Instance))), 
                   PExpr.Literal(Literal.Integer(1, false, null).WithProperType())])
func_call():       PExpr.Call(PExpr.Ref(Name.NameInCurrentColor("func_call", _N_MacroContexts.Get(1, ManagerClass.Instance))), [])
func_call(arg1):   PExpr.Call(PExpr.Ref(Name.NameInCurrentColor("func_call", _N_MacroContexts.Get(1, ManagerClass.Instance))), 
                   [PExpr.Ref(Name.NameInCurrentColor("arg1", _N_MacroContexts.Get(1, ManagerClass.Instance)))])
func_call($(args)):PExpr.Call(PExpr.Ref(Name.NameInCurrentColor("func_call", _N_MacroContexts.Get(1, ManagerClass.Instance))), [args])
$(f)($(args)):     PExpr.Call(f, [args])

(отформатировано для лучшего влезания на экран).

VD>>В купе это ~ 150К кода. Причем кода довольно простого, так как это в основном декларации.


FDS>Ага, я его уже видел. На первый взгляд, кстати, сильно понятнее, чем gcc


Ну, дык вариантные типы рулят!
Хотя за бардак в именах авторам нужно было бы глаз на зад натянуть.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Как сделать и найти метку в дереве AST
От: FDSC Россия consp11.github.io блог
Дата: 07.08.11 17:20
Оценка:
Здравствуйте, VladD2, Вы писали:

FDS>>Что конкретно делать в смысле общественной полезности?


VD>Ну, ты же сам сказал "поучаствовать в документировании AST". Тебе даже виднее, что и как документировать, так как мой глаз уже сильно замылен.


Формат документации (RSDN Authoring Pack для статей у меня не работает): в чём именно лучше документировать?

VD>Тут вообще не нужны рефлексия. Я немного посидел сегодня и создал такое приложение. Единственная проблема — макросы можно распечатывать только изнутри макро-сборки, так как для их лифтинга требуется макро-контекст.

VD>Солюшен с этим делом можно взять здесь.

Ага, посмотрел. Работает. Сейчас немного форматирование только сделаю более читаемым
Спасибо
Re[9]: Как сделать и найти метку в дереве AST
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.08.11 18:41
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Формат документации (RSDN Authoring Pack для статей у меня не работает):


А в чем проблема?

FDS>в чём именно лучше документировать?


Можно сразу в вики, если на английском.
Можно в РСДН-овскую вики.
Если запустится Authoring Pack, то оптимально в нем делать.

FDS>Ага, посмотрел. Работает. Сейчас немного форматирование только сделаю более читаемым

FDS>Спасибо

Не за что.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Как сделать и найти метку в дереве AST
От: FDSC Россия consp11.github.io блог
Дата: 07.08.11 18:56
Оценка:
Здравствуйте, VladD2, Вы писали:

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


FDS>>Формат документации (RSDN Authoring Pack для статей у меня не работает):


VD>А в чем проблема?


здесь
Автор: FDSC
Дата: 06.08.11


FDS>>в чём именно лучше документировать?


VD>Можно сразу в вики, если на английском.


Не, я буду на русском.

VD>Можно в РСДН-овскую вики.


rsdn-овская — это где?

VD>Если запустится Authoring Pack, то оптимально в нем делать.


Re[11]: Как сделать и найти метку в дереве AST
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.08.11 19:50
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>здесь
Автор: FDSC
Дата: 06.08.11


Отвечу там.

VD>>Можно сразу в вики, если на английском.

FDS>Не, я буду на русском.
VD>>Можно в РСДН-овскую вики.

FDS>rsdn-овская — это где?


http://wiki.rsdn.ru/
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: AST
От: FDSC Россия consp11.github.io блог
Дата: 07.08.11 22:34
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Тут вообще не нужны рефлексия. Я немного посидел сегодня и создал такое приложение. Единственная проблема — макросы можно распечатывать только изнутри макро-сборки, так как для их лифтинга требуется макро-контекст.

VD>Солюшен с этим делом можно взять здесь.


Сделал ещё через рефлекшн, чтобы можно было сравнивать

На всяк пожарный, выкладываю
здесь
ast dump
Re[9]: AST
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.08.11 11:07
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Сделал ещё через рефлекшн, чтобы можно было сравнивать


Кстати, хорошей идеей было бы сделать визуалайзер для студии который бы показывал бы содержимое выбранной переменной в разных видах, в том числе предлагая паттерны для распознавания хранящегося в ней АСТ.

Если не в лом, можешь сделать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: AST
От: FDSC Россия consp11.github.io блог
Дата: 11.08.11 12:24
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Кстати, хорошей идеей было бы сделать визуалайзер для студии который бы показывал бы содержимое выбранной переменной в разных видах, в том числе предлагая паттерны для распознавания хранящегося в ней АСТ.


VD>Если не в лом, можешь сделать.


Честно говоря, даже не знаю, с какого конца браться.
Я сейчас пытаюсь просто AST в виде rsdn-статьи по шаблону задокументировать (примерами макросов, получающих различные декларации и обрабатывающими код). Когда разберусь с форматом (кажется, это надолго, я только с декларациями верхнего уровня и уровня класса разбирался дня три — просто как их получить ), можно будет смотреть дальше.


Вообще, забавная ситуация, в декларациях верхнего уровня варианты декларируются типом TopDeclaration.Variant, а в декларациях внутри класса они становятся типа ClassMember.Class, а вариантного типа в ClassMember вообще нет
Re[11]: AST
От: hardcase Пират http://nemerle.org
Дата: 11.08.11 12:27
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Вообще, забавная ситуация, в декларациях верхнего уровня варианты декларируются типом TopDeclaration.Variant, а в декларациях внутри класса они становятся типа ClassMember.Class, а вариантного типа в ClassMember вообще нет


ClassMember.Class должен по уму называться ClassMember.NestedType. Внутри он содержит какраз объявление типа.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[11]: AST
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.08.11 13:53
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Честно говоря, даже не знаю, с какого конца браться.

FDS>Я сейчас пытаюсь просто AST в виде rsdn-статьи по шаблону задокументировать (примерами макросов, получающих различные декларации и обрабатывающими код). Когда разберусь с форматом (кажется, это надолго, я только с декларациями верхнего уровня и уровня класса разбирался дня три — просто как их получить ), можно будет смотреть дальше.

OK. Похоже моя идея — перебор.

FDS>Вообще, забавная ситуация, в декларациях верхнего уровня варианты декларируются типом TopDeclaration.Variant, а в декларациях внутри класса они становятся типа ClassMember.Class, а вариантного типа в ClassMember вообще нет


ClassMember.Class содержит ссылку на TopDeclaration, что позволяет запаковывать в него любой тип.

Вообще, проще не декомпилировать что-то, а находить определение этого чего-то. Сделать это не трудно. Просто поиском по содержимому файлов ищешь "variant Xxx", где вместо Xxx нужный тип. Не нашлось, ищешь "class Xxx".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: AST
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.08.11 13:57
Оценка:
Здравствуйте, hardcase, Вы писали:

H>ClassMember.Class должен по уму называться ClassMember.NestedType. Внутри он содержит какраз объявление типа.


По уму ClassMember нужно было бы назвать TypeMember, ClassMember.Class, соответственно TypeMember.Type. То что он Nested и так понятно из того что он Member. Но это поломает обратную совместимость. Да и не особо нужно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: AST
От: FDSC Россия consp11.github.io блог
Дата: 11.08.11 14:42
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>ClassMember.Class содержит ссылку на TopDeclaration, что позволяет запаковывать в него любой тип.


VD>Вообще, проще не декомпилировать что-то, а находить определение этого чего-то. Сделать это не трудно. Просто поиском по содержимому файлов ищешь "variant Xxx", где вместо Xxx нужный тип. Не нашлось, ищешь "class Xxx".


Я так и делаю: открываю немерлевский проект в VS2010 и ищу по всем исходникам со словами macro, class, variant, module.
Просто ещё ж надо код сделать, чтобы он правильно это получал — иначе что это за документация, без примеров кода.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.