Как делают интерпретаторы, записанные в C и C++, связывают идентификаторы с C (++) функции

Я говорю о C и/или C++ здесь, поскольку это - единственные языки, я знаю используемый для интерпретаторов, где следующее могло быть проблемой:

Если у нас есть интерпретируемый язык X, как может, библиотека, записанная для него, добавляет функции к языку, который можно затем назвать из программ, записанных на языке?

Пример PHP:

substr( $str, 5, 10 );
  • Как функция substr добавлена к "функциональному пулу" PHP, таким образом, это можно назвать из сценариев?

Это легко для PHP, хранящего все зарегистрированные имена функций в массиве и перерывающего его, поскольку функция вызвана в сценарии. Однако, поскольку, очевидно, нет никакой оценки в C (++), как функция может затем быть вызвана? Я предполагаю, что PHP не имеет 100 МБ кода как:

if( identifier == "substr" )
{
   return PHP_SUBSTR(...);
} else if( ... ) {
   ...
}

Ха ха это было бы довольно забавно. Я надеюсь, что Вы поняли мой вопрос до сих пор.

  • Как делают интерпретаторы, записанные в C/C++, решают эту проблему?
  • Как я могу решить это для своего собственного экспериментального игрушечного интерпретатора, записанного в C++?
7
задан sub 30 March 2010 в 19:01
поделиться

4 ответа

На самом деле языки сценариев делают что-то вроде того, что вы упомянули.
Они оборачивают функции и регистрируют эти функции в движке интерпретатора.

Пример Lua:

static int io_read (lua_State *L) {
  return g_read(L, getiofile(L, IO_INPUT), 1);
}


static int f_read (lua_State *L) {
  return g_read(L, tofile(L), 2);
}
...
static const luaL_Reg flib[] = {
  {"close", io_close},
  {"flush", f_flush},
  {"lines", f_lines},
  {"read", f_read},
  {"seek", f_seek},
  {"setvbuf", f_setvbuf},
  {"write", f_write},
  {"__gc", io_gc},
  {"__tostring", io_tostring},
  {NULL, NULL}
};
...
luaL_register(L, NULL, flib);  /* file methods */
7
ответ дан 7 December 2019 в 01:19
поделиться

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

Очевидно, что вам нужно добавить положения для разных уровней охвата и т. Д., Но в этом суть.

2
ответ дан 7 December 2019 в 01:19
поделиться

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

Так, например, интерпретатор смотрит на

substr( $str, 5, 10 );

и находит «substr» в своей таблице символов:

symbolTableEntry entry = symbolTable["substr"];

оттуда он будет собирать $ str , 5 и 10 в качестве аргументов и посмотрите на запись , чтобы убедиться, что аргументы действительны для функции. Затем он будет искать в записи , чтобы узнать, куда перейти с упорядоченными аргументами.

1
ответ дан 7 December 2019 в 01:19
поделиться

В C++ вы, вероятно, будете использовать тот же механизм, что и Nick D, но, используя его возможности OO:

typedef luaFunction boost::function<void(*)(lua_State&)>
std::map<std::string, luaFunction > symbolTable;
symbolTable["read"] = f_read;
symbolTable["close"] = f_close; // etc.
// ...
luaFunction& f = symbolTable[*symbolIterator++];
f(currentLuaState);
0
ответ дан 7 December 2019 в 01:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: