Comments 114
P.S. Есть прямые варианты запуска программ KolibriOS почти как родные в рамках Linux и Windows.
Эмуляция KolibriOS API (Windows)
Эмулятор под Linux
Ну и разные варианты Паскаль компиляторов тоже есть под KolibriOS, включая и Oberon.
Видно вы увлечены языком Паскаль, а в чем по вашему мнению достоинства этого языка по сравнению с другими — скажем из первой десятки популярности (на выбор)
Однако Паскаль, как и всякий язык, требовалось развивать. Компания Borland внесла здесь огромный вклад, и уже в ранних Turbo Pascal все недостатки, описанные Керниганом, были устранены. Но, фактически став детищем Borland, Паскаль вместе с этой корпорацией и умер (увы, судьба языков слишком зависит от судьбы корпораций).
В результате чуть не половина языков из «первой десятки» тащат за собой наследие C, пытаясь с ним совладать. Вот, нам мой взгляд, недостатки C, которые так или иначе просвечивают и в его потомках и которые совершенно чужды Паскалю:
- Отсутствие ключевых слов, обозначающих вид объявляемого идентификатора:
function
,var
,type
и т.д. Из-за этого начинается нездоровая игра со скобками, а читаемость программы резко ухудшается. - Сильная зависимость от препроцессора. Без него невозможно подключить внешний модуль или задать подлинную константу, не занимающую памяти.
- Провалившаяся попытка отождествить массивы и указатели. Насколько я понимаю, сначала разработчики языка надеялись на полное отождествление. Однако как только пришлось допустить массивы в качестве полей структуры, тождество стало фикцией. В результате для двумерного массива
A
все величиныA
,&A
,*A
,A[0]
,&A[0]
равны друг другу. Не абсурд ли это? - Неудобный оператор
switch
. Это вынужден был признать ещё Керниган. - Параллельное существование у структур «имени типа» и «тега типа». Как такое могло появиться, я вообще не представляю.
Я понимаю, что от многих этих недостатков пытаются уйти — если не в C++, то в каком-нибудь Go. Однако здесь мне остаётся присоединиться к одному меткому комментарию на Хабре:
Не понимаю, зачем индустрия хоронит Паскаль, а потом много раз изобретает его заново.
в С++ от этих недостатков не ушли, а добавили новые, усложнив при этом и так не простой процесс компиляции кода. Неудивительно, что современный тренд — делать языки с максимально простым синтаксисом и простейшим компилятор. Тем более в тренде автогенерации кода
У C-подобных языков есть большое преимущество: возможность объявлять переменную там, где она нужна и тогда, когда она нужна. В паскале-подобных языках приходится или заранее, до написания собственно кода, придумывать, что написать в var
блоке, либо бегать туда-сюда при написании кода, либо заполнять var
блок когда функция уже написана. Ни один из вариантов не похож на заботу о программисте.
У Паскаля есть большое преимущество — программиста учат думать перед тем, как что-то написать. А необьявление переменных было в бейсике)
Не более, чем для любого другого языка программирования.
программиста учат думать перед тем, как что-то написать
Да, возможно, что для обучения это хорошо. Но это для обучения. В промышленном же программировании удобнее, когда можно писать не думая.
Што-а? А потом мы имеем глючные, медленные программы.
Потому что думать нужно всегда
Но соглашусь в том, что когда язык именно, что вставляет палки в колеса разработки, заставляя отвлекаться от самой функциональной нагрузки кода — это очень плохо
В промышленном же программировании удобнее, когда можно писать не думая.Истинно.
(утверждение прямо в стиле Черномырдина)
У C-подобных языков есть большое преимущество: возможность объявлять переменную там, где она нужна и тогда, когда она нужна
Да, но до C99 в C (например, C89) ситуация с объявлением переменных тоже была почти как в Паскале. За тем исключением, что:
1) можно было объявлять переменные не только в начале функции, но и в начале блока (scope), глобальные переменные в расчёт не берём
2) не было необходимости в отдельном var-блоке
Из-за этого в C89 даже привычную сейчас декларацию переменную цикла for приходилось объявлять заранее, а не внутри for-конструкции.
Это уже будет не совсем паскаль. Если начать добавлять в него подобные нюансы, то они потянут за собой другие изменения и в итоге получится что-то сильно другое.
- допустим, мы разрешили объявлять переменные в произвольных местах.
- Было бы логично добавить автовывод типов, чтобы не писать лишнего конструкции вида
var a := 2
- можно прикрутить константы (напимер,
val a := 2
), чтобы код стал более строгим. - тогда захочется, чтобы конструкции типа if возвращали выражения, чтобы было удобно инициализировать константы:
val sign := if (a>=0) then 1 else 0 end
В итоге получается сильно другой язык с более сложным компилятором. Мне кажется, уж если менять, то всё сразу.
Если остановиться на пол-пути и сделать только первое изменение, то возможность легко разложить переменные функции по регистрам/стеку пропадает (придётся анализировать все возможные пути исполнения, включая использование goto), а сам язык не станет сильно лучше.
Язык и эволюция? Это такой же миф как и апгрейд.
Может просто стоит выкидывать каждый старый язык и писать ещё один лучший новый, на основе новых достижений и ошибок прошлого?
Иначе мы имеем кейс с++, когда нужно тянуть ворох всей обратной совместимости с классическим Си и его модификациями, так и предыдущими ревизиями С++. Это усложняет и удорожает разработку компилятора, но кого это волнует? А вот то, что это удорожает разработку на этом языке, т.к. постоянно нужно допиливать код и обходить "ловушки", которые появляются из-за разных версий стандарта. Ну, что ж.
И, действительно, если б все было так хорошо с эволюцией, то не появились бы golang, d, rust. Хотя и они менее популярны, как кресты, по крайне мере сейчас
begin
begin
var a:=123;
Writeln(a);
end;
begin
var a:=123.456;
Writeln(a);
end;
begin
var a:=now;
Writeln(a);
end;
begin
var a:='Marasmus C in Pascal';
Writeln(a);
end;
readln;
end;
Ждем реализации сишных макросов, обязательной препроцессорной обработки и регистро-зависимого объявления переменных.
Брр-р-р-р, шикарный язык уродуют чудаки на букву м (с)
Ждем реализации сишных макросов, обязательной препроцессорной обработки и регистро-зависимого объявления переменных.
Зачем ждать это в паскале, если прямой сейчас можно перейти на C++ и получить все эти преимущества немедленно?
возможность объявлять переменную там, где она нужна и тогда, когда она нужна в PASCAL-подобных языках
Пожалуйста:
В Modula-3 ( ...).Однако, локальная область определения переменной цикла в данном случае вполне соответствует «духу» языка (поскольку возможны прочие локальные области в виде вложенных блоков «VAR… BEGIN… END» для поддержки «горячего определения переменных в коде», в т.ч. с возможностью вывода типа, но оставаясь в рамках «структуризации по-Паскалевски»).
Практика использования вышеупомянутого в Modula-3:
caltech-parser\cit_util\src\SIsuffix.m3
FOR i := FIRST(List) TO LAST(List) DO
VAR
x : BOOLEAN;
BEGIN
x := tbl.put(List[i].char, List[i]);
<* ASSERT NOT x *>
END
END
m3-libs\bitvector\test\src\TestBitVector.m3
FOR i := 0 TO Max - 1 BY 7 DO
FOR j := 1 TO 6 DO
VAR set := bv2.set(i+j); BEGIN <* ASSERT NOT set *> END
END
END;
Аналогично — в ADA
Когда доделаю очередную статью по надежности, будет чуть подробнее.
Уж точно не более нездоровая, чем вечное «begin...end».
begin
...end
), а круглые в предложениях вида void (*fun_ptr)(int) = &fun
. Их обилие напрямую связано с отсутствием ключевых слов для вида объявляемого идентификатора.А стоит только появиться
typedef
в начале, так fun_ptr
, стоящий в середине, вдруг окажется именем типа. И это тоже логично?Нет, независимо от вашего конкретного примера я всего лишь подумал о часто встречающемся использовании круглых скобок помимо математических операций и перечисления аргументов.
>И разве это логично
Вы всего лишь привыкли к паскалевскому синтаксису и субъективно, т.е. для вас, непривычный синтаксис в C/C++ объявляете объективно нелогичным :-)
C is sometimes castigated for the syntax of its declarations, particularly ones that involve pointers to functions. The syntax… can be confusing ..., because declarations cannot be read left to right, and because parentheses are over-used.
Так исторически синтаксис Си и появился, чтобы быть компактным (1) и иметь возможность быть набранным на клавиатурах той эпохи (2) — поэтому и есть странные вещи в спецификации языка, вроде триграфов.
2. Ничего из клавиатурных ограничений или кодовых таблиц не заставляет писать «int *a» вместо «var a: *int».
Компактность — единственное, что тут можно более-менее вменить как причину таких синтаксических выборов. Но и то — настолько жёсткую экономию на 2-3 ключевых словах — получаем буквально пару процентов за счёт резкого ухудшения в сложных случаях…
Защитники сразу же скажут, что, мол, надо знать и понимать, что делаешь, однако статистика уязвимостей показывает, что, похоже, 9 из 10 всевозможных багов и дыр в современном ПО связаны прямо или косвенно с тем, что за всем этим уследить невозможно, как бы ты хорош не был. Если ружье на стене висит, оно обязательно выстрелит.
В Паскале об этом вообще думать не надо практически, что позволяет сосредоточиться на задаче, а не бегать смотреть, там ли ты поставил звездочку, вычитывать warnings компилятора и стараться понять, это ты плохо сделал или это просто перестраховка от компилятора.
Эх, вспоминаю свою юность, ночами на пролет писал на Паскале для Fido, потом портировал это все на пиратский Virtual Pascal, который умел компилировать под Win и OS/2, потом на Free Pascal уже под Linux (и все портирование, кстати, было в убирании прямой работы с видеопамятью и изменение пары типов переменных; вот она сила Паскаля, код из 1998 года компилируется в 2019 :).
Захожу раз в год на свой github, перечитываю и пересматриваю код и радуюсь воспоминаниям.
Дикая усидчивость, терпение и желание творить были. Имея под рукой только одну книжку по Паскалю, несколько чужих примеров, ворованную techhelp библиотеку про прерывания, получалось делать массу всего и очень быстро.
P.S. А выбор в свое время пал на Паскаль только потому, что, когда мне с трудом удалось достать диск с разными компиляторами, он был поцарапанный и архив с Borland C не читался, а Borland Pascal распаковать удалось.
В Паскале об этом вообще думать не надо практически
Это за счёт чего это? В Паскале нет указателей, разименований и прочих конструкций?
Скорость компиляции в Дельфи) у меня может быть проект на 500 тыщ строк и я могу компилировать после любого изменения и через 1сек видеть результат
Считаю, что это очень гармонично спроектированный, лёгкий для чтения и удобный для компиляции язык.
Золотые слова!
А еще наиболее удобный (с мой точки зрения) для начального обучения.
Проблема питона в нескольких вещах
- Конкуренция между питон 2. и питон 3. Если б своевременно закопали второй, то мы бы быстрее получили нормальный третий
- Отсутствие четкости в тех же типах переменных. Это приводит к тому, что быстро наговнякать скрипт или какой-то маленький проект на питоне действительно очень легко. Но создать большое и надёжное продакшн решени тяжело. Я не говорю, что невозможно, это решаемая проблема, но на какой-нибудь джаве это будет проще, т.к. она больше страхует разраба от него самого. Но ценой своеобразного тулинга и большей многословности кода
Мой опыт программирования начинался с Бейсика, и переход к языкам с явной статической типизацией был мучителен.
А у меня — не был. В Бейсике очень быстро привыкаешь объявлять все переменные в начале процедуры, это просто хороший тон.
Меня настораживает такое явление: Те люди, кто не стал программистами, Паскаль — забыли как страшный сон, а Бейсик — помнят и иногда используют для прикладных расчётов. Те же, кто стал программистами — просто знают несколько языков, и совсем неважно, с которого они начинали.
P.S. В январе Вы критиковали один из Basic-ов:
где из переходов только GOSUB/GOTO и из циклов только FOR — то это может быть слишком оторвано от современности.И чё? На нём же не проект писать, а чисто с алгоритмами экспериментировать.
Для чего-то более серьёзного — переходить на более актуальные языки.
+=
или возможности передать в функцию массив произвольной длины, чего не было в Паскале). Однако C вырос из бестипового B, и отпечатки этого, к сожалению, видны до сих пор.История явно движется по кругу, ибо мы вернулись к "бестиповым" языкам — а точнее — языкам с автовыводом типов переменных (щтоа?) и утиной типизацией
Не лукавьте. Расчеты были возможны, но количество служебного кода… Зашкалило бы. Поэтому разработка вряд ли была бы эффективной или надёжной.
Насчёт спирали — да, можно и так назвать. Это не столь принципиально.
Все остальные вещи, будь-то математика, строковые операции и т.д., выполнялись с помощью внешних библиотек. Возможность использовать библиотеки в В имелась, возможность форматировать вывод в нужном виде также была. Поэтому он вполне себе подходил для повседневных задач начала 1970-х.
(#sarcasm_mode_on) Но конечно же, если бы основная масса софта писалась на б-жественном Паскале, не было бы ни обновлений безопасности, ни глюков, ни зависаний.(#sarcasm_mode_off)
На самом деле — все указанные проблемы связаны с ростом спроса на софт и снижением качества софта в угоду скорости выпуска софта на рынок. Издержки массового производства. И использование «серебряной пилюли» в виде «единственно правильного ЯП, который точно принес бы счастье, но про него незаслуженно забыли» не решает эту проблему.
Язык операционных систем — С/С++, и пишем мы всё под операционные системы, ну или под железо, у которого вендорский код либо сишный, опять же, либо азм.
Язык для обучения в школе? Имея на плечах опыт кодинга на разных языках, вижу идеальными языки Го и Питон, т.к. на них проще всего уделять больше времени логике, нежели работе с синтаксисом языка.
Очевидный плюс Дельфы: непревзойдённый пока редактор графического интерфейса, да. И именно он меня привлекал когда-то. Но это не так страшно:)
Дизайнер форм Qt мог бы с этой непревзойденностью неслабо поспорить.
Потому что по сути его поддерживал только один вендор — Борланд.
Или хотите дальше копнуть?
Паскаль очень активно продвигался в 80-е: был Паскаль от Apple (и у них была первая объектная реализация — Borland уже копировал её идеи, хотя они все следовали за ранним C++), был от Microsoft (и очень неплохой, и совместимый с Borland по многим фичам — это редко упоминают, что они синхронизировались).
Но всё это сорвалось: он перестал быть привлекательным для тех, кто оказался тут ключевым. Я писал несколько раз его проблемы, как их вижу по результату обучения других — и мне кажется, что именно подходы типа «вам это не позволено» стали главными в его падении.
Ряд свойств паскалевского стиля был бы крайне полезен и сейчас — например, порядок слов в объявлениях. Но это надо ждать следующей волны языков…
Sound
, управляющая PC Speaker'ом. Если вам нужен именно он, то можете управлять им напрямую путём записи в системные порты. Для этого в XD Pascal, как и в Turbo Pascal, есть процедура OutP
.LLVM — да, а вот насчёт LEXX/YACC… Насколько я знаю (но это больше с чужих слов), как раз в неигрушечных компиляторах они, как правило, и не используются.
Они удобны — и мой небольшой опыт это подтверждает — 1) когда невысоки требования к обработке ошибок и вообще работе с невалидным исходным кодом, 2) когда язык только разрабатывается и нужно иметь возможность многократно и кардинально переделывать грамматику.
А при написании полноценного компилятора, с одной стороны, они не особо и помогают (если использовать LL-парсер — он легко пишется руками), а с другой создают лишние проблемы (отдельный язык, влекущий проблему сопряжения с ним; пляски когда надо сделать что-то хоть чуть-чуть нестандартное).
Плюс использования lexx/yacc в том что грамматика вашего языка будет LALR(1), а не ад типа Perl 5, который вообще undecidable.
There are a few things I (perhaps surprisingly) suggest should not be considerations… Easy parsing. It isn’t hard to write parsers with arbitrary lookahead. The looks of the language shouldn’t be compromised to save a few lines of code in the parser. Remember, you’ll spend a lot of time staring at the code. That comes first.
…Somewhat more controversial, I wouldn’t bother wasting time with lexer or parser generators… They’re a waste of time. Writing a lexer and parser is a tiny percentage of the job of writing a compiler.
Мой очень скромный опыт тоже подтверждает эту мысль. Написание LL-парсера вручную не является особой проблемой. Гораздо больше сил уходит на все остальное.
github.com/AntKrotov/oberon-07-compiler
Я уважаю ваш труд и считаю проект интересным, но:
Если повезёт, XD Pascal будет внедрён, наряду с BeRo Tiny Pascal, в лабораторный практикум по курсу конструирования компиляторов в МГТУ им. Н.Э. Баумана.Это очень плохая идея. Хорошее методическое пособие должно быть простым и прививать правильные подходы. Вы же развивали компилятор, исходя из личной любви к Паскалю, и сделали несколько очень спорных дизайн-решений, если не сказать костылей, из-за которых проект нельзя использовать как пример для подражания:
при каждом проходе заново повторяются все этапы компиляции, начиная с лексического разбора.
Вычисление любых выражений в XD Pascal строится так, что все промежуточные результаты имеют длину 32 бита и сохраняются в стеке. Для строк и множеств Паскаля этот подход неприемлем.
Для самых употребительных процедур, в том числе Read и Write, я сделал исключение и реализовал их нетипичными для грамматики языкаВозьмите лучше специально разработанный для этого минимальный язык\компилятор, типа ChibiCC.
Вы отчего-то не задались вопросом, как именно построен учебный процесс и как именно предполагается применять компилятор, и почему-то спешите предложить компилятор C вместо Паскаля и, кажется, даже без самокомпиляции. Далее, вы неизвестно почему видите недостаток в том, что «для самых употребительных процедур, в том числе
Read
и Write
, я сделал исключение и реализовал их нетипичными для грамматики языка». Однако эти процедуры в Паскале действительно нетипичны для грамматики (принимают любое количество любых аргументов) и действительно требуют реализации как особого случая, что я и сделал. Упрекать же за отсутствие поддержки множеств в любительском компиляторе, ей-богу, чрезмерно.В общем, извините, я не принимаю ваших доводов.
Однако эти процедуры в Паскале действительно нетипичны для грамматики (принимают любое количество любых аргументов)
Иэ это, кстати, очень уродующая язык штука. Я в своё время из-за этого на С и перешёл: пусть printf
и сложен и неудобен, но зато всё честно, а это важно для душевного здоровья программиста.
Read
и Write
, было бы не так тяжко. Но таких процедур оказываются десятки. Конечно, хотелось бы видеть грамматику Паскаля сразу достаточно гибкой для того, чтобы списки аргументов Read
и Write
укладывались в эту грамматику и не торчали бы неудобными исключениями.К сожалению, в языках вечно чего то не хватает, и создатели добавляют то атрибуты то трейты…
А когда эта магия добавлена, то язык начинает расплываться от спецификаций.
В этом случае вся статика летит к чертям.
Не обязательно. Просто решение получается сложным, даже монструозным.
Но это не значит, что так как сделано в Паскале — это единственный выход. Есть и другой: не иметь функций с переменным числом параметров ни в каком виде, а проблему удобного ввода-вывода решать иначе. Так сделано в Rust (ипользуются макросы), так сделано в современном C++ (используются темплейты). И решение из C# также может быть доведено до статического-типизированного (params IFormattable[] args
вместо params object[] args
), хотя оверхед из-за динамической диспатчеризации останется.
Если разрешить на уровне языка определение процедур с произвольным количеством формальных параметров ( да ещё и с произвольными типами аргументов ). В этом случае вся статика летит к чертям.Зачем же с абсолютно произвольными?
Objective Modula-2
Calling a Variadic Procedure
Index arguments and value terminating arguments are never supplied in the actual parameter
list of a variadic procedure call. The compiler automatically determines and
inserts these arguments into the procedure’s activation record.
Listing 16: variadic procedure calls omit index and value terminating arguments(* calling procedure Variadic from Listing 14 *) Variadic( (* counter omitted *) foo1, bar2, foo2, bar2 ); (* calling procedure Variadic from Listing 15 *) Variadic( foo1, bar1, foo2, bar2 (* -1 omitted *) );
Variadic Procedures with Counter Terminated Variadic Parameter Lists
The number of variadic parameters of a counter terminated variadic parameter list is
automatically passed as a hidden parameter immediately before the variadic list.
Listing 14: procedure with a counter terminated variadic parameter listPROCEDURE Variadic(v : VARIADIC OF (p1 : Bar; p2 : Baz)); BEGIN (* iterate over all variadic tuples by index *) FOR n OF CARDINAL := 0 to HIGH(v) DO DoSomethingWithBar(v[n].p1); DoSomethingWithBaz(v[n].p2); END; (* FOR *) END Variadic;
Variadic Procedures with Value Terminated Variadic Parameter Lists
A value terminated variadic parameter list is terminated by a given constant value.
Listing 15: procedure with a value terminated variadic parameter listPROCEDURE Variadic(v : VARIADIC [-1] OF (p1 : INT; p2 : Baz)); BEGIN (* v points to first variadic tuple *) WHILE v # NIL DO (* while there are tuples *) DoSomethingWithINT(v^.p1); DoSomethingWithBaz(v^.p2); v := NEXTV(v); (* next variadic tuple *) END; (* WHILE *) END Variadic;
В Modula-2 R10 ( в варианте M2Sharp) чуть менее наглядно:
( newVector и PrintList — разные функции; не стал исправлять, привёл 1 к 1, как в первоисточнике )
Variadic Parameters
The extended dialect supports the ARGLIST attribute in formal types and formal parameters. Parameters marked with the ARGLIST attribute may be passed a variable number of arguments.
PROCEDURE newVector ( values : ARGLIST OF REAL ) : Vector; VAR v1, v2, v3 : Vector; v1 := newVector(1.2, 3.4); (* two arguments *) v2 := newVector(1.2, 3.4, 5.6); (* three arguments *) v3 := newVector(1.2, 3.4, 5.6, 7.8); (* four arguments *)
Within the procedure or function, the argument count may be obtained using built-in function COUNT and the arguments are addressable using array subscript notation.
PROCEDURE PrintList ( values : ARGLIST OF REAL ); VAR index : CARDINAL; BEGIN FOR index := 0 TO COUNT(values)-1 DO WriteReal(values[index]); WriteLn END END PrintList;
Зачем же с абсолютно произвольными?
В начале обсуждения об этом написано.
Вот, например, в Активном Обероне есть встроенная процедура TRACE, которая принимает любое количество параметров любых типов, и распечатывает их в системный лог ).
TRACE( «Hello», 123, 1.5, NIL );
Она реализована в компиляторе, потому что на уровне языка такое не определишь.
Если все параметры одного типа, то и изобретать особо ничего не нужно — достаточно открытых массивов и массивов-литералов.
Например:
PROCEDURE P( CONST args: ARRAY [ * ] OF HUGEINT );
и вызов
P( [5, 78, 3758, 383489, 585959, 5785759 ] );
можно даже определить так:
PROCEDURE P( CONST args: ARRAY [ * ] );
И тогда процедура будет принимать массивы с любым типом элементов, но это не решит проблему разнородности типов аргументов, которая, к примеру, в Delphi решается с помощью массива вариантов.
Если повезёт, XD Pascal будет внедрён, наряду с BeRo Tiny Pascal, в лабораторный практикум по курсу конструирования компиляторов в МГТУ им. Н.Э. Баумана.
Риторический вопрос, почему российское образование всегда оторвано от реальной жизни…
Нет бы на «конструировании компиляторов» какую-нибудь кодогенерацию для реально работающих микроконтроллеров или плис рассмотреть, нет, нужно что-то обязательно архаичное и нежизнеспособное :) Специально чтобы каждый студент чувствовал, что нигде кроме пар ему это в жизни не пригодится.
Что касается образования, то курс вовсе не ограничивается упражнениями с простенькими компиляторами Паскаля. Вы же не станете утверждать, что нужно перестать преподавать черчение на бумаге, взятие интегралов на бумаге, расчёт прочности балок на бумаге и т.п. лишь потому, что это нечто «архаичное и нежизнеспособное»?
А почему не Котлин
Мне нравится, когда говорят о Си, как о виртуальной машине. Ибо действительно, если бы он однозначно компилировался в ассемблер, то не было возможности для UB. Получается, что на самом деле, он достаточно высокоуровневен, чтобы на нем нельзя было гарантировать последовательность исполнения и результат исполнения ЛЮБОЙ (не обязательно корректной!) программы на Си, и достаточно низкоуровневен, чтобы была возможность отстрелить себе руки и ноги из-за магии битиков.
Но вообще это мне не мешает любить этот язык, т.к. он реально прекрасен своей лаконичностью и своим распространением.
А, да, еще дичь в Си — это триграфы. Это к вопросу о скобочках и т.п., что иногда может тоже отсрелить обе ноги и обе руки.
Да и нужен ли тогда Паскаль?
Почему же? Пусть будет больше языков хороших и разных. С компиляцией в разные байткоды.
- Множества
- Строковые операции
- Процедурные переменные
- Процедуры
Break
,Continue
,Exit
- Открытые массивы
- Вызов функций как процедур
- Нетипизированные аргументы
- Однопроходная компиляция
- Быстрый лексический разбор
История с продолжением: собственный компилятор Паскаля для Windows с чистого листа