Кратко рассмотрим что из себя представляет urbiScript.
Как уже говорилось — urbiScript — это скриптовый язык, используемый для написания программ (скриптов) для управления роботами.
Важными чертами urbiScript являются:
* параллельность
* программирования на основе событий
* прототипное программирование (объекты могут изменяться «на лету»)
* синтаксис в стиле С++
urbiScript выполняется на Urbi-сервере, который запускается либо на роботе, либо на компьютере и к которому можно подключиться простым telnet-ом.
Взаимодействие с аппаратной частью робота осуществляется через объекты UObject, которые выполняют роль драйверов (прослойка между Urbi и аппаратной частью робота).
Данные драйвера реализуются в виде библиотек (.dll), подключаются к серверу Urbi и далее могут прозрачным образом использоваться в urbiScript (вызывать функции, изменять переменные).
Чтобы попробовать urbiScript на вкус нужно запустить Urbi-сервер (устанавливается при инсталляции Urbi SDK) через ярлык «runtime» в меню Пуск, который всего-лишь выполняет команду
«С:\Program Files\Gostai Engine Runtime\bin\urbi.exe» —interactive —port 54000
и прямо в этой консоли можно сразу вводить команды.
Либо можно подключиться telnet-ом к 54000-му порту или лучше всего воспользоваться
Gostai urbiConsole.
Дальнейший материал про urbiScript — это вольный перевод официальной документации, которая идёт в комплекте URBI SDK. Заранее приношу извинения за возможные неточности или ошибки. В случае сомнений рекомендую обращаться к первоисточнику.
1. Комментарии
Комментарии в urbiScript аналогичны комментариям в С++:
/* это блочный комментарий */ // это комментарий до конца строки
2. Значения
42; // целое число [00000000] 42 3.14; // число с плавающей точкой [00000000] 3.14 "string"; // строка [00000000] "string" [1, 2, "a", "b"]; // список [00000000] [1, 2, "a", "b"] ["a" => 1, "b" => 2]; // словарь (ассоциированный список) [00000000] ["a" => 1, "b" => 2] nil; // нейтральное значение void; // отсутствие значения
3. Вызов функций
функции вызываются обычным образом, с передачей им в круглых скобках параметров.
cos(0); // вычисление косинуса [00000000] 1 max(1, 3); // вернёт максимальный аргумент [00000000] 3 max(1, 3, 4, 2); [00000000] 4
результат выполнения функции выводится на экран. Стоит обратить внимание, что функции могут иметь переменное число аргументов (как max())
А вот и долгожданная функция вывода на экран:
echo("Hello world!"); [00000000] *** Hello world!
4. Переменные
переменные определяются ключевым словом var
var x = 42; [00000000] 42 echo(x); [00000000] *** 42 x = 51; [00000000] 51 x; [00000000] 51
если переменная не инициализирована, то она по-умолчанию содержит void.
! При попытке распечатать такую переменную интерпритатор ничего не выдаст.
var y; y; // интерпритатор хранит молчание, // т.к. void не распечатывается // Можно убедиться, что переменная хранит // void с помощью следующих методов: y.asString; [00000000] "void" y.isVoid; [00000000] true
5. Операторы
urbiScript поддерживает классическую семантику арифметических операторов.
1 + 1 == 2; // сложение 1 - 2 == -1; // вычитание 2 * 3 == 6; // умножение 10 / 2 == 5; // деление 2 ** 10 == 1024; // возведение в степень 5%2 == 1; // модуль (целочисленное деление) -(1 + 2) == -3; // смена знака 1 + 2 * 3 == 7; (1 + 2) * 3 == 9; -2 ** 2 == -4; - - - - 1 == 1;
5.1 Операторы присваивания
Присваивание в urbiScript выполняется оператором равно (=). Так же существуют сокращённые версии арифметического действия и присваивания (например +=). Эти операторы не могут быть переопределены, т.к. они эквивалентны простому оператору с последующей операцией присваивания.
var y = 0; [00000000] 0 y = 10; [00000000] 10 y += 10; [00000000] 20 y /= 5; [00000000] 4 y++; [00000000] 4 y; [00000000] 5
5.2 Поразрядные операторы
4 << 2 == 16; // сдвиг влево на 2 бита 4 >> 2 == 1; // сдвиг вправо на 2 бита 2^1; // XOR - исключающе ИЛИ [00000000] 3
5.3 Логические операторы
urbiScript поддерживает обычные логические операторы.
Обратите внимание, что у операторов && и || условие справа будет проверяться только если это необходимо.
true && true; true || false; !true == false; true || (1 / 0); (false && (1 / 0)) == false;
5.4 Операторы сравнения
urbiScript использует классические операторы сравнения.
Обратите внимание на операторы == и ===
== возвращает симантическое равенство (сравнивается величины (содержимое объектов))
=== возвращает физическое равенство (т.е. если два объекта имеют одинаковый идентификатор (uid) ):
var a = 42; [00000000] 42 var b = 42; [00000000] 42 a == b; [00000000] true a === b; // a и b - разные объекты [00000000] false a = b; // теперь a указывает на объект b [00000000] 42 a === b; [00000000] true
5.5 Операторы контейнеров
операторы in и not in — проверяют содержится ли требуемая величина в контейнере (списке):
1 in [0, 1, 2]; [00000000] true 3 not in [0, 1, 2]; [00000000] true "one" in ["zero" => 0, "one" => 1, "two" => 2]; [00000000] true "three" not in ["zero" => 0, "one" => 1, "two" => 2]; [00000000] true
так же обратите внимание, что оператор [] — варьируемый: он может принимать сразу несколько аргументов.
// на списке var l = [1, 2, 3, 4, 5]; [00000000] [1, 2, 3, 4, 5] assert { l[0] == 1; l[-1] == 5; (l[0] = 10) == 10; l == [10, 2, 3, 4, 5]; };
// на строках var s = "abcdef"; [00000005] "abcdef" assert { s[0] == "a"; s[1,3] == "bc"; (s[1,3] = "foo") == "foo"; s == "afoodef"; };
5.6 Операторы доступа к свойствам объектов
Для доступа к свойствам объекта используются те же операторы, что и в С++:
. и ->
class Foo { var a = 42; var b = "foo"; }; [00000000] Foo Foo.a; [00000000] 42
6. Области
Области обозначаются фигурными скобками ({}). Они могут содержать любое количество операторов.
Переменные, объявленные внутри области и существуют только внутри данной области.
{ var x = "test"; echo(x); }; [00000000] *** test // здесь x уже больше не определён
7. Вызов методов
Методы объектов вызываются с помощью точки (.) в стиле С++.
Методы могут быть вызваны последовательно.
Метод без аргуметов может вызываться без круглых скобок.
0.cos(); [00000000] 1 "a-b-c".split("-"); [00000000] ["a", "b", "c"] // пустые круглые скобки не обязательны "foo".length(); [00000000] 3 "foo".length; [00000000] 3 // последовательный вызов методов "".length.cos; [00000000] 1
8. Функции
Функции определяются ключевым словом function
// определение функции myFunction function myFunction() { echo("Hello world"); echo("from my function!"); }; [00000000] function () { echo("Hello world"); echo("from my function!"); } // вызов myFunction(); [00000000] *** Hello world [00000000] *** from my function!
Обратите внимание, что после определения функции, интерпритатор распечатывает её. Это происходит из-за того, что определение myFunction приводит к созданию этой новой функции, а интерпритатор просто распечатывает результат выполнения операции:
// работаем в области { // определяем f function f() { echo("f") }; // Это не вызывает f, а возвращает её значение. f; }; [00000000] function () { echo("f") } { // определяем f function f() { echo("Hello World"); }; // вызываем f f(); }; [00000000] *** Hello World
здесь f выступает как обычная переменная. Вызвав её без круглых скобок можно увидеть тело функции. А с круглыми скобками — это уже вызов данной функции. В это состоит отличие функций от вызова методов: для методов круглые скобки не обязательны, методы всегда выполняются.
Т.к. вывод тела функции при её определении чаще всего нежелателен, можно воспользоваться | {}; (или даже |; )
Работает это просто — при выполнении команды
code | {};
Urbi-сервер сначала выполняет code, затем выполняет {} и возвращает значение (void) последнего, что приводит к тому что сервер ничего не выводит.
function sum(a, b, c) { return a + b + c; } | {}; sum(20, 2, 20); [00000000] 42
Ключевое слово return позволяет возвращать значение от функции. Если return не определён, то возвращается значение последнего выражения функции:
function succ(i) { i + 1 } | {}; succ(50); [00000000] 51
Читать далее: введение в urbiScript — часть 2