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.
Числа Фібоначчі:
Приклад працює аналогічно факторіалу, але інтенсивніше використовує зберігання даних у стеку та команду копіювання верхнього елемента стека, щоб уникнути зайвих звернень до пам'яті. Крім того, у цьому прикладі лічильник негативний і збільшується на кожній ітерації.