@axpecter/lync 2.3.3 → 3.0.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 +21 -0
- package/README.md +302 -299
- package/Types.luau +215 -0
- package/api/Define.luau +154 -0
- package/api/Lifecycle.luau +119 -0
- package/api/Packet.luau +108 -0
- package/api/Query.luau +149 -0
- package/api/Set.luau +189 -0
- package/channel/Blocks.luau +124 -0
- package/channel/Group.luau +118 -0
- package/channel/Link.luau +135 -0
- package/channel/Outbox.luau +261 -0
- package/channel/Recipients.luau +129 -0
- package/channel/Transport.luau +138 -0
- package/codec/Base.luau +236 -0
- package/codec/Composites.luau +128 -0
- package/codec/Datatypes.luau +162 -0
- package/codec/Legality.luau +61 -0
- package/codec/Scalars.luau +72 -0
- package/codec/Text.luau +89 -0
- package/codec/init.luau +39 -0
- package/index.d.ts +285 -0
- package/init.luau +91 -0
- package/kernel/Bits.luau +16 -0
- package/kernel/Catalog.luau +121 -0
- package/kernel/Heap.luau +80 -0
- package/kernel/Listeners.luau +95 -0
- package/kernel/Log.luau +197 -0
- package/kernel/Tally.luau +128 -0
- package/kernel/Threads.luau +44 -0
- package/kernel/Wide.luau +267 -0
- package/package.json +15 -32
- package/runtime/Boundary.luau +180 -0
- package/runtime/Dispatch.luau +91 -0
- package/runtime/Handles.luau +114 -0
- package/runtime/Handshake.luau +90 -0
- package/runtime/Pending.luau +196 -0
- package/runtime/Router.luau +379 -0
- package/runtime/Session.luau +731 -0
- package/shape/Compile.luau +340 -0
- package/shape/Folds.luau +332 -0
- package/shape/Frames.luau +170 -0
- package/shape/Grid.luau +169 -0
- package/shape/Ir.luau +540 -0
- package/shape/Joins.luau +125 -0
- package/shape/Legality.luau +273 -0
- package/shape/Lower.luau +419 -0
- package/shape/Order.luau +64 -0
- package/shape/Regions.luau +113 -0
- package/shape/Rotation.luau +472 -0
- package/shape/Serial.luau +258 -0
- package/shape/Words.luau +89 -0
- package/shape/emit/Block.luau +453 -0
- package/shape/emit/Column.luau +338 -0
- package/shape/emit/Leaf.luau +462 -0
- package/shape/emit/Word.luau +234 -0
- package/shape/emit/init.luau +222 -0
- package/shape/init.luau +78 -0
- package/state/Apply.luau +330 -0
- package/state/Audience.luau +126 -0
- package/state/Catchup.luau +218 -0
- package/state/Coalesce.luau +43 -0
- package/state/Fieldset.luau +177 -0
- package/state/Newest.luau +339 -0
- package/state/Plan.luau +441 -0
- package/state/Sections.luau +468 -0
- package/state/Store.luau +188 -0
- package/state/Sync.luau +762 -0
- package/wire/Bytes.luau +118 -0
- package/wire/Clock.luau +37 -0
- package/wire/Protocol.luau +110 -0
- package/wire/Sequence.luau +40 -0
- package/wire/Varint.luau +124 -0
- package/src/Types.luau +0 -180
- package/src/api/Group.luau +0 -156
- package/src/api/Packet.luau +0 -317
- package/src/api/Query.luau +0 -338
- package/src/api/Scope.luau +0 -90
- package/src/api/Signal.luau +0 -193
- package/src/codec/Base.luau +0 -136
- package/src/codec/composite/Array.luau +0 -473
- package/src/codec/composite/Map.luau +0 -485
- package/src/codec/composite/Optional.luau +0 -54
- package/src/codec/composite/Shared.luau +0 -311
- package/src/codec/composite/Struct.luau +0 -494
- package/src/codec/composite/Tagged.luau +0 -103
- package/src/codec/composite/Tuple.luau +0 -143
- package/src/codec/datatype/Buffer.luau +0 -66
- package/src/codec/datatype/CFrame.luau +0 -109
- package/src/codec/datatype/Color.luau +0 -32
- package/src/codec/datatype/Instance.luau +0 -52
- package/src/codec/datatype/IntVector.luau +0 -39
- package/src/codec/datatype/NumberRange.luau +0 -39
- package/src/codec/datatype/Ray.luau +0 -36
- package/src/codec/datatype/Rect.luau +0 -31
- package/src/codec/datatype/Region.luau +0 -62
- package/src/codec/datatype/Sequence.luau +0 -184
- package/src/codec/datatype/String.luau +0 -94
- package/src/codec/datatype/UDim.luau +0 -46
- package/src/codec/datatype/Vector.luau +0 -130
- package/src/codec/meta/Auto.luau +0 -318
- package/src/codec/meta/Bitfield.luau +0 -160
- package/src/codec/meta/Custom.luau +0 -33
- package/src/codec/meta/DeltaScalar.luau +0 -390
- package/src/codec/meta/Enum.luau +0 -50
- package/src/codec/meta/Float.luau +0 -38
- package/src/codec/meta/Nothing.luau +0 -13
- package/src/codec/meta/Unknown.luau +0 -41
- package/src/codec/primitive/Bool.luau +0 -26
- package/src/codec/primitive/Float16.luau +0 -99
- package/src/codec/primitive/Int.luau +0 -59
- package/src/codec/primitive/Number.luau +0 -24
- package/src/codec/primitive/Signed.luau +0 -32
- package/src/codec/primitive/Varint.luau +0 -165
- package/src/codec/primitive/Zint.luau +0 -99
- package/src/index.d.ts +0 -423
- package/src/init.luau +0 -362
- package/src/internal/Baseline.luau +0 -57
- package/src/internal/Channel.luau +0 -484
- package/src/internal/Middleware.luau +0 -100
- package/src/internal/Pool.luau +0 -66
- package/src/internal/Registry.luau +0 -119
- package/src/internal/Transport.luau +0 -28
- package/src/transport/Bridge.luau +0 -110
- package/src/transport/Client.luau +0 -97
- package/src/transport/Gate.luau +0 -488
- package/src/transport/Reader.luau +0 -331
- package/src/transport/Server.luau +0 -233
- package/src/util/Array.luau +0 -18
- package/src/util/Buffer.luau +0 -90
- package/src/util/Constants.luau +0 -30
- package/src/util/Log.luau +0 -68
- package/src/util/Player.luau +0 -14
- package/src/util/Quantize.luau +0 -84
- package/src/util/Quat.luau +0 -124
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- What a start will take: the declaration a definition is, and every test made of one.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.codec.Base)
|
|
6
|
+
local Folds = require (script.Parent.Folds)
|
|
7
|
+
local Grid = require (script.Parent.Grid)
|
|
8
|
+
local Joins = require (script.Parent.Joins)
|
|
9
|
+
local Log = require (script.Parent.Parent.kernel.Log)
|
|
10
|
+
local Order = require (script.Parent.Order)
|
|
11
|
+
local Protocol = require (script.Parent.Parent.wire.Protocol)
|
|
12
|
+
local Scalars = require (script.Parent.Parent.codec.Scalars)
|
|
13
|
+
local Serial = require (script.Parent.Serial)
|
|
14
|
+
local Types = require (script.Parent.Parent.Types)
|
|
15
|
+
|
|
16
|
+
local Legality = {}
|
|
17
|
+
|
|
18
|
+
-- Constants -----------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
-- What a set replicates, and how many of its fields one dirty mask covers.
|
|
21
|
+
const RECORD: Base.Kind = "struct"
|
|
22
|
+
const FIELDS = Protocol.MAX_FIELDS
|
|
23
|
+
|
|
24
|
+
-- The widest leaf a bit run carries, which is the line one computation may not fall across.
|
|
25
|
+
const CEILING = Protocol.BIT_CEILING
|
|
26
|
+
|
|
27
|
+
-- How far a double counts exactly, which is what a grid's span has to stay under.
|
|
28
|
+
const REACH = Protocol.EXACT
|
|
29
|
+
|
|
30
|
+
-- What one fire of the lossy lane carries, which is the ceiling a block on it stays under.
|
|
31
|
+
const CAP = Protocol.UNRELIABLE_CAP
|
|
32
|
+
|
|
33
|
+
-- The punctuation the descriptor grammar separates a namespace with, which no name may hold.
|
|
34
|
+
const SPELLED = table.freeze ({ ";", "=" })
|
|
35
|
+
|
|
36
|
+
-- Types ---------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
--[[
|
|
39
|
+
Where a definition was written, which is the one fact a refusal here carries that a caller
|
|
40
|
+
cannot work out for themselves. A start legality is raised inside a compile and a compile runs a
|
|
41
|
+
long way from the line that declared the thing, so a message without this says a schema is wrong
|
|
42
|
+
and leaves finding it to a search.
|
|
43
|
+
]]
|
|
44
|
+
export type Site = { read file: string, read line: number }
|
|
45
|
+
|
|
46
|
+
-- A definition as its caller declared it, which is what they said rather than what it means.
|
|
47
|
+
export type Packet = {
|
|
48
|
+
read kind: "packet",
|
|
49
|
+
read of: Types.Codec<any>,
|
|
50
|
+
read isUnreliable: boolean,
|
|
51
|
+
read isNewest: boolean,
|
|
52
|
+
read hz: number?,
|
|
53
|
+
read isTimestamped: boolean,
|
|
54
|
+
read at: Site,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type Query = {
|
|
58
|
+
read kind: "query",
|
|
59
|
+
read of: Types.Codec<any>,
|
|
60
|
+
read reply: Types.Codec<any>,
|
|
61
|
+
read at: Site,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type Set = {
|
|
65
|
+
read kind: "set",
|
|
66
|
+
read of: Types.Codec<any>,
|
|
67
|
+
read keyField: string?,
|
|
68
|
+
read at: Site,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type Declared = Packet | Query | Set
|
|
72
|
+
|
|
73
|
+
-- Private -------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
-- A refusal, as the one line whoever wrote the schema reads.
|
|
76
|
+
local function refuse (name: string, at: Site, said: string): never
|
|
77
|
+
return Log.refuse (`{name} {said}, declared at {at.file}:{at.line}`)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
-- The first node under here carrying a state marker, and the marker it carries.
|
|
81
|
+
local function marked (of: Base.Cell, at: string): (string?, Base.Marker)
|
|
82
|
+
if of.marker ~= "none" then return at, of.marker end
|
|
83
|
+
|
|
84
|
+
local children = of.children
|
|
85
|
+
if children == nil then return nil, "none" end
|
|
86
|
+
|
|
87
|
+
for _, name in Order.names (children) do
|
|
88
|
+
local where, mark = marked (children[name], Serial.under (at, name))
|
|
89
|
+
if where ~= nil then return where, mark end
|
|
90
|
+
end
|
|
91
|
+
return nil, "none"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
-- How many points a declaration's grid holds, where a division decides that rather than a count.
|
|
95
|
+
local function points (of: Base.Cell): number?
|
|
96
|
+
local kind, params = of.kind, of.params
|
|
97
|
+
|
|
98
|
+
if kind == "int" then return (params.max :: number) - (params.min :: number) end
|
|
99
|
+
if kind == "quant" then
|
|
100
|
+
return ((params.max :: number) - (params.min :: number)) / (params.step :: number)
|
|
101
|
+
end
|
|
102
|
+
if kind == "angle" then return Scalars.TURN / (params.step :: number) end
|
|
103
|
+
return nil
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
-- Whether one computation's leaves fall either side of the bit run's ceiling.
|
|
107
|
+
local function straddles (of: Base.Cell): boolean
|
|
108
|
+
local fold = Folds.fold (of)
|
|
109
|
+
if fold == nil then return false end
|
|
110
|
+
|
|
111
|
+
local under, over = false, false
|
|
112
|
+
for _, grid in fold.leaves do
|
|
113
|
+
if grid.width > CEILING then
|
|
114
|
+
over = true
|
|
115
|
+
else
|
|
116
|
+
under = true
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
return under and over
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
-- What one node declares that its constructor could not refuse, as the clause a message reads.
|
|
123
|
+
local function imprecise (of: Base.Cell, at: string): string?
|
|
124
|
+
local span = points (of)
|
|
125
|
+
if span ~= nil and span >= REACH then
|
|
126
|
+
return `declares {at} over {span} points, which is past what a double counts exactly`
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
if of.kind == "angle" then
|
|
130
|
+
local step = of.params.step :: number
|
|
131
|
+
if not Grid.divides (Scalars.TURN, step) then
|
|
132
|
+
return `declares {at} to {step} degrees, which does not divide a turn`
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
if not straddles (of) then return nil end
|
|
137
|
+
return `declares {at} to a precision whose parts fall either side of {CEILING} bits`
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
-- Every node of a tree, in the one order a walk of this library visits children in.
|
|
141
|
+
local function imprecision (of: Base.Cell, at: string): string?
|
|
142
|
+
local said = imprecise (of, at)
|
|
143
|
+
if said ~= nil then return said end
|
|
144
|
+
|
|
145
|
+
local children = of.children
|
|
146
|
+
if children == nil then return nil end
|
|
147
|
+
|
|
148
|
+
for _, name in Order.names (children) do
|
|
149
|
+
local under = imprecision (children[name], Serial.under (at, name))
|
|
150
|
+
if under ~= nil then return under end
|
|
151
|
+
end
|
|
152
|
+
return nil
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
-- A tree carrying no state between frames, which is every tree outside a set.
|
|
156
|
+
local function stateless (name: string, at: Site, what: string, of: Base.Cell, root: string)
|
|
157
|
+
local where, mark = marked (of, root)
|
|
158
|
+
if where ~= nil then
|
|
159
|
+
refuse (name, at, `declares {mark} at {where}, and {what} keeps nothing to differ from`)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
local why = imprecision (of, root)
|
|
163
|
+
if why == nil then return end
|
|
164
|
+
refuse (name, at, why)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
-- A record a set replicates, and the four things a set decides about it that nothing else does.
|
|
168
|
+
local function replicated (name: string, at: Site, of: Set)
|
|
169
|
+
local cell = Base.cell (of.of)
|
|
170
|
+
if cell.kind ~= RECORD then
|
|
171
|
+
refuse (name, at, `replicates a {cell.kind}, and a set replicates records`)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
local fields = cell.children :: { [string]: Base.Cell }
|
|
175
|
+
local names = Order.names (fields)
|
|
176
|
+
local reach = #names
|
|
177
|
+
|
|
178
|
+
if reach == 0 then refuse (name, at, "replicates a record of no fields") end
|
|
179
|
+
if reach > FIELDS then
|
|
180
|
+
refuse (name, at, `replicates {reach} fields, and one dirty mask covers {FIELDS}`)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
for _, field in names do
|
|
184
|
+
local children = fields[field].children
|
|
185
|
+
if children == nil then continue end
|
|
186
|
+
|
|
187
|
+
local under = Serial.under (name, field)
|
|
188
|
+
for _, inner in Order.names (children) do
|
|
189
|
+
local where, mark = marked (children[inner], Serial.under (under, inner))
|
|
190
|
+
if where == nil then continue end
|
|
191
|
+
refuse (name, at, `declares {mark} at {where}, and a set deltas its own fields`)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
local why = imprecision (cell, name)
|
|
196
|
+
if why ~= nil then refuse (name, at, why) end
|
|
197
|
+
|
|
198
|
+
local key = of.keyField
|
|
199
|
+
if key == nil then return end
|
|
200
|
+
|
|
201
|
+
local held = fields[key]
|
|
202
|
+
if held == nil then
|
|
203
|
+
refuse (name, at, `is keyed by {key}, which its record does not declare`)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
if held.marker == "newest" then
|
|
207
|
+
refuse (name, at, `is keyed by {key} and declares newest on it, and a key has to arrive`)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
if Joins.grid (held) ~= nil then return end
|
|
211
|
+
refuse (name, at, `is keyed by {key}, and its {held.kind} is not one number to partition by`)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
-- Public --------------------------------------------------------------
|
|
215
|
+
|
|
216
|
+
-- Which of the three lanes a packet asked for.
|
|
217
|
+
function Legality.delivery (of: Packet): Serial.Delivery
|
|
218
|
+
if of.isUnreliable then return "unreliable" end
|
|
219
|
+
if of.isNewest then return "newest" end
|
|
220
|
+
return "reliable"
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
-- A block that has to fit one fire, refused where it cannot.
|
|
224
|
+
function Legality.block (name: string, of: Packet, bytes: number)
|
|
225
|
+
local lane = Legality.delivery (of)
|
|
226
|
+
if lane == "reliable" or bytes <= CAP then return end
|
|
227
|
+
|
|
228
|
+
refuse (
|
|
229
|
+
name,
|
|
230
|
+
of.at,
|
|
231
|
+
`is {lane} and its widest block is {bytes} bytes, past the {CAP} one fire carries`
|
|
232
|
+
)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
-- What a query's two halves are called, wherever one of them has to be named apart from the other.
|
|
236
|
+
Legality.REQUEST = "request"
|
|
237
|
+
Legality.RESPONSE = "response"
|
|
238
|
+
|
|
239
|
+
-- Why a name is one the descriptor cannot spell back, or nothing.
|
|
240
|
+
function Legality.named (name: string): string?
|
|
241
|
+
for _, mark in SPELLED do
|
|
242
|
+
if string.find (name, mark, 1, true) == nil then continue end
|
|
243
|
+
return `holds a {mark}, which is what a descriptor separates its own names with`
|
|
244
|
+
end
|
|
245
|
+
return nil
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
-- One definition, refused on the first thing wrong with it.
|
|
249
|
+
function Legality.definition (name: string, of: Declared)
|
|
250
|
+
local at = of.at
|
|
251
|
+
|
|
252
|
+
local why = Legality.named (name)
|
|
253
|
+
if why ~= nil then refuse (name, at, why) end
|
|
254
|
+
|
|
255
|
+
if of.kind == "packet" then
|
|
256
|
+
if of.isUnreliable and of.isNewest then
|
|
257
|
+
refuse (name, at, "declares two ways of delivering itself, unreliable and newest")
|
|
258
|
+
end
|
|
259
|
+
stateless (name, at, "a packet", Base.cell (of.of), name)
|
|
260
|
+
return
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
if of.kind == "query" then
|
|
264
|
+
stateless (name, at, "a query", Base.cell (of.of), Serial.under (name, Legality.REQUEST))
|
|
265
|
+
local reply = Base.cell (of.reply)
|
|
266
|
+
stateless (name, at, "a query", reply, Serial.under (name, Legality.RESPONSE))
|
|
267
|
+
return
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
replicated (name, at, of)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
return table.freeze (Legality)
|
package/shape/Lower.luau
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- A codec tree as the nodes the emitter writes, which is the whole of what a schema decides.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.codec.Base)
|
|
6
|
+
local Folds = require (script.Parent.Folds)
|
|
7
|
+
local Grid = require (script.Parent.Grid)
|
|
8
|
+
local Ir = require (script.Parent.Ir)
|
|
9
|
+
local Joins = require (script.Parent.Joins)
|
|
10
|
+
local Order = require (script.Parent.Order)
|
|
11
|
+
local Regions = require (script.Parent.Regions)
|
|
12
|
+
local Serial = require (script.Parent.Serial)
|
|
13
|
+
local Words = require (script.Parent.Words)
|
|
14
|
+
|
|
15
|
+
local Lower = {}
|
|
16
|
+
|
|
17
|
+
-- Constants -----------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
--[[
|
|
20
|
+
The names a value in parts is read off, in the order they are written.
|
|
21
|
+
|
|
22
|
+
Cloned at every use rather than handed over, because the constructor freezes the array it is
|
|
23
|
+
given and a second freeze on a frozen table raises. What is shared is the reading of them.
|
|
24
|
+
]]
|
|
25
|
+
const PLANE = table.freeze ({ "X", "Y" })
|
|
26
|
+
const SPACE = table.freeze ({ "X", "Y", "Z" })
|
|
27
|
+
const LIGHT = table.freeze ({ "R", "G", "B" })
|
|
28
|
+
const FRAME = table.freeze ({ "Position", "Rotation" })
|
|
29
|
+
|
|
30
|
+
-- The third of the three a vector and a colour are each read off.
|
|
31
|
+
const THIRD = #SPACE
|
|
32
|
+
|
|
33
|
+
-- Types ---------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
--[[
|
|
36
|
+
The two tables a walk interns into, which is everything a lowering needs that is not the
|
|
37
|
+
declaration it is on. A record rather than two arguments, because the walk is recursive and the
|
|
38
|
+
pair travels together to every node of a tree.
|
|
39
|
+
]]
|
|
40
|
+
export type Site = {
|
|
41
|
+
read paths: Serial.Interner,
|
|
42
|
+
read expected: Serial.Interner,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
-- Private -------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
-- Where a declaration is and what it wanted, with the caller's own checks where there are any.
|
|
48
|
+
local function tagged (of: Base.Cell, at: string, site: Site): Ir.Tag
|
|
49
|
+
local pathId, expectId = Serial.tagged (site.paths, site.expected, at, of)
|
|
50
|
+
local checks = of.validates
|
|
51
|
+
|
|
52
|
+
return table.freeze ({
|
|
53
|
+
pathId = pathId,
|
|
54
|
+
expectId = expectId,
|
|
55
|
+
checks = if #checks == 0 then nil else checks,
|
|
56
|
+
})
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
-- The same place, for the nodes under the one the checks are on and for the bits that are no node.
|
|
60
|
+
local function plain (of: Base.Cell, at: string, site: Site): Ir.Tag
|
|
61
|
+
local pathId, expectId = Serial.tagged (site.paths, site.expected, at, of)
|
|
62
|
+
return table.freeze ({ pathId = pathId, expectId = expectId })
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
local function counted (of: Base.Params): Ir.Span
|
|
66
|
+
return { min = of.min :: number, max = of.max :: number }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
-- Where a field is, spelled from where the record holding it is, one dissolved name at a time.
|
|
70
|
+
local function pathed (at: string, path: { string }): string
|
|
71
|
+
local out = at
|
|
72
|
+
for _, name in path do
|
|
73
|
+
out = Serial.under (out, name)
|
|
74
|
+
end
|
|
75
|
+
return out
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
-- The same, as the one string a table of them can be keyed by.
|
|
79
|
+
local function spelled (path: { string }, deep: number): string
|
|
80
|
+
return table.concat (path, ".", 1, deep)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
-- Whether a field is there, which is the whole of what a presence bit is filled from.
|
|
84
|
+
local function there (value: any, into: { number }, at: number): boolean
|
|
85
|
+
into[at] = if value == nil then 0 else 1
|
|
86
|
+
return true
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
-- What a presence bit answers, which is nothing.
|
|
90
|
+
local function nothing (): any return nil end
|
|
91
|
+
|
|
92
|
+
local function planar (from: { any }): any return Vector2.new (from[1], from[2]) end
|
|
93
|
+
|
|
94
|
+
local function spatial (from: { any }): any return Vector3.new (from[1], from[2], from[THIRD]) end
|
|
95
|
+
|
|
96
|
+
local function lit (from: { any }): any return Color3.new (from[1], from[2], from[THIRD]) end
|
|
97
|
+
|
|
98
|
+
--[[
|
|
99
|
+
A frame from its two halves, which is a turn moved to where it sits. The rotation comes back as
|
|
100
|
+
a frame at the origin and adding a vector to a frame is the translation the position is written
|
|
101
|
+
as, so there is nothing to compose here that the engine does not.
|
|
102
|
+
]]
|
|
103
|
+
local function framed (from: { any }): any return from[2] + from[1] end
|
|
104
|
+
|
|
105
|
+
-- A declaration whose value is one bit run, as the region it is on its own.
|
|
106
|
+
local function worded (of: Base.Cell, at: string, site: Site, tag: Ir.Tag): Ir.Word
|
|
107
|
+
local held = plain (of, at, site)
|
|
108
|
+
|
|
109
|
+
local made = Joins.of (of, held, 1, nil)
|
|
110
|
+
if made == nil then made = Folds.of (of, held, 1, nil) end
|
|
111
|
+
|
|
112
|
+
local field = made :: Joins.Field
|
|
113
|
+
local widths = table.create (#field.leaves) :: { number }
|
|
114
|
+
for index, grid in field.leaves do
|
|
115
|
+
widths[index] = grid.width
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
return Ir.word (tag, Words.plan (widths), field.leaves, { field.join })
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
-- A record, as the four regions and the records that dissolved into it.
|
|
122
|
+
local function recorded (
|
|
123
|
+
of: Base.Cell,
|
|
124
|
+
at: string,
|
|
125
|
+
site: Site,
|
|
126
|
+
tag: Ir.Tag,
|
|
127
|
+
carries: string?
|
|
128
|
+
): Ir.Group
|
|
129
|
+
local split = Regions.of (of.children :: { [string]: Base.Cell })
|
|
130
|
+
|
|
131
|
+
--[[
|
|
132
|
+
The records that dissolved, each hanging off the one above it. They arrive in depth order,
|
|
133
|
+
so the one a nest hangs off has always been made by the time the nest is.
|
|
134
|
+
]]
|
|
135
|
+
local nests = table.create (#split.nests) :: { Ir.Nest }
|
|
136
|
+
local under: { [string]: number } = {}
|
|
137
|
+
|
|
138
|
+
-- The names each of these records may carry, one set per record.
|
|
139
|
+
local allow: { [string]: boolean } = {}
|
|
140
|
+
local allows = table.create (#split.nests) :: { { [string]: boolean } }
|
|
141
|
+
|
|
142
|
+
for index, entry in split.nests do
|
|
143
|
+
local path = entry.at
|
|
144
|
+
local deep = #path
|
|
145
|
+
|
|
146
|
+
allows[index] = {}
|
|
147
|
+
nests[index] = {
|
|
148
|
+
key = path[deep],
|
|
149
|
+
under = if deep == 1 then nil else under[spelled (path, deep - 1)],
|
|
150
|
+
allow = allows[index],
|
|
151
|
+
tag = plain (entry.of, pathed (at, path), site),
|
|
152
|
+
}
|
|
153
|
+
under[spelled (path, deep)] = index
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
local function inside (path: { string }): number?
|
|
157
|
+
if #path == 1 then return nil end
|
|
158
|
+
return under[spelled (path, #path - 1)]
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
--[[
|
|
162
|
+
Every nest is made before any name is declared, so a field at any depth reaches the record
|
|
163
|
+
it belongs to. An optional's bit and its payload are one declaration under one name, so the
|
|
164
|
+
presence list has nothing here the variable list does not.
|
|
165
|
+
]]
|
|
166
|
+
local function declare (path: { string })
|
|
167
|
+
local deep = #path
|
|
168
|
+
local into = if deep == 1 then allow else allows[under[spelled (path, deep - 1)] ]
|
|
169
|
+
into[path[deep] ] = true
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
for _, entry in split.nests do
|
|
173
|
+
declare (entry.at)
|
|
174
|
+
end
|
|
175
|
+
for _, entry in split.bits do
|
|
176
|
+
declare (entry.at)
|
|
177
|
+
end
|
|
178
|
+
for _, entry in split.bytes do
|
|
179
|
+
declare (entry.at)
|
|
180
|
+
end
|
|
181
|
+
for _, entry in split.vars do
|
|
182
|
+
declare (entry.at)
|
|
183
|
+
end
|
|
184
|
+
--[[
|
|
185
|
+
The one name a record may carry that its own declaration does not hold, which is the tag a
|
|
186
|
+
variant was chosen by. Every variant is a struct and none of them declares the tag, both of
|
|
187
|
+
which the constructor holds them to, so this adds a name and never replaces one.
|
|
188
|
+
]]
|
|
189
|
+
if carries ~= nil then allow[carries] = true end
|
|
190
|
+
|
|
191
|
+
for _, one in allows do
|
|
192
|
+
table.freeze (one)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
--[[
|
|
196
|
+
Which leaf each optional's bit is, which the payload needs and the partition already knows:
|
|
197
|
+
the bits are the first leaves of the region in the order the presence list holds them, and
|
|
198
|
+
the same entry is in the variable list under the same field's name.
|
|
199
|
+
]]
|
|
200
|
+
local bit: { [Regions.Entry]: number } = {}
|
|
201
|
+
local leaves: { Grid.Grid } = {}
|
|
202
|
+
local joins: { Ir.Join } = {}
|
|
203
|
+
|
|
204
|
+
for index, entry in split.presence do
|
|
205
|
+
local path = entry.at
|
|
206
|
+
bit[entry] = index
|
|
207
|
+
|
|
208
|
+
table.insert (leaves, Grid.flag ())
|
|
209
|
+
table.insert (joins, {
|
|
210
|
+
at = index,
|
|
211
|
+
count = 1,
|
|
212
|
+
key = path[#path],
|
|
213
|
+
nest = inside (path),
|
|
214
|
+
tag = plain (entry.of, pathed (at, path), site),
|
|
215
|
+
pull = there,
|
|
216
|
+
push = nothing,
|
|
217
|
+
})
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
for _, entry in split.bits do
|
|
221
|
+
local path = entry.at
|
|
222
|
+
local held = tagged (entry.of, pathed (at, path), site)
|
|
223
|
+
local key, nest = path[#path], inside (path)
|
|
224
|
+
|
|
225
|
+
local made = Joins.of (entry.of, held, #leaves + 1, key, nest)
|
|
226
|
+
if made == nil then made = Folds.of (entry.of, held, #leaves + 1, key, nest) end
|
|
227
|
+
|
|
228
|
+
local field = made :: Joins.Field
|
|
229
|
+
for _, grid in field.leaves do
|
|
230
|
+
table.insert (leaves, grid)
|
|
231
|
+
end
|
|
232
|
+
table.insert (joins, field.join)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
local parts: { Ir.Part } = {}
|
|
236
|
+
|
|
237
|
+
for _, entry in split.bytes do
|
|
238
|
+
local path = entry.at
|
|
239
|
+
table.insert (parts, {
|
|
240
|
+
key = path[#path],
|
|
241
|
+
nest = inside (path),
|
|
242
|
+
of = Lower.of (entry.of, pathed (at, path), site),
|
|
243
|
+
})
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
--[[
|
|
247
|
+
An optional is its payload and the bit that says whether it is there, and the bit was laid
|
|
248
|
+
down above. The checks a caller declared on it ride on the node that may not be reached, so
|
|
249
|
+
an absent field is one they never run on.
|
|
250
|
+
]]
|
|
251
|
+
for _, entry in split.vars do
|
|
252
|
+
local path = entry.at
|
|
253
|
+
local where = pathed (at, path)
|
|
254
|
+
local place = bit[entry]
|
|
255
|
+
|
|
256
|
+
local made: Ir.Shape
|
|
257
|
+
if place == nil then
|
|
258
|
+
made = Lower.of (entry.of, where, site)
|
|
259
|
+
else
|
|
260
|
+
local inner = (entry.of.children :: any).inner :: Base.Cell
|
|
261
|
+
made = Ir.opt (
|
|
262
|
+
tagged (entry.of, where, site),
|
|
263
|
+
place,
|
|
264
|
+
Lower.of (inner, Serial.under (where, "inner"), site)
|
|
265
|
+
)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
table.insert (parts, { key = path[#path], nest = inside (path), of = made })
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
local word: Ir.Word? = nil
|
|
272
|
+
if #joins > 0 then
|
|
273
|
+
local widths = table.create (#leaves) :: { number }
|
|
274
|
+
for index, grid in leaves do
|
|
275
|
+
widths[index] = grid.width
|
|
276
|
+
end
|
|
277
|
+
word = Ir.word (plain (of, at, site), Words.plan (widths), leaves, joins)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
return Ir.group (tag, word, parts, if #nests == 0 then nil else nests, allow)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
-- One declaration to the node it becomes, with everything under it already its own.
|
|
284
|
+
local function shaped (
|
|
285
|
+
of: Base.Cell,
|
|
286
|
+
at: string,
|
|
287
|
+
site: Site,
|
|
288
|
+
tag: Ir.Tag,
|
|
289
|
+
carries: string?
|
|
290
|
+
): Ir.Shape
|
|
291
|
+
local kind, params = of.kind, of.params
|
|
292
|
+
if Regions.packs (of) then return worded (of, at, site, tag) end
|
|
293
|
+
|
|
294
|
+
-- A field the language carries whose one leaf is too wide to flow, which is whole bytes.
|
|
295
|
+
local single = Joins.grid (of)
|
|
296
|
+
if single ~= nil then return Ir.wide (tag, single) end
|
|
297
|
+
|
|
298
|
+
if kind == "f32" then return Ir.float (tag, false) end
|
|
299
|
+
if kind == "f64" then return Ir.float (tag, true) end
|
|
300
|
+
if kind == "vlq" then return Ir.varint (tag, false) end
|
|
301
|
+
if kind == "vli" then return Ir.varint (tag, true) end
|
|
302
|
+
if kind == "inst" then return Ir.slot (tag, params.class) end
|
|
303
|
+
|
|
304
|
+
if kind == "str" then return Ir.bytes (tag, counted (params), "string", params.symbols) end
|
|
305
|
+
if kind == "buffer" then return Ir.bytes (tag, counted (params), "buffer", nil) end
|
|
306
|
+
|
|
307
|
+
--[[
|
|
308
|
+
An array is a packed run where its element is one leaf that fits, and a list of aligned
|
|
309
|
+
elements otherwise. An element of several leaves that would all fit is a list too, and pays
|
|
310
|
+
up to seven pad bits each for it, because a run carries one grid and a bitfield or a
|
|
311
|
+
quantized vector is more than one. Closing that means a run whose element is a region.
|
|
312
|
+
]]
|
|
313
|
+
if kind == "array" then
|
|
314
|
+
local element = (of.children :: any).element :: Base.Cell
|
|
315
|
+
local grid = if Regions.packs (element) then Joins.grid (element) else nil
|
|
316
|
+
if grid ~= nil then return Ir.run (tag, counted (params), grid) end
|
|
317
|
+
|
|
318
|
+
return Ir.list (
|
|
319
|
+
tag,
|
|
320
|
+
counted (params),
|
|
321
|
+
Lower.of (element, Serial.under (at, "element"), site)
|
|
322
|
+
)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
if kind == "map" then
|
|
326
|
+
local children = of.children :: any
|
|
327
|
+
return Ir.pairs (
|
|
328
|
+
tag,
|
|
329
|
+
counted (params),
|
|
330
|
+
Lower.of (children.key, Serial.under (at, "key"), site),
|
|
331
|
+
Lower.of (children.value, Serial.under (at, "value"), site)
|
|
332
|
+
)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
--[[
|
|
336
|
+
An optional whose whole definition it is. Its bit has no region to live in, so it gets one
|
|
337
|
+
of its own, and both the bit and the payload are nameless because what comes back is the
|
|
338
|
+
value rather than a record of one field.
|
|
339
|
+
]]
|
|
340
|
+
if kind == "optional" then
|
|
341
|
+
local held = plain (of, at, site)
|
|
342
|
+
local join: Ir.Join = {
|
|
343
|
+
at = 1,
|
|
344
|
+
count = 1,
|
|
345
|
+
key = nil,
|
|
346
|
+
tag = held,
|
|
347
|
+
pull = there,
|
|
348
|
+
push = nothing,
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
local inner = (of.children :: any).inner :: Base.Cell
|
|
352
|
+
local part: Ir.Part = {
|
|
353
|
+
of = Ir.opt (tag, 1, Lower.of (inner, Serial.under (at, "inner"), site)),
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return Ir.group (
|
|
357
|
+
held,
|
|
358
|
+
Ir.word (held, Words.plan ({ 1 }), { Grid.flag () }, { join }),
|
|
359
|
+
{ part }
|
|
360
|
+
)
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
if kind == "tagged" then
|
|
364
|
+
local variants = of.children :: { [string]: Base.Cell }
|
|
365
|
+
local names = Order.names (variants)
|
|
366
|
+
local field = params.field :: string
|
|
367
|
+
|
|
368
|
+
local arms = table.create (#names) :: { Ir.Shape }
|
|
369
|
+
for index, name in names do
|
|
370
|
+
arms[index] = Lower.of (variants[name], Serial.under (at, name), site, field)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
return Ir.branch (tag, field, names, arms)
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
if kind == "struct" then return recorded (of, at, site, tag, carries) end
|
|
377
|
+
|
|
378
|
+
--[[
|
|
379
|
+
A vector and a colour of components too wide to flow, which is every one whose components
|
|
380
|
+
are floats. The component is lowered once and stood in every place, since the three are one
|
|
381
|
+
declaration and a node is a value.
|
|
382
|
+
]]
|
|
383
|
+
if kind == "vec2" or kind == "vec3" or kind == "color3" then
|
|
384
|
+
local children = of.children
|
|
385
|
+
local component = if children == nil then nil else children.component
|
|
386
|
+
|
|
387
|
+
local one = if component == nil
|
|
388
|
+
then Ir.float (plain (of, at, site), false) :: Ir.Shape
|
|
389
|
+
else Lower.of (component, Serial.under (at, "component"), site)
|
|
390
|
+
|
|
391
|
+
if kind == "vec2" then
|
|
392
|
+
return Ir.apart (tag, Folds.ENGINE.vec2, table.clone (PLANE), { one, one }, planar)
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
local push = if kind == "vec3" then spatial else lit
|
|
396
|
+
local keys = if kind == "vec3" then SPACE else LIGHT
|
|
397
|
+
local engine = if kind == "vec3" then Folds.ENGINE.vec3 else Folds.ENGINE.color3
|
|
398
|
+
return Ir.apart (tag, engine, table.clone (keys), { one, one, one }, push)
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
local children = of.children :: any
|
|
402
|
+
return Ir.apart (tag, Folds.ENGINE.cframe, table.clone (FRAME), {
|
|
403
|
+
Lower.of (children.position, Serial.under (at, "position"), site),
|
|
404
|
+
Lower.of (children.rotation, Serial.under (at, "rotation"), site),
|
|
405
|
+
}, framed)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
-- Public --------------------------------------------------------------
|
|
409
|
+
|
|
410
|
+
-- A declaration, at the path a refusal in it reads as, and everything under it.
|
|
411
|
+
function Lower.of (of: Base.Cell, at: string, site: Site, carries: string?): Ir.Shape
|
|
412
|
+
local lift = of.lift
|
|
413
|
+
if lift == nil then return shaped (of, at, site, tagged (of, at, site), carries) end
|
|
414
|
+
|
|
415
|
+
local inner = shaped (of, at, site, plain (of, at, site), carries)
|
|
416
|
+
return Ir.xform (tagged (of, at, site), inner, lift, of.lower :: (any) -> any)
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
return table.freeze (Lower)
|