]]> ]]>
Править | Обсудить | История

Hack VM

Парадигма:
Типизация:
Реализации и версии (свернуть все | развернуть все):
Язык программирования

Hack VM — миниатюрный язык программирования (хотя автор называет его “виртуальной машиной для хакеров”, он вполне заслуживает называться языком).

Hack VM был создан Adam Miller, и авторская реализация на двух языках остается единственной. Неизвестно, влияли ли на создание языка другие эзотерические языки, хотя это кажется вполне вероятным.

Основным и единственным назначением этого языка является его использование для решения заданий hacker.org, что делает его одним из немногих востребованных эзотерических языков программирования.

Программа на Hack VM представляет собой строку односимвольных команд. Виртуальная машина начинает с первой команды, выполняет ее, переходит на следующую и т.д. Индекс текущей команды называется счетчиком программы. Выполнение прекращается либо по достижении конца программы, либо по команде !, либо после возникновения ошибки. Счетчиком программы называется указатель на текущую команду.

Hack VM — стековый язык; виртуальная машина состоит из стека операндов, буфера памяти и стека вызовов. Каждый элемент стека операндов — 32-битное знаковое целое. Стек вызовов используется для запоминания значения счетчика программы при переходе на подпрограмму, из которой нужно будет возвращаться. Буфер памяти содержит 16384 ячеек, номера которых начинаются с 0. По умолчанию, выполнение программы начинается с пустым стеком вызовов, пустым стеком операндов и памятью, заполненной нулями. Буфер памяти можно заполнить значениями, определенными пользователем, и использовать их для имитации ручного ввода.

Список команд языка (S<n> означает n-ый элемент от верхушки стека; так, S0 — верхний элемент).

  • ' ': Не делать ничего (используется для улучшения читабельности)
  • 'p': Напечатать S0 как целое число
  • 'P': Напечатать S0 как ASCII-символ (используются только младшие 7 бит)
  • '0'..'9': Добавить значение 0..9 в стек
  • '+', '-', '*', '/': Добавить в стек S1+S0, S1-S0, S1*S0, S1/S0, соответственно
  • ':': Добавить в стек -1, если S1<S0, 0, если S1=S0, и 1, если S1>S0
  • 'g': Добавить S0 к счетчику программы
  • '?': Добавить S0 к счетчику программы, если S1=0
  • 'c': Добавить счетчик программы в стек вызовов и установить ему значение S0
  • '$': Установить счетчик программы равным вехрнему элементу стека вызовов
  • '<': Добавить в стек значение из ячейки памяти номер S0
  • '>': Записать S1 в ячейку памяти номер S0
  • '^': Добавить в стек копию S<S0+1> (например: 0^ копирует S0)
  • 'v': Удалить из стека S<S0+1> и добавить это значение в стек (например: 1v меняет местами S0 и S1)
  • 'd': Удалить из стека S0
  • '!': Остановить выполнение программы

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

Элементы синтаксиса:

Регистрозависимость да
Сравнение :

Примеры:

Hello, World!:

Пример для версий Miller's Hack VM (JavaScript), Miller's Hack VM (Python)

Программа работает довольно очевидным образом — ASCII-коды символов сообщения вычисляются и выводятся один за другим. Вычислять их приходится из-за того, что сразу помещать в стек можно только числа от 0 до 9, большие числа приходится комбинировать из меньших. Единственным нетривиальным приемом является обработка символа l — когда его ASCII-код вычисляется, он утраивается в стеке командой 0^ и выводится на печать два раза сразу же и один раз позднее.

89*P 45*99*+P 39*99*+0^0^PP 56*99*+P 29+4*P 48*P 92+8*1-P 56*99*+0^P 3+P P 25*0^*P 56*3+P

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

Пример для версий Miller's Hack VM (JavaScript), Miller's Hack VM (Python)

Этот пример использует итерацию и работает так же, как в других эзотерических языках: ячейка памяти 0 хранит оставшееся количество чисел для вычисления, ячейки 1 и 2 хранят ASCII-коды запятой и пробела, ячейки 3 и 4 — два последних рассчитанных числа Фибоначчи. В цикле извлекаются значения ячеек 3 и 4, суммируются, новое значение выводится на печать, а ячейки памяти обновляются. После этого количество оставшихся чисел уменьшается на 1, и если оно становится 0, счетчик программы (эквивалент указателя инструкций в Brainfuck) перемещается на 6 символов вперед и выходит из цикла, в противном случае он возвращается обратно к началу цикла. Наконец, выводятся три точки.

27*0> 92+4*1> 84*2> 10^p3> 1<P 2<P 10^p4> 1<P 2<P 3< 4< + 0^p 4< 3> 4> 0< 1- 0> 0<  6? 67*c 58*6+0^0^PPP

Факториал:

Пример для версий Miller's Hack VM (JavaScript), Miller's Hack VM (Python)

Этот пример очень похож на вычисление чисел Фибоначчи, только в каждой итерации приходится выводить больше символов. Поскольку тип данных имеет размер 32 бита, 13! вызывает ошибку переполнения:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
!ERROR: integer overflow

28*0> 56*3+1> 84*2> 78*5+3> 25*4> 05> 16> 5<p1<P2<P3<P2<P6<p4<P 5<1+5> 5<6<*6> 0<1-0> 0<6? 67*c 

Комментарии

]]>

blog comments powered by Disqus

]]>

Работа программистам