如何 运行 一个字符串并得到一个 table,其中包含代码在 lua 中创建的所有变量?

How to run a string and get a table that has all the variables that the code created in lua?

所以我正在为 LIKO-12 制​​作自己的 OS,我需要 运行 .lk12 文件,但我需要一个函数来 运行 一个字符串作为代码return 一个 table 包含代码创建的所有变量

示例:

function foo()
        return "Hello,"
end

function bar()
        return " World!"
end

hello = foo()..bar()

应该 return 具有 2 个功能的 table: 一个名为 foo 的函数 returns "Hello," 一个名为 bar 的函数 returns “World!” 和一个名为 hello 的变量,其中包含“Hello, World!”

您应该可以使用以下代码从代码中调用函数 vars["foo"]()vars.foo()

谁能帮帮我?

当您创建或使用全局变量时,它实际上存储在称为“环境”的 table 或 _ENV 不是 全局, 这是你自动获得的本地)

所以你的代码:

function foo()
        return "Hello,"
end

function bar()
        return " World!"
end

hello = foo()..bar()

真的在做:

function _ENV.foo()
        return "Hello,"
end

function _ENV.bar()
        return " World!"
end

_ENV.hello = _ENV.foo().._ENV.bar()

所以如果我们只是将 _ENV 设置为一个新的 table,然后 return 它,那么这正是您想要的 table。您可以使用 load(这是 运行 字符串的方式)将其作为第四个参数传递。此函数将执行此操作:

function loadAndReturnEnv(codeString)
    local env = {}
    load(codeString, nil, nil, env)() -- error checking skipped for demonstration
    return env
end

但是,请注意所有常见的全局内容,如 string.reptable.sortloadprint 都不存在于这个新的 _ENV 中。如果那是你想要的,那就太好了。但我想你可能确实想要它们。在那种情况下,我们可以使用 metatable __index 功能,这样如果代码在其 _ENV 中查找某些内容但不存在,它会在我们(调用者的)_ENV 中查找。

function loadAndReturnEnvWithGlobals(codeString)
    -- note: env is the environment for the code we're about to run
    -- (which will be called _ENV in that code), and _ENV is the environment
    -- of the loadAndReturnEnvWithGlobals function (i.e. the "real" environment)
    local env = {}
    setmetatable(env, {__index=_ENV})
    load(codeString, nil, nil, env)() -- error checking skipped for demonstration
    setmetatable(env, nil) -- set the table back to normal before we return it
    return env
end

但是等等...程序现在可以在您 运行 时调用 print,但是如果它定义了一个函数,该函数不能调用 print 因为我们删除了在代码 returned 之后 link 回到真实环境。所以我认为解决这个问题的最好方法是离开环境 linked,只复制函数等

function loadAndReturnEnvWithGlobals2(codeString)
    local env = {}
    setmetatable(env, {__index=_ENV})
    load(codeString, nil, nil, env)() -- error checking skipped for demonstration

    local result = {}
    for k,v in pairs(env) do result[k]=v end
    return result
end

尽管这会复制值,所以如果您有任何更改变量的函数,您将看不到更改后的变量。

使用哪个版本由您决定。他们各有利弊。