Skip to main content

lua_std/
metatable.rs

1//! Metatables and metamethods.
2
3use crate::{any, boolean, nil, number, string, table, Repeatable};
4
5/// Metamethods controlling the arithmetic operators.
6///
7/// Each event fires when the corresponding operator is applied to a value
8/// that does not support it natively — for example, adding two tables
9/// looks for an `__add` field in either operand's metatable and calls it
10/// with both operands.
11pub trait arithmetic {
12    /// The addition (`+`) operation.
13    ///
14    /// # Examples
15    ///
16    /// ```lua
17    /// local mt = { __add = function(a, b) return a.n + b.n end }
18    /// local a = setmetatable({ n = 1 }, mt)
19    /// local b = setmetatable({ n = 2 }, mt)
20    /// print(a + b)    --> 3
21    /// ```
22    fn __add(&self, other: any) -> any {
23        todo!()
24    }
25
26    /// The subtraction (`-`) operation.
27    ///
28    /// # Examples
29    ///
30    /// ```lua
31    /// mt.__sub = function(a, b) return a.n - b.n end
32    /// print(a - b)    --> -1
33    /// ```
34    fn __sub(&self, other: any) -> any {
35        todo!()
36    }
37
38    /// The multiplication (`*`) operation.
39    ///
40    /// # Examples
41    ///
42    /// ```lua
43    /// mt.__mul = function(a, b) return a.n * b.n end
44    /// print(a * b)    --> 2
45    /// ```
46    fn __mul(&self, other: any) -> any {
47        todo!()
48    }
49
50    /// The division (`/`) operation.
51    ///
52    /// # Examples
53    ///
54    /// ```lua
55    /// mt.__div = function(a, b) return a.n / b.n end
56    /// print(a / b)    --> 0.5
57    /// ```
58    fn __div(&self, other: any) -> any {
59        todo!()
60    }
61
62    /// The modulo (`%`) operation.
63    ///
64    /// # Examples
65    ///
66    /// ```lua
67    /// mt.__mod = function(a, b) return a.n % b.n end
68    /// print(a % b)    --> 1
69    /// ```
70    fn __mod(&self, other: any) -> any {
71        todo!()
72    }
73
74    /// The exponentiation (`^`) operation.
75    ///
76    /// # Examples
77    ///
78    /// ```lua
79    /// mt.__pow = function(a, b) return a.n ^ b.n end
80    /// print(a ^ b)    --> 1.0
81    /// ```
82    fn __pow(&self, other: any) -> any {
83        todo!()
84    }
85
86    /// The negation (unary `-`) operation.
87    ///
88    /// # Examples
89    ///
90    /// ```lua
91    /// mt.__unm = function(v) return -v.n end
92    /// print(-a)    --> -1
93    /// ```
94    fn __unm(&self) -> any {
95        todo!()
96    }
97
98    /// The floor division (`//`) operation.
99    ///
100    /// # Examples
101    ///
102    /// ```lua
103    /// mt.__idiv = function(a, b) return a.n // b.n end
104    /// print(a // b)    --> 0
105    /// ```
106    fn __idiv(&self, other: any) -> any {
107        todo!()
108    }
109}
110
111/// Metamethods controlling the bitwise operators.
112///
113/// These events fire when a bitwise operator is applied to an operand
114/// that is neither an integer nor a value convertible to an integer.
115pub trait bitwise {
116    /// The bitwise AND (`&`) operation.
117    ///
118    /// # Examples
119    ///
120    /// ```lua
121    /// local mt = { __band = function(a, b) return a.bits & b.bits end }
122    /// local a = setmetatable({ bits = 0x0F }, mt)
123    /// local b = setmetatable({ bits = 0x03 }, mt)
124    /// print(a & b)    --> 3
125    /// ```
126    fn __band(&self, other: any) -> any {
127        todo!()
128    }
129
130    /// The bitwise OR (`|`) operation.
131    ///
132    /// # Examples
133    ///
134    /// ```lua
135    /// mt.__bor = function(a, b) return a.bits | b.bits end
136    /// print(a | b)    --> 15
137    /// ```
138    fn __bor(&self, other: any) -> any {
139        todo!()
140    }
141
142    /// The bitwise exclusive OR (`~`) operation.
143    ///
144    /// # Examples
145    ///
146    /// ```lua
147    /// mt.__bxor = function(a, b) return a.bits ~ b.bits end
148    /// print(a ~ b)    --> 12
149    /// ```
150    fn __bxor(&self, other: any) -> any {
151        todo!()
152    }
153
154    /// The bitwise NOT (unary `~`) operation.
155    ///
156    /// # Examples
157    ///
158    /// ```lua
159    /// mt.__bnot = function(v) return ~v.bits & 0xFF end
160    /// print(~a)    --> 240
161    /// ```
162    fn __bnot(&self) -> any {
163        todo!()
164    }
165
166    /// The bitwise left shift (`<<`) operation.
167    ///
168    /// # Examples
169    ///
170    /// ```lua
171    /// mt.__shl = function(a, b) return a.bits << b.bits end
172    /// print(a << b)    --> 120
173    /// ```
174    fn __shl(&self, other: any) -> any {
175        todo!()
176    }
177
178    /// The bitwise right shift (`>>`) operation.
179    ///
180    /// # Examples
181    ///
182    /// ```lua
183    /// mt.__shr = function(a, b) return a.bits >> b.bits end
184    /// print(a >> b)    --> 1
185    /// ```
186    fn __shr(&self, other: any) -> any {
187        todo!()
188    }
189}
190
191/// Metamethods controlling the comparison operators.
192///
193/// Note that `a > b` is translated to `b < a` and `a >= b` to `b <= a`,
194/// so only three events exist.
195pub trait comparison {
196    /// The equal (`==`) operation. Only invoked when the values being
197    /// compared are both tables or both full userdata and they are not
198    /// primitively equal. The result is always converted to a boolean.
199    ///
200    /// # Examples
201    ///
202    /// ```lua
203    /// local mt = { __eq = function(a, b) return a.x == b.x and a.y == b.y end }
204    /// local p = setmetatable({ x = 1, y = 2 }, mt)
205    /// local q = setmetatable({ x = 1, y = 2 }, mt)
206    /// print(p == q)    --> true   (same coordinates, different tables)
207    /// ```
208    fn __eq(&self, other: any) -> boolean {
209        todo!()
210    }
211
212    /// The less than (`<`) operation.
213    ///
214    /// # Examples
215    ///
216    /// ```lua
217    /// local mt = { __lt = function(a, b) return a.len < b.len end }
218    /// local short = setmetatable({ len = 1 }, mt)
219    /// local long  = setmetatable({ len = 9 }, mt)
220    /// print(short < long)    --> true
221    /// print(long > short)    --> true   (a > b runs __lt(b, a))
222    /// ```
223    fn __lt(&self, other: any) -> boolean {
224        todo!()
225    }
226
227    /// The less equal (`<=`) operation.
228    ///
229    /// # Examples
230    ///
231    /// ```lua
232    /// mt.__le = function(a, b) return a.len <= b.len end
233    /// print(short <= long)    --> true
234    /// ```
235    fn __le(&self, other: any) -> boolean {
236        todo!()
237    }
238}
239
240/// Metamethods controlling indexed access.
241pub trait indexing {
242    /// The indexing access operation `t[key]`. Invoked when `t` is not a
243    /// table or when `key` is not present in the table. The metavalue may
244    /// be a function (called with `t` and `key`) or a table (in which
245    /// the access is repeated) — the latter is the basis of inheritance
246    /// in Lua.
247    ///
248    /// ```lua
249    /// setmetatable(child, { __index = parent })
250    /// ```
251    fn __index(&self, key: any) -> any {
252        todo!()
253    }
254
255    /// The indexing assignment `t[key] = value`. Invoked when `t` is not
256    /// a table or when `key` is not present in the table. Like `__index`,
257    /// the metavalue may be a function or another table.
258    ///
259    /// # Examples
260    ///
261    /// ```lua
262    /// local data = {}
263    /// local t = setmetatable({}, {
264    ///   __newindex = function(t, k, v)
265    ///     print("setting", k)
266    ///     rawset(data, k, v)     -- rawset avoids re-triggering __newindex
267    ///   end,
268    /// })
269    /// t.answer = 42    --> setting   answer
270    /// ```
271    fn __newindex(&self, key: any, value: any) {
272        todo!()
273    }
274}
275
276/// Metamethod making a value callable.
277pub trait callable {
278    /// The call operation `f(args)`. Invoked when Lua tries to call a
279    /// non-function value: its `__call` metavalue is called with the
280    /// value itself as the first argument, followed by the original
281    /// arguments.
282    ///
283    /// # Examples
284    ///
285    /// ```lua
286    /// local counter = setmetatable({ n = 0 }, {
287    ///   __call = function(self)
288    ///     self.n = self.n + 1
289    ///     return self.n
290    ///   end,
291    /// })
292    /// print(counter(), counter(), counter())    --> 1   2   3
293    /// ```
294    fn __call(&self, args: Repeatable<any>) -> Repeatable<any> {
295        todo!()
296    }
297}
298
299/// Metamethod controlling the length operator.
300pub trait length {
301    /// The length (`#`) operation. If the value is not a string and its
302    /// metatable defines `__len`, that metavalue is called with the value
303    /// as argument and its result becomes the length.
304    ///
305    /// # Examples
306    ///
307    /// ```lua
308    /// local t = setmetatable({}, { __len = function() return 42 end })
309    /// print(#t)    --> 42
310    /// ```
311    fn __len(&self) -> number {
312        todo!()
313    }
314}
315
316/// Metamethod controlling the concatenation operator.
317pub trait concatenation {
318    /// The concatenation (`..`) operation. Invoked whenever an operand is
319    /// neither a string nor a number.
320    ///
321    /// # Examples
322    ///
323    /// ```lua
324    /// local mt = { __concat = function(a, b) return "<" .. a.tag .. b .. ">" end }
325    /// local x = setmetatable({ tag = "x" }, mt)
326    /// print(x .. "!")    --> <x!>
327    /// ```
328    fn __concat(&self, other: any) -> any {
329        todo!()
330    }
331}
332
333/// Metamethods controlling string conversion.
334pub trait tostring {
335    /// Invoked by [`tostring()`](crate::tostring()) (and therefore by
336    /// [`print`](crate::print)) to convert the value to a string.
337    ///
338    /// # Examples
339    ///
340    /// ```lua
341    /// local pt = setmetatable({ x = 1, y = 2 }, {
342    ///   __tostring = function(p) return "(" .. p.x .. ", " .. p.y .. ")" end,
343    /// })
344    /// print(pt)    --> (1, 2)
345    /// ```
346    fn __tostring(&self) -> string {
347        todo!()
348    }
349
350    /// A string naming the type of the value, used in error messages and
351    /// by `tostring` when `__tostring` is absent.
352    ///
353    /// # Examples
354    ///
355    /// ```lua
356    /// local obj = setmetatable({}, { __name = "Point" })
357    /// print(obj)    --> Point: 0x...
358    /// ```
359    fn __name(&self) -> string {
360        todo!()
361    }
362}
363
364/// Metamethods controlling the life cycle of a value.
365pub trait lifecycle {
366    /// The finalizer: called by the garbage collector when the value is
367    /// collected, if the metatable had a `__gc` field when it was set.
368    ///
369    /// # Examples
370    ///
371    /// ```lua
372    /// setmetatable({}, { __gc = function() print("collected") end })
373    /// collectgarbage()    --> collected
374    /// ```
375    fn __gc(&self) {
376        todo!()
377    }
378
379    /// Called when the value, used as a to-be-closed variable
380    /// (`local x <close> = ...`), goes out of scope.
381    ///
382    /// # Examples
383    ///
384    /// ```lua
385    /// do
386    ///   local guard <close> = setmetatable({}, {
387    ///     __close = function() print("closed") end,
388    ///   })
389    ///   print("inside")
390    /// end
391    /// --> inside
392    /// --> closed
393    /// ```
394    fn __close(&self, errobj: any) {
395        todo!()
396    }
397
398    /// A metavalue controlling how the value behaves as a weak table:
399    /// `"k"` for weak keys, `"v"` for weak values, `"kv"` for both.
400    ///
401    /// # Examples
402    ///
403    /// ```lua
404    /// local cache = setmetatable({}, { __mode = "k" })   -- weak keys
405    /// cache[{}] = "value"
406    /// collectgarbage()
407    /// print(next(cache))    --> nil   (the key was collected)
408    /// ```
409    fn __mode(&self) -> string {
410        todo!()
411    }
412
413    /// If present, protects the metatable: [`getmetatable`](crate::getmetatable)
414    /// returns this metavalue instead, and
415    /// [`setmetatable`](crate::setmetatable) raises an error.
416    ///
417    /// # Examples
418    ///
419    /// ```lua
420    /// local t = setmetatable({}, { __metatable = "locked" })
421    /// print(getmetatable(t))            --> locked
422    /// print(pcall(setmetatable, t, {}))  --> false   cannot change a protected metatable
423    /// ```
424    fn __metatable(&self) -> any {
425        todo!()
426    }
427}
428
429impl arithmetic for number {}
430impl bitwise for number {}
431impl comparison for number {}
432impl tostring for nil {}
433impl tostring for boolean {}
434impl tostring for number {}
435
436impl comparison for string {}
437impl concatenation for string {}
438impl length for string {}
439impl indexing for string {}
440impl tostring for string {}
441
442impl arithmetic for table {}
443impl bitwise for table {}
444impl comparison for table {}
445impl indexing for table {}
446impl callable for table {}
447impl length for table {}
448impl concatenation for table {}
449impl tostring for table {}
450impl lifecycle for table {}