Однажды на лекции друг рассказал мне, что существует язык программирования пони, (основанный на сериале, конечно). Он сказал, что видел его на reddit, но даже после продолжительного поиска я смог найти только пустой репозиторий на Google Code без деталей реализации. Я был очень этим разочарован, но только на несколько минут, пока не понял, что могу написать реализацию этого языка сам. Возможно, она не будет хороша или вообще используема в том смысле, что не каждый сможет написать к ней интерпретатор, но мне хотелось проверить свои умения. А ещё мне нравятся затянувшиеся шутки.
Итак, я представляю вашему вниманию довольно сырую версию синтаксиса того, что я называю FiM++.
FiM++ является динамически типизированным, интерпретируемым, объектно ориентированным и полным по Тьюрингу языком для написании писем Принцессе Селестии от лица любой из пони (Я использовал Twilight для моей спецификации). Функции в языке форматируются как параграфы письма. Это сделано для того, чтобы код мог легко читаться и быть максимально похожим на письмо. Каждое такое письмо является классом, так что каждая программа может состоять из нескольких писем, если пользователь того захочет. Однако, минимально интерпретируемая единица — это класс, почти как в Java. Язык не поддерживает библиотеки, так как мы посылаем письма, а значит код должен быть максимально лёгким. Нужные типы данных могут определяться пользователем.
Каждый класс начинается с заголовка, который всегда одинаков:
Dear Princess Celestia: Letter One
Операторные скобки для частей кода были убраны, так как они нарушают формат письма, но могут быть использованы при желании пользователя.Они не будут упоминаться в дальнейшем, вместо них используются отступы, почти как в Python. «Princess Celestia» является зарезервированным ключевым словом для создания класса и поэтому всегда должна быть первым получателем. 'Letter One' — это название класса.
Интерфейсы могут быть добавлены в первую строку заголовка класса через запятую:
Dear Princess Celestia, and Princess Luna, and Princess Cadance: Letter One
Каждый интерфейс определяется параграфами (функциями), которые должны находиться внутри класса. Вызывается обычный класс так:
I wrote you another letter! It's titled Letter Two.
'Letter Two' теперь иллюстрируемый объект и может быть использован как таковой; например, он может быть использован для переноса функции из нового класса в текущий. В нём так же может быть объявлен объект для дальнейшего использования в коде:
I wrote you another letter!
// code
// code
Oh, about that other letter. It's titled Letter Two!
Функция «main» выглядит так:
Today I learned
// code
// code
Your faithful student, Twilight Sparkle.
Она никогда не принимает аргументов, таких как, например, аргументы командной строки. Возврат значения состоит из строки «Your faithful student, » и аргумента, коим является имя. Возврат значения может быть не нужен, в зависимости от интерпретатора.
Любая другая функция выглядит так:
I learned about ducks
// code
// code
Она вызывается по имени, в этом случае 'friendship'. Возврат значений не является строго необходимым и может быть проигнорирован. Конечно же функция может быть вызвана с параметрами:
I learned about friendship with Spike and Rarity
// code
// code
«Spike» и «Rarity» теперь могут быть использованы внутри функции. Все аргументы передаются магическим образом (так, на всякий случай).
Ключевое слово «I» работает как оператор «self» в большинстве языков. Однако он ссылается не на экземпляр класса, а на писателя письма. Он может быть определён где угодно.
Присваивание переменный выглядит так:
Did you know that Spike is a dragon?
В этом примере мы присваиваем переменной «Spike» строковое значение «dragon». У Spike также могло бы быть любое другое значение, а точный тип данных определяется во время выполнения программы.
Несмотря на то, что язык динамически типизирован, определённые проверки всё равно выполняются при операциях с двумя переменными. Если кто-то напишет что-то вроде «Pinkie Pie идёт на свидание с числом», то интерпретатор должен будет выдать исключение, в этом случае — RidiculousException.
Циклы в FiM++:
I did this 100 times…
// code
// code
Этого должно быть достаточно для того, чтобы написать интерпретатор данного языка. И ещё кое-что: зарезервированное ключевое слово «friendship» всегда должно интерпретироваться как «magic», иначе вы рискуете нарушить основы правила Вселенной, в которой находится Эквестрия.
Hello world
Dear Princess Celestia: Hello World!
Today I learned how to say Hello World!
I said “Hello World”!
That’s all about how to say Hello World!
Your faithful student, Twilight Sparkle.
Ссылки
Документ, в котором описана текущая спецификация языка
Простенький JavaScript интерпретатор
Пример кода: 99 Jugs of Cider