The problem#
Using my Factorio reflection library discussed previously involves interacting with Lua values that are a combination of the actual value and some metadata, so you have to know about those values to use them. Worse, the interactions I defined are quite verbose. The main thing you're like to want to do on a value is lookup a property on it. Normally in Lua that looks like
table[key]
but if instead of table
you have a wrapped
value from the reflection
library, you would look up key
on it with
ReflectionLibraryMod.typed_object_lookup_property(
wrapped, key).value
If you want to do multiple levels of property lookups, then this quickly gets quite unwieldy.
The solution#
Lua supports operator overloading through a mechanism it calls metatables (some additional examples).
Using that mechanism, the library defines a value
ReflectionLibraryMod.typed_data_raw
that can be indexed as
wrapped[key]
and assigned to like wrapped[key] = newValue
.
The basic setup looks like
local prototype = {} -- table for methods
local mt = {}
mt.__index = function (table, key)
local res = prototype[key]
or ReflectionLibraryMod.wrap_typed_object(
ReflectionLibraryMod.typed_object_lookup_property(
table._private, key))
if res == nil then
if key == "_value" then
res = table._private.value
end
end
return res
end
mt.__newindex = function (table, key, newValue)
-- If newValue is a wrapped typed value, then unwrap it.
if getmetatable(newValue) == mt then
newValue = newValue._private.value
end
table._private.value[key] = newValue
end
function ReflectionLibraryMod.wrap_typed_object(typedValue)
if typedValue == nil then
return nil
end
local res = {_private = typedValue}
setmetatable(res, mt)
return res
end
Any additional properties would be defined next to the definition of
_value
. And any methods would be defined on prototype
.