summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2024-06-11 21:42:10 -0400
committerNat Goodspeed <nat@lindenlab.com>2024-06-11 21:42:10 -0400
commit18c4dcc5998e061fe3ab54607665c775dd18c826 (patch)
tree69d84b90ca249c2a0877c7a368692b64d289be11 /indra/newview
parenteae45eefb55410782559b4ace5350b2a99f63234 (diff)
Allow Python-like 'object = ClassName(ctor args)' constructor calls.
The discussions we've read about Lua classes conventionally use ClassName:new() as the constructor, and so far we've followed that convention. But setting metaclass(ClassName).__call = ClassName.new permits Lua to respond to calls of the form ClassName(ctor args) by implicitly calling ClassName:new(ctor args). Introduce util.classctor(). Calling util.classctor(ClassName) sets ClassName's metaclass's __call to ClassName's constructor method. If the constructor method is named something other than new(), pass ClassName.method as the second arg. Use util.classctor() on each of our classes that defines a new() method. Replace ClassName:new(args) calls with ClassName(args) calls throughout.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/scripts/lua/ErrorQueue.lua5
-rw-r--r--indra/newview/scripts/lua/Floater.lua3
-rw-r--r--indra/newview/scripts/lua/Queue.lua4
-rw-r--r--indra/newview/scripts/lua/WaitQueue.lua7
-rw-r--r--indra/newview/scripts/lua/leap.lua13
-rw-r--r--indra/newview/scripts/lua/qtest.lua12
-rw-r--r--indra/newview/scripts/lua/test_luafloater_demo.lua2
-rw-r--r--indra/newview/scripts/lua/test_luafloater_demo2.lua2
-rw-r--r--indra/newview/scripts/lua/test_luafloater_gesture_list.lua2
-rw-r--r--indra/newview/scripts/lua/test_luafloater_gesture_list2.lua2
-rw-r--r--indra/newview/scripts/lua/test_timers.lua16
-rw-r--r--indra/newview/scripts/lua/timers.lua3
-rw-r--r--indra/newview/scripts/lua/util.lua25
13 files changed, 71 insertions, 25 deletions
diff --git a/indra/newview/scripts/lua/ErrorQueue.lua b/indra/newview/scripts/lua/ErrorQueue.lua
index 13e4e92941..e6e9a5ef48 100644
--- a/indra/newview/scripts/lua/ErrorQueue.lua
+++ b/indra/newview/scripts/lua/ErrorQueue.lua
@@ -5,8 +5,11 @@
local WaitQueue = require('WaitQueue')
local function dbg(...) end
-- local dbg = require('printf')
+local util = require('util')
-local ErrorQueue = WaitQueue:new()
+local ErrorQueue = WaitQueue()
+
+util.classctor(ErrorQueue)
function ErrorQueue:Error(message)
-- Setting Error() is a marker, like closing the queue. Once we reach the
diff --git a/indra/newview/scripts/lua/Floater.lua b/indra/newview/scripts/lua/Floater.lua
index 75696533e4..d057a74386 100644
--- a/indra/newview/scripts/lua/Floater.lua
+++ b/indra/newview/scripts/lua/Floater.lua
@@ -2,6 +2,7 @@
local leap = require 'leap'
local fiber = require 'fiber'
+local util = require 'util'
-- list of all the events that a LLLuaFloater might send
local event_list = leap.request("LLFloaterReg", {op="getFloaterEvents"}).events
@@ -45,6 +46,8 @@ function Floater:new(path, extra)
return obj
end
+util.classctor(Floater)
+
function Floater:show()
-- leap.eventstream() returns the first response, and launches a
-- background fiber to call the passed callback with all subsequent
diff --git a/indra/newview/scripts/lua/Queue.lua b/indra/newview/scripts/lua/Queue.lua
index 5ab2a8a72c..5bc72e4057 100644
--- a/indra/newview/scripts/lua/Queue.lua
+++ b/indra/newview/scripts/lua/Queue.lua
@@ -7,6 +7,8 @@
-- But had to resist
-- For fear it might be too obscua.
+local util = require 'util'
+
local Queue = {}
function Queue:new()
@@ -20,6 +22,8 @@ function Queue:new()
return obj
end
+util.classctor(Queue)
+
-- Check if the queue is empty
function Queue:IsEmpty()
return self._first > self._last
diff --git a/indra/newview/scripts/lua/WaitQueue.lua b/indra/newview/scripts/lua/WaitQueue.lua
index 6bcb9d62c2..7e10d03295 100644
--- a/indra/newview/scripts/lua/WaitQueue.lua
+++ b/indra/newview/scripts/lua/WaitQueue.lua
@@ -4,14 +4,15 @@
local fiber = require('fiber')
local Queue = require('Queue')
+local util = require('util')
local function dbg(...) end
-- local dbg = require('printf')
-local WaitQueue = Queue:new()
+local WaitQueue = Queue()
function WaitQueue:new()
- local obj = Queue:new()
+ local obj = Queue()
setmetatable(obj, self)
self.__index = self
@@ -20,6 +21,8 @@ function WaitQueue:new()
return obj
end
+util.classctor(WaitQueue)
+
function WaitQueue:Enqueue(value)
if self._closed then
error("can't Enqueue() on closed Queue")
diff --git a/indra/newview/scripts/lua/leap.lua b/indra/newview/scripts/lua/leap.lua
index 8caae24e94..82f91ce9e9 100644
--- a/indra/newview/scripts/lua/leap.lua
+++ b/indra/newview/scripts/lua/leap.lua
@@ -43,6 +43,7 @@ local ErrorQueue = require('ErrorQueue')
local inspect = require('inspect')
local function dbg(...) end
-- local dbg = require('printf')
+local util = require('util')
local leap = {}
@@ -129,7 +130,7 @@ local function requestSetup(pump, data)
-- because, unlike the WaitFor base class, WaitForReqid does not
-- self-register on our waitfors list. Instead, capture the new
-- WaitForReqid object in pending so dispatch() can find it.
- local waitfor = leap.WaitForReqid:new(reqid)
+ local waitfor = leap.WaitForReqid(reqid)
pending[reqid] = waitfor
-- Pass reqid to send() to stamp it into (a copy of) the request data.
dbg('requestSetup(%s, %s) storing %s', pump, data, waitfor.name)
@@ -432,7 +433,7 @@ function leap.WaitFor:new(priority, name)
self._id += 1
obj.name = 'WaitFor' .. self._id
end
- obj._queue = ErrorQueue:new()
+ obj._queue = ErrorQueue()
obj._registered = false
-- if no priority, then don't enable() - remember 0 is truthy
if priority then
@@ -442,6 +443,8 @@ function leap.WaitFor:new(priority, name)
return obj
end
+util.classctor(leap.WaitFor)
+
-- Re-enable a disable()d WaitFor object. New WaitFor objects are
-- enable()d by default.
function leap.WaitFor:enable()
@@ -514,13 +517,13 @@ function leap.WaitFor:exception(message)
end
-- ------------------------------ WaitForReqid -------------------------------
-leap.WaitForReqid = leap.WaitFor:new()
+leap.WaitForReqid = leap.WaitFor()
function leap.WaitForReqid:new(reqid)
-- priority is meaningless, since this object won't be added to the
-- priority-sorted waitfors list. Use the reqid as the debugging name
-- string.
- local obj = leap.WaitFor:new(nil, 'WaitForReqid(' .. reqid .. ')')
+ local obj = leap.WaitFor(nil, 'WaitForReqid(' .. reqid .. ')')
setmetatable(obj, self)
self.__index = self
@@ -529,6 +532,8 @@ function leap.WaitForReqid:new(reqid)
return obj
end
+util.classctor(leap.WaitForReqid)
+
function leap.WaitForReqid:filter(pump, data)
-- Because we expect to directly look up the WaitForReqid object of
-- interest based on the incoming ["reqid"] value, it's not necessary
diff --git a/indra/newview/scripts/lua/qtest.lua b/indra/newview/scripts/lua/qtest.lua
index 009446d0c3..9526f58b04 100644
--- a/indra/newview/scripts/lua/qtest.lua
+++ b/indra/newview/scripts/lua/qtest.lua
@@ -21,8 +21,8 @@ function resume(co, ...)
end
-- ------------------ Queue variables are instance-specific ------------------
-q1 = Queue:new()
-q2 = Queue:new()
+q1 = Queue()
+q2 = Queue()
q1:Enqueue(17)
@@ -33,8 +33,8 @@ assert(q1:Dequeue() == nil)
assert(q2:Dequeue() == nil)
-- ----------------------------- test WaitQueue ------------------------------
-q1 = WaitQueue:new()
-q2 = WaitQueue:new()
+q1 = WaitQueue()
+q2 = WaitQueue()
result = {}
values = { 1, 1, 2, 3, 5, 8, 13, 21 }
@@ -76,7 +76,7 @@ print('result:', inspect(result))
assert(util.equal(values, result))
-- try incrementally enqueueing values
-q3 = WaitQueue:new()
+q3 = WaitQueue()
result = {}
values = { 'This', 'is', 'a', 'test', 'script' }
@@ -124,7 +124,7 @@ print(string.format('%q', table.concat(result, ' ')))
assert(util.equal(values, result))
-- ----------------------------- test ErrorQueue -----------------------------
-q4 = ErrorQueue:new()
+q4 = ErrorQueue()
result = {}
values = { 'This', 'is', 'a', 'test', 'script' }
diff --git a/indra/newview/scripts/lua/test_luafloater_demo.lua b/indra/newview/scripts/lua/test_luafloater_demo.lua
index ab638dcdd1..65a31670c8 100644
--- a/indra/newview/scripts/lua/test_luafloater_demo.lua
+++ b/indra/newview/scripts/lua/test_luafloater_demo.lua
@@ -60,7 +60,7 @@ local resp = leap.request("LLFloaterReg", key)
COMMAND_PUMP_NAME = resp.command_name
reqid = resp.reqid
-catch_events = leap.WaitFor:new(-1, "all_events")
+catch_events = leap.WaitFor(-1, "all_events")
function catch_events:filter(pump, data)
if data.reqid == reqid then
return data
diff --git a/indra/newview/scripts/lua/test_luafloater_demo2.lua b/indra/newview/scripts/lua/test_luafloater_demo2.lua
index 9e24237d28..3903d01e65 100644
--- a/indra/newview/scripts/lua/test_luafloater_demo2.lua
+++ b/indra/newview/scripts/lua/test_luafloater_demo2.lua
@@ -2,7 +2,7 @@ local Floater = require 'Floater'
local leap = require 'leap'
local startup = require 'startup'
-local flt = Floater:new(
+local flt = Floater(
'luafloater_demo.xml',
{show_time_lbl = {"right_mouse_down", "double_click"}})
diff --git a/indra/newview/scripts/lua/test_luafloater_gesture_list.lua b/indra/newview/scripts/lua/test_luafloater_gesture_list.lua
index 3d9a9b0ad4..a5fd325430 100644
--- a/indra/newview/scripts/lua/test_luafloater_gesture_list.lua
+++ b/indra/newview/scripts/lua/test_luafloater_gesture_list.lua
@@ -58,7 +58,7 @@ local key = {xml_path = XML_FILE_PATH, op = "showLuaFloater"}
key.extra_events={gesture_list = {_event("double_click")}}
handleEvents(leap.request("LLFloaterReg", key))
-catch_events = leap.WaitFor:new(-1, "all_events")
+catch_events = leap.WaitFor(-1, "all_events")
function catch_events:filter(pump, data)
if data.reqid == reqid then
return data
diff --git a/indra/newview/scripts/lua/test_luafloater_gesture_list2.lua b/indra/newview/scripts/lua/test_luafloater_gesture_list2.lua
index d702d09c51..bd397ef2a6 100644
--- a/indra/newview/scripts/lua/test_luafloater_gesture_list2.lua
+++ b/indra/newview/scripts/lua/test_luafloater_gesture_list2.lua
@@ -2,7 +2,7 @@ local Floater = require 'Floater'
local LLGesture = require 'LLGesture'
local startup = require 'startup'
-local flt = Floater:new(
+local flt = Floater(
"luafloater_gesture_list.xml",
{gesture_list = {"double_click"}})
diff --git a/indra/newview/scripts/lua/test_timers.lua b/indra/newview/scripts/lua/test_timers.lua
index ed0de070f7..be5001aa16 100644
--- a/indra/newview/scripts/lua/test_timers.lua
+++ b/indra/newview/scripts/lua/test_timers.lua
@@ -6,9 +6,9 @@ local timers = require 'timers'
-- is true, that timeUntilCall() is (true, close to 10), that cancel() returns
-- true. After that, isRunning() is false, timeUntilCall() returns (false, 0),
-- and a second cancel() returns false.
-print('t0:new(10)')
+print('t0(10)')
start = os.clock()
-t0 = timers.Timer:new(10, function() print('t0 fired at', os.clock() - start) end)
+t0 = timers.Timer(10, function() print('t0 fired at', os.clock() - start) end)
print('t0:isRunning(): ', t0:isRunning())
print('t0:timeUntilCall(): ', t0:timeUntilCall())
print('t0:cancel(): ', t0:cancel())
@@ -18,16 +18,16 @@ print('t0:cancel(): ', t0:cancel())
-- t1 is supposed to fire after 5 seconds, but it doesn't wait, so you see the
-- t2 messages immediately after.
-print('t1:new(5)')
+print('t1(5)')
start = os.clock()
-t1 = timers.Timer:new(5, function() print('t1 fired at', os.clock() - start) end)
+t1 = timers.Timer(5, function() print('t1 fired at', os.clock() - start) end)
-- t2 illustrates that instead of passing a callback to new(), you can
-- override the timer instance's tick() method. But t2 doesn't wait either, so
-- you see the Timer(5) message immediately.
-print('t2:new(2)')
+print('t2(2)')
start = os.clock()
-t2 = timers.Timer:new(2)
+t2 = timers.Timer(2)
function t2:tick()
print('t2 fired at', os.clock() - start)
end
@@ -37,7 +37,7 @@ end
-- then the t1 callback message before the Timer(5) completion message.
print('Timer(5) waiting')
start = os.clock()
-timers.Timer:new(5, 'wait')
+timers.Timer(5, 'wait')
print(string.format('Timer(5) waited %f seconds', os.clock() - start))
-- This test demonstrates a repeating timer. It also shows that you can (but
@@ -50,7 +50,7 @@ print(string.format('Timer(5) waited %f seconds', os.clock() - start))
-- it's worth knowing that a coroutine timer callback can be used to manage
-- more complex control flows.
start = os.clock()
-timers.Timer:new(
+timers.Timer(
2,
coroutine.wrap(function()
for i = 1,5 do
diff --git a/indra/newview/scripts/lua/timers.lua b/indra/newview/scripts/lua/timers.lua
index e0d27a680d..e4938078dc 100644
--- a/indra/newview/scripts/lua/timers.lua
+++ b/indra/newview/scripts/lua/timers.lua
@@ -1,6 +1,7 @@
-- Access to the viewer's time-delay facilities
local leap = require 'leap'
+local util = require 'util'
local timers = {}
@@ -78,6 +79,8 @@ function timers.Timer:new(delay, callback, iterate)
return obj
end
+util.classctor(timers.Timer)
+
function timers.Timer:tick()
error('Pass a callback to Timer:new(), or override Timer:tick()')
end
diff --git a/indra/newview/scripts/lua/util.lua b/indra/newview/scripts/lua/util.lua
index a2191288f6..bfbfc8637c 100644
--- a/indra/newview/scripts/lua/util.lua
+++ b/indra/newview/scripts/lua/util.lua
@@ -2,6 +2,31 @@
local util = {}
+-- Allow MyClass(ctor args...) equivalent to MyClass:new(ctor args...)
+-- Usage:
+-- local MyClass = {}
+-- function MyClass:new(...)
+-- ...
+-- end
+-- ...
+-- util.classctor(MyClass)
+-- or if your constructor is named something other than MyClass:new(), e.g.
+-- MyClass:construct():
+-- util.classctor(MyClass, MyClass.construct)
+-- return MyClass
+function util.classctor(class, ctor)
+ -- get the metatable for the passed class
+ local mt = getmetatable(class)
+ if mt == nil then
+ -- if it doesn't already have a metatable, then create one
+ mt = {}
+ setmetatable(class, mt)
+ end
+ -- now that class has a metatable, set its __call method to the specified
+ -- constructor method (class.new if not specified)
+ mt.__call = ctor or class.new
+end
+
-- check if array-like table contains certain value
function util.contains(t, v)
return table.find(t, v) ~= nil