@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.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +302 -299
  3. package/Types.luau +215 -0
  4. package/api/Define.luau +154 -0
  5. package/api/Lifecycle.luau +119 -0
  6. package/api/Packet.luau +108 -0
  7. package/api/Query.luau +149 -0
  8. package/api/Set.luau +189 -0
  9. package/channel/Blocks.luau +124 -0
  10. package/channel/Group.luau +118 -0
  11. package/channel/Link.luau +135 -0
  12. package/channel/Outbox.luau +261 -0
  13. package/channel/Recipients.luau +129 -0
  14. package/channel/Transport.luau +138 -0
  15. package/codec/Base.luau +236 -0
  16. package/codec/Composites.luau +128 -0
  17. package/codec/Datatypes.luau +162 -0
  18. package/codec/Legality.luau +61 -0
  19. package/codec/Scalars.luau +72 -0
  20. package/codec/Text.luau +89 -0
  21. package/codec/init.luau +39 -0
  22. package/index.d.ts +285 -0
  23. package/init.luau +91 -0
  24. package/kernel/Bits.luau +16 -0
  25. package/kernel/Catalog.luau +121 -0
  26. package/kernel/Heap.luau +80 -0
  27. package/kernel/Listeners.luau +95 -0
  28. package/kernel/Log.luau +197 -0
  29. package/kernel/Tally.luau +128 -0
  30. package/kernel/Threads.luau +44 -0
  31. package/kernel/Wide.luau +267 -0
  32. package/package.json +15 -32
  33. package/runtime/Boundary.luau +180 -0
  34. package/runtime/Dispatch.luau +91 -0
  35. package/runtime/Handles.luau +114 -0
  36. package/runtime/Handshake.luau +90 -0
  37. package/runtime/Pending.luau +196 -0
  38. package/runtime/Router.luau +379 -0
  39. package/runtime/Session.luau +731 -0
  40. package/shape/Compile.luau +340 -0
  41. package/shape/Folds.luau +332 -0
  42. package/shape/Frames.luau +170 -0
  43. package/shape/Grid.luau +169 -0
  44. package/shape/Ir.luau +540 -0
  45. package/shape/Joins.luau +125 -0
  46. package/shape/Legality.luau +273 -0
  47. package/shape/Lower.luau +419 -0
  48. package/shape/Order.luau +64 -0
  49. package/shape/Regions.luau +113 -0
  50. package/shape/Rotation.luau +472 -0
  51. package/shape/Serial.luau +258 -0
  52. package/shape/Words.luau +89 -0
  53. package/shape/emit/Block.luau +453 -0
  54. package/shape/emit/Column.luau +338 -0
  55. package/shape/emit/Leaf.luau +462 -0
  56. package/shape/emit/Word.luau +234 -0
  57. package/shape/emit/init.luau +222 -0
  58. package/shape/init.luau +78 -0
  59. package/state/Apply.luau +330 -0
  60. package/state/Audience.luau +126 -0
  61. package/state/Catchup.luau +218 -0
  62. package/state/Coalesce.luau +43 -0
  63. package/state/Fieldset.luau +177 -0
  64. package/state/Newest.luau +339 -0
  65. package/state/Plan.luau +441 -0
  66. package/state/Sections.luau +468 -0
  67. package/state/Store.luau +188 -0
  68. package/state/Sync.luau +762 -0
  69. package/wire/Bytes.luau +118 -0
  70. package/wire/Clock.luau +37 -0
  71. package/wire/Protocol.luau +110 -0
  72. package/wire/Sequence.luau +40 -0
  73. package/wire/Varint.luau +124 -0
  74. package/src/Types.luau +0 -180
  75. package/src/api/Group.luau +0 -156
  76. package/src/api/Packet.luau +0 -317
  77. package/src/api/Query.luau +0 -338
  78. package/src/api/Scope.luau +0 -90
  79. package/src/api/Signal.luau +0 -193
  80. package/src/codec/Base.luau +0 -136
  81. package/src/codec/composite/Array.luau +0 -473
  82. package/src/codec/composite/Map.luau +0 -485
  83. package/src/codec/composite/Optional.luau +0 -54
  84. package/src/codec/composite/Shared.luau +0 -311
  85. package/src/codec/composite/Struct.luau +0 -494
  86. package/src/codec/composite/Tagged.luau +0 -103
  87. package/src/codec/composite/Tuple.luau +0 -143
  88. package/src/codec/datatype/Buffer.luau +0 -66
  89. package/src/codec/datatype/CFrame.luau +0 -109
  90. package/src/codec/datatype/Color.luau +0 -32
  91. package/src/codec/datatype/Instance.luau +0 -52
  92. package/src/codec/datatype/IntVector.luau +0 -39
  93. package/src/codec/datatype/NumberRange.luau +0 -39
  94. package/src/codec/datatype/Ray.luau +0 -36
  95. package/src/codec/datatype/Rect.luau +0 -31
  96. package/src/codec/datatype/Region.luau +0 -62
  97. package/src/codec/datatype/Sequence.luau +0 -184
  98. package/src/codec/datatype/String.luau +0 -94
  99. package/src/codec/datatype/UDim.luau +0 -46
  100. package/src/codec/datatype/Vector.luau +0 -130
  101. package/src/codec/meta/Auto.luau +0 -318
  102. package/src/codec/meta/Bitfield.luau +0 -160
  103. package/src/codec/meta/Custom.luau +0 -33
  104. package/src/codec/meta/DeltaScalar.luau +0 -390
  105. package/src/codec/meta/Enum.luau +0 -50
  106. package/src/codec/meta/Float.luau +0 -38
  107. package/src/codec/meta/Nothing.luau +0 -13
  108. package/src/codec/meta/Unknown.luau +0 -41
  109. package/src/codec/primitive/Bool.luau +0 -26
  110. package/src/codec/primitive/Float16.luau +0 -99
  111. package/src/codec/primitive/Int.luau +0 -59
  112. package/src/codec/primitive/Number.luau +0 -24
  113. package/src/codec/primitive/Signed.luau +0 -32
  114. package/src/codec/primitive/Varint.luau +0 -165
  115. package/src/codec/primitive/Zint.luau +0 -99
  116. package/src/index.d.ts +0 -423
  117. package/src/init.luau +0 -362
  118. package/src/internal/Baseline.luau +0 -57
  119. package/src/internal/Channel.luau +0 -484
  120. package/src/internal/Middleware.luau +0 -100
  121. package/src/internal/Pool.luau +0 -66
  122. package/src/internal/Registry.luau +0 -119
  123. package/src/internal/Transport.luau +0 -28
  124. package/src/transport/Bridge.luau +0 -110
  125. package/src/transport/Client.luau +0 -97
  126. package/src/transport/Gate.luau +0 -488
  127. package/src/transport/Reader.luau +0 -331
  128. package/src/transport/Server.luau +0 -233
  129. package/src/util/Array.luau +0 -18
  130. package/src/util/Buffer.luau +0 -90
  131. package/src/util/Constants.luau +0 -30
  132. package/src/util/Log.luau +0 -68
  133. package/src/util/Player.luau +0 -14
  134. package/src/util/Quantize.luau +0 -84
  135. 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)
@@ -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)