Re[8]: Refactoring : Rename
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.05.11 16:32
Оценка:
Здравствуйте, maxkar, Вы писали:

M>Не работает. То, что программа должна знать модель кода — правильно. И я даже мог бы ее научить там, где надо. Только вот рефакторинг "переименования" для таких случаев может работать только на уровне SST.


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

Но базовую функциональность можно и нужно делать общей и универсальной.

M>В каком виде на макросах? Сейчас на вход идут несколько файлов с одинаковыми ключами. Язык описан. Это можно считать макросами или нет?


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

M>Согласен, надо менять макру. Рефакторинг "переименования" это сможет сделать автоматически?


Конечно нет. И глупо было бы на это закладываться. Но можно проектировать макросы так, чтобы они не зависили от логики именования.

Кроме того, как я уже говорил, можно сделать некие плагины к рефакторингам которые могли бы сделать рефакторинги настраиваемыми, и более интеллектуальными.

M>Нет. Я про другое. Я хочу видеть проблемы не при очередной компиляции. Не после того, как рефакторинг прошел и все сломалось. Я хочу видеть запрос "подтверждения" рефакторинга со списком предупреждений сразу после того, как я ввел новое имя. Что-то вроде preview, который есть в eclipse и idea.


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

VD>>Что-то как-то очень много букв, а смысл ускользает. "derive" этот будет автоматом перегенерировать класс и находить соответствия между именами исходного объекта и именами интерфейса. Ничего специально делать не придется.


M>Не, то что будет делать derive после рефакторинга — понятно. Не понятно, как там будет работать "автоматическое" переименование.


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

Кроме того тут можно воспользоваться теми самыми плагинами к рефакторингам. Предположим, что макрос derive генерируя прокси будет, с помощью специального API, регистрировать обработчики на изменение исходных методов интерфейсов (для которых генерируются члены-обертки). В момент осуществления рефакторинга переименования методов интерфейсов будут срабатывать эти самые обработчики и пользователь увидит набор связанных рефакторингов инициированных этими обработчиками. Если пользователь их не отменит, то будут произведены и переименования методов типов к которым применен макрос derive. В случае конфликта в других местах пользователь об этом будет оповещен.

VD>>Если же члена с нужным именем ненайдется, то будет выдано сообщение об ошибке. Что тут еще можно придумать?


M>Ну в SST как-то будет представлена связь между одноименными методами "несвязных" типов. Что-то вроде "same-name-as", например. Только вот рефакторинг переименования в этом случае опять должен работать на SST.


Ты просто уперся в неправильный путь. Я уже сто раз сказал, что все манипуляции можно осуществлять по TAST. Но ты (и не только ты) в десятый раз повторяешь одно и тоже даже не попытавшись опровергнуть мои утверждения.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Framework для создания языков программирования
От: cvetkov  
Дата: 30.05.11 17:18
Оценка:
Здравствуйте, VladD2, Вы писали:

C>>>>не очень ясно зачем нужно чем отдичаются AST и TAST но это для нашего разговора не принципиально.

VD>>>TAST не поддерживает неоднозначностей. В нем типы обязаны быть изначально. AST может существовать в нетипизированном виде.
C>>ну выглядит так что есть преобразовантя из SST в AST и из AST в TAST и не очень понятно зачем их два.

VD>Преобразование из SST в AST значительно проще нежели из SST в TAST или из AST в TAST, так как TAST содержит значительно больше информации (весьма низкоуровневой). TAST это своего рода высокоуровневый ассемблер.

и зачем это нужно? как-то не получается у меня вас понять.
VD>Он отличается от реального ассемблера или MSIL только тем, что это представление в памяти и это представление не может быть некорректным (т.е. все связи явные и гарантированно корректные, нет никаких умолчаний).
ну мсил после верификации тоже не может быть некоректным.

VD>Генерация TAST — это по сути процесс типизации.

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

VD>При этом и SST, и AST могут содержать типы, но это не обязательно.

т.е. полагатся на это нельзя. так зачем они там? если мы все равно не знаем есть они или нет.

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

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

VD>>>Отнюдь. Это совершенно универсальная вещь. От языка зависит типизатор.

C>>какой у типизатора по вашему интерфейс?
VD>Вам как, расписать все детали? В двух словах... на входе AST, на выходе TAST.
ну этому я уже поудивлялся.
и это опять же не правда.
у вас там еще есть интерфейс который на входе AST а на выходе список типов.
и еще интерфейс для рефакторинга кажется там. так что давайте более развернутый список.


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


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


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

VD>>> Но любой типизатор обязан будет поддерживать и эту штуку. Пока что я вижу типизатор в виде объекта с набором виртуальных методов. Для конкретного языка создается наследник в котором переопределяются те методы которые отличаются для конкретного языка (вплоть до всех).

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

VD>>>Еще раз в TAST все имена разрешены. У каждого имени ссылка на объявление (переменной, функции, поля и т.п.).

VD>>>А вот за то как формируется TAST отвечает типизатор, который затачивается на конкретные языки.
C>>еще раз. проблема не в том как найти ссылку, а втом какие требуются манипуляции с текстом.

VD>Эта проблема решается универсально. Все что надо сделать это произвести тестовое переименование и сравнить старое и новое TAST (без учета имени переменной). Если они совпадают, переименование прошло без ошибок. Если нет, то не совпадающие ветви — это конфликт имен которые надо разрешать.

интересный подход. не черезчур расточительно?
VD>Можно даже обойтись исходным TAST, просто пробежавшись по нему и проверив не видно ли в местах ссылок на исходную переменную (функцию или еще что-то) нового имени.
этого сделать нельзя (если вы конечно не держите для каждой точки все видимые типы.)
VD>Для этого придется хранить в TAST информацию о тех самых областях видимости и видимых в них переменных.
ага. так я и думал.
VD> Но это как раз не проблема. Надо только заранее подумать об этом.
подумайте я как раз и пытаюсь указать вам на наибольшее количество мест над которыми нужно подумать.
Re[12]: Framework для создания языков программирования
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.05.11 17:31
Оценка:
Здравствуйте, cvetkov, Вы писали:

VD>>Естественно! Фокус в том, что когда человек описывает языковые конструкции в виде макросов, он тем самым описывает их структуру. Нужно всего лишь дополнить эту разметку дополнительной информацией позволяющей движку IDE узнать в каких местах нужно делать фолдинг. Это можно сделать в виде атрибута.

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

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

C>ваш типизатор становится супер классом ответственным за все. как-то не модульно однако.


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

VD>>Так и сделано в Немерле 1. Я просто подхачил компилятор и он стал работать как движок автодополенения.

C>я потом найду табличку с надписью сарказм
C>вы не считаете это плохим решением?

Нет. Более того, я уверен на 100%, что в будущем идея создавать отдельно компилятор и движок IDE будет считаться маразматической. Примерно так же как сейчас маразмом считается писать движок РСБУД для отдельного проекта. Сложность языков (их реализация) растет. И дублировать один и тот же код только из-за того, что в нем есть 1% различий, никто не будет.

C>>>но самое сложное то при этом не переиспользуется. я и говорю языкозависимо.

VD>>Типизатор по любому у языков будет отличаться. Но не полностью. Есть куча языков в которых типизатор отличается мелкими деталями.
C>ваш типизатор перестает быть типизатором и становится названием для всего языкозависимого функционала.

Я не понял, что здесь сказано и что из этого проистекает.

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

Более того, когда создают типизаторы для других языков, то повторяют всю эту работу с нуля. При этом дублируется опять же около 99% работы. Например, типизаторы C# и VB.NET отличаются очень незначительно. Так зачем же для них писать полностью обособленные типизаторы?

Если сумировать дублирование типизаторов в разных языках и помножить на дублирование в инеграциях к IDE, то объем копипастинга выглядит во истину устрашающе!

C>может стоит дать ему соответствующее имя что-бы не путать людей?


Например? Мне кажется имя вполне подходящие. В прочем, возможно на меня давит компиляторная терминология. В движках IDE это может иметь название "модуль анализа кода" или еще как-то.

VD>>Для этого придется для каждого языка (а точнее для языковых групп) определить преобразование метаинформации в текст.

C>не надо было дальше расписывать.
C>достаточно было просто со мной согласится

В чем? Я по прежнему не согласен с тем, что нельзя делать универсальные рефакторинги и сем, что все придется делать по SST.

VD>>Выше я привел пример с фолдингом. Для подсветки вообще ничего указывать не придется. Все что описывается в макросе через литерал (т.е. "class") будет автоматом учитываться как "ключевые слова". В кавычках, так как они могут быть контекстными. Типы будут подсвечиваться на основе TAST.

C>это исчерпывает набор дополнительной информации?

Исчерпывающим может быть только работающий код. Любые слова априори абстрактны.

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


Проще попытаться доказать свое предположение. Мое объяснение очень простое. В конечном итоге все превращается в метаднные сборки и исполняемый код. Раз код можно представить ограниченным (и весьма скромным по объему) набором инструкций, значит и TAST тоже будет конечным и не очень большим.

C>как минимум перечисление домыслов, а это тоже перечисление


А смысл обсуждать домыслы?

C>а во вторых мои домыслы основываются на моем не полном знании, если они вам не интересны можете просто не отвечать.


Мне интересны любые не повторяющиеся идеи. Мысль о том что "не взлетит" или о том что "невозможно". Меня не интересует. Меня интересуют доводы, факты рассуждения. Короче, то за что можно зацепиться.

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

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

VD>> Я уже показывал, что, например, рефакторин переименования спокойно абстрагируется от языка.

C>нифига, код переносится в "типизатор", от абстрактного рефакторинга остается только скелет.

Что значит переносится? Да, безусловно — переносится! И это прекрасно, так как он становится универсальным и пишется один раз. Типизатор не надо писать с нуля для каждого языка. Для многих языков можно обойтись изменением всего лишь нескольких методов универсального типизатора. Это вам не тоже самое, что писать код типизации для всего языка с нуля. Но то он и фрэйворк. Я не предлагаю единого решения для всех проблем (ака серебряная пуля). Это просто невозможно. Я предлагаю фрэймворк который существенно облегчит работу по созданию компилятора и IDE, но при этом позволит гибко расширять функциональность, так чтобы учесть особенности разных языков.

VD>>
VD>>// сначала макрос вводящий оператор if
VD>>macro If : Ast.Expression
VD>>  syntax: "if" "(" condition ")" trueExpr "else" falseExpr
VD>>{
VD>>  <[ match ($condition)
VD>>     {
VD>>       | true => $trueExpr
VD>>       | _    => $falseExpr
VD>>     }
VD>>  ]>    
VD>>}
VD>>refactoring "Inverse if"
VD>>  reformat: true
VD>>{
VD>>  <[ if (! $condition) $falseExpr else $trueExpr ]>
VD>>}
VD>>

C>т.е. вы рефакторинг еще и в парсинг затянули. круто.

В какой еще парсинг? Если вы знакомы с квази-цитированием то должны понимать, что оно работает не на уровне парсера, а на уровне объектной модели. Просто АСТ не надо описывать в виде объектов. Оно описывается квази-цитатами.

C>вы минусов что не видите?


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

C>если вы зададите преобразование SST -> AST декларативно и гарантируете его обратимость в нужных случаях то да. вопрос как этого добится остается открытым.


Для хинтов не нужно преобразовывать обратно 100% синтаксиса. Хинты ведь показываются для вполне определенных конструкций: вызовы методов/функций, доступ к свойствам/полям, доступ к локальным переменным и т.п. Для всего этого не сложно создать прети-принтер (не страшно даже если это будет сделано вручную).

C>ацкий ад вы все три дерева храните. понятно. память то дешевая.


Не знаю насколько ты знаком с тем сколько дерьма хранят современные IDE. Если не знаком, то просто погляди сколько жрет памяти тот же Решарпер. Это ведь не спроста.

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

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

Мы и для интеграции Nemerle 1 храним два дерева. Потребление памяти при этом очень незначительное. Вписываемся в 100-150 метров на проект средних размеров.

C>а то как от других списков требовать так легко, а как самим что-то рассказать, так в кусты.


Я уже много чего навыкладывал. Сейчас у меня задача сделать так, чтобы мои мысли стали понятны другим. И чтобы эти другие выдали мне конструктивную критику, которую я смог бы переварить, и если что, подправить свои идеи.

VD>>Выше я привел пример рефакторинга инверсии if-а.


C>отвечу вашими словами "это всего лиш домыслы"

C>примеры ни чего не доказывают.

Хм. А что же доказываем? Я привел конкретный пример реализации как ответ на конкретный вопрос. Будут другие вопросы, будут другие примеры.

Пока что я не услышал критика даже этого простого примера.

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


Хм... не знаю даже что сказать.

C>ну так бы сразу и говорили. я же не против всех этих ваших штучек. просто звучало так как-будто вы считаете это панацеей.


Я принципиально но не верю в панацеи. Но вижу что люди даже банальное повторное использование кода в этом области не используют.

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


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

Так что прошу прощения, за то что я что-то не описал.

C>>>2. для разных языков требуются разные алгоритмы обработки, вы же утверждаете что напишите общий код.

VD>>Какие-то алгоритмы будут общими.
C>мое мнение что их будет очень мало.

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

Можно сказать, что мы имеем на руках прототип — Nemerle 1. Во многом он уже сделан весьма универсально. Нам удалось весьма легко реализовать компиляцию сабсета C# 4.0 на базе компилятора Nemerle. Именно полученный опыт и позволяет делать столь смелые планы. Это не просто фантазии. Это развитие уже работающих (а значит проверенных) идей.

C>приведите хоть какой нибуть список общих алгоритмов.


В какой области? Иначе я до следующего тысячелетия буду перечислять.

VD>>Скажем для рефакторингов выноса кода в отдельную функцию вазным является вычисление внешний связей. Это можно сделать на базе TAST универсально. Формирование же кода будет зависимым от языка, но его можно будет реализовать на базе КЦ. Таким образом языко-зависимого кода будет существенно меньше чем при традиционных подходах.

C>в написании скольких систем рефакторингов вы участвовали?

Одной. Но к делу это не относится, так как апелляция к опыту сразу идет в топку.

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

C>т.е. тут никакого велосипеда вы не изобрели.

Что за система? Сколько языков поддерживал? Использовалось ли квази-цитирование для разбора и композиции кода? Было ли разделение на универсальное АСТ и специализированное?

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

C>на мой взгляд главное новшество вашей системы это не такие мелочи как паттерн матчинг и цитирование, а попытка декларативно связать SST и TAST (зачем вам нужно промежуточное звено в виде AST я так толком и не понял). это действительно интересная задумка. но пока я не вижу как вы из этого извлечете пользу.


Полностью декларативно связать не выйдет. Есть нюансы. AST позволяет сделать процесс типизации универсальным (с возможностью настройки).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Framework для создания языков программирования
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.05.11 17:59
Оценка:
Здравствуйте, cvetkov, Вы писали:

VD>>Преобразование из SST в AST значительно проще нежели из SST в TAST или из AST в TAST, так как TAST содержит значительно больше информации (весьма низкоуровневой). TAST это своего рода высокоуровневый ассемблер.

C>и зачем это нужно? как-то не получается у меня вас понять.

Уф. Я уже столько раз пробовал объяснить это, что устал. Еще раз повторять одно и тоже просто бессмысленно.

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

При работе над сложными макросами для Nemerle 1 выработался четкий паттерн создания успешного сложного синтаксического макроса. Паттерн заключается в следующем:
1. Мы разбираем некий другой язык (обычно DSL, но это может быть и другой ЯП, например, C#).
2. Преоразуем его в специализированное AST в виде вариантных типов данных (АлгТД в Немерле).
3. Анализируем (вомзожно трансформируя) это специализированное AST (к сожалению, без квази-цитирования).
4. Генерируем по специализированному AST — AST немерла.
5. Далее AST немерла автоматически компилируется ядром компилятора (типизатором) в TAST и в последвствии в сборку дотенета.

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

Например, вот как выглядит SST для макроса PegGrammar (главный тип Rule). Вот как выглядят его трансформации. А вот так по нему генерируется код на Nemerle (на самом деле генерируется то самое абстрактное AST).

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

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

C>ну мсил после верификации тоже не может быть некоректным.

Ага. Программа тоже может быть скомпилирован. Но до тех пор это всего лишь текст который может содержать пургу. Точно так же и МСИЛ может содержать пургу. Часть ее отлавливает джит, а часть — нет. Во втором случае будут рантайм-падения.

Так вот TAST — это как бы IL прошедший верификацию. Плюс в инструкциях IL зачастую нет типов, так как они зависят от аргументов. Это и проверяет верификатор. В TAST же все инструкции высокоуровневые. Если инструкция подразумевает аргументы, то они будут перечислены прямо в ней и при этом все связи и типы будут корректными.

VD>>Генерация TAST — это по сути процесс типизации.

C>вам стоит всетоки использовать другой термин, или по крайней мере дать четкое определение этому и всюду указывать что оно отличается от интуитивного.
C>типизация в моем понимании это вычисление типа выражения.
C>исходя из этого мнения TAST это AST для узлов (являющихся экспрешенами или типами) которого известны типы. вы же явно имеете в виду чтото сильно отличное.

ОК. Предлагайте название. Рассмотрим.

VD>>При этом и SST, и AST могут содержать типы, но это не обязательно.

C>т.е. полагатся на это нельзя. так зачем они там? если мы все равно не знаем есть они или нет.

Полагаться на этом можно. Но это надо специальным образом проверять. Если типов нет, то можно специальным образом дождаться момента когда они появятся.

Типы в SST и AST нужны исключительно для логики преобразования. А появляются они как раз в процессе генерации TAST по AST.

Еще один аспект который я забыл озвучить — любые ветви AST (т.е. SST, TAST и AST) могут быть отброшены. Это позволяет делать спекулятивное АСТ и спекулятивную типизацию.

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

Другими словами все виды АСТ являются чистыми с функциональной точки зрения. Я пока не решил как быть со связями между видами АСТ и с типами. Но в крайнем случае это будет единственное изменяемое состояние в этих деревьях.

VD>>Вам как, расписать все детали? В двух словах... на входе AST, на выходе TAST.

C>ну этому я уже поудивлялся.
C>и это опять же не правда.
C>у вас там еще есть интерфейс который на входе AST а на выходе список типов.

Ну, да. AST же разные бывает. Бывает код тел методов. А бывает описание типов. Они по разному обрабатываются. Есть понятие дерево типов. Оно строится перед типизацией тел методов.

C>и еще интерфейс для рефакторинга кажется там. так что давайте более развернутый список.


Интерфейс для рефакторинга вмонтирован в интерфейсы "компиляции". По сути интерфейсы рефакторинга — это расширение общей "машины".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Framework для создания языков программирования
От: cvetkov  
Дата: 30.05.11 18:19
Оценка:
уже начал писать ответ, но стер.

можете записывать меня в список неосиливших споры с вами
Re[15]: Framework для создания языков программирования
От: WolfHound  
Дата: 30.05.11 19:04
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>И это универсальное решение. Мы как бы описываем новый язык, преобрзуем его в объектную форму пригодную для обработки МП-ом, обрабатываем его и потом генерируем по нему код на неком универсальном языке. При этом мы можем даже генерировать выскоуровневые конструкции (не являющиеся частями базового языка, а являющиеся расширениями), но они в итоге так же будут раскрыты до уровня базового языка. Делается это довольно легко, так как у нас нет нужды выполнять сложные действия вроде типизации. Типизацию же за нас делает компилятор. Но он уже обрабатывает универсальное (расщепленное до предела) АСТ.

Только тут есть одна очень большая засада, которую ты никак не хочешь понимать.

Для того чтобы сгенерировать AST в общем случае нужно типизировать SST!
В том же PegGrammar приходится типизировать SST руками.
Компилятор тут никак не помогает.
И в Н2 ты хочешь сделать ту же байду.

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

Еще ты тут несколько раз повторил слово "фреймворк".
Что интересно ты уже дошёл до того что сложные задачи лучше всего решаются на ДСЛ.
Но почему то не дошёл до мысли, что разработка компиляторов это тоже сложная задача.
И ей тоже нужен ДСЛ.
Причем несколько разных.
Как минимум:
1)Парсинг.
2)Типизация.
3)Рефакторинг.
4)Кодогенерация.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[16]: Framework для создания языков программирования
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.05.11 20:42
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Для того чтобы сгенерировать AST в общем случае нужно типизировать SST!


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

WH>В том же PegGrammar приходится типизировать SST руками.


Можно описать что ты называешь типизацией правил?

WH>Компилятор тут никак не помогает.

WH>И в Н2 ты хочешь сделать ту же байду.

Я не против того чтобы позволить типизировать и SST. Но это должен быть частный случай, а не общий. Человек должен иметь право решать что он использует.

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

Кроме того есть примеры кода типизация по SST невозможна в принципе. Классический пример такого макроса — синтаксис linq-а. Он уже в спецификации описан как синтаксическое расширение, а его семантика описана через query-паттерн.

Сбрасывать со сетов это никак нельзя.

WH>При этом все ошибки выявляются на уровнях парсинга и типизации.


Несомненно. И что? Вот только типизировать SST можно не всегда. Это не оспоримый факт.

WH>Также на этих уровнях получается вся информация нужная IDE.


После типизации то? Конечно! Только типизация и есть самый сложный аспект. Если с парсингом у нас теоретические вопросы сняты, то с типизацией все далеко не так гладко.

WH>Как следствие трансформация в PExpr во время работы IDE вообще не нужна. Только память и процессор кушает.


А вот тут я не согласен. Как раз типизация SST для меня под огромным вопросом. Я проанализировал те варианты использования с которыми я знаком (т.е. большинство применений макросов с коротыми я сталкивался) и пришел к выводу, что пользы от рукопашной типизации SST нет никакой!

Если взять тот же макрос foreach, то оказывается, что в нем нужно всего лишь знать тип одного из параметров (того в котором передается коллекция). Все остальное в нем осуществляется точно так же в виде нетипизированной трансформации. А это совсем не тоже самое что полная типизация SST.

Более того, я вообще не вижу как можно типизировать SST для foreach-а не прибегая к типизации (а следовательно к раскрытию) подвыражений. Ведь как минимум часть из выражений просто обязана быть раскрыта до типизации!

WH>Еще ты тут несколько раз повторил слово "фреймворк".


Ну, если честно, то это хитрый ход. К сожалению, мозг человека не изменяется в одночасье. Люди привыкли к некоторым догмам. Им кажется, что для комплексных задач библиотеки не годятся. Вот я и выбрал этот термин. На самом деле никаких атрибутов фрэймворка, как это принято я вводить не собираюсь. Это будет набор библиотек. Не более того.

Только никому не рассказывай .

WH>Что интересно ты уже дошёл до того что сложные задачи лучше всего решаются на ДСЛ.

WH>Но почему то не дошёл до мысли, что разработка компиляторов это тоже сложная задача.

Гы-гы.

WH>И ей тоже нужен ДСЛ.


Да я не против. Только ДСЛ — не панацея. Если ты видел мое описание макроса foreach, то заметил, что в нем как раз применяется нечто вроде ДСЛ-я.

WH>Причем несколько разных.

WH>Как минимум:
WH>1)Парсинг.
WH>2)Типизация.
WH>3)Рефакторинг.
WH>4)Кодогенерация.

Согласен по всем пунктам. Тем более, что раз мы предлагаем ДСЛ как новый вид повышения абстракции, то было бы как-то странно не использовать их самим.

Как будет выглядеть ДСЛ для парсинга, кодогенерации и даже рефакторинга
Автор: VladD2
Дата: 27.05.11
я представляю довольно отчетливо. Как он может выглядеть для типизации для меня пока является открытым вопросом.

Мне пока что видятся следующие вещи:
1. В процессе типизации неизбежно придется дожидаться когда типы будут выведены окончательно. Сейчас это делается весьма некрасивым способом — такой код помещается в лямбду с кучей проверок и приседаний. Мне видится, что тут можно было бы использовать нечто вроде ComputationExpressions. Но хорошо бы спрятать эту механику по глубже.
2. Периодически макросу нужно знать тип некоторых из его параметров. Это надо надо указывать декларативно, прямо в описании макроса. Пример этого я приводил вот здесь
Автор: VladD2
Дата: 24.05.11
на примере все того же foreach-а. Декларируешь что один из параметров должен быть типизирован:
  macro ForEach : Ast.Expression
    syntax: "foreach" "(" pattern "in" collection ")" body
      where: pattern    = Ast.PatternWithGuard,
             collection = Ast.Expression,
             body       = Ast.Expression;
    require: IsTyped(collection) // требуем чтобы перед вызовом тела макроса был типизирован параметр collection
{
  ...

и тело макроса будет вызвано только когда это случится. При этом компилятору дается четкое указание, что параметр (collection в данном примере) должен быть типизирован. Компилятор видит это начинает типизировать collection, но оставляет pattern и body не тронутыми. Если компилятор вздумает типизировать pattern или body, то он потерпит неудачу, так как не будучи подставленными в общее выражение (которое будет разным в зависимости от того какой тип у collection) их типизация окончится неудачей.

Мой план, как видишь, просто, прямолинеен и декларативен. Теперь опиши свое видение и сравним их.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Framework для создания языков программирования
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.05.11 20:44
Оценка:
Здравствуйте, cvetkov, Вы писали:

C>уже начал писать ответ, но стер.

C>можете записывать меня в список неосиливших споры с вами

Ничего, ничего. Попытка не пытка (ну, по крайней мере не сильная ). Может быть когда проникнетесь идеей, то вернетесь и наш диалог будет более продуктивен. Пока что получается на все мои слова ответ один "все это фигня... ничего не выйдет". А это как-то не конструктивно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Framework для создания языков программирования
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.05.11 20:48
Оценка:
Здравствуйте, VladD2, Вы писали:

WH>>Причем несколько разных.

WH>>Как минимум:
WH>>1)Парсинг.
WH>>2)Типизация.
WH>>3)Рефакторинг.
WH>>4)Кодогенерация.

VD>Мне пока что видятся следующие вещи:

VD>1. В процессе типизации неизбежно придется дожидаться когда типы будут выведены окончательно. Сейчас это делается весьма некрасивым способом — такой код помещается в лямбду с кучей проверок и приседаний. Мне видится, что тут можно было бы использовать нечто вроде ComputationExpressions. Но хорошо бы спрятать эту механику по глубже.
VD>2. Периодически макросу нужно знать тип некоторых из его параметров. Это надо надо указывать декларативно, прямо в описании макроса.

3. Еще очень хочется иметь качественный паттерн-матчинг по типам. Так чтобы можно было анализировать тип примерно так:
type match (expr.Type)
{
  | IEnumerable[_ * $type] => assert(type is ITypeInfo); ...
  ...
}

Так чтобы IEnumerable лукапился по открытым пространствам имен, но в рамках типов (сборок/кода) компилируемого проекта.

А то в Н1 с этим страшная возня.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Framework для создания языков программирования
От: WolfHound  
Дата: 30.05.11 22:35
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>В общем, случае как раз не надо.

Это в частных случаях можно обойтись, а в общем надо.

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

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

VD>Можно описать что ты называешь типизацией правил?

GrammarTyper и все то, что с этим связано.

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

Тут ты, мягко говоря, не прав.
Напишем вот такую байду:
    def x = if (123)
        "asd";
      else
        123;

получаем:
Error: expected bool, got int in type-enforced expression: System.Int32 is not a subtype of System.Boolean [simple require]
Error: expected string-, got int in computation branch: the types int and string are not compatible [simple unify]
Warning: hint: this means two branches of ''if'' or ''match'' have different types

Первая ошибка весьма мутная. Что за "type-enforced expression" когда у нас if?
Можно только догадываться о том, что там не так.

Вторая ошибка понятнее.
Но хинт доставляет... информация о макросе захардкожена в ядро компилятора!
              Message.HintOnce ("this means two branches of ``if'' or "
                                "``match'' have different types"));

(C)Typer.n

Сравним с:
macro if : Expression
syntax "if" "(" condition ")" trueExpression "else" falseExpression;
    condition       = Expression;
    trueExpression  = Expression;
    falseExpression = Expression;
typing
    typeof(condition) == bool;
    CanUnify(typeof(trueExpression), typeof(falseExpression));
rewrite
{
    <[
        match ($condition)
        {
            | true  => $trueExpression;
            | false => $falseExpression;
        }
    ]>
}

Типизация описывается языком подобным Mercury.

И полностью автоматически сгенерированные сообщения об ошибках:
Error: "condition" type must be "bool" but got "int".
Error: Can't unify "trueExpression" and "falseExpression" types. "string" and "int" are not compatible.

Ну, или как-то по-другому. Шаблоны сообщений можно настроить как угодно.

VD>Кроме того есть примеры кода типизация по SST невозможна в принципе. Классический пример такого макроса — синтаксис linq-а. Он уже в спецификации описан как синтаксическое расширение, а его семантика описана через query-паттерн.

Можно описать их типизацию примерно в том же стиле.

VD>Несомненно. И что? Вот только типизировать SST можно не всегда. Это не оспоримый факт.

Это твоя вера.

VD>После типизации то? Конечно! Только типизация и есть самый сложный аспект. Если с парсингом у нас теоретические вопросы сняты, то с типизацией все далеко не так гладко.

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

VD>Ну, если честно, то это хитрый ход. К сожалению, мозг человека не изменяется в одночасье. Люди привыкли к некоторым догмам. Им кажется, что для комплексных задач библиотеки не годятся. Вот я и выбрал этот термин. На самом деле никаких атрибутов фрэймворка, как это принято я вводить не собираюсь. Это будет набор библиотек. Не более того.

Ты не понял, что я сказал.
Нужен набор _языков_, а не библиотек.
Библиотеками тут не отделаться.
Они слишком неповоротливые.

VD>Как будет выглядеть ДСЛ для парсинга, кодогенерации и даже рефакторинга
Автор: VladD2
Дата: 27.05.11
я представляю довольно отчетливо. Как он может выглядеть для типизации для меня пока является открытым вопросом.

Вот надо его закрывать, а не твердить "невозможно".

VD>Мне пока что видятся следующие вещи:

VD>1. В процессе типизации неизбежно придется дожидаться когда типы будут выведены окончательно. Сейчас это делается весьма некрасивым способом — такой код помещается в лямбду с кучей проверок и приседаний. Мне видится, что тут можно было бы использовать нечто вроде ComputationExpressions. Но хорошо бы спрятать эту механику по глубже.
macro lock : Expression
syntax "lock" "(" lockOnExpression ")" body;
    lockOnExpression = Expression;
    body             = Expression;
typing
    IsReferenceType(typeof(lockOnExpression));
rewrite
{
    <[
        def toLock = $lockOnExpression;
        System.Threading.Monitor.Enter(toLock);
        try { $body }
        finally { System.Threading.Monitor.Exit(toLock); }
    ]>;
}


VD>2. Периодически макросу нужно знать тип некоторых из его параметров. Это надо надо указывать декларативно, прямо в описании макроса. Пример этого я приводил вот здесь
Автор: VladD2
Дата: 24.05.11
на примере все того же foreach-а. Декларируешь что один из параметров должен быть типизирован:

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

VD>Мой план, как видишь, просто, прямолинеен и декларативен.

Ошибаешься все три раза.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Framework для создания языков программирования
От: Ziaw Россия  
Дата: 02.06.11 05:37
Оценка: 10 (1) +1
Здравствуйте, VladD2, Вы писали:

VD>Размышляя над следующей версией компилятора языка программирования Nemerle я пришел к выводу, что то что получается в результате его дизайна уже нельзя назвать компилятором да и языком тоже.


VD>В процессе дизайна Nemerle 2 родилась идея создания Framework-а для разработки языков программирования.


VD>Первое — почему языков, а не компиляторов? Да потому что получается не просто библиотека упрощающая создание компилятора, а нечто что облегчает и обобщает разработку компилятора, интеграции с IDE и самого языка!


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


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


В общем и целом выглядит достаточно перспективно. Особенно если будут бэкэкнды к LLVM, JVM, JavaScript.

Получится очень востребованная платформа, позволяющая в одном проекте легко совмещать native, JVM, CLR и JavaScript. Возможно даже на одном языке. Тот же C# имеет все конструкции для работы с нейтивом, для работы в браузере можно его слегка рассахарить. А некоторым наоборот нужно бесшовно интегрировать разные языки, это тоже будет не сложнее чем вызывать сишные функции из паскаля.

Опять же нейтиву не хватает нормального гибридного языка, лямбды и немного вывода типов в C++0x просочились, но этого мало. Основная масса хорошо воспринимает C нотацию и с трудом ML или Lisp.

Серьезная проблема только в стандартной библиотеке. Но это проблема финансирования, а такую платформу ждет рынок.
Re[2]: Framework для создания языков программирования
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 02.06.11 06:09
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>В общем и целом выглядит достаточно перспективно. Особенно если будут бэкэкнды к LLVM, JVM, JavaScript.


Довольно интересная мысль. Если к Немерле прикрутить поддержку LLVM или JVM, то у него, скорей всего, появится какое-то будущее.
Re[3]: Framework для создания языков программирования
От: Ziaw Россия  
Дата: 02.06.11 09:32
Оценка:
Здравствуйте, kaa.python, Вы писали:

Z>>В общем и целом выглядит достаточно перспективно. Особенно если будут бэкэкнды к LLVM, JVM, JavaScript.


KP>Довольно интересная мысль. Если к Немерле прикрутить поддержку LLVM или JVM, то у него, скорей всего, появится какое-то будущее.


Сейчас hardcase абстрагирует бэкэнды чтения метаданных и кодогенерации. Это первый шаг.

C JVM все должно быть не так сложно, да будет, наверное, отличаться вывод типов или поведение дженериков. Но это детали. Реализовать бэкенд используя IKVM + каконибудь Сglib будет не так сложно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.