Энциклопедия языков программирования ru.progopedia.comhttp://ru.progopedia.comНовые статьи на ru.progopedia.comruSat, 20 Feb 2021 21:01:49 -0000 Версия Clarion C11 http://ru.progopedia.com/version/clarion-11/ <p>C11 Gold was released on October 8, 2018. </p> http://ru.progopedia.com/version/clarion-11/ Реализация Ада-Эльбрус http://ru.progopedia.com/implementation/mptr128/ <p>В Новосибирском филиале Института точной механики и вычислительной техники АН СССР в 1980х годах группа под руководством Запреева Сергея Степановича реализовала Систему программирования Ада-Эльбрус. Нетипичность разработки — в том, что, как правило, трансляторы разрабатываются для процессора, а в данном случае процессор адаптировался под язык программирования. Языков программирования, под которые можно было бы адаптировать архитектуру команд, было много, но, что касается языка Ада, в своей книге «Языки программирования. Концепции и принципы» (2010) Виталий Шахнович Кауфман пишет: </p> <p>«Первая [часть книги] посвящена основным абстракциям, используемым в современных ЯП. В качестве основного языка примеров здесь фигурирует ЯП <a href="/language/ada/">Ada</a>. Он удобен в этой роли потому, что в той или иной форме содержит ответы практически на все технологические проблемы. Другими словами, Ада служит примером «максимального» современного ЯП. «Минимальные» ЯП представлены языками Никлауса Вирта — это <a href="/language/modula/">Modula</a>-2 и <a href="/language/oberon/">Oberon</a>…» </p> <p>Инженеры МВК Эльбрус встречались на совещаниях Рабочей группы по реализации языков программирования (РГ-20, РГ РЯП) с разработчиками системы СП Ада-Эльбрус. Из протоколов заседаний: </p> <p>«С 22 по 24 апреля 1981 г. в Протвино Московской области состоялось совещание РГ РЯП … В докладе Б.А.Бабаяна были изложены основные принципы архитектуры и операционной системы МВК Эльбрус, при этом особое внимание было уделено тем аспектам, которые способствуют реализации трансляторов и систем программирования.» </p> <p>«С 21 по 26 мая 1984 г. в Львовском госуниверситете проходило 6-е заседание Рабочей группы по реализации языков программирования. … В.М.Пентковский (Москва) в докладе «Требования к среде программирования на языке Ада» сделал обзор требований к системе программирования на языке Ада. … В докладе В.Ю.Волконского и В.М.Пентковского (Москва) «Системная поддержка СП в МВК Эльбрус» В.Ю.Волконский сообщил о динамической и технологической поддержке систем программирования. Отмечалось, что многие функции динамической поддержки реализованы аппаратно, что обеспечивает эффективное исполнение программ. Использование стандартных файлов обеспечивает скорость работы компиляторов. Богатый системный инструментарий применим ко всем языкам высокого уровня. В МВК реализовано многоязыковое взаимодействие, широко используются стандартные пакеты и модули.» </p> <p>«3 – 6 октября 1988 года в Тбилиси проходила научная конференция «Язык программирования Ада». … Группой представителей НФ ИТМ и ВТ (Чеблаков Б.Г., Разгулин В.Б., Полюдов П.А.) были сделаны три доклада по системе программирования Ада-Эльбрус. … Рыбин С.И. рассказал о методике тестирования диагностики транслятора (вообще, и языка Ада в частности), разрабатываемой в МГУ под руководством Кауфмана В.Ш. Приведены данные по оценке качества и диагностики трех трансляторов Лада, Ада-Эльбрус и венгерская Ада ЕС; из них видно, что качество диагностики Ада-Эльбрус — лучшее из трёх систем.» </p> <p>Таким образом, адаптацию МВК Эльбрус под языки программирования можно понимать как аппаратную поддержку возможностей языка программирования Ада. ЯП Ада раскрывает все возможности аппаратуры, а другие ЯП — некоторое подмножество. </p> <p>Сергей Игоревич Рыбин пишет: </p> <p>«В начале 80‐х Ада привлекла всеобщее внимание среди русских специалистов и ученых в области компьютерных наук. В 1980г. в Москве была образованна русская группа SIGAda, которая активно действовала до конца 80‐х годов. … Были начаты проекты по реализации языка Ада для всех архитектур мейнфреймов, используемых в России, и некоторые из них достигли уровня работающих прототипов. … К сожалению, наши «реформы» конца 80‐х — начала 90‐х годов погубили в том числе и практически все отечественные Ада‐проекты, равно как и исследования в области информационных стандартов.» </p> <p>Лихая година (выражение президента Ельцина Б.Н., 1992г.) настала и для Ады в России, и для Эльбруса. </p> <p>Двадцать лет спустя на сайте МЦСТ не осталось и следа славного советского прошлого. Среди поддерживаемых языков программирования Ада официально не значится, но по косвенным признакам можно судить, что прошлые разработки не пропали, и в архитектуре продолжают существовать. Аппаратная поддержка языка программирования Ада переименована в так называемый «Защищённый режим Эльбрус». Вместо Ада-Эльбрус МЦСТ предоставляет транслятор lcc для языка <a href="/language/c/">C</a> со специальным ключом -mptr128. -mptr играет роль, похожую на -m в GCC для x86/64: -m32 для 32-разрядного режима, -m64 для 64-разрядного. Так же и в Эльбрус: -mptr32 — 32-разрядный режим, -mptr64 — 64-разрядный режим, а -mptr128 — как бы продолжая эту линию, 128-разрядный режим, он же режим аппаратной поддержки языка Ада, он же «Защищённый режим Эльбрус». По ключевым словам «Эльбрус mptr128» можно искать информацию об этом режиме. </p> <p>Кауфман В.Ш. описывает ЯП <a href="/language/ada/">Ada</a> как «максимальный», а ЯП <a href="/language/modula/">Modula</a>-2 и <a href="/language/oberon/">Oberon</a> — «минимальные». Ему повезло во время своей работы над диагностикой не видеть такого пробивающего дно языка программирования, как <a href="/language/c/">C</a>. Хотя C и <a href="/language/pascal/">Pascal</a> появились примерно в одно время, на рубеже 1960х-1970х, и у СССР было время 20 лет до развала, чтобы отзеркалить оба языка в ГОСТ, на Фортран есть ГОСТ, на Паскаль есть ГОСТ, на язык Ада есть ГОСТ, а на язык Си — не было и нет ГОСТа. В СССР товары массового потребления были обязаны соответствовать ГОСТу, и отсутствие ГОСТа на язык программирования Си в некотором роде служило запретом на широкое применение. Система флагов транслятора идеологически устроена так, будто режим аппаратной поддержки языка Ада (также известный как Защищённый режим Эльбрус) является третьим в линейке после 32-разрядного и 64-разрядного режимов, но это уловка (возможно, сделанная не сознательно). То обстоятельство, что Си — более минимальный, чем то, что считалось минимальным в СССР, безусловно требует «подтянуть» входной язык до некоторого уровня, без которого невозможна работа в этом режиме. Проблема в том, что язык Си, подтянутый к языку Ада, перестаёт быть прежним языком Си, и становится неким новым, Эльбрусобезопасным Си или Адаистичным Си. Евангелисты МЦСТ пользуются этой уловкой, чтобы лучше продавать Эльбрусы. </p> <p>Если потенциальный покупатель исходит из того мнения, что lcc — транслятор языков Си и C++, -mptr128 — всего лишь флаг транслятора, а защищённый режим Эльбрус — просто такой режим работы, то можно впасть в иллюзию, что вот готовые программы, вот готовый процессор, вот транслятор, и всё это будет работать в сборе. Суровая правда, что при переходе между -mptr64 и -mptr128 становится совсем другой Си, под которым без переработки не собирается практически ни одна существующая программа, помешала бы продажам Эльбрус, и это объясняет, почему лица, аффилированные с МЦСТ, выстраивают пропаганду именно таким образом. Таким образом, информацию о СП Ада-Эльбрус и о том, как особенности языков программирования, в первую очередь, языка программирования Ада, отразились в аппаратном устройстве архитектуры Эльбрус, приходится почерпывать из источников, не упоминающих о языке Ада. </p> <p>Немного суровой правды просачивается через доклад, сделанный в декабре 2017го года. Например, оттуда: </p> <p>«Библиотеки libmodbusregshelper и libmodbussrv были реализованы на языке Си (переписаны с языка C++ на C)», — то есть, C++ не поддерживается. </p> <p>«Графические библиотеки на языке С: mesa, x86emul, rfb (подготовлены к переносу в защищенный режим)», — то есть, с графическими приложениями пока довольно туговато. Согласно докладу графическая часть была вынесена на отдельный ПК под управлением Windows 10. </p> <p>«Был добавлен изначально отсутствующий функционал обработки исключений математических функций с помощью функции matherr. Функция-обработчик может быть определена пользователем для перехвата исключений (аналог try/catch в C++)», — в языке Ада исключения пораньше были лет на 10, чем в C++, и стандарт на язык Ада с самого начала определял исключительные ситуации вроде Numeric_Error, в отличие от не к месту упомянутого C++, где такие ситуации в общем случае не обрабатываются, а исключения есть только пользовательские, явно сделанные throw. Например, Access Violation в Windows и SIGSEGV проецируются в языке Ада на Storage_Error, и любые написанные за все 30 лет программы на языке Ада написаны со знанием этого обстоятельства, а matherr — это библиотечный вызов, который есть не на любой ОС и не в любой библиотеке времени исполнения под выбранную ОС. Учитывая, что matherr где-то всё же есть, это ещё не начало Эльбрусобезопасного Си, но дальше — больше. </p> <p>В книге «Микропроцессоры и вычислительные комплексы семейства «Эльбрус»» можно прочитать: </p> <p>«Архитектура «Эльбрус» защищает контекст программного модуля, образованный объектами, которые допускается в нём использовать согласно правилам языка программирования. Это делается путём организации доступа к низкоуровневому представлению объекта в памяти или «регистрах» через «проходную» его дескриптора — служебного слова, содержащего ссылку и информацию об объекте, соответствующую его типу. Доступ возможен только через дескриптор. Аппаратные операции создания и использования дескрипторов специализированы таким образом, что не оставляют возможности непосредственного воздействия на объект.» </p> <p>«…согласно правилам языка программирования…», — очень интересно, а это правила какого же языка программирования имеются в виду? В языке Ада можно в публичной части пакета написать &#8220;type Cursor is private;&#8221;, и посторонние модули семантически теряют право посмотреть внутрь типа Cursor, но могут размещать переменные этого типа на стеке, класть в структуры и массивы. Если поддержать этот запрет в аппаратуре, для нормальных программ ничего не меняется. А в языке Си любой typedef «показывает» всему миру содержимое struct, и как понять, какому коду можно обращаться внутрь, а какому — нельзя? Как понять, что такое модуль в языке Си? Единица трансляции (.o) — это уже модуль? Да нет, есть программы и библиотеки, которые рассчитывают на возможность лезть внутрь структуры из разных единиц трансляции, и это как бы модуль, разрешающий другим модулям (в языке Ада есть два способа сделать вложение, а вложенные единицы имеют доступ к приватной части объемлющих пакетов) доступ. Статическая или динамическая библиотека (.so) — это уже модуль? Наверное, но чтобы это понять, требуется хакнуть язык. В обычном языке Си есть некие приватные инклуды и публичные. В обычном языке Си эти инклуды не отличимы. Соответственно, транслятор Адаистичного Си, чтобы протащить эту аппаратную возможность в язык Си, например, должен научиться отличать приватные инклуды от публичных. Например, транслятору Адаистичного Си нужно как-то подсказать: вот в этой директории лежат приватные инклуды, а в этой директории лежат публичные инклуды. И транслятор Адаистичного Си, когда читает приватные инклуды, должен давать права доступа к структурам в них только одному модулю, а когда читает публичные инклуды, должен давать права неограниченные. А во многих реальных библиотеках те и другие инклуды лежат вперемешку, и только скрипты установки избирательно одни файлы устанавливают, а другие — нет. Соответственно, надо поменять систему сборки, чтобы сообщать транслятору, какой заголовочный файл — приватный, а какой — публичный. И, в отличие от языка Ада, по-видимому, непрозрачными могут быть только указатели. Либо Адаистичный Си как-то так синтаксически модифицирован, чтоб можно было объявить структуру, её содержимое все видят, но аппаратура и транслятор запрещают обращения внутрь неё. Класть в другие структуры можно, а читать/писать содержимое — только через соответствующий модуль. </p> <p>«Устройство преобразования адресных типов оперирует адресными словами. Результат выполнения — также адресное слово, например дескриптор на подмассив исходного массива, метка процедуры и др.», — тоже интересная вещь. Откуда в языке Ада подмассивы, понятно. Там есть недоопределённые (indefinite) типы данных, и самый простой String — как раз такой массив, и если брать средствами языка подстроку, то транслятор по возможности не копирует целиком подстроку, а манипулирует метаданными так, чтобы получить ссылку на подстроку. Это работает и для любых других массивов. В терминах других языков программирования это срезы (slice, span), жирные указатели с длиной. На Эльбрусе указатели тоже получаются жирными, но обычные программы на языке Си совершенно не могут об этом знать! Например, это проявляется так: программа на языке Ада передаёт доступ к массиву на запись другой подпрограмме, и не ко всему массиву, а к подмассиву. Подпрограмма не сможет выйти за рамки подмассива. Если же программа на обычном языке Си пытается делать то же самое, то в общепринятом стиле это делается при помощи передачи двух аргументов: указателя на начало массива и длины. Адресной арифметикой из массива берётся указатель в середину массива (в начало подмассива), затем вычисляется длина подмассива, и программа передаёт два параметра. Поскольку обычные программы ничего не знают про Эльбрус, именно так они и будут написаны. А на Эльбрусе указатели (дескрипторы) — жирные и содержат копию информации о длине массива, но программа на языке Си об этом не знает и будет ориентироваться на длину, переданную числом. Тут есть два отличия от языка Ада. Во-первых, в языке Си допустимо получать при адресной арифметике невалидные указатели. Требуется только, чтоб они были валидные при попытке разыменовать их. То есть, если в программе ошибка, указатель на начало массива может быть невалидным, и в программе на Ада даже вызвать подпрограмму не получилось бы. Кроме того, вычисление длины подмассива — это операция с точки зрения транслятора чисто целочисленная. В результате может получиться любое число, даже такое, которое соответствует выходу за границу объемлющего массива. В языке Ада эта ошибка была бы перехвачена тоже до вызова подпрограммы. В языке Си, так получается, что вызов удался бы. На Эльбрусе подпрограмма получает доступ на запись ко всему массиву, как он был выделен изначально, и имеет возможность что-нибудь перезаписать за границами подмассива, если это всё ещё в границах массива. А если не в границах, то обнаруживается это только в самый последний момент, при попытке обращения. Чтобы с этим бороться, в Адаистичном Си можно ввести концепцию срезов из языка Ада, и таким образом дать возможность манипулировать жирными указателями-дескрипторами. Это получается другой Си, Адаистичный Си, Эльбрусобезопасный Си, под который практически нет программ, в то время, как на языке Ада программ и библиотек явно поболее будет, чем «почти ничего». Программы на Аде расчитаны на проверки, которые вставляет транслятор, а на Эльбрусе часть этих проверок просто переносится в аппаратуру, без изменений исходного кода. Программы на Си придётся «портировать» (а если начистоту — переписывать на другой язык программирования, которым, если уж дело доходит до переписывания, могла бы быть Ада, но в МЦСТ сделали выбор в пользу Адаистичного Си, и скрывать, что это другой язык программирования, под который нет программ и библиотек). </p> <p>«Возникшие проблемы защиты данных при переиспользовании памяти эффективно разрешены снабжением указателей на память в стеке специальными тегами и введением в указатели и дескрипторы уровня (номера) процедуры в стеке процедур. Этот номер позволяет определить принадлежность указателя к той или иной процедуре и тем самым решить проблему защиты данных», — в языке Ада нельзя без обхода безопасности передать access за пределы области видимости, и вложенность как раз нумеруется. Для программ на языке Си это, конечно, новшество неожиданное. </p> <p>Но ещё большие неожиданности начинаются при попытке выделить память: «Операционная система должна взять на себя реализацию части функций управления памятью, которые традиционно включались в библиотеки динамической поддержки реализации языков. В первую очередь это касается функций выделения и освобождения памяти под объекты, таких как malloc, realloc, calloc, free…», и вот, почему: написано где-нибудь в коде «X<em> Y = (X</em>) malloc (sizeof (X) * Z);», и с точки зрения обычного Си «sizeof (X) * Z» — это просто число, а в режиме аппаратной поддержки языка Ада это не может быть просто числом. Если программа выделяет память таким образом, то надо полагать, впоследствии программа будет считать что на этом месте возник массив длиной Z из структур типа X. А это значит, надо после приведения типа от (void *) в (X * ) получить жирный указатель с информацией о том, сколько элементов есть в массиве, и какого типа этот массив, во внутреннем тэге, даже разметить выделенную память. Это уже как минимум два отклонения от Си: результат такого malloc — не void<em>, void</em> «съедается», а сразу возвращается X * , и аргумент malloc — это уже не просто число, а дерево AST, которое проверяется по шаблону, и при совпадении шаблона из этого дерева убирается умножение, sizeof — уже не статическая функция, возвращающая число, а нечто, что будет записано во внутренний тег полученного дескриптора. Это уже не Си, а угадайка какая-то, это уже Адаистичный Си. Не все выражения malloc удастся угадать, в отличие от сильно типизированного языка Ада. Не угаданные случаи придётся переписывать. Рано или поздно в большой замысловатой программе придётся дотягивать семантику Си до Ады, прибегая к расширениям языка и нестандартным (с точки зрения Си) функциям. В то время, как на языке Ада можно было бы оставаться в пределах стандарта. </p> <p>Семантические отличия также касаются обработки переполнения целых чисел. Обычно числа переполняются, и программы на Си пишутся в оптимистичном расчёте, что там, где не надо, числа не переполнятся. А там, где надо, — там переполнятся с прокручиванием через границу (два миллиарда умножить на три равно примерно минус два миллиарда). С точки зрения исходных кодов это неотличимо. В режиме аппаратной поддержки языка программирования Ада транслятор lcc навешивает контроль на все целые числа, но это становится другая крайность. Тогда, наоборот, проблемы возникают в программах, ожидавших, что будет прокрутка. Такие программы придётся переписать на Адаистичный Си. Чтобы была прокрутка, потребуется прибегнуть к нестандартным расширениям языка Си, позволяющим указать, где можно допускать прокрутку, а где — нельзя. В языке Ада этим целям служат модульные типы вроде Unsigned_32, и программы на языке Ада написаны со знанием о существовании этих типов. А если писать новые программы, то информацию о том, как правильно писать на Аде, можно почерпнуть из общедоступного стандарта на язык Ада, а не из труднодоступной документации на Эльбрусобезопасный Си. </p> <p>Лица, аффилированные с МЦСТ, настаивают на том, что режим поддержки языка Ада — уникален, но это не совсем не так. Кроме Эльбруса, существует достаточно давно CHERI. В Эльбрусе VLIW, в CHERI — RISC на базе MIPS. Давно продаётся. Есть эмулятор на базе QEMU. Имеет своё архитектурное своеобразие: на Эльбрусе есть и дескрипторы модулей, на CHERI есть «способности» (capabilities), которые аппаратно запрещено подделывать. Из дескриптора, содержащего некие разрешённые способности, можно производить дескриптор с меньшим наобором способностей, для этого, опять же, есть некие расширения языка Си или нестандартные функции. Для работы со срезами массивов — нестандартные расширения и/или функции. Причём, если работы над CHERI и над Эльбрусом не координировались, то можно ожидать, что результаты, достигнутые на CHERI, не подойдут к Эльбрусу и наоборот. Везде разные функции, разные расширения языка Си. </p> <p>Повышением безопасности унаследованного кода на языке Си занимались и для обычных процессоров, и выдающимся проектом является CCured. Так же, как и на Эльбрусе, и на CHERI, приходится расширять язык программирования, и это ещё один, третий, набор расширений, которые требуется применять в достаточно сложных программах. Доклад «CCured in the Real World» упоминает об успешном переписывании на CCured таких программ, как ftpd, OpenSSL, OpenSSH, sendmail, bind. Доклад датируется 2003м годом. Когда код на языке Си называется унаследованным, это подразумевает, нового кода на этих языках не должно производиться. </p> <p>Но суровая проза жизни — в том, что продолжает производиться. Суровая проза жизни — в том, что безопасность оказалась категорически не востребована, с какой стороны ни посмотреть. На безопасном языке программирования Ада пишут как раньше мало, так и сейчас. Безопасные версии программ, перенесённые на CCured, не вошли дистрибутивы Linux и BSD. Мейнтейнеры Linux бесстыдно продолжают класть в свои дистрибутивы версии программ с критическими уязвимостями, журналисты бесстыдно продолжают называть напрочь проигнорировавший стремление к безопасному коду Linux безопасной операционной системой потому что миллион пытливых глаз. Или макОС, потому что «это же Макинтош». Или «потому что консоль». И всё идёт своим чередом. Как и язык Ада, CCured оказался не востребован, но в отличие от языка Ада, совсем заброшен. Не стал хитом продаж CHERI с киллер-фичей защищённого режима CHERI. Пока срабатывает оруэлловский метод «решения» проблем с безопасностью, ситуация не улучшится. </p> <p>Как если бы было мало проблем с отнюдь не помогающими журналистами, указанные группы разработчиков, занимающиеся одной и той же проблемой, игнорируют достижения друг друга, не ссылаются друг на друга, постоянно начинают с нуля, поодиночке не достигают весомых результатов и забрасывают. Например, в материалах CCured было бы логично ожидать, что этот инструмент — для унаследованного кода, а новый код нужно писать на языке Ада, но такой рекомендации нет. Тоже следовало бы писать лицам, аффилированным с МЦСТ, тем более, что это именно тот фундамент, на котором стоит Эльбрус. Безумие — рекомендовать писать новый код на Си, пусть даже с аппаратной защитой. Это только для повышения безопасности старого кода! Нельзя новый. Почему в МЦСТ не учитывают опыт CHERI, понять ещё возможно, ведь внезапно выяснится, что Эльбрус не уникален, и у конкурентов не очень-то выстрелило. Но всё же как-то выстрелило, и если игнорировать опыт Ada, CCured, CHERI, а сейчас игнорируется вообще всё, что только можно, то всё случается как в первый раз, или как у золотых рыбок память три секунды, или как в анекдоте про склероз, каждый день новости. Правда ли, что финансово обусловленное невежество лиц, аффилированных с МЦСТ, действительно выгоднее, чем «разглядеть» попытки других групп и воспользоваться плодами их деятельности, сорганизоваться медийно, большой вопрос. Но точно не выгодно оставаться в неведении лицам, не аффилированным с МЦСТ. </p> <p>Бочка дёгтя про защищённый режим Эльбрус: -mptr128 значит квадрослово, 128 бит. В эти 128 бит должны уместиться: базовый виртуальный адрес, размер, текущий указатель, уровень процедуры в стеке, внутренний тег. То есть, защищённый режим Эльбрус — это обязательно 32-разрядный режим. </p> <p>Подводя итоги, можно составить список рекомендаций для разработчиков: </p> <p>Пишите на Аде. Вам не нужен Эльбрус за 200т.р., чтобы проверить переполнение буфера или целочисленное переполнение, это сделает Ада на любом бросовом x86/x64 процессоре. Не переполнится буфер, не затрётся адрес возврата, не перейдёт управление полученным из Сети данным, — для всего этого вам не нужен Intel MPX, Intel SGX, Эльбрус mptr128 или очередная припарка, вокруг которой делается ажиотаж. Писать код на Си — значит, создавать проблему, быть проблемой. И все эти iMPX — попытки героически полумерами решить проблему. </p> <p>Чисто — не там, где убирают, а там, где не мусорят. Не будьте проблемой, не создавайте проблемы, не мусорите, не пишите на Си. Просто пишите на Аде. И будет чисто. Безопасно. Всегда. Везде. На Эльбрусе доступна трансляция сквозь язык Си средствами <a href="/implementation/adamagic/">AdaMagic</a>. Без аппаратной поддержки, зато можно писать под 64 бита безопасно на Эльбрусе. Со временем можно ожидать, что «угадайка» внутри lcc научится хорошо понимать промежуточный код AdaMagic и проецировать на соответствующие возможности аппаратуры, это был бы самый простой способ возобновить поддержку языка Ада, если СП Ада-Эльбрус утеряна. Так что можно безопасно писать на Аде впрок, а даже если этот «впрок» никак не наступает, всё равно все выигрывают. </p> <p>Если вы чувствуете, что вас «зацепили» защищённым режимом Эльбрус, но Эльбруса у вас нет и, может быть, никогда и не будет, а раз нет Эльбруса, то и о безопасности можно не думать, с таким наваждением нужно бороться рациональными доводами. Если безопасность — это так здорово, а есть какой-то код на Си, и есть процессора, сильно отличающиеся от Эльбрус по своему устройству, на которых работает программа, то нужно сделать что? Правильно, для начала взять хотя бы CCured. И обезопасить им программу, раз это настолько важно. Лучше, конечно, на Аду переписать, но хотя бы CCured. </p> <p>mptr128 на Эльбрусе, CCured на остальных платформах, а новый код — так вообще на Аде, да и старый понемногу переписывать на Аду — это самая последовательная линия поведения человека, действительно заботящегося о безопасности. mptr128 только на Эльбрусе, а про CCured и Аду вообще не думать — это не последовательная линия поведения. Это линия поведения человека, которому что-то впродали. </p> http://ru.progopedia.com/implementation/mptr128/ Язык программирования Sparkel http://ru.progopedia.com/language/sparkel/ <p>Sparkel — это язык программирования зелёных потоков, созданный по подобию языка <a href="/dialect/spark/">SPARK</a>, подмножества языка <a href="/language/ada/">Ada</a>. По сравнению с аналогичными системами (<a href="/language/erlang/">Erlang</a>, <a href="/language/go/">Go</a>, <a href="/language/limbo/">Limbo</a>), имеет большую степень параллельности. Так, в упомянутых системах потоки создаются не средствами операционной системы, а средствами среды времени исполнения, предоставляемой языком программирования, и таких потоков может быть гораздо больше, чем потоков операционной системы, однако создавать зелёные потоки требуется явно. Например, в языке <a href="/language/go/">Go</a> нужно явно написать ключевое слово &#8220;go&#8221; перед вызовом процедуры. По замыслу создателей Sparkel программа должна иметь возможность быть рассечена в любом месте по мере необходимости. Любое выражение, такое как «F(X) + G(Y)», может быть вычислено параллельно, освобождая разработчика от необходимости вручную разбивать вычислительный процесс. Активные потоки конкурируют за работу. Также по сравнению с императивным <a href="/dialect/spark/">SPARK</a> изменена семантика циклов. Циклы тоже могут быть автоматически разбиты на параллельно обрабатывающиеся задания, но если это невозможно и нужно строго соблюдать последовательность, это указывается новыми ключевыми словами. </p> <p>Обратной стороной язвляется, например, отказ от исключений. В обычной императивном языке исключение прерывает исполнение программы в определённом месте, а в Sparkel элементы синтаксиса могут обрабатываться параллельно с разной скоростью, и концепция исключений не вписывается в эту модель исполнения. Также в Sparkel нет явных указателей. Вместо них есть «распахиваемые записи» с одиночными ссылками. Распахиваемая запись — это запись, наличие которой необязательно, то есть, значение таких переменных может отсутствовать, и место под поля записи в этом случае не выделено. Если запись распахнуть, семантически она становится аналогичной обычной записи, а на нижнем уровне выделяется память и присваивается указатель. Счётчика ссылок нет, и новую ссылку на ту же структуру нельзя создать. Можно только скопировать значение, получив полностью независимую реплику. Однако, чтобы всё же воспользоваться знанием о том, что на нижнем уровне используются указатели, вводится новая операция обмена двух переменных. Таким образом, язык остаётся удобным для параллельной обработки, но и острые углы срезаны. </p> <p>Также от других аналогов Sparkel выгодно отличается тем, что его трансляторы и виртуальная машина реализована на языке <a href="/language/ada/">Ada</a>, а не на устаревшем <a href="/language/c/">C</a>. </p> <p>От <a href="/language/cyclone/">Cyclone</a> язык позаимствовал концепцию регионов. На нижнем уровне используется сегментированная модель памяти, а в каждом сегменте — линейная адресация. Как и <a href="/dialect/spark/">SPARK</a>, Sparkel — строго типизированный язык, поэтому у всех типов данных известно их низкоуровневое представление. Концепция регионов используется для установления ссылок между сегментами. </p> <p>Так же, как и <a href="/dialect/spark/">SPARK</a>, Sparkel поддерживает обобщённое программирование, однако явно специализировать пакеты не требуется. Вместо этого обобщённые пакеты транслируются один раз в общий программный код, поведение которого управляется дескрипторами типов. </p> <p>Текущая реализация компилятора производит байт-код. Далее этот байт-код может либо непосредственно исполняться на виртуальной машине PSVM, либо для повышения производительности быть скомпилирован через LLVM в машинные коды и загружен в таком виде в виртуальную машину. Виртуальная машина в этом случае выполняет роль планировщика и средства взаимодействия с внешним миром. </p> <p>Аналогично тому, как Sparkel был сделан по подобию <a href="/dialect/spark/">SPARK</a>, в лаборатории SofCheck&amp;AdaCore независимыми командами были сделаны Parython (PARallel + <a href="/language/python/">pYTHON</a>) и Javallel (<a href="/language/java/">Java</a> + paraLLEL). На основе этих трёх языков, собрав удачные решения, был создан новый язык программирования ParaSail (Parallel Specification and Implementation Language), который сейчас продвигается как основной в этой четвёрке. У всех четырёх языков общая виртуальная машина и некоторые другие средства разработки. Трансляторы для всех 4х, как правило, поставляются в одном архиве. Поэтому можно читать блог о ParaSail, скачивать средства разработки с сайта ParaSail, и многое из этого применимо к Sparkel в том числе. На сайте ParaSail средства разработки, например, новее, чем на сайте Sparkel. </p> http://ru.progopedia.com/language/sparkel/ Реализация A2JS http://ru.progopedia.com/implementation/a2js/ <p>Транслятор Ada в JavaScript является частью проекта «Матрёшка». Поддерживается крайне небольшое подмножество языка Ada. </p> http://ru.progopedia.com/implementation/a2js/ Реализация ObjectAda http://ru.progopedia.com/implementation/objectada/ <p>Aonix ObjectAda — реализация <a href="/dialect/ada95/">Ada 95</a> на основе технологии <a href="/implementation/adamagic/">AdaMagic</a>. Как и у других поставщиков компиляторов Ada, у ObjectAda конкурировала на рынке инструментов разработки для встраиваемых систем, и у ObjectAda имелись специализированные версии для микроконтроллёров, но при этом ObjectAda примечательна как среда разработки, наиболее близкая к другим средам разработки обычных программ с графическим интерфейсом (Desktop GUI), таким, как Delphi и Visual Studio, и имевшая успех на этом рынке. </p> <p>В разное время программным продуктом владели Alsys, Aonix, Atego. Текущий владелец — PTC. </p> <p>Однажды была выпущена бесплатная, не требующая ключа, но ограниченная по количеству строк, версия ObjectAda for Windows, Special Edition, v7.2. В Сети ещё можно найти эту версию по названию архива oa71sped.zip . </p> http://ru.progopedia.com/implementation/objectada/ Реализация AdaMagic http://ru.progopedia.com/implementation/adamagic/ <p>AdaMagic — это компилятор <a href="/dialect/ada95/">Ada 95</a>, разработанный в Intermetrics под руководством С. Такера Тефта (S. Tucker Taft). Intermetrics — это одна из четырёх компаний, участвовавших в конкурсе на первый язык Ada. В том конкурсе победил язык под кодовым названием Green, и стал <a href="/dialect/ada83/">Ada 83</a>. Кодовое имя языка, предложенного Intermetrics, было Red. Ada 95 сформирована под большим влиянием Red. Подход ООП, не вошедший в первую основную версию стандарта Ada, попал, таким образом, во вторую. </p> <p>Технология AdaMagic работает в трёх режимах, лицензируется производителям, а те, в свою очередь, дорабатывают на этой основе собственный компилятор. </p> <ol> <li> Трансляция в промежуточное представление. </li> <li> Трансляция в C или C++. </li> <li> Трансляция в байт-код Java (AppletMagic). </li> </ol> <p>Например, один из компиляторов на базе AdaMagic, <a href="/implementation/objectada/">ObjectAda</a>, имел поддержку первого и третьего режимов. В этом компиляторе промежуточное представление докомпилируется до машинных кодов, например, для x86. AppletMagic также распространялся бесплатно без посредников. </p> <p>AppletMagic поддерживает стандарт <a href="/dialect/ada95/">Ada 95</a>, в то время, как GNAT поддерживает стандарт <a href="/dialect/ada-2012/">Ada 2012</a> и поддерживает трансляцию и в байт-код Java, и в .NET. Таким образом, из всех этих режимов не потерял актуальности только второй. </p> <p>Intermetrics несколько раз сменил имя, сначала на AverStar, затем на SofCheck, затем SofCheck слился с AdaCore, но после этого слияния на сайте AdaCore не появилось никаких следов владения технологией AdaMagic. </p> <p>На данный момент компилятор Ada в C/C++ можно скачать в составе MapuSoft AppCOE. Соответствующий компонент называется Ada-C/C++ Changer®. Имеются версии компилятора IDE для Windows и Linux, а в качестве целевых платформ могут потенциально выступать любые, для которых есть компилятор <a href="/language/c-plus-plus/">C++</a>. MapuSoft специализируется на переносе программ с одной OS на другую, и в составе их инструментария есть достаточно богатый выбор поддерживаемых целевых операционных систем: Android®, Linux®, LynxOS®, LynxOS-SE®, LynxOS-178®, micro-ITRON®, MQX®, NetBSD®, Nucleus®, QNX® Neutrino® RTOS, RT Linux®, Solaris®, ThreadX®, T-Kernel®, UNIX®, VxWorks® 6x/5x, Windows ® XP/Vista/7/CE, microC/OS-III® — для этих целевых платформ MapuSoft AppCOE поддерживает работу «из коробки» при помощи так называемого OS Abstractor. Для других целевых платформ может потребоваться переносить системную библиотеку или отключать возможности языка Ada. </p> http://ru.progopedia.com/implementation/adamagic/ Диалект Ada 2012 http://ru.progopedia.com/dialect/ada-2012/ <p>15 декабря 2012 года был опубликован новый стандарт языка Ада. </p> <p>Большинство изменений так или иначе связано со стремлением непосредственно в языке обеспечить поддержку методу «Контрактного программирования». Добавлены пред- и пост-условия к подпрограммам, инварианты приватных типов и предикаты для подтипов. Для эффективного использования этих конструкций были добавлены новые типы выражений и расширены существующие. Получила дальнейшее развитие стандартная библиотека. Были введены контейнеры ограниченного размера, появились удобные механизмы итерации по контейнеру и доступу к содержащимся в них элементам. Другие изменения коснулись использования неполных описаний типов, режимов параметров функций, указания пула памяти при создании объекта и прочее. </p> http://ru.progopedia.com/dialect/ada-2012/ Диалект SPARK http://ru.progopedia.com/dialect/spark/ <p>SPARK — это формально определённый язык программирования, основанный на языке программирования Ада и предназначенный для разработки программного обеспечения высокой целостности (high integrity) для областей применения, где предсказуемость и высоконадёжное функционирование — ключевые требования. Для собственно компиляции используется компилятор языка Ada, а инструментарий SPARK предназначен для верификации поведения программы. </p> <p>Не все возможности языка Ada позволяют верифицировать программы, их использущие, поэтому SPARK — в некотором смысле подмножество языка Ада. С другой стороны, SPARK требует документировать поведение программы контрактами, и эти элементы тем или иным способом вносятся в текст программы. </p> <p>Первое поколение этого языка программирования представлено 3мя версиями: SPARK 83, SPARK 95 и SPARK 2005, основанные на Ada 83, Ada 95 и Ada 2005, соответственно. И отдельно идёт развитие второго поколения, начало которому положил SPARK 2014 на базе Ada 2012. </p> <p>Принципиальное различие — в том, что в первом поколении контракты записывались в специальным образом оформленных комментариях языка Ada (минус минус решётка), а во втором поколении для их записи используются аспекты, прагмы и другие синтаксические элементы языка Ада. SPARK 2014 и Ada 2012 связаны более тесно. Так, компилятор языка Ada 2012 в режиме проверки утверждений (assertions) добавляет проверки пре- и постусловий методов, а верификатор языка SPARK 2014 — проверяет корректность на этапе верификации. Оборотной стороной является невозможность использования верификаторов SPARK 2014 с компиляторами языка Ada, не поддерживающими версию Ada 2012, то есть, практически со всеми, кроме GNAT. </p> <p>Верификаторы для обоих поколений SPARK можно скачать на сайте AdaCore Libre, в зависимости от версии GNAT GPL. Самая новая версия верификатора первого поколения (Examiner) — в GNAT 2012 GPL, более новые — это второе поколение (GNATprove). </p> http://ru.progopedia.com/dialect/spark/ Пример: Факториал - SQL (581) http://ru.progopedia.com/example/factorial/581/ <pre><code>declare @max_n tinyint = 20 ;with t as ( select 1 as n, convert(bigint,1) as f union all select n+1, f*(n+1) from t where n &lt; @max_n ) select convert(varchar,n)+&#39;! = &#39;+convert(varchar(32),f)+&#39;, &#39; from t as [text] FOR XML PATH (&#39;&#39;) </code></pre> http://ru.progopedia.com/example/factorial/581/ Пример: Факториал - Clarion (580) http://ru.progopedia.com/example/factorial/580/ <pre><code> PROGRAM OMIT(&#39;***&#39;) * User: Shur * Date: 29.02.2016 * Time: 23:49 *** MAP include(&#39;i64.inc&#39;) Factorial PROCEDURE(SHORT,*INT64 a) ShowINT64 PROCEDURE(*INT64 a),STRING END a LIKE(INT64) b LIKE(INT64) c LIKE(INT64) str1 CSTRING(32000) str2 CSTRING(32000) CODE Factorial(20,a) message(str1,&#39;Factorial&#39;,,,,10b) Factorial PROCEDURE(SHORT n,*INT64 a) b like(INT64) CODE if n = 1 then i64Assign(a,1) str1 = &#39;1! = 1&#39; RETURN . i64Assign(b,n) Factorial(n-1,a) if a.lo = 0 and a.hi = 0 RETURN . i64Mult(a,b,c) if i64Sign(c) = -1 i64Assign(a,0) RETURN . a :=: c str1 = str1 &amp; &#39;|&#39; &amp; n &amp; &#39;! = &#39; &amp; ShowINT64(a) ShowINT64 PROCEDURE(a) d DECIMAL(30,0) CODE i64ToDecimal(d,a) return(d) </code></pre> http://ru.progopedia.com/example/factorial/580/ Пример: Числа Фибоначчи - Clarion (579) http://ru.progopedia.com/example/fibonacci/579/ <pre><code> PROGRAM OMIT(&#39;***&#39;) * User: Shur * Date: 29.02.2016 * Time: 21:18 *** MAP include(&#39;i64.inc&#39;) ShowINT64 PROCEDURE(*INT64 a),STRING END a LIKE(INT64) b LIKE(INT64) c LIKE(INT64) str1 CSTRING(32000) str2 CSTRING(32000) CODE a.lo = 1 str1 = &#39;1=&#39; &amp; ShowINT64(a) b.lo = 1 str1 = str1 &amp; &#39;|2=&#39; &amp; ShowINT64(b) str2 =&#39;1, 1&#39; loop i# = 3 to 200 i64Add(a,b,c) if i64Sign(c) = -1 break end a :=: b ! deep assignment uses for structures b = c ! usual assignment can be also used str1 = str1 &amp; &#39;|&#39; &amp; i# &amp; &#39;=&#39; &amp; ShowINT64(c) str2 = str2 &amp; &#39;, &#39; &amp; ShowINT64(c) end message(str2,&#39;Fibonacci&#39;,,,,10b) message(str1,&#39;Fibonacci&#39;,,,,10b) ShowINT64 PROCEDURE(a) d DECIMAL(30,0) CODE i64ToDecimal(d,a) return(d) </code></pre> http://ru.progopedia.com/example/fibonacci/579/ Диалект T-SQL http://ru.progopedia.com/dialect/t-sql/ <p>T-SQL или Transact-SQL &#8212; диалект SQL, реализуемый компанией Microsoft в своих продуктах Microsoft SQL Server </p> http://ru.progopedia.com/dialect/t-sql/ Пример: Числа Фибоначчи - SQL (578) http://ru.progopedia.com/example/fibonacci/578/ <pre><code>declare @max_n tinyint = 92 ;with t as ( select n = 1, fib = convert(bigint,1), xfib = convert(bigint,0) union all select n = n+1, fib = fib+xfib, xfib = fib from t where n &lt; @max_n ) select fib from t</code></pre> http://ru.progopedia.com/example/fibonacci/578/ Пример: Квадратное уравнение - Clarion (577) http://ru.progopedia.com/example/quadratic-equation/577/ <pre><code> PROGRAM OMIT(&#39;***&#39;) * User: Shur * Date: 28.02.2016 * Time: 14:05 *** complex GROUP,TYPE a REAL(0) b REAL(0) END MAP cxSum PROCEDURE(*complex cxA, *complex cxB, *complex cxRes) cxMul PROCEDURE(*complex cxA, *complex cxB, *complex cxRes) cxDiv PROCEDURE(*complex cxA, *complex cxB, *complex cxRes) END A REAL B REAL C REAL X GROUP,PRE(X),DIM(2) X LIKE(complex) F CSTRING(64) R LIKE(complex) END root CSTRING(64) check_ CSTRING(256) CX1 LIKE(complex) CX2 LIKE(complex) CX3 LIKE(complex) CODE A=1; B=3; C=3 !A=1; B=-5; C=3 !A=1; B=2; C=1 D$ = B * B - 4 * A * C if A = 0 root = &#39;Not a quadratic equation.&#39; elsif D$ = 0 X[1].X.a = -B/2/A root = &#39;x = &#39; &amp; X[1].X.a elsif D$ &gt; 0 then X[1].X.a = (-B-sqrt(D$))/2/A X[2].X.a = (-B+sqrt(D$))/2/A root = &#39;x1 = &#39; &amp; X[1].X.a &amp; &#39;|&#39; &amp; | &#39;x2 = &#39; &amp; X[2].X.a else X[1].X.a = -B/2/A; X[1].X.b = sqrt(-D$)/2/A X[2].X.a = -B/2/A; X[2].X.b = -sqrt(-D$)/2/A root = &#39;x1 = (&#39; &amp; X[1].X.a &amp; &#39;, &#39; &amp; X[1].X.b &amp; &#39;)&#39; &amp; &#39;|&#39; &amp; | &#39;x2 = (&#39; &amp; X[2].X.a &amp; &#39;, &#39; &amp; X[2].X.b &amp; &#39;)&#39; end loop i# = 1 to 2 !loop j# = 1 to 2 if X[i#].X.a or X[i#].X.b if D$ ~&lt; 0 X[i#].F = choose(A=0,&#39;&#39;,A&amp;&#39;*&#39;&amp;X[i#].X.a&amp;&#39;^2&#39;)&amp;choose(B=0,&#39;&#39;,choose(B&gt;0,&#39;+&#39;,&#39;&#39;)&amp;B&amp;&#39;*&#39;&amp;X[i#].X.a)&amp;choose(C=0,&#39;&#39;,choose(C&gt;0,&#39;+&#39;,&#39;&#39;)&amp;C) X[i#].R.a = round(EVALUATE(X[i#].F),0.0000000000001) check_ = check_ &amp; choose(check_&lt;&gt;&#39;&#39;,&#39;|&#39;,&#39;&#39;) &amp; X[i#].F&amp;&#39;=&#39; &amp; X[i#].R.a else CX1.a = X[i#].X.a; CX1.b = X[i#].X.b CX2.a = A; CX2.b = 0 cxMul(CX1, CX1, CX3) ! x^2 cxMul(CX2, CX3, CX3) ! a*x^2 X[i#].R = CX3 CX2.a = B; CX2.b = 0 cxMul(CX1, CX2, CX3) ! b*x CX2 = X[i#].R cxSum(CX2,CX3,CX1) ! a*x^2 + b*x X[i#].R = CX1 CX2.a = C; CX2.b = 0 cxSum(CX1,CX2,CX3) ! a*x^2 + b*x + c X[i#].R = CX3 check_ = check_ &amp; choose(check_&lt;&gt;&#39;&#39;,&#39;|&#39;,&#39;&#39;) &amp;&#39;= (&#39; &amp; X[i#].R.a &amp; &#39;, &#39; &amp; X[i#].R.b &amp; &#39;)&#39; end end !end end message(choose(A=0,&#39;&#39;,&#39;D=&#39;&amp;D$&amp;&#39;|----------|&#39;)&amp;| root&amp;| choose(A=0,&#39;&#39;,choose(check_&gt;&#39;&#39;,| &#39;|----------|&#39;&amp;| check_,&#39;&#39;)),&#39;Quadratic equation&#39;) cxSum PROCEDURE(cxA, cxB, cxRes) CODE cxRes.a = cxA.a + cxB.a cxRes.b = cxA.b + cxB.b cxMul PROCEDURE(cxA, cxB, cxRes) CODE cxRes.a = cxA.a*cxB.a - cxA.b*cxB.b cxRes.b = cxA.a*cxB.b + cxB.a*cxA.b cxDiv PROCEDURE(cxA, cxB, cxRes) CODE cxRes.a = (cxA.a*cxB.a + cxA.b*cxB.b) / (cxB.a^2 + cxB.a^2) cxRes.b = (cxB.a*cxA.b - cxB.b*cxA.a) / (cxB.a^2 + cxB.a^2) </code></pre> http://ru.progopedia.com/example/quadratic-equation/577/ Пример: Квадратное уравнение - Clarion (576) http://ru.progopedia.com/example/quadratic-equation/576/ <pre><code> PROGRAM OMIT(&#39;***&#39;) * User: Shur * Date: 28.02.2016 * Time: 14:05 *** MAP END A REAL B REAL C REAL root CSTRING(64) CODE A=0; B=2; C=3 !A=1; B=-5; C=3 !A=1; B=2; C=1 D$ = B * B - 4 * A * C if A = 0 root = &#39;Not a quadratic equation.&#39; elsif D$ = 0 root = &#39;x = &#39; &amp; -B/2/A elsif D$ &gt; 0 then root = &#39;x1 = &#39; &amp; (-B-sqrt(D$))/2/A &amp; &#39;|&#39; &amp; | &#39;x2 = &#39; &amp; (-B+sqrt(D$))/2/A else root = &#39;x1 = (&#39; &amp; -B/2/A &amp; &#39;, &#39; &amp; sqrt(-D$)/2/A &amp; &#39;)&#39; &amp; &#39;|&#39; &amp; | &#39;x2 = (&#39; &amp; -B/2/A &amp; &#39;, &#39; &amp; -sqrt(-D$)/2/A &amp; &#39;)&#39; end message(choose(A=0,&#39;&#39;,&#39;D=&#39;&amp;D$&amp;&#39;|----------|&#39;)&amp;root,&#39;Quadratic equation&#39;) </code></pre> http://ru.progopedia.com/example/quadratic-equation/576/ Пример: CamelCase - Clarion (575) http://ru.progopedia.com/example/camelcase/575/ <pre><code> PROGRAM MAP END InitStr STRING(&#39;Some string with any symbols&#39;) Str CSTRING(100),AUTO symbol STRING(1) CODE j# = 1 ! implicit variable loop i# = 1 to len(InitStr) by 1 symbol = lower(InitStr[i#]) ! string can be considered as array case symbol of &#39;a&#39; to &#39;z&#39; Str[j#] = choose(was_letter#,symbol,upper(symbol)) j# += 1 ! using of add equals operator for increment was_letter# = TRUE else was_letter# = FALSE end end message(Str,&#39;CamelCase&#39;) </code></pre> http://ru.progopedia.com/example/camelcase/575/ Пример: Hello, World! - Clarion (574) http://ru.progopedia.com/example/hello-world/574/ <pre><code> PROGRAM MAP END CODE MESSAGE(&#39;Hello World!&#39;,&#39;Clarion&#39;) RETURN</code></pre> http://ru.progopedia.com/example/hello-world/574/ Версия Clarion C10 http://ru.progopedia.com/version/clarion-c10/ <p>C10 Gold + was released on November 2015. </p> <p>C10 was re-worked to build up on .NET 4 </p> http://ru.progopedia.com/version/clarion-c10/ Версия Clarion C9 http://ru.progopedia.com/version/clarion-c9/ <p>In August 2014 C9.1 Gold was released. </p> http://ru.progopedia.com/version/clarion-c9/ Версия Clarion C8 http://ru.progopedia.com/version/clarion-c8/ <p>On September 12, 2011 SoftVelocity released Clarion 8. It continues the line of Clarion 7 (the latest release was C7.3). </p> http://ru.progopedia.com/version/clarion-c8/ Версия Clarion C7 http://ru.progopedia.com/version/clarion-c7/ <p>On April 13, 2009 SoftVelocity released Clarion 7 (aka C7). The new IDE will look familiar to SharpDevelop users, SoftVelocity obtained a commercial license for the SharpDevelop code and integrated Clarion&#8217;s code generation and application generation technology, fixed and extended the basic functionality. Major new features (other than the standard modern IDE features lacking in C6) include a build system based on MSBuild and backward compatibility with all releases of Clarion going back to Clarion for Windows 1.5. </p> http://ru.progopedia.com/version/clarion-c7/ Версия Clarion C6.3 http://ru.progopedia.com/version/clarion-c6.3/ <p>Clarion 6.3 as released Jan 2006. Excluding patches this is the final release of the 16 bit Clarion development environment. The use of a 16 bit IDE produced some problems using current Windows technologies (ActiveX, OCX, COM, DOC, &#8230;); however, note that the series 6.x of Clarion produces native Win32 executables (32-bit exes and/or dlls). Previous versions produced both 16-bit and 32-bit executables, the 16-bit support was dropped from the end-user product with version 6.0 of Clarion. </p> http://ru.progopedia.com/version/clarion-c6.3/ Версия Clarion C6.2 http://ru.progopedia.com/version/clarion-c6.2/ <p>Clarion 6.2 was released May 2005 </p> http://ru.progopedia.com/version/clarion-c6.2/ Версия Clarion C6.1 http://ru.progopedia.com/version/clarion-c6.1/ <p>Clarion 6.1 was released May 2004. </p> http://ru.progopedia.com/version/clarion-c6.1/ Версия Clarion C6 http://ru.progopedia.com/version/clarion-c6/ <p>Clarion 6.0 (aka C6) was released November 2003, and added direct support for pre-emptive multi-threading. </p> http://ru.progopedia.com/version/clarion-c6/