Whitespace - Енциклопедія мов програмування

Whitespace — популярна езотерична мова програмування, відома тим, що вихідний код програми складається лише з символів, що не друкуються.

Усі команди мови складаються з трьох типів символів: пробіл (Space, ASCII 32), табуляція (Tab, ASCII 9) та новий рядок (LF, ASCII 10). Самі команди досить довгі (зазвичай 3-4 символи), та їх чимало; вони систематизовані за допомогою використання префікса (т.зв. параметр модифікації інструкції), який означає тип команди: операції зі стеком, арифметика, доступ до купи, керування потоком виконання програми, введення/виведення.

Віртуальна машина мови оснащена стеком та купою, які можуть обробляти цілі числа довільної розрядності. Стек використовується виконання команд, а купа грає роль сховища даних.

У мові використовується лише один тип даних – цілі числа у двійковому поданні. Число починається із завдання його знака (Space - позитивне, Tab - негативне), потім слідує двійковий запис абсолютного значення числа (Space - 0, Tab - 1) і LF, що сигналізує про кінець числа.

Мітка – це довільний список пробілів та знаків табуляції, що закінчується перекладом рядка. Мітки використовуються в управлінні потоком виконання програми і повинні бути унікальні в межах програми.

Команди мови (згруповані за типом):

Операції зі стеком

  • Space-Space-Number : додати число до стек
  • Space-LF-Space: продублювати число на вершині стека
  • Space-LF-Tab : поміняти місцями два верхні елементи стека
  • Space-LF-LF : витягти з стека верхній елемент та викинути його
  • Space-Tab-Space-Number : скопіювати N-ий елемент стека (індекс задається аргументом) на вершину стека
  • Space-Tab-LF-Number :"зрушити" зі стека N елементів, зберігаючи при цьому верхній

Дві останні команди — розширення, доступне з Whitespace 0.3, призначене для спрощення роботи з рекурсивними функціями.

Арифметика

  • Tab-Space-Space-Space : додавання
  • Tab-Space-Space-Tab : віднімання
  • Tab-Space-Space-LF : множення
  • Tab-Space-Tab-Space : поділ (цілочисленний)
  • Tab-Space-Tab-Tab : залишок від розподілу

Операція застосовується до двох верхніх елементів стеку. Лівим операндом вважається більш ранній елемент стеку (доданий першим).

Доступ до купи

Управління потоком виконання програми

  • LF-Space-Space-Label: створити мітку
  • LF-Space-Tab-Label : викликати підпрограму
  • LF-Space-LF-Label : перейти до мітки
  • LF-Tab-Space-Label : перейти до мітки, якщо верхній елемент стека дорівнює нулю
  • LF-Tab-Tab-Label : перейти до мітки, якщо верхній елемент стека негативний
  • LF-Tab-LF : закінчити підпрограму і передати управління програмі, що викликала її
  • LF-LF-LF: закінчити програму

Ввід вивід

Слід зазначити, що з використанням елементів стека у виконанні команд здебільшого вони видаляються зі стека.

Hello, World!:

Купа використовується для зберігання змінних: 1 — перше число, факторіал якого не потрібен, 2..5 — ASCII коди символів, що використовуються при виведенні на друк, 6 і 7 — поточне число та його факторіал. Сам факторіал обчислюється ітеративно: на кожній ітерації друкуються раніше обчислене число та факторіал, потім обчислюються та заносяться на згадку нові. Після цього, нове число (осередок 6) порівнюється з осередком 1: якщо число менше, цикл повторюється, інакше припиняється.

Цікаво, що в Whitespace нуль "негативний": число має містити в записі хоча б один Tab, у двійковому записі нуля одиниць немає, тому доводиться ставити знаковий біт і записувати нуль як Tab-LF.

Числа Фібоначчі:

Приклад працює аналогічно факторіалу, але інтенсивніше використовує зберігання даних у стеку та команду копіювання верхнього елемента стека, щоб уникнути зайвих звернень до пам'яті. Крім того, у цьому прикладі лічильник негативний і збільшується на кожній ітерації.