aganm
aganm

Reputation: 1369

Lua - Finding file in which global variable is declared

I want to have a user provided config file like this

-- file cfg.lua, provided or modifiable by user

cfg = {} -- global table

cfg.string_value = 153 -- supposed to be a string, user mistake

return cfg

And use it from somewhere such as if there's something wrong with the config file, I can tell the user what and where exactly went wrong

-- file init.lua

local cfg = require("cfg")

if type(cfg.string_value) ~= "string" then
    error("config value 'string_value' expected a string")
end

And I want the error message to tell the user in which file and line is that value such as

ERROR:init.lua:6: config value 'string_value' expected a string
      LOOK INSIDE cfg.lua: line 5

Is it possible to retrieve the file and line number from where a variable was declared?

Upvotes: 0

Views: 101

Answers (2)

Piglet
Piglet

Reputation: 28950

Lua is dynamically typed. Any variable may have any type. So the only way to make sure that the correct type is assigned is by actually checking it.

You could use a proxy table to check wether the expected type was assigned. That way every assignment will pass through a function that makes sure we have matching types.

You can either define a type for each property or just use the type of it's default value.

You can use the debug library to get more information about where the assignment happened https://www.lua.org/manual/5.4/manual.html#6.10

-- simulate loading a module
function require()
  local cfg = {
    string_value = {type = "string", value = "default"},
    table_value = {type = "table", value = {}},
  }
  local mt = {
    __index = function (t,k) return cfg[k].value end,
    __newindex = function (t,k,v)
      assert(type(v) == cfg[k].type, string.format(
        "attempted to assign a %s to config field %s. %s expected!",
        type(k), k, cfg[k].type))
      print(debug.traceback())
      cfg[k].value = v
    end
  }
  local interface = setmetatable({}, mt)

  return interface
end


local cfg = require("cfg")
cfg.string_value = "test"
print(cfg.string_value)
cfg.table_value = 4

Upvotes: 2

koyaanisqatsi
koyaanisqatsi

Reputation: 2793

For a number that has to be a string use...

-- file cfg.lua, provided or modifiable by user

cfg = {} -- global table

cfg.string_value = tostring(153) -- supposed to be a string
-- or: cfg.string_value = "153"

return cfg

Upvotes: 0

Related Questions