LiquidProxy Lua Edition
1--[[
2make lua functions for each operator.
3it looks like i'm mapping 1-1 between metamethods and fields in this table.
4useful for using Lua as a functional language.
5
6TODO rename to 'ops'?
7--]]
8
9--local load = require 'string'.load -- string.load = loadstring or load
10local load = loadstring or load
11
12-- test if we hae lua 5.3 bitwise operators
13-- orrr I could just try each op and bail out on error
14-- and honestly I should be defaulting to the 'bit' library anyways, esp in the case of luajit where it is translated to an asm opcode
15local lua53 = _VERSION >= 'Lua 5.3'
16
17local symbolscode = [[
18
19 -- which fields are unary operators
20 local unary = {
21 unm = true,
22 bnot = true,
23 len = true,
24 lnot = true,
25 }
26
27 local symbols = {
28 add = '+',
29 sub = '-',
30 mul = '*',
31 div = '/',
32 mod = '%',
33 pow = '^',
34 unm = '-', -- unary
35 concat = '..',
36 eq = '==',
37 ne = '~=',
38 lt = '<',
39 le = '<=',
40 gt = '>',
41 ge = '>=',
42 land = 'and', -- non-overloadable
43 lor = 'or', -- non-overloadable
44 len = '#', -- unary
45 lnot = 'not', -- non-overloadable, unary
46]]
47if lua53 then
48 symbolscode = symbolscode .. [[
49 idiv = '//', -- 5.3
50 band = '&', -- 5.3
51 bor = '|', -- 5.3
52 bxor = '~', -- 5.3
53 shl = '<<', -- 5.3
54 shr = '>>', -- 5.3
55 bnot = '~', -- 5.3, unary
56]]
57--[[ alternatively, luajit 'bit' library:
58I should probably include all of these instead
59would there be a perf hit from directly assigning these functions to my own table,
60 as there is a perf hit for assigning from ffi.C func ptrs to other variables? probably.
61 how about as a tail call / vararg forwarding?
62I wonder if luajit adds extra metamethods
63
64luajit 2.0 lua 5.2 lua 5.3
65band band &
66bnot bnot ~
67bor bor |
68bxor bxor ~
69lshift lshift <<
70rshift rshift >>
71arshift arshift
72rol lrotate
73ror rrotate
74bswap (reverses 32-bit integer endian-ness of bytes)
75tobit (converts from lua number to its signed 32-bit value)
76tohex (string conversion)
77 btest (does some bitflag stuff)
78 extract (same)
79 replace (same)
80--]]
81end
82symbolscode = symbolscode .. [[
83 }
84]]
85
86local symbols, unary = assert(load(symbolscode..' return symbols, unary'))()
87
88local code = symbolscode .. [[
89 -- functions for operators
90 local ops
91 ops = {
92]]
93for name,symbol in pairs(symbols) do
94 if unary[name] then
95 code = code .. [[
96 ]]..name..[[ = function(a) return ]]..symbol..[[ a end,
97]]
98 else
99 code = code .. [[
100 ]]..name..[[ = function(a,b) return a ]]..symbol..[[ b end,
101]]
102 end
103end
104code = code .. [[
105 index = function(t, k) return t[k] end,
106 newindex = function(t, k, v)
107 t[k] = v
108 return t, k, v -- ? should it return anything ?
109 end,
110 call = function(f, ...) return f(...) end,
111
112 symbols = symbols,
113
114 -- special pcall wrapping index, thanks luajit. thanks.
115 -- while i'm here, multiple indexing, so it bails out nil early, so it's a chained .? operator
116 safeindex = function(t, ...)
117 if select('#', ...) == 0 then return t end
118 local res, v = pcall(ops.index, t, ...)
119 if not res then return nil, v end
120 return ops.safeindex(v, select(2, ...))
121 end,
122 }
123 return ops
124]]
125return assert(load(code))()