Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

К вопросу о совершенствовании языка программирования

Введение

Введение

            В статье приводятся работы, выполненные небольшим коллективом программистов на протяжении ряда лет. Сложилось так, что ещё в 1987 году было принято решение разобраться в единственном доступном на тот момент компиляторе для персонального компьютера с языка PL/1, созданным американским специалистом Гарри Килдэллом (Gary Kildall). Предполагалось собственными силами сопровождать компилятор и вносить в него изменения по мере развития вычислительных средств. Так и вышло: компилятор прошел весь путь развития от MS-DOS 1.0 до Win32, притом, что сам автор более не занимался этой темой, а в 1994 году погиб. Так что этот компилятор можно считать отечественной разработкой, особенно с учетом большого числа изменений, используемых только здесь. Сопровождение компилятора, помимо массы хлопот имеет и ряд преимуществ, благодаря которым он продолжает и поныне развиваться и использоваться.

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

            В данном случае эти проблемы отсутствовали, причем основным занятием было не сопровождение компилятора, а решение широкого круга задач в Ракетно-космической корпорации «Энергия». Далее приводится сводка результатов многолетнего эксперимента на тему того, как бы программисты переделали стандарт. Большую роль здесь играет субъективный фактор и, вероятно, люди с другими взглядами внесли бы другие изменения. Все это так, но, во-первых, все приводимые изменения — свершившийся факт, а не просто высказанные пожелания, они реально используются, некоторые уже много лет, во-вторых, изменения вводились в результате выявления проблем при решении конкретных задач. Успешное решение этих задач с помощью новых возможностей вселяло уверенность, что «самодеятельное» развитие языка идет по правильному пути.

            Язык PL/1 не знаком большинству сегодняшних программистов. Несмотря на это, в статье не объясняются все его возможности, а описываются лишь изменения относительно стандарта [3] или стандарта упрощенного варианта [4]. Но поскольку PL/1 классический императивный универсальный язык программирования, можно надеяться, что читателям будет несложно разобраться, о каких возможностях и их расширениях идет речь.

Соответствие языка возможностям процессора

            Последние десятилетия, несмотря на быстрое развитие вычислительных средств, на практике пришлось иметь дело почти только с процессорами архитектуры IA-32, являющейся потомком архитектуры IA-16. Первый процессор этой архитектуры, Intel 8086, был выпущен в 1978 году. При его разработке, безусловно, обращалось внимание и на поддержку языков высокого уровня, а в середине 70-х в США PL/1 активно внедрялся фирмой IBM и относился как раз к языкам, которые надо поддерживать архитектурно. Поэтому многие его понятия нашли прямое отражение в командах IA-16/32.

            PL/1 оперирует числами с плавающей и фиксированной точками, что соответствует командам плавающей арифметики, целочисленной арифметики (для целых) и двоично-десятичной арифметики (точные числа с дробной частью). PL/1 оперирует строками, что хорошо соответствует «цепочечным» командам процессора. PL/1 использует логические операции с битовыми строками, что соответствует всем логическим операциям процессора. Наконец, такие объекты языка как процедуры-переменные и метки-переменные строго отображаются в процессоре в команды косвенных вызовов и косвенных переходов. Даже оператор TRANSLATE очень похож на команду «перекодировки» XLAT.

Оператор присваивания в виде обмена

            Но есть команда процессора, не имеющая отображения в PL/1. Это команда обмена XCHG как одновременного двунаправленного присваивания. Оператор взаимного присваивания затребован, например, в алгоритмах сортировки или при работе с такими объектами как семафоры. Поэтому в язык был добавлен оператор обмена в виде: X↔Y;

            Из-за ограничения в символах знак операции обмена был сделан из трех символов: «<», «=» и «>», что оказалось самым наглядным вариантом.

            Если объекты занимают 1, 2 или 4 байта, обмен производится одной командой XCHG и двумя MOV (примеры приводятся вместе с генерацией кода):
DECLARE (X,Y) FIXED(31);
X<=>Y;

A108000000           mov    eax,X
F087050C000000       xchg   eax,Y
A308000000           mov    X,eax
            Для более длинных объектов применяется цикл из команд обмена. Типы и размерности объектов должны строго совпадать, так как из-за преобразований простая команда обмена станет невозможной. Для использования в семафорах генерируется префикс блокировки шины LOCK (байт F0). На практике оператор обмена применялся и для объектов размером в байт, и к фрагментам файлов «отображаемых на память» размером в сто мегабайт.

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

Операторы обнуления

            Стандарт языка [3] позволяет писать операторы вида A=CONSTANT; где A — массив, т.е. работать со сложными объектами как с единым целым. В стандарт [4] эти возможности уже не включены. Однако наличие «цепочечных» команд STOS и SCAS позволяет в части обнуления частично вернуться к таким операторам, причем реализация обнуления проста.

            Поэтому к обычным операторам пересылки массивов типа:
DECLARE (X,Y) (1:10) FLOAT(53);
X=Y;

BE58000000        mov    esi,offset Y
BF08000000        mov    edi,offset X
B914000000        mov    ecx,20
F2 A5             rep    movsd
            Или к обычным операторам сравнения массивов типа:
IF X^=Y THEN ...

BE58000000        mov    esi,offset Y
BF08000000        mov    edi,offset X
B950000000        mov    ecx,80
F3A6              repe   cmpsb
0F95C0            setne  al
3C00              cmp    al,0
7405              je     @1
            Добавлены операторы обнуления как единого целого:
X=0;

BF08000000        mov    edi,offset X
B914000000        mov    ecx,20
33C0              xor    eax,eax
F2AB              rep    stosd
и операторы сравнения с нулем как единого целого:
IF X^=0 THEN ... или  IF X=0 THEN ...

BF08000000        mov    edi,offset X
B950000000        mov    ecx,80
32C0              xor    al,al
F3AE              repe   scasb
0F95C0            setne  al   или 0F94C0   sete  al
3C00              cmp    al,0
7405              je     @2
            Еще добавлены и специальные операторы обнуления. На практике часто требовалось, чтобы первоначально отдельная программа (EXE-файл) со временем включалась бы как процедура в общий модуль большого проекта. Однако если при первом вызове такой процедуры её локальная явно не инициализированная память содержит, как и раньше, нули, то при последующих вызовах могли происходить ошибки, поскольку эта память уже не содержит исходных нулей. Для облегчения перевода программ в процедуры был добавлен оператор обнуления локальных данных подпрограммы одним действием:
TEST:PROCEDURE(A,B,C);
DECLARE...
TEST=0; // КАЖДЫЙ РАЗ ОБНУЛЯЕМ ВСЕ ЛОКАЛЬНЫЕ ДАННЫЕ
...
            Доработка компилятора незначительна, поскольку он имеет и размер, и адрес начала блока локальных данных каждой процедуры, и использует их, например, для запоминания при рекурсии. Новый оператор обнуления внешне похож на присвоение результату функции в Паскале.

            И ещё одной новой формой оператора обнуления является автоматический сброс значения указателя в операторе освобождения памяти:
DECLARE  P       PTR;
DECLARE  X(10)   FLOAT(53) BASED;
... FREE P->X;

33DB                xor    ebx,ebx
F0871D08000000      xchg   ebx,P
E800000000          call   ?FREOP
            Использование команды XCHG вместо MOV позволяет автоматически убирать «висячие ссылки» после освобождения ранее выделенной памяти, хотя, конечно, полностью снять проблему неверных ссылок и не может.

            В обнулении есть тонкость. В целом, заполнение нулевыми байтами соответствует логическому понятию «нуля» в языке. Это годится и для чисел с плавающей и фиксированной точкой, и для целых чисел, и для строк переменной длины (строка нулевой длины считается пустой), и для битовых строк, и даже для указателей понятие нуля и NULL идентичны. И только строка постоянной длины считается в стандарте пустой, если она заполнена пробелами, а не нулями. Но поскольку нулевой символ отображается как пробел и на дисплее, и на распечатке, а встроенная функция TRIM была доработана, чтобы воспринимать нули как пробелы, с таким несоответствием можно мириться, даже учитывая потенциальную возможность ошибок.

Операторы сложной инициализации

            На практике часто требуется выполнить группу операторов только один раз, причем управление проходит через это место в программе более одного раза. Разумеется, можно использовать условный оператор, однократно меняющий свое условие внутри себя. Но в данном случае для подобных целей введен специальный оператор в виде префикса «1» перед составным оператором или оператором цикла, который в PL/1 ограничен словами DO ... END; Поэтому любую группу и любой цикл можно сделать одноразовыми с помощью конструкции:
1 DO ... END;
            При генерации кодов такая конструкция превращается в системный вызов, который при получении управления превращает себя в команду перехода, и затем управление будет обходить всю группу операторов.

Сокращенная форма записи операций

            Форма записи типа X+=2; вместо X=X+2; принята после появления языка Си. Даже фирма IBM дополнила свой транслятор PL/1 в этой части [2]. И в данном компиляторе тоже все операции, имеющие два операнда и результат, помещаемый в первый, могут записываться в сокращенном виде. Это относится и к операции склейки строк:
DECLARE S CHAR(*) VAR;
S||=’ ’; // ДОПИСЫВАЕМ ПРОБЕЛ В КОНЕЦ СТРОКИ S

Улучшение модульности

            В старой реализации PL/1 для компьютеров «Wang» даже вводили новое ключевое слово MODULE, чтобы улучшить модульность программ, так как в стандарте независимой единицей трансляции является процедура, а не модуль. Оказалось, что достаточно просто разрешить трансляцию отдельного BEGIN-блока, поскольку он полностью соответствует понятию модуля. Не потребовалось ни новых ключевых слов, ни, тем более, новых понятий в языке.

Вызовы процедур без ключевого слова

            По мысли разработчиков PL/1, все операторы языка (за исключением присваивания) должны были обязательно начинаться с ключевого слова. На практике оказалось, что ключевое слово оператора вызова CALL можно сделать необязательным, и ни к каким плохим последствиям это не приводит. Конечно, тогда имена процедур уже не могут совпадать с некоторыми ключевыми словами. Но, во-первых, так никто на практике процедуры и не называет, а во-вторых, в таких случаях всегда можно вернуться к использованию CALL.

Вызов функций как процедур

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

            Например, вызов объекта как функции:
//---- НАЧИНАЕМ РИСОВАТЬ СПРАЙТ ----
IF BEGINSPRITE(SPRITE,0)^=0 THEN
      PUT SKIP LIST(’ОШИБКА НАЧАЛА РИСОВАНИЯ СПРАЙТА’);
Использование вызова того же объекта как процедуры:
//---- НАЧИНАЕМ РИСОВАТЬ СПРАЙТ ----
BEGINSPRITE(SPRITE,0);

Доработка операторов цикла

            Операторы цикла в PL/1 довольно развитые, и доработки связаны не с их неудобством, а с доведением до логического конца заложенных в язык идей. Единственный недостаток — отсутствие в стандарте оператора следующей итерации CONTINUE, который и был добавлен в компилятор одной из первых доработок в пару к имеющемуся в стандарте оператору выхода из цикла LEAVE.

            Следующей несложной доработкой циклов стало введение более простой конструкции «бесконечного» цикла вместо заголовка типа WHILE(’1’B). Для этой цели используется единственное и уже имеющееся ключевое слово REPEAT. Бесконечный цикл выглядит как:
DO REPEAT; ... END;
            Еще одной простейшей доработкой языка в части циклов стало расширение применения необязательного имени после END. Т.е. если в языке можно писать имя в конце подпрограммы:
TEST:PROCEDURE; ... END TEST;
то точно также можно писать и имена параметров в конце циклов, в духе предложений [1], например:
DO I=1 TO 100;
      DO J=1 TO 100;
        ...
      END J;
END I;
или вставляя в конец ключевые слова REPEAT/WHILE:
DO REPEAT; ... END REPEAT;
что повышает наглядность и «ошибкоустойчивость» текста программы. Причем стандартная возможность с меткой также сохраняется:
M1: DO REPEAT; ... END M1;
            Более серьезной доработкой стало расширение возможностей «сложных» (составных) циклов, имеющих перечисление через запятую отдельных «простых» циклов в своем заголовке. Идея «сложных» циклов была доведена до уровня полной независимости каждого «простого» цикла в заголовке. Теперь можно менять не только закон приращения параметра очередного цикла, но и сам этот параметр цикла, например, вот задание «квадратной» траектории:
Y=0;
DO X=0 TO 99, Y=0 TO 99, X=100 TO 1 BY -1, Y=100 TO 0 BY -1;
   ПЕРЕМЕСТИТЬ(X,Y);
END;
            Здесь 4 цикла с двумя параметрами, и когда один из них меняется, второй — «замораживается» и остается таким, каким был при выходе из предыдущего «простого» цикла.

            Доработанные циклы оказались даже нагляднее конструкции UNTIL, когда первую итерацию нужно выполнять всегда:
//---- цикл итераций для подбора Axe ----
do Axe=a1/(1e0+j*c2u*si2), while(abs(last-Axe)>=eps);
   last = Axe;                // предыдущее значение полуоси
   j    = Em/Axe/Axe;         // новая часть возмущения
   Axe  = a1/(1e0+j*c2u*si2); // очередное значение полуоси
end while;
            Еще один пример из реальной задачи — нахождение полного приращения DF функции F от шести переменных при решении в частных производных. Вместо длинной записи с шестью вызовами функции F можно использовать «сложный» цикл, причем даже не цикл в обычном понимании, а просто выделение повторяющейся части алгоритма с разными параметрами:
DF=0;  X=X0; Y=Y0; Z=Z0; U=U0; V=V0; W=W0;
F0=F(X,Y,Z,U,V,W);

DO X=X0+DX, Y=Y0+DY, Z=Z0+DZ, U=U0+DU, V=V0+DV, W=W0+DW;
   DF+=F(X,Y,Z,U,V,W)-F0;
   X=X0; Y=Y0; Z=Z0; U=U0; V=V0; W=W0;
END;

Оператор окончания программы с кодом ответа

            На практике оказалось, что оператор окончания программы STOP удобнее, если после него может быть необязательное целое выражение в скобках, например STOP(10); Тогда это значение будет передано операционной системе как код окончания всей программы и может быть использовано, например, «скриптом», запустившим программу.

            Добавлена также возможность писать STOP прямо в конце операторов текстовой выдачи с целью сокращения числа операторных «скобок», т.е. вместо:
IF I=0 THEN DO; PUT SKIP LIST(’ОШИБКА’); STOP(-1); END;
можно писать:
IF I=0 THEN PUT SKIP LIST(’ОШИБКА’, STOP(-1));

Третий параметр функции поиска образца INDEX

            В языке имеется удобная встроенная функция поиска образца в строке INDEX, возвращающая номер позиции найденного вхождения образца или ноль. Но часто нужно найти не первое, а следующие вхождения, и для этого удобнее иметь необязательный третий параметр, показывающий с какого места в строке нужно начать поиск, например, найти последнюю запятую в строке S:
DO I=0, WHILE(I>0);
   J=I;
   I=INDEX(S,’,’,I+1);
END WHILE;
IF J>0 THEN PUT LIST(’ПОСЛЕДНЯЯ ЗАПЯТАЯ В ПОЗИЦИИ’,J);
            В релизе транслятора фирмы IBM [5] как новость упоминается такая же возможность, притом, что в описываемом компиляторе INDEX с тремя параметрами используется ещё с ноября 1993 года.

Встроенные константы времени компиляции

            Для отладочных выводов оказалось удобным иметь константы, автоматически заполняемые компилятором. Имена таких констант решено начинать со знака вопроса, чтобы не путаться с идентификаторами программы. Используются следующие константы:
  • ?DATE — дата сборки программы как строка из 8 символов.
  • ?MD — имя модуля программы
  • ?FILE — имя файла с исходным текстом программы
  • ?PROC — имя текущей процедуры
  • ?LINE — номер текущей строки исходного текста
  • ?INCL — имя текущего файла оператора %INCLUDE
  • ?VER — номер текущей версии компилятора
            С такими константами удобно создавать универсальные отладочные операторы печати, которые могут копироваться в разные части исходного теста.

Упрощение комплексных чисел

            Поскольку в исходном компиляторе комплексных чисел не было, при их реализации было решено максимально упростить эту часть языка. На практике комплексные числа требовались в научных расчетах, поэтому было решено использовать их только в формате с плавающей точкой. Комплексные константы в стандарте [3] рассматривались как выражения, т.е. даже в простом операторе X=1+2i; единица дополнялась нулевой мнимой частью, затем двойка дополнялась нулевой действительной частью и только потом эти два комплексных числа складывались. Для исключения таких преобразований было решено писать комплексные константы в кавычках, как строку: X=’1+2i’; что позволило компилятору разбирать их уже как единые объекты. Но если у константы нет действительной части, её можно писать и без кавычек. Удалось также обойтись и без встроенных функций COMPLEX, REAL, IMAG, CONJG, вместо которых используется просто «наложение» объектов в памяти:
DECLARE
X           FLOAT(53) COMPLEX,
1 Y         DEFINED(X),
   2  R     FLOAT(53),  // ДЕЙСТВИТЕЛЬНАЯ ЧАСТЬ X
   2  IM    FLOAT(53);  // МНИМАЯ ЧАСТЬ X

//---- ЗАМЕНА ВСТРОЕННОЙ ФУНКЦИИ COMPLEX ----
R=1; IM=2; // ПОЛУЧЕНИЕ КОМПЛЕКСНОГО X=1+2i

//---- ЗАМЕНА ВСТРОЕННОЙ ФУНКЦИИ REAL ----
X=’1+2i’;  // СРАЗУ ПОЛУЧАЕМ ДЕЙСТВИТЕЛЬНУЮ ЧАСТЬ В R=1

//---- ЗАМЕНА ВСТРОЕННОЙ ФУНКЦИИ IMAG ----
X=’1+2i’;  // СРАЗУ ПОЛУЧАЕМ МНИМУЮ ЧАСТЬ В IM=2

//---- ЗАМЕНА ВСТРОЕННОЙ ФУНКЦИИ CONJG ----
IM=-IM;   // ПОЛУЧЕНИЕ СОПРЯЖЕННОГО ЧИСЛА X=1-2i

Оператор выхода из обработчика исключения

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

Доработка многозадачности

            На практике оказалось неудобным, что в стандарте языка [3] имеется параллельный запуск процедуры как задачи, но нет принудительного завершения. Поэтому оператор параллельного запуска типа:
CALL TEST TASK; или просто TEST TASK; 
был дополнен оператором снятия задачи:
CALL TEST STOP; или просто TEST STOP;
позволяющим вызывающей процедуре в любой момент остановить вызванную. Был упрощен и оператор синхронизации WAIT, аргументом которого теперь является не специальный объект типа «событие», а простая логическая переменная (битовая строка в один бит).

Контроль выходных параметров процедуры

            В языке PL/1 есть сложности с выходными параметрами процедур. Правила преобразований, в том числе по умолчанию, могут привести к тому, что из-за преобразований, которых программист не ожидал или о которых забыл, вычисления внутри тела процедуры попадут не в выходной параметр, как хотел программист, а в его копию, созданную компилятором. А сам выходной параметр не изменит своего значения. Поэтому добавлен символ «*» как необязательный признак контроля выходного параметра в операторе вызова процедуры или функции. Если в программе применить вызов, например, TEST(A,*B);, и в процессе трансляции из-за преобразований будет создана копия переменной B (т.е. данный параметр не может быть выходным), компилятор выдаст соответствующее предупреждение.

Операторы и переменные низкого уровня

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

            Во-первых, были расширены возможности встроенной функции UNSPEC, которая теперь может встречаться вне оператора присваивания, и тогда генерирует произвольные коды в программе. Например, код исключения отладки в IA-32 (команда INT 3) отображается как UNSPEC(’CC’B4), а код команды чтения из порта (команда IN AL,DX) отображается как UNSPEC(’EC’B4).

            Во-вторых, появились служебные переменные, начинающиеся со знака «?» и обозначающие регистры IA-32.

            Становятся допустимыми конструкции типа:
//---- ВЫХОД В ОТЛАДЧИК, ЕСЛИ ПЕРЕМЕННАЯ X ОТРИЦАТЕЛЬНА --
IF X<0 THEN UNSPEC(’CC’B4);

//---- ЧТЕНИЕ ИЗ ПАРАЛЛЕЛЬНОГО ПОРТА В ПЕРЕМЕННУЮ X ----
DECLARE X BIT(8),?DX BIT(16),?AL BIT(8);

?DX=’0378’B4;
UNSPEC(’EC’B4);   // ЧТЕНИЕ IN AL,DX
X=?AL;

66BA7803           mov     dx,888
EC                 cop     236
A208000000         mov     X,al

Взаимодействие с Win32 API как с процедурами PL/1

            Для использования Win32 API, а также для реализации процедур-«обратных» вызовов Windows потребовалось ввести ключевое слово IMPORT в заголовке процедуры, которое указывает компилятору, что передача параметров и прием результата идет по правилам Win32. Проблемой оказалась и несовместимость имен: в PL/1 у идентификаторов строчные и прописные буквы не различаются, к тому же в DLL-библиотеках встречаются имена длиннее 31 символа. Было решено иметь в системной библиотеке специальные таблицы «псевдонимов», устанавливающие соответствие между именами, которые используются в PL/1 программе и именами, которые реально имеются в DLL-библиотеках. Такие таблицы уже заранее составлены для наиболее используемых библиотек вроде kernel32.dll или user32.dll.

            С точки зрения языка процедуры из динамически подключаемых библиотек имеют атрибуты ENTRY VARIABLE EXTERNAL и именно эти атрибуты автоматически добавляются в случае указания атрибута IMPORT, например:
DECLARE
MOVEWINDOW ENTRY(FIXED(31), FIXED(31), FIXED(31), FIXED(31),
                 FIXED(31), FIXED(31))
           RETURNS(FIXED(31)) IMPORT;

//---- ЗАДАЕМ РАЗМЕРЫ НАШЕГО ОКНА ПО ЭКРАНУ ----
MOVEWINDOW(HWND,0,0,РАЗМЕР(1)-1,РАЗМЕР(2)-1,-1);
            В случае загрузки процедур во время исполнения, таблицы «псевдонимов» не требуются:
//---- ДИНАМИЧЕСКИ ЗАГРУЖАЕМ ФУНКЦИЮ ИНИЦИАЛИЗАЦИИ ----

DCL DIRECT3DCREATE9 ENTRY(FIXED(31)) RETURNS(PTR) IMPORT;
?ЗАГРУЗИТЬ_ИЗ_DLL
     ('D3D9.DLL','Direct3DCreate9',ADDR(DIRECT3DCREATE9));

//---- САМО ОБРАЩЕНИЕ К ПРОЦЕДУРЕ СОЗДАНИЯ ИНТЕРФЕЙСА ----
P_ИНТЕРФЕЙС=DIRECT3DCREATE9(D3D_SDK_VERSION);
            В целом, введенные доработки позволяют использовать процедуры Win32 в полной мере, без ограничений из-за использования PL/1.

Новые встроенные функции

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

            Новая встроенная функция DATE4Y возвращает четыре цифры года и решает «проблему тысячелетия», а функция LDATE достает дату без «лишнего» обращения к Windows, исключая потенциальную ошибку полуночи.

            Новые встроенные функции ASIND и ACOSD (возвращающие ответ в градусах) убирают непоследовательность стандарта, поскольку имеются ATAN и ATAND, COS и COSD, а вот ACOSD/ASIND как пары к ACOS/ASIN — почему-то нет.

            На практике потребовалась и введение новой функции REPLACE, работающей аналогично TRANSLATE, но меняющей не отдельные символы, а заданные образцы строк, например оператор:
S=REPLACE(S,’палки’,’елки’);
заменит в строке S все вхождения образца «елки» на образец «палки», причем результирующая строка в общем случае будет иметь длину, отличную от исходной.

            Одна из новых функций обязана своим появлением удобной команде процессора FSINCOS, выдающей значения синуса и косинуса одновременно. При реализации этой команды как встроенной функции SINCOSSINDCOSD) для сохранения системы тригонометрических функций, имеющих всегда один операнд и один результат, было принято, что функция SINCOS возвращает значение как комплексное число. Это оказалось удачным решением, поскольку пара синуса и косинуса часто требуется на практике именно как комплексное число.

            Потребовалась и новая встроенная функция обработки исключений ONTERM, возвращающая число правильно считанных объектов из списка GET DATA и GET LIST, поскольку если в этих операторах указаны большие списки переменных, бывает затруднительно быстро найти тот элемент в списке, который при чтении вызвал исключение.

            Были расширены применения некоторых уже имеющихся функций. Так, оказалось удобным разрешить обращение к встроенной функции LENGTH не только для строк, но и для файлов, особенно «отображаемых на память». А функция ROUND стала применима и к битовым строкам, для которых она генерирует команду циклического сдвига:
DECLARE B BIT(8);
B=ROUND(B,4); // ПЕРЕСТАНОВКА «ТЕТРАД» В БАЙТЕ МЕСТАМИ

Доработка операторов обмена READ/WRITE

            В стандарте размер данных при обмене с помощью операторов READ и WRITE определяется размером указанных в этих операторах переменных. Но это оказалось неудобным, если размер передаваемых данных заранее неизвестен и определяется ими самими. Например, в читаемом файле указана длина элемента, а затем идет сам элемент указанной длины. В таком случае приходилось организовывать цикл чтения, например в массив объектов размером в байт. Поэтому в операторы READ и WRITE был добавлен необязательный второй аргумент — явная длина в байтах:
//---- ЧИТАЕТСЯ ЧИСЛО БАЙТ ПО РАЗМЕРУ ПЕРЕМЕННОЙ X ----
READ FILE(F) INTO(X);

//---- ЧИТАЕТСЯ X БАЙТ, НЕЗАВИСИМО ОТ РАЗМЕРА A ----
READ FILE(F) INTO(A,X);
            Конечно, в таких случаях программист должен сам следить за тем, чтобы размер переменной не был меньше числа передаваемых байт.

Дублирующие и необязательные ключевые слова

            Язык PL/1 имеет множество ключевых не зарезервированных слов, и как показала практика, не все они удачны или необходимы. Например, выглядит излишним ключевое слово KEYFROM в операторе WRITE вместо просто KEY (как в операторе READ),.поэтому слова KEY и KEYFROM сделаны эквивалентными. Ключевое слово OPTIONS в заголовке процедур и ENVIRONMENT в операторе OPEN обозначают одно и то же — параметры внешней среды, поэтому они тоже сделаны эквивалентными. Также разрешено использовать в операторах DECLARE ключевые слова PROC/PROCEDURE вместо ENTRY, поскольку в стандарте сокращенной версии [4] нет дополнительных точек входов. И в операторе перехода GO TO можно не писать TO.

            А для файлов применен такой же подход, что и для описания размерности массива: если явно не указано ключевое слово, размерность должна быть обязательно в начале описания:
DECLARE X(1:10) FLOAT(53);
DECLARE X FLOAT(53) DIMENSION(1:10);
            В данном компиляторе точно так же ключевое слово FILE можно не указывать в операторах обмена, но тогда его имя должно идти в начале оператора:
OPEN (F) PRINT;
OPEN PRINT FILE(F);
            Необязательным стало и ключевое слово ERROR в обработчиках исключительных ситуаций, т.е. вместо ON ERROR(35) ... можно писать просто ON(35) ... Такие допущения упрощают написание программы на PL/1.

Объединение исключительных ситуаций

            В стандарте разрешено объединять однотипные операторы в один с помощью запятых, т.е. например, вместо:
CLOSE FILE(F1); CLOSE FILE(F2);
можно писать короче:
CLOSE FILE(F1),FILE(F2); или CLOSE(F1),(F2);
            Однако в стандарте так не сделано для операторов исключительных ситуаций, имеющих одинаковые «тела». В данном компиляторе такие операторы тоже можно объединять:
ON ENDFILE(F), CONVERSION, ERROR(35) STOP;

Выделение памяти без указания имени объекта

            Стандарт требовал, чтобы в операторе ALLOCATE явно указывались имена объектов, которым выделяется память. Однако на практике нужно выделять и память для передачи как параметра процедуры без указания имени. Поэтому была внесена доработка: если в операторе указывается не имя, а выражение в скобках, то выделяется заданное число байт и адрес начала записывается в указатель:
ALLOCATE(100000) SET(P);
            В транслятор IBM VisualAge PL/I были внесены подобные изменения, но с изменением и первоначального синтаксиса оператора:
P=ALLOCATE(100000);

Коэффициент повторения в строчных константах

            В данном компиляторе в отличие от стандарта коэффициент повторения перенесен в конец строки, например, четыре байта единичных бит можно записать как ’1’(32)B. Это упростило компилятор, но главное, коэффициент повторения строчной константы перестал путаться с коэффициентом повторения при инициализации начальных значений. Например:
DECLARE Х(10) CHAR(5) STATIC INITIAL((10) ’*’(5));
здесь внутри атрибута INITIAL (10) — это повторение констант в массиве, а (5) — повторение символа в константе.

Определение длины строки по длине инициируемого значения

            Было добавлено автоматическое определение длины строк по максимальной длине инициируемых значений, например:
DECLARE S(1:4) CHAR(*) VAR
        STATIC INIT(’СЕВЕР’,’ЮГ’,’ЗАПАД’,’ВОСТОК’);
Компилятор назначит длину строк в массиве S равной 6.

Знак подчеркивания в числовых константах

            В данном компиляторе можно писать числовые константы, используя для удобства чтения знак подчеркивания (как и в языке Ада), например: X=1_000_000;

Использование специальных символов

            Еще одной особенностью стало разрешение использовать «псевдографические» символы там, где разрешены пробелы, причем они и воспринимаются компилятором как пробелы (если не стоят внутри текстовых констант). Это позволяет применять всякие «уголки» и «полочки» в исходном тексте, например, для выделения циклов на нескольких строках. Такое оформление облегчает анализ текста. Нашлось применение и не определенным в стандарте фигурным скобкам. Было принято, что открывающая фигурная скобка эквивалентна слову DO, а закрывающая — END, т.е. можно писать в стиле, напоминающим язык Си, например:
IF X=0 THEN {; Y=1; Z=2; };

Доработка комментариев

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

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

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

            Были также введены препроцессорные операторы для управления подробностью отладочной печати, которые задаются в тексте программы как числа %0 ... %9 обычно в начале строки. При запуске трансляции можно задать число — «уровень» отладочной печати. Если число %0 ... %9 меньше или равно данному уровню — компилятор превращает его в два пробела, иначе в две косых черты (в однострочный комментарий). Это позволяет иметь вывод с разной степенью подробности и варьировать его уровнем при трансляции. Эту же возможность можно применять и просто для получения разных вариантов программы без редактирования её текста.

Управление кодировкой

            Из-за того, что PL/1 был рассчитан на англоязычную среду, потребовалось добавить кириллицу. Причем сразу ставилась задача свободного её использования, в том числе и в ключевых словах (см. раздел ниже). Появление «кириллицы Windows» усложнило кодировку, так как в консольном окне осталась «кириллица DOS». Это привело к использованию текстовых строк-констант вместе с «квалификатором» W, обозначающего кодировку Windows, например:
DECLARE
S1 CHAR(*) VAR STATIC INITIAL (’Привет!’),
S2 CHAR(*) VAR STATIC INITIAL (’Привет!’W);
Первый символ строки S1 имеет код 8F. Первый символ строки S2 имеет код СF.             Для операторов выдачи PUT DATA, содержащих идентификаторы на кириллице, были добавлены препроцессорные операторы %D и %W, переводящие PUT DATA в соответствующую кодировку и действующие до появления следующего подобного препроцессорного оператора.

Русификация

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

            Русификация реализована как предопределенная таблица значений для ключевых слов и встроенных функций, каждая из строк которой эквивалентна препроцессорному оператору %REPLACE и содержит элементы типа:
ЕСЛИ     BY IF,
ТОГДА    BY THEN,
ИНАЧЕ    BY ELSE,
На рисунке представлен фрагмент исходного текста реальной программы с учетом изложенных выше особенностей.
Исходный текст программы на русифицированном PL/1

Заключение

            Рассмотренные в статье расширения языка составляют лишь небольшую часть от проведенных работ по развитию системы программирования на PL/1, поскольку основные затраты пришлись на переработку компилятора, разработку библиотек, средств отладки и т.п. Однако без изменений в самом языке многие решения так и остались бы неэффективными, неудобными или просто неудачными. Легко заметить, что все изменения носят эволюционный характер и о создании нового языка PL/2 речь не идет.

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

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

Литература

1. «Ошибки программирования и приемы работы на языке ПЛ/1» Л.Ф. Штернберг, Москва «Машиностроение», 1993.
2. G.U.I.D.E. & SHARE Europe Joint Conference (10-13 October 1994, Vienna, Austria) «Power vs. Adventure — PL/I and C». Eberchard Sturm. Munster, Germany.
3. American National Standard: programming language PL/I. New York, NY, American National Standards Institute, 1979 (Rev 1998); 403p. ANSI Standard X3.53-1976.
4. American National Standard: information systems — programming language — PL/I general-purpose subset. New York, NY, American National Standards Institute, 1987; 449p. ANSI Standard X3.74-1987.
5. What’s new in Enterprise PL/I 4.1 and z/OS XL C/C++ V1R12 Peter Eldern, Chwan-Hang Lee IBM Corporation February 28, 2011.

Автор: Д.Ю.Караваев. 29.12.2011

Опубликовано: 2018.08.26, последняя правка: 2019.01.28    20:49

ОценитеОценки посетителей
   ██████████████████████████████████████████ 1 (100%)
   ▌ 0
   ▌ 0
   ▌ 0

Отзывы

     2019/03/28 08:50, rst256          # 

Знак подчеркивания в числовых константах

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

     2019/03/28 22:53, Автор сайта          # 

Если обратить внимание, когда написана статья (2011 г.), то не удивительно, что Дмитрий Юрьевич выбрал знак нижнего подчёркивания. В тот момент этого сайта не существовало, поэтому познакомиться с пробелами между цифр он не смог :) А вот Rust и другие были перед глазами, а там приняты «_» :(

     2019/03/29 12:18, kt          # 

Скорее, здесь повлиял уже готовый компилятор. Поскольку лексический анализатор выдает по одной лексеме, в том числе и числовые константы: целые, дробные и плавающие, а пробел — универсальный разделитель лексем, то нужна серьезная переделка. Что чревато граблями и подводными камнями.

Целые константы — только цифры, дробные — есть точка, плавающие — есть порядок «Е».

Пробелы можно ставить везде? Или только в целых? Несколько пробелов подряд можно? А табуляцию? И стоит ли такая овчинка выделки?

А подчеркивание ничего сильно не меняет, одна лексема остается. И в Аде уже проверено на практике (исправление в компилятор было внесено в июне 1999 года).

     2019/03/30 17:58, Comdiv          # 

Если для задействования пробела в числах нужна существенная переделка, то возникает вопрос: как же был воплощён лексический анализ в трансляторе Килдалла? Обычно завершение лексемы ищут не по разделительному символу, а по отсутствию допустимого, так как разделителем может послужить всё, что угодно, например, арифметические знаки или знаки препинания. Добавить в допустимые символы пробел несложно.Более того, раз знак подчёркивания уже обработан как внутренний разделитель, то достаточно просто заменить его на пробел.

То есть, если, утрируя, оригинальный считыватель чисел выглядел так:
REPEAT
i := i + 1
UNTIL ~isDigit(source[i])
То с одиночным разделителем это выглядело бы так
REPEAT
REPEAT
i := i + 1
UNTIL ~isDigit(source[i])
UNTIL ~isDigitSeparator(source[i]) OR ~isDigit(source[i + 1])
А что проверяется в isDigitSeparator — пробел или знак подчёркивания — не имеет значения.

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

     2019/03/31 14:27, Автор сайта          # 

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

     2019/03/31 14:20, MihalNik          # 

И не понятно, почему такая мода на подчёркивание в новых языках

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

     2019/03/31 16:27, Автор сайта          # 

Очень может быть, что не бездумное, в вполне себе расчётливое. Для создания эффекта «О, я это уже знаю». Десятки, наверное, языков копируют синтаксис Си не от того, что он наилучший, а для того, чтобы казаться уже знакомым, оказывать наименьшее сопротивление при изучении. С одной стороны, консерватизм — это хорошо. Но он не всегда оправдан.

     2019/04/11 03:12, rst256          # 

Десятки, наверное, языков копируют синтаксис Си не от того, что он наилучший...

Да по возможностям он один из лучших, в каком еще языке есть: «+=» и т.п. операции. Присваивание как выражение, например «if(x=fx(...)){ ... }». Инкремент и декремент «++» и «--»). Тернарный оператор ветвления «усл ? то : иначе».

Обычно именно это перенимают из синтаксиса Си, ну и операторные скобки «{}», ибо это короче чем «begin/end». Ну еще формат строковых литералов, ибо, наверное, удобнее нет ничего: "string\n". А еще мое любимоё: 0 — ложь, не 0 — истина. Я когда изучал Си, долго этим восхищался: как естественно и удобно такое решение.

     2019/04/11 16:40, Автор сайта          # 

Читаю замечательные «Воспоминания советского программиста» и встречаю объяснение популярности Си: это был первый язык программирования для программистов!

Так чем очаровывал Unix? Прежде всего, языком C, на котором был написан. Долгожданным языком программирования для программистов. Стоп! А другие языки, тот же ФОРТРАН или КОБОЛ, они для кого? Да, для нас, конечно, для кого ж ещё. Но только эти языки были заточены под решение тех или иных прикладных задач — инженерно-расчетных или бухгалтерско-учетных, а вот как быть с задачами неприкладными? Они как невидимая часть айсберга — неприметная громадина, с которой пользователь напрямую не соприкасается: операционные системы и базы данных, компиляторы тех же языков программирование, утилиты, драйверы устройств и и ещё тысячи всяких разных программ, сервисов, библиотек функций и т.д. и т.п. И все это нам надо программировать. На чем? Нынче и вопроса такого не возникает, но ведь было время, когда в ответ звучало: «на ассемблере» — на низкоуревневом машинном языке. Или же на языках вроде ФОРТРАНа или ПЛ/1 — чересчур высокоуревневых. Гений дизайнера (Денниса Ритчи) как раз и проявился в безошибочном выборе уровня языка, уровня абстракции — достаточно близкого к «железу», чтоб обеспечить эффективность и достаточно далекого от него, чтоб не утратить мобильность… А ещё язык был как-то очень ладно скроен, явственно ощущалось, что запроектировал его человек, знаюший ремесло программера не понаслышке. Короче говоря, прочитав с восторгом описание языка (тут ещё сыграла свою роль изумительная книга Кернигана и Ритчи, недаром называемая «the White Bible» и по праву считающаяся шедевром технической прозы) и написав пару-тройку программок я уже ни на каких других языках работать не хотел. (Но всему свое время: уже лет пятнадцать, как я на нем не работаю и… не хочу — на C++ или C# куда как удобней)…

Си — не «профессорский» язык или «бухгалтерский», а «программистский». Вот поэтому его ждали любовь и признание. Он очаровал тем, в чём нуждались программисты. Если смотреть на Си с позиций сегодняшнего дня, то видны недостатки то там, здесь. Но для того времени это был замечательный язык.

     2019/04/13 22:05, MihalNik          # 

Впечатления мало чем отличаются от сегодняшних восхищений, открывающих для себя какие-то (притом как новые, так и давно существующие) ЯП на разных форумах. Фортран вообще был самым первым реализованным ЯВУ, но в СССР пришел на десяток лет позже, а Си появился спустя 15 лет. И это не Фортран был слишком высокоуровневым, это в Союзе был слишком низкий уровень программирования и отсутствие основного состава системного ПО. Ну а количество ПО на Коболе на загнивающем Западе было велико:

ещё в 2006 году Кобол считался языком программирования, на котором было написано больше всего строк кода

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

И кто бы его не критиковал, но американская экономика вывезла свой банковский сектор на нем:

К 1997 году активно использовалось около 240 миллиардов строк кода на Коболе, кодом на Коболе обрабатывалось около 90% финансовых транзакций в мире и 75% коммерческих транзакций

Тут сразу налицо эпичность оставания СССР в программировании.
Фортран — 1957 г., Бэкус
Лисп — 1958, МакКарти
Кобол — 1959, Хоппер

     2019/04/14 12:38, Неслучайный читатель          # 

И это не Фортран был слишком высокоуровневым, это в Союзе был слишком низкий уровень программирования

Я вам не скажу за всю Одессу, но в 1980-е годы многие прикладные задачи решались на ассемблере. Не на Фортране, не на PL/1, а именно на ассемблере. Сам в этом участвовал. Кобол был на «задворках», и я за всю свою жизнь не встретил ни одного программиста на Коболе! Для первого и второго поколения советских ЭВМ и транслятора Кобола вообще не существовало, по-моему. Когда же появились ЕС ЭВМ и Кобол вместе с ними, то кому Кобол мог понадобиться? К тому времени уже был PL/1 — более продвинутый.

К 1997 году активно использовалось около 240 миллиардов строк кода на Коболе

В 1997 году чуть было не устроился работать программистом на Коболе. Предстояло решать проблему 2000 года, в старом ПО год записывали двумя цифрами. Как же было неохота изучать реликтовый язык программирования! Кстати, после знакомства с Коболом понял, откуда ноги растут у xBase и SQL.

Один мой однокашник писал, по его словам, АСУ одной из АССР. Но на чём? На Фортране!

Эпичность отставания была связана с тем, что СССР был небогатым государством. Плюс плановая экономика. Инициативные люди в СССР не могли заработать денег на передовых идеях, не могли вложить эти деньги в развитие идей. Впереди стояла стена плановой экономики. Зачем руководителям было шевелиться, что-то менять, если вся работа была расписана на пятилетку вперёд? Чтобы что-то продвинуть, инициативы снизу чаще всего не хватало. Нужны были волевые усилия сверху.

Линейка техники ЕС ЭВМ появилась в расчёте на то, что мы перепишем западное ПО. Не в смысле «заново напишем», а в смысле «перепишем ПО с американских носителей информации на советские». Решили сэкономить. Не будь этой экономии, пришлось бы писать самим, тратить на это деньги и время, отнимать кусок хлеба у стариков и детей.

     2019/04/14 15:37, Автор сайта          # 

В наших палестинах тоже были не лыком шиты. Вот далеко не полный перечень отечественных языков. Но продолжения всё это не получило :(

     2019/04/14 15:34, MihalNik          # 

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

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

По воспоминаниям Хоппер, когда у неё появился компилятор, все вокруг еще думали, что ЭВМ — это просто калькулятор для арифметических действий.

     2019/04/14 16:45, Автор сайта          # 

Не до всех доходило коренное отличие ЭВМ и калькулятора: ЭВМ не только вычисляет, но и помнит.

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

Тут надобно пояснить несведущему читателю обстоятельства дела. Когда-то в самом начале компьютерной эры в чью-то начальницкую голову пришла здравая (на первый взгляд) идея: а чего это, товарищи, одну и ту же задачу должны решать в нескольких организациях? У нас, чай, не капиталистические джунгли, конкуренции быть не может, экономика передовая — плановая. Ну так и воспользуемся ее преимуществами, т.е. пусть кто первый сделал какую программу, сейчас же сдаст ее в центральный фонд; другие же народные деньги попусту не тратят, не дублируют работу, а используют готовую. Ну, усовершенствуют там, если надо. Как не захотят отдавать в фонд? А сознательность? Ах, все равно не хотят! Так это мы быстро — издадим постановление, что покуда нет справки из ЦПС о приемке в фонд проектной документации, покуда тамошний клерк вам эту бумажку не подмахнул, сдача вашего проекта заказчику даже начаться не может; ни о каком выполнении плана, ни о какой премии и разговора нет. Система получилась: ius primae noctis — своего рода право первой ночи применительно к программированию. Что оно большой радости не доставляло, это можно пьесу Бомарше вспомнить. Только там (в пьесе) Альмавива не утратил еще величия и влиятельности; Фигаро привычно еще ему кланяется; сам комизм ситуации говорит о возможности полюбовного покамест ее разрешения. У нас же какой там смех, грех один. Ладно бы провинциалы (вроде моей конторы) на поклон туда ездили, так ведь столичные надменные фигары, институты, возглавляемые академиками и членами ЦК, тоже — куда денешься — отправляли ходоков на поклон к убогому тверскому альмавиве за заветной справкой. Кафкианский абсурд бессмысленного ритуала в том был, что никто ни разу этим фондом не воспользовался, захотел бы — не смог…

А почему, кстати? А потому, хотя бы, что сдать требовалось именно документацию, сиречь запись программы на бумаге. Это когда все только начиналось и программировали с помощью штырьков на коммутационной панели, идея может была и ничего; не прилагать же штырьки, в самом деле. С течением времени появились, правда, магнитные носители и в правила добавили, что комплект документации можно дополнить магнитной лентой. Ха! Отдать им еще на халяву и магнитную ленту. Ха-ха-ха! А списывать ее как? А самим что? Помидоры-то как подвязывать?..

Тут опять же надобно пояснить, какое отношение имеют помидоры к советским информационным технологиям. Самое прямейшее, чтоб не сомневались. По весне весь советский народ, как вы помните, выходил на свои шесть соток и высаживал картошку, огурчики, помидорчики и прочие овощи, которые по неведомым агрономической науке причинам упорно не хотели произрастать на миллионах гектаров колхозных полей… Ну так вот: помидоры надо подвязывать. Чем? В ход шли веревки всякие, бечевки, которые быстро размокали, рвались… короче — тот еще геморрой. То ли дело мы, причастные к передовым технологиям XX века. На наших грядках весело играли на солнце блестящие коричнево-черные полоски магнитной ленты — прочные, неразмокающие, они держались все лето и осень до холодов. Поэтому, по весне странная эпидемия косила магнитные ленты: они и падали-разбивались, и рвались в лентоводах и размагничивались с невозможностью дальнейшей эксплуатации. В одном знакомом ВЦ так даже крысы-мутанты обьявились — сгрызли, гады, целый шкаф с лентами аккурат в мае месяце… Короче, вы понимаете, что отдать за просто так ценнейший для домашнего хозяйства ресурс… ищи дураков.

Вредные калининские тетки ленты не требовали. Зато на книжках с документацией пытались отыграться… А тексты программ надо было представлять не просто так, а как всякую проектную документацию — на листах-форматках в рамочке и со «штампом» с тремя подписями (исполнитель, руководитель, нормоконтролер). Позже, к середине 80-х, было разрешено эти рамки-штампы выпечатывать на компьютерном принтере вместе с текстом, что породило лавину разработок оригинальных документаторов и усовершенствования западных программ (nroff-troff) на предмет научения их печатанию «в рамках»… Ну это все будет потом, а покамест требования ортодоксально-твердые: или рамка и штампик чертятся тушью от руки, или они отпечатаны типографски на бланке. Но тогдашние барабанные принтеры печатать умели только на фальцованной бумажной ленте. Так что оную ленту потом резали, наклеивали на бланки, а затем светокопировали «на синьки». Каковые (синьки) давали совсем не синий, а слабый красновато-фиолетовый оттиск на грязновато-желтом фоне. Но если даже кто-то особо зоркий мог на этих синьках различить текст программы, далеко не факт, что он видел всю программу!

Как я говорил, распечатку на фальцованной ленте надо было нарезать на листы. Ну вот, она и поступала к вечно пьяненькому переплетчику Яше (наша гордость — пьющий еврей-пролетарий). Так он устраивал тот еще брис! Если справа чуток больше рубанет — уйдут концы длинных строк. Потом по фальцам — чик-чик. Что там было около сгибов пропечатано, да кто ж теперь узнает. А если те листочки локтем задел и потом сложил, так вы думаете, в том же порядке? А если в это время клиент пришел книгу переплетать, бутылку принес (святое!), закусь; так листочки колбаску разложить они из клиентовой книжки, думаете, брали?.. Да, а сам я, как вы думаете, загодя, за месяц распечатав программу, потом ее больше не правил? А как же ее заставить работать, если ничего не менять? Работать она начинала аккурат в последнюю ночь перед сдачей…

В общем какого качества макулатура сдавалась, всем было ясно. Однако ж, надо тащить это дерьмо в Калинин. А начальство норовит, как всегда, совместить-сэкономить. Едешь себе в нормальную командировку. «Вот и славненько; заскочишь (!) в Калинин, сдашь там махонький, легонький совсем (на пуд с гаком!) проектик». Куда деваться, тащишь. Можно представить, — с каким чувством. А тамошним теткам этот негативный заряд, вероятно, передается и они в ответ начинают куражиться. Скажет одна: «А вот мы возьмем сейчас… да хоть эти вот два листа, отперфорируем и введем в ЭВМ. Будут работать?» — «Конечно, — отвечаю, — какие сомнения. А ближайшая колонна химического синтеза у вас где?» «Какого-такого синтеза?» «А такого. Видите, что в названии прописано: Новомосковское объединение “Азот”, АСУ технологических процессов. Синтезом, значит, управляем. Так что, колонна-то где?» Скривится, подпишет бумажку…

Возвращаешься в веселом настроении, газетку читаешь. Там как раз статья о грандиозных успехах советского программизма. Что в то время, дескать, как дураки-западнюки разбазаривают свои ресурсы в конкуренции, наш «Центрпрограмсистем» уже накопил три миллиона программ и тридцать тысяч автоматизированных систем на благо народного хозяйства. Так что, мы далеко ушли вперед и микросхемы наши — самые большие в мире! Читаешь и думаешь: если у вас, ребята, в ракетных шахтах таких же кондиций стоит, как в «цэпээсе» лежит — мир может спать спокойно…

     2019/04/14 18:19, MihalNik          # 

Проблема не в распечатке как таковой, а в приемке и дальнешем способе распространения. Ленты копировать, думаю, было несложно, а по тем временам это колоссально емкие носители данных. Распечатки можно было делать для изучения во всяких профильных вузах. Естественно, на месте. Думаю, изучать код с бумаги явно полезнее, чем с экрана ЭЛТ, который еще и жутко дорогой тогда был, а распечатки можно передавать из рук в руки. И если был бы язык вроде Кобола, только с русскими словами — программы можно было бы даже зачитывать на лекции для записи студентами. Да, пусть звучал бы код кривавато, но масштабы и скорость обучения выросла б на порядок.

     2019/04/14 22:15, MihalNik          # 

Вот еще какой вопрос возник. А была ли до Сей практика распечатки наборов заголовков процедур? Т.е. по сути основной библиотечной информации для программистов.

     2019/04/22 16:02, Автор сайта          # 

Кто б ответил на этот вопрос? Моя осведомлённость не уходит корнями в глубь веков и не могу сказать, что было до Си. Может, Дмитрий Юрьевич может что-то сказать? Всё-таки PL/1 появился до Си.

Идею Кобола приблизить язык программирования к естественному языку не встретили «на ура». Это иллюзия, что запись словами повышает ясность текста. Так бы давно математика в школе обходилась бы словами. Лобачевский: «Чему одолжены своими блестящими успехами науки, слава нынешних времен, торжество ума человеческого? Без сомнения, ИСКУССТВЕННОМУ языку своему!».

     2019/04/22 17:31, MihalNik          # 

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

     2019/04/23 12:18, kt          # 

До Си в нашей стране был БЭСМ-Алгол. Там проблемы распространения решались легко, поскольку из библиотеки вытаскивался не оттранслированный модуль, а прямо его исходный код. В качестве примера (хотя, может быть, и не совсем в тему) вот ссылка на древние программные разработки, которые мы с удовольствием используем до сих пор, а гамма-функция и интеграл вероятности включены в системную библиотеку нашего компилятора, поскольку являются встроенными функциями языка: http://files.rsdn.org/122727/MATH.pdf

Даже без этого описания можно было анализировать как раз только заголовки библиотечных функций — и вперед! Сам я раз сдавал программу в Общий фонд алгоритмов и программ в 1980 году. Но не припомню, чтобы при этом я куда-то ездил или готовил распечатки. Заполнялась специальная карточка на программу и сама программа записывалась на ленту.

     2019/04/23 12:57, Автор сайта          # 

MihalNik
И где тут сходство с блок-схемами? В упор не вижу:
a + (b + c) = (a + b) + c
(x + y)(x - y) = x**2 — y**2
(x + y) **2 = x**2 + 2*x*y + y**2
(a**m) **n = a ** (n*m)
(x**2)' = 2*x
Не согласен, что современные языки программирования стали ближе к естественной речи. Haskell ближе к математике. Rust, Go, Swift — разве они так же подробно «разжёвывают», как древний Cobol?

Разница в численности — не порядки. Не забывайте о математиках, которые преподают в школах и вузах. Что-то Вы как-то не в тему :(

kt

Несмотря на хихиканье остальных сотрудников, эта работа была проведена

Да, помню такие времена, когда всё советское считалось гнилым и отсталым, а западное — априори передовое, прогрессивное.

     2019/04/23 15:43, MihalNik          # 

И где тут сходство с блок-схемами?

Так Вы написали скорее на каком-то ЯП (или подобии), а не математическим языком)
Звездочек нет, там смещение знака и уменьшение размера надписей должно быть. Дроби, индексы — тоже смещения, вложенные скобки — меньшего размера. Т.е. вполне себе графическая схематичность.

Haskell ближе к математике

А его запись — к линейному письму.

Не забывайте о математиках, которые преподают в школах и вузах.

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

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

     2019/05/11 08:57, utkin          # 

Си — не «профессорский» язык или «бухгалтерский», а «программистский». Вот поэтому его ждали любовь и признание. Он очаровал тем, в чём нуждались программисты. Если смотреть на Си с позиций сегодняшнего дня, то видны недостатки то там, здесь. Но для того времени это был замечательный язык.

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

Я вам не скажу за всю Одессу, но в 1980-е годы многие прикладные задачи решались на ассемблере.

Потому что таков был сам уровень решаемых задач. Вот и оцените масштаб трагедии. Что лучше — решать какую-нибудь ракетную баллистику на ассемблере или на PL/1? Ностальгировать-то конечно приятно, но и не видеть бездарность такого подхода...

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

Вы думаете, сейчас что-то сильно изменилось :) ? Любое серьезное начинание только с одобрения руководства, даже не сомневайтесь на этот счет. Сделать собственный Яндекс Вам никто не позволит, ибо как же политика и цензура тогда :)?

В наших палестинах тоже были не лыком шиты.

Теперь, когда прошло столько времени, можно смело спросить — во имя чего все это было?

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

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

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

Это Вы про то, что на Коболе миллиарды строк кода? Еще как на ура. Иначе никто бы на нем столько не писал.

Это иллюзия, что запись словами повышает ясность текста.

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

Так бы давно математика в школе обходилась бы словами.

Так что же в математике совсем слов нет? Прямо вот все тайными значками пишут? Всё-всё-всё? У них есть просто краткая форма записи терминов которые всем понятны. Потому что в математике НЕ ПРИДУМЫВАЮТ новых концепций в каждом вычислении. Математика это не программирование. В программировании Вы создаете новую модель и описать ее просто закорючками сложно. Хотя бы потому что математика декларативная форма описания.

Лобачевский: «Чему одолжены своими блестящими успехами науки, слава нынешних времен, торжество ума человеческого? Без сомнения, ИСКУССТВЕННОМУ языку своему!».

Он жил в 18-м веке. Тогда еще программированием и не пахло особо. Вы еще Пифагора начните цитировать...

     2019/05/11 09:13, utkin          # 

И где тут сходство с блок-схемами? В упор не вижу.

Так Вы тут алгоритм и не представили, а представили ГОТОВЫЙ РЕЗУЛЬТАТ. А вообще-то эти преобразования нужно ПРОВОДИТЬ. А Вы взяли готовые формы. Например,
(x + y)(x - y) = x**2 — y**2
Это алгоритмы символьных преобразований. Типа, раскрыть скобки:
(x + y)(x - y)=x*x + y*x - y*x -y*y
И только потом уже
x**2 — y**2
Просто в учебниках дают готовые результаты преобразований (что, кстати, и приводит к тому, что дети потом не понимают, как это работает). Это вообще-то не аксиомы ни разу, а цепочки символьных вычислений.

Haskell ближе к математике. Rust, Go, Swift — разве они так же подробно «разжёвывают», как древний Cobol?

А ничего, что Хаскелл вообще-то маргинальный язык? И Раст, кстати, тоже не для кухарок. Вы еще Брейнфак бы на одну доску поставили. Отлично разжевывает Джава (оцените количество строк кода на Джава и на Раст), чудесно разжевывает C#. Весь мейнстрим — он как раз быдлокодерский и отлично всё объясняет без этих ваших формул. По поводу Go:
package main

import "fmt"

func add(a int, b int) int {
return a + b
}

func main() {
fmt.Println("Сумма равна ", add(10, 19))
}
Что Вам тут математичного? Ваш аргумент явно шит белыми нитками.

     2019/05/12 14:31, Автор сайта          # 

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

А ставить знак равенства между теми условиями и сегодняшними — это признак одарённости? Когда на машине — 1 Мб оперативной памяти, но на ней должны работать несколько задач одновременно, то какому языку отдать предпочтение? Запускаешь на трансляцию простейшую программу на ассемблере — и смело можно уходить курить, результат появится только к концу перекура. И что тут говорить о трансляции на том же PL/1?

Вы думаете, сейчас что-то сильно изменилось :) ? Любое серьезное начинание только с одобрения руководства, даже не сомневайтесь на этот счет. Сделать собственный Яндекс Вам никто не позволит, ибо как же политика и цензура тогда :)?

Вы думаете, лично Путин давал «добро» Сысоеву, Бреславу и Попкову на создание Nginx, Kotlin и «Одноклассников»? А Вам для создания нового Яндекса не хватает исключительно тёплого взгляда Темнейшего?

Теперь, когда прошло столько времени, можно смело спросить — во имя чего все это было?

Ну а теперь, с высоты минувших лет, ответьте — для чего создавались ЭВМ «Урал», «Минск», «Мир», БЭСМ, «Эльбрус»? Во имя чего? Можно, конечно, ответить, что с целью торжества коммунизма. А раз коммунизм почил в бозе, то и языки программирования, и ЭВМ были бесполезны. Но лично я вижу в этом стремление к саморазвитию, торжество человеческого разума. Не будь такого опыта — не нарос бы гумус, отсутствовала бы интеллектуальная почва. И к тому моменту, когда Вы решили изучить программирование, просто не было бы книг по программированию на русском языке — кто бы их написал?

Так что же в математике совсем слов нет?

Пишем классную или домашнюю работу: «Дано» — а далее, выражаясь языком программистов, ТЗ — техническое задание. В решении: «45/3 = 15 — скорость велосипедиста». Вторая часть этой записи — комментарии, если по-программистски. Сходств немало.

Он жил в 18-м веке.

Он был ректором Казанского университета в 19 веке (1827 — 1845 годы). Довелось побывать в той старинной аудитории, где он преподавал. Постоял у кафедры. Необычные ощущения — прикоснулся к истории.

Так Вы тут алгоритм и не представили, а представили ГОТОВЫЙ РЕЗУЛЬТАТ.

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

Просто в учебниках дают готовые результаты преобразований (что, кстати, и приводит к тому, что дети потом не понимают, как это работает)

У Вас похожая ситуация произошла с русским языком. В каждом Вашем сообщении мне приходится исправлять Ваши ошибки.

Это вообще-то не аксиомы ни разу

Повторюсь: писали про блок-схемы. При чём здесь аксиомы?

А ничего, что Хаскелл вообще-то маргинальный язык? И Раст, кстати, тоже не для кухарок.

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

Что Вам тут математичного? Ваш аргумент явно шит белыми нитками.

Вы привели выше запись на искусственном языке. Если бы стремились к естественному, то там было бы написано «function», а не «func», «integer», а не «int», «summarize a and b», а не «a + b», «print line», а не «Println». Не фигурные скобочки, а «begin» и «end». Так было бы «по-кобольски». И язык математики, и язык программирования — это искусственные языки — и это их объединяет. И если какой-то язык программирования не похож на математический язык, то это не значит, что он естественный.

     2019/05/12 20:02, utkin          # 

А ставить знак равенства между теми условиями и сегодняшними — это признак одарённости? Когда на машине — 1 Мб оперативной памяти, но на ней должны работать несколько задач одновременно, то какому языку отдать предпочтение? Запускаешь на трансляцию простейшую программу на ассемблере — и смело можно уходить курить, результат появится только к концу перекура. И что тут говорить о трансляции на том же PL/1?

Что снова говорит об отсталости. PL/1 это же не эзотерика и не роскошь, а средство решения проблем. И в сравнении с ассемблером решение очевидно.

Вы думаете, лично Путин давал «добро» Сысоеву, Бреславу и Попкову на создание Nginx, Kotlin и «Одноклассников»?

А почему в одном ряду не стоит ВКонтакте и Дуров, у которого его доблестно отжали :) ?

Во имя чего? Можно, конечно, ответить, что с целью торжества коммунизма. А раз коммунизм почил в бозе, то и языки программирования, и ЭВМ были бесполезны.

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

И к тому моменту, когда Вы решили изучить программирование, просто не было бы книг по программированию на русском языке — кто бы их написал?

Вирт, Ахо, Дейкстра, Торвальдс и пр.?

Пишем классную или домашнюю работу: «Дано» — а далее, выражаясь языком программистов, ТЗ — техническое задание.

А это классическая подмена понятий. Сама задача записана в нормальной форме. А домашняя работа это уже формализация процесса. Никто полтора землекопа не записывает в лямбда. Нет, там написано, что то типа такого:
"Два землекопа за 2 часа работы выкопают 2 м канавы. Сколько нужно землекопов, чтобы они за 100 час. работы выкопали 100 м такой же канавы?"

Он был ректором Казанского университета в 19 веке (1827 — 1845 годы). Довелось побывать в той старинной аудитории, где он преподавал. Постоял у кафедры. Необычные ощущения — прикоснулся к истории.

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

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

Потому что Вы не пытались их искать. А они очевидно есть, иначе люди не могли решать такие задачи. Навскидку:
1. Раскрыть скобки, чтобы избавиться от особого порядка вычислений
2. Избавиться от аргументов, сумма которых равна нулю

Пойдет такой?

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

Но ведь блок-схема все равно получится? Может это и оскорбляет Ваше чувство прекрасного, но ответ тот же — символьные вычисления имеют определенный порядок, а следовательно имеется алгоритм, который можно пытаться выразить в блок-схеме.

У Вас похожая ситуация произошла с русским языком. В каждом Вашем сообщении мне приходится исправлять Ваши ошибки.

Не отрицаю, что есть, то есть.

Повторюсь: писали про блок-схемы. При чём здесь аксиомы?

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

Ну так и теория относительности не всем доступна

Это другое. Она может и не всем доступна, но она обязательна для решения проблем в физике. В программировании Хаскелл НЕ ОБЯЗАТЕЛЕН, потому что есть иные языки, способные решать проблемы без математических загибонов (точней без ярко выраженных загибонов). Сравнение не уместно.

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

Первоначальный посыл был другой. Вы пишите:

Не согласен, что современные языки программирования стали ближе к естественной речи. Haskell ближе к математике. Rust, Go, Swift — разве они так же подробно «разжёвывают», как древний Cobol?

Вы в качестве примера дали не репрезентативную выборку. Я Вам дал именно мейнстрим — Ява, C# и т.д. А они именно за естественную запись, а не за хаскелловскую. Критерий отбора прост — количество написанных строк кода, количество разработчиков в мире и количество вакансий в мире. И Хаскелл здесь на обочине. Хаскелл интересен, но он не определяет развитие программирования и его тенденций. Он всего лишь один из ряда ему подобных.

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

Это не искусственный язык, а пример кода на языке GO.

     2019/05/14 12:52, Автор сайта          # 

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

Во-вторых, потому что обсуждения зациклились. Не видно выхода из очередной итерации пережёвывания одного и того же. Я утверждаю, что все языки программирования — это искусственные языки. Специально придуманные, а не стихийно возникшие в территориально ограниченной общности людей. Вы же говорите, что пример кода на языке Go — это не искусственный язык, что Ява и C# — это естественная запись. Это говорит о том, что прийти к общему мнению мы не можем, а потому дискуссию следует прекратить — она бесполезна.

     2019/05/16 17:27, Неслучайный читатель          # 

Уткину: Вы тут рассуждаете о бездарности подхода, если разработку ведут на ассемблере. А ничего, что компилятор PL/1, про который тут пишут, не один десяток лет пишется на ассемблере? Просто разработчик забил на всё «современное» и «прогрессивное», на всех советчиков и работает себе в удовольствие. Респект и уважуха!

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

     2019/06/05 14:42, utkin          # 

Уткину: Вы тут рассуждаете о бездарности подхода, если разработку ведут на ассемблере. А ничего, что компилятор PL/1, про который тут пишут, не один десяток лет пишется на ассемблере? Просто разработчик забил на всё «современное» и «прогрессивное», на всех советчиков и работает себе в удовольствие. Респект и уважуха!

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

     2019/06/05 20:08, VIT1972          # 

А ничего, что компилятор PL/1, про который тут пишут, не один десяток лет пишется на ассемблере?

Вообще-то ничего хорошего. Факты таковы:
1. Самые мощные компиляторы того же PL писались на PL же.
2. Ассемблер приводит к полной непортабельности, он жестко привязан к платформе.
3. Обсуждаемый компилятор писался на ассемблере не от хорошей жизни — читайте историю его создания.
4. Трудность сопровождения и модификации. Не автором.
4. Из плюсов только скорость работы, не самое ценное качество для компилятора.

     2019/06/05 23:21, kt          # 

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


В данном случае привязка к платформе не из-за того, что написан на ассемблере, а из-за того, что генерирует "нативный" код x86 или x86-64.

     2019/07/25 13:00, utkin          # 

В данном случае привязка к платформе не из-за того, что написан на ассемблере, а из-за того, что генерирует "нативный" код x86 или x86-64.

Здрасьте. А ОС Вам так и дала её проигнорировать да? То есть по-Вашему нативный код x86 на Windows 98 также красиво запустится на Win10 без танцев с бубном? Или в Линуксе?
Очевидно, что исполняемый файл имеет свой формат, который отличается в различных операционных системах, а не только в разрядности и архитектуре процессора.

     2019/07/25 19:54, Александр Коновалов aka Маздайщик          # 

То есть, по-Вашему нативный код x86 на Windows 98 также красиво запустится на Win10 без танцев с бубном?

Да.

Вообще-то, любой прикладной код для Win32, работавший на Windows 98, будет работать и на Windows 10. Потому что формат 32-разрядного EXE-файла остался тем же (PE), прикладное Win32api со времён Windows 98 только расширялось. Понятное дело, с системным ПО (вроде антивирусов) или с драйверами это не прокатит, они используют специфические для Windows 98 функции, полагаются на конкретную ОС и т.д.

Также, скорее всего, код для Win16, работавший на Windows 98, пойдёт и на Windows 10 x86 (но не x64, поскольку в них нет 16-разрядной подсистемы).

А вот наоборот, программы для Windows 10 (даже x86) на Windows 98, скорее всего, не пойдут. Поскольку компилировались более новыми компиляторами, используют новые функции API, как минимум, используют API из WinNT.

Т.е. если компилятор порождает Win32-код, который работает на Windows 98 (и не использует специфические средства Win9x: API, ключи реестра), то он будет работать и на Windows 10. Обратное не верно.

Windows 98 была только под x86, поэтому x64 на ней запустить в принципе невозможно.

Или в Линуксе?
Очевидно, что исполняемый файл имеет свой формат, который отличается в различных операционных системах, а не только в разрядности и архитектуре процессора.

А с этим никто не спорит. На Windows формат исполнимого файла PE (portable executable), на Linux — ELF.

     2019/07/25 21:34, kt          # 

То есть по-Вашему нативный код x86 на Windows 98 также красиво запустится на Win10 без танцев с бубном?

Я имел ввиду, что есть две версии компилятора: plink.exe для Win-32 и plink64.exe для Win-64, которые генерируют разные версии PE-файлов.
Однако набор Win API в обоих случаях одинаковый:
https://pl1.su/%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b0-%d0%b2%d1%8b%d1%81%d0%be%d0%ba%d0%be%d0%b3%d0%be-%d1%83%d1%80%d0%be%d0%b2%d0%bd%d1%8f-%d1%87%d0%b5%d1%80/

     2019/07/29 10:28, utkin          # 

Потому что формат 32-разрядного EXE-файла остался тем же (PE)

Во-первых, Вин98 поддерживал ещё и 16-разрядные приложения.
Во-вторых, в теории все просто. Откройте Интернет — куча статей и тем на форумах о том, как же запустить старый софт на Вин7-Вин10. Или режим совместимости в ОСях так для красоты придуман?

     2019/07/30 14:06, Александр Коновалов aka Маздайщик          # 

Во-первых, Вин98 поддерживал ещё и 16-разрядные приложения.
Во-вторых, в теории все просто. Откройте Интернет — куча статей и тем на форумах о том, как же запустить старый софт на Вин7-Вин10. Или режим совместимости в ОСях так для красоты придуман?

**utkin,** я знаю про 16-разрядные приложения (и, кстати, упоминал их в своём комментарии), и про то, что на практике всё сложнее, и про режим совместимости. Если про всё это писать, предыдущий комментарий стал бы в три раза длиннее.

Ядро Win9x гибридное — нативно поддерживает и 16-, и 32-разрядные программы, это обеспечивало максимально возможную совместимость с DOS и Windows 3.1. В WinNT для x86 есть подсистема для запуска 16-разрядных программ, но идеальную совместимость это не обеспечивало. И, на сколько я знаю, эта подсистема есть даже в Windows 10 для x86 (не проверял). На Windows NT x64 этой подсистемы нет, поскольку тупо нет возможности запустить в длинном режиме процессора 16-разрядный код.

Для того, чтобы запускать старый софт в Windows 7, Микрософт даже придумала Windows XP Mode — виртуалку с предустановленной 32-разрядной Windows XP, куда можно ставить программы, не идущие под Windows 7. (Жалко, что они не сохранили Windows Virtual PC, на котором работал Windows XP Mode, в следующих редакциях. Виртуалка была простая и удобная, не то, что Hyper-V.) Понятно, что если бы с обратной совместимостью было всё гладко, костыль такой эпичности в систему бы не воткнули.

Добавить свой отзыв

Написать автору можно на электронную почту mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Каким должен быть язык программирования?

Анализ и критика

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

Двадцать тысяч строк кода, которые потрясут мир?

Почему владение/заимствование в Rust такое сложное?

Масштабируемые архитектуры программ

Почему Хаскелл так мало используется в отрасли?

Бесплатный софт в мышеловке

Исповедь правового нигилиста

Русской операционной системой должна стать ReactOS

Почему обречён язык Форт

Программирование без программистов — это медицина без врачей

Электроника без электронщиков

Программисты-профессионалы и программирующие инженеры

Статьи Дмитрия Караваева

●  Идеальный транслятор

●  В защиту PL/1

●  К вопросу о совершенствовании языка программирования

●  О реализации метода оптимизации при компиляции

●  О реализации метода распределения регистров при компиляции

●  О распределении памяти при выполнении теста Кнута

●  Опыты со стеком или «чемпионат по выполнению теста Кнута»

●  О размещении переменных в стеке

●  Сколько проходов должно быть у транслятора?

●  Чтение лексем

●  Экстракоды при синтезе программ

●  Об исключенных командах или за что «списали» инструкцию INTO?

●  Типы в инженерных задачах

●  Непрерывное компилирование

●  Об одной реализации специализированных операторов ввода-вывода

●  Особенности реализации структурной обработки исключений в Win64

●  О русском языке в программировании

●  Формула расчета точности для умножения

●  Права доступа к переменным

●  Заметки о выходе из функции без значения и зеркальности get и put

●  Ошибка при отсутствии выполняемых действий

●  Скорость в попугаях

●  Крах операции «Инкогнито»

●  Предопределённый результат

Компьютерный юмор

Новости и прочее

Последние комментарии

2019/08/19 19:19 ••• Автор сайта
Шестнадцатиричные и двоичные константы

2019/08/05 19:22 ••• Геннадий Тышов
Программирование без программистов — это медицина без врачей

2019/07/30 14:06 ••• Александр Коновалов aka Маздайщик
К вопросу о совершенствовании языка программирования

2019/07/21 20:30 ••• Автор сайта
Деньги = работа / знание

2019/07/20 19:42 ••• Александр Коновалов aka Маздайщик
Права доступа к переменным

2019/07/20 15:11 ••• Александр Коновалов aka Маздайщик
Статьи Дмитрия Караваева

2019/06/25 11:22 ••• VIT1972
Идеальный транслятор

2019/05/14 16:10 ••• utkin
Обработка ошибок

2019/05/09 18:05 ••• евгений
Русский язык и программирование

2019/04/22 16:19 ••• Автор сайта
Почему языки с синтаксисом Си популярнее языков с синтаксисом Паскаля?

2019/04/03 22:24 ••• Антон
Все голосования

2019/04/02 12:25 ••• Автор сайта
Выбор кодировки для компилятора