yuin / gopher-lua

GopherLua: VM and compiler for Lua in Go
MIT License
6.24k stars 648 forks source link

API to export and import definition of a function #111

Closed riking closed 2 years ago

riking commented 7 years ago

Add a Go-side API to export and import the definition of a LFunction across LStates.

Ideally, the API could be used something like this:

func luaFuncLibrary__newindex(L *lua.LState) int {
    lib := L.CheckUserdata(1)
    name := L.CheckString(2)
    f := L.CheckFunction(3)
    if f.IsG {
        L.RaiseError("Cannot save platform-provided functions")
    }
    p := f.Proto
    bytes, err := f.Export()
    if err != nil {
        L.RaiseError("Cannot save %s: %v", p.SourceName, err)
    }
    lib.Value.(*LFuncLibrary).Save(name, bytes)
    return 0
}

func luaFuncLibrary__index(L *lua.LState) int {
    lib := L.CheckUserdata(1)
    name := L.CheckString(2)
    bytes, err := lib.Value.(*LFuncLibrary).Load(name)
    if err != nil {
        return 0 // not found
    }
    func, err := L.ImportFunction(bytes)
    if err != nil {
        L.RaiseError("Could not import %s: %v", name, err)
    }
    L.Push(func)
    return 1
}

Prior art: This is supported by www.luaj.org: https://github.com/headius/luaj/blob/master/src/core/org/luaj/vm2/compiler/DumpState.java#L201 and used in this Java program here: https://github.com/clone1018/Shocky/blob/3350f15/modulesrc/ModuleLua.java#L224 (see also lines 146, 152)

Current status:

We can export most of a LFunction.FunctionProto (can't export the stringConstants) but there's no way to reconstruct it later.

You also need to save the Upvalues.

If the source is provided to the library as a string, you can use L.LoadString(str) in __index(), but this isn't very ergonomical in the Lua code. "Library functions" would have to be defined out of band, and you don't have self-documenting arguments unless the source is of the form return function(arg1, arg2, arg3) .... end.

A trivial implementation would be to save the string slices of the original source and return them from the saving function. Of course, this would only work for function environments of the same "shape" but I'm not sure that's too much of an issue?

yuin commented 7 years ago

This may be a duplicate issue( #57 ).