Katahdin

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 20:11, 1 июня 2016.
Katahdin
Парадигма мультипарадигменный
Спроектировано Chris Seaton
Первый   появившийся 2007
Печать дисциплины статическая, динамическая
Лицензия BSD
Портал: http://chrisseaton.com/katahdin/

Katahdin — язык программирования, в котором семантика и синтаксис могут изменяться во время исполнения. В Katahdin используются РВ-грамматики и packrat-парсер. Новые конструкции (выражения, операторы и др.), или даже новый язык программирования могут быть созданы с нуля. Единственная реализация языка использует платформу .NET (реализацию Mono).

Введение

Katahdin позволяет вводить новые конструкции также легко, как в обычных языках программирования можно создавать функции и типы данных. Например, во многих языках программирования присутствует операция взятия остатка (mod). Если используемый язык программирования не содержит такой операции и не позволяет каким-то образом ее перегрузить, то реализация подобной операции выльется в изучение реализации языка, изменение грамматики и сборку нового транслятора. Katahdin позволяет описать операцию взятия остатка в несколько строк:

class ModExpression : Expression {
    pattern {
        option leftRecursive;
        a:Expression "%" b:Expression
    }

    method Get() {
        a = this.a.Get...();
        b = this.b.Get...();
        return a - (b * (a / b));
    }
}

Этот код выполнится во время исполнения программы, и сразу после этого операция взятия остатка станет частью языка. Таким образом, после объявления новой операции, она может быть использована дальше в программе. Katahdin не содержит специальных конструкций, которые не могут быть изменены (даже пробелы и ключевые слова не являются исключением). Если описать все конструкции какого-либо языка программирования подобным образом, то Katahdin превратится в интерпретатор этого языка. Таким образом, Katahdin может быть использован в качестве универсального интерпретатора. Также можно использовать один язык в рамках другого, просто описав оба языка в Katahdin. На сегодняшний момент существуют подобные описания для языков Фортран и Python.

Иногда программист хочет использовать один язык в рамках другого. Например, SQL используется повсеместно в рамках других языков, при этом код на SQL записывается в строках. Katahdin позволяет совместить основной язык с SQL, чтобы тот использовался как часть основного языка. Также иногда возникает желание определить новый оператор во время исполнения. Например, в Java 1.5 была добавлен оператор for-each. Но пока эта реализация языка не была выпущена, программисты не могли использовать эту возможность. Использование Katahdin в этом случае позволило бы программистам использовать эту конструкцию, не дожидаясь следующей версии Java. Реализация этого оператора выглядела бы примерно следующим образом:

class ForStatement : Statement {
    pattern {
        "for" "(" init:Expression ";"
            cond:Expression ";" inc:Expression ")"
        body:Statement
    }

    method Run {
        init.Get...();
        while (cond.Get...()) {
            body.Run...();
            inc.Get...();
        }
    }
}

Грамматика

Описание шаблонов

Грамматики в Katahdin представляют собой измененные РВ-грамматики. Запись очень близка также КС-грамматикам. Просто текст помещается в кавычки ("текст") и может включать в себя стандартные Escape-последовательности. Диапазон символов может быть выражен при помощи оператора .. : "a".."z". Оператор . соответствует любому символу. Другие структуры обозначаются именами (value). Последовательность представляется словами, разделенными пробелами: a b c Операторы ? * + переводятся как ноль-или-один, ноль-или-больше, один-или-больше, соответственно. Выражения могут группироваться в скобки для определения приоритета вычисления. Операторы & и ! проверяют текст, но не убирают его. Оператор & проходит тогда, когда проходит, если выражение подходит. Оператор ! — наоборот. Альтернатива представляется оператором |. В отличие от РВ-грамматик, которые используют оператор /, из альтернатив выбирается наибольшая подходящая, а порядок альтернатив не влияет на их приоритет.

Примеры шаблонов.

Универсальный конец строки:
    "\r" "\n"? | "\n"
Список параметров:
    "(" (Value, ("," Value)*)? ")"
Комментарий в С:
    "//" (!EndOfLine .)*

Приоритеты

Приоритеты операций определяют порядок, в котором они будут выполнены при вычислении выражения. В математике и большинстве языков программирования операции * и / имеют больший приоритет, чем + и -. Вообще говоря, приоритеты можно описывать просто описывая грамматику, однако добавление новой операции в язык повлечет изменение других правил, причем, если эти правила были описаны в другом модуле, у программиста не будет возможности узнать, какие именно правила нужно менять. Поэтому Katahdin побуждает описывать операции естественным образом, определяя приоритеты потом, при помощи ключевого слова precedence:

class AddExpression : Expression {
    pattern {
        option leftRecursive;
        Expression '+' Expression
    }
}

class SubExpression : Expression {
    pattern {
        option leftRecursive;
        Expression '-' Expression
    }
}

precedence SubExpression = AddExpression;

class MulExpression : Expression {
    pattern {
        option leftRecursive;
        Expression '*' Expression
    }
}

class DivExpression : Expression {
    pattern {
        option leftRecursive;
        Expression '*' Expression
    }
}

precedence DivExpression = MulExpression;
precedence MulExpression > AddExpression;

Достоинства языка

Общая среда исполнения

В настоящее время написание системы на нескольких различных языках довольно затруднено. Для каждого языка требуется своя среда, которую необходимо выбрать, возможно, купить и установить. Каждая среда должна периодически обновляться и дополняться. При смене платформы, все среды должны быть портированы. Katahdin предоставляет единую среду для выполнения кода на различных языках. При смене платформы, должна быть портирована только среда Katahdin.

Простое взаимодействие языков

Взаимодействие между языками, исполняющимися в разных средах исполнения, естественным образом затруднено. Обмен информацией может быть осуществлен посредством создания канала чтения/записи. Доступ к коду (например, к функциям или типам) организовывается ещё сложнее, требуя использование таких инструментов, как CORBA или COM. В программе на Katahdin код и данные свободно разделяются между используемыми языками, не требуя связывания или ввода-вывода.

Пример использования языков FORTRAN и Python в одном исходном файле:

import "fortran.kat";
import "python.kat";

fortran {
    SUBROUTINE RANDOM(SEED, RANDX)

    INTEGER SEED
    REAL RANDX

    SEED = 2045*SEED + 1
    SEED = SEED - (SEED/1048576)*1048576
    RANDX = REAL(SEED + 1)/1048577.0
    RETURN

    END
}

python {
    seed = 128
    randx = 0

    for n in range(5):
        RANDOM(seed, randx)
        print randx
}

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

Например, программа на Фортране, предназначенная для вычислений, может плохо справляться с некоторой обработкой текста, требуемой при вводе-выводе. В этом месте лучше использовать более подходящий язык, например, Perl. В программе на Katahdin код, обрабатывающий текст и написанный на Perl, может быть использован в том же файле, что и программа на Фортране.

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

Дизайн

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

  • Свободная форма. Языки, такие как Python и Оккама устанавливают область видимости, используя правило вне стороны, где отступы увеличивается с глубиной области и выражения завершаются символом новой строки. Программисты либо любят, либо ненавидят этот стиль, так что его нет.
  • Фигурные скобки. Начиная с BCPL в 1960-х, фигурные скобки {} всегда используются, чтобы выразить область видимости в ведущих языках сегодня, в том числе в C, C ++, Java и C#. Почти все программисты имеют опыт работы с фигурными скобками.
  • Императивный. ПЭГ может быть задуман как императивная грамматики, так что естественно, что язык является также императивным. Большинство программистов знакомы с императивной парадигмой.
  • Объектно-ориентированный. Объектная ориентация - дизайн, хорошо понимаемый программистами и реализуется на многих языках. Как будет показано, конструкция грамматики Katahdin также может быть описана как объектно.
  • Динамически типизированных, также известный как типизация во время исполнения. Как и в большинстве интерпретируемых языках или скрипиах, Katahdin переменные и функции не типизированы. Объекты содержит свои типы в себе, и совместимость типа решается в точке выполнения оператора duck-typing. Объекты будут автоматически преобразованы между типами по мере необходимости. Katahdin должен поддерживать динамически и статически типизированные языки, и динамическая типизация оказалась наиболее общей для двух дисциплин типизации.

Язык программирования или генератор

Катадин - это язык программирования, а не генератор-парсер. Язык императивный, объектно-ориентированный, ducktyped и с фигурными скобками. Программисты, знакомые с C, Java, C#, Python или почти любым популярным императивным языком не должны иметь никаких проблем с использованием Katahdin. Новые конструкции языка определены как частный случай определения нового класса. Семантика конструкции реализованы путем определения методов в классе, используя существующие языковые конструкции. Этот класс является полным синтаксическим и смысловым определением нового оператора возведения в степень:

class Pow : Expression {
pattern {
a:Expression ‘∧’ b:Expression
}
method Get() {
return System.Math.Pow(@a.Get(),
@b.Get());
}
}

Метод Get () определен для всех выражений. Для реализации семантики оператора возведения мы вызываем Get () для обоих операндов, а затем вызываем метод библиотеки System.Math.Pow (). Методы каждой конструкции зависят от конвенции. Выражения имеют Get () и Set () методы. Если метод Set () не определен, то выражение не может быть назначено: реализация Set() по умолчанию выбрасывает исключение. Другие конструкции имеют соответствующие методы, например, все выражения имеют метод Run(). Этот класс показывает перегрузку метода Run() for-loop выражения:

class ForLoop : Statement {
pattern {
for ( init:Expression ;
cond:Expression ; inc:Expression )
body:Statement
}
method Run() {
init.Get();
while (cond.Get()) {
body.Run...();
inc.Get();
}
}
}

Body.Run ... (); обозначение выполняет вызов в области видимости вызывающего метода. Это связано с тем, что ссылки на переменные в теле цикла разрешены в области метода, который содержит цикл, а не в области метода ForLoop.Run ().

import ‘‘python.kat’’;
class PythonStatement : Statement {
pattern {
‘‘python’’ ‘‘{’’
statement:Python.Statement ‘‘}’’
}
method Run() {
statement.Run();
}
}

Пример

import ‘‘sql.kat’’;
class SqlExpression : Expression {
pattern {
option recursive = false;
database:Expression ?
statement:Sql.Statement
}
method Get() {
// Evaluate the operands
database = @database.Get...();
sql = @statement.Get...();
// Execute the command
command = database.CreateCommand();
command.CommandText = sql;
reader = command.ExecuteReader();
// Read each row into a list
rows = [];
while (reader.Read()) {
row = [];
for (n = 0; n < reader.FieldCount; n++)
row.Add(reader.GetValue(n));
rows.Add(row);
}
return rows;
}
}
children = contactDatabase? select name
from contacts where age < 18;

Ссылки

  1. Katahdin
  2. Growing A Syntax
  3. A language with extensible syntax

Автор статьи: Макаров Д. В.