LoveScript

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

Общие понятия

Холст, которым оперирует LoveScript, имеет квадратное соотношение сторон. На холсте введена декартова система координат: ось X направлена слева направо, а ось Y — сверху вниз. Центр координат расположен в левом верхнем углу. Правый нижний угол имеет координаты (1, 1). Все размеры также указываются в этих координатах, таким образом, size = 1 обозначает объект размером в 100% холста.

Синтаксис языка

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

Стартовый символ

  <start> ::= <list>

Программа является списком операторов.

Список операторов

  <list> ::= <statement> <list> | ε

Список операторов (statement) может состоять из:

  • одного оператора , за которым может следовать список операторов;
  • либо быть пустым (ε).

Оператор (statement)

  <statement> ::= <for> | <if> | <using> | <call> | <comment>

Оператор может быть:

  • циклом for,
  • условным оператором if (с возможным блоком else),
  • блоком using,
  • вызовом функции,
  • комментарием

Цикл for

  <for> ::= 'for' '(' 'let' <identifier> 'from' <number> 'to' <number> ')' '{' <list> '}'

Правило описывает цикл for, который имеет следующую структуру:

  1. Ключевое слово for.
  2. В круглых скобках: объявление переменной через let, за которым следует имя переменной, ключевые слова from и to с указанием начального и конечного значения.
  3. Тело цикла заключено в фигурные скобки, внутри которых содержится список операторов.

Пример:

  for (let i from 1 to 10) {
    ...
  }

Условный оператор if

  <if> ::= 'if' '(' <expression> ')' '{' <list> '}' 
           [ 'else' '{' <list> '}' ]?

Условная конструкция начинается со слова if, за которым в круглых скобках указывается выражение. Затем следует блок оператора if (тело if) в фигурных скобках. Необязательная часть else, также заключённая в фигурные скобки, выполняется, если условие ложно.

Пример:

  if (i % 2 == 0) {
    ...
  } else {
    ...
  }

Блок using

  <using> ::= 'using' '(' <expression> ')' '{' <list> '}'

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

Пример:

  using (blendMode(value = 'multiply')) {
    ...
  }

Выражения

  <expression> ::= <call> | 
                   <expression> '?' <expression> ':' <expression> |
                   <identifier> | <string> | <number> |
                   '(' <expression> ')' |
                   <expression> ('==' | '!=' | '>=' | '>' | '<=' | '<' | '+' | '-' | '/' | '*' | '%') <expression>

Выражение может содержать

  • вызов функции
  • тернарный оператор
  • идентификатор
  • строковый литерал
  • числовой литерал
  • другое выражение в скобках
  • бинарный оператор применённый к двум выражениям.

Приоритет операторов (упорядочены от самого низкого, до самого высокого):

  1. Тернарный оператор
  2. ==, !=
  3. >=, >, <=, <
  4. +, -
  5. /, *, %

Вызов функции

  <call> ::= <identifier> '(' <arguments> ')'

Вызов функции начинается с идентификатора функции, за которым следуют круглые скобки с аргументами.

Аргументы функции

  <arguments> ::= <argument> [, <argument>]* | ε

Аргументы — это список аргументов, разделённых запятой. Список аргументов может быть пустым.

  <argument> ::= <identifier> '=' <expression>

Каждый аргумент имеет вид: имя параметра (идентификатор), знак «=» и значение (выражение).

Строковые литералы

  <string> ::= "'" <string_contents> "'"

Строка заключается в одинарные кавычки.

  <string_contents> ::= <string_char>*

  <string_char> ::= [^\\'] | ('\\' .)

Внутри строки могут присутствовать любые символы, за исключением одинарной кавычки и обратного слэша (если они не экранированы).

Числовые литералы

  <number> ::= '-'? [0-9]* '.' [0-9]+ | '-'? [0-9]+ ('.' [0-9]+)?

Число состоит из опционального знака «-» в начале, далее идут опциональные целая часть и дробная часть, однако либо целая часть, либо дробная часть обязательно должны быть.

Идентификаторы

  <identifier> ::= [a-zA-Z_][a-zA-Z_0-9]*

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

Комментарии

  <comment> ::= '//' [^\n]*

Комментарии начинаются с двух символов косой черты // и продолжаются до конца строки. Комментарии игнорируются при выполнении программы и используются для пояснений в коде.

Пример:

// Это комментарий
fill(bg = solidBackground(color = 'pink'))  // Заливаем фон розовым цветом

// Рисуем сердце в центре
heart(
  bg = solidBackground(color = 'red'),
  size = 0.5
)

Типы данных

number

Числа представлены в виде 64-битного формата IEEE-754.

color

Описывает цвет. На уровне программы описывается как строковый литерал, содержащий цвет в hex формате, либо как строковый литерал описывающий один из заранее заготовленных цветов:

'transparent'
'red'
'green'
'blue'
'yellow'
'pink'
'black'
'white'

bg

Описывает фон. Напрямую задать в виде литерала нельзя, можно только получить его из функции.

using

Описывает глобальные настройки. Напрямую задать в виде литерала нельзя, можно только получить его из функции. Для применения настроек необходимо передать их в блок using

Доступные функции

radialGradient

  • Описание: Возвращает фон с радиальным градиентом состоящим из двух цветов: начального (start) и конечного (end).
  • Аргументы:
    • start (color, обязательный): Начальный цвет градиента.
    • end (color, обязательный): Конечный цвет градиента.
  • Возвращает: bg

linearGradient

  • Описание: Возвращает фон с линейным градиентом состоящим из двух цветов: начального (start) и конечного (end), а также с углом наклона (angle).
  • Аргументы:
    • start (color, обязательный): Начальный цвет градиента.
    • end (color, обязательный): Конечный цвет градиента.
    • angle (number, обязательный): Угол наклона градиента в градусах против часовой стрелки.
  • Возвращает: bg

solidBackground

  • Описание: Возвращает одноцветный фон.
  • Аргументы:
    • color (color, обязательный): Цвет фона.
  • Возвращает: bg

pattern

  • Описание: Добавляет на задний план шаблоны указанного цвета.
  • Аргументы:
    • type (string, обязательный): Тип шаблона. Допустимые значения: 'triangle', 'circle', 'rhomb', 'heart', 'flower', 'star', 'square'.
    • color (color, обязательный): Цвет шаблона.
    • size (number, обязательный): Размер элемента шаблона (от 0.01 до 1).
    • space (number, обязательный): Пробел между элементами (от 0 до 1).
    • angle (number): Угол наклона шаблона.
    • distortion (number): Искажение элементов (от 0 до 100).
    • distortionSize (number): Размер области искажения (от 0.001 до 100).
    • speed (number): Скорость анимации искажения (от 0 до 50).
  • Возвращает: void

fill

  • Описание: Заполняет задний план фоном (bg).
  • Аргументы:
    • bg (bg, обязательный): Объект фона.
  • Возвращает: void

heart

  • Описание: Рисует сердце, используя фон (bg) и размер. Используйте параметр mode для переключения между режимами "shape" (по умолчанию) и "dots". В режиме dots вместо формы сердца рисуются круги в вершинах.
  • Аргументы:
    • bg (bg, обязательный): Объект фона.
    • size (number, обязательный): Размер сердца (от 0 до 2).
    • x (number): Позиция по оси X.
    • y (number): Позиция по оси Y.
    • vertices (number): Количество вершин (от 3 до 64).
    • distort (number): Искажение формы (от 0 до 10).
    • borderWidth (number): Толщина границы (от 0 до 0.2).
    • borderColor (color): Цвет границы.
    • mode (string): Режим отрисовки. Допустимые значения: 'shape', 'dots'.
    • dotSize (number): Размер точек в режиме dots (от 0 до 0.5).
  • Возвращает: void

alpha

  • Описание: Устанавливает глобальную прозрачность для всех элементов в процентах.
  • Аргументы:
    • value (number, обязательный): Значение прозрачности (от 0 до 100).
  • Возвращает: using

blendMode

  • Описание: Устанавливает глобальную операцию композиции, определяемую значением (value).
  • Аргументы:
    • value (string, обязательный): Режим смешивания. Допустимые значения: 'source-over', 'lighter', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light', 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity'
  • Возвращает: using

transform

  • Описание: Устанавливает глобальное преобразование для всех элементов. Доступные преобразования: translateX, translateY, rotate, scale, skew, skewX, skewY. Все преобразования применяются относительно центра холста (0.5, 0.5).
  • Аргументы:
    • translateX (number): Смещение по оси X.
    • translateY (number): Смещение по оси Y.
    • rotate (number): Поворот по часовой стрелке. Указывается в градусах.
    • scale (number): Изменяет масштаб.
    • scaleX (number): Изменяет масштаб вдоль оси X.
    • scaleY (number): Изменяет масштаб вдоль оси Y.
    • skew (number): Аналогично skewX (от -85 до 85).
    • skewX (number): Искажает элемент сдвигая его части вдоль оси X. Указывается в градусах (от -85 до 85).
    • skewY (number): Искажает элемент сдвигая его части вдоль оси Y. Указывается в градусах (от -85 до 85).
  • Возвращает: using

rgb

  • Описание: Комбинирует численные значения красного, зелёного и синего в один цвет
  • Аргументы:
    • r (number, обязательный): Красная компонента (от 0 до 255).
    • g (number, обязательный): Зелёная компонента (от 0 до 255).
    • b (number, обязательный): Синяя компонента (от 0 до 255).
    • a (number): Альфа канал (от 0 до 1).
  • Возвращает: color

hsl

  • Описание: Комбинирует численные значения тона, насыщенности и светлоты в один цвет
  • Аргументы:
    • h (number, обязательный): Тон (от 0 до 360).
    • s (number, обязательный): Насыщенность (от 0 до 100).
    • l (number, обязательный): Светлота (от 0 до 100).
    • a (number): Альфа канал (от 0 до 1).
  • Возвращает: color

mix

  • Описание: Смешивает два цвета в заданной пропорции (линейная интерполяция). Полезно для создания плавных переходов между цветами.
  • Аргументы:
    • color1 (color, обязательный): Первый цвет.
    • color2 (color, обязательный): Второй цвет.
    • ratio (number, обязательный): Пропорция смешивания (от 0 до 1). При 0 возвращается color1, при 1 — color2.
  • Возвращает: color

Функции анимации

animate

  • Описание: Возвращает значение от 0 до 1 на основе времени с функцией сглаживания (easing). Используется для создания анимаций.
  • Аргументы:
    • duration (number, обязательный): Длительность анимации в секундах (минимум 0.01).
    • easingCurve (string): Кривая сглаживания. Допустимые значения: 'linear', 'quad', 'cubic', 'quart', 'back', 'elastic', 'bounce', 'heartbeat'.
    • easingMode (string): Режим сглаживания. Допустимые значения: 'in', 'out', 'in-out'. Игнорируется для heartbeat.
    • loop (string): Режим цикла. Допустимые значения: 'repeat', 'mirror'.
    • offset (number): Задержка начала анимации в секундах (минимум 0).
  • Возвращает: number

Пример:

heart(
  bg = solidBackground(color = 'red'),
  size = 0.3 + animate(duration = 1, easingCurve = 'heartbeat') * 0.1
)

map

  • Описание: Преобразует значение из одного диапазона в другой. Полезно для масштабирования значений анимации.
  • Аргументы:
    • value (number, обязательный): Значение для преобразования.
    • inMin (number): Минимум входного диапазона (по умолчанию 0).
    • inMax (number): Максимум входного диапазона (по умолчанию 1).
    • outMin (number, обязательный): Минимум выходного диапазона.
    • outMax (number, обязательный): Максимум выходного диапазона.
  • Возвращает: number

Пример:

heart(
  bg = solidBackground(color = 'red'),
  size = map(value = animate(duration = 2), outMin = 0.2, outMax = 0.5)
)

sin

  • Описание: Возвращает синус угла в градусах (те же единицы, что и rotate). Полезно для создания круговых движений и волновых паттернов.
  • Аргументы:
    • angle (number, обязательный): Угол в градусах.
  • Возвращает: number

cos

  • Описание: Возвращает косинус угла в градусах (те же единицы, что и rotate). Полезно для создания круговых движений и волновых паттернов.
  • Аргументы:
    • angle (number, обязательный): Угол в градусах.
  • Возвращает: number

Пример кругового движения:

for (let i from 0 to 5) {
  heart(
    bg = solidBackground(color = 'red'),
    size = 0.1,
    x = 0.5 + cos(angle = i * 60 + animate(duration = 2) * 360) * 0.3,
    y = 0.5 + sin(angle = i * 60 + animate(duration = 2) * 360) * 0.3
  )
}

Функции звука

audio

  • Описание: Определяет аудио-трек с использованием ABC-нотации. Не отображает ничего на холсте. ABC-нотация — это текстовый формат для записи музыки.
  • Аргументы:
    • abc (string, обязательный): Тело ABC-нотации (ноты и ритм).
    • key (string): Тональность (по умолчанию: C). Например: 'C', 'G', 'Am', 'F#m'.
    • tempo (number): Темп в ударах в минуту (от 1 до 300).
    • play (string): Режим воспроизведения. Допустимые значения: 'loop', 'single'.
    • unitNoteLength (string): Базовая длительность ноты. Например: '1/4', '1/8'.
    • instrument (string): Инструмент. Допустимые значения: 'piano', 'bass', 'pad', 'lead', 'pluck', 'flute', 'bell', 'hearth', 'synth', 'snare', 'hihat', 'kick', 'guitar', 'chip', 'organ'.
    • offset (number): Смещение начала воспроизведения в секундах (минимум 0).
  • Возвращает: void

Пример:

audio(
  abc = 'CDEF GABc|',
  tempo = 120,
  instrument = 'piano',
  play = 'loop'
)

Основы ABC-нотации:

  • Ноты записываются буквами: C D E F G A B (заглавные — нижняя октава), c d e f g a b (строчные — верхняя октава)
  • Длительность: C2 — половинная, C/2 — восьмая, C — четвертная
  • Паузы: z (четвертная пауза), z2 (половинная пауза)
  • Тактовая черта: |

volume

  • Описание: Возвращает текущий уровень громкости аудио от 0 до 1. Полезно для создания аудио-реактивных визуализаций, которые реагируют на музыку.
  • Аргументы: нет
  • Возвращает: number

Пример аудио-реактивной визуализации:

audio(
  abc = 'C2 E2 G2 c2|',
  tempo = 120,
  instrument = 'piano',
  play = 'loop'
)

heart(
  bg = solidBackground(color = 'red'),
  size = 0.3 + volume * 0.2
)