Вдохновившись проектом Google Glass, я подумал, как хорошо было бы сделать крайне простой, но мощный инструмент дополненной реальности специально для таких очков. И почему бы не сделать его на основе такой широко используемой технологии как QR-коды. Так родилась задумка языка QuRava — набора байтов, записанных в QR-коде и интерпретируемого в полноценную программу, реализующую часть возможностей языка Java.
Хочу сразу предупредить, что все нижеизложенное — альфа-версия, сделано за несколько вечеров. Поэтому по поводу маленьких возможностей сильно не ругайтесь и вопросов про отсутствие лямбда-исчисления не задавайте.
Как мне кажется, большинство инструментов дополненной реальности напрочь оторваны от реальности. Они красивые, интересные, но бесполезны для практического применения. И мне захотелось сделать технологию, которая была бы крайне проста и удобна для повседневного пользования. Лучшее, что пришло на ум — это встроить интерпретируемый язык в QR-коды. Они уже широко распространены, и не вызывают у людей отторжения. Их можно распечатать и прилепить в любое место, будь то столик кафе или витрина магазина. Они считываются почти мгновенно, и поэтому с помощью Google Glass можно будет отображать программы в реальном времени.
Плюсы такого подхода очевидны:
Но есть и минусы:
В QR-коды информация записывается с помощью последовательности участков по 8 бит каждый. Поэтому язык я решил создать на основе байтового исчисления, то бишь на основе шестнадцатеричных символов от 00 до FF. Сначала в голову пришла идея записи в штрих-код байт-кода Java, но я отказался от нее из-за избыточности данного подхода. Интерпретируемый язык для QR должен быть очень краток, так штрих-код может содержать в себе в лучшем случае лишь 2 килобайта памяти. Да и много возможностей этому языку много не надо.
Пока что в языке используются лишь три вида конструкций: переменные, процедуры и компоненты Андроид. У каждого объекта этих трех типов есть свой подтип (например, для переменных это 00-boolean, 01 — int, 02-float, 03-String), однобайтовое имя и тело. Для удобство парсера перед каждой конструкцией ставится байт длины.
Например в синтаксической конструкции {
В процедурах же задается список примитивных операций. Например {
Так как Google Glass еще не вышли, то я написал программу-интерпретатор под Андроид. Поэтому в QuRavе сейчас поддерживаются именно компоненты Андроид. Пока что только Button, TextView и Edit Text. Можно задать их положение на экране, текст на них, а для кнопок добавить указание на процедуру, вызываемую при нажатии. Например, {
Если честно, сейчас синтаксис выглядит просто ужасно. Он чертовски сложен и имеет очень мало возможностей. Но это же просто прототип. В будущем планирую распихать все примитивные операции по библиотекам, сделав более короткой и удобной их конструкцию. Еще нету возможности вызывать процедуру из другой процедуры, что обусловлено глупо написанным компилятором. Сейчас кстати о нем.
Основной парсер интерпретатора читает программу, разбивает ее на куски и рассылает их субпарсерам, которые в свою очередь могут иметь свои субпарсеры. На основе результатов работы многочисленных парсеров программа по кусочкам собирается на не менее малочисленных фабриках. Готовые процедуры, переменные и компоненты попадают в класс Main.
В классе Main все содержится в отдельных HashMap'ах. Примером такой HashMap'ы является namesOfVariables:
А чтобы доступ к переменным и компонентам был из процедур и примитивных операций, класс Procedure является наследником класса ProgramUnit (на рисунке обозначен как Main), а примитивная операция расширяет класс Procedure.
В классе процедуры переопределен метод взятия переменной. Добавив к нему еще пару строк, можно реализовать механизм локальных переменных.
Если честно, то интерпретатор самая скучная часть сделанного, поэтому хватит о нем.
А сейчас покажу Вам то, ради чего Вы собственно и начали читать эту статью. Пример действующей программы на языке QuRava.
В данном примере использованы числа типа byte, а не их hex-эквиваленты!
Ну и собственно демонстрация работы: (извините за качество)
Сейчас я показал Вам лишь альфа-версию прототипа того, что я хочу сделать. В будущем я бы хотел добавить много интересных вещей в язык QuRava:
К сожалению пока что показывать еще почти нечего, поэтому не выложу никаких ссылок. Если будет интересно, то поработаю над этим и напишу еще одну статью.
А пока что хочу провести опрос.
Хочу сразу предупредить, что все нижеизложенное — альфа-версия, сделано за несколько вечеров. Поэтому по поводу маленьких возможностей сильно не ругайтесь и вопросов про отсутствие лямбда-исчисления не задавайте.
1. Предназначение
Как мне кажется, большинство инструментов дополненной реальности напрочь оторваны от реальности. Они красивые, интересные, но бесполезны для практического применения. И мне захотелось сделать технологию, которая была бы крайне проста и удобна для повседневного пользования. Лучшее, что пришло на ум — это встроить интерпретируемый язык в QR-коды. Они уже широко распространены, и не вызывают у людей отторжения. Их можно распечатать и прилепить в любое место, будь то столик кафе или витрина магазина. Они считываются почти мгновенно, и поэтому с помощью Google Glass можно будет отображать программы в реальном времени.
Плюсы такого подхода очевидны:
- нужна лишь программа-интерпретатор и сам QR-код, не нужно никакого дополнительного оборудования
- стандартизированность интерфейсов; людям не нужно обучаться заново каждый раз
- огромные потенциальные возможности: например, можно сделать заказ в кафе, посмотрев на столик, или заказать билеты на рок-концерт, посмотрев на афишу
- элементарная простота и дешевизна создания и распространения программок
Но есть и минусы:
- маленький размер программы. Решается выкачкой дополнительной логики по сети
- возможно легче было бы скачивать из интернета по QR-ссылке код на каком-нибудь скриптовом языке, хоть это и медленнее
- вспоминается роман Стивенсона «Лавина», в котором люди, посмотрев на черно-белое изображение, плавили себе мозги
2. Структура языка
В QR-коды информация записывается с помощью последовательности участков по 8 бит каждый. Поэтому язык я решил создать на основе байтового исчисления, то бишь на основе шестнадцатеричных символов от 00 до FF. Сначала в голову пришла идея записи в штрих-код байт-кода Java, но я отказался от нее из-за избыточности данного подхода. Интерпретируемый язык для QR должен быть очень краток, так штрих-код может содержать в себе в лучшем случае лишь 2 килобайта памяти. Да и много возможностей этому языку много не надо.
Пока что в языке используются лишь три вида конструкций: переменные, процедуры и компоненты Андроид. У каждого объекта этих трех типов есть свой подтип (например, для переменных это 00-boolean, 01 — int, 02-float, 03-String), однобайтовое имя и тело. Для удобство парсера перед каждой конструкцией ставится байт длины.
Например в синтаксической конструкции {
06,01,AA,00,00,00,03
} содержится следующее:- Первый байт — байт длины, равный 6, и парсер считывает 6 байтов после него
- Второй байт — байт типа данных. Он равен 01, что означает integer
- Третий байт означает имя переменной. Здесь переменная названа AA, и после интерпретатор будет знать ее именно под этим прозвищем
- После идет 4 байта тела. Означают, что переменной изначально присвоено значение равное 3
В процедурах же задается список примитивных операций. Например {
4,14,АА,АА,ВВ
} означает АА = АА + ВВ;Так как Google Glass еще не вышли, то я написал программу-интерпретатор под Андроид. Поэтому в QuRavе сейчас поддерживаются именно компоненты Андроид. Пока что только Button, TextView и Edit Text. Можно задать их положение на экране, текст на них, а для кнопок добавить указание на процедуру, вызываемую при нажатии. Например, {
05,09,05,02,03,08
} означает создание кнопки (код 09) с именем 05, положением на экране 02 (вверху по центру, по системе старых телефонных хардварных клавиатур от 1 до 9), с текстом строки по имени 03 и вызовом процедуры по имени 08 при нажатии.Если честно, сейчас синтаксис выглядит просто ужасно. Он чертовски сложен и имеет очень мало возможностей. Но это же просто прототип. В будущем планирую распихать все примитивные операции по библиотекам, сделав более короткой и удобной их конструкцию. Еще нету возможности вызывать процедуру из другой процедуры, что обусловлено глупо написанным компилятором. Сейчас кстати о нем.
3. Интерпретатор
Основной парсер интерпретатора читает программу, разбивает ее на куски и рассылает их субпарсерам, которые в свою очередь могут иметь свои субпарсеры. На основе результатов работы многочисленных парсеров программа по кусочкам собирается на не менее малочисленных фабриках. Готовые процедуры, переменные и компоненты попадают в класс Main.
В классе Main все содержится в отдельных HashMap'ах. Примером такой HashMap'ы является namesOfVariables:
public Object getVariable(Byte name)
{
return namesOfVariables.get(name);
}
А чтобы доступ к переменным и компонентам был из процедур и примитивных операций, класс Procedure является наследником класса ProgramUnit (на рисунке обозначен как Main), а примитивная операция расширяет класс Procedure.
В классе процедуры переопределен метод взятия переменной. Добавив к нему еще пару строк, можно реализовать механизм локальных переменных.
@Override
public Object getVariable(Byte name)
{
return superiorUnit.getVariable(name);
}
Если честно, то интерпретатор самая скучная часть сделанного, поэтому хватит о нем.
4. Пример использования
А сейчас покажу Вам то, ради чего Вы собственно и начали читать эту статью. Пример действующей программы на языке QuRava.
В данном примере использованы числа типа byte, а не их hex-эквиваленты!
02,03,00
— объявление пустой строки по имени 0002,01,01
— объявление переменной типа int по имени 0102,01,02
— объявление переменной типа int по имени 0206,03,03,80,108,117,115
— объявление строки с текстом «Plus» 04,11,04,01,00
— создание изменяемого текстового поля по имени 0405,09,05,02,03,08
— создание кнопки по имени 05 вызывающей при нажатии процедуру 0804,11,06,03,00
— создание изменяемого текстового поля по имени 0604,13,07,08,00
— создание неизменяемого текстового поля по имени 0731,04,08
— объявление процедуры по имени 08........03,42,00,04
— читаем текст, записанный в поле 04 и кладем его в строку 00........03,41,01,00
— переводим строку 00 в int и записываем результат в переменную 01........03,42,00,06
— читаем текст, записанный в поле 06 и кладем его в строку 00........03,41,02,00
— переводим строку 00 в int и записываем результат в переменную 02........04,14,01,01,02
— складываем переменные 01 и 02 и записываем результат в 01........03,40,00,01
— переводим значение 01 в строку и записываем результат в 00........03,43,07,00
— выводим в текстовое поле 07 строку 00Ну и собственно демонстрация работы: (извините за качество)
5. Дальнейшее развитие
Сейчас я показал Вам лишь альфа-версию прототипа того, что я хочу сделать. В будущем я бы хотел добавить много интересных вещей в язык QuRava:
- разработать простой и мощный синтаксис
- добавить регулярные выражения, массивы, циклы и многое другое
- распределить все примитивные операции по библиотекам, дублирующим основные классы-библиотеки самой Java (такие как Math или Arrays например.
- добавить возможность вызова процедур из других процедур и локальных переменных
- добавить работу с сетью, функцию скачивания из сети дополнительного контента к программе или даже логики
- написать кучу стандартных библиотек
- написать компилятор под desktop и маленькую, но удобную IDE к нему
- написать всеобъемлюющую справку к языку
- выложить проект на github
К сожалению пока что показывать еще почти нечего, поэтому не выложу никаких ссылок. Если будет интересно, то поработаю над этим и напишу еще одну статью.
А пока что хочу провести опрос.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Что Вы думаете насчет моей поделки?
52.2%
Это интересно и над этим стоит поработать
297
36.03%
Это прикольно, но не более того
205
11.78%
Что этот бред делает в моей ленте?
67
Проголосовали 569 пользователей.
Воздержались 99 пользователей.