Refactor type definitions: implement immutability and enhance Primitive class functionality
This commit is contained in:
parent
ec6e7552fc
commit
89e36db5cb
124
oop/types.lua
124
oop/types.lua
@ -20,13 +20,57 @@ local function freeze_table(t)
|
||||
})
|
||||
end
|
||||
|
||||
local function IntDef(cls)
|
||||
local function PrimitiveDef(cls)
|
||||
function cls._freeze(this)
|
||||
rawset(this, "__immutable", true)
|
||||
end
|
||||
|
||||
function cls._thaw(this)
|
||||
rawset(this, "__immutable", false)
|
||||
end
|
||||
|
||||
function cls.copy(this)
|
||||
local cls_ref = getmetatable(this)
|
||||
local items = rawget(this, "__items")
|
||||
if items then
|
||||
return cls_ref(items)
|
||||
end
|
||||
return cls_ref(this.value)
|
||||
end
|
||||
end
|
||||
|
||||
Types.Primitive = oop.class(PrimitiveDef)
|
||||
Types.Primitive.__name = "Primitive"
|
||||
|
||||
local function make_primitive(def, name)
|
||||
local cls = oop.class(def)
|
||||
cls.__name = name
|
||||
cls.inherit(Types.Primitive)
|
||||
local base_newindex = cls.__newindex
|
||||
cls.__newindex = function(self, key, value)
|
||||
if rawget(self, "__immutable") and key ~= "__fields" then
|
||||
local mt = getmetatable(self)
|
||||
local cname = mt and mt.__name or name or "Primitive"
|
||||
error(cname .. " is immutable", 2)
|
||||
end
|
||||
return base_newindex(self, key, value)
|
||||
end
|
||||
function cls.__call(this)
|
||||
local items = rawget(this, "__items")
|
||||
if items then
|
||||
return this.items
|
||||
end
|
||||
return this.value
|
||||
end
|
||||
return cls
|
||||
end
|
||||
|
||||
local function IntDef(cls)
|
||||
|
||||
function cls.__init(this, value)
|
||||
rawset(this, "__frozen", false)
|
||||
rawset(this, "__immutable", false)
|
||||
this.value = math.floor(tonumber(value) or 0)
|
||||
rawset(this, "__frozen", true)
|
||||
rawset(this, "__immutable", true)
|
||||
end
|
||||
|
||||
function cls.__add(a, b)
|
||||
@ -59,21 +103,14 @@ local function IntDef(cls)
|
||||
return this.value
|
||||
end
|
||||
|
||||
function cls.__newindex(this, key, value)
|
||||
if rawget(this, "__frozen") and key ~= "__fields" then
|
||||
error("Int is immutable", 2)
|
||||
end
|
||||
return base_newindex(this, key, value)
|
||||
end
|
||||
end
|
||||
|
||||
local function FloatDef(cls)
|
||||
local base_newindex = cls.__newindex
|
||||
|
||||
function cls.__init(this, value)
|
||||
rawset(this, "__frozen", false)
|
||||
rawset(this, "__immutable", false)
|
||||
this.value = tonumber(value) or 0.0
|
||||
rawset(this, "__frozen", true)
|
||||
rawset(this, "__immutable", true)
|
||||
end
|
||||
|
||||
function cls.__add(a, b)
|
||||
@ -106,12 +143,6 @@ local function FloatDef(cls)
|
||||
return this.value
|
||||
end
|
||||
|
||||
function cls.__newindex(this, key, value)
|
||||
if rawget(this, "__frozen") and key ~= "__fields" then
|
||||
error("Float is immutable", 2)
|
||||
end
|
||||
return base_newindex(this, key, value)
|
||||
end
|
||||
end
|
||||
|
||||
local function ListDef(cls)
|
||||
@ -198,16 +229,19 @@ local function ListDef(cls)
|
||||
end
|
||||
|
||||
local function TupleDef(cls)
|
||||
local base_newindex = cls.__newindex
|
||||
|
||||
function cls.__init(this, items)
|
||||
rawset(this, "__frozen", false)
|
||||
rawset(this, "__immutable", false)
|
||||
if type(items) == "table" then
|
||||
this.items = freeze_table({ table.unpack(items) })
|
||||
local raw_items = { table.unpack(items) }
|
||||
rawset(this, "__items", raw_items)
|
||||
this.items = freeze_table(raw_items)
|
||||
else
|
||||
this.items = freeze_table({})
|
||||
local raw_items = {}
|
||||
rawset(this, "__items", raw_items)
|
||||
this.items = freeze_table(raw_items)
|
||||
end
|
||||
rawset(this, "__frozen", true)
|
||||
rawset(this, "__immutable", true)
|
||||
end
|
||||
|
||||
function cls.__len(this)
|
||||
@ -230,12 +264,6 @@ local function TupleDef(cls)
|
||||
return ipairs(this.items)
|
||||
end
|
||||
|
||||
function cls.__newindex(this, key, value)
|
||||
if rawget(this, "__frozen") and key ~= "__fields" then
|
||||
error("Tuple is immutable", 2)
|
||||
end
|
||||
return base_newindex(this, key, value)
|
||||
end
|
||||
end
|
||||
|
||||
local function QueueDef(cls)
|
||||
@ -413,12 +441,11 @@ local function SetDef(cls)
|
||||
end
|
||||
|
||||
local function BoolDef(cls)
|
||||
local base_newindex = cls.__newindex
|
||||
|
||||
function cls.__init(this, value)
|
||||
rawset(this, "__frozen", false)
|
||||
rawset(this, "__immutable", false)
|
||||
this.value = not not value
|
||||
rawset(this, "__frozen", true)
|
||||
rawset(this, "__immutable", true)
|
||||
end
|
||||
|
||||
function cls.__tostring(this)
|
||||
@ -429,21 +456,14 @@ local function BoolDef(cls)
|
||||
return a.value == b.value
|
||||
end
|
||||
|
||||
function cls.__newindex(this, key, value)
|
||||
if rawget(this, "__frozen") and key ~= "__fields" then
|
||||
error("Bool is immutable", 2)
|
||||
end
|
||||
return base_newindex(this, key, value)
|
||||
end
|
||||
end
|
||||
|
||||
local function StrDef(cls)
|
||||
local base_newindex = cls.__newindex
|
||||
|
||||
function cls.__init(this, value)
|
||||
rawset(this, "__frozen", false)
|
||||
rawset(this, "__immutable", false)
|
||||
this.value = tostring(value or "")
|
||||
rawset(this, "__frozen", true)
|
||||
rawset(this, "__immutable", true)
|
||||
end
|
||||
|
||||
function cls.__len(this)
|
||||
@ -458,25 +478,15 @@ local function StrDef(cls)
|
||||
return this.value
|
||||
end
|
||||
|
||||
function cls.__newindex(this, key, value)
|
||||
if rawget(this, "__frozen") and key ~= "__fields" then
|
||||
error("Str is immutable", 2)
|
||||
end
|
||||
return base_newindex(this, key, value)
|
||||
end
|
||||
end
|
||||
|
||||
Types.Int = oop.class(IntDef)
|
||||
Types.Int.__name = "Int"
|
||||
|
||||
Types.Float = oop.class(FloatDef)
|
||||
Types.Float.__name = "Float"
|
||||
Types.Int = make_primitive(IntDef, "Int")
|
||||
Types.Float = make_primitive(FloatDef, "Float")
|
||||
|
||||
Types.List = oop.class(ListDef)
|
||||
Types.List.__name = "List"
|
||||
|
||||
Types.Tuple = oop.class(TupleDef)
|
||||
Types.Tuple.__name = "Tuple"
|
||||
Types.Tuple = make_primitive(TupleDef, "Tuple")
|
||||
Types.Tupple = Types.Tuple
|
||||
|
||||
Types.Queue = oop.class(QueueDef)
|
||||
@ -492,11 +502,9 @@ Types.Dict.__name = "Dict"
|
||||
Types.Set = oop.class(SetDef)
|
||||
Types.Set.__name = "Set"
|
||||
|
||||
Types.Bool = oop.class(BoolDef)
|
||||
Types.Bool.__name = "Bool"
|
||||
Types.Bool = make_primitive(BoolDef, "Bool")
|
||||
|
||||
Types.Str = oop.class(StrDef)
|
||||
Types.Str.__name = "Str"
|
||||
Types.Str = make_primitive(StrDef, "Str")
|
||||
Types.String = Types.Str
|
||||
|
||||
return Types
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user