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 {}