我在这里谈的是C和/或C ++,因为这是我所知道的唯一用于解释器的语言,其中以下可能是一个问题:
如果我们有一个解释型语言X,为它编写的库如何为该语言添加函数,然后可以从用该语言编写的程序中调用它?
PHP示例:
substr( $str, 5, 10 );
PHP很容易将所有已注册的函数名称存储在一个数组中,并在脚本中调用函数进行搜索。但是,由于C(++)中显然没有eval,那么如何调用该函数呢?我假设PHP没有100MB的代码,如:
if( identifier == "substr" )
{
return PHP_SUBSTR(...);
} else if( ... ) {
...
}
哈哈,那会非常有趣。我希望你到目前为止理解我的问题。
答案 0 :(得分:7)
实际上脚本语言会像你提到的那样做 它们包装函数,并将这些函数注册到解释器引擎。
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 */
答案 1 :(得分:2)
解释器可能只是将函数名称的哈希映射保存到函数定义中(其中包括参数信息,返回类型,函数位置/定义等)。这样,您只需在哈希映射上搜索函数名称(当你的口译员遇到一个)。如果存在,请使用哈希表中的函数info来评估它。
你显然需要为不同级别的范围等添加条款,但这就是它的要点。
答案 2 :(得分:1)
几乎所有编译器都有一个“符号表”,用于查找标识符所代表的内容。符号表将包含函数名称,变量名称,类型名称等...任何具有名称的东西都在符号表中,这基本上是编译器知道该名称的所有内容的名称映射(我在这里简化) )。然后,当编译器遇到标识符时,它会在符号表中查找它,并发现它是一个函数。如果您正在使用解释器,则符号表将包含有关在何处查找函数和继续解释的信息。如果这是一个编译器,则符号表将具有该函数在编译代码中的位置的地址(或稍后填充地址的占位符)。然后可以生成程序集,基本上说:将参数放在堆栈上,并在某个地址恢复执行。
所以,对于你的例子,翻译会查看
substr( $str, 5, 10 );
并在其符号表中找到“substr”:
symbolTableEntry entry = symbolTable["substr"];
从那里开始,它会收集$str
,5
和10
作为参数,并查看entry
以查看参数对函数是否有效。然后它会查看entry
以查找使用编组参数跳转到的位置。
答案 3 :(得分:0)
在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);