Именованные блоки кода

Императивное программирование - это в некотором роде основы основ. Это то, без чего кажется немыслимым ни один язык программирования - операторы if, else, while, for и т.д. Казалось бы, в этой области уже все придумано и продумано... Но так ли это? Ведь в действительности многим программистам наверняка хотелось немного улучшить старые добрые операторы, расширить их, сделать удобнее и мощнее.
Самое удивительное, что улучшить операторы действительно можно. И сейчас будет рассмотрено одно из наиболее красивых, и в то же время простых в реализации улучшений.
Итак, императивные операторы, или операторы управления исполнением программы. Обычно они делятся на операторы ветвления, операторы циклов, операторы множественного выбора и операторы безусловной передачи управления. В разных языках они выглядят немного по-разному (неизменными остаются, пожалуй, только ключевые слова if, else и goto). В Паскаль-подобных языках обычно используется связка "if-then", где "then" - вторая "половинка" ключевого слова, играющая роль закрывающей скобки для условия. Впрочем, в паскаль-подобных языках используются разнообразные связки: for..to..do, for..downto..do, repeat..until, while..do.
В си-подобных языках используется одно ключевое слово (if, while, for) и аргумент блока заключается в круглые скобки. Такой подход лично мне нравится больше всего, так как он не содержит "лишних" ключевых слов. Именно он и будет применяться в Neo.

Операторы образуют древовидную структуру. То есть внутри блока if может находиться цикл while, в котором блок выбора switch, внутри которого еще if и т.д. - в любых сочетаниях. Разумеется, делать слишком большую вложенность не рекомендуется (вместо этого рекомендуется выносить код в функции). Но ситуации бывают разные.

Очевидно, что оператор (и соответствующий ему блок кода) - это полноценная сущность языка программирования, такая же как функция, структура или переменная. За исключением одной важной особенности - в большинстве языков операторы не имеют собственных имен. Я решил исправить это упущение и ввел в Neo именованные блоки кода. Аналогов этому нет практически ни в одном языке программирования. Каждый блок кода может иметь некоторое имя, подчиняющееся общим правилам задания идентификаторов. Это имя можно использовать в различных целях. Вот как выглядят именованные блоки
if(x>0) NamedIf 
{
  match(m) NamedMatch
  {
  }
}
else NamedElse
{
  while(i<100) NamedWhile 
  {
    do NamedDo 
    {


    } while(z!=k);    
  }
}


В приведенном примере представлено несколько различных именованных блоков, вложенных друг в друга.

Дополнительные возможности, которые дают именованные блоки кода
1. Возможность выйти сразу из нескольких циклов (блоков), возможность продолжить исполнение сразу нескольких блоков. Операторы break и continue расширены, теперь можно указывать аргумент - имя блока, из которого следует выйти или который следует продолжить. При использовании имен выйти и продолжить исполление ("зациклить") можно и операторы, для которых ранее такой возможности не было: if и else. Для удобства, break и continue без аргументов на if и else не распространяются.
2. Появилась возможность именованного закрытия блоков. Эта возможность введена для дополнительной наглядности программ. В конце каждого блока кода, после закрывающей скобки можно написать имя блока кода и завершить оператор точкой с запятой. Компилятор осуществит дополнительную проверку соответствия имен начала и конца блока, и если имена разные - выдаст ошибку. Разумеется, указывать имя в конце блока необязательно.
3. Низкоуровневые возможности. Можно получить размер (sizeof) и адрес блока кода (подобно тому, как это делается в Ассемблере);
4. Безусловные переходы. Можно осуществить переход goto на любой блок кода по имени (то есть имена блоков в каком-то смысле аналогичны меткам).
5. Области видимости. В некоторых случаях имена блоков можно использовать как имена модулей (пространств имен). В частности, для доступа к вложенному блоку используется имя объемлющего.

Правила видимости блоков похожи на правила видимости переменных. На одном уровне не может быть двух блоков с одинаковым именем. Тем ни менее, вложенный блок может иметь такое же имя, как и любой объемлющий.

if(x>0) MyBlock
{
  if(y>1) MyBlock 
  {
    if(z>2) MyBlock 
    {
      foo();

    }
  }
}
//...
goto MyBlock.MyBlock.MyBlock; // на if(z>2)

Синтаксически блоки требуют заключения кода в фигурные скобки. Конечно, можно было бы сделать именованные блоки и без фигурных скобок, но мне кажется, что такие блоки смотрелись бы не очень красиво. Поэтому в текущей версии языка для именованных блоков фигурные скобки обязательны.


No comments:

Post a Comment