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