Выразительный JavaScript (Хавербеке) - страница 119

Вот и всё, что нужно для интерпретации Egg. Вот так просто. Но без определения нескольких специальных форм и добавления полезных значений в окружение, вы с этим языком ничего не сможете сделать.

Специальные формы

Объект >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;