Языковая семантическая дисперсия - PullRequest
5 голосов
/ 28 августа 2010

Я думал о создании собственного языка (практичность: это мысленный эксперимент).Одна из идей, которые мне пришли, - это семантическая вариация на языке.Вы бы написали по существу семантические регулярные выражения, которые должны быть заменены эквивалентным кодом.Вы можете увидеть это в несколько менее прямой форме в D - у них есть строковые миксины, которые преобразуются в код D.За исключением того, что я собирался делать их неявно и более круговым способом.

Прямо сейчас я происходил из C ++.Так что если вы считаете:

string a, b, c, d;
// do stuff
a = b + c + d;

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

string a, b, c, d;
// do stuff
a.resize(b.size() + c.size() + d.size());
a = b; a += c; a += d;

Если бы я реализовал std :: string, я мог бы написать что-то еще быстрее.Ключом к этому является то, что они неявные - когда вы используете класс std :: string, аксиомы, написанные реализатором std :: string, могут влиять на любой код std :: string.Вы можете просто вставить его в существующую кодовую базу C ++, перекомпилировать и получить самую быструю конкатенацию строк, которую ваш разработчик std :: string может представить бесплатно.

В настоящее время возможности оптимизации, которые вы можете сделать, ограниченыпотому что у вас есть только столько контекста, сколько позволяет язык, в этом случае перегрузка операторов в C ++ принимает только два аргумента: this и arg.Но семантический регистр ex может взять практически весь контекст, который вам когда-либо понадобится - поскольку вы можете диктовать, что ему соответствует - и даже соответствовать языковым функциям, которых нет в языке хоста.Например, было бы тривиально обменять

string a;
a.size;

на

string a;
a.size();

, если вы хотите украсть свойства C #.Вы можете сопоставить определения классов и реализовать отражение во время компиляции или выполнения и т. Д.

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

О, чувак, выбирая правильные теги.Ммм ....

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

int i;
cin >> i;
int lols[i];

в

int i;
cin >> i;
std::variable_array<int>(alloca(sizeof(int) * i), i);

Семантика alloca делает невозможным манипулирование с шаблонами - вы должны написать макрос, если вы хотите выше.В C ++ 03 или C ++ 0x вы не можете инкапсулировать свои собственные VLA.

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

Ответы [ 2 ]

1 голос
/ 28 августа 2010

(Внимание: мамонт ответит!)

Я думаю, что это называется макросом;) Ну, по крайней мере, за пределами мира C / C ++ (где «макрос» относится к этой строго ограниченной замене, которую обеспечивает препроцессор). И это не очень ново. Хотя я думаю, что правильная, мощная система макросов может добавить в язык больше возможностей, чем любая другая функция (учитывая, что мы сохранили достаточно примитивов, чтобы она была не просто полной по turing, но полезной для реального программирования), поскольку достаточно умный программист может добавить почти все функции, которые могут оказаться полезными в будущем или для конкретного домена без добавления (дополнительных) правил к языку.

Основная идея состоит в том, чтобы разобрать программу в представление над строкой с исходным кодом, скажем, AST или дерево разбора . Такие деревья предоставляют больше информации о программе, и другая программа может обойти это дерево и изменить его. Например, можно было бы найти узел VariableDeclaration, проверить, объявляет ли он простой старый массив T, и заменить его новым узлом VariableDeclaration, который вместо этого объявляет std::variable_array из T , Это, например, может быть улучшено путем обеспечения соответствия шаблонов для дерева, что облегчает метапрограммирование. Мощная процедура, тогда и только тогда, когда программист может справиться с этим уровнем абстрактности и знает, как его эффективно использовать.

Обратите внимание, что когда я говорю о «сопоставлении с образцом», я говорю о сопоставлении с образцом в функциональном программировании, а не о регулярных выражениях. Регулярных выражений недостаточно, чтобы понять смысл нерегулярных языков, это касается практически всех полезных языков - просто разрешение выражений абрита, включая сбалансированные скобки, исключает регулярные выражения. См. Принятый ответ на Что такое «сопоставление с образцом» в функциональных языках? для отличного введения в сопоставление с образцом и, возможно, выучите функциональный язык, такой как Haskell oder O'Caml, если только узнайте, как его использовать и как обрабатывать деревья (и есть множество других интересных функций!).

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

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

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

1 голос
/ 28 августа 2010

Если вы ищете в Google что-то вроде «шаблона выражения C ++», вы обнаружите, что в действительности C ++ уже имеет довольно похожие возможности. В зависимости от того, что вы придумали для синтаксиса, ваша идея может облегчить понимание такого кода (шаблоны выражений , конечно, не тривиальны), но, по крайней мере, для меня не совсем ясно, что вы добавляете много ( если что) на пути к действительно новым возможностям.

...