Автор Тема: Oberon-07/11: Замечания по результатам использования.  (Прочитано 38451 раз)

akron1

  • Jr. Member
  • **
  • Сообщений: 76
    • Просмотр профиля
Итак, я написал несколько десятков тысяч строк некачественного, но работающего кода на этом языке. Кратко расскажу об этом опыте.

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

Перечислю некоторые особенности языка/реализации, которые можно считать недостатками:

- ран-тайм проверки (индексы, указатели). Замедляют и так небыстрые программы. Но оказывают неоценимую помощь, позволяют быстро выявить такие ошибки, которые бывает очень трудно найти без пошагового отладчика и прочих средств. Вряд ли я хоть что-нибудь написал бы на O7 без них. Конечно, люди разные, есть и такие, которые могут кодировать сразу без ошибок на любом языке, но я к таким не отношусь.

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

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

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

Операторы:

- CASE. Вероятно, использование этого оператора для проверки типа указателя (как в поздних ревизиях) вполне оправдано. Для проверки целочисленных значений позволяет сделать более эффективный и компактный машкод, чем серия IF. Без ELSE практически бесполезен.

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

- WHILE ... DO ... ELSIF ... DO. "Цикл Дийкстры" - почти бесполезен, хотя и не мешает. Одно из немногих применений:
PROCEDURE Scroll (value: INTEGER);
BEGIN
  value := 2 * value;
  WHILE value > 0 DO
    Down;
    DEC(value)
  ELSIF value < 0 DO
    Up;
    INC(value)
  END
END Scroll;
Конечно, здесь можно сделать по-другому, но мне показалось, что "цикл Дийкстры" подходит лучше.

Типы:

- SET. Применяется нечасто, но бывает полезен, когда надо упаковать несколько булевских значений в одну переменную, чтобы не раздувать список параметров.
- Беззнаковое целое. Я ни разу не пожалел о его отсутствии. Конечно, бывают случаи, когда этот тип был бы полезен, но для 32-битной реализации это бывает нечасто. Для 64-бит, ИМХО, вообще "не стОит выделки".
- ANYREC, ANYPTR. Лучше бы были.
- Динамические массивы. Без них плохо.
- POINTER TO. Здесь желательно ослабить типизацию, как это сделано в КП.
- Псевдонимы типов. Лучше бы были. В поздних ревизия они есть.

Встроенные процедуры:

- ORD(BOOLEAN): INTEGER. Используется довольно часто, странно, что в AO ее нет.
- BITS(INTEGER): SET. Такой процедуры в O7 нет. Пришлось добавить в дополнение к ORD(SET): INTEGER.
- LSR. Такой процедуры нет, но она однозначно нужна. Тоже добавил в дополнение к LSL.
- LENGTH(ARRAY OF CHAR): INTEGER. Используется часто, лучше, когда она встроена в язык. Тоже добавил.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
В свете задачки из соседней ветки ( http://oberspace.dyndns.org/index.php/topic,695.0.html ), вопрос - твой компилятор не научился кодогенерить для *nix'ов? Может какой-то еще есть компилятор который уже вменяемо держит язык и умеет компилить консольные *nix приложения?

А то из компиляторов которые умеют генерить нативный x86 или AMD64 *nix бинарь приходится выбирать из XDS, BB и A2. При этом у двух последних имеется некоторый геморрой на тему создания консольного stand alone приложения и автоматизации сборки.
Y = λf.(λx.f (x x)) (λx.f (x x))

akron1

  • Jr. Member
  • **
  • Сообщений: 76
    • Просмотр профиля
Давно уже можно генерить для Linux, в инструкции написано. Только без библиотек это неудобно. И зачем тестировать на производительность игрушечный компилятор?

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Давно уже можно генерить для Linux, в инструкции написано. Только без библиотек это неудобно. И зачем тестировать на производительность игрушечный компилятор?
Ну я же описал проблему. И, что-то мне кажется, что узким местом в той задаче будет не производительность сгенерированного кода :-)
Y = λf.(λx.f (x x)) (λx.f (x x))

trurl

  • Full Member
  • ***
  • Сообщений: 133
    • Просмотр профиля
- LSR. Такой процедуры нет, но она однозначно нужна. Тоже добавил в дополнение к LSL.
А разве нельзя вместо LSR(x, n) использовать LSL(x, -n)?

akron1

  • Jr. Member
  • **
  • Сообщений: 76
    • Просмотр профиля
Это связано с архитектурой x86. Там для сдвигов влево и вправо используются разные команды. При этом, величина сдвига помещается в регистр cl (8 бит), но процессор учитывает только младшие 5 бит. Т. е. величина сдвига всегда в диапазоне 0..31. Не знаю как в ARM, но в реализации Astrobe тоже есть LSR.

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
- единственный выход из процедуры, отсутствие прерываний циклов. Спорная фича. Затрудняет кодинг, увеличивает размер и снижает эффективность кода, немного упрощает отладку.
А вот я склонен считать это сильной стороной. Всегда так пишу вне зависимости от выбранного языка. Если не привыкать к обратному, то и не возникает желания писать неструктурно. В MISRA C есть похожие, но не доведённые до логического конца требования.

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Итак, я написал несколько десятков тысяч строк некачественного, но работающего кода на этом языке.
Смотрел я исходники твоего fb2-ридера, толком не разглядывал, но выглядит куда лучше, чем у Вирта, так что нормлаьный код, нечего себя принижать )))
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Если не привыкать к обратному, то и не возникает желания писать неструктурно. В MISRA C есть похожие, но не доведённые до логического конца требования.

Во-первых, оно только у труЪ оберонщиков считается "неструктурно", за пределами оберон-сообщества никто не комплексует по поводу множественного RETURN.
Во-вторых, я целый компилятор написал и так и не привык. Будет еще одно расширение в ебероне.
В-третьих, единственный RETURN порождает объективную проблему - увеличивает вложенность кода, что крайне хреново сказывается на читабельности.

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Зачем же Вы с плеча так рубите про труЪ Оберонщиков? Это ценится не только у них, но и, например, у людей, пишущих защищённый код. В таких задачах нередко возникает потребность в зачистке важных данных в уже неиспользуемых переменных https://www.securecoding.cert.org/confluence/display/c/MEM03-C.+Clear+sensitive+information+stored+in+reusable+resources. Угадайте, где больше шансов пропустить очистку. Это, конечно, лишь частный случай большой картины, но переубеждать не берусь, я за свободу религий.

Цитировать
Во-вторых, я целый компилятор написал и так и не привык
Вы это серьёзно? А сколько до, во время и после написания транслятора Вы написали кода не так? Привычка подразумевает стабильность и отсутствие предубеждённости, естественно.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Зачем же Вы с плеча так рубите про труЪ Оберонщиков? Это ценится не только у них, но и, например, у людей, пишущих защищённый код. В таких задачах нередко возникает потребность в зачистке важных данных в уже неиспользуемых переменных https://www.securecoding.cert.org/confluence/display/c/MEM03-C.+Clear+sensitive+information+stored+in+reusable+resources. Угадайте, где больше шансов пропустить очистку.

Вы сами читали там по ссылке? :) Там постоянно упоминатеся некий /* Handle error */, а вот что там внутри очень интересно применительно к "структурности". Cудя по коду внутри там или goto (привет линукс-стайл) или какой-нибудь abort (аварийное завершение программы) или return :) Четвертого не дано, потому что оно крэшиться будет сразу после такого if'а :)

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

Картина такая, что люди пытаются избежать многоуровневых if'ов. В разных языках по-разному. В С с помощью goto. В С++ RAII. В джавах/шарпах return/finally. И только в оберонах влолженные if'ы готовый считать чем-то хорошим, лишь бы не множественый return.

Цитировать
Во-вторых, я целый компилятор написал и так и не привык
Вы это серьёзно? А сколько до, во время и после написания транслятора Вы написали кода не так? Привычка подразумевает стабильность и отсутствие предубеждённости, естественно.

До компилятора тоже пытался пару недель соблюдать в рамках работы (C++). Убедился что не, херня получается.

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Вы сами читали там по ссылке? :) Там постоянно упоминатеся некий /* Handle error */, а вот что там внутри очень интересно применительно к "структурности". Cудя по коду внутри там или goto (привет линукс-стайл) или какой-нибудь abort (аварийное завершение программы) или return :) Четвертого не дано, потому что оно крэшиться будет сразу после такого if'а :)
Наверно, нужно было прояснить для чего была ссылка, ведь как говорится в одной из вариаций закона Мерфи, если есть малейшая возможность, что поймут неправильно, то обязательно кто-то поймёт неправильно. А я оставил не просто малейшую возможность, а большущую  ;D и наводящий вопрос не оправдание - не тот случай.
Ссылка была дана для показа реальной, хотя и довольно неочевидной потребности. То, как предлагают её решать на этом ресурсе - это отдельная песня, скажу только, что они составляли свой список правил из раздельного анализа выявленных уязвимостей, целостного решения они не предлагают.
Ну а я повторю заданный ранее наводящий вопрос, может быть в этот раз получится лучше. Как Вы думаете, в каком случае проще упустить нужную зачистку(и не только)?

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Картина такая, что люди пытаются избежать многоуровневых if'ов. В разных языках по-разному. В С с помощью goto. В С++ RAII. В джавах/шарпах return/finally. И только в оберонах влолженные if'ы готовый считать чем-то хорошим, лишь бы не множественый return.
А вот это вообще умора. Сначала люди придумывают отступы, чтобы сделать поток управления более наглядным, а затем уничтожают наглядность с помощью неструктурных переходов, и даже считают, что всё в порядке. Если так не нравятся лишние отступы, может просто их не делать :) ?

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Цитировать
Во-вторых, я целый компилятор написал и так и не привык
Вы это серьёзно? А сколько до, во время и после написания транслятора Вы написали кода не так? Привычка подразумевает стабильность и отсутствие предубеждённости, естественно.

До компилятора тоже пытался пару недель соблюдать в рамках работы (C++). Убедился что не, херня получается.
Такой богатый опыт заслуживает апплодисментов.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Как Вы думаете, в каком случае проще упустить нужную зачистку(и не только)?

Допустим у нас O7. "Зачистки" не так актуальны, потому что 95% зачисток берет на себя GC. В 5% я согласен написать вложенный IF. Но GOTO лучше :) (можно с контролем, что только в конец процедуры, как раз для зачисток).