Разработка компилятора. Контекст исполнения


Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Deprecated: Function eregi_replace() is deprecated in /hlds/web/u138079p19/code4life.ru/htdocs/wp-content/plugins/wp-note/wp-note.php on line 43

Notice: Функция get_currentuserinfo с версии 4.5.0 считается устаревшей! Используйте wp_get_current_user(). in /hlds/web/u138079p19/code4life.ru/htdocs/wp-includes/functions.php on line 3840

Контекст исполнения играет большую роль на этапе исполнения кода, а правильная организация контекстов скажется на всей работе виртуальной машины в целом.

Контекст исполнения — конечное пространство имен, которое позволяет четко идентифицировать все входящие в него данные и трактовать их единообразно.

Также рекомендую обратиться к википедии для уточнения.

В s4g контексты создаются сборщиком мусора, да и вообще любой объект внутри скриптовой системы создается именно сборщиком. В данной статье я буду говорить об организации контекстов в нашем скриптовом языке s4g 0.9.2

Состав контекста исполнения

Контекст исполнения содержит в себе таблицу, которая является пространством имен. В этой таблице хранятся переменные.

Контекст может иметь несколько состояний:

//! типы контекстов
enum S4G_CONTEXT_TYPE_WORK
{
	S4G_CONTEXT_TYPE_WORK_OFFLINE,		//!< не рабочий
	S4G_CONTEXT_TYPE_WORK_ONLINE,		//!< рабочий
	S4G_CONTEXT_TYPE_WORK_ONLINE_EVER,	//!< рабочий всегда
};

То есть во время работы виртуальной машины контексты могут быть доступны или недоступны.

В нашем случае контекст исполнения представлен структурой:

/*! контекст содержащий в себе все переменные текущего исполнения
*/
struct s4g_Context : public s4g_OwnerVar
{
	s4g_Table *m_pTable;	//!< таблица с переменными

	/*! прошлая таблица с переменными
	каждый контекст при создании создает себе таблицу, 
	и если мы в текущий контекст хотим поместить таблицу с замыканием тогда текущую таблицу контекста #m_pTable запишем сюда
	а потом поменяем их местами и обнулим m_pOldTable (если не используется должна быть 0)
	*/
	s4g_Table* m_pOldTable;	

	/*! тип контекста #S4G_CONTEXT_TYPE_WORK, 
	это нужно в случае когда вызывается функция, вызываемая блокирует все предыдущие контексты, после отработки разблокирует */
	S4G_CONTEXT_TYPE_WORK m_TypeWork;
	
};

При исполнении кода тела скрипта контекстом будет является глобальное пространство имен, а когда исполняется функция — локальное пространство имен, то есть контекст функции. Также у нас есть языковой константный контекст, в котором хранятся языковые (а вообще любые можно) данные (функции, таблицы в виде пространств имен). В контексты можно записывать данные и считывать.

Виды контекстов/пространств имен

Иерархия контекстов выглядит так:

  1. языковой контекст (доступен всегда)
  2. глобальный контекст
  3. иной контекст (контекст функции либо управляющей контструкции if/for/while и т.д.)

Языковой контекст доступен всегда для чтения на прямую. Для записи он доступен только внутри скриптовой системы и через API.

Глобальный контекст доступен непосредственно (на прямую) только при исполнении тела скрипта. В него можно записывать и с него можно считывать, однако только он в этот момент доступен для записи.

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

Зачем это сделано? Чтобы код скрипта был понятен. Когда глобальное пространство имен имеет достаточно много данных, то обращение внутри функции к ним, особенно если нет стандарта оформления кода, может быть не очевидным. К примеру где то в глобальном пространстве объявили переменную var a; а затем в функции ее считываем/записываем и совершено случайно создали локальную переменную var a; как быть в таком случае? Конечно лучше всего не писать такой код, но если он уже написан?

Именно поэтому мы сделали посредственную доступность глобального контекста при исполнении функции, как бы попытались внести ясность в будущий код)) То есть если нужен доступ к глобальной переменной из тела функции, придется обращаться к ней через _g, а в нашем случае чтобы обратиться к переменной «a» надо _g.a

Каждый вызов функции блокирует все предыдущие контексты (кроме языкового) и делает их недоступными для чтения либо записи, а когда исполнение кода функции заканчивается и машина возвращается в прежнее состояние самый верхний контекст (контекст функции которую сейчас выполняла машина) удаляется и разблокировывается предыдущий. То есть это стек контекстов (жирным выделены доступные контексты, курсивом недоступные):

  1. языковой контекст (доступен всегда)
  2. глобальный контекст
  3. контекст функции func1
  4. контекст функции func2

После того как функция func2 закончит свою работу стек контекстов будет выглядеть:

  • языковой контекст (доступен всегда)
  • глобальный контекст
  • контекст функции func1

А после того как func1 закончит работать стек контекстов будет:

  • языковой контекст (доступен всегда)
  • глобальный контекст

Для управляющих конструкций (if/for/while) тоже создаются контексты, но их создание (в отличии от функций) не ведет к блокировке предыдущих, то есть можно считать все данные которые доступны.

При таком подходе рекурсия поддерживает без проблем, так как каждый раз для вызова функции создается новый контекст.

При разработке s4g мы не оставили без внимание замыкания, однако они дались с трудом))

При создании функции с замыканием, в ее структуру записывается таблица с принимаемыми переменными, при вызове этой функции устанавливается 2 контекста:

  1. контекст с принятыми переменными во время создания замыкания
  2. контекст функции

Причем для записи доступен только второй контекст.

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


Как оказалось разработка контекстов это не сложно, а сложно было это все придумать и рассчитать, проанализировать и испытать))

Поделиться:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*