продолжаю выкладывать по просьбе автора статьи, уже не попавшие в исчезнувший журнал RSDN magazine
Предыдущую обсудили, уже пошло зубоскальство по поводу педали. Вспомните еще фарфоровые ручки на цепочках в сортирах
Здравствуйте, кт, Вы писали:
кт>Вспомните еще фарфоровые ручки на цепочках в сортирах
Между прочим, фарфоровые ручки — клёвые. я бы не отказался
кт>По теме, на мой взгляд, в философию. Сама статья, написана 2.5 года назад: кт>http://files.rsdn.org/122727/pl1ex14.doc
По теме:
В статье предполагается, что принцип "сначала опиши, а затем используй" используется в языках исключительно с целью уменьшения количества проходов компилятора.
После чего объясняется что количество проходов не так важно, и было бы неплохо разрешить описывать переменную в любом месте.
Я думаю, что автор стотьи исходит из ложной предпосылки.
Принцип "сначала опиши, а затем используй" используется в первую очередь для удобства чтения программы, так как человек читает сверху вниз и мотать код туда-сюда банально неудобно.
Я лично придерживаюсь той точки зрения, что переменная должна быть описана максимально близко к месту первого использования (лучше всего — в той же конструкции).
Ещё переменная по максимуму должна быть неизменяемой, но это уже не относится к теме.
Re[2]: сколько проходов должно быть у транслятора?
Здравствуйте, vmpire, Вы писали:
V>В статье предполагается, что принцип "сначала опиши, а затем используй" используется в языках исключительно с целью уменьшения количества проходов компилятора.
Я понял так, что не для уменьшения а для ровно одного прохода
V>После чего объясняется что количество проходов не так важно, и было бы неплохо разрешить описывать переменную в любом месте. V>Я думаю, что автор стотьи исходит из ложной предпосылки.
Автор пишет что в С появились дурацкие прототипы функций из-за одного прохода, а прототип за три десятка команд может сделать транслятор автоматически и демонстрирует кусочек реального транслятора, который так и делает.
V>Принцип "сначала опиши, а затем используй" используется в первую очередь для удобства чтения программы, так как человек читает сверху вниз и мотать код туда-сюда банально неудобно. V>Я лично придерживаюсь той точки зрения, что переменная должна быть описана максимально близко к месту первого использования (лучше всего — в той же конструкции).
Часто приходится читать разбросанными фрагментами, а не непрерывно сверху донизу.
А как удобнее располагать описания должен решать программист, а не транслятор.
V>Ещё переменная по максимуму должна быть неизменяемой, но это уже не относится к теме.
Неизменяемая переменная — это что-то не то.
Здравствуйте, кт, Вы писали:
V>>В статье предполагается, что принцип "сначала опиши, а затем используй" используется в языках исключительно с целью уменьшения количества проходов компилятора. кт>Я понял так, что не для уменьшения а для ровно одного прохода
Насколько я знаю, одного прохода почти нигде и так нет. Впрочем, мои знания в этой области устаревшие лет на 10.
V>>После чего объясняется что количество проходов не так важно, и было бы неплохо разрешить описывать переменную в любом месте. V>>Я думаю, что автор стотьи исходит из ложной предпосылки. кт>Автор пишет что в С появились дурацкие прототипы функций из-за одного прохода, а прототип за три десятка команд может сделать транслятор автоматически и демонстрирует кусочек реального транслятора, который так и делает.
Лет 10-20 назад компилятор C++ (не С) был, вроде, четырёхпроходным (препроцессор, генерация объектного кода, разрешение символов, линковка, если правильно помню)
V>>Принцип "сначала опиши, а затем используй" используется в первую очередь для удобства чтения программы, так как человек читает сверху вниз и мотать код туда-сюда банально неудобно. V>>Я лично придерживаюсь той точки зрения, что переменная должна быть описана максимально близко к месту первого использования (лучше всего — в той же конструкции). кт>Часто приходится читать разбросанными фрагментами, а не непрерывно сверху донизу. кт>А как удобнее располагать описания должен решать программист, а не транслятор.
Ну так программисты это и решили при проектировании языка
V>>Ещё переменная по максимуму должна быть неизменяемой, но это уже не относится к теме. кт>Неизменяемая переменная — это что-то не то.
Расскажите про это функциональщикам.
Чем же это не то?
Re[2]: сколько проходов должно быть у транслятора?
кт>продолжаю выкладывать по просьбе автора статьи, уже не попавшие в исчезнувший журнал RSDN magazine
Это я периодически в качестве прикола привожу этот пример :
IF IF=THEN THEN ELSE=THEN; ELSE THEN=ELSE;
я, правда, оформляю его немного иначе:
IF IF=THEN THEN=ELSE; ELSE ELSE=IF; /* UPD: Здесь я в результате ошибся: пропустил один THEN */
IF IF=THEN THEN THEN=ELSE; ELSE ELSE=IF; /* Правильно так. В эпоху перфокарт из-за такой мелочи можно было легко рабочий день потерять */
Но о тупости разработчиков компилятора PL/1 я никогда не говорил. Наоборот, компилятор, работавший на IBM/360 можно считать шедевром. Который доставлял немало головняка некоторым студентам. Потому что работал в 96К памяти. И это было основанием для отказа студентам, которые иногда просили 128К. ЕМНИП, этот компилятор был шестипроходным.
Грабли языков программирования того времени – отсутствие зарезервированных слов. Как следствие – требование к компилятору проводить более глубокий анализ текста программы. И требование к программисту – следить за собой. Потому что в эпоху перфокарт исходный текст читался по распечатке. Или прямо с карт. Отличить имя переменной от служебного слова в таких условиях проблематично. Там подсветка не особенно хорошо работала.
Во-первых, если мы говорим о числе проходов в контексте грамматики языка, то речь идет о числе проходов парсера. После окончания грамматического разбора компилятор может сделать еще 100500 "проходов", с целью анализа программы, оптимизации и кодогенерации. С грамматикой языка эти "проходы" вообще мало связаны.
Во-вторых, первый компилятор Си действительно обладал однопроходным парсером (макропроцессор был вообще отдельной программой), что по тем временам было оправданно, поскольку памяти было мало, а диски медленные. Но в той версии языка Си вообще не было прототипов функций, они появились сильно позже. И тем не менее, вызывать функцию до ее описания, или, вообще, из другого файла, разрешалось.
В третьих, языки, в которых можно ссылаться на сущности, описанные позже, и позволяющие, тем не менее, однопроходный синтаксический анализ, существуют. Насколько я понимаю, к таким языкам относятся, среди прочего, Go, JavaScript, в какой-то мере C++.
В четвертых, большую часть времени современный компилятор тратит вовсе даже не на синтаксический анализ, а на оптимизацию и кодогенерацию. В этом легко убедиться, сравнив скорость компиляции с включенной оптимизацоей и без. Поэтому число проходов компилятора сейчас особо не важно.
В пятых, простой синтаксис важен, в первую очередь, для человека, а не для компилятора. А что он помогает компилятору, это лишь не очень важный, хотя и приятный, дополнительный бонус.
Re[4]: сколько проходов должно быть у транслятора?
кт>>Автор пишет что в С появились дурацкие прототипы функций из-за одного прохода, а прототип за три десятка команд может сделать транслятор автоматически и демонстрирует кусочек реального транслятора, который так и делает. V>Лет 10-20 назад компилятор C++ (не С) был, вроде, четырёхпроходным (препроцессор, генерация объектного кода, разрешение символов, линковка, если правильно помню)
Разрешение символов — это первый проход линкера.
Линкер к компилятору не имеет отношения.
Так что получается только два. Причем препроцессор тоже к компилятору не относится — это отдельная программа.
На вход компилятору поступает программная единица — обработанный препроцессором файл.
Вот он и обрабатывается компилятором, который создает объектный код.
Другое дело, что сам компилятор делится на две довольно крупные часьти фронт-енд и бэкенд.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Правильный ответ на вопрос: Да кто их считает?
1)Делать язык без вывода типов или с однопроходным выводом типов издевательство над пользователями языка.
2)В современном мире язык без ИДЕ не нужен. А писать сначала компилятор, а потом тоже самое для поддержки ИДЕ глупость полная. Даже в майкрософт это поняли.
А поддержка ИДЕ работает совсем иначе чем тупой транслятор.
Там нужно и сломанный текст понимать и инкрементально пересчитывать изменения, ибо делать разбор сотни мегабайт исходников на каждое нажатие клавиши не реально.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: сколько проходов должно быть у транслятора?
Здравствуйте, LaptevVV, Вы писали:
LVV>Разрешение символов — это первый проход линкера.
Внутри модуля может и компилятор делать.
LVV>Линкер к компилятору не имеет отношения.
Они сейчас очень тесно интегрированны.
LVV>Так что получается только два. Причем препроцессор тоже к компилятору не относится — это отдельная программа.
Препроцессор может быть встроен в компилятор, чтобы два раза лексический анализ не делать. Это если мы говорим про Си, в более других языках препроцессора может и вовсе не быть.
LVV>На вход компилятору поступает программная единица — обработанный препроцессором файл.
У Go, например, компилятор заглядывает в импортированные модули, и может принимать некоторые оптимизационные решения, типа делать ли функцию инлайновой, раскрутив всю цепочку.
Удобнее же. Сообщество больше, читать можно онлайн а не скачивать док, ну и заодно получите инвайт и возможность нормально комментировать другие статьи.
Нет такого преступления, на которое не пошло бы суверенное родоплеменное быдло ради продления своего бессмысленного рода и распространения своего бессмысленного генома.
Здравствуйте, anonymouse2, Вы писали:
A>Удобнее же. Сообщество больше, читать можно онлайн а не скачивать док, ну и заодно получите инвайт и возможность нормально комментировать другие статьи.
так я же предлагал администратору с самого начала
* * *
Дата: 22.11.16 08:41 кт>Здравствуйте, VladD2, Вы писали: VD>К сожалению, бумажный журнал окончательно помер. Так что профессиональной вычитки, к сожалению, больше не будет.
... кт>Может быть кто-то (Вы или Купаев или еще кто-то) возьмете на себя труд разместить в дереве статей все оставшиеся?
* * *
Все эти статьи (а, наверное, и других авторов) давно в редакции лежали, перенесли бы их все автоматом в "статьи" и дело с концом
Здравствуйте, кт, Вы писали:
кт>так я же предлагал администратору с самого начала кт>Все эти статьи (а, наверное, и других авторов) давно в редакции лежали, перенесли бы их все автоматом в "статьи" и дело с концом
Не понял чего вы предлагали и почему администраторам. Статья ваша? Вот и публикуйте ее на хабре. РСДН это чисто форум, остальные разделы были актуальны в бородатые девяностые разве что. Никакой особой вычитки не надо, люди не глупые, опечатки у всех бывают и все это понимают.
Нет такого преступления, на которое не пошло бы суверенное родоплеменное быдло ради продления своего бессмысленного рода и распространения своего бессмысленного генома.
Re[3]: сколько проходов должно быть у транслятора?
N>>Или автор все эти промежуточные стадии не считает "проходами"? V>А сколько там получается? Просто интересно, а gcc под рукой нет.
Сколько чего? Проходов? Вот как раз столько, сколько я описал — 127. Ну, может, минус 2-3 (потому что некоторые файлы это отчёты о финальных состояниях некоторых групп проходов).
Некоторые из них принципиальные и глобальные (перевод в дерево AST, генерация операций в промежуточной машине). Некоторые средневажные — например, без включения оптимизации может быть куча лишних копирований между регистрами — это всё устраняется. Dead code elimination, common subexpression merge. Некоторые совсем частные (объединение sin и cos, если позволяет процессор).
The God is real, unless declared integer.
Re[2]: сколько проходов должно быть у транслятора?
Здравствуйте, Privalov, Вы писали:
P>Это я периодически в качестве прикола привожу этот пример :
P>IF IF=THEN THEN ELSE=THEN; ELSE THEN=ELSE;
P>я, правда, оформляю его немного иначе:
P>IF IF=THEN THEN=ELSE; ELSE ELSE=IF; /* UPD: Здесь я в результате ошибся: пропустил один THEN */ P>IF IF=THEN THEN THEN=ELSE; ELSE ELSE=IF; /* Правильно так. В эпоху перфокарт из-за такой мелочи можно было легко рабочий день потерять */
Да, пример злобный.
P>Но о тупости разработчиков компилятора PL/1 я никогда не говорил. Наоборот, компилятор, работавший на IBM/360 можно считать шедевром. Который доставлял немало головняка некоторым студентам. Потому что работал в 96К памяти. И это было основанием для отказа студентам, которые иногда просили 128К. ЕМНИП, этот компилятор был шестипроходным.
Сочувствую студентам — повторить все хитрости уровня ассемблера (а вряд ли это чисто алгоритмически влезли в 96K) было нетривиально.
P>Грабли языков программирования того времени – отсутствие зарезервированных слов. Как следствие – требование к компилятору проводить более глубокий анализ текста программы. И требование к программисту – следить за собой. Потому что в эпоху перфокарт исходный текст читался по распечатке. Или прямо с карт. Отличить имя переменной от служебного слова в таких условиях проблематично. Там подсветка не особенно хорошо работала.
А сейчас часто грабли — наличие зарезервированных слов
Вообще имеет смысл в новых языках делать где-то так: Символ '$' (например) перед любым идентификатором исключает восприятие этого идентификатора как зарезервированного слова. Обратный вариант: '@' первым символом задаёт интерпретацию всего последующего как ключевого слова, даже если без '@' оно таким не считается; допустимо ли тут такое слово — вопрос уже синтаксиса.
Без начального '$' или '@' восприятие зависит от контекста. Правила могут медленно меняться с развитием языка.
Часть ключевых слов понимается только при начальном '@' (экспериментальные или редкие возможности), также тут пишутся аналоги для операторов (например, @shl вместо <<).
Для возможности введения вообще любых идентификаторов: После @,$ может идти (без пробельных символов!) простая строка в кавычках, чтобы как идентификатор или ключевое слово передать вообще любую последовательность, а не только похожую на идентификатор. Пример: $"a$b", $"class x", $"if.", @"if", $"" (пустой идентификатор — да, вдруг где-то нужен).
Если в каком-то эти $,@ уже заняты, то вместо них взять ¤ (U+00A4), § (U+00A7). Вроде бы языков, которые не допускают использование Unicode на входе, считай не осталось (SQL не в счёт)
И строку в виде @IF $IF=$THEN @THEN $THEN=$ELSE; @ELSE $ELSE=$IF; поймут и человек, и машина.
The God is real, unless declared integer.
Re[3]: сколько проходов должно быть у транслятора?
Здравствуйте, netch80, Вы писали:
P>>IF IF=THEN THEN THEN=ELSE; ELSE ELSE=IF; /* Правильно так. В эпоху перфокарт из-за такой мелочи можно было легко рабочий день потерять */
N>Да, пример злобный.
Ага. Причем я его не сам придумал. Он откуда-то из студенческих времен, когда нас учили читать исходники по распечатке. Похожие примеры были и для Фортрана.
N>Сочувствую студентам — повторить все хитрости уровня ассемблера (а вряд ли это чисто алгоритмически влезли в 96K) было нетривиально.
Я деталей не знаю. Знаю только, что там в полный рост использовались оверлеи.
N>А сейчас часто грабли — наличие зарезервированных слов
Я на это нарывался несколько раз. Когда к C++ проекту подключали legacy, сделанный на чистом C. Там частенько можно было встретить this в качестве идентификатора. Реже — class и некоторые другие. Переименование таких идентификаторов связвно с известными трудностями.
N>Вообще имеет смысл в новых языках делать где-то так: Символ '$' (например) перед любым идентификатором исключает восприятие этого идентификатора как зарезервированного слова.
Или пользоваться правильными язывами, у которых хорошая поддержка со стороны IDE. Все-таки время перфокарт и IEBUPDTE прошло.
N>И строку в виде @IF $IF=$THEN @THEN $THEN=$ELSE; @ELSE $ELSE=$IF; поймут и человек, и машина.
Достаточно просто "@" пропустить. И не обратить внимания но то, что IDE слово не тем цветом выделено.