@px-petals/roku.motion-web 0.0.0-stage → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/audio/audio.cues.js +27 -0
- package/audio/audio.js +259 -0
- package/bands/bands.js +392 -0
- package/bundle/bundle.fonts.js +55 -0
- package/bundle/bundle.js +131 -0
- package/focus/focus.direction.js +46 -0
- package/focus/focus.dom.js +158 -0
- package/focus/focus.js +277 -0
- package/focus/focus.tree.js +146 -0
- package/hit/hit.geometry.js +113 -0
- package/hit/hit.js +129 -0
- package/list/list.flex.js +181 -0
- package/list/list.items.js +80 -0
- package/list/list.js +518 -0
- package/lottie/lottie.js +124 -0
- package/lottie/lottie.layers.js +416 -0
- package/lottie/lottie.paint.js +238 -0
- package/lottie/lottie.paths.js +474 -0
- package/lottie/lottie.props.js +265 -0
- package/lottie/lottie.shapes.js +259 -0
- package/mixer/mixer.js +307 -0
- package/mixer/mixer.mix.js +107 -0
- package/mixer/mixer.stage.js +431 -0
- package/motion/motion.convert.js +404 -0
- package/motion/motion.flow.js +421 -0
- package/motion/motion.keys.js +150 -0
- package/motion/motion.machine.js +382 -0
- package/motion/motion.nested.js +345 -0
- package/motion/motion.values.js +368 -0
- package/motion.js +1155 -0
- package/package.json +47 -4
- package/player/overlay/overlay.js +325 -0
- package/player/overlay/overlay.layout.js +208 -0
- package/player/player.fit.js +101 -0
- package/player/player.js +421 -0
- package/player/player.raster.js +127 -0
- package/pointer/pointer.js +292 -0
- package/readme.md +345 -0
- package/script/luau/lib/base/base.js +202 -0
- package/script/luau/lib/base/base.table.js +189 -0
- package/script/luau/lib/lib.args.js +152 -0
- package/script/luau/lib/lib.js +23 -0
- package/script/luau/lib/math/math.bit32.js +144 -0
- package/script/luau/lib/math/math.js +288 -0
- package/script/luau/lib/math/math.vector.js +125 -0
- package/script/luau/lib/string/string.format.js +143 -0
- package/script/luau/lib/string/string.js +160 -0
- package/script/luau/lib/string/string.pattern.js +505 -0
- package/script/luau/load/load.js +362 -0
- package/script/luau/load/load.ops.js +79 -0
- package/script/luau/luau.convert.js +259 -0
- package/script/luau/luau.js +132 -0
- package/script/luau/luau.md +111 -0
- package/script/luau/vm/vm.js +167 -0
- package/script/luau/vm/vm.meta.js +401 -0
- package/script/luau/vm/vm.num.js +236 -0
- package/script/luau/vm/vm.run.js +842 -0
- package/script/luau/vm/vm.value.js +406 -0
- package/script/play/play.js +199 -0
- package/script/play/play.objects.js +295 -0
- package/script/play/play.scope.js +91 -0
- package/script/rive/api/api.statics.js +31 -0
- package/script/rive/api/api.type.js +188 -0
- package/script/rive/api/artboard/artboard.js +89 -0
- package/script/rive/api/assets/assets.js +72 -0
- package/script/rive/api/data/data.value.js +99 -0
- package/script/rive/api/draw/draw.contours.js +163 -0
- package/script/rive/api/draw/draw.measure.js +196 -0
- package/script/rive/api/draw/draw.paint.js +235 -0
- package/script/rive/api/draw/draw.path.js +153 -0
- package/script/rive/api/draw/draw.renderer.js +117 -0
- package/script/rive/api/math/math.color.js +96 -0
- package/script/rive/api/math/math.mat2d.js +180 -0
- package/script/rive/api/math/math.vector.js +121 -0
- package/script/rive/api/media/media.audio.js +113 -0
- package/script/rive/api/media/media.draw.js +73 -0
- package/script/rive/api/media/media.image.js +61 -0
- package/script/rive/api/media/media.mesh.js +50 -0
- package/script/rive/api/pointer/pointer.event.js +64 -0
- package/script/rive/api/pointer/pointer.route.js +69 -0
- package/script/rive/api/text/text.font.js +129 -0
- package/script/rive/api/text/text.js +278 -0
- package/script/rive/api/text/text.layout.js +259 -0
- package/script/rive/context/context.js +76 -0
- package/script/rive/context/context.memory.js +196 -0
- package/script/rive/context/context.viewmodel.js +302 -0
- package/script/rive/context/lists/lists.js +160 -0
- package/script/rive/context/lists/lists.values.js +281 -0
- package/script/rive/host/host.globals.js +44 -0
- package/script/rive/host/host.js +533 -0
- package/script/rive/host/host.node.js +45 -0
- package/script/rive/rive.js +23 -0
- package/script/rive/rive.md +180 -0
- package/script/script.js +11 -0
- package/skin/skin.deform.js +514 -0
- package/skin/skin.ik.js +260 -0
- package/skin/skin.js +297 -0
- package/README.md +0 -3
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `table` library.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { LuaTable, fail, typeName } from '../../vm/vm.value.js'
|
|
6
|
+
import { lessThan, truthy } from '../../vm/vm.meta.js'
|
|
7
|
+
import { argError, checkFunction, checkInt, checkTable, optInt, register } from '../lib.args.js'
|
|
8
|
+
import { unpack } from './base.js'
|
|
9
|
+
|
|
10
|
+
/** @param {LuaTable} t */
|
|
11
|
+
function writable(t) {
|
|
12
|
+
if (t.frozen) throw fail('attempt to modify a readonly table')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Sorts `list` in place with `less`, stably (merge sort).
|
|
17
|
+
*
|
|
18
|
+
* @param {any[]} list
|
|
19
|
+
* @param {(a: any, b: any) => boolean} less
|
|
20
|
+
*/
|
|
21
|
+
function sort(list, less) {
|
|
22
|
+
const n = list.length
|
|
23
|
+
if (n < 2) return
|
|
24
|
+
let src = list
|
|
25
|
+
let dst = new Array(n)
|
|
26
|
+
for (let width = 1; width < n; width *= 2) {
|
|
27
|
+
for (let lo = 0; lo < n; lo += 2 * width) {
|
|
28
|
+
const mid = Math.min(lo + width, n)
|
|
29
|
+
const hi = Math.min(lo + 2 * width, n)
|
|
30
|
+
let i = lo
|
|
31
|
+
let j = mid
|
|
32
|
+
let o = lo
|
|
33
|
+
while (i < mid && j < hi) dst[o++] = less(src[j], src[i]) ? src[j++] : src[i++]
|
|
34
|
+
while (i < mid) dst[o++] = src[i++]
|
|
35
|
+
while (j < hi) dst[o++] = src[j++]
|
|
36
|
+
}
|
|
37
|
+
const swap = src
|
|
38
|
+
src = dst
|
|
39
|
+
dst = swap
|
|
40
|
+
}
|
|
41
|
+
if (src !== list) for (let i = 0; i < n; i++) list[i] = src[i]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {import('../../vm/vm.js').VM} vm
|
|
46
|
+
* @param {LuaTable} G
|
|
47
|
+
*/
|
|
48
|
+
export function installTable(vm, G) {
|
|
49
|
+
const table = new LuaTable()
|
|
50
|
+
G.set('table', table)
|
|
51
|
+
|
|
52
|
+
register(table, {
|
|
53
|
+
insert(vm, args) {
|
|
54
|
+
const t = checkTable(args, 0, 'insert')
|
|
55
|
+
writable(t)
|
|
56
|
+
const n = t.length()
|
|
57
|
+
if (args.length === 2) {
|
|
58
|
+
t.set(n + 1, args[1])
|
|
59
|
+
return []
|
|
60
|
+
}
|
|
61
|
+
if (args.length !== 3) throw fail("wrong number of arguments to 'insert'")
|
|
62
|
+
const pos = checkInt(args, 1, 'insert')
|
|
63
|
+
if (pos < 1 || pos > n + 1) throw argError(2, 'insert', 'position out of bounds')
|
|
64
|
+
if (args[2] === undefined) return []
|
|
65
|
+
t.arr.splice(pos - 1, 0, args[2])
|
|
66
|
+
if (t.hn !== null) t.migrate()
|
|
67
|
+
return []
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
remove(vm, args) {
|
|
71
|
+
const t = checkTable(args, 0, 'remove')
|
|
72
|
+
writable(t)
|
|
73
|
+
const n = t.length()
|
|
74
|
+
const pos = optInt(args, 1, 'remove', n)
|
|
75
|
+
if (n === 0 && args[1] === undefined) return undefined
|
|
76
|
+
if (pos < 1 || pos > n) {
|
|
77
|
+
if (args[1] !== undefined && pos !== n + 1) throw argError(2, 'remove', 'position out of bounds')
|
|
78
|
+
return undefined
|
|
79
|
+
}
|
|
80
|
+
const v = t.arr[pos - 1]
|
|
81
|
+
t.arr.splice(pos - 1, 1)
|
|
82
|
+
let m = t.arr.length
|
|
83
|
+
while (m > 0 && t.arr[m - 1] === undefined) m--
|
|
84
|
+
t.arr.length = m
|
|
85
|
+
return v
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
concat(vm, args) {
|
|
89
|
+
const t = checkTable(args, 0, 'concat')
|
|
90
|
+
const sep = args[1] === undefined ? '' : String(args[1])
|
|
91
|
+
const i = optInt(args, 2, 'concat', 1)
|
|
92
|
+
const j = optInt(args, 3, 'concat', t.length())
|
|
93
|
+
const parts = []
|
|
94
|
+
for (let n = i; n <= j; n++) {
|
|
95
|
+
const v = t.get(n)
|
|
96
|
+
if (typeof v === 'string') parts.push(v)
|
|
97
|
+
else if (typeof v === 'number') parts.push(vm.tostring(v))
|
|
98
|
+
else throw fail('invalid value (' + typeName(v) + ') at index ' + n + " in table for 'concat'")
|
|
99
|
+
}
|
|
100
|
+
return parts.join(sep)
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
unpack(vm, args) {
|
|
104
|
+
return unpack(checkTable(args, 0, 'unpack'), args[1], args[2])
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
pack(vm, args) {
|
|
108
|
+
const t = new LuaTable()
|
|
109
|
+
t.setRange(1, args, 0, args.length)
|
|
110
|
+
t.set('n', args.length)
|
|
111
|
+
return t
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
sort(vm, args) {
|
|
115
|
+
const t = checkTable(args, 0, 'sort')
|
|
116
|
+
writable(t)
|
|
117
|
+
const cmp = args[1]
|
|
118
|
+
if (cmp !== undefined) checkFunction(args, 1, 'sort')
|
|
119
|
+
const n = t.length()
|
|
120
|
+
const list = t.arr.slice(0, n)
|
|
121
|
+
/** @type {(a: any, b: any) => boolean} */
|
|
122
|
+
const less = cmp === undefined
|
|
123
|
+
? function (a, b) { return lessThan(vm, a, b) }
|
|
124
|
+
: function (a, b) { return truthy(vm.call(cmp, [ a, b ])[0]) }
|
|
125
|
+
sort(list, less)
|
|
126
|
+
for (let i = 0; i < n; i++) t.arr[i] = list[i]
|
|
127
|
+
return []
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
find(vm, args) {
|
|
131
|
+
const t = checkTable(args, 0, 'find')
|
|
132
|
+
const init = optInt(args, 2, 'find', 1)
|
|
133
|
+
const n = t.length()
|
|
134
|
+
for (let i = init; i <= n; i++) if (t.get(i) === args[1]) return i
|
|
135
|
+
return undefined
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
clear(vm, args) {
|
|
139
|
+
const t = checkTable(args, 0, 'clear')
|
|
140
|
+
writable(t)
|
|
141
|
+
t.arr.length = 0
|
|
142
|
+
for (let s = 0; s < t.hv.length; s++) t.hv[s] = undefined
|
|
143
|
+
t.dead = t.hv.length
|
|
144
|
+
return []
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
create(vm, args) {
|
|
148
|
+
const n = checkInt(args, 0, 'create')
|
|
149
|
+
if (n < 0) throw argError(1, 'create', 'size out of range')
|
|
150
|
+
const t = new LuaTable()
|
|
151
|
+
if (args[1] !== undefined) for (let i = 1; i <= n; i++) t.set(i, args[1])
|
|
152
|
+
return t
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
clone(vm, args) {
|
|
156
|
+
return checkTable(args, 0, 'clone').clone()
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
freeze(vm, args) {
|
|
160
|
+
const t = checkTable(args, 0, 'freeze')
|
|
161
|
+
if (t.meta !== undefined && t.meta.getStr('__metatable') !== undefined) throw argError(1, 'freeze', 'table has a protected metatable')
|
|
162
|
+
t.frozen = true
|
|
163
|
+
return t
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
isfrozen(vm, args) {
|
|
167
|
+
return checkTable(args, 0, 'isfrozen').frozen
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
getn(vm, args) {
|
|
171
|
+
return checkTable(args, 0, 'getn').length()
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
move(vm, args) {
|
|
175
|
+
const a1 = checkTable(args, 0, 'move')
|
|
176
|
+
const f = checkInt(args, 1, 'move')
|
|
177
|
+
const e = checkInt(args, 2, 'move')
|
|
178
|
+
const t = checkInt(args, 3, 'move')
|
|
179
|
+
const a2 = args[4] === undefined ? a1 : checkTable(args, 4, 'move')
|
|
180
|
+
writable(a2)
|
|
181
|
+
if (e >= f) {
|
|
182
|
+
if (!(f > 0 || e < Number.MAX_VALUE + f)) throw argError(3, 'move', 'too many elements to move')
|
|
183
|
+
if (t > e || t <= f || a1 !== a2) for (let i = 0; i <= e - f; i++) a2.set(t + i, a1.get(f + i))
|
|
184
|
+
else for (let i = e - f; i >= 0; i--) a2.set(t + i, a1.get(f + i))
|
|
185
|
+
}
|
|
186
|
+
return a2
|
|
187
|
+
},
|
|
188
|
+
}, 'table.')
|
|
189
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Argument checks for native library functions, with Luau's messages
|
|
3
|
+
* (`invalid argument #1 to 'insert' (table expected, got nil)`).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { LuaTable, NativeFunction, LuaClosure, fail, typeName } from '../vm/vm.value.js'
|
|
7
|
+
import { toNumber } from '../vm/vm.meta.js'
|
|
8
|
+
import { numberToString } from '../vm/vm.num.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {number} n 1-based argument number
|
|
12
|
+
* @param {string} fname
|
|
13
|
+
* @param {string} message
|
|
14
|
+
*/
|
|
15
|
+
export function argError(n, fname, message) {
|
|
16
|
+
return fail('invalid argument #' + n + " to '" + fname + "' (" + message + ')')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {any[]} args
|
|
21
|
+
* @param {number} i 0-based
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
function got(args, i) {
|
|
25
|
+
return typeName(args[i])
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The error for an argument of the wrong type: Luau says "missing argument"
|
|
30
|
+
* when there is none at all, and "invalid argument" with the type it got otherwise.
|
|
31
|
+
*
|
|
32
|
+
* @param {any[]} args
|
|
33
|
+
* @param {number} i 0-based
|
|
34
|
+
* @param {string} fname
|
|
35
|
+
* @param {string} expected such as 'table'
|
|
36
|
+
*/
|
|
37
|
+
export function typeError(args, i, fname, expected) {
|
|
38
|
+
if (i >= args.length) return fail('missing argument #' + (i + 1) + " to '" + fname + "' (" + expected + ' expected)')
|
|
39
|
+
return argError(i + 1, fname, expected + ' expected, got ' + got(args, i))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {any[]} args
|
|
44
|
+
* @param {number} i 0-based
|
|
45
|
+
* @param {string} fname
|
|
46
|
+
* @returns {LuaTable}
|
|
47
|
+
*/
|
|
48
|
+
export function checkTable(args, i, fname) {
|
|
49
|
+
const v = args[i]
|
|
50
|
+
if (!(v instanceof LuaTable)) throw typeError(args, i, fname, 'table')
|
|
51
|
+
return v
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {any[]} args
|
|
56
|
+
* @param {number} i
|
|
57
|
+
* @param {string} fname
|
|
58
|
+
* @returns {number} a number, or a string that reads as one
|
|
59
|
+
*/
|
|
60
|
+
export function checkNumber(args, i, fname) {
|
|
61
|
+
const n = toNumber(args[i])
|
|
62
|
+
if (n === undefined) throw typeError(args, i, fname, 'number')
|
|
63
|
+
return n
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {any[]} args
|
|
68
|
+
* @param {number} i
|
|
69
|
+
* @param {string} fname
|
|
70
|
+
* @param {number} def
|
|
71
|
+
* @returns {number}
|
|
72
|
+
*/
|
|
73
|
+
export function optNumber(args, i, fname, def) {
|
|
74
|
+
return args[i] === undefined ? def : checkNumber(args, i, fname)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {any[]} args
|
|
79
|
+
* @param {number} i
|
|
80
|
+
* @param {string} fname
|
|
81
|
+
* @returns {number} an integer: the number cut toward zero
|
|
82
|
+
*/
|
|
83
|
+
export function checkInt(args, i, fname) {
|
|
84
|
+
const n = checkNumber(args, i, fname)
|
|
85
|
+
return n < 0 ? Math.ceil(n) : Math.floor(n)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @param {any[]} args
|
|
90
|
+
* @param {number} i
|
|
91
|
+
* @param {string} fname
|
|
92
|
+
* @param {number} def
|
|
93
|
+
* @returns {number}
|
|
94
|
+
*/
|
|
95
|
+
export function optInt(args, i, fname, def) {
|
|
96
|
+
return args[i] === undefined ? def : checkInt(args, i, fname)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {any[]} args
|
|
101
|
+
* @param {number} i
|
|
102
|
+
* @param {string} fname
|
|
103
|
+
* @returns {string} a string, or a number written as one
|
|
104
|
+
*/
|
|
105
|
+
export function checkString(args, i, fname) {
|
|
106
|
+
const v = args[i]
|
|
107
|
+
if (typeof v === 'string') return v
|
|
108
|
+
if (typeof v === 'number') return numberToString(v)
|
|
109
|
+
throw typeError(args, i, fname, 'string')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @param {any[]} args
|
|
114
|
+
* @param {number} i
|
|
115
|
+
* @param {string} fname
|
|
116
|
+
* @param {string} def
|
|
117
|
+
* @returns {string}
|
|
118
|
+
*/
|
|
119
|
+
export function optString(args, i, fname, def) {
|
|
120
|
+
return args[i] === undefined ? def : checkString(args, i, fname)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {any[]} args
|
|
125
|
+
* @param {number} i
|
|
126
|
+
* @param {string} fname
|
|
127
|
+
* @returns {any} a function
|
|
128
|
+
*/
|
|
129
|
+
export function checkFunction(args, i, fname) {
|
|
130
|
+
const v = args[i]
|
|
131
|
+
if (!(v instanceof LuaClosure) && !(v instanceof NativeFunction)) throw typeError(args, i, fname, 'function')
|
|
132
|
+
return v
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @param {any[]} args
|
|
137
|
+
* @param {number} i
|
|
138
|
+
*/
|
|
139
|
+
export function checkAny(args, i) {
|
|
140
|
+
if (i >= args.length) throw fail('missing argument #' + (i + 1))
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Puts native functions into a table under their names.
|
|
145
|
+
*
|
|
146
|
+
* @param {LuaTable} table
|
|
147
|
+
* @param {Record<string, import('../vm/vm.value.js').NativeCall>} fns
|
|
148
|
+
* @param {string} [prefix] such as 'string.', so errors and `tostring` name the function
|
|
149
|
+
*/
|
|
150
|
+
export function register(table, fns, prefix) {
|
|
151
|
+
for (const name in fns) table.set(name, new NativeFunction((prefix || '') + name, fns[name]))
|
|
152
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installs the standard library subset into a VM's globals: base, `string`,
|
|
3
|
+
* `table`, `math`, `bit32`, `vector` and `os`. The host adds its own globals
|
|
4
|
+
* to `vm.globals` afterwards.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { installBase } from './base/base.js'
|
|
8
|
+
import { installTable } from './base/base.table.js'
|
|
9
|
+
import { installBit32 } from './math/math.bit32.js'
|
|
10
|
+
import { installMath } from './math/math.js'
|
|
11
|
+
import { installVector } from './math/math.vector.js'
|
|
12
|
+
import { installString } from './string/string.js'
|
|
13
|
+
|
|
14
|
+
/** @param {import('../vm/vm.js').VM} vm */
|
|
15
|
+
export function installLibs(vm) {
|
|
16
|
+
const G = vm.globals
|
|
17
|
+
installBase(vm, G)
|
|
18
|
+
installString(vm, G)
|
|
19
|
+
installTable(vm, G)
|
|
20
|
+
installMath(vm, G)
|
|
21
|
+
installBit32(vm, G)
|
|
22
|
+
installVector(vm, G)
|
|
23
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `bit32` library: 32-bit unsigned integer operations on doubles.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { LuaTable, fail } from '../../vm/vm.value.js'
|
|
6
|
+
import { argError, checkNumber, register } from '../lib.args.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {any[]} args
|
|
10
|
+
* @param {number} i
|
|
11
|
+
* @param {string} name
|
|
12
|
+
* @returns {number} the argument as an unsigned 32-bit integer
|
|
13
|
+
*/
|
|
14
|
+
function u32(args, i, name) {
|
|
15
|
+
return checkNumber(args, i, name) >>> 0
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {number} x
|
|
20
|
+
* @param {number} disp positive shifts left, negative right
|
|
21
|
+
* @returns {number}
|
|
22
|
+
*/
|
|
23
|
+
function shift(x, disp) {
|
|
24
|
+
if (disp <= -32 || disp >= 32) return 0
|
|
25
|
+
return (disp >= 0 ? x << disp : x >>> -disp) >>> 0
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {import('../../vm/vm.js').VM} vm
|
|
30
|
+
* @param {LuaTable} G
|
|
31
|
+
*/
|
|
32
|
+
export function installBit32(vm, G) {
|
|
33
|
+
const bit32 = new LuaTable()
|
|
34
|
+
G.set('bit32', bit32)
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {string} name
|
|
38
|
+
* @param {(a: number, b: number) => number} f
|
|
39
|
+
* @param {number} init
|
|
40
|
+
*/
|
|
41
|
+
const fold = function (name, f, init) {
|
|
42
|
+
bit32.set(name, vm.native('bit32.' + name, function (vm2, args) {
|
|
43
|
+
let r = init
|
|
44
|
+
for (let i = 0; i < args.length; i++) r = f(r, u32(args, i, name)) >>> 0
|
|
45
|
+
return r
|
|
46
|
+
}))
|
|
47
|
+
}
|
|
48
|
+
fold('band', function (a, b) { return a & b }, 0xffffffff)
|
|
49
|
+
fold('bor', function (a, b) { return a | b }, 0)
|
|
50
|
+
fold('bxor', function (a, b) { return a ^ b }, 0)
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {any[]} args
|
|
54
|
+
* @param {string} name
|
|
55
|
+
* @returns {[number, number]} field start and width
|
|
56
|
+
*/
|
|
57
|
+
const field = function (args, name) {
|
|
58
|
+
const f = checkNumber(args, 1, name)
|
|
59
|
+
const w = args[2] === undefined ? 1 : checkNumber(args, 2, name)
|
|
60
|
+
if (f < 0) throw argError(2, name, 'field cannot be negative')
|
|
61
|
+
if (w <= 0) throw argError(3, name, 'width must be positive')
|
|
62
|
+
if (f + w > 32) throw fail('trying to access non-existent bits')
|
|
63
|
+
return [ f, w ]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
register(bit32, {
|
|
67
|
+
bnot(vm, args) {
|
|
68
|
+
return ~u32(args, 0, 'bnot') >>> 0
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
btest(vm, args) {
|
|
72
|
+
let r = 0xffffffff
|
|
73
|
+
for (let i = 0; i < args.length; i++) r = (r & u32(args, i, 'btest')) >>> 0
|
|
74
|
+
return r !== 0
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
lshift(vm, args) {
|
|
78
|
+
return shift(u32(args, 0, 'lshift'), Math.floor(checkNumber(args, 1, 'lshift')))
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
rshift(vm, args) {
|
|
82
|
+
return shift(u32(args, 0, 'rshift'), -Math.floor(checkNumber(args, 1, 'rshift')))
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
arshift(vm, args) {
|
|
86
|
+
const x = u32(args, 0, 'arshift')
|
|
87
|
+
const d = Math.floor(checkNumber(args, 1, 'arshift'))
|
|
88
|
+
if (d >= 32) return (x & 0x80000000) !== 0 ? 0xffffffff : 0
|
|
89
|
+
if (d <= -32) return 0
|
|
90
|
+
return d >= 0 ? (x | 0) >> d >>> 0 : shift(x, -d)
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
lrotate(vm, args) {
|
|
94
|
+
const x = u32(args, 0, 'lrotate')
|
|
95
|
+
const r = Math.floor(checkNumber(args, 1, 'lrotate')) & 31
|
|
96
|
+
return r === 0 ? x : ((x << r) | (x >>> (32 - r))) >>> 0
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
rrotate(vm, args) {
|
|
100
|
+
const x = u32(args, 0, 'rrotate')
|
|
101
|
+
const r = Math.floor(checkNumber(args, 1, 'rrotate')) & 31
|
|
102
|
+
return r === 0 ? x : ((x >>> r) | (x << (32 - r))) >>> 0
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
extract(vm, args) {
|
|
106
|
+
const x = u32(args, 0, 'extract')
|
|
107
|
+
const fw = field(args, 'extract')
|
|
108
|
+
return fw[1] === 32 ? x : (x >>> fw[0]) & (Math.pow(2, fw[1]) - 1)
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
replace(vm, args) {
|
|
112
|
+
const x = u32(args, 0, 'replace')
|
|
113
|
+
const v = u32(args, 1, 'replace')
|
|
114
|
+
const f = checkNumber(args, 2, 'replace')
|
|
115
|
+
const w = args[3] === undefined ? 1 : checkNumber(args, 3, 'replace')
|
|
116
|
+
if (f < 0) throw argError(3, 'replace', 'field cannot be negative')
|
|
117
|
+
if (w <= 0) throw argError(4, 'replace', 'width must be positive')
|
|
118
|
+
if (f + w > 32) throw fail('trying to access non-existent bits')
|
|
119
|
+
const mask = w === 32 ? 0xffffffff : Math.pow(2, w) - 1
|
|
120
|
+
return (((x & ~(mask * Math.pow(2, f))) | ((v & mask) << f)) >>> 0)
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
countlz(vm, args) {
|
|
124
|
+
const x = u32(args, 0, 'countlz')
|
|
125
|
+
if (x === 0) return 32
|
|
126
|
+
let n = 0
|
|
127
|
+
for (let bit = 0x80000000; (x & bit) === 0; bit >>>= 1) n++
|
|
128
|
+
return n
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
countrz(vm, args) {
|
|
132
|
+
const x = u32(args, 0, 'countrz')
|
|
133
|
+
if (x === 0) return 32
|
|
134
|
+
let n = 0
|
|
135
|
+
while (((x >>> n) & 1) === 0) n++
|
|
136
|
+
return n
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
byteswap(vm, args) {
|
|
140
|
+
const x = u32(args, 0, 'byteswap')
|
|
141
|
+
return (((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x >>> 8) & 0xff00) | (x >>> 24)) >>> 0
|
|
142
|
+
},
|
|
143
|
+
}, 'bit32.')
|
|
144
|
+
}
|