teal.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // Package teal supplies the Lua modules for Teal language support
  2. // teal.lua and compat52.lua were modified as per https://github.com/yuin/gopher-lua/issues/314
  3. package teal
  4. import (
  5. "embed"
  6. "fmt"
  7. "path/filepath"
  8. "strings"
  9. log "github.com/sirupsen/logrus"
  10. lua "github.com/xyproto/gopher-lua"
  11. )
  12. const tealLoadScript = "require('compat52'); tl = require('tl'); tl.cache = {}"
  13. var (
  14. //go:embed *.lua
  15. fs embed.FS
  16. // Teal files that should be preloaded when Teal is loaded
  17. preloadTealFilenames = []string{"bit.lua", "bit32.lua", "compat52.lua", "tl.lua"}
  18. )
  19. // preloadModuleFromFS loads the given Lua filename from the embedded filesystem
  20. func preloadModuleFromFS(L *lua.LState, fname string) error {
  21. // Derive package name by removing file extension
  22. pkgname := strings.TrimSuffix(fname, filepath.Ext(fname))
  23. // Read the file content
  24. b, err := fs.ReadFile(fname)
  25. if err != nil {
  26. return fmt.Errorf("unable to read %s: %w", fname, err)
  27. }
  28. // Load the Lua module
  29. mod, err := L.LoadString(string(b))
  30. if err != nil {
  31. return fmt.Errorf("could not load %s: %w", fname, err)
  32. }
  33. // Get the "package" table
  34. pkg := L.GetField(L.Get(lua.EnvironIndex), "package")
  35. if pkg == lua.LNil {
  36. return fmt.Errorf("unable to get 'package' table")
  37. }
  38. // Get the "preload" table inside "package"
  39. preload := L.GetField(pkg, "preload")
  40. if preload == lua.LNil {
  41. return fmt.Errorf("unable to get 'preload' table")
  42. }
  43. L.SetField(preload, pkgname, mod)
  44. return nil
  45. }
  46. // Load makes Teal available in the Lua VM
  47. func Load(L *lua.LState) {
  48. for _, fname := range preloadTealFilenames {
  49. if err := preloadModuleFromFS(L, fname); err != nil {
  50. log.Errorf("Failed to load Teal: %v", err)
  51. return
  52. }
  53. }
  54. if err := L.DoString(tealLoadScript); err != nil {
  55. log.Errorf("Failed to set `tl` global variable: %v", err)
  56. }
  57. }