Why is this not working

I have this class module I am working on and the problem is that whenever the __index metamethod in the metatable in the class function runs it freezes everything and then produces like 5000 errors and then stops freezing

The error line is here local new_class = t:__call(...)


The code I try to use with my module

local new, class, extends = require(module)()

class "foo" {
    constructor = function(a, b, c)
        print(a + b + c)
    end
}

new "foo"(1, 2, 3) -- prints 6

class "bar" [extends "foo"] { -- freezes somewhere about here
    a = 1
}

print(new "bar" (1,2,3).a) -- does not even run


The module

type ClassIdentifier = string | {}

-- deep copy
local function copy_t(t)
	local result = {}

	for k, v in pairs(t) do
		result[k] = (type(v) == "table") and copy_t(v) or v
	end

	return result
end

-- set variable
local function setv(v, n, l)
	getfenv(l or 3)[n] = v

	return v, n, l
end

local function get_class(class)
	local class = type(class) == "string" and getfenv(3)[class] or class

	assert(type(class) == "table", `unexpected '{type(class)}'`)

	return class
end

function extends(class : ClassIdentifier)
	return get_class(class)
end

function class<T>(a : ClassIdentifier & T): (<A>(a: A) -> A) & T
	local checkconstructor = function(k, v, c)
		if k == "constructor" then
			assert(type(v) == "function", "class field uses reserved keyword 'constructor'")
			assert(c.constructor == nil, "classes may only have a singular constructor")
		end
	end

	local new_class = a and setv({}, a) or {}

	local result = {
		__call = function(_, ...)			
			assert(#{...} == 1, "unexpected syntax")

			local body = ({...})[1]

			assert(type(body) == "table", `unexpected '{type(body)}'`)

			for k, v in pairs(body) do
				checkconstructor(k, v, new_class)

				new_class[k] = v
			end

			return new_class
		end,

		__index = function(t, extended_class)
			return function(...)
				local new_class = t:__call(...)

				for k, v in pairs(extended_class) do
					new_class[k] = new_class[k] or v
				end

				if new_class.constructor then
					setv(function(...)
						assert(extended_class.constructor, "unexpected 'super'")

						return extended_class.constructor(...)
					end, "super", new_class.constructor)
				end
			end
		end
	}

	return type(a) == "table" and result:__call(a) or setmetatable({}, result)
end

function new<T>(class : ClassIdentifier & T)
	local class = get_class(class)

	return function(...) : T
		local instance = copy_t(class)

		for k, v in pairs(instance) do
			if type(v) == "function" then
				setv(instance, "this", v)

				if k == "constructor" then
					v(...)

					instance[k] = nil
				end
			end
		end

		return instance
	end
end

return 
	function(): (typeof(new), typeof(class), typeof(extends))
		return new, class, extends 
	end
1 Like

Can somebody please help me thanks