mt-lang 0.2.0 → 0.2.2

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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -0
  3. data/Rakefile +1 -1
  4. data/docs/index.html +13 -3
  5. data/lib/milk_tea/base.rb +7 -2
  6. data/std/asset_pack.mt +267 -0
  7. data/std/async/libuv_runtime.mt +539 -0
  8. data/std/async/mailbox.mt +191 -0
  9. data/std/async/runtime.mt +87 -0
  10. data/std/async.mt +87 -0
  11. data/std/base64.mt +185 -0
  12. data/std/behavior_tree.mt +396 -0
  13. data/std/binary.mt +314 -0
  14. data/std/binary_heap.mt +157 -0
  15. data/std/bitset.mt +239 -0
  16. data/std/box2d.mt +535 -0
  17. data/std/bytes.mt +46 -0
  18. data/std/c/box2d.mt +1254 -0
  19. data/std/c/cgltf.mt +647 -0
  20. data/std/c/cjson.mt +106 -0
  21. data/std/c/crypto.mt +11 -0
  22. data/std/c/crypto_support.h +51 -0
  23. data/std/c/ctype.mt +19 -0
  24. data/std/c/ctype_bindgen.h +29 -0
  25. data/std/c/curl.mt +1223 -0
  26. data/std/c/enet.mt +473 -0
  27. data/std/c/errno.mt +41 -0
  28. data/std/c/errno_bindgen.h +53 -0
  29. data/std/c/flecs.mt +2945 -0
  30. data/std/c/fs.linux.mt +43 -0
  31. data/std/c/fs.windows.mt +43 -0
  32. data/std/c/fs_support.h +954 -0
  33. data/std/c/gl.mt +2065 -0
  34. data/std/c/gl_registry_helpers.h +10748 -0
  35. data/std/c/glfw.mt +499 -0
  36. data/std/c/libc.mt +167 -0
  37. data/std/c/libuv.mt +1491 -0
  38. data/std/c/math.mt +22 -0
  39. data/std/c/math_bindgen.h +31 -0
  40. data/std/c/miniaudio.mt +3420 -0
  41. data/std/c/pcre2.mt +735 -0
  42. data/std/c/process.mt +58 -0
  43. data/std/c/process_support.h +1147 -0
  44. data/std/c/raygui.mt +1602 -0
  45. data/std/c/raylib.mt +1245 -0
  46. data/std/c/raymath.mt +163 -0
  47. data/std/c/rlgl.mt +434 -0
  48. data/std/c/rpng.mt +60 -0
  49. data/std/c/rres.mt +187 -0
  50. data/std/c/sdl3.mt +4132 -0
  51. data/std/c/sqlite3.mt +951 -0
  52. data/std/c/stb_image.mt +52 -0
  53. data/std/c/stb_image_resize2.mt +128 -0
  54. data/std/c/stb_image_write.mt +19 -0
  55. data/std/c/stb_rect_pack.mt +38 -0
  56. data/std/c/stb_truetype.mt +175 -0
  57. data/std/c/stb_vorbis.mt +31 -0
  58. data/std/c/stdio.mt +90 -0
  59. data/std/c/steamworks.h +5769 -0
  60. data/std/c/steamworks.mt +4771 -0
  61. data/std/c/string.mt +16 -0
  62. data/std/c/string_bindgen.h +36 -0
  63. data/std/c/sync.mt +33 -0
  64. data/std/c/sync_support.h +219 -0
  65. data/std/c/terminal.mt +24 -0
  66. data/std/c/terminal_support.h +408 -0
  67. data/std/c/time.mt +26 -0
  68. data/std/c/tls.mt +24 -0
  69. data/std/c/tls_support.h +626 -0
  70. data/std/c/tracy.mt +53 -0
  71. data/std/c/zlib.mt +20 -0
  72. data/std/c/zlib_support.h +239 -0
  73. data/std/c/zstd.mt +231 -0
  74. data/std/cell.mt +60 -0
  75. data/std/cgltf.mt +115 -0
  76. data/std/cjson.mt +90 -0
  77. data/std/cli.mt +768 -0
  78. data/std/cookie.mt +198 -0
  79. data/std/counter.mt +160 -0
  80. data/std/crypto.mt +74 -0
  81. data/std/cstring.mt +13 -0
  82. data/std/ctype.mt +52 -0
  83. data/std/curl/runtime.mt +261 -0
  84. data/std/curl.mt +38 -0
  85. data/std/deque.mt +348 -0
  86. data/std/encoding.mt +93 -0
  87. data/std/enet.mt +133 -0
  88. data/std/env.mt +41 -0
  89. data/std/errno.mt +47 -0
  90. data/std/flecs.mt +978 -0
  91. data/std/fmt.mt +271 -0
  92. data/std/fs.linux.mt +696 -0
  93. data/std/fs.windows.mt +711 -0
  94. data/std/fsm.mt +267 -0
  95. data/std/gl.mt +2062 -0
  96. data/std/glfw.mt +471 -0
  97. data/std/goap.mt +342 -0
  98. data/std/graph.mt +521 -0
  99. data/std/gzip.mt +77 -0
  100. data/std/hash.mt +429 -0
  101. data/std/http/server.mt +810 -0
  102. data/std/http.mt +1227 -0
  103. data/std/intern.mt +53 -0
  104. data/std/jobs.mt +288 -0
  105. data/std/json.mt +627 -0
  106. data/std/libc.mt +34 -0
  107. data/std/libuv.mt +554 -0
  108. data/std/linear_algebra.mt +243 -0
  109. data/std/linked_map.mt +372 -0
  110. data/std/linked_map_view.mt +49 -0
  111. data/std/linked_set.mt +117 -0
  112. data/std/log.mt +69 -0
  113. data/std/map.mt +418 -0
  114. data/std/math.mt +24 -0
  115. data/std/mem/arena.mt +137 -0
  116. data/std/mem/endian.mt +51 -0
  117. data/std/mem/heap.mt +298 -0
  118. data/std/mem/pool.mt +164 -0
  119. data/std/mem/stack.mt +47 -0
  120. data/std/mem/tracking.mt +119 -0
  121. data/std/miniaudio.mt +1299 -0
  122. data/std/multiset.mt +191 -0
  123. data/std/net/channel.mt +727 -0
  124. data/std/net/clock.mt +237 -0
  125. data/std/net/discovery.mt +277 -0
  126. data/std/net/lobby.mt +813 -0
  127. data/std/net/manager.mt +539 -0
  128. data/std/net/mux.mt +839 -0
  129. data/std/net/nat.mt +122 -0
  130. data/std/net/packet.mt +219 -0
  131. data/std/net/punch.mt +162 -0
  132. data/std/net/rpc.mt +119 -0
  133. data/std/net/session.mt +1157 -0
  134. data/std/net/stun.mt +252 -0
  135. data/std/net/sync.mt +183 -0
  136. data/std/net/turn.mt +459 -0
  137. data/std/net.mt +2944 -0
  138. data/std/oauth2.mt +408 -0
  139. data/std/option.mt +51 -0
  140. data/std/ordered_map.mt +497 -0
  141. data/std/ordered_set.mt +348 -0
  142. data/std/path.mt +368 -0
  143. data/std/pcre2/runtime.mt +35 -0
  144. data/std/pcre2.mt +78 -0
  145. data/std/priority_queue.mt +55 -0
  146. data/std/process.mt +837 -0
  147. data/std/queue.mt +55 -0
  148. data/std/random.mt +146 -0
  149. data/std/raygui.mt +99 -0
  150. data/std/raylib/debug_console.mt +71 -0
  151. data/std/raylib/easing.mt +388 -0
  152. data/std/raylib/packed_assets.mt +255 -0
  153. data/std/raylib/runtime.mt +30 -0
  154. data/std/raylib/tracy_gpu.mt +37 -0
  155. data/std/raylib.mt +1510 -0
  156. data/std/raymath.mt +153 -0
  157. data/std/result.mt +89 -0
  158. data/std/rlgl.mt +268 -0
  159. data/std/rpng.mt +46 -0
  160. data/std/rres.mt +36 -0
  161. data/std/sdl3/runtime.mt +54 -0
  162. data/std/sdl3.mt +1731 -0
  163. data/std/serialize.mt +68 -0
  164. data/std/set.mt +124 -0
  165. data/std/spatial.mt +176 -0
  166. data/std/sqlite3.mt +151 -0
  167. data/std/stack.mt +55 -0
  168. data/std/stb_image.mt +47 -0
  169. data/std/stb_image_resize2.mt +41 -0
  170. data/std/stb_image_write.mt +17 -0
  171. data/std/stb_rect_pack.mt +15 -0
  172. data/std/stb_truetype.mt +77 -0
  173. data/std/stb_vorbis.mt +16 -0
  174. data/std/stdio.mt +88 -0
  175. data/std/steamworks.mt +1542 -0
  176. data/std/str.mt +293 -0
  177. data/std/string.mt +234 -0
  178. data/std/sync.mt +194 -0
  179. data/std/tar.mt +704 -0
  180. data/std/terminal.mt +1002 -0
  181. data/std/testing.mt +266 -0
  182. data/std/thread.mt +120 -0
  183. data/std/time.mt +105 -0
  184. data/std/tls.mt +616 -0
  185. data/std/toml.mt +1310 -0
  186. data/std/tracy.mt +42 -0
  187. data/std/uri.mt +118 -0
  188. data/std/url.mt +372 -0
  189. data/std/vec.mt +433 -0
  190. data/std/zstd.mt +94 -0
  191. metadata +187 -2
data/std/toml.mt ADDED
@@ -0,0 +1,1310 @@
1
+ import std.str as text_ops
2
+ import std.fmt as fmt
3
+ import std.string as string
4
+ import std.vec as vec
5
+ import std.mem.heap as heap
6
+
7
+ const byte_tab: ubyte = 9
8
+ const byte_newline: ubyte = 10
9
+ const byte_carriage_return: ubyte = 13
10
+ const byte_space: ubyte = 32
11
+ const byte_quote: ubyte = 34
12
+ const byte_hash: ubyte = 35
13
+ const byte_plus: ubyte = 43
14
+ const byte_comma: ubyte = 44
15
+ const byte_minus: ubyte = 45
16
+ const byte_equal: ubyte = 61
17
+ const byte_left_bracket: ubyte = 91
18
+ const byte_backslash: ubyte = 92
19
+ const byte_right_bracket: ubyte = 93
20
+ const byte_left_brace: ubyte = 123
21
+ const byte_right_brace: ubyte = 125
22
+ const byte_underscore: ubyte = 95
23
+
24
+ public struct ParseError:
25
+ line: ptr_uint
26
+ column: ptr_uint
27
+ message: string.String
28
+
29
+ public enum ValueKind: int
30
+ string_ = 0
31
+ integer = 1
32
+ boolean = 2
33
+ array_ = 3
34
+ object_ = 4
35
+
36
+ public struct Value:
37
+ kind: ValueKind
38
+ string_value: string.String
39
+ integer_value: long
40
+ boolean_value: bool
41
+ array_value: ptr[Array]?
42
+ object_value: ptr[Object]?
43
+
44
+ public struct Entry:
45
+ key: string.String
46
+ value: Value
47
+
48
+ public struct Object:
49
+ entries: vec.Vec[Entry]
50
+
51
+ public struct Array:
52
+ values: vec.Vec[Value]
53
+
54
+ public struct Table:
55
+ name: string.String
56
+ entries: Object
57
+
58
+ public struct ArrayTable:
59
+ name: string.String
60
+ tables: vec.Vec[Object]
61
+
62
+ public struct Document:
63
+ root: Object
64
+ tables: vec.Vec[Table]
65
+ array_tables: vec.Vec[ArrayTable]
66
+
67
+ struct Parser:
68
+ text_value: str
69
+ index: ptr_uint
70
+ line: ptr_uint
71
+ column: ptr_uint
72
+
73
+ enum SectionKind: int
74
+ root = 0
75
+ table = 1
76
+ array_table = 2
77
+
78
+ struct Cursor:
79
+ kind: SectionKind
80
+ table_index: ptr_uint
81
+ array_table_index: ptr_uint
82
+ array_item_index: ptr_uint
83
+
84
+
85
+ function string_value(value: string.String) -> Value:
86
+ return Value(
87
+ kind = ValueKind.string_,
88
+ string_value = value,
89
+ integer_value = 0,
90
+ boolean_value = false,
91
+ array_value = null,
92
+ object_value = null
93
+ )
94
+
95
+
96
+ function integer_value(value: long) -> Value:
97
+ return Value(
98
+ kind = ValueKind.integer,
99
+ string_value = string.String.create(),
100
+ integer_value = value,
101
+ boolean_value = false,
102
+ array_value = null,
103
+ object_value = null
104
+ )
105
+
106
+
107
+ function boolean_value(value: bool) -> Value:
108
+ return Value(
109
+ kind = ValueKind.boolean,
110
+ string_value = string.String.create(),
111
+ integer_value = 0,
112
+ boolean_value = value,
113
+ array_value = null,
114
+ object_value = null
115
+ )
116
+
117
+
118
+ function array_value(value: ptr[Array]?) -> Value:
119
+ return Value(
120
+ kind = ValueKind.array_,
121
+ string_value = string.String.create(),
122
+ integer_value = 0,
123
+ boolean_value = false,
124
+ array_value = value,
125
+ object_value = null
126
+ )
127
+
128
+
129
+ function object_value(value: ptr[Object]?) -> Value:
130
+ return Value(
131
+ kind = ValueKind.object_,
132
+ string_value = string.String.create(),
133
+ integer_value = 0,
134
+ boolean_value = false,
135
+ array_value = null,
136
+ object_value = value
137
+ )
138
+
139
+
140
+ public function release_value(value: Value) -> void:
141
+ var owned = value.string_value
142
+ owned.release()
143
+
144
+ let nested_array = value.array_value
145
+ if nested_array != null:
146
+ unsafe:
147
+ read(nested_array).release()
148
+ heap.release(nested_array)
149
+
150
+ let nested_object = value.object_value
151
+ if nested_object != null:
152
+ unsafe:
153
+ read(nested_object).release()
154
+ heap.release(nested_object)
155
+
156
+
157
+ function value_as_string(value: Value) -> Option[str]:
158
+ if value.kind == ValueKind.string_:
159
+ return Option[str].some(value= value.string_value.as_str())
160
+
161
+ return Option[str].none
162
+
163
+
164
+ function value_as_integer(value: Value) -> Option[long]:
165
+ if value.kind == ValueKind.integer:
166
+ return Option[long].some(value= value.integer_value)
167
+
168
+ return Option[long].none
169
+
170
+
171
+ function value_as_boolean(value: Value) -> Option[bool]:
172
+ if value.kind == ValueKind.boolean:
173
+ return Option[bool].some(value= value.boolean_value)
174
+
175
+ return Option[bool].none
176
+
177
+
178
+ function value_as_array(value: Value) -> ptr[Array]?:
179
+ if value.kind == ValueKind.array_:
180
+ return value.array_value
181
+
182
+ return null
183
+
184
+
185
+ function value_as_object(value: Value) -> ptr[Object]?:
186
+ if value.kind == ValueKind.object_:
187
+ return value.object_value
188
+
189
+ return null
190
+
191
+
192
+ extending ParseError:
193
+ public editable function release() -> void:
194
+ this.message.release()
195
+
196
+
197
+ extending Entry:
198
+ public editable function release() -> void:
199
+ this.key.release()
200
+ release_value(this.value)
201
+
202
+
203
+ extending Object:
204
+ public static function create() -> Object:
205
+ return Object(entries = vec.Vec[Entry].create())
206
+
207
+
208
+ static function find_entry(current: Object, key: str) -> ptr[Entry]?:
209
+ return current.entries.find(proc(entry: ptr[Entry]) -> bool: unsafe: read(entry).key.as_str().equal(key))
210
+
211
+
212
+ public function contains(key: str) -> bool:
213
+ return Object.find_entry(this, key) != null
214
+
215
+
216
+ public function get_string(key: str) -> Option[str]:
217
+ let entry = Object.find_entry(this, key) else:
218
+ return Option[str].none
219
+
220
+ unsafe:
221
+ return value_as_string(read(entry).value)
222
+
223
+
224
+ public function get_integer(key: str) -> Option[long]:
225
+ let entry = Object.find_entry(this, key) else:
226
+ return Option[long].none
227
+
228
+ unsafe:
229
+ return value_as_integer(read(entry).value)
230
+
231
+
232
+ public function get_boolean(key: str) -> Option[bool]:
233
+ let entry = Object.find_entry(this, key) else:
234
+ return Option[bool].none
235
+
236
+ unsafe:
237
+ return value_as_boolean(read(entry).value)
238
+
239
+
240
+ public function get_array(key: str) -> ptr[Array]?:
241
+ let entry = Object.find_entry(this, key) else:
242
+ return null
243
+
244
+ unsafe:
245
+ return value_as_array(read(entry).value)
246
+
247
+
248
+ public function get_object(key: str) -> ptr[Object]?:
249
+ let entry = Object.find_entry(this, key) else:
250
+ return null
251
+
252
+ unsafe:
253
+ return value_as_object(read(entry).value)
254
+
255
+
256
+ public editable function release() -> void:
257
+ var index: ptr_uint = 0
258
+ while index < this.entries.len():
259
+ let entry = this.entries.get(index) else:
260
+ fatal(c"toml.Object.release missing entry")
261
+
262
+ unsafe:
263
+ read(entry).release()
264
+
265
+ index += 1
266
+
267
+ this.entries.release()
268
+
269
+
270
+ extending Array:
271
+ public static function create() -> Array:
272
+ return Array(values = vec.Vec[Value].create())
273
+
274
+
275
+ public function len() -> ptr_uint:
276
+ return this.values.len()
277
+
278
+
279
+ public function get_string(index: ptr_uint) -> Option[str]:
280
+ let value_ptr = this.values.get(index) else:
281
+ return Option[str].none
282
+
283
+ unsafe:
284
+ return value_as_string(read(value_ptr))
285
+
286
+
287
+ public function get_integer(index: ptr_uint) -> Option[long]:
288
+ let value_ptr = this.values.get(index) else:
289
+ return Option[long].none
290
+
291
+ unsafe:
292
+ return value_as_integer(read(value_ptr))
293
+
294
+
295
+ public function get_boolean(index: ptr_uint) -> Option[bool]:
296
+ let value_ptr = this.values.get(index) else:
297
+ return Option[bool].none
298
+
299
+ unsafe:
300
+ return value_as_boolean(read(value_ptr))
301
+
302
+
303
+ public function get_array(index: ptr_uint) -> ptr[Array]?:
304
+ let value_ptr = this.values.get(index) else:
305
+ return null
306
+
307
+ unsafe:
308
+ return value_as_array(read(value_ptr))
309
+
310
+
311
+ public function get_object(index: ptr_uint) -> ptr[Object]?:
312
+ let value_ptr = this.values.get(index) else:
313
+ return null
314
+
315
+ unsafe:
316
+ return value_as_object(read(value_ptr))
317
+
318
+
319
+ public editable function release() -> void:
320
+ var index: ptr_uint = 0
321
+ while index < this.values.len():
322
+ let value_ptr = this.values.get(index) else:
323
+ fatal(c"toml.Array.release missing value")
324
+
325
+ unsafe:
326
+ release_value(read(value_ptr))
327
+
328
+ index += 1
329
+
330
+ this.values.release()
331
+
332
+
333
+ extending Table:
334
+ public function get_string(key: str) -> Option[str]:
335
+ return this.entries.get_string(key)
336
+
337
+
338
+ public function get_integer(key: str) -> Option[long]:
339
+ return this.entries.get_integer(key)
340
+
341
+
342
+ public function get_boolean(key: str) -> Option[bool]:
343
+ return this.entries.get_boolean(key)
344
+
345
+
346
+ public function get_array(key: str) -> ptr[Array]?:
347
+ return this.entries.get_array(key)
348
+
349
+
350
+ public function get_object(key: str) -> ptr[Object]?:
351
+ return this.entries.get_object(key)
352
+
353
+
354
+ public editable function release() -> void:
355
+ this.name.release()
356
+ this.entries.release()
357
+
358
+
359
+ extending ArrayTable:
360
+ public function len() -> ptr_uint:
361
+ return this.tables.len()
362
+
363
+
364
+ public function get(index: ptr_uint) -> ptr[Object]?:
365
+ return this.tables.get(index)
366
+
367
+
368
+ public function at(index: ptr_uint) -> Option[Object]:
369
+ return this.tables.at(index)
370
+
371
+
372
+ public editable function release() -> void:
373
+ this.name.release()
374
+
375
+ var index: ptr_uint = 0
376
+ while index < this.tables.len():
377
+ let table_ptr = this.tables.get(index) else:
378
+ fatal(c"toml.ArrayTable.release missing table")
379
+
380
+ unsafe:
381
+ read(table_ptr).release()
382
+
383
+ index += 1
384
+
385
+ this.tables.release()
386
+
387
+
388
+ extending Document:
389
+ public static function create() -> Document:
390
+ return Document(
391
+ root = Object.create(),
392
+ tables = vec.Vec[Table].create(),
393
+ array_tables = vec.Vec[ArrayTable].create()
394
+ )
395
+
396
+
397
+ public function get_string(key: str) -> Option[str]:
398
+ return this.root.get_string(key)
399
+
400
+
401
+ public function get_integer(key: str) -> Option[long]:
402
+ return this.root.get_integer(key)
403
+
404
+
405
+ public function get_boolean(key: str) -> Option[bool]:
406
+ return this.root.get_boolean(key)
407
+
408
+
409
+ public function get_array(key: str) -> ptr[Array]?:
410
+ return this.root.get_array(key)
411
+
412
+
413
+ public function get_object(key: str) -> ptr[Object]?:
414
+ return this.root.get_object(key)
415
+
416
+
417
+ public function get_table(name: str) -> ptr[Table]?:
418
+ var index: ptr_uint = 0
419
+ while index < this.tables.len():
420
+ let table_ptr = this.tables.get(index) else:
421
+ fatal(c"toml.Document.get_table missing table")
422
+
423
+ unsafe:
424
+ if read(table_ptr).name.as_str().equal(name):
425
+ return table_ptr
426
+
427
+ index += 1
428
+
429
+ return null
430
+
431
+
432
+ public function get_array_table(name: str) -> ptr[ArrayTable]?:
433
+ var index: ptr_uint = 0
434
+ while index < this.array_tables.len():
435
+ let table_ptr = this.array_tables.get(index) else:
436
+ fatal(c"toml.Document.get_array_table missing table")
437
+
438
+ unsafe:
439
+ if read(table_ptr).name.as_str().equal(name):
440
+ return table_ptr
441
+
442
+ index += 1
443
+
444
+ return null
445
+
446
+
447
+ public editable function release() -> void:
448
+ this.root.release()
449
+
450
+ var table_index: ptr_uint = 0
451
+ while table_index < this.tables.len():
452
+ let table_ptr = this.tables.get(table_index) else:
453
+ fatal(c"toml.Document.release missing table")
454
+
455
+ unsafe:
456
+ read(table_ptr).release()
457
+
458
+ table_index += 1
459
+
460
+ var array_table_index: ptr_uint = 0
461
+ while array_table_index < this.array_tables.len():
462
+ let table_ptr = this.array_tables.get(array_table_index) else:
463
+ fatal(c"toml.Document.release missing array table")
464
+
465
+ unsafe:
466
+ read(table_ptr).release()
467
+
468
+ array_table_index += 1
469
+
470
+ this.tables.release()
471
+ this.array_tables.release()
472
+
473
+
474
+ function parse_error(parser: ref[Parser], message: str) -> ParseError:
475
+ return ParseError(line = parser.line, column = parser.column, message = string.String.from_str(message))
476
+
477
+
478
+ function ascii_letter(value: ubyte) -> bool:
479
+ return (value >= 65 and value <= 90) or (value >= 97 and value <= 122)
480
+
481
+
482
+ function ascii_digit(value: ubyte) -> bool:
483
+ return value >= 48 and value <= 57
484
+
485
+
486
+ function inline_space(value: ubyte) -> bool:
487
+ return value == byte_space or value == byte_tab
488
+
489
+
490
+ function bare_key_byte(value: ubyte) -> bool:
491
+ return ascii_letter(value) or ascii_digit(value) or value == byte_minus or value == byte_underscore
492
+
493
+
494
+ function header_name_byte(value: ubyte) -> bool:
495
+ return bare_key_byte(value)
496
+
497
+
498
+ function parser_peek_byte(parser: ref[Parser]) -> Option[ubyte]:
499
+ if parser.index >= parser.text_value.len:
500
+ return Option[ubyte].none
501
+
502
+ return Option[ubyte].some(value= parser.text_value.byte_at(parser.index))
503
+
504
+
505
+ function parser_peek_offset_byte(parser: ref[Parser], offset: ptr_uint) -> Option[ubyte]:
506
+ if offset > heap.ptr_uint_max - parser.index:
507
+ return Option[ubyte].none
508
+
509
+ let index = parser.index + offset
510
+ if index >= parser.text_value.len:
511
+ return Option[ubyte].none
512
+
513
+ return Option[ubyte].some(value= parser.text_value.byte_at(index))
514
+
515
+
516
+ function parser_advance(parser: ref[Parser]) -> Option[ubyte]:
517
+ if parser.index >= parser.text_value.len:
518
+ return Option[ubyte].none
519
+
520
+ let current = parser.text_value.byte_at(parser.index)
521
+ if current == byte_carriage_return:
522
+ parser.index += 1
523
+ if parser.index < parser.text_value.len and parser.text_value.byte_at(parser.index) == byte_newline:
524
+ parser.index += 1
525
+ parser.line += 1
526
+ parser.column = 1
527
+ return Option[ubyte].some(value= byte_newline)
528
+
529
+ parser.index += 1
530
+ if current == byte_newline:
531
+ parser.line += 1
532
+ parser.column = 1
533
+ else:
534
+ parser.column += 1
535
+
536
+ return Option[ubyte].some(value= current)
537
+
538
+
539
+ function parser_consume_byte(parser: ref[Parser], expected: ubyte) -> bool:
540
+ match parser_peek_byte(parser):
541
+ Option.none:
542
+ return false
543
+ Option.some as payload:
544
+ if payload.value != expected:
545
+ return false
546
+
547
+ parser_advance(parser)
548
+ return true
549
+
550
+
551
+ function parser_skip_inline_space(parser: ref[Parser]) -> void:
552
+ while true:
553
+ match parser_peek_byte(parser):
554
+ Option.none:
555
+ return
556
+ Option.some as payload:
557
+ if not inline_space(payload.value):
558
+ return
559
+ parser_advance(parser)
560
+
561
+
562
+ function parser_skip_comment(parser: ref[Parser]) -> void:
563
+ if not parser_consume_byte(parser, byte_hash):
564
+ return
565
+
566
+ while true:
567
+ match parser_peek_byte(parser):
568
+ Option.none:
569
+ return
570
+ Option.some as payload:
571
+ if payload.value == byte_newline or payload.value == byte_carriage_return:
572
+ return
573
+ parser_advance(parser)
574
+
575
+
576
+ function parser_skip_layout(parser: ref[Parser]) -> void:
577
+ while true:
578
+ parser_skip_inline_space(parser)
579
+
580
+ match parser_peek_byte(parser):
581
+ Option.none:
582
+ return
583
+ Option.some as payload:
584
+ if payload.value == byte_hash:
585
+ parser_skip_comment(parser)
586
+ continue
587
+ if payload.value == byte_newline or payload.value == byte_carriage_return:
588
+ parser_advance(parser)
589
+ continue
590
+ return
591
+
592
+
593
+ function parser_finish_line(parser: ref[Parser]) -> Result[bool, ParseError]:
594
+ parser_skip_inline_space(parser)
595
+ parser_skip_comment(parser)
596
+
597
+ match parser_peek_byte(parser):
598
+ Option.none:
599
+ return Result[bool, ParseError].success(value= true)
600
+ Option.some as payload:
601
+ if payload.value == byte_newline or payload.value == byte_carriage_return:
602
+ parser_advance(parser)
603
+ return Result[bool, ParseError].success(value= true)
604
+
605
+ return Result[bool, ParseError].failure(error= parse_error(parser, "expected end of line"))
606
+
607
+
608
+ function parser_starts_with(parser: ref[Parser], literal: str) -> bool:
609
+ if parser.text_value.len - parser.index < literal.len:
610
+ return false
611
+
612
+ var offset: ptr_uint = 0
613
+ while offset < literal.len:
614
+ if parser.text_value.byte_at(parser.index + offset) != literal.byte_at(offset):
615
+ return false
616
+ offset += 1
617
+
618
+ return true
619
+
620
+
621
+ function parser_consume_literal(parser: ref[Parser], literal: str) -> bool:
622
+ if not parser_starts_with(parser, literal):
623
+ return false
624
+
625
+ var offset: ptr_uint = 0
626
+ while offset < literal.len:
627
+ parser_advance(parser)
628
+ offset += 1
629
+
630
+ return true
631
+
632
+
633
+ function parse_string(parser: ref[Parser]) -> Result[string.String, ParseError]:
634
+ if not parser_consume_byte(parser, byte_quote):
635
+ return Result[string.String, ParseError].failure(error= parse_error(parser, "expected string"))
636
+
637
+ var result = string.String.create()
638
+ while true:
639
+ match parser_peek_byte(parser):
640
+ Option.none:
641
+ result.release()
642
+ return Result[string.String, ParseError].failure(error= parse_error(parser, "unterminated string"))
643
+ Option.some as payload:
644
+ let current = payload.value
645
+ if current == byte_quote:
646
+ parser_advance(parser)
647
+ return Result[string.String, ParseError].success(value= result)
648
+ if current == byte_newline or current == byte_carriage_return:
649
+ result.release()
650
+ return Result[string.String, ParseError].failure(error= parse_error(parser, "unterminated string"))
651
+ if current != byte_backslash:
652
+ result.push_byte(current)
653
+ parser_advance(parser)
654
+ continue
655
+
656
+ parser_advance(parser)
657
+ match parser_advance(parser):
658
+ Option.none:
659
+ result.release()
660
+ return Result[string.String, ParseError].failure(error= parse_error(parser, "unterminated escape"))
661
+ Option.some as payload:
662
+ let escaped = payload.value
663
+ if escaped == 98:
664
+ result.push_byte(8)
665
+ else if escaped == 102:
666
+ result.push_byte(12)
667
+ else if escaped == 110:
668
+ result.push_byte(byte_newline)
669
+ else if escaped == 114:
670
+ result.push_byte(byte_carriage_return)
671
+ else if escaped == 116:
672
+ result.push_byte(byte_tab)
673
+ else if escaped == byte_quote:
674
+ result.push_byte(byte_quote)
675
+ else if escaped == byte_backslash:
676
+ result.push_byte(byte_backslash)
677
+ else:
678
+ result.release()
679
+ return Result[string.String, ParseError].failure(error= parse_error(
680
+ parser,
681
+ "unsupported string escape"
682
+ ))
683
+
684
+
685
+ function parse_key(parser: ref[Parser]) -> Result[string.String, ParseError]:
686
+ match parser_peek_byte(parser):
687
+ Option.none:
688
+ return Result[string.String, ParseError].failure(error= parse_error(parser, "expected key"))
689
+ Option.some as payload:
690
+ if payload.value == byte_quote:
691
+ return parse_string(parser)
692
+ if not bare_key_byte(payload.value):
693
+ return Result[string.String, ParseError].failure(error= parse_error(parser, "expected key"))
694
+
695
+ let start = parser.index
696
+ while true:
697
+ var advance = false
698
+ match parser_peek_byte(parser):
699
+ Option.none:
700
+ pass
701
+ Option.some as payload:
702
+ if not bare_key_byte(payload.value):
703
+ pass
704
+ else:
705
+ advance = true
706
+
707
+ if not advance:
708
+ break
709
+
710
+ parser_advance(parser)
711
+
712
+ let key_text = parser.text_value.slice(start, parser.index - start)
713
+ return Result[string.String, ParseError].success(value= string.String.from_str(key_text))
714
+
715
+
716
+ function parse_header_name(parser: ref[Parser]) -> Result[string.String, ParseError]:
717
+ match parser_peek_byte(parser):
718
+ Option.none:
719
+ return Result[string.String, ParseError].failure(error= parse_error(parser, "expected header name"))
720
+ Option.some as payload:
721
+ if payload.value == byte_quote:
722
+ return parse_string(parser)
723
+ if not header_name_byte(payload.value):
724
+ return Result[string.String, ParseError].failure(error= parse_error(parser, "expected header name"))
725
+
726
+ let start = parser.index
727
+ while true:
728
+ var advance = false
729
+ match parser_peek_byte(parser):
730
+ Option.none:
731
+ pass
732
+ Option.some as payload:
733
+ if not header_name_byte(payload.value):
734
+ pass
735
+ else:
736
+ advance = true
737
+
738
+ if not advance:
739
+ break
740
+
741
+ parser_advance(parser)
742
+
743
+ let name_text = parser.text_value.slice(start, parser.index - start)
744
+ return Result[string.String, ParseError].success(value= string.String.from_str(name_text))
745
+
746
+
747
+ function parse_integer(parser: ref[Parser]) -> Result[long, ParseError]:
748
+ var negative = false
749
+ match parser_peek_byte(parser):
750
+ Option.none:
751
+ return Result[long, ParseError].failure(error= parse_error(parser, "expected integer"))
752
+ Option.some as payload:
753
+ if payload.value == byte_minus:
754
+ negative = true
755
+ parser_advance(parser)
756
+ else if payload.value == byte_plus:
757
+ parser_advance(parser)
758
+
759
+ match parser_peek_byte(parser):
760
+ Option.none:
761
+ return Result[long, ParseError].failure(error= parse_error(parser, "expected integer"))
762
+ Option.some as payload:
763
+ if not ascii_digit(payload.value):
764
+ return Result[long, ParseError].failure(error= parse_error(parser, "expected integer"))
765
+
766
+ var result: long = 0
767
+ while true:
768
+ var advance = false
769
+ match parser_peek_byte(parser):
770
+ Option.none:
771
+ pass
772
+ Option.some as payload:
773
+ if not ascii_digit(payload.value):
774
+ pass
775
+ else:
776
+ result = result * 10 + long<-(payload.value - 48ub)
777
+ advance = true
778
+
779
+ if not advance:
780
+ break
781
+
782
+ parser_advance(parser)
783
+
784
+ if negative:
785
+ result = -result
786
+
787
+ return Result[long, ParseError].success(value= result)
788
+
789
+
790
+ function parse_boolean(parser: ref[Parser]) -> Result[bool, ParseError]:
791
+ if parser_consume_literal(parser, "true"):
792
+ return Result[bool, ParseError].success(value= true)
793
+ if parser_consume_literal(parser, "false"):
794
+ return Result[bool, ParseError].success(value= false)
795
+
796
+ return Result[bool, ParseError].failure(error= parse_error(parser, "expected boolean"))
797
+
798
+
799
+ function parse_array(parser: ref[Parser]) -> Result[ptr[Array]?, ParseError]:
800
+ if not parser_consume_byte(parser, byte_left_bracket):
801
+ return Result[ptr[Array]?, ParseError].failure(error= parse_error(parser, "expected array"))
802
+
803
+ let array_ptr = heap.must_alloc[Array](1)
804
+ unsafe:
805
+ read(array_ptr) = Array.create()
806
+
807
+ parser_skip_inline_space(parser)
808
+ if parser_consume_byte(parser, byte_right_bracket):
809
+ return Result[ptr[Array]?, ParseError].success(value= array_ptr)
810
+
811
+ while true:
812
+ parser_skip_inline_space(parser)
813
+ let value_result = parse_value(parser)
814
+ match value_result:
815
+ Result.failure as payload:
816
+ unsafe:
817
+ read(array_ptr).release()
818
+ heap.release(array_ptr)
819
+ return Result[ptr[Array]?, ParseError].failure(error= payload.error)
820
+ Result.success as payload:
821
+ unsafe:
822
+ read(array_ptr).values.push(payload.value)
823
+
824
+ parser_skip_inline_space(parser)
825
+ if parser_consume_byte(parser, byte_comma):
826
+ continue
827
+ if parser_consume_byte(parser, byte_right_bracket):
828
+ return Result[ptr[Array]?, ParseError].success(value= array_ptr)
829
+
830
+ unsafe:
831
+ read(array_ptr).release()
832
+ heap.release(array_ptr)
833
+ return Result[ptr[Array]?, ParseError].failure(error= parse_error(parser, "expected ',' or ']'"))
834
+
835
+
836
+ function parse_inline_object(parser: ref[Parser]) -> Result[ptr[Object]?, ParseError]:
837
+ if not parser_consume_byte(parser, byte_left_brace):
838
+ return Result[ptr[Object]?, ParseError].failure(error= parse_error(parser, "expected inline table"))
839
+
840
+ let object_ptr = heap.must_alloc[Object](1)
841
+ unsafe:
842
+ read(object_ptr) = Object.create()
843
+
844
+ parser_skip_inline_space(parser)
845
+ if parser_consume_byte(parser, byte_right_brace):
846
+ return Result[ptr[Object]?, ParseError].success(value= object_ptr)
847
+
848
+ while true:
849
+ parser_skip_inline_space(parser)
850
+ let key_result = parse_key(parser)
851
+ match key_result:
852
+ Result.failure as payload:
853
+ unsafe:
854
+ read(object_ptr).release()
855
+ heap.release(object_ptr)
856
+ return Result[ptr[Object]?, ParseError].failure(error= payload.error)
857
+ Result.success as key_payload:
858
+ var key = key_payload.value
859
+ parser_skip_inline_space(parser)
860
+ if not parser_consume_byte(parser, byte_equal):
861
+ key.release()
862
+ unsafe:
863
+ read(object_ptr).release()
864
+ heap.release(object_ptr)
865
+ return Result[ptr[Object]?, ParseError].failure(error= parse_error(parser, "expected '='"))
866
+
867
+ parser_skip_inline_space(parser)
868
+ let value_result = parse_value(parser)
869
+ match value_result:
870
+ Result.failure as payload:
871
+ key.release()
872
+ unsafe:
873
+ read(object_ptr).release()
874
+ heap.release(object_ptr)
875
+ return Result[ptr[Object]?, ParseError].failure(error= payload.error)
876
+ Result.success as value_payload:
877
+ let key_text = key.as_str()
878
+ if unsafe: read(object_ptr).contains(key_text):
879
+ key.release()
880
+ release_value(value_payload.value)
881
+ unsafe:
882
+ read(object_ptr).release()
883
+ heap.release(object_ptr)
884
+ return Result[ptr[Object]?, ParseError].failure(error= parse_error(parser, "duplicate key"))
885
+
886
+ unsafe:
887
+ read(object_ptr).entries.push(Entry(key = key, value = value_payload.value))
888
+
889
+ parser_skip_inline_space(parser)
890
+ if parser_consume_byte(parser, byte_comma):
891
+ continue
892
+ if parser_consume_byte(parser, byte_right_brace):
893
+ return Result[ptr[Object]?, ParseError].success(value= object_ptr)
894
+
895
+ unsafe:
896
+ read(object_ptr).release()
897
+ heap.release(object_ptr)
898
+ return Result[ptr[Object]?, ParseError].failure(error= parse_error(parser, "expected ',' or '}'"))
899
+
900
+
901
+ function parse_value(parser: ref[Parser]) -> Result[Value, ParseError]:
902
+ match parser_peek_byte(parser):
903
+ Option.none:
904
+ return Result[Value, ParseError].failure(error= parse_error(parser, "expected value"))
905
+ Option.some as payload:
906
+ let current = payload.value
907
+ if current == byte_quote:
908
+ let string_result = parse_string(parser)
909
+ match string_result:
910
+ Result.failure as error_payload:
911
+ return Result[Value, ParseError].failure(error= error_payload.error)
912
+ Result.success as string_payload:
913
+ return Result[Value, ParseError].success(value= string_value(string_payload.value))
914
+
915
+ if current == byte_left_bracket:
916
+ let array_result = parse_array(parser)
917
+ match array_result:
918
+ Result.failure as error_payload:
919
+ return Result[Value, ParseError].failure(error= error_payload.error)
920
+ Result.success as array_payload:
921
+ return Result[Value, ParseError].success(value= array_value(array_payload.value))
922
+
923
+ if current == byte_left_brace:
924
+ let object_result = parse_inline_object(parser)
925
+ match object_result:
926
+ Result.failure as error_payload:
927
+ return Result[Value, ParseError].failure(error= error_payload.error)
928
+ Result.success as object_payload:
929
+ return Result[Value, ParseError].success(value= object_value(object_payload.value))
930
+
931
+ if current == 116 or current == 102:
932
+ let boolean_result = parse_boolean(parser)
933
+ match boolean_result:
934
+ Result.failure as error_payload:
935
+ return Result[Value, ParseError].failure(error= error_payload.error)
936
+ Result.success as boolean_payload:
937
+ return Result[Value, ParseError].success(value= boolean_value(boolean_payload.value))
938
+
939
+ if ascii_digit(current) or current == byte_minus or current == byte_plus:
940
+ let integer_result = parse_integer(parser)
941
+ match integer_result:
942
+ Result.failure as error_payload:
943
+ return Result[Value, ParseError].failure(error= error_payload.error)
944
+ Result.success as integer_payload:
945
+ return Result[Value, ParseError].success(value= integer_value(integer_payload.value))
946
+
947
+ return Result[Value, ParseError].failure(error= parse_error(parser, "unsupported value"))
948
+
949
+
950
+ function document_find_table_index(document: ref[Document], name: str) -> Option[ptr_uint]:
951
+ return document.tables.find_index(proc(table_ptr: ptr[Table]) -> bool: unsafe: read(table_ptr).name.as_str().equal(name))
952
+
953
+
954
+ function document_find_array_table_index(document: ref[Document], name: str) -> Option[ptr_uint]:
955
+ return document.array_tables.find_index(proc(table_ptr: ptr[ArrayTable]) -> bool: unsafe: read(table_ptr).name.as_str().equal(name))
956
+
957
+
958
+ function current_object_contains(document: ref[Document], cursor: Cursor, key: str) -> bool:
959
+ match cursor.kind:
960
+ SectionKind.root:
961
+ return document.root.contains(key)
962
+ SectionKind.table:
963
+ let table_ptr = document.tables.get(cursor.table_index) else:
964
+ fatal(c"toml.current_object_contains missing table")
965
+
966
+ unsafe:
967
+ return read(table_ptr).entries.contains(key)
968
+ SectionKind.array_table:
969
+ let array_table_ptr = document.array_tables.get(cursor.array_table_index) else:
970
+ fatal(c"toml.current_object_contains missing array table")
971
+
972
+ unsafe:
973
+ let object_ptr = read(array_table_ptr).tables.get(cursor.array_item_index) else:
974
+ fatal(c"toml.current_object_contains missing array table item")
975
+
976
+ return read(object_ptr).contains(key)
977
+
978
+
979
+ function current_object_push(document: ref[Document], cursor: Cursor, entry: Entry) -> void:
980
+ match cursor.kind:
981
+ SectionKind.root:
982
+ document.root.entries.push(entry)
983
+ return
984
+ SectionKind.table:
985
+ let table_ptr = document.tables.get(cursor.table_index) else:
986
+ fatal(c"toml.current_object_push missing table")
987
+
988
+ unsafe:
989
+ read(table_ptr).entries.entries.push(entry)
990
+ return
991
+ SectionKind.array_table:
992
+ let array_table_ptr = document.array_tables.get(cursor.array_table_index) else:
993
+ fatal(c"toml.current_object_push missing array table")
994
+
995
+ unsafe:
996
+ let object_ptr = read(array_table_ptr).tables.get(cursor.array_item_index) else:
997
+ fatal(c"toml.current_object_push missing array table item")
998
+
999
+ read(object_ptr).entries.push(entry)
1000
+ return
1001
+
1002
+
1003
+ function parse_assignment(document: ref[Document], cursor: Cursor, parser: ref[Parser]) -> Result[bool, ParseError]:
1004
+ let key_result = parse_key(parser)
1005
+ match key_result:
1006
+ Result.failure as payload:
1007
+ return Result[bool, ParseError].failure(error= payload.error)
1008
+ Result.success as key_payload:
1009
+ var key = key_payload.value
1010
+ parser_skip_inline_space(parser)
1011
+ if not parser_consume_byte(parser, byte_equal):
1012
+ key.release()
1013
+ return Result[bool, ParseError].failure(error= parse_error(parser, "expected '='"))
1014
+
1015
+ parser_skip_inline_space(parser)
1016
+ let value_result = parse_value(parser)
1017
+ match value_result:
1018
+ Result.failure as payload:
1019
+ key.release()
1020
+ return Result[bool, ParseError].failure(error= payload.error)
1021
+ Result.success as value_payload:
1022
+ let key_text = key.as_str()
1023
+ if current_object_contains(document, cursor, key_text):
1024
+ key.release()
1025
+ release_value(value_payload.value)
1026
+ return Result[bool, ParseError].failure(error= parse_error(parser, "duplicate key"))
1027
+
1028
+ current_object_push(document, cursor, Entry(key = key, value = value_payload.value))
1029
+ return Result[bool, ParseError].success(value= true)
1030
+
1031
+
1032
+ function parse_header(document: ref[Document], cursor: ref[Cursor], parser: ref[Parser]) -> Result[bool, ParseError]:
1033
+ if not parser_consume_byte(parser, byte_left_bracket):
1034
+ return Result[bool, ParseError].failure(error= parse_error(parser, "expected table header"))
1035
+
1036
+ let array_table = parser_consume_byte(parser, byte_left_bracket)
1037
+ parser_skip_inline_space(parser)
1038
+
1039
+ let name_result = parse_header_name(parser)
1040
+ match name_result:
1041
+ Result.failure as payload:
1042
+ return Result[bool, ParseError].failure(error= payload.error)
1043
+ Result.success as name_payload:
1044
+ var name = name_payload.value
1045
+ parser_skip_inline_space(parser)
1046
+
1047
+ if array_table:
1048
+ if not parser_consume_byte(
1049
+ parser,
1050
+ byte_right_bracket
1051
+ ) or not parser_consume_byte(parser, byte_right_bracket):
1052
+ name.release()
1053
+ return Result[bool, ParseError].failure(error= parse_error(parser, "expected ']]'"))
1054
+
1055
+ match document_find_table_index(document, name.as_str()):
1056
+ Option.some:
1057
+ name.release()
1058
+ return Result[bool, ParseError].failure(error= parse_error(parser, "table name already used"))
1059
+ Option.none:
1060
+ pass
1061
+
1062
+ match document_find_array_table_index(document, name.as_str()):
1063
+ Option.some as payload:
1064
+ let index = payload.value
1065
+ name.release()
1066
+ let array_table_ptr = document.array_tables.get(index) else:
1067
+ fatal(c"toml.parse_header missing array table")
1068
+
1069
+ unsafe:
1070
+ read(array_table_ptr).tables.push(Object.create())
1071
+ cursor.kind = SectionKind.array_table
1072
+ cursor.array_table_index = index
1073
+ cursor.array_item_index = read(array_table_ptr).tables.len() - 1
1074
+ return Result[bool, ParseError].success(value= true)
1075
+ Option.none:
1076
+ var next = ArrayTable(name = name, tables = vec.Vec[Object].create())
1077
+ next.tables.push(Object.create())
1078
+ document.array_tables.push(next)
1079
+ cursor.kind = SectionKind.array_table
1080
+ cursor.array_table_index = document.array_tables.len() - 1
1081
+ cursor.array_item_index = 0
1082
+ return Result[bool, ParseError].success(value= true)
1083
+
1084
+ if not parser_consume_byte(parser, byte_right_bracket):
1085
+ name.release()
1086
+ return Result[bool, ParseError].failure(error= parse_error(parser, "expected ']'"))
1087
+
1088
+ match document_find_table_index(document, name.as_str()):
1089
+ Option.some:
1090
+ name.release()
1091
+ return Result[bool, ParseError].failure(error= parse_error(parser, "duplicate table"))
1092
+ Option.none:
1093
+ pass
1094
+
1095
+ match document_find_array_table_index(document, name.as_str()):
1096
+ Option.some:
1097
+ name.release()
1098
+ return Result[bool, ParseError].failure(error= parse_error(parser, "duplicate table"))
1099
+ Option.none:
1100
+ pass
1101
+
1102
+ document.tables.push(Table(name = name, entries = Object.create()))
1103
+ cursor.kind = SectionKind.table
1104
+ cursor.table_index = document.tables.len() - 1
1105
+ return Result[bool, ParseError].success(value= true)
1106
+
1107
+
1108
+ public function parse(text_value: str) -> Result[Document, ParseError]:
1109
+ var parser = Parser(text_value = text_value, index = 0, line = 1, column = 1)
1110
+ var document = Document.create()
1111
+ var cursor = Cursor(kind = SectionKind.root, table_index = 0, array_table_index = 0, array_item_index = 0)
1112
+
1113
+ while true:
1114
+ parser_skip_layout(ref_of(parser))
1115
+
1116
+ let next_byte = parser_peek_byte(ref_of(parser)) else:
1117
+ return Result[Document, ParseError].success(value= document)
1118
+
1119
+ var statement_result = Result[bool, ParseError].success(value= true)
1120
+ if next_byte == byte_left_bracket:
1121
+ statement_result = parse_header(ref_of(document), ref_of(cursor), ref_of(parser))
1122
+ else:
1123
+ statement_result = parse_assignment(ref_of(document), cursor, ref_of(parser))
1124
+
1125
+ match statement_result:
1126
+ Result.failure as payload:
1127
+ document.release()
1128
+ return Result[Document, ParseError].failure(error= payload.error)
1129
+ Result.success:
1130
+ let line_result = parser_finish_line(ref_of(parser))
1131
+ match line_result:
1132
+ Result.failure as payload:
1133
+ document.release()
1134
+ return Result[Document, ParseError].failure(error= payload.error)
1135
+ Result.success:
1136
+ pass
1137
+
1138
+
1139
+ function append_quoted_string(output: ref[string.String], text_value: str) -> void:
1140
+ output.push_byte(byte_quote)
1141
+
1142
+ var index: ptr_uint = 0
1143
+ while index < text_value.len:
1144
+ let value = text_value.byte_at(index)
1145
+ if value == byte_backslash:
1146
+ output.append("\\\\")
1147
+ else if value == byte_quote:
1148
+ output.append("\\\"")
1149
+ else if value == byte_newline:
1150
+ output.append("\\n")
1151
+ else if value == byte_carriage_return:
1152
+ output.append("\\r")
1153
+ else if value == byte_tab:
1154
+ output.append("\\t")
1155
+ else if value == 8:
1156
+ output.append("\\b")
1157
+ else if value == 12:
1158
+ output.append("\\f")
1159
+ else:
1160
+ output.push_byte(value)
1161
+ index += 1
1162
+
1163
+ output.push_byte(byte_quote)
1164
+
1165
+
1166
+ function bare_header_name(text_value: str) -> bool:
1167
+ if text_value.len == 0:
1168
+ return false
1169
+
1170
+ var index: ptr_uint = 0
1171
+ while index < text_value.len:
1172
+ if not header_name_byte(text_value.byte_at(index)):
1173
+ return false
1174
+ index += 1
1175
+
1176
+ return true
1177
+
1178
+
1179
+ function append_header_name(output: ref[string.String], name: str) -> void:
1180
+ if bare_header_name(name):
1181
+ output.append(name)
1182
+ else:
1183
+ append_quoted_string(output, name)
1184
+
1185
+
1186
+ function append_entry_key(output: ref[string.String], key: str) -> void:
1187
+ append_quoted_string(output, key)
1188
+
1189
+
1190
+ function append_value(output: ref[string.String], value: Value) -> void:
1191
+ if value.kind == ValueKind.string_:
1192
+ append_quoted_string(output, value.string_value.as_str())
1193
+ return
1194
+
1195
+ if value.kind == ValueKind.integer:
1196
+ fmt.append_long(output, value.integer_value)
1197
+ return
1198
+
1199
+ if value.kind == ValueKind.boolean:
1200
+ fmt.append_bool(output, value.boolean_value)
1201
+ return
1202
+
1203
+ if value.kind == ValueKind.array_:
1204
+ output.push_byte(byte_left_bracket)
1205
+ let nested_array = value.array_value
1206
+ if nested_array != null:
1207
+ unsafe:
1208
+ let values = read(nested_array)
1209
+ var index: ptr_uint = 0
1210
+ while index < values.len():
1211
+ if index != 0:
1212
+ output.append(", ")
1213
+
1214
+ let item = values.values.get(index) else:
1215
+ fatal(c"toml.append_value missing array item")
1216
+
1217
+ append_value(output, unsafe: read(item))
1218
+ index += 1
1219
+
1220
+ output.push_byte(byte_right_bracket)
1221
+ return
1222
+
1223
+ output.push_byte(byte_left_brace)
1224
+ let nested_object = value.object_value
1225
+ if nested_object != null:
1226
+ unsafe:
1227
+ let object_entries = read(nested_object)
1228
+ var index: ptr_uint = 0
1229
+ while index < object_entries.entries.len():
1230
+ if index != 0:
1231
+ output.append(", ")
1232
+
1233
+ let entry = object_entries.entries.get(index) else:
1234
+ fatal(c"toml.append_value missing object entry")
1235
+
1236
+ let current = unsafe: read(entry)
1237
+ append_entry_key(output, current.key.as_str())
1238
+ output.append(" = ")
1239
+ append_value(output, current.value)
1240
+ index += 1
1241
+
1242
+ output.push_byte(byte_right_brace)
1243
+
1244
+
1245
+ function append_table_entries(output: ref[string.String], object_entries: Object) -> void:
1246
+ var index: ptr_uint = 0
1247
+ while index < object_entries.entries.len():
1248
+ let entry = object_entries.entries.get(index) else:
1249
+ fatal(c"toml.append_table_entries missing entry")
1250
+
1251
+ let current = unsafe: read(entry)
1252
+ append_entry_key(output, current.key.as_str())
1253
+ output.append(" = ")
1254
+ append_value(output, current.value)
1255
+ output.append("\n")
1256
+ index += 1
1257
+
1258
+
1259
+ public function render(document: Document) -> string.String:
1260
+ var output = string.String.create()
1261
+
1262
+ append_table_entries(ref_of(output), document.root)
1263
+
1264
+ let has_root = document.root.entries.len() > 0
1265
+ let has_sections = document.tables.len() > 0 or document.array_tables.len() > 0
1266
+ if has_root and has_sections:
1267
+ output.append("\n")
1268
+
1269
+ var table_index: ptr_uint = 0
1270
+ while table_index < document.tables.len():
1271
+ if table_index != 0:
1272
+ output.append("\n")
1273
+
1274
+ let table_ptr = document.tables.get(table_index) else:
1275
+ fatal(c"toml.render missing table")
1276
+
1277
+ let current = unsafe: read(table_ptr)
1278
+ output.push_byte(byte_left_bracket)
1279
+ append_header_name(ref_of(output), current.name.as_str())
1280
+ output.push_byte(byte_right_bracket)
1281
+ output.append("\n")
1282
+ append_table_entries(ref_of(output), current.entries)
1283
+ table_index += 1
1284
+
1285
+ var array_table_index: ptr_uint = 0
1286
+ while array_table_index < document.array_tables.len():
1287
+ let array_table_ptr = document.array_tables.get(array_table_index) else:
1288
+ fatal(c"toml.render missing array table")
1289
+
1290
+ let current = unsafe: read(array_table_ptr)
1291
+ var object_index: ptr_uint = 0
1292
+ while object_index < current.tables.len():
1293
+ if output.len() > 0 and not output.as_str().ends_with("\n\n"):
1294
+ output.append("\n")
1295
+
1296
+ output.push_byte(byte_left_bracket)
1297
+ output.push_byte(byte_left_bracket)
1298
+ append_header_name(ref_of(output), current.name.as_str())
1299
+ output.push_byte(byte_right_bracket)
1300
+ output.push_byte(byte_right_bracket)
1301
+ output.append("\n")
1302
+
1303
+ let object_ptr = current.tables.get(object_index) else:
1304
+ fatal(c"toml.render missing array table item")
1305
+
1306
+ append_table_entries(ref_of(output), unsafe: read(object_ptr))
1307
+ object_index += 1
1308
+ array_table_index += 1
1309
+
1310
+ return output