Clarion: мощное оружие, бьющее точно в цель.Как все начиналось
Продолжение, начало в N№ 13
Промежуточные значения
В первых версиях компилятора Cla-rion для числовых промежуточных значений использовались всего два типа данных: 32-х битовое целое со знаком (LONG) и 64-х битовое с плавающей точкой. Операция деления или любая операция, в которой используется хотя бы один операнд типа REAL, даст промежуточное значение типа REAL. Такая стратегия обеспечивала достаточную точность, поскольку REAL может давать максимальную значимость числа (15 десятичных цифр), поддерживаемую в Clarion. Хотя значения с плавающей точкой и имеют высокую точность, есть один нюанс. Два эквивалентных выражения, такие, как 1/2 и 2/4, могут давать значения с плавающей точкой, различающиеся в последнем двоичном разряде.
В вычислениях это обычно не имеет значения. Но не при сравнении. Программист ожидает, что одна вторая равна двум четвертям. Можно запретить сравнение значений с плавающей точкой, но вы вправе ожидать, что приведенное далее логическое выражение будет правильно работать независимо от времени суток:
IF Hours> Normal * 1.5
Использование промежуточного значения типа REAL для выражения справа от знака "> " бросает тень на результаты сравнения. Эта проблема была решена в Clarion for Windows посредством реализации промежуточного значения с фиксированной точкой, имеющего по 31 десятичной цифре в целой и дробной части. Кроме того, это новшество повысило точность числа до 31-й цифры.
Управляющиеструктуры
Если языки коммерческих применений COBOL PL/1 имели тогда предпочтительную систему объявления данных, то языки, производные от Алгола, особенно Modula-2, отличались более удобными структурами управления обработкой коммерческих данных. При разработке Cla-rion был модифицирован оператор IF языка, благодаря замене ключевого слова THEN разделителем. В результате исчезли избыточные THEN из IF структур, занимающих несколько строк. Из Modula-2 был взят ELSEIF, тем самым избавив язык от необходимости многократных отступов вправо и многочисленных разделителей в сильно вложенных IF структурах:
IF Number <0
Sign=-1
ELSEIF Number> 0
Sign=+1
ELSE
Sign=0
End
Оператор CASE языка Clarion был создан на базе аналогичного оператора выбора языка Modula-2, в котором метки элементов оператора и интервалы значений относятся к перечисляемому типу данных, что очень полезно. Однако потребовала изменений не очень красивая и не естественная система разделителей, в которой ключевое слово OF предшествовало первой метке, а последующие метки начинались с вертикальной черточки. Вместо этого OF поставили в начале каждой метки, внутри меток использовалось ключевое слово OROF, а для интервалов значений - ключевое слово ТО. В результате получилась привлекательная с точки зрения синтаксиса структура:
CASE SUB(Name, 1, 1)
OF('A') TO ('M') OROF('a') TO ('m')
DO FirstHalf
OF('N') TO ('Z') OROF('n') TO ('z')
DO SecondHalf
ELSE
DO FirstHalf
END
Только в Modula-2 ключевое слово LOOP использовалось в нормальном контексте. LOOP... END выполняет безусловный цикл, который завершается выполнением оператора EXIT. Эта идея была развита путем добавления оператора CYCLE, чтобы перезапустить цикл изнутри. Также пришлось заменить EXIT на BREAK, потому что EXIT использовался для другой цели. Условные циклы были реализованы путем добавления четырех дополнительных предложений к оператору LOOP:
LOOP I = 1 TO 100 BY 2
LOOP 10000 TIMES
LOOP WHILE Count 0
LOOP UNTIL EndOfFile
Хорошая организация программы требует наличия внутренних подпрограмм, то есть блоков операторов, отделенных от текста основной программы и выполняемых с помощью оператора вызова внутренней подпрограммы. Если подпрограмме умело дать имя, текст основной программы становится короче, ясность же при этом не теряется. В COBOL и BASIC для выполнения внутренних подпрограмм используются ключевые слова PERFORM и COSUB. Локальные процедуры Pascal и Modula-2 почти точно подходили, но для объявления типов параметров они требовали наличия операторов прототипов. Оказалось не желательным, чтобы локальные процедуры имели параметры, так как все данные вызывающей процедуры должны быть доступны локальной программе. Поэтому был придуман оператор ROUTINE для инициализации внутренней подпрограммы. Подпрограммы располагаются в конце процедуры или функции и выполняются оператором DO.
В ряде языков предусмотрен механизм выбора для выполнения одного оператора из списка в зависимости от значения целого числа, определяющего выбор. В FORTRAN используется вычисляемый GOTO, в BASIC - ON... GOTO и ON... COSUB. Разработчикам Clarion тоже захотелось реализовать подобную возможность, позволяющую выполнять любой тип оператора из списка в зависимости от значения выражения целого числа. Такая структура была названа EXECUTE, так как известная машинная команда XEQ является сокращением этого же английского слова. Указанная команда выполняет одну из следующих команд, на которую указывает ее операнд. Эта структура существует только в языке Clarion, но уже доказала свою пользу:
EXECUTE UpdateAction
ADD(Master)
PUT(Master)
DELETE(Master)
END
Проектирование базы данных
Одной из приоритетных задач, которую требовалось реализовать, являлся доступ к БД с простым синтаксисом, который позволял бы применять все три стандартных метода доступа к файлам: прямой, последовательный и индексный. Организация файла виделась простой: заголовок, за которым идут информационные записи фиксированной длины. Заголовок описывает структуру записи, связанные с ней ключи и поля типа memo, расположенные в отдельных файлах. Эта схема похожа на принятую в dBase: доступ к записи может быть последовательным или прямым через ключ, или относительный номер записи. Чтобы объявлять файлы и их компоненты, была введена структура FILE, аналогичная структуре FD языка COBOL.
Последовательная обработка была реализована с помощью ключевых слов SET, NEXT, PREVIOUS, SKIP. Команда SET задает последовательность (с помощью ключа или относительного номера записи) и начальную точку обработки для трех других команд, которые задают прямое и обратное считывание и пропуск записей. Эти ключевые слова прекрасно сочетаются с функцией "конец файла" (EOF) в цикле чтения:
SET(Dt:AcctKey) ! Установить последовательность обработки номеров счетов
LOOP UNTIL EOF(Detail) !Цикл обработки каждой записи
NEXT(Detail) !Читать следующую запись
:
END
Команда GET читает произвольную запись по ключу или относительному номеру. Важно, что GET не мешает последовательной обработке, поскольку эта команда не устанавливает следующую для обработки запись. Команды PUT и DELETE обрабатывают записи, доступ к которым был получен с помощью команд NEXT, PREVIOUS или GET. Команда ADD включает новую запись в БД. Как оказалось, такая концепция доступа эффективна, надежна и универсальна - существенная и популярная составная часть языка Cla-rion.
Однако, по мере роста популярности Clarion приходилось вводить новые возможности. Сначала потребовался доступ к файлам dBASE, поэтому была добавлена библиотека процедур по работе с dBASE (библиотеки процедур Clarion принято называть "Language Extension Modules" или LEM'ы - модули расширения языка). Потом Novell разработала систему поддержки связи клиента и сервера для Btrieve (с ведением индекса на сервере). Для некоторых крупных прикладных систем на Cla-rion требовалась Btrieve для повышения производительности при обработке транзакций. В результате появились Btrieve LEM'ы, разработанные двумя партнерами Clarion.
Еще оставались DB2 и RDB, Oracle и SQL Server, и любые другие системы по управлению базами данных, работающие на ПК или к которым ПК имеет доступ. Поэтому была добавлена поддержка прямых вызовов функций на С в следующих версиях языка с таким расчетом, чтобы программа на Clarion могла работать с БД, для которой имеется API на языке С. Однако было ясно, что это не может решить всех проблем. Нельзя было допустить, чтобы в универсальном языке для коммерческих применений использовались разные наборы процедур доступа в зависимости от формата БД. Работа с файлами не должна приводить к необходимости переделки программ. Для языка Clarion нужна была стандартизованная, встроенная поддержка для работы со всеми широко распространенными базами данных.
Вначале было предложено принять в качестве синтаксиса запросов к БД синтаксис SQL. Но вскоре от этой порочной идеи пришлось отказаться. Дело в том, что для написания программ синтаксис SQL слишком многословен и не изящен. Более того, концепция курсора в SQL не только не изящна, но и почти бесполезна. Нельзя с помощью курсора пропустить часть информации, например, чтобы вновь вывести предыдущую страницу записей. Нельзя также произвольно изменить его позицию.
Началось создание заменяемых драйверов баз данных. Программистам на Clarion нравился метод доступа к БД этого языка, но им нужна была поддержка форматов других БД. На основе имеющейся структуры языка, был расширен их кругозор и повышены возможности разработанных прикладных систем. С помощью новой технологии драйверов баз данных был одинаково реализован доступ ко всем базам данных - нетривиальное преимущество продукта.
Первый компилятор
В комплект поставки версии 1.0 Cla-rion, отгруженной в мае 1986 г., входили компилятор и интерпретатор. Компилятор вырабатывал проме-жуточный код, который затем интерпретировался утилитой Processor. Промежуточный код был настолько компактен, что большие прикладные программы на Clarion помещались в небольшую по объему основную память (256К), которая была у ПК типа IBM РС того времени.
Но сжатый код не был основной целью. Интерпретируя данные на выходе компилятора, Processor мог выполнить прикладную программу на Clarion без дополнительного этапа компоновки. И это было существенно, так как в 1986 г. и еще долго после этого компоновка оставалась одним из самых медленных процессов.
Клиенты Clarion высоко оценивали скоростные характеристики тестовых примеров, но при этом высказывали замечания, что "настоящие" языки программирования приводят к появлению.EXE файлов! В начале следующего года был выпущен транслятор, который преобразовывал промежуточный код в.OBJ файлы, заменяя коды операций вызовами процедур. Указатели передавались в качестве параметров. Этот подход послужил верой и правдой шесть лет, но он породил ряд проблем, связанных с использованием внешних библиотек, большими по объему.EXE файлами, более медленной работе программ на Clarion, чем на С, Pascal и Modula-2.
Но самое главное - была нужна технология, которая бы обеспечила разработчикам переход к Windows, OS/2, UNIX, 32-разрядной машине и архитектурам не фирмы Intel.
Начало начал
В мае 1990 г. эти и многие другие проблемы были решены с покупкой лицензии на технологию фирмы JPI, разработчиков продуктов серии TopSpeed. Достаточно сказать, что JPI была основана одним из основателей Borland International Нильсом Йенсеном (Niels Jensen). JPI разработала компиляторы языков С, С++, Pascal, Modula-2, в состав которых входил один и тот же оптимизирующий генератор кода. JPI назвала компиляторы "внешними" компонентами, а генератор кода - "внутренним" компонентом.
Несмотря на то, что разработка внешнего компонента Clarion заняла столько времени и средств, как ни в одних даже самых смелых прогнозах, результаты были просто ошеломляющими. Программа, реализовавшая на Clarion алгоритм "Решето Эратосфена", работала в два раза быстрее, чем аналог на Turbo C++ от Borland. Дополнительные преимущества принесла технология компоновки TopSpeed. Ее уникальный компонент "Smart Linking" (интеллектуальная компоновка) убирал из.EXE файлов все процедуры, на которые не было ссылок, и статические элементы данных. Даже более того, пока велась работа над внешним компонентом, JPI разработала автоматический загрузчик оверлеев, DLL DOS, DOS Extender и объявила о поддержке 32-разрядной архитектуры. Благодаря этим новшествам было, наконец, устранено отставание в быстродействии, которое всегда было свойственно языкам высокого уровня, предназначенным для административных и экономических задач.
Новые характеристики и взаимосвязь с системой TopSpeed вызвали восторженные отклики среди программистов и в прессе. В 1994 произошло слияние с образованием объединенной компании TopSpeed Corporation. А уже в октябре того же года вышел в свет Clarion for Windows.
"Разработка программного обеспечения представляется мне как процесс тихого покачивания китайской доски - игрушки, в которой все мраморные шарики должны заполнить ямки. В этой аналогии финал - законченный программный продукт. До выхода в свет Clarion for Windows я чувствовал, что мы еще далеки от цели. Теперь я думаю иначе. Совсем немного шариков еще катается".
По материалам журналов "МирПК", "Clarion Magazine"
Подготовил Максим Костюченко
Промежуточные значения
В первых версиях компилятора Cla-rion для числовых промежуточных значений использовались всего два типа данных: 32-х битовое целое со знаком (LONG) и 64-х битовое с плавающей точкой. Операция деления или любая операция, в которой используется хотя бы один операнд типа REAL, даст промежуточное значение типа REAL. Такая стратегия обеспечивала достаточную точность, поскольку REAL может давать максимальную значимость числа (15 десятичных цифр), поддерживаемую в Clarion. Хотя значения с плавающей точкой и имеют высокую точность, есть один нюанс. Два эквивалентных выражения, такие, как 1/2 и 2/4, могут давать значения с плавающей точкой, различающиеся в последнем двоичном разряде.
В вычислениях это обычно не имеет значения. Но не при сравнении. Программист ожидает, что одна вторая равна двум четвертям. Можно запретить сравнение значений с плавающей точкой, но вы вправе ожидать, что приведенное далее логическое выражение будет правильно работать независимо от времени суток:
IF Hours> Normal * 1.5
Использование промежуточного значения типа REAL для выражения справа от знака "> " бросает тень на результаты сравнения. Эта проблема была решена в Clarion for Windows посредством реализации промежуточного значения с фиксированной точкой, имеющего по 31 десятичной цифре в целой и дробной части. Кроме того, это новшество повысило точность числа до 31-й цифры.
Управляющиеструктуры
Если языки коммерческих применений COBOL PL/1 имели тогда предпочтительную систему объявления данных, то языки, производные от Алгола, особенно Modula-2, отличались более удобными структурами управления обработкой коммерческих данных. При разработке Cla-rion был модифицирован оператор IF языка, благодаря замене ключевого слова THEN разделителем. В результате исчезли избыточные THEN из IF структур, занимающих несколько строк. Из Modula-2 был взят ELSEIF, тем самым избавив язык от необходимости многократных отступов вправо и многочисленных разделителей в сильно вложенных IF структурах:
IF Number <0
Sign=-1
ELSEIF Number> 0
Sign=+1
ELSE
Sign=0
End
Оператор CASE языка Clarion был создан на базе аналогичного оператора выбора языка Modula-2, в котором метки элементов оператора и интервалы значений относятся к перечисляемому типу данных, что очень полезно. Однако потребовала изменений не очень красивая и не естественная система разделителей, в которой ключевое слово OF предшествовало первой метке, а последующие метки начинались с вертикальной черточки. Вместо этого OF поставили в начале каждой метки, внутри меток использовалось ключевое слово OROF, а для интервалов значений - ключевое слово ТО. В результате получилась привлекательная с точки зрения синтаксиса структура:
CASE SUB(Name, 1, 1)
OF('A') TO ('M') OROF('a') TO ('m')
DO FirstHalf
OF('N') TO ('Z') OROF('n') TO ('z')
DO SecondHalf
ELSE
DO FirstHalf
END
Только в Modula-2 ключевое слово LOOP использовалось в нормальном контексте. LOOP... END выполняет безусловный цикл, который завершается выполнением оператора EXIT. Эта идея была развита путем добавления оператора CYCLE, чтобы перезапустить цикл изнутри. Также пришлось заменить EXIT на BREAK, потому что EXIT использовался для другой цели. Условные циклы были реализованы путем добавления четырех дополнительных предложений к оператору LOOP:
LOOP I = 1 TO 100 BY 2
LOOP 10000 TIMES
LOOP WHILE Count 0
LOOP UNTIL EndOfFile
Хорошая организация программы требует наличия внутренних подпрограмм, то есть блоков операторов, отделенных от текста основной программы и выполняемых с помощью оператора вызова внутренней подпрограммы. Если подпрограмме умело дать имя, текст основной программы становится короче, ясность же при этом не теряется. В COBOL и BASIC для выполнения внутренних подпрограмм используются ключевые слова PERFORM и COSUB. Локальные процедуры Pascal и Modula-2 почти точно подходили, но для объявления типов параметров они требовали наличия операторов прототипов. Оказалось не желательным, чтобы локальные процедуры имели параметры, так как все данные вызывающей процедуры должны быть доступны локальной программе. Поэтому был придуман оператор ROUTINE для инициализации внутренней подпрограммы. Подпрограммы располагаются в конце процедуры или функции и выполняются оператором DO.
В ряде языков предусмотрен механизм выбора для выполнения одного оператора из списка в зависимости от значения целого числа, определяющего выбор. В FORTRAN используется вычисляемый GOTO, в BASIC - ON... GOTO и ON... COSUB. Разработчикам Clarion тоже захотелось реализовать подобную возможность, позволяющую выполнять любой тип оператора из списка в зависимости от значения выражения целого числа. Такая структура была названа EXECUTE, так как известная машинная команда XEQ является сокращением этого же английского слова. Указанная команда выполняет одну из следующих команд, на которую указывает ее операнд. Эта структура существует только в языке Clarion, но уже доказала свою пользу:
EXECUTE UpdateAction
ADD(Master)
PUT(Master)
DELETE(Master)
END
Проектирование базы данных
Одной из приоритетных задач, которую требовалось реализовать, являлся доступ к БД с простым синтаксисом, который позволял бы применять все три стандартных метода доступа к файлам: прямой, последовательный и индексный. Организация файла виделась простой: заголовок, за которым идут информационные записи фиксированной длины. Заголовок описывает структуру записи, связанные с ней ключи и поля типа memo, расположенные в отдельных файлах. Эта схема похожа на принятую в dBase: доступ к записи может быть последовательным или прямым через ключ, или относительный номер записи. Чтобы объявлять файлы и их компоненты, была введена структура FILE, аналогичная структуре FD языка COBOL.
Последовательная обработка была реализована с помощью ключевых слов SET, NEXT, PREVIOUS, SKIP. Команда SET задает последовательность (с помощью ключа или относительного номера записи) и начальную точку обработки для трех других команд, которые задают прямое и обратное считывание и пропуск записей. Эти ключевые слова прекрасно сочетаются с функцией "конец файла" (EOF) в цикле чтения:
SET(Dt:AcctKey) ! Установить последовательность обработки номеров счетов
LOOP UNTIL EOF(Detail) !Цикл обработки каждой записи
NEXT(Detail) !Читать следующую запись
:
END
Команда GET читает произвольную запись по ключу или относительному номеру. Важно, что GET не мешает последовательной обработке, поскольку эта команда не устанавливает следующую для обработки запись. Команды PUT и DELETE обрабатывают записи, доступ к которым был получен с помощью команд NEXT, PREVIOUS или GET. Команда ADD включает новую запись в БД. Как оказалось, такая концепция доступа эффективна, надежна и универсальна - существенная и популярная составная часть языка Cla-rion.
Однако, по мере роста популярности Clarion приходилось вводить новые возможности. Сначала потребовался доступ к файлам dBASE, поэтому была добавлена библиотека процедур по работе с dBASE (библиотеки процедур Clarion принято называть "Language Extension Modules" или LEM'ы - модули расширения языка). Потом Novell разработала систему поддержки связи клиента и сервера для Btrieve (с ведением индекса на сервере). Для некоторых крупных прикладных систем на Cla-rion требовалась Btrieve для повышения производительности при обработке транзакций. В результате появились Btrieve LEM'ы, разработанные двумя партнерами Clarion.
Еще оставались DB2 и RDB, Oracle и SQL Server, и любые другие системы по управлению базами данных, работающие на ПК или к которым ПК имеет доступ. Поэтому была добавлена поддержка прямых вызовов функций на С в следующих версиях языка с таким расчетом, чтобы программа на Clarion могла работать с БД, для которой имеется API на языке С. Однако было ясно, что это не может решить всех проблем. Нельзя было допустить, чтобы в универсальном языке для коммерческих применений использовались разные наборы процедур доступа в зависимости от формата БД. Работа с файлами не должна приводить к необходимости переделки программ. Для языка Clarion нужна была стандартизованная, встроенная поддержка для работы со всеми широко распространенными базами данных.
Вначале было предложено принять в качестве синтаксиса запросов к БД синтаксис SQL. Но вскоре от этой порочной идеи пришлось отказаться. Дело в том, что для написания программ синтаксис SQL слишком многословен и не изящен. Более того, концепция курсора в SQL не только не изящна, но и почти бесполезна. Нельзя с помощью курсора пропустить часть информации, например, чтобы вновь вывести предыдущую страницу записей. Нельзя также произвольно изменить его позицию.
Началось создание заменяемых драйверов баз данных. Программистам на Clarion нравился метод доступа к БД этого языка, но им нужна была поддержка форматов других БД. На основе имеющейся структуры языка, был расширен их кругозор и повышены возможности разработанных прикладных систем. С помощью новой технологии драйверов баз данных был одинаково реализован доступ ко всем базам данных - нетривиальное преимущество продукта.
Первый компилятор
В комплект поставки версии 1.0 Cla-rion, отгруженной в мае 1986 г., входили компилятор и интерпретатор. Компилятор вырабатывал проме-жуточный код, который затем интерпретировался утилитой Processor. Промежуточный код был настолько компактен, что большие прикладные программы на Clarion помещались в небольшую по объему основную память (256К), которая была у ПК типа IBM РС того времени.
Но сжатый код не был основной целью. Интерпретируя данные на выходе компилятора, Processor мог выполнить прикладную программу на Clarion без дополнительного этапа компоновки. И это было существенно, так как в 1986 г. и еще долго после этого компоновка оставалась одним из самых медленных процессов.
Клиенты Clarion высоко оценивали скоростные характеристики тестовых примеров, но при этом высказывали замечания, что "настоящие" языки программирования приводят к появлению.EXE файлов! В начале следующего года был выпущен транслятор, который преобразовывал промежуточный код в.OBJ файлы, заменяя коды операций вызовами процедур. Указатели передавались в качестве параметров. Этот подход послужил верой и правдой шесть лет, но он породил ряд проблем, связанных с использованием внешних библиотек, большими по объему.EXE файлами, более медленной работе программ на Clarion, чем на С, Pascal и Modula-2.
Но самое главное - была нужна технология, которая бы обеспечила разработчикам переход к Windows, OS/2, UNIX, 32-разрядной машине и архитектурам не фирмы Intel.
Начало начал
В мае 1990 г. эти и многие другие проблемы были решены с покупкой лицензии на технологию фирмы JPI, разработчиков продуктов серии TopSpeed. Достаточно сказать, что JPI была основана одним из основателей Borland International Нильсом Йенсеном (Niels Jensen). JPI разработала компиляторы языков С, С++, Pascal, Modula-2, в состав которых входил один и тот же оптимизирующий генератор кода. JPI назвала компиляторы "внешними" компонентами, а генератор кода - "внутренним" компонентом.
Несмотря на то, что разработка внешнего компонента Clarion заняла столько времени и средств, как ни в одних даже самых смелых прогнозах, результаты были просто ошеломляющими. Программа, реализовавшая на Clarion алгоритм "Решето Эратосфена", работала в два раза быстрее, чем аналог на Turbo C++ от Borland. Дополнительные преимущества принесла технология компоновки TopSpeed. Ее уникальный компонент "Smart Linking" (интеллектуальная компоновка) убирал из.EXE файлов все процедуры, на которые не было ссылок, и статические элементы данных. Даже более того, пока велась работа над внешним компонентом, JPI разработала автоматический загрузчик оверлеев, DLL DOS, DOS Extender и объявила о поддержке 32-разрядной архитектуры. Благодаря этим новшествам было, наконец, устранено отставание в быстродействии, которое всегда было свойственно языкам высокого уровня, предназначенным для административных и экономических задач.
Новые характеристики и взаимосвязь с системой TopSpeed вызвали восторженные отклики среди программистов и в прессе. В 1994 произошло слияние с образованием объединенной компании TopSpeed Corporation. А уже в октябре того же года вышел в свет Clarion for Windows.
"Разработка программного обеспечения представляется мне как процесс тихого покачивания китайской доски - игрушки, в которой все мраморные шарики должны заполнить ямки. В этой аналогии финал - законченный программный продукт. До выхода в свет Clarion for Windows я чувствовал, что мы еще далеки от цели. Теперь я думаю иначе. Совсем немного шариков еще катается".
По материалам журналов "МирПК", "Clarion Magazine"
Подготовил Максим Костюченко
Компьютерная газета. Статья была опубликована в номере 14 за 1999 год в рубрике программирование :: разное