mt-lang 0.4.24 → 0.4.25

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +8 -8
  5. data/lib/milk_tea/base.rb +1 -1
  6. data/lib/milk_tea/core/control_flow/builder.rb +12 -0
  7. data/lib/milk_tea/tooling/cli/commands/std.rb +84 -0
  8. data/lib/milk_tea/tooling/cli.rb +25 -0
  9. data/lib/milk_tea/tooling/linter/fix_engine.rb +100 -0
  10. data/lib/milk_tea/tooling/linter/release_rules.rb +69 -11
  11. data/lib/milk_tea/tooling/linter/visitors.rb +58 -31
  12. data/lib/milk_tea/tooling/linter.rb +8 -1
  13. data/lib/milk_tea/tooling/std_catalog.rb +277 -0
  14. data/lib/milk_tea/tooling.rb +1 -0
  15. data/std/async/libuv_runtime.mt +20 -23
  16. data/std/async/mailbox.mt +2 -2
  17. data/std/base64.mt +3 -6
  18. data/std/behavior_tree.mt +1 -6
  19. data/std/binary.mt +2 -5
  20. data/std/color.mt +20 -20
  21. data/std/cookie.mt +1 -4
  22. data/std/deque.mt +2 -8
  23. data/std/encoding.mt +1 -4
  24. data/std/fmt.mt +1 -4
  25. data/std/graph.mt +5 -1
  26. data/std/htn.mt +9 -1
  27. data/std/http/server.mt +1 -4
  28. data/std/http.mt +14 -17
  29. data/std/jobs.mt +9 -10
  30. data/std/json.mt +17 -28
  31. data/std/linked_map.mt +3 -9
  32. data/std/map.mt +1 -4
  33. data/std/net/channel.mt +6 -6
  34. data/std/net/lobby.mt +3 -3
  35. data/std/net/manager.mt +0 -1
  36. data/std/net/mux.mt +1 -1
  37. data/std/net/packet.mt +4 -1
  38. data/std/net/punch.mt +3 -2
  39. data/std/net/rpc.mt +1 -3
  40. data/std/net/session.mt +12 -25
  41. data/std/net/sync.mt +3 -3
  42. data/std/net/turn.mt +7 -3
  43. data/std/net.mt +145 -159
  44. data/std/noise.mt +11 -7
  45. data/std/ordered_map.mt +2 -8
  46. data/std/ordered_set.mt +3 -5
  47. data/std/path.mt +1 -4
  48. data/std/process.mt +7 -18
  49. data/std/random.mt +2 -2
  50. data/std/sdl3/runtime.mt +1 -1
  51. data/std/steering.mt +27 -4
  52. data/std/string.mt +1 -4
  53. data/std/tar.mt +8 -10
  54. data/std/terminal.mt +21 -40
  55. data/std/thread.mt +3 -4
  56. data/std/tls.mt +22 -29
  57. data/std/toml.mt +23 -31
  58. data/std/uri.mt +2 -1
  59. data/std/utility.mt +2 -2
  60. data/std/vec.mt +7 -17
  61. metadata +5 -3
@@ -0,0 +1,277 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ # Discovers the hand-written standard library modules shipped in std/, and
5
+ # resolves module names to source paths for tooling commands.
6
+ #
7
+ # Generated modules (bindgen output under std/c/ and imported-binding
8
+ # wrappers such as raylib or zstd) are excluded from discovery but stay
9
+ # resolvable, so `std show` can still print them.
10
+ class StdCatalog
11
+ Entry = Struct.new(:name, :description, :category, :path, keyword_init: true)
12
+
13
+ GENERATED_HEADER_PREFIX = "# generated by mtc"
14
+ PLATFORM_SUFFIXES = %w[linux windows wasm].freeze
15
+ EXCLUDED_DIRECTORIES = %w[c].freeze
16
+
17
+ CATEGORY_ORDER = [
18
+ "Core & Patterns",
19
+ "Collections",
20
+ "Memory",
21
+ "Text & Formatting",
22
+ "Math & Simulation",
23
+ "Data & Serialization",
24
+ "Concurrency & Time",
25
+ "Files & System",
26
+ "Network",
27
+ "Security",
28
+ "AI & Behavior",
29
+ "Game & Graphics",
30
+ ].freeze
31
+
32
+ # name => [category, description]. Must cover every hand-written module
33
+ # discovered under std/; a test enforces that coverage.
34
+ REGISTRY = {
35
+ "asset_pack" => ["Game & Graphics", "MTAP asset pack reader and writer for bundled runtime assets."],
36
+ "async" => ["Concurrency & Time", "Async/await runtime facade over a pluggable event-loop backend."],
37
+ "async.libuv_runtime" => ["Concurrency & Time", "libuv-backed async runtime implementation."],
38
+ "async.mailbox" => ["Concurrency & Time", "Typed mailboxes for message passing between async tasks."],
39
+ "async.runtime" => ["Concurrency & Time", "Async backend selection and event-loop plumbing shared by async code."],
40
+ "base64" => ["Text & Formatting", "Base64 encode and decode."],
41
+ "behavior_tree" => ["AI & Behavior", "Behavior trees with sequence, selector, decorator, and leaf nodes."],
42
+ "binary" => ["Data & Serialization", "Binary reader/writer with explicit endianness and error reporting."],
43
+ "binary_heap" => ["Collections", "Binary heap over a flat array with sift-up/sift-down operations."],
44
+ "bitset" => ["Collections", "Fixed-capacity bit array with set, clear, test, and population count."],
45
+ "blackboard" => ["AI & Behavior", "Typed key-value shared state for AI agents."],
46
+ "box" => ["Core & Patterns", "Explicit single-value heap storage for owned boxed values."],
47
+ "bytes" => ["Data & Serialization", "Byte buffer type with slicing, comparison, and stream I/O."],
48
+ "cli" => ["Files & System", "Command-line parsing helpers for flags, options, and positionals."],
49
+ "cmd" => ["Core & Patterns", "Command pattern with paired do/undo callbacks for undo/redo stacks."],
50
+ "color" => ["Game & Graphics", "RGBA color conversion, blending, and named presets."],
51
+ "cookie" => ["Data & Serialization", "HTTP cookie parsing and serialization."],
52
+ "counter" => ["Collections", "Occurrence counter keyed by value, a counting multiset."],
53
+ "crypto" => ["Security", "Digests, HMAC, and secure random via the platform crypto bindings."],
54
+ "cstring" => ["Text & Formatting", "Null-terminated C string helpers backed by libc memory routines."],
55
+ "ctype" => ["Text & Formatting", "Character classification: alnum, digit, space, and case tests."],
56
+ "curl.runtime" => ["Network", "libcurl runtime glue for handle setup and error reporting."],
57
+ "deque" => ["Collections", "Double-ended queue with amortized O(1) operations at both ends."],
58
+ "encoding" => ["Text & Formatting", "UTF-8 validation, codepoint iteration, and encoding helpers."],
59
+ "env" => ["Files & System", "Environment variable access returning Option values."],
60
+ "errno" => ["Files & System", "errno code constants and error message lookup."],
61
+ "fmt" => ["Text & Formatting", "Value formatting helpers for integers, floats, and fixed buffers."],
62
+ "fs" => ["Files & System", "File and directory operations with platform-specific variants."],
63
+ "fsm" => ["AI & Behavior", "Finite state machines with table-driven transitions and dispatch."],
64
+ "goap" => ["AI & Behavior", "Goal-oriented action planning (GOAP) with forward search."],
65
+ "graph" => ["Game & Graphics", "Weighted graph algorithms such as shortest paths and reachability."],
66
+ "gzip" => ["Data & Serialization", "Gzip and zlib compression and decompression."],
67
+ "hash" => ["Core & Patterns", "Canonical hash, equality, and ordering for common primitive types."],
68
+ "htn" => ["AI & Behavior", "Hierarchical Task Network (HTN) planner."],
69
+ "http" => ["Network", "HTTP client for requests, responses, and chunked bodies."],
70
+ "http.server" => ["Network", "Small HTTP server with routing, static files, and JSON responses."],
71
+ "input" => ["Game & Graphics", "Input action mapping that decouples logical actions from physical devices."],
72
+ "intern" => ["Text & Formatting", "String interning table producing unique identifier handles."],
73
+ "iter" => ["Core & Patterns", "Composable lazy iteration adaptors over sequences."],
74
+ "jobs" => ["Concurrency & Time", "Job scheduler for fan-out parallel work with completion tracking."],
75
+ "json" => ["Data & Serialization", "JSON parsing and serialization over cjson with arena-backed values."],
76
+ "libc" => ["Files & System", "Curated libc facade for memory, string, process, and math functions."],
77
+ "linear_algebra" => ["Math & Simulation", "Vectors and matrices for 2D/3D graphics and physics."],
78
+ "linked_map" => ["Collections", "Hash map with a doubly-linked order list for O(1) reordering."],
79
+ "linked_map_view" => ["Collections", "Read-only snapshot views over linked_map instances."],
80
+ "linked_set" => ["Collections", "Insertion-ordered hash set backed by a linked list."],
81
+ "log" => ["Files & System", "Leveled logging with configurable output sinks."],
82
+ "lru_cache" => ["Collections", "Least-recently-used cache with bounded capacity."],
83
+ "map" => ["Collections", "Chained hash map with pluggable hashing for generic keys and values."],
84
+ "math" => ["Math & Simulation", "Mathematical constants and functions beyond the language builtins."],
85
+ "mem.arena" => ["Memory", "Region allocator: bump allocation with O(1) mark/reset."],
86
+ "mem.endian" => ["Memory", "Byte-swap and endian conversion helpers."],
87
+ "mem.heap" => ["Memory", "General-purpose heap allocator wrapper with alignment control."],
88
+ "mem.pool" => ["Memory", "Fixed-slot pool allocator for uniform-size objects."],
89
+ "mem.ptr" => ["Memory", "Safe pointer load/store wrappers around raw memory access."],
90
+ "mem.stack" => ["Memory", "Stack allocator with mark/release layered on the arena."],
91
+ "mem.tracking" => ["Memory", "Allocation tracker for leak detection and usage diagnostics."],
92
+ "multiset" => ["Collections", "Hash multiset that counts duplicate values."],
93
+ "net" => ["Network", "UDP and TCP sockets, address resolution, and packet I/O."],
94
+ "net.channel" => ["Network", "Multiplexed message channels over a single connection."],
95
+ "net.clock" => ["Network", "Synchronized network clock with ping and offset estimation."],
96
+ "net.discovery" => ["Network", "LAN service discovery via UDP broadcast."],
97
+ "net.lobby" => ["Network", "Lobby listing and joining built on discovery."],
98
+ "net.manager" => ["Network", "Connection and session manager for multiplayer topologies."],
99
+ "net.mux" => ["Network", "Stream multiplexer with reliable and unordered delivery flags."],
100
+ "net.nat" => ["Network", "NAT type detection and address binding via STUN."],
101
+ "net.packet" => ["Network", "Framed packet reading and writing over byte streams."],
102
+ "net.punch" => ["Network", "UDP hole punching for peer-to-peer connections."],
103
+ "net.rpc" => ["Network", "Request/response RPC framing over net channels."],
104
+ "net.session" => ["Network", "Client session state machine with heartbeats and timeouts."],
105
+ "net.stun" => ["Network", "STUN client for public address and port discovery."],
106
+ "net.sync" => ["Network", "State synchronization primitives for replicated values."],
107
+ "net.turn" => ["Network", "TURN relay client for NAT-restricted peers."],
108
+ "noise" => ["Math & Simulation", "Coherent Perlin noise and fractal variants."],
109
+ "oauth2" => ["Data & Serialization", "OAuth2 token requests and refresh flows."],
110
+ "option" => ["Core & Patterns", "Option[T] optional values, some(value) or none, with combinators."],
111
+ "ordered_map" => ["Collections", "Hash map that preserves insertion order."],
112
+ "ordered_set" => ["Collections", "Hash set that preserves insertion order."],
113
+ "parse" => ["Text & Formatting", "Numeric string parsing for integers and floats."],
114
+ "path" => ["Files & System", "Path join, split, and normalization utilities."],
115
+ "pcre2.runtime" => ["Text & Formatting", "Compiled regex matching runtime over the pcre2 bindings."],
116
+ "pool" => ["Collections", "Fixed-capacity reusable object storage."],
117
+ "priority_queue" => ["Collections", "Priority queue backed by a binary heap."],
118
+ "process" => ["Files & System", "Child process spawning with pipes and exit status."],
119
+ "queue" => ["Collections", "First-in first-out queue."],
120
+ "random" => ["Math & Simulation", "PCG pseudo-random number generation with seeding and ranges."],
121
+ "raylib.debug_console" => ["Game & Graphics", "In-game debug console overlay with command history."],
122
+ "raylib.easing" => ["Game & Graphics", "Easing curves for animation interpolation."],
123
+ "raylib.packed_assets" => ["Game & Graphics", "Load images, textures, and audio from assets.mtpack packs."],
124
+ "raylib.runtime" => ["Game & Graphics", "raylib app lifecycle helpers: window loop, asset directory, fatal errors."],
125
+ "raylib.tracy_gpu" => ["Game & Graphics", "Tracy profiler GPU zone calibration for raylib."],
126
+ "result" => ["Core & Patterns", "Result[T, E] success/failure type for recoverable errors."],
127
+ "ring_buffer" => ["Collections", "Fixed-capacity circular buffer with overwrite behavior."],
128
+ "sdl3.runtime" => ["Game & Graphics", "SDL3 app lifecycle helpers and main-loop wrappers."],
129
+ "serialize" => ["Data & Serialization", "Struct field serialization helpers layered on std.binary."],
130
+ "set" => ["Collections", "Hash set of unique values."],
131
+ "signal" => ["Concurrency & Time", "Fixed-capacity observer and publish-subscribe signals."],
132
+ "simd" => ["Math & Simulation", "SIMD load, store, and reduction helpers."],
133
+ "sparse_set" => ["Collections", "Sparse set with dense iteration for integer-keyed data."],
134
+ "spatial" => ["Math & Simulation", "Uniform spatial hash grid for broad-phase queries."],
135
+ "stack" => ["Collections", "Last-in first-out stack."],
136
+ "steering" => ["AI & Behavior", "Craig Reynolds steering behaviors for autonomous motion."],
137
+ "stdio" => ["Files & System", "Stdin, stdout, and stderr FILE wrappers and console I/O."],
138
+ "str" => ["Text & Formatting", "Borrowed string slice helpers: length, compare, search, split."],
139
+ "string" => ["Text & Formatting", "Heap-owned growable string type with builder operations."],
140
+ "sync" => ["Concurrency & Time", "Mutex, condition variable, and once primitives over libuv."],
141
+ "tar" => ["Data & Serialization", "TAR archive reading and writing with 512-byte blocks."],
142
+ "terminal" => ["Files & System", "Terminal size, color, and raw-mode helpers."],
143
+ "thread" => ["Concurrency & Time", "Threads via libuv with join and handle management."],
144
+ "time" => ["Concurrency & Time", "Wall-clock timestamps and monotonic time helpers."],
145
+ "timer" => ["Concurrency & Time", "Countdown and repeating timers."],
146
+ "tls" => ["Security", "TLS client and server streams over libuv handles."],
147
+ "toml" => ["Data & Serialization", "TOML parser for configuration files."],
148
+ "tween" => ["Game & Graphics", "Tweening and easing for smooth value interpolation."],
149
+ "uri" => ["Data & Serialization", "URI parsing and construction, including file and web schemes."],
150
+ "url" => ["Data & Serialization", "URL parsing: scheme, host, path, query, and percent-encoding."],
151
+ "utility" => ["AI & Behavior", "Utility AI with score-based action selection."],
152
+ "vec" => ["Collections", "Growable contiguous array Vec[T], the default dynamic sequence."],
153
+ }.freeze
154
+
155
+ class << self
156
+ def std_root
157
+ File.join(MilkTea.root.to_s, "std")
158
+ end
159
+
160
+ def entries
161
+ discover
162
+ end
163
+
164
+ # Resolves a module name ("mem.arena", "mem/arena", "c.cjson", "fs") to a
165
+ # source path. Prefers the active platform variant, matching the
166
+ # compiler's import resolution rule. Returns nil when unresolvable.
167
+ def resolve(name)
168
+ clean = name.to_s.strip
169
+ return nil if clean.empty? || clean.include?("..")
170
+
171
+ relative = clean.tr(".", "/").delete_suffix(".mt")
172
+ root = std_root
173
+
174
+ variant = File.join(root, "#{relative}.#{MilkTea.host_platform}.mt")
175
+ return variant if File.file?(variant)
176
+
177
+ shared = File.join(root, "#{relative}.mt")
178
+ return shared if File.file?(shared)
179
+
180
+ nil
181
+ end
182
+
183
+ def discover
184
+ root = std_root
185
+ by_name = {}
186
+
187
+ module_files(root).each do |path|
188
+ add_module(by_name, logical_name(path), path)
189
+ end
190
+
191
+ namespace_directories(root).each do |directory|
192
+ namespace = File.basename(directory)
193
+ module_files(directory).each do |path|
194
+ add_module(by_name, "#{namespace}.#{logical_name(path)}", path)
195
+ end
196
+ end
197
+
198
+ by_name.values.sort_by(&:name)
199
+ end
200
+
201
+ def add_module(by_name, name, path)
202
+ return if generated?(path)
203
+
204
+ category, description = REGISTRY.fetch(name, [nil, nil])
205
+ description ||= doc_comment_summary(path)
206
+ entry = by_name[name]
207
+ unless entry
208
+ by_name[name] = Entry.new(name:, description:, category:, path:)
209
+ return
210
+ end
211
+
212
+ entry.path = path if prefer_path?(path, entry.path)
213
+ end
214
+
215
+ # A shared file beats any variant; among variants the host platform
216
+ # wins, then the first alphabetically.
217
+ def prefer_path?(candidate, current)
218
+ candidate_rank = path_rank(candidate)
219
+ current_rank = path_rank(current)
220
+ order = candidate_rank <=> current_rank
221
+ order.negative? || (order.zero? && candidate < current)
222
+ end
223
+
224
+ def path_rank(path)
225
+ host = MilkTea.host_platform.to_s
226
+ [platform_variant?(path) ? 1 : 0, platform_of(path) == host ? 0 : 1]
227
+ end
228
+
229
+ def module_files(directory)
230
+ Dir.glob(File.join(directory, "*.mt")).sort
231
+ end
232
+
233
+ def namespace_directories(root)
234
+ Dir.children(root).map { |child| File.join(root, child) }
235
+ .select { |path| File.directory?(path) }
236
+ .reject { |path| EXCLUDED_DIRECTORIES.include?(File.basename(path)) }
237
+ .sort
238
+ end
239
+
240
+ def logical_name(path)
241
+ stem = File.basename(path, ".mt")
242
+ platform = platform_of(path)
243
+ platform ? stem.delete_suffix(".#{platform}") : stem
244
+ end
245
+
246
+ def platform_variant?(path)
247
+ PLATFORM_SUFFIXES.include?(platform_of(path))
248
+ end
249
+
250
+ def platform_of(path)
251
+ stem = File.basename(path, ".mt")
252
+ suffix = stem[/\.([^.]+)\z/, 1]
253
+ suffix && PLATFORM_SUFFIXES.include?(suffix) ? suffix : nil
254
+ end
255
+
256
+ def generated?(path)
257
+ File.open(path, "r") { |file| file.readline.start_with?(GENERATED_HEADER_PREFIX) }
258
+ rescue EOFError, Errno::ENOENT
259
+ false
260
+ end
261
+
262
+ def doc_comment_summary(path)
263
+ File.foreach(path) do |line|
264
+ stripped = line.strip
265
+ next if stripped.empty?
266
+
267
+ return stripped.sub(/\A##\s?/, "").rstrip if stripped.start_with?("##")
268
+
269
+ break
270
+ end
271
+ nil
272
+ rescue Errno::ENOENT
273
+ nil
274
+ end
275
+ end
276
+ end
277
+ end
@@ -15,6 +15,7 @@ require_relative "tooling/error_formatter"
15
15
  require_relative "tooling/formatter"
16
16
  require_relative "tooling/linter"
17
17
  require_relative "tooling/docs_app"
18
+ require_relative "tooling/std_catalog"
18
19
  require_relative "tooling/project_scaffold"
19
20
  require_relative "tooling/toolchain_cli"
20
21
  require_relative "tooling/bindgen_cli"
@@ -79,23 +79,22 @@ function work_as_req(work: ptr[NativeWorkRequest]) -> ptr[NativeRequest]:
79
79
  return unsafe: ptr[NativeRequest]<-work
80
80
 
81
81
 
82
- function close_all_handles_cb(handle: ptr[NativeHandle], arg: ptr[void]) -> void:
82
+ function close_all_handles_cb(handle: ptr[NativeHandle], _arg: ptr[void]) -> void:
83
83
  if libuv.is_closing(handle) == 0:
84
84
  libuv.close(handle, close_all_handles_close_cb)
85
- unsafe: arg
86
85
 
87
86
 
88
- function close_all_handles_close_cb(handle: ptr[NativeHandle]) -> void:
89
- unsafe: ptr[void]<-handle
87
+ function close_all_handles_close_cb(_handle: ptr[NativeHandle]) -> void:
88
+ pass
90
89
 
91
90
 
92
- function noop_waiter(frame: ptr[void]) -> void:
93
- unsafe: frame
91
+ function noop_waiter(_frame: ptr[void]) -> void:
92
+ pass
94
93
 
95
94
 
96
95
  function require_current_runtime() -> Runtime:
97
96
  if not current_runtime_active:
98
- fatal(c"async runtime requires an active runtime; use async.wait or async.run, or call the explicit *_on helpers")
97
+ fatal(c"async runtime requires an active runtime; use async.wait or async.run, or call the *_on helpers")
99
98
  return current_runtime
100
99
 
101
100
 
@@ -337,20 +336,19 @@ public function sleep_on(runtime: Runtime, timeout: ptr_uint) -> Task[int]:
337
336
  let loop = live_loop(runtime)
338
337
 
339
338
  let state = heap.must_alloc_zeroed[SleepState](1)
340
- unsafe:
341
- state.ready = false
342
- state.status = 0
343
- state.waiter_frame = null
344
- state.waiter = noop_waiter
345
- state.waiter_registered = false
346
- state.timer = null
347
- state.closing = false
348
- state.closed = false
349
- state.released = false
339
+ state.ready = false
340
+ state.status = 0
341
+ state.waiter_frame = null
342
+ state.waiter = noop_waiter
343
+ state.waiter_registered = false
344
+ state.timer = null
345
+ state.closing = false
346
+ state.closed = false
347
+ state.released = false
350
348
 
351
349
  let timer_size = libuv.handle_size(libuv.uv_handle_type.UV_TIMER)
352
350
  let timer = unsafe: ptr[NativeTimerHandle]<-heap.must_alloc_zeroed_bytes(1, timer_size)
353
- unsafe: state.timer = timer
351
+ state.timer = timer
354
352
 
355
353
  let init_status = libuv.timer_init(loop, timer)
356
354
  if init_status != 0:
@@ -367,11 +365,10 @@ public function sleep_on(runtime: Runtime, timeout: ptr_uint) -> Task[int]:
367
365
 
368
366
  let start_status = libuv.timer_start(timer, sleep_timer_fire, timeout, 0)
369
367
  if start_status != 0:
370
- unsafe:
371
- state.status = start_status
372
- state.ready = true
373
- state.closing = true
374
- libuv.close(timer_as_handle(timer), sleep_timer_close)
368
+ state.status = start_status
369
+ state.ready = true
370
+ state.closing = true
371
+ libuv.close(timer_as_handle(timer), sleep_timer_close)
375
372
 
376
373
  return sleep_task(state)
377
374
 
data/std/async/mailbox.mt CHANGED
@@ -45,8 +45,8 @@ function handle_as_async(handle: ptr[NativeHandle]) -> ptr[NativeAsyncHandle]:
45
45
  return unsafe: ptr[NativeAsyncHandle]<-handle
46
46
 
47
47
 
48
- function mailbox_async_callback(handle: ptr[NativeAsyncHandle]) -> void:
49
- unsafe: handle
48
+ function mailbox_async_callback(_handle: ptr[NativeAsyncHandle]) -> void:
49
+ pass
50
50
 
51
51
 
52
52
  function mailbox_destroy_state[T](state_frame: ptr[void]) -> void:
data/std/base64.mt CHANGED
@@ -163,18 +163,15 @@ public function decode(text_value: str) -> Result[bytes.Bytes, Error]:
163
163
 
164
164
  let combined = (ulong<-raw0 << 18) | (ulong<-raw1 << 12) | (ulong<-raw2 << 6) | ulong<-raw3
165
165
 
166
- unsafe:
167
- read(output + out_index) = ubyte<-( (combined >> 16) & 0xFF)
166
+ read(output + out_index) = ubyte<-( (combined >> 16) & 0xFF)
168
167
  out_index += 1
169
168
 
170
169
  if out_index < output_len:
171
- unsafe:
172
- read(output + out_index) = ubyte<-( (combined >> 8) & 0xFF)
170
+ read(output + out_index) = ubyte<-( (combined >> 8) & 0xFF)
173
171
  out_index += 1
174
172
 
175
173
  if out_index < output_len:
176
- unsafe:
177
- read(output + out_index) = ubyte<-(combined & 0xFF)
174
+ read(output + out_index) = ubyte<-(combined & 0xFF)
178
175
  out_index += 1
179
176
 
180
177
  return Result[bytes.Bytes, Error].success(value = bytes.Bytes(data = output, len = output_len))
data/std/behavior_tree.mt CHANGED
@@ -233,11 +233,8 @@ function tick_node[Context](tree: ref[Tree[Context]], node_id: ptr_uint, context
233
233
  match child_status:
234
234
  Status.success:
235
235
  return Status.success
236
- Status.failure:
237
- return Status.running
238
- Status.running:
236
+ Status.failure | Status.running:
239
237
  return Status.running
240
-
241
238
  NodeKind.until_failure:
242
239
  let child_ptr = read(node).children.first() else:
243
240
  return Status.failure
@@ -251,8 +248,6 @@ function tick_node[Context](tree: ref[Tree[Context]], node_id: ptr_uint, context
251
248
  Status.running:
252
249
  return Status.running
253
250
 
254
- return Status.failure
255
-
256
251
 
257
252
  extending Node[Context]:
258
253
  static function create(kind: NodeKind) -> Node[Context]:
data/std/binary.mt CHANGED
@@ -95,10 +95,7 @@ extending Writer:
95
95
 
96
96
 
97
97
  public editable function write_bool(value: bool) -> void:
98
- if value:
99
- writer_append_byte(ref_of(this), 1)
100
- else:
101
- writer_append_byte(ref_of(this), 0)
98
+ if value: writer_append_byte(ref_of(this), 1) else: writer_append_byte(ref_of(this), 0)
102
99
 
103
100
 
104
101
  public editable function write_bytes(data: span[ubyte]) -> void:
@@ -268,7 +265,7 @@ extending Reader:
268
265
 
269
266
  public editable function read_span(count: ptr_uint) -> Result[span[ubyte], Error]:
270
267
  if count == 0:
271
- let empty = unsafe: span[ubyte](data = this.data.data, len = 0)
268
+ let empty = span[ubyte](data = this.data.data, len = 0)
272
269
  return Result[span[ubyte], Error].success(value = empty)
273
270
 
274
271
  reader_check_remaining(ref_of(this), count)?
data/std/color.mt CHANGED
@@ -51,7 +51,7 @@ function fmod(x: float, m: float) -> float:
51
51
  # x - floor(x / m) * m
52
52
  let div = x / m
53
53
  let fl = float<-(int<-div)
54
- if div < 0.0 and float<-(int<-div) != div:
54
+ if div < 0.0 and (int<-div) != div:
55
55
  return x - (fl - 1.0) * m
56
56
  return x - fl * m
57
57
 
@@ -143,9 +143,9 @@ extending Color:
143
143
 
144
144
 
145
145
  public function to_hsl() -> (float, float, float):
146
- let rf = float<-this.r / 255.0
147
- let gf = float<-this.g / 255.0
148
- let bf = float<-this.b / 255.0
146
+ let rf = this.r / 255.0
147
+ let gf = this.g / 255.0
148
+ let bf = this.b / 255.0
149
149
 
150
150
  let mx = fmax(fmax(rf, gf), bf)
151
151
  let mn = fmin(fmin(rf, gf), bf)
@@ -171,9 +171,9 @@ extending Color:
171
171
 
172
172
 
173
173
  public function to_hsv() -> (float, float, float):
174
- let rf = float<-this.r / 255.0
175
- let gf = float<-this.g / 255.0
176
- let bf = float<-this.b / 255.0
174
+ let rf = this.r / 255.0
175
+ let gf = this.g / 255.0
176
+ let bf = this.b / 255.0
177
177
 
178
178
  let mx = fmax(fmax(rf, gf), bf)
179
179
  let mn = fmin(fmin(rf, gf), bf)
@@ -198,10 +198,10 @@ extending Color:
198
198
 
199
199
 
200
200
  public function lerp(target: Color, t: float) -> Color:
201
- let r = float<-this.r + (float<-target.r - float<-this.r) * t
202
- let g = float<-this.g + (float<-target.g - float<-this.g) * t
203
- let b = float<-this.b + (float<-target.b - float<-this.b) * t
204
- let a = float<-this.a + (float<-target.a - float<-this.a) * t
201
+ let r = this.r + (float<-target.r - float<-this.r) * t
202
+ let g = this.g + (float<-target.g - float<-this.g) * t
203
+ let b = this.b + (float<-target.b - float<-this.b) * t
204
+ let a = this.a + (float<-target.a - float<-this.a) * t
205
205
  return Color(r = ubyte<-r, g = ubyte<-g, b = ubyte<-b, a = ubyte<-a)
206
206
 
207
207
 
@@ -211,12 +211,12 @@ extending Color:
211
211
  if this.a == 255:
212
212
  return this
213
213
 
214
- let sa = float<-this.a / 255.0
215
- let da = float<-background.a / 255.0
214
+ let sa = this.a / 255.0
215
+ let da = background.a / 255.0
216
216
 
217
- let r_out = float<-this.r * sa + float<-background.r * da * (1.0 - sa)
218
- let g_out = float<-this.g * sa + float<-background.g * da * (1.0 - sa)
219
- let b_out = float<-this.b * sa + float<-background.b * da * (1.0 - sa)
217
+ let r_out = this.r * sa + background.r * da * (1.0 - sa)
218
+ let g_out = this.g * sa + background.g * da * (1.0 - sa)
219
+ let b_out = this.b * sa + background.b * da * (1.0 - sa)
220
220
  let a_out = sa + da * (1.0 - sa)
221
221
 
222
222
  return Color(
@@ -228,9 +228,9 @@ extending Color:
228
228
 
229
229
 
230
230
  public function scale(factor: float) -> Color:
231
- let r = fmin(fmax(float<-this.r * factor, 0.0), 255.0)
232
- let g = fmin(fmax(float<-this.g * factor, 0.0), 255.0)
233
- let b = fmin(fmax(float<-this.b * factor, 0.0), 255.0)
231
+ let r = fmin(fmax(this.r * factor, 0.0), 255.0)
232
+ let g = fmin(fmax(this.g * factor, 0.0), 255.0)
233
+ let b = fmin(fmax(this.b * factor, 0.0), 255.0)
234
234
  return Color(r = ubyte<-r, g = ubyte<-g, b = ubyte<-b, a = this.a)
235
235
 
236
236
 
@@ -242,4 +242,4 @@ extending Color:
242
242
 
243
243
 
244
244
  public function with_alpha(a: ubyte) -> Color:
245
- return Color(r = this.r, g = this.g, b = this.b, a = a)
245
+ return this.with(a = a)
data/std/cookie.mt CHANGED
@@ -138,10 +138,7 @@ function ascii_lower(text_value: str) -> string.String:
138
138
  var index: ptr_uint = 0
139
139
  while index < text_value.len:
140
140
  let value = text_value.byte_at(index)
141
- if value >= 65 and value <= 90:
142
- result.push_byte(value + 32)
143
- else:
144
- result.push_byte(value)
141
+ if value >= 65 and value <= 90: result.push_byte(value + 32) else: result.push_byte(value)
145
142
  index += 1
146
143
 
147
144
  return result
data/std/deque.mt CHANGED
@@ -114,10 +114,7 @@ extending Deque[T]:
114
114
  new_capacity = 4
115
115
 
116
116
  while new_capacity < min_capacity:
117
- if new_capacity > heap.ptr_uint_max / 2:
118
- new_capacity = min_capacity
119
- else:
120
- new_capacity *= 2
117
+ if new_capacity > heap.ptr_uint_max / 2: new_capacity = min_capacity else: new_capacity *= 2
121
118
 
122
119
  let new_data = heap.must_alloc[T](new_capacity)
123
120
  let old_data = this.data
@@ -191,10 +188,7 @@ extending Deque[T]:
191
188
  let data = this.data else:
192
189
  fatal(c"deque.push_front missing storage")
193
190
 
194
- if this.len == 0:
195
- this.head = 0
196
- else:
197
- this.head = Deque[T].previous_index(this.head, this.capacity)
191
+ if this.len == 0: this.head = 0 else: this.head = Deque[T].previous_index(this.head, this.capacity)
198
192
 
199
193
  unsafe:
200
194
  let data_ptr = ptr[T]<-data
data/std/encoding.mt CHANGED
@@ -26,10 +26,7 @@ public function utf8_codepoint_count(text: str) -> ptr_uint:
26
26
  while index < text.len:
27
27
  let b = text.byte_at(index)
28
28
  let len = utf8_codepoint_length(b)
29
- if len == 0:
30
- index += 1
31
- else:
32
- index += len
29
+ if len == 0: index += 1 else: index += len
33
30
  count += 1
34
31
 
35
32
  if index != text.len:
data/std/fmt.mt CHANGED
@@ -32,10 +32,7 @@ public function append_cstr(output: ref[string.String], c_text: cstr) -> void:
32
32
 
33
33
 
34
34
  public function append_bool(output: ref[string.String], bool_value: bool) -> void:
35
- if bool_value:
36
- output.append("true")
37
- else:
38
- output.append("false")
35
+ if bool_value: output.append("true") else: output.append("false")
39
36
 
40
37
 
41
38
  function append_formatted_float(output: ref[string.String], format: cstr, number: double) -> void:
data/std/graph.mt CHANGED
@@ -612,7 +612,11 @@ extending DenseGraph[T]:
612
612
  return ShortestPaths(dist = dist, prev = prev)
613
613
 
614
614
 
615
- public function astar(source: ptr_uint, target: ptr_uint, heuristic: fn(node: ptr_uint) -> float) -> vec.Vec[ptr_uint]:
615
+ public function astar(
616
+ source: ptr_uint,
617
+ target: ptr_uint,
618
+ heuristic: fn(node: ptr_uint) -> float
619
+ ) -> vec.Vec[ptr_uint]:
616
620
  var path = vec.Vec[ptr_uint].create()
617
621
  let n = this.node_count()
618
622
  if n == 0 or source >= n or target >= n:
data/std/htn.mt CHANGED
@@ -110,7 +110,15 @@ function plan_task[World, Context](
110
110
 
111
111
  for subtask_name_ptr in method.subtasks:
112
112
  let subtask_name = unsafe: read(subtask_name_ptr)
113
- let sub_plan = plan_task(planner, context, current_world, subtask_name, depth + 1, iterations, reason)
113
+ let sub_plan = plan_task(
114
+ planner,
115
+ context,
116
+ current_world,
117
+ subtask_name,
118
+ depth + 1,
119
+ iterations,
120
+ reason
121
+ )
114
122
  match sub_plan:
115
123
  Option.none:
116
124
  success = false
data/std/http/server.mt CHANGED
@@ -69,10 +69,7 @@ public function request_query_param(request: Request, key: str) -> Option[str]:
69
69
 
70
70
  return Option[str].some(value = decoded.as_str())
71
71
 
72
- if amp >= query_str.len:
73
- start = query_str.len
74
- else:
75
- start = amp + 1
72
+ if amp >= query_str.len: start = query_str.len else: start = amp + 1
76
73
 
77
74
  return Option[str].none
78
75