LINUX.ORG.RU

Программируете ли вы на Паскале?

 


0

4

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

>>> Результаты



Проверено: hobbit ()
Последнее исправление: hobbit (всего исправлений: 4)

Ответ на: комментарий от liksys

Если тебе нужны генерируемые форматные строки - генерируй их внимательно.

Банально любая локализация через printf(gettext(... — это генерируемая форматная строка. И я каждый раз думаю о том, что это потенциальная дыра.

wandrien ★★
()
Ответ на: комментарий от wandrien

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

liksys ★★★★
()
Ответ на: комментарий от wandrien

Если тебе надо в ТОЧКЕ ВХОДА в функцию знать размер её фрейма

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

no-such-file ★★★★★
()
Ответ на: комментарий от wandrien

про компилируемую функцию.

Так а про неё-то что надо знать? У тебя 3 int-а и всё. Какая нахрен разница, функцией они инициализируются, или константой? В любом случае делается sub sp, 3 условно. Дальше при инициализации по-месту тупо вставляется не mov [sp-2], 42, а типа call f2; mov [sp-2], ax.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

А как ты узнал, что у тебя три инта, не читая тело функции, которое содержит строки, из которых нужно генерировать код? Га!

wandrien ★★
()
Ответ на: комментарий от wandrien

А как ты узнал, что у тебя три инта

Приехали. Распределение локальных переменных компилятору знать неизбежно надо. Внутренняя табличка строится, к текущему фрейму, что где лежит. Т.е. определения переменных читаются, заносятся в табличку. Как только кончились, значит начался код и в этот момент мы уже знаем ВСЕ переменные, можно фигачить фрейм, пролог и никуда не возвращаться. Важно при этом, что нам не надо держать весь исходник и результирующий код в памяти. С этого блджад и начался спор, почему все переменные должны быть определены в начале блока. Да тупо потому что к началу кода однопроходный компилятор должен знать всё что нужно для пролога. А не потому что в этом есть какой-то высокий смысл и так академически правильнее.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 3)
Ответ на: комментарий от no-such-file

Еще раз. Внимательно смотри на код:

void f()
{
   int a = A();
   int b = B(a);
   int c = C(a, b);
}

Объясняю:

   int a /* заносим в табличку содержимого локального фрейма */
   = A(); /* генерируем исполняемый код */
   int b /* заносим в табличку содержимого локального фрейма */
   = B(a); /* генерируем исполняемый код */
   int c /* заносим в табличку содержимого локального фрейма */
   = C(a, b); /* генерируем исполняемый код */

В какой момент ты будешь генерировать sub sp, frame_size? В какой? У тебя на этапе чтения выражения A() уже нужно генерировать машинный код внутри тела функции f. А ты еще список локальных переменных не прочитал, чтобы знать, какое число подставить вместо frame_size.

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

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 2)
Ответ на: комментарий от wandrien

Объясняю

Во-первых, вовсе не обязательно делать sub sp, 3, а можно формировать фрейм инкрементально, т.е. push ax и т.д.

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

Сразу отвечу на вопрос «а почему бы тогда весь код не генерировать в буфер»? Потому что код инициализации это несколько байт, а весь код функции может быть несколько килобайт. Такого объёма может и не быть. А если он есть, то выгоднее делать двухпроходный компилятор.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от wandrien

В какой момент ты будешь генерировать sub sp, frame_size?

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

alysnix ★★★
()
Ответ на: комментарий от alysnix

потом апдейтится

Потом нельзя апдейтить. У тебя сгенереный код не хранится в памяти, а сразу пишется на ленту/перфокарты.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

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

делаются апдейты кода внутри сгенерированной части в случае -

-goto вперед

-любых булевских выражений

-условных операторов

-операторов цикла (выход по окончанию цикла в его конец)

-return, если эпилог функции сложный, наличия типа всяких там defer или деструкторов.

это навскидку.

alysnix ★★★
()
Ответ на: комментарий от no-such-file

у меня код на перфокарты не пишется. купи что-то без перфокарт уже. уже есть и такое.

перечитай список сверху, когда код надо апдейтить, не мели чушь про перфокарты.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

у меня код на перфокарты не пишется

Так ты никому и нахер не нужен. Мы говорим про 60-70 годы и почему все переменные обязательно должны быть в начале блока. Так вот потому что тогда компиляторы были однопроходные, потому что не было там памяти тупо, всю память занимал сам компилятор. Код читался с перфокарт и сразу же писался на перфокарты, никакого буфера там не было. Там под рантайм структуры компилятора: распределение переменных и т.п. едва хватало.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

как ты оператор

if ( cond ) {....} else {...} 

закодишь на своих перфокартах, если при условии == false, надо переходить на else, которое вообще еще непонятно где.

никто не гнал сразу «на перфокарты».

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

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 4)
Ответ на: комментарий от alysnix

надо переходить на else, вообще еще непонятно где

Решается косвенным переходом. Адрес перехода пишется позже в секцию адресов.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Решается косвенным переходом. Адрес перехода пишется позже в секцию адресов.

распиши код для вычисления бул выражения

bool res = (a and b) or (c and d);

alysnix ★★★
()
Ответ на: комментарий от alysnix

сделай a b c d функциями

Ещё один долбень, который не понимает что для компайлтайма нет разницы, константа это или функция?

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

я тебе привел список КОГДА ДЖАМПЫ ВПЕРЕД НЕОБХОДИМЫ. учи его. и попытайся это отобразить на свои «перфокарты».

и не мути воду. булевское выражение может быть сколь угодно сложным. и не лезить на твою «перфокарту».

а также вспомни себя. ты еще тявкал и про перфоленту, ааааааааахахахаха.

alysnix ★★★
()
Ответ на: комментарий от alysnix

булевское выражение может быть сколь угодно сложным

Вообще похер, это одно выражение. Читается и парсится как одно, т.е. можно сразу генерировать переходы. Вот goto вперёд и даже простой if (else не нужен для примера, пенёк) требуют отсроченной записи адреса, да.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

про перфоленту разверни. :)))) там байт пишется сразу.

откуда вообще у тебя такие познания? все язычки уровня си, и паскаля, уже делались на мейнфреймах, где памяти для кода функции уже было достаточно. что ты уперся в свои «перфоленты».

alysnix ★★★
()
Ответ на: комментарий от alysnix

все язычки уровня си, и паскаля, уже делались на мейнфреймах

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

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

И у каждого в подвале стоял мейнфрейм.

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

и языков было - по пальцам пересчитать. а не как сейчас. уже никто не знает сколько их вообще

alysnix ★★★
()
Ответ на: комментарий от alysnix

где памяти для кода функции уже было достаточно

Где-то достаточно, где-то нет. Даже если взять сферические в вакууме 64К. Из них что-то занимает ОС, большую часть сам компилятор. В наличии, ну допустим 10К под данные. Много ты накомпилируешь в память при таких ограничениях? А с ленты на ленту практически не ограниченно, 10K под временные структуры должно хватать. Поэтому были такие компиляторы.

no-such-file ★★★★★
()
Ответ на: комментарий от alysnix

языки делались там, где стоял мейнфрейм

В основном да, но таки для всех, а не только для мейнфреймов.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Во-первых, вовсе не обязательно делать sub sp, 3, а можно формировать фрейм инкрементально, т.е. push ax и т.д.

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

Твоя же идея соответствует паскалю с выделенной секцией var, но никак не Си в варианте C89.

Более того, сама концепция «блока, в начале которого можно объявлять переменные», ломает эту идею, даже если бы объявления не включали в себя исполняемый код.

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

wandrien ★★
()
Ответ на: комментарий от no-such-file

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

так оригинальный компилятор Modula-2 от вирта для pdp-11 был 5 проходным и лез в 64к. чтобы работать на машинах уровня lsi-11.

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

alysnix ★★★
()
Ответ на: комментарий от no-such-file

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

Ну ваще-т они делались на том, что было под рукой. У разрабов юникса вроде PDP-7 и PDP-11 были доступны, вот на них и делалось.

Никакого «большинства» просто не существовало.

wandrien ★★
()
Ответ на: комментарий от alysnix

так оригинальный компилятор Modula-2 от вирта для pdp-11 был 5 проходным и лез в 64к

Это немножко другая история.

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

Вот именно, поэтому Модула-2 никому в хер не упёрлась, шликать туда сюда по 5 раз. За это время можно 10 раз скомпилять программу на Си.

no-such-file ★★★★★
()
Ответ на: комментарий от wandrien

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

Нет не ровно. Он предлагал весь код генерировать в буфер, а не инициализацию. К слову сказать в раннем Си функции нельзя было в инициализацию пихать, нужно было писать явно

int c;
c = f();

И такой код ещё долго сохранялся, в ранних Юниксах можно видеть, хотя фичу запилили уже к тому времени.

никак не Си в варианте C89

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

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Вот именно, поэтому Модула-2 никому в хер не упёрлась, шликать туда сюда по 5 раз. За это время можно 10 раз скомпилять программу на Си.

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

alysnix ★★★
()
Ответ на: комментарий от no-such-file

Нет не ровно. Он предлагал весь код генерировать в буфер, а не инициализацию

Нет. Он тебе говорил, что код вида:

{
   int a;
   a = 1;
   foo(a);
   int b;
   b = 1;
   foo(b);
}

эквивалентен коду вида:

{
   int a;
   a = 1;
   foo(a);
   {
     int b;
     b = 1;
     foo(b);
   }
}

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

К слову сказать в раннем Си функции нельзя было в инициализацию пихать, нужно было писать явно

Ну в B так и было, объявление не подразумевало инициализации, это два отдельных statement:

f() {
  auto a;
  a = 1;
}

Но тут вот что интересно. Было ли у компилятора B, который они делали, техническое ограничение о том, что нельзя ставить auto не в начало функции? Я не нашел информации.

wandrien ★★
()
Ответ на: комментарий от wandrien

если компилятор умеет компилировать второй

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

Кроме того, второй вариант создаёт новый скоуп/фрейм каждый раз в однопроходном варианте. Как по мне это не то, что я бы хотел, чтобы компилятор втыкал автоматически.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Кроме того, второй вариант создаёт новый скоуп/фрейм каждый раз в однопроходном варианте.

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

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

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

alysnix ★★★
()
Ответ на: комментарий от alysnix

блоку не нужен свой фрейм

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

под его переменные место зарезервировано в общем фрейме

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

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Что значит не нужен. Переменные на стеке?

на стеке.

fun f(){
  int x = 0;
  {
    int a;
    ...
  }
  {
    int b;
    ...
  }
  {
    int c;
    ...
  }
}

тут будут на стеке сразу в прологе зарезервирован ДВА инта, первый из которых для x, и а второй - место для a, b c. и никаких новых фреймов не надо.

и усьо!

можете поэкспериментировать. запишите a = 333; и прочитайте b без присвоения.

alysnix ★★★
()
Ответ на: комментарий от alysnix

тут будут на стеке сразу в прологе зарезервирован ДВА инта

Нет не будут. Когда однопроходный компилятор видит

fun f(){
  int x = 0;
  {

он не знает что там ещё что-то есть. А когда узнает, то будет уже поздно.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

опять 25. ваш «однопроходовый на перфолентах» существует лишь в вашей голове. реальные однопроходовые делают все в памяти и не парятся.

alysnix ★★★
()
Ответ на: комментарий от alysnix

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

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

примерно до какого года простирается ваш аспект? в каком году он благополучно завершился-то?

когда были перфокарты, вообще компилировали в голове. переводили код фортрана в байты и пробивали в перфокартах дырки. примерно этому периоду и относится «ваш исторический аспект».

alysnix ★★★
()
Ответ на: комментарий от no-such-file

Ты мне так и не ответил, откуда твой однопроходный компилятор в коде

{
  int a = 1;
  int b = f(a);
  int c = 3;
на момент вызова f(a) будет знать про фрейм. Опять сольёшься?

У меня есть подозрение, что твои рассказы про теорию кое-как-компилирования исторически с языком Си никогда не пересекались. С фортраном - вполне вероятно, но речь не про него, а про то, почему в Си было запрещено перемешивание кода и объявлений.

firkax ★★★★★
()

В универе на младших курсах был Pascal/Delphi. begin..end, секция var… Никогда не понимал, почему бы не преподавать более актуальный язык программирования.

Надо запилить опрос типа «Преподаватели, что вас заставляет до сих пор преподавать Паскаль?»

И ответы:

  • ничего больше не знаю
  • садистские наклонности
  • а чтоб хрен эти сопляки нормальную работу нашли ))
Aster
()
Ответ на: комментарий от liksys

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

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

mister_VA ★★
()
Ответ на: комментарий от wandrien

Блок кода позволяет ограничить область видимости переменных

Мой пример и показывает, что так НЕЛЬЗЯ делать, область видимости по «голым скобкам» дырявая минимум для доступа к переменных через printf, если где-то «выше» у вас объявлена переменная с тем же именем. Как бы ни был экзотичен и маловероятен такой прокол, он возможен.

Если уж хотите, то делайте это через if (1) {};

mister_VA ★★
()
Ответ на: комментарий от mister_VA

Если уж хотите, то делайте это через if (1) {};

что за совет? блок в if просто тождественен блоку без if. там и синтаксически и семантически тот же самый блок.

написать

if (1) {
  int x = 0;
  ...
}

эквивалентно записи

{
  int x = 0;
  ...
}

даже без учета того, что компилятор выкинет всегда истинное условие и оставит просто {…}

alysnix ★★★
()
Ответ на: комментарий от mister_VA

Мой пример и показывает, что так НЕЛЬЗЯ делать, область видимости по «голым скобкам» дырявая минимум для доступа к переменных через printf, если где-то «выше» у вас объявлена переменная с тем же именем.

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

вы видите только обьекты из текущего скопа, и всех скопов-парентов. а также подсоединенных скопов, навроде скопа класса и предков его. это если у вас классы есть.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 2)
Ответ на: комментарий от Aster

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

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

С обучением программированию во всём мире очень плачевно, поскольку нет понимания, что сначала идёт пропедевтика «базовые алгоритмы и типы данных» на чём-то очень ясном, общедоступном и «живом» (имеющим трансляторы) (Паскаль, с оговорками Питон), а потом языки программирования в зависимости от специальности с примерами по специальности.

Т.е., если готовим профессиональных программистов, то это Си и далее. Если математиков-теоретиков, то это Лисп, Фортран. Если прикладных математиков, то это Фортран, Лисп, Си. Если физиков, то Фортран, Си. Социологам – R.

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

Например, кафедре ТВиМС желателен был бы курс R, а матану или физикам-ядерщшикам – углублённый курс «числодробилки на Фортране/Лиспе» с использованием реальных компьютеров, не ПК, а мейнфреймов. И всем математикам и физикам – Октаве, GnuPlot как альтернатива недешёвому МатЛабу.

Но где там, зато теперь будет курс «История религий России», как будто студентам на этот курс не будет насрать так же, как когда-то на «Историю ВКП(б)» и «Научный коммунизм».

mister_VA ★★
()
Ответ на: комментарий от mister_VA

Все ваши теоретизирования уместны

Теоретизируешь тут только ты, клоун.

когда она используется периодически далее в следующих 10 тыс строках.

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

liksys ★★★★
()
Последнее исправление: liksys (всего исправлений: 1)
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)