[Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.10.14 23:00
Оценка: 15 (1)
Здравствуйте, VladD2, Вы писали:

VD>Как обещал ранее, обновил Nitra Roadmap


Пару слов по поводу символов, деклараций и биндинга, раз уж оно интересно и не понятно.

Все метаданные в Нитра выражаются через символы. Символ — это эдакий объект описывающий ту или иную сущность языка. У символов есть типы (что-то вроде классов).

В общем-то задача процесса типизации пройтись по исходникам преобразовать информацию из них в граф символов. Примером сиволов можно считать рефлексию дотнета. Только объекты рефлексии описывают финсированный набор символов, а Найтра будет предоставлять возможность вводить собственные типы символов.

Любая ссылка внутри кода может быть только на символы. Скажем, если у вас в языке есть запись:
a + b

то a и b — это ссылки на некоторые символы. Задача процесса связывания найти символы на которые ссылаются эти a и b, а общая задача процесса типизации вычислить полный набор символов и связать с ними все имена. Конечно это не весь круг задач типизации, но важная его часть.

Разные языки организуют символы по разному. В некоторых языках вроде Немерла, Шарпа и Найтры есть глобальное дерево символов организованное в пространства имен. Найтра будет предоставлять подобные пресеты для часто используемых случаев и позволять создавать свои.

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

На практике не всегда просто отобразить Дерево разбора (детальный АСТ порождаемый Найтрой) на символы. Во-первых, разные синтаксические конструкции могут отображаться на одинаковые типы символов, во-вторых, отображение может быть не прямолинейным, в-третьих, при отображении есть некоторые проблемы с производительностью.

Проект может быть большим и довольно наивно пытаться производить полное отображение ДР (дерева разбора) при каждом изменении. По этому мы вводим промежуточную структур — декларацию. Декларация — это что-то типа АСТ файла (еденицы компиляции) только содержит оно исключительно конструкции верхнего уровня. Скажем для Шарпа в декларации будут попадать пространства имен (объявленные в файле плюс глобальное пространство файла), типы и их члены. Код членов (методов, свойств и т.п.) в них попадать не будет.

Для каждого файла создается дерево деклараций. Оно автоматически сериализуется и при открытии проекта нет нужды парсить все его файлы снова. При изменении файла декларации для его автоматически пересоздаются.

Декларации создаются на основе так называемых отображений. Это эдакая декларативная запись говорящая что брать из ДР и куда помещать в декларации. Пример деклараций и отображения можно поглядеть в проекте нового форматера РСДН-а (правда там они используются как AST, в целях тестирования).

Имея описание деклараций и отображение мы можем автоматически (при первой загрузке проекта или при изменении исходника) получать дерево деклараций. В дальнейшем они сериализуются и подгружаются при открытии проекта без парсинга.

Точно так же описываются символы и отображение с деклараций на символы.

При изменении сходника перестраивается дерево деклараций для измененного файла, старая версия деклараций "вычитается" из старого набора символов а новая, наоборот, накатывается. В результате этого процесса мы актуализируем символы и они начинают отражать актуальную информацию о проекте/солюшене.

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

Кроме того, автор языка должен задать описание областей видимости для своего языка. Если области видимости идут слева направо и сверху вниз, то области видимости задавать не надо, так как это дефолтное поведение. Если же области видмости отличаются от указанного подхода, то придется описать отличия явно. Пока что язык для этого не разработан, так что не буду приводить примеры. Лучше приведу примеры того где это актуально. Опять возьмем в качестве примера Шарп. При объявлении обобщенного метода в шарпе параметр типов может декларироваться правее его первого использования (в возвращаемом значении):
T Foo<T>() {}
▲     ▲
│     └─Декларация
└─Использование


Вот здесь в грамматике (точнее в расширяющем ее DSL-е) придется описать, что параметры типов видны не только правее и ниже по коду, но и левее, где описывается тип возвращаемого значения метода.

Такие случаи в языках встречаются редко, так что аннотаций будет не много.

Имея определенные области видимости, символы, декларации и отображение с ДР на декларации и с деклараций на символы мы можем связывать имена внутри программы.

В примере выше мы должны указать, что объявление параметра типов порождает символ типа "Параметр типов". Далее мы можем связать имя T использованное в типе возвращаемого значения с этим символом. Когда мы будем обрабатывать код на следующих этапах, то у всех идентификаторов можно будет узнать на какой символ они ссылаются.

Процесс сопоставления имен (ссылок) с символами называется связывание. Для его работы нужно иметь символы, области видимости и алгоритм связывания.

К сожалению, формализовать алгоритм связывания довольно не просто. Мы пока не имеем готового решения на этот счет. Так что любые предложения приветствуются. Если не получится придумать внятного декларативного описания принципов связывания имен, придется использовать для этого императивный код вынеся его в стратегию. В принципе такой код уже используется в самой Найтре. Но он довольно суров и тяжел в поддержке.

Еще раз повторюсь, если есть идеи по этому поводу, просьба ими делиться.

Связывание имен будет производиться в ленивом режиме, чтобы улучшить отклик в режиме IDE.

После связывания имен можно будет найти все ссылки на каждый из символов (будь то локальная переменная или синтаксический модуль).

Параллельно с этой работой мы будем работать над автоматической поддержкой символов в IDE. Символы и декларации должны будут автоматически обновляться при изменении исходников, при этом должны сбрасываться все затронутые связывания имен. При записи проекта на диск декларации сериализуются и пишутся в кэши. При загрузке проекта декларации загружаются из кэша. Так же из внешних библиотек загружаются хранящиеся в них символы (если язык поддерживает бинарные модули).

В итоге сразу после открытия проекта мы будем иметь граф символов поддерживаемый в актуальном состоянии при изменении сходников или библиотек.

Все это позволит создать создать такие сервисы IDE как:
1. Подсветка символов.
2. Навигация по символом (поиск деклараций, поиск ссылок).
3. Рефакторинг переименования.
4. Визуализация графа/дерева/списка символов (граф наследования, граф вызовов, ...).
5. Всплывающие подсказки с информацией о том на какой символ ссылается имя.
6. Комбы со списками деклараций из файла.

К сожалению, работы тут непочатый край. И код будет критичен к производительности. Так что этот этап займет не менее полугода (по моим оценкам).

29.10.14 02:03: Ветка выделена из темы [Nitra] Roadmap
Автор: VladD2
Дата: 27.10.14
— VladD2
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 28.10.2014 23:16 VladD2 . Предыдущая версия . Еще …
Отредактировано 28.10.2014 23:15 VladD2 . Предыдущая версия .
Отредактировано 28.10.2014 23:13 VladD2 . Предыдущая версия .
Отредактировано 28.10.2014 23:08 VladD2 . Предыдущая версия .
Re: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: btn1  
Дата: 29.10.14 10:52
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Пару слов по поводу символов, деклараций и биндинга, раз уж оно интересно и не понятно.


Я скажу больше — после прочитанного, мне вообще бы никогда в голову не пришло, о каких декларациях речь, если бы не документация!

VD>Символ — это эдакий объект описывающий ту или иную сущность языка.


Знак "+" — это тоже "символ"?

VD>Если язык подразумевает наличие внешних бинарных модулей или библиотек, то символы можно будет сериализовать и загружать в эти внешние модули


Э-э-э... Как можно загружать символы _ВО_ внешние модули? Я так понял, будет встроенная функция считывать символы ИЗ модулей? (и кэшировать, видимо)


VD>На практике не всегда просто отобразить Дерево разбора (детальный АСТ порождаемый Найтрой) на символы. Во-первых, разные синтаксические конструкции могут отображаться на одинаковые типы символов,


Вот тут непонятно. Раз символы — это какие-то терминалы из имён, какая разница в какие синтаксические конструкции они входят? Синтаксис — это вообще вопрос формы ветки в АСТ.

VD> во-вторых, отображение может быть не прямолинейным


Например?

Всё равно немного непонятна глубина проблемы. Пусть есть АСТ:

+
|\
a b


Здесь "a" и "b" — те самые символы из начала поста. Теперь нам нужно связать эти символы с конкретными сущностями — полем класса или локальной переменной, что угодно. Ну так пробегаемся по глобальному дереву имён и связываем!

VD>Декларация — это что-то типа АСТ файла (еденицы компиляции) только содержит оно исключительно конструкции верхнего уровня.


Суть понятна. Но как будут связываться локальные переменные? Типа "если не нашёл символ в дереве деклараций — ищи в локальном АСТ"?


VD>К сожалению, формализовать алгоритм связывания довольно не просто. Мы пока не имеем готового решения на этот счет. Так что любые предложения приветствуются. Если не получится придумать внятного декларативного описания принципов связывания имен....


эээ... а зачем "декларативно"? (да и возможно ли?) Это же задача разработчика языка — написать процедуру связки имён, мало ли что он себе в языке придумал! Вот пусть бегает по дереву и связывает.

VD>К сожалению, работы тут непочатый край. И код будет критичен к производительности. Так что этот этап займет не менее полугода (по моим оценкам).


Это да, не всё так просто, блин! Выскажу лишь идею: не стоит подобно разрабам WPF с головой уходить в декларативность. Если можно написать строчку кода или 5 строк деклараций, пусть лучше это будет строчка кода! (да и код ГИБЧЕ в развитии, чем прибитые гвоздями декларации)


Спасибо за разъяснения, Влад! Много текста, конечно, но я осилил А диаграммы были бы ещё круче!
Re: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: s22  
Дата: 03.11.14 07:03
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Кроме того, автор языка должен задать описание областей видимости для своего языка. Если области видимости идут слева направо и сверху вниз, то области видимости задавать не надо, так как это дефолтное поведение. Если же области видмости отличаются от указанного подхода, то придется описать отличия явно. Пока что язык для этого не разработан, так что не буду приводить примеры. Лучше приведу примеры того где это актуально. Опять возьмем в качестве примера Шарп. При объявлении обобщенного метода в шарпе параметр типов может декларироваться правее его первого использования (в возвращаемом значении):

VD>
VD>T Foo<T>() {}
VD>▲     ▲
VD>│     └─Декларация
VD>└─Использование
VD>


VD>Вот здесь в грамматике (точнее в расширяющем ее DSL-е) придется описать, что параметры типов видны не только правее и ниже по коду, но и левее, где описывается тип возвращаемого значения метода.


VD>Такие случаи в языках встречаются редко, так что аннотаций будет не много.



goto a1;

a2:

a=1;

goto a3;

a1:

int a;

goto a2;

a3:


в генерируемом коде такое встречатся сплошь и рядом.

Код надо преобразовывать в поток управления, а после уже разбирать.
Re[2]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.11.14 17:11
Оценка:
Здравствуйте, s22, Вы писали:

s22>
s22>goto a1;
s22>...
s22>a1:
s22>


s22>в генерируемом коде такое встречатся сплошь и рядом.


Это редкость везде. На одно goto есть 100500 других конструкций где область видимости классическая.

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

Куда разумнее описывать исключения из этого правила. Тогда аннотации связанные с областями видимости не будут напрягать создателей языков.

s22>Код надо преобразовывать в поток управления, а после уже разбирать.


Это тут никаким боком. Потоки управления к областям видимости отношения не имеют. Совращенные языки имеют статические области видимости. А там где есть динамические, они один фиг флоу-анализом не выводятся.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: s22  
Дата: 03.11.14 17:29
Оценка:
Здравствуйте, VladD2, Вы писали:

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


s22>>
s22>>goto a1;
s22>>...
s22>>a1:
s22>>


s22>>в генерируемом коде такое встречатся сплошь и рядом.


VD>Это редкость везде. На одно goto есть 100500 других конструкций где область видимости классическая.


VD>Тут вопрос очень прост. Мы можем заставить создателей языков указывать области видимости явно. Но это приведет к тому, что большая часть таких аннотаций будет протаскивать области вниз по дереву разбора и распространять их направо.


VD>Куда разумнее описывать исключения из этого правила. Тогда аннотации связанные с областями видимости не будут напрягать создателей языков.


s22>>Код надо преобразовывать в поток управления, а после уже разбирать.


VD>Это тут никаким боком. Потоки управления к областям видимости отношения не имеют. Совращенные языки имеют статические области видимости. А там где есть динамические, они один фиг флоу-анализом не выводятся.


И как ты предлагаешь описывать данное исключение? Если какой то вариант принципиально не описывается, то это уже не гуд.
По мне заставить явно описывать области видимости, например для раста придется все равно.
Re: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: s22  
Дата: 04.11.14 17:43
Оценка:
Так как быть с goto?
Re[2]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.11.14 21:56
Оценка:
Здравствуйте, s22, Вы писали:

s22>Так как быть с goto?


Во-первых, goto виден в той же области видимости, что и объявление метки. Но есть речь идет не о нестандартной области видмости, а о видимости во всем блоке. Языков с таким поведением масса. Например, локальные переменные в яваскрипте.
Во-вторых, если что-то не вписывается в поведение по умолчанию, то придется задать это дело явной аннотацией.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: s22  
Дата: 05.11.14 06:37
Оценка:
Здравствуйте, VladD2, Вы писали:

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


s22>>Так как быть с goto?


VD>Во-первых, goto виден в той же области видимости, что и объявление метки. Но есть речь идет не о нестандартной области видмости, а о видимости во всем блоке. Языков с таким поведением масса. Например, локальные переменные в яваскрипте.

VD>Во-вторых, если что-то не вписывается в поведение по умолчанию, то придется задать это дело явной аннотацией.

я не о метках goto (хотя порядок переход, а метка после тоже не гуд), а о порядке инициализации типа

Если идти в порядке сверху вниз, то в начале идет использование, а только после определение типа переменной.
Re[4]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.11.14 15:51
Оценка:
Здравствуйте, s22, Вы писали:

s22>я не о метках goto (хотя порядок переход, а метка после тоже не гуд), а о порядке инициализации типа


Какого типа?

s22>Если идти в порядке сверху вниз, то в начале идет использование, а только после определение типа переменной.


Какой переменной?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: s22  
Дата: 05.11.14 19:41
Оценка:
Здравствуйте, VladD2, Вы писали:

goto a1;
a2:
a=1;
goto a3;
a1:
int a;
goto a2;
a3:


Если поток сверху вниз, то первым идет инициализация переменной a (a=1), а потом только ее объявление (int a).
По мойму без предварительного построения графа управления это не разрешить.
Какие аннотации ты предлагаешь делать в подобном случае?
Будет ли язык разбирать подобный код? или надо будет делать после парсинга предварительное преобразование приводящее код в более простой вариант?
Как при этом измениться соответствие строк исходника и дерева разбора?
Re[6]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.11.14 20:57
Оценка:
Здравствуйте, s22, Вы писали:

s22>Если поток сверху вниз, то первым идет инициализация переменной a (a=1), а потом только ее объявление (int a).


Это некорректный код для большинства языков. А от потока управления области видимости не зависят ни в одном языке.

s22>Какие аннотации ты предлагаешь делать в подобном случае?


Я предлагаю не делать таких нелогичных языков. Нас проклянут за это.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: s22  
Дата: 09.11.14 10:31
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Я предлагаю не делать таких нелогичных языков. Нас проклянут за это.


C++ (gcc), C

такие языки уже к сожалению есть.

Но для собственного языка я такое делать не стал бы
Re[8]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: hardcase Пират http://nemerle.org
Дата: 11.11.14 15:36
Оценка:
Здравствуйте, s22, Вы писали:

s22>C++ (gcc), C


Какой именно gcc такое умеет компилировать?

http://ideone.com/zxx1NP
/* иЗвиНите зА неРовнЫй поЧерК */
Re[8]: [Nitra] Roadmap - Milestone 2 (Символы и связывание)
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.11.14 16:16
Оценка:
Здравствуйте, s22, Вы писали:

VD>>Я предлагаю не делать таких нелогичных языков. Нас проклянут за это.


s22>C++ (gcc), C

s22>такие языки уже к сожалению есть.

Ты что-то путаешь. В С/С++ лексическая область видимости.

s22>Но для собственного языка я такое делать не стал бы


И никто не стал, потому что это бессмысленно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.