Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local wrapper = {}
- --[[
- gonna be fun lol
- - CHL
- Notes:
- - Too lazy to add descriptive errors, refer to the line number from the output.
- * When __index is invoked on the obj, and there are multiple indexes in properties,
- functions and events, then the script will check properties, function and events
- in that order.
- Descriptions:
- * wrapper:createConstructor()
- Legend:
- Indexes:
- [A] = Argument (based on index?)
- [M] = Mandatory? (T or F)
- [ ] = same as last
- ,________________________________________________________________________________________________.
- |A|Type |M|Description |
- |1|table (dictionary)|F|Represents as the properties of the object. In this dictionary, the index|
- | | | |is the property name and the value represents as an optional table |
- | | | |(ITEM_1). See more charts below about this. |
- |2|table (dictionary)| |Represents as the functions of the object. In this dictionary, each index|
- | | | |represents the function name while the value represents the function |
- | | | |(ITEM_2). See more charts below about this. |
- |3|table (dictionary)| |Represents as the events of the object. In this dictionary, the index is |
- | | | |the event name and the value represents as a non-falsy value, typically |
- | | | |true |
- '------------------------------------------------------------------------------------------------'
- This function returns a function, representing as the constructor function, as well as a dictionary,
- where the index is the event name and the value is the function, where when called with any
- arguments, it will call the functions from an internal dictionary.
- * ITEM_1
- Legend:
- Indexes:
- [M] = Mandatory? (T or F)
- [ ] = same as last
- ,________________________________________________________________________________________________.
- |Index |M|value type |value description |
- |strictValueType |F|table (dictionary)|Represents how many values can the new value has to be. |
- | | | |Index being the type of value and the value being a |
- | | | |boolean-ish value. |
- | | |string |Same as last but this string represents as the index and |
- | | | |the value is true. |
- |newIndexCallback| |function |Function which is called when the object has __newindex |
- | | | |invoked. The value returned is the value that is stored |
- | | | |internally. Refer to ITEM_1.1 for parameter info. |
- |indexCallback | |function |Function which is called when the object has __index |
- | | | |invoked. The returned value of that function is also the |
- | | | |returned value for the __index invoke. Refer to ITEM_1.2 |
- | | | |for parameter info. |
- |default | |variant |default value of the property. |
- '------------------------------------------------------------------------------------------------'
- * ITEM_1.1
- Legend:
- Indexes:
- [P] = Expected parameters
- ,________________________________________________________________________________________________.
- |P|Type |Description |
- |1|Variant |The new value |
- |2|table |The object |
- |3|table |The object's internal storage |
- '------------------------------------------------------------------------------------------------'
- * ITEM_1.2
- Legend:
- Indexes:
- [P] = Expected parameters
- ,________________________________________________________________________________________________.
- |P|Type |Description |
- |1|Variant |The index |
- |2|table |The object |
- |3|table |The object's internal storage |
- '------------------------------------------------------------------------------------------------'
- * ITEM_2
- Legend:
- Indexes:
- [Par] = Expected parameters
- [T] = tuple arguments
- ,________________________________________________________________________________________________.
- |P|Type |Description |
- |1|table |Object |
- |2|table (dictionary)|Object's internal storage |
- |3|Variant |The value when there's at least one argument and when the object was |
- | | |indexed with a period. |
- | |table |Representing as the object if the function was indexed with a colon, |
- | | |however since this object is the same as argument 1, you can use the == |
- | | |operator to determine if the function was index with a colon or period |
- |T| |Tuple arguments |
- '------------------------------------------------------------------------------------------------'
- ]]
- function wrapper:createConstructor(properties, functions, events)
- -- precondtions
- properties = properties or {}
- functions = functions or {}
- events = events or {}
- assert(
- type(properties) == 'table' and
- type(functions) == 'table'and
- type(events) == 'table'
- )
- local currentlyUsedEvents = {}
- local fireableEvents = {}
- -- set up functions
- local function getFireableEvent(name)
- return function(...)
- for _, set in next, currentlyUsedEvents[name]do
- local func = set['function']
- if set.newThread then
- func = coroutine.wrap(func)
- end
- func(...)
- end
- end
- end
- -- check properties
- for propertyName, set in next, properties do
- assert(
- type(propertyName) == 'string' and
- type(set) == 'table'
- )
- if set.strictValueType then
- assert(
- type(set.strictValueType) == 'string' or
- type(set.strictValueType) == 'table'
- )
- end
- if set.newIndexCallback then
- assert(type(set.newIndexCallback) == 'function')
- end
- if set.indexCallback then
- assert(type(set.indexCallback) == 'function')
- end
- end
- -- check functions
- for functionName, func in next, functions do
- assert(
- type(functionName) == 'string' and
- type(func) == 'function'
- )
- end
- -- check events
- for eventName, bool in next, events do
- assert(type(eventName) == 'string')
- if bool then
- currentlyUsedEvents[eventName] = {}
- fireableEvents[eventName] = getFireableEvent(eventName)
- end
- end
- -- return constructor + listeners
- return function()
- local objPropertiesInternal = {}
- local obj = {}
- -- set up obj
- setmetatable(obj, {
- __index = function(_, index)
- -- index invoked, can be properties, functions or events
- local propertiesSet = properties[index]
- local functionsSet = functions[index]
- local eventSet = events[index]
- local returnedValue
- if propertiesSet then
- -- properties
- returnedValue = objPropertiesInternal[index]
- -- use callback if there is so,
- if propertiesSet.indexCallback then
- returnedValue = propertiesSet.indexCallback(index, obj, objPropertiesInternal)
- end
- elseif functionsSet then
- -- functions
- returnedValue = function(...)
- return functionsSet(obj, objPropertiesInternal, ...)
- end
- elseif eventSet then
- local eventName = index
- local timeStamp = "" .. os.time()
- returnedValue = {
- Connect = function(obj2, func)
- assert(type(obj2) == 'table', 'Attempting to index event with a period.')
- currentlyUsedEvents[eventName][timeStamp] = {
- ['function'] = func;
- newThread = true
- }
- return {
- Disconnect = function()
- currentlyUsedEvents[eventName][timeStamp] = nil
- end
- }
- end;
- Wait = function()
- local thread = coroutine.running()
- currentlyUsedEvents[eventName][timeStamp] = {
- ['function'] = function(...)
- coroutine.resume(thread, ...)
- currentlyUsedEvents[eventName][timeStamp] = nil
- end;
- }
- return coroutine.yield()
- end,
- }
- else
- error('Attempting to use index, ' .. index .. ' but the object has none.')
- end
- return returnedValue
- end;
- __newindex = function(_, index, newValue)
- -- assume it's a property
- local set = assert(properties[index])
- -- check value type if we have to
- if set.strictValueType then
- checkType(newValue, set.strictValueType)
- end
- -- change newvalue from callback if we have to
- if set.newIndexCallback then
- newValue = set.newIndexCallback(newValue, obj, objPropertiesInternal)
- end
- -- set internal table
- objPropertiesInternal[index] = newValue
- end
- })
- -- set defaults
- for propertyName, set in next, properties do
- obj[propertyName] = set.default
- end
- -- return
- return obj
- end, fireableEvents
- end
- function checkType(value, types)
- if type(types) == 'string'then
- types = {
- [types] = true
- }
- end
- assert(types[typeof(value)], 'Non-valid type of value')
- end
- return wrapper
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement