Объект >specialForms
используется для определения особого синтаксиса Egg. Он сопоставляет слова с функциями, интерпретирующими эти специальные формы. Пока он пуст. Давайте добавим несколько форм.
>specialForms["if"] = function(args, env) {
> if (args.length != 3)
> throw new SyntaxError("Неправильное количество аргументов для if");
> if (evaluate(args[0], env) !== false)
> return evaluate(args[1], env);
> else
> return evaluate(args[2], env);
>};
Конструкция >if
языка Egg ждёт три аргумента. Она вычисляет первый, и если результат не >false
, вычисляет второй. В ином случае вычисляет третий. Этот >if
больше похож на тернарный оператор >?:
. Это выражение, а не инструкция, и она выдаёт значение, а именно, результат второго или третьего выражения.
Egg отличается от JavaScript тем, как он обрабатывает условие >if
. Он не будет считать ноль или пустую строку за >false
.
>if
представлено в виде особой формы а не обычной функции, потому что аргументы функций вычисляются перед вызовом, а >if
должен интерпретировать один из двух аргументов – второй или третий, в зависимости от значения первого.
Форма для >while
схожая.
>specialForms["while"] = function(args, env) {
> if (args.length != 2)
> throw new SyntaxError("Неправильное количество аргументов для while");
> while (evaluate(args[0], env) !== false)
> evaluate(args[1], env);
> // Поскольку undefined не задано в Egg,
> // за отсутствием осмысленного результата возвращаем false
> return false;
>};
Ещё одна основная часть языка – >do
, выполняющий все аргументы сверху вниз. Его значение – это значение, выдаваемое последним аргументом.
>specialForms["do"] = function(args, env) {
> var value = false;
> args.forEach(function(arg) {
> value = evaluate(arg, env);
> });
> return value;
>};
Чтобы создавать переменные и давать им значения, мы создаём форму >define
. Она ожидает >word
в качестве первого аргумента, и выражение, производящее значение, которое надо присвоить этому слову в качестве второго. >define
, как и всё, является выражением, поэтому оно должно возвращать значение. Пусть оно возвращает присвоенное значение (прямо как оператор >=
в JavaScript).
>specialForms["define"] = function(args, env) {
> if (args.length != 2 || args[0].type != "word")
> throw new SyntaxError("Bad use of define");
> var value = evaluate(args[1], env);
> env[args[0].name] = value;