Алексей Яковлев
ENGLISH
Избранные проекты » Несколько слов о языке Why
Главная страница
Последние новости
Избранные проекты
Загрузка файлов
Чужие проекты
Ссылки по теме
Панель управления
Выбор языка
Русский (по умолчанию)
English
Выбор палитры
Сирень (по умолчанию)
Кирпичные стены
Серебристые тени
Тонкие линии
Стиль отображения
Графический (по умолчанию)
Только текст (для печати)

Язык программирования Why

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

Алексей Яковлев
Апрель 2001

Что такое язык Why и почему?

Why — это язык программирования, который создан на основе концепции языка Форт. Название Why появилось совершенно случайно. Первоначально оно относилось только к компилятору ("Чем не компилятор?", "Why not a compiler?"), когда новый язык еще не был окончательно сформирован, а позже оно перешло и на сам язык.

Идея языка Why

Как и Форт, Why целиком построен на использовании стека. Все данные, над которыми производятся действия, кладутся в стек. Все подпрограммы (в терминологии Форта — "слова") извлекают несколько верхних элементов стека и кладут вместо них результаты операций. К примеру, сложение "2 + 3" на Форте (как и на языке Why) записывается как "2 3 +": "2" и "3" — это операции занесения в стек целочисленных констант, "+" — операция сложения двух верхних элементов стека. После выполнения указанных действий на вершине стека оказывается число 5 — результат сложения.

К сожалению, автор не может гордиться блестящим знанием Форта (мягко говоря), поэтому, как и любой дилетант, ко всему относится критически. С его точки зрения, Форт, разработанный во времена малопроизводительных ЭВМ со скуднейшими ресурсами, содержит некоторые моменты, на сегодняшний день устаревшие. Кроме того, имея довольно большой опыт программирования на современных языках, автор считает, что Форту недостает кое-каких элементов, присутствующих в этих языках. Чтобы не навлечь на себя всеобщий гнев почитателей Форта, автор не будет останавливаться на этих моментах, а просто опишет все, что есть в языке Why, который понятен ему в несколько большей степени, чем Форт.

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

Программа на языке Why — это набор инструкций, разделенных между собой пробелами или комментариями. Каждая инструкция — это либо занесения в стек некоторого параметра, либо вызов подпрограммы (подпрограмма может быть и встроенной — "inline"). Простейшая программа, с которой начинают изучение любого языка программирования — печать приветствия "Hello, World!" (добрая традиция, пришедшая из книги Кернигана и Ритчи), на Why выглядит так:

: Main
  "Hello, World!" Puts
;

(знатоки Форта, несомненно, заметят некоторое сходство записей). В стек заносится строковая константа (вернее, ее адрес), затем вызывается подпрограмма печати строки, которая извлекает строку из стека и печатает на экран. По окончании всех этих действий стек остается таким же, как и до их начала.

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

Программа — это библиотека, которая содержит функцию Main. Язык Why нечувствителен к регистру символов, поэтому "Main", "main" и "MAIN" представляют собой один и тот же идентификатор.

Управляющие конструкции языка Why

В языке Why все управляющие конструкции имеют самый простой синтаксис. На самом деле они представляют собой inline-подпрограммы, которые оперируют со стеком. Например, синтаксис обычного цикла со счетчиком:

<ToLoopStatement> ::= "to" <Sequence> "loop"

сразу бросается в глаза полным отсутствием любых признаков самого счетчика. На самом деле "to" и "loop" - это просто две разных операции. Слово "to" сравнивает верхний элемент стека с элементом под ним и делает условный переход на слово, следующее за "loop", если элемент на вершине стека больше. Слово "loop" делает безусловный переход на "to". Все остальные операции — инициализация цикла, увеличение счетчика и т.д. — это забота программиста. Единственное, что делает компилятор Why — это извлечение из стека двух верхних элементов после слова "loop". Вот пример цикла "to-loop", который пять раз подряд печатает "Hello again" (не слишком остроумно, но для примера сойдет):

5 1 to
    "Hello again" Puts
++ loop

В теле цикла верхний элемент арифметического стека — это и есть счетчик. "++" — операция увеличения верхнего элемента стека на единицу. Вовсе не обязательно делать именно эту операцию: например, можно сделать "2 +" для увеличения верхнего элемента стека на 2 (компилятор на это совершенно не смотрит, потому что это вообще отсутствует в правиле грамматики). После слова "loop" первыми операциями будут два идущих подряд "drop", которые вставит компилятор, чтобы извлечь из стека счетчик цикла и его верхний предел.

Кроме цикла "to-loop" в языке Why есть аналогичный цикл "downto-loop", который отличается только операцией проверки условия, циклы "begin-until", "begin-while-repeat" и, конечно, оператор выбора "if-else-then". Как в Форте, в зависимости от условия, лежащего на вершине стека, выполняется либо блок "if", либо "else", после чего управление переходит к слову, следующему после "then":

1 if
  "All goes right"
else
  "Opps! A bug in the compiler."
then

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

"String constant" PutNumber

Компилятор "не знает", какой тип параметра необходим для процедуры PutNumber, поскольку это никак не указано в ее заголовке. Благодаря этому процедура языка Why может брать из стека заранее неизвестное число параметров, как, например printf в языке Си или writeln в Паскале.

Оптимизация кода

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

Такая организация существенно усложняет генератор кода, зато позволяет намного улучшить качество готовых программ. Например, для выражения "7 3 * 1 - 10 /" компилятор сгенерирует такой же код, как для "2". Кроме того, хранение констант на этапе компиляции позволяет пропускать циклы и ветки условных операторов, которые не выполняются ни разу (например, "1 5 to .. loop" или "0 if .. then").

Перекомпиляция компилятора

Компилятор Why целиком написан на Паскале с использованием объектов. Библиотеки времени выполнения написаны на языке Why (практически целиком) и ассемблере (несколько низкоуровневых процедур).

Для перекомпиляции необходим Turbo Pascal 7.x. Автор использовал Turbo Pascal 7.1, © 1997 Borland International. Возможно, есть и другие компиляторы, которые без изменений позволят перекомпилировать исходные тексты, хотя это крайне маловероятно. Общий объем исходного кода – около 5.5 тысяч строк; это дает основания предполагать, что где-нибудь обязательно встретится какая-нибудь несовместимость.

Май 2000

Имеется еще один текст, содержащий несколько слов о компиляторе Why.


Copyright © 2000-2003 YALLIE, Inc. All Rights Reserved
webmaster: yallie@yandex.ru
Используются технологии uCoz