Разделы сайта находятся в разработке.

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

Иерархия кода

Области имён, модули и пакеты

Пространства имён

TrustLang поддерживает пространства имён; разделитель, как и в C++, — двойное двоеточие ::. Область имён может быть указана как для отдельного идентификатора, так и для целого блока кода.

В отличие от namespace в C++, области имён в TrustLang служат не только для организации кода логическими группами и избежания конфликтов имён: имя, в котором явно указана область имён, относится к статическим объектам (память под которые выделяется на этапе компиляции).

Глобальное имя не может быть перекрыто макросом или локальной переменной при разрешении имён (name lookup). Чтобы создать глобальную (статическую) переменную, достаточно записать её имя с глобальным квалификатором ::var. Пространство имён для блока кода указывают перед открывающей фигурной скобкой (ns:: { ... };).

::var := 0;    # глобальная переменная (не перекрывается макросом/локальной)

ns:: {          # область имён ns
    a:Int32 := 2;   # ns::a
    sub:: {         # вложенная область имён
        c:Int32 := 3;   # ns::sub::c
    };
};

Модули

TrustLang реализует программные модули и пакеты: идея иерархического расположения файлов в каталогах файловой системы (как в Python), но разделитель имён — не точка, а обратная косая черта \.

Имя модуля может содержать только строчные английские буквы, цифры и символ подчёркивания (кроме первой и последней позиций). Ограничение связано с прямым отображением имён модулей на объекты файловой системы: у разных файловых систем могут различаться кодировки и требования к регистру.

Под модулем понимается файл с исходным кодом (расширение *.src). Модули хранят часто используемые функции, классы, константы и т. п. Их условно делят на модули и программы: программы предназначены для непосредственного запуска, модули — для импорта в другие программы (функционально они не отличаются).

Объекты модуля

Все объекты, определённые внутри одного модуля без указания глобального пространства имён, видны только в рамках текущего файла и в модулях, подключённых после его определения.

Время жизни статических и локальных переменных верхнего уровня модуля одинаково и ограничено временем жизни самого модуля, но для многопоточности они различаются: статическая переменная модуля всегда существует в единственном экземпляре для всех потоков, а локальная переменная модуля — своя для каждого потока (аналог thread_local в C++11).

Импорт модулей

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

Проще всего импортировать модуль, записав его имя со скобками как вызов функции; в скобках можно передать аргументы инициализации модуля, список импортируемых функций и т. д. Если перед именем модуля стоит символ препроцессора (@\dir\module()), модуль импортирует не только код, но и свои макросы (только при статической загрузке).

Загрузка модулей возможна статически или динамически (по аналогии со статической и динамической линковкой библиотек):

  • \dir\module() — статическая загрузка по относительному пути;
  • @\dir\module() — статическая загрузка с импортом макросов;
  • \\root\dir\module() — статическая загрузка по абсолютному пути;
  • \( "каталог\файл" ) — динамическая загрузка во время выполнения (при динамической линковке макросы импортировать нельзя).

При динамической загрузке компиляция модуля и все проверки выполняются во время выполнения приложения; статическая загрузка позволяет выявить возможные ошибки на этапе компиляции.

Помимо импорта по исходному тексту, TrustLang описывает семантический ABI — способ представления скомпилированного модуля, при котором бинарные символы связаны с типизированным семантическим определением, а сопоставление объектов выполняет компилятор языка. Принцип описан в Семантическом ABI модулей.

Пакеты

Пакет — это каталог, который включает другие каталоги и модули и содержит дополнительный файл __init__.src. Пакеты используются как дополнение к пространствам имён и позволяют работать с модулями через указание уровня вложенности. В отличие от Python и Java, где модули/пакеты заменяют пространства имён, в TrustLang модульная структура и области имён используются одновременно и при указании полного имени объединяются: \root\dir\module::ns::name::var, где root и dir — каталоги относительно текущего модуля, module — имя файла (root/dir/module.src).

Файл __init__.src, в отличие от Python, не может быть пустым — он должен в явном виде загружать входящие в пакет модули:

\simper();
\compper();
\annuity();

Импорт пакетов использует тот же синтаксис, что и импорт модулей. Пример пакета fincalc (__init__.src + модули simper.src, compper.src, annuity.src):

\fincalc();                 # импорт всего пакета
\fincalc\simper();          # импорт одного модуля
sp := \fincalc\simper();    # импорт модуля с псевдонимом
\fincalc\simper(__import__="fv");  # импорт конкретной функции

Пространства имён и классы

В TrustLang не применяется декорирование (манглинг) имён по типам аргументов. Методы классов (когда ООП будет реализовано) получают уникальные идентификаторы по аналогии с Python: глобальная функция с именем класса и метода, объединёнными через :: (для класса :NewClass и метода method — NewClass::method). Это позволяет определять методы класса вне тела класса, указав нужное имя в пространстве имён. Полноценное ООП в текущей версии не реализовано (см. Классы и Статус).