Micro — интерпретируемый высокоуровневый язык программирования. Поддерживает функциональную парадигму, обладает сильной полустатической типизацией и сборкой мусора.
Файлы исходного кода должны быть в кодировке ASCII и иметь концы строк как в UNIX (LF).
3 ключевых слова: fn, let, as.
Типизация: сильная полустатическая.
Менеджмент памяти: сборка мусора.
Копирование: по ссылке.
Хранение:
- ссылки — на стеке;
- значения — в куче.
Название: nil.
Тип: фиктивный тип; не хранит значение, а служит маркером его отсутствия; существует единственное значение данного типа.
Определение: значение данного типа доступно через вызов функции рантайма nil.
Название: num.
Тип: с плавающей запятой, 8 байт.
Определение:
/\d+(\.\d+)?(e-?\d+)?/
/0x[A-Fa-f0-9]+/
/'(\\.|\\x[A-Fa-f0-9]{2}|[^'])'/
Название: list.
Тип: LISP-подобный список — или пустой список, или пара из головы и хвоста, где голова может иметь любой тип (и является хранимым элементом), а хвост является аналогичным списком.
Определение:
- пустого списка — через вызов функции рантайма
[]; - списка из головы и хвоста — через вызов функции рантайма
,.
Доступ к элементам:
- к количеству элементов — через вызов функции рантайма
size; - к голове списка — через вызов функции рантайма
head; - к хвосту списка — через вызов функции рантайма
tail; - к элементу по индексу — через вызов функции рантайма
..
Строками являются списки, хранящие коды символов. Используется кодировка ASCII.
Определение: /"(\\.|\\x[A-Fa-f0-9]{2}|[^"])*"/.
Название: hash.
Тип: ассоциативный массив, реализованный через хеш-таблицу; порядок ключей не гарантируется.
Определение:
- пустой хеш-таблицы — через вызов функции рантайма
{}; - новой хеш-таблицы из старой и пары ключа и значения — через вызов функции рантайма
#; - новой хеш-таблицы из старой без определённого ключа — через вызов функции рантайма
#.
Доступ:
- к количеству пар ключей и значений — через вызов функции рантайма
size; - к списку ключей — через вызов функции рантайма
keys; - к значению по ключу — через вызов функции рантайма
..
Название: pack.
Тип: обёртка над значением; единственное предназначение — остановка автоматического вызова замыканий нулевой арности.
Определение: оборачивание значения в пак доступно через вызов функции рантайма >@.
Доступ к обёрнутому значению:
- однократный доступ (на один уровень вглубь) — через вызов функции рантайма
<@; - итеративный доступ (на максимальный уровень вглубь) — через вызов функции рантайма
<<@; функция итеративно разворачивает значение до тех пор, пока результат является обёрнутым значением.
Название: closure.
Объявление:
"fn", [identifier], "(", {identifier, {":", INTEGRAL NUMBER}}, ")", {":", INTEGRAL NUMBER},
{entity},
";"
Здесь первый identifier — имя замыкания, по которому оно будет доступно ниже в текущей области видимости, а также внутри самого себя, а все последующие identifier — имена аргументов замыкания.
{":", INTEGRAL NUMBER} — определение типа аргументов замыкания и результата замыкания (в последнем случае). Тип указывается только для замыканий (полустатическая типизация) и является списком арностей этих замыканий и их результатов.
Перегрузка замыканий не поддерживается, но поддерживается их переопределение.
Вызов замыкания: entity, entity, {entity}.
Здесь первая entity — идентификатор, являющийся замыканием, или аналогичный вызов замыкания (вложенный вызов), возвращающий замыкание, а все последующие entity — аргументы.
В качестве значений логического типа используются значения других типов:
- ложным логическим значением являются:
- значение
nil; - число 0;
- пустой список;
- пустые хеш-таблицы;
- значение
- истинным логическим значением являются:
- числа, отличные от 0;
- непустые списки;
- непустые хеш-таблицы;
- любые паки;
- любые замыкания.
"let", [identifier], {":", INTEGRAL NUMBER},
{entity},
";"
Здесь identifier — имя переменной, по которому она будет доступна ниже в текущей области видимости. При этом внутри определения самой себя она доступна не будет.
{":", INTEGRAL NUMBER} — определение типа переменной. Тип указывается только для замыканий (полустатическая типизация) и является списком арностей этих замыканий и их результатов.
Присваивание переменным нового значения не поддерживается, но поддерживается переопределение переменных.
"as", "(", {entity}, ")", {":", INTEGRAL NUMBER}
В качестве условного оператора используется функция рантайма if:
"if", condition,
true value,
false value
Здесь:
condition— это вызов замыкания; его результат трактуется как значение логического типа;true value— это вызов замыкания; его значение возвращается, если результатconditionявляется истинным логическим значением;false value— это вызов замыкания; его значение возвращается, если результатconditionявляется ложным логическим значением.
Стоит учесть, что и true value, и false value вычисляются до выбора значения результата. Поэтому, если их вычисление производит побочные эффекты, нужно обернуть их в замыкания:
if condition
fn() true value;
fn() false value;
Отсутствует.
Отсутствует. Интерпретатор исполняет весь предоставленный код в порядке его следования.
Шебанг: /^#!.*/.
Однострочные: /(?<![A-Za-z_])nb(?![:A-Za-z_]).*/.
Многострочные: /(?<![A-Za-z_])nb:.*?(?<![A-Za-z_])nb;/s.
Тип: включением кода как текста и его последующим исполнением.
Для включения кода используется функция рантайма load:
load filename
Здесь filename — это вызов замыкания, результат которого должен быть строкой и содержать относительный путь к файлу с кодом.
Функция ищет указанный файл, читает его и исполняет, после чего возвращает полученный результат.
Функция кеширует свой результат по абсолютному пути к указанному файлу. Таким образом каждый конкретный файл исполняется только один раз, вне зависимости от того, сколько раз он загружался.
Поиск указанного файла осуществляется в несколько этапов. Функция по очереди перебирает следующие возможные места расположения файла:
- директория того скрипта, из которого был осуществлён вызов функции
load; - директория
vendor, расположенная в директории того скрипта, который был передан интерпретатору; - директории, указанные в переменной окружения
MICRO_LIBRARY(перечисляются через символ:; перебираются в обратном порядке); - директория установки pip-пакета интерпретатора.
В каждом месте расположения функция по очереди пытается найти следующие файлы:
- файл, непосредственно указанный в функции
load; - файл, указанный в функции
load, с добавленным расширением.micro; - файл
__main__.micro, лежащий в директории, указанной в функцииload.
Интерпретатор поддерживает шебанг (то есть игнорирует его). Шебанг может выглядеть, например, так: #!/usr/bin/env micro.
