Implement immutability for Int, Float, Bool, and Str types; add freeze_table function for Tuple

This commit is contained in:
Chipperfluff 2026-01-01 18:11:36 +01:00
parent 05756f9289
commit 971cbbc8a2

View File

@ -2,9 +2,31 @@ local oop = require("oop")
local Types = {} local Types = {}
local function freeze_table(t)
return setmetatable({}, {
__index = t,
__newindex = function()
error("Tuple is immutable", 2)
end,
__len = function()
return #t
end,
__pairs = function()
return pairs(t)
end,
__ipairs = function()
return ipairs(t)
end
})
end
local function IntDef(cls) local function IntDef(cls)
local base_newindex = cls.__newindex
function cls.__init(this, value) function cls.__init(this, value)
rawset(this, "__frozen", false)
this.value = math.floor(tonumber(value) or 0) this.value = math.floor(tonumber(value) or 0)
rawset(this, "__frozen", true)
end end
function cls.__add(a, b) function cls.__add(a, b)
@ -36,11 +58,22 @@ local function IntDef(cls)
function cls.to_number(this) function cls.to_number(this)
return this.value return this.value
end 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 end
local function FloatDef(cls) local function FloatDef(cls)
local base_newindex = cls.__newindex
function cls.__init(this, value) function cls.__init(this, value)
rawset(this, "__frozen", false)
this.value = tonumber(value) or 0.0 this.value = tonumber(value) or 0.0
rawset(this, "__frozen", true)
end end
function cls.__add(a, b) function cls.__add(a, b)
@ -72,6 +105,13 @@ local function FloatDef(cls)
function cls.to_number(this) function cls.to_number(this)
return this.value return this.value
end 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 end
local function ListDef(cls) local function ListDef(cls)
@ -161,10 +201,11 @@ local function TupleDef(cls)
local base_newindex = cls.__newindex local base_newindex = cls.__newindex
function cls.__init(this, items) function cls.__init(this, items)
rawset(this, "__frozen", false)
if type(items) == "table" then if type(items) == "table" then
this.items = { table.unpack(items) } this.items = freeze_table({ table.unpack(items) })
else else
this.items = {} this.items = freeze_table({})
end end
rawset(this, "__frozen", true) rawset(this, "__frozen", true)
end end
@ -372,8 +413,12 @@ local function SetDef(cls)
end end
local function BoolDef(cls) local function BoolDef(cls)
local base_newindex = cls.__newindex
function cls.__init(this, value) function cls.__init(this, value)
rawset(this, "__frozen", false)
this.value = not not value this.value = not not value
rawset(this, "__frozen", true)
end end
function cls.__tostring(this) function cls.__tostring(this)
@ -383,11 +428,22 @@ local function BoolDef(cls)
function cls.__eq(a, b) function cls.__eq(a, b)
return a.value == b.value return a.value == b.value
end 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 end
local function StrDef(cls) local function StrDef(cls)
local base_newindex = cls.__newindex
function cls.__init(this, value) function cls.__init(this, value)
rawset(this, "__frozen", false)
this.value = tostring(value or "") this.value = tostring(value or "")
rawset(this, "__frozen", true)
end end
function cls.__len(this) function cls.__len(this)
@ -401,6 +457,13 @@ local function StrDef(cls)
function cls.__tostring(this) function cls.__tostring(this)
return this.value return this.value
end 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 end
Types.Int = oop.class(IntDef) Types.Int = oop.class(IntDef)