@shd101wyy/yo 0.1.33 → 0.1.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/skills/yo-core-patterns/SKILL.md +1 -1
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +51 -21
- package/.github/skills/yo-syntax/SKILL.md +1 -1
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +56 -67
- package/out/cjs/index.cjs +670 -655
- package/out/cjs/yo-cli.cjs +744 -729
- package/out/cjs/yo-lsp.cjs +687 -672
- package/out/esm/index.mjs +492 -477
- package/out/types/src/codegen/exprs/comptime-value.d.ts +2 -1
- package/out/types/src/codegen/types/generation.d.ts +1 -1
- package/out/types/src/codegen/utils/index.d.ts +2 -4
- package/out/types/src/evaluator/exprs/_expr.d.ts +1 -0
- package/out/types/src/evaluator/types/flowability.d.ts +21 -0
- package/out/types/src/expr.d.ts +5 -13
- package/out/types/src/types/creators.d.ts +2 -3
- package/out/types/src/types/definitions.d.ts +2 -3
- package/out/types/src/types/guards.d.ts +2 -2
- package/out/types/src/types/tags.d.ts +2 -2
- package/out/types/src/value-tag.d.ts +0 -1
- package/out/types/src/value.d.ts +2 -11
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/alg/hash.yo +5 -3
- package/std/build.yo +46 -46
- package/std/collections/array_list.yo +73 -66
- package/std/collections/hash_map.yo +2 -81
- package/std/collections/list_view.yo +77 -0
- package/std/crypto/random.yo +5 -5
- package/std/encoding/base64.yo +12 -13
- package/std/encoding/hex.yo +6 -6
- package/std/encoding/json.yo +6 -5
- package/std/encoding/utf16.yo +9 -9
- package/std/env.yo +8 -8
- package/std/fmt/to_string.yo +12 -12
- package/std/http/client.yo +1 -1
- package/std/imm/list.yo +4 -3
- package/std/imm/map.yo +3 -2
- package/std/imm/set.yo +4 -3
- package/std/imm/sorted_map.yo +3 -2
- package/std/imm/sorted_set.yo +4 -3
- package/std/imm/string.yo +12 -5
- package/std/imm/vec.yo +8 -3
- package/std/prelude.yo +175 -401
- package/std/string/string.yo +198 -71
- package/std/url/index.yo +26 -26
- package/out/types/src/evaluator/types/slice.d.ts +0 -8
package/package.json
CHANGED
package/std/alg/hash.yo
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
//! FNV-1a (Fowler-Noll-Vo) hash function.
|
|
2
2
|
//!
|
|
3
3
|
//! A fast, non-cryptographic hash function with good distribution.
|
|
4
|
+
pragma(Pragma.AllowUnsafe);
|
|
4
5
|
//! Used internally by `HashMap` and `HashSet`.
|
|
5
6
|
/// FNV offset basis constant (0xcbf29ce484222325).
|
|
6
7
|
FNV_OFFSET_BASIS :: u64(14695981039346656037);
|
|
7
8
|
/// FNV prime constant (0x100000001b3).
|
|
8
9
|
FNV_PRIME :: u64(1099511628211);
|
|
9
10
|
/// Hash a byte sequence using FNV-1a.
|
|
10
|
-
fnv1a_hash_bytes :: (fn(bytes :
|
|
11
|
+
fnv1a_hash_bytes :: (fn(bytes : RawSlice(u8)) -> u64)({
|
|
11
12
|
hash := FNV_OFFSET_BASIS;
|
|
12
|
-
length := bytes.len
|
|
13
|
+
length := bytes.len;
|
|
13
14
|
i := usize(0);
|
|
14
15
|
while(i < length, i = (i + usize(1)), {
|
|
15
|
-
|
|
16
|
+
// SAFETY: i < len; the RawSlice contract requires ptr to cover len bytes.
|
|
17
|
+
byte := unsafe((bytes.ptr &+ i).*);
|
|
16
18
|
xor := (hash ^ u64(byte));
|
|
17
19
|
hash = (xor * FNV_PRIME);
|
|
18
20
|
});
|
package/std/build.yo
CHANGED
|
@@ -76,11 +76,11 @@ export(target_host);
|
|
|
76
76
|
/// Configuration for building an executable.
|
|
77
77
|
Executable :: struct(
|
|
78
78
|
/// Artifact name.
|
|
79
|
-
name :
|
|
79
|
+
name : comptime_str,
|
|
80
80
|
/// Root source file.
|
|
81
|
-
root :
|
|
81
|
+
root : comptime_str,
|
|
82
82
|
/// Compilation target triple (defaults to host).
|
|
83
|
-
(target :
|
|
83
|
+
(target : comptime_str) ?= __yo_build_target_host(),
|
|
84
84
|
/// Optimization level.
|
|
85
85
|
(optimize : Optimize) ?= Optimize.Debug,
|
|
86
86
|
/// Memory allocator.
|
|
@@ -92,11 +92,11 @@ export(Executable);
|
|
|
92
92
|
/// Configuration for building a static library.
|
|
93
93
|
StaticLibrary :: struct(
|
|
94
94
|
/// Artifact name.
|
|
95
|
-
name :
|
|
95
|
+
name : comptime_str,
|
|
96
96
|
/// Root source file.
|
|
97
|
-
root :
|
|
97
|
+
root : comptime_str,
|
|
98
98
|
/// Compilation target triple (defaults to host).
|
|
99
|
-
(target :
|
|
99
|
+
(target : comptime_str) ?= __yo_build_target_host(),
|
|
100
100
|
/// Optimization level.
|
|
101
101
|
(optimize : Optimize) ?= Optimize.Debug
|
|
102
102
|
);
|
|
@@ -104,11 +104,11 @@ export(StaticLibrary);
|
|
|
104
104
|
/// Configuration for building a shared/dynamic library.
|
|
105
105
|
SharedLibrary :: struct(
|
|
106
106
|
/// Artifact name.
|
|
107
|
-
name :
|
|
107
|
+
name : comptime_str,
|
|
108
108
|
/// Root source file.
|
|
109
|
-
root :
|
|
109
|
+
root : comptime_str,
|
|
110
110
|
/// Compilation target triple (defaults to host).
|
|
111
|
-
(target :
|
|
111
|
+
(target : comptime_str) ?= __yo_build_target_host(),
|
|
112
112
|
/// Optimization level.
|
|
113
113
|
(optimize : Optimize) ?= Optimize.Debug
|
|
114
114
|
);
|
|
@@ -116,11 +116,11 @@ export(SharedLibrary);
|
|
|
116
116
|
/// Configuration for a test suite.
|
|
117
117
|
TestSuite :: struct(
|
|
118
118
|
/// Suite name.
|
|
119
|
-
name :
|
|
119
|
+
name : comptime_str,
|
|
120
120
|
/// Root test file.
|
|
121
|
-
root :
|
|
121
|
+
root : comptime_str,
|
|
122
122
|
/// Compilation target triple (defaults to host).
|
|
123
|
-
(target :
|
|
123
|
+
(target : comptime_str) ?= __yo_build_target_host()
|
|
124
124
|
);
|
|
125
125
|
export(TestSuite);
|
|
126
126
|
// ── Build module type ────────────────────────────────────────────────
|
|
@@ -128,17 +128,17 @@ export(TestSuite);
|
|
|
128
128
|
/// Modules are the unit of reuse across Yo dependencies.
|
|
129
129
|
BuildModule :: struct(
|
|
130
130
|
/// Module name.
|
|
131
|
-
name :
|
|
131
|
+
name : comptime_str,
|
|
132
132
|
/// Root source file.
|
|
133
|
-
root :
|
|
134
|
-
_dep :
|
|
133
|
+
root : comptime_str,
|
|
134
|
+
_dep : comptime_str
|
|
135
135
|
);
|
|
136
136
|
export(BuildModule);
|
|
137
137
|
// ── Import entry type ────────────────────────────────────────────────
|
|
138
138
|
/// Pairs an import name with a module for use with `add_import`/`add_import_list`.
|
|
139
139
|
ImportEntry :: struct(
|
|
140
140
|
/// Import alias used in source code.
|
|
141
|
-
name :
|
|
141
|
+
name : comptime_str,
|
|
142
142
|
/// The module to import.
|
|
143
143
|
module : BuildModule
|
|
144
144
|
);
|
|
@@ -148,7 +148,7 @@ export(ImportEntry);
|
|
|
148
148
|
/// Use `step.depend_on(dep)` to wire dependencies between steps.
|
|
149
149
|
Step :: struct(
|
|
150
150
|
/// Step name.
|
|
151
|
-
name :
|
|
151
|
+
name : comptime_str,
|
|
152
152
|
/// Kind of step.
|
|
153
153
|
kind : StepKind
|
|
154
154
|
);
|
|
@@ -179,7 +179,7 @@ impl(
|
|
|
179
179
|
)
|
|
180
180
|
),
|
|
181
181
|
/// Add extra C compiler flags to this step.
|
|
182
|
-
add_c_flags : (fn(comptime(self) : Self, comptime(flags) :
|
|
182
|
+
add_c_flags : (fn(comptime(self) : Self, comptime(flags) : comptime_str) -> comptime(unit))({
|
|
183
183
|
__yo_build_add_cflags(self.name, flags);
|
|
184
184
|
})
|
|
185
185
|
);
|
|
@@ -197,46 +197,46 @@ impl(
|
|
|
197
197
|
/// User-configurable build option (declared in `build.yo`, set via `yo build -Dname=value`).
|
|
198
198
|
BuildOption :: struct(
|
|
199
199
|
/// Option name (used with `-D`).
|
|
200
|
-
name :
|
|
200
|
+
name : comptime_str,
|
|
201
201
|
/// Human-readable description.
|
|
202
|
-
description :
|
|
202
|
+
description : comptime_str,
|
|
203
203
|
/// Default value if not provided.
|
|
204
|
-
(default :
|
|
204
|
+
(default : comptime_str) ?= ""
|
|
205
205
|
);
|
|
206
206
|
export(BuildOption);
|
|
207
207
|
// ── Dependency config types ──────────────────────────────────────────
|
|
208
208
|
/// Git-hosted dependency configuration.
|
|
209
209
|
GitDependency :: struct(
|
|
210
210
|
/// Dependency name.
|
|
211
|
-
name :
|
|
211
|
+
name : comptime_str,
|
|
212
212
|
/// Git repository URL.
|
|
213
|
-
url :
|
|
213
|
+
url : comptime_str,
|
|
214
214
|
/// Git ref (tag, branch, or commit SHA). Defaults to `"HEAD"`.
|
|
215
|
-
(ref :
|
|
215
|
+
(ref : comptime_str) ?= "HEAD",
|
|
216
216
|
/// Subdirectory within the repository.
|
|
217
|
-
(path :
|
|
217
|
+
(path : comptime_str) ?= ""
|
|
218
218
|
);
|
|
219
219
|
export(GitDependency);
|
|
220
220
|
/// Local path dependency configuration.
|
|
221
221
|
PathDependency :: struct(
|
|
222
222
|
/// Dependency name.
|
|
223
|
-
name :
|
|
223
|
+
name : comptime_str,
|
|
224
224
|
/// Filesystem path to the dependency root.
|
|
225
|
-
path :
|
|
225
|
+
path : comptime_str
|
|
226
226
|
);
|
|
227
227
|
export(PathDependency);
|
|
228
228
|
/// System C library discovered via `pkg-config`.
|
|
229
229
|
SystemLibrary :: struct(
|
|
230
230
|
/// Library name (passed to `pkg-config`).
|
|
231
|
-
name :
|
|
231
|
+
name : comptime_str,
|
|
232
232
|
/// Fallback include path if pkg-config fails.
|
|
233
|
-
(fallback_include :
|
|
233
|
+
(fallback_include : comptime_str) ?= "",
|
|
234
234
|
/// Fallback library path.
|
|
235
|
-
(fallback_lib :
|
|
235
|
+
(fallback_lib : comptime_str) ?= "",
|
|
236
236
|
/// Fallback link flags.
|
|
237
|
-
(fallback_link :
|
|
237
|
+
(fallback_link : comptime_str) ?= "",
|
|
238
238
|
/// Extra C preprocessor defines.
|
|
239
|
-
(defines :
|
|
239
|
+
(defines : comptime_str) ?= ""
|
|
240
240
|
);
|
|
241
241
|
export(SystemLibrary);
|
|
242
242
|
// ── Dependency handle ────────────────────────────────────────────────
|
|
@@ -244,20 +244,20 @@ export(SystemLibrary);
|
|
|
244
244
|
// Provides access to artifacts defined in the dependency's build.yo.
|
|
245
245
|
/// Handle to a registered dependency. Use `.artifact()` or `.module()` to access its exports.
|
|
246
246
|
Dependency :: struct(
|
|
247
|
-
name :
|
|
247
|
+
name : comptime_str
|
|
248
248
|
);
|
|
249
249
|
export(Dependency);
|
|
250
250
|
impl(
|
|
251
251
|
Dependency,
|
|
252
252
|
/// Access a named artifact from the dependency's `build.yo`.
|
|
253
253
|
/// Returns a `Step` that can be linked to the consumer's artifacts.
|
|
254
|
-
artifact : (fn(comptime(self) : Self, comptime(artifact_name) :
|
|
254
|
+
artifact : (fn(comptime(self) : Self, comptime(artifact_name) : comptime_str) -> comptime(Step))({
|
|
255
255
|
__yo_build_dep_artifact(self.name, artifact_name);
|
|
256
256
|
Step(name : artifact_name, kind : StepKind.StaticLibrary)
|
|
257
257
|
}),
|
|
258
258
|
/// Get a module from the dependency's `build.yo`.
|
|
259
259
|
/// Empty `module_name` defaults to the sole module if exactly one exists.
|
|
260
|
-
module : (fn(comptime(self) : Self, (comptime(module_name) :
|
|
260
|
+
module : (fn(comptime(self) : Self, (comptime(module_name) : comptime_str) ?= "") -> comptime(BuildModule))({
|
|
261
261
|
_encoded :: __yo_build_dep_module(self.name, module_name);
|
|
262
262
|
BuildModule(name : module_name, root : "", _dep : self.name)
|
|
263
263
|
})
|
|
@@ -331,8 +331,8 @@ export(run);
|
|
|
331
331
|
/// Register a named build step. Use `step.depend_on(dep)` to add dependencies.
|
|
332
332
|
step :: (
|
|
333
333
|
fn(
|
|
334
|
-
comptime(name) :
|
|
335
|
-
comptime(description) :
|
|
334
|
+
comptime(name) : comptime_str,
|
|
335
|
+
comptime(description) : comptime_str
|
|
336
336
|
) -> comptime(Step)
|
|
337
337
|
)({
|
|
338
338
|
__yo_build_step(name, description);
|
|
@@ -360,9 +360,9 @@ export(system_library);
|
|
|
360
360
|
/// Module configuration for shared compilation units.
|
|
361
361
|
ModuleConfig :: struct(
|
|
362
362
|
/// Module name.
|
|
363
|
-
name :
|
|
363
|
+
name : comptime_str,
|
|
364
364
|
/// Root source file for the module.
|
|
365
|
-
root :
|
|
365
|
+
root : comptime_str
|
|
366
366
|
);
|
|
367
367
|
export(ModuleConfig);
|
|
368
368
|
/// Register a named module. Returns a `BuildModule` for linking system libraries
|
|
@@ -398,11 +398,11 @@ export(DocFormat);
|
|
|
398
398
|
/// Configuration for documentation generation.
|
|
399
399
|
DocConfig :: struct(
|
|
400
400
|
/// Step name (e.g., "doc").
|
|
401
|
-
name :
|
|
401
|
+
name : comptime_str,
|
|
402
402
|
/// Root source file or directory to document.
|
|
403
|
-
root :
|
|
403
|
+
root : comptime_str,
|
|
404
404
|
/// Output directory (default: "yo-out/doc").
|
|
405
|
-
(output :
|
|
405
|
+
(output : comptime_str) ?= "yo-out/doc",
|
|
406
406
|
/// Output format (default: Html).
|
|
407
407
|
(format : DocFormat) ?= DocFormat.Html,
|
|
408
408
|
/// Document non-exported (private) items.
|
|
@@ -410,14 +410,14 @@ DocConfig :: struct(
|
|
|
410
410
|
/// Document dependencies too.
|
|
411
411
|
(include_deps : bool) ?= false,
|
|
412
412
|
/// Custom site title (default: project name).
|
|
413
|
-
(title :
|
|
413
|
+
(title : comptime_str) ?= "",
|
|
414
414
|
/// Release version to display (e.g., "v1.0.0").
|
|
415
415
|
/// When empty, auto-detects from git tag or commit hash.
|
|
416
|
-
(version :
|
|
416
|
+
(version : comptime_str) ?= "",
|
|
417
417
|
/// Path to logo image.
|
|
418
|
-
(logo :
|
|
418
|
+
(logo : comptime_str) ?= "",
|
|
419
419
|
/// Path to favicon.
|
|
420
|
-
(favicon :
|
|
420
|
+
(favicon : comptime_str) ?= ""
|
|
421
421
|
);
|
|
422
422
|
export(DocConfig);
|
|
423
423
|
/// Register a documentation generation step. Returns a Step for dependency wiring.
|
|
@@ -37,19 +37,6 @@ impl(
|
|
|
37
37
|
ptr : (fn(self : Self) -> ?*(T))(
|
|
38
38
|
self._ptr
|
|
39
39
|
),
|
|
40
|
-
/**
|
|
41
|
-
* Get a slice view of the ArrayList
|
|
42
|
-
* Returns a fat pointer Slice(T) with data pointer and length
|
|
43
|
-
* This allows passing ArrayList to functions expecting slices
|
|
44
|
-
* Returns .None for an empty ArrayList with no allocated buffer
|
|
45
|
-
*/
|
|
46
|
-
as_slice : (fn(self : Self) -> Option(Slice(T)))(
|
|
47
|
-
match(
|
|
48
|
-
self._ptr,
|
|
49
|
-
.Some(p) =>.Some(Slice(T).from_raw_parts(p, self._length)),
|
|
50
|
-
.None =>.None
|
|
51
|
-
)
|
|
52
|
-
),
|
|
53
40
|
/** * Directly set the length of the ArrayList
|
|
54
41
|
* UNSAFE: This does not initialize new elements or free removed elements
|
|
55
42
|
* Only use when you've manually populated the buffer (e.g., via direct memory writes)
|
|
@@ -73,6 +60,55 @@ impl(
|
|
|
73
60
|
)
|
|
74
61
|
),
|
|
75
62
|
/**
|
|
63
|
+
* Create an ArrayList by copying the elements of a fixed-size array.
|
|
64
|
+
* The owned-copy companion to array range-indexing
|
|
65
|
+
* (plans/SLICE_REWORK.md).
|
|
66
|
+
*/
|
|
67
|
+
/**
|
|
68
|
+
* Owned copy of the elements in `[r.start, r.end)` — JS-style range
|
|
69
|
+
* slicing with value semantics (plans/SLICE_REWORK.md: `list(a..b)`
|
|
70
|
+
* lowers to this).
|
|
71
|
+
*/
|
|
72
|
+
slice_copy : (fn(self : Self, r : Range(usize)) -> Self)({
|
|
73
|
+
e := cond((r.end > self.len()) => self.len(), true => r.end);
|
|
74
|
+
out := Self.new();
|
|
75
|
+
i := r.start;
|
|
76
|
+
while(i < e, i = (i + usize(1)), {
|
|
77
|
+
match(
|
|
78
|
+
self.get(i),
|
|
79
|
+
.Some(v) => {
|
|
80
|
+
___ := out.push(v);
|
|
81
|
+
},
|
|
82
|
+
.None => ()
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
out
|
|
86
|
+
}),
|
|
87
|
+
/// Inclusive-range companion of `slice_copy` (`list(a..=b)`).
|
|
88
|
+
slice_copy_inclusive : (fn(self : Self, r : RangeInclusive(usize)) -> Self)({
|
|
89
|
+
last := cond((r.end >= self.len()) => self.len(), true => (r.end + usize(1)));
|
|
90
|
+
out := Self.new();
|
|
91
|
+
i := r.start;
|
|
92
|
+
while(i < last, i = (i + usize(1)), {
|
|
93
|
+
match(
|
|
94
|
+
self.get(i),
|
|
95
|
+
.Some(v) => {
|
|
96
|
+
___ := out.push(v);
|
|
97
|
+
},
|
|
98
|
+
.None => ()
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
out
|
|
102
|
+
}),
|
|
103
|
+
from_array : (fn(forall(N : usize), arr : Array(T, N)) -> Self)({
|
|
104
|
+
out := Self.with_capacity(N);
|
|
105
|
+
i := usize(0);
|
|
106
|
+
while(i < N, i = (i + usize(1)), {
|
|
107
|
+
out.push(arr(i));
|
|
108
|
+
});
|
|
109
|
+
out
|
|
110
|
+
}),
|
|
111
|
+
/**
|
|
76
112
|
* Create an ArrayList with a specific initial cap
|
|
77
113
|
*/
|
|
78
114
|
with_capacity : (fn(cap : usize) -> Self)(
|
|
@@ -507,28 +543,6 @@ impl(
|
|
|
507
543
|
})
|
|
508
544
|
)
|
|
509
545
|
);
|
|
510
|
-
/// Indexable impl — projection-style indexing yielding `ref(T)`.
|
|
511
|
-
/// See plans/ITERATOR_REDESIGN.md. Body wraps the pointer arithmetic
|
|
512
|
-
/// in `unsafe(...)` to pass the flowability check.
|
|
513
|
-
impl(
|
|
514
|
-
forall(T : Type),
|
|
515
|
-
ArrayList(T),
|
|
516
|
-
Indexable(usize)(
|
|
517
|
-
Element : T,
|
|
518
|
-
project : (fn(ref(self) : Self, pos : usize) -> ref(T))({
|
|
519
|
-
assert(pos < self._length, "ArrayList: project out of bounds");
|
|
520
|
-
match(
|
|
521
|
-
self._ptr,
|
|
522
|
-
// SAFETY: assert above bounds `pos < self._length` and the
|
|
523
|
-
// length invariant guarantees `pos < self._capacity`, so
|
|
524
|
-
// `_ptr &+ pos` stays inside the Rc-managed heap buffer
|
|
525
|
-
// for the duration of the borrow.
|
|
526
|
-
.Some(_ptr) => unsafe(_ptr &+ pos),
|
|
527
|
-
.None => panic("ArrayList: project on empty list")
|
|
528
|
-
)
|
|
529
|
-
})
|
|
530
|
-
)
|
|
531
|
-
);
|
|
532
546
|
impl(
|
|
533
547
|
forall(T : Type),
|
|
534
548
|
ArrayList(T),
|
|
@@ -586,37 +600,6 @@ impl(
|
|
|
586
600
|
ArrayListIter(T)(_list : self, _index : usize(0))
|
|
587
601
|
)
|
|
588
602
|
);
|
|
589
|
-
/// Position iterator for ArrayList — yields `usize` indices into the
|
|
590
|
-
/// list. Used by `ArrayList.iter()`; the for-macro pairs each yielded
|
|
591
|
-
/// position with `ArrayList.project(pos)` (Indexable from Phase C) to
|
|
592
|
-
/// bind the body's `ref`-name. See plans/ITERATOR_REDESIGN.md.
|
|
593
|
-
_ArrayListPosIter :: struct(
|
|
594
|
-
_index : usize,
|
|
595
|
-
_len : usize
|
|
596
|
-
);
|
|
597
|
-
impl(
|
|
598
|
-
_ArrayListPosIter,
|
|
599
|
-
Iterator(
|
|
600
|
-
Item : usize,
|
|
601
|
-
next : (fn(ref(self) : Self) -> Option(usize))(
|
|
602
|
-
cond(
|
|
603
|
-
(self._index >= self._len) =>.None,
|
|
604
|
-
true => {
|
|
605
|
-
out := self._index;
|
|
606
|
-
self._index = (self._index + usize(1));
|
|
607
|
-
.Some(out)
|
|
608
|
-
}
|
|
609
|
-
)
|
|
610
|
-
)
|
|
611
|
-
)
|
|
612
|
-
);
|
|
613
|
-
impl(
|
|
614
|
-
forall(T : Type),
|
|
615
|
-
ArrayList(T),
|
|
616
|
-
iter : (fn(ref(self) : Self) -> _ArrayListPosIter)(
|
|
617
|
-
_ArrayListPosIter(_index : usize(0), _len : self._length)
|
|
618
|
-
)
|
|
619
|
-
);
|
|
620
603
|
impl(
|
|
621
604
|
forall(T : Type),
|
|
622
605
|
where(T <: Eq(T)),
|
|
@@ -859,4 +842,28 @@ array_list :: (fn(...(quote(elems))) -> unquote(Expr))({
|
|
|
859
842
|
unquote(tmp)
|
|
860
843
|
})
|
|
861
844
|
});
|
|
845
|
+
/// Range slicing on fixed-size arrays returns an OWNED ArrayList copy
|
|
846
|
+
/// (`arr(a..b)` lowers to this — plans/SLICE_REWORK.md).
|
|
847
|
+
impl(
|
|
848
|
+
forall(T : Type, N : usize),
|
|
849
|
+
Array(T, N),
|
|
850
|
+
slice_copy : (fn(self : Array(T, N), r : Range(usize)) -> ArrayList(T))({
|
|
851
|
+
e := cond((r.end > N) => N, true => r.end);
|
|
852
|
+
out := ArrayList(T).new();
|
|
853
|
+
i := r.start;
|
|
854
|
+
while(i < e, i = (i + usize(1)), {
|
|
855
|
+
out.push(self(i));
|
|
856
|
+
});
|
|
857
|
+
out
|
|
858
|
+
}),
|
|
859
|
+
slice_copy_inclusive : (fn(self : Array(T, N), r : RangeInclusive(usize)) -> ArrayList(T))({
|
|
860
|
+
last := cond((r.end >= N) => N, true => (r.end + usize(1)));
|
|
861
|
+
out := ArrayList(T).new();
|
|
862
|
+
i := r.start;
|
|
863
|
+
while(i < last, i = (i + usize(1)), {
|
|
864
|
+
out.push(self(i));
|
|
865
|
+
});
|
|
866
|
+
out
|
|
867
|
+
})
|
|
868
|
+
);
|
|
862
869
|
export(array_list);
|
|
@@ -565,9 +565,8 @@ impl(
|
|
|
565
565
|
where(K <: (Eq(K), Hash)),
|
|
566
566
|
HashMap(K, V),
|
|
567
567
|
/// Pointer iterator — yields `*(Bucket(K, V))` for each occupied bucket.
|
|
568
|
-
///
|
|
569
|
-
/// `
|
|
570
|
-
/// later in the file, enabling `for(map, ref(b) => body)`.
|
|
568
|
+
/// For privileged/unsafe internal use; value iteration goes through
|
|
569
|
+
/// `into_iter()`.
|
|
571
570
|
iter_ptr : (fn(self : Self) -> HashMapIterPtr(K, V))(
|
|
572
571
|
HashMapIterPtr(K, V)(_map : self, _index : usize(0))
|
|
573
572
|
)
|
|
@@ -690,84 +689,6 @@ impl(
|
|
|
690
689
|
})
|
|
691
690
|
)
|
|
692
691
|
);
|
|
693
|
-
/// Position iterator for HashMap that walks occupied buckets and yields
|
|
694
|
-
/// their bucket indices. Pairs with the `Indexable(usize)` impl below to
|
|
695
|
-
/// make `for(map, ref(b) => body)` legal: `b` becomes a `ref(Bucket(K, V))`
|
|
696
|
-
/// and the loop body can destructure `b.key` / `b.value`.
|
|
697
|
-
HashMapPosIter :: (fn(comptime(K) : Type, comptime(V) : Type) -> comptime(Type))(
|
|
698
|
-
struct(
|
|
699
|
-
_map : HashMap(K, V),
|
|
700
|
-
_index : usize
|
|
701
|
-
)
|
|
702
|
-
);
|
|
703
|
-
impl(
|
|
704
|
-
forall(K : Type, V : Type),
|
|
705
|
-
where(K <: (Eq(K), Hash)),
|
|
706
|
-
HashMapPosIter(K, V),
|
|
707
|
-
Iterator(
|
|
708
|
-
Item : usize,
|
|
709
|
-
next : (fn(ref(self) : Self) -> Option(usize))(
|
|
710
|
-
cond(
|
|
711
|
-
(self._map.capacity == usize(0)) =>.None,
|
|
712
|
-
true => {
|
|
713
|
-
ctrl_ptr := self._map.ctrl.unwrap();
|
|
714
|
-
result := Option(usize).None;
|
|
715
|
-
while((self._index < self._map.capacity) && result.is_none(), self._index = (self._index + usize(1)), {
|
|
716
|
-
ctrl_byte := (ctrl_ptr &+ self._index).*;
|
|
717
|
-
cond(
|
|
718
|
-
((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
|
|
719
|
-
result =.Some(self._index);
|
|
720
|
-
},
|
|
721
|
-
true => ()
|
|
722
|
-
);
|
|
723
|
-
});
|
|
724
|
-
result
|
|
725
|
-
}
|
|
726
|
-
)
|
|
727
|
-
)
|
|
728
|
-
)
|
|
729
|
-
);
|
|
730
|
-
/// Indexable(usize) — projects an occupied bucket index back to a
|
|
731
|
-
/// `ref(Bucket(K, V))` so `for(map, ref(b) => ...)` works. The body of
|
|
732
|
-
/// `for` (Phase D) calls `coll.iter()` to obtain a position iter and
|
|
733
|
-
/// then `coll.project(pos)` for each yielded position. We override
|
|
734
|
-
/// `iter` for HashMap to return the position-iter rather than the
|
|
735
|
-
/// `*(Bucket)` iter — the for-macro only cares about which yields
|
|
736
|
-
/// positions consumable by `project`.
|
|
737
|
-
///
|
|
738
|
-
/// See plans/ITERATOR_REDESIGN.md Open Question 3. The choice here is
|
|
739
|
-
/// "projection-returns a single Bucket struct, user destructures
|
|
740
|
-
/// inside the loop" — chosen over the rejected `(ref(K), ref(V))`
|
|
741
|
-
/// tuple-of-inouts shape.
|
|
742
|
-
impl(
|
|
743
|
-
forall(K : Type, V : Type),
|
|
744
|
-
where(K <: (Eq(K), Hash)),
|
|
745
|
-
HashMap(K, V),
|
|
746
|
-
Indexable(usize)(
|
|
747
|
-
Element : Bucket(K, V),
|
|
748
|
-
project : (fn(ref(self) : Self, pos : usize) -> ref(Bucket(K, V)))(
|
|
749
|
-
cond(
|
|
750
|
-
(pos >= self.capacity) => panic("HashMap: project out of bounds"),
|
|
751
|
-
// SAFETY: cond above bounds `pos`; `_data_ptr` returns the
|
|
752
|
-
// start of the Rc-managed _data buffer, which is alive while
|
|
753
|
-
// `self` holds the Rc.
|
|
754
|
-
true => unsafe(Self._data_ptr(self) &+ pos)
|
|
755
|
-
)
|
|
756
|
-
)
|
|
757
|
-
)
|
|
758
|
-
);
|
|
759
|
-
/// Position-iter constructor for HashMap (paired with the Indexable
|
|
760
|
-
/// impl above): `iter()` yields each occupied bucket index, and the
|
|
761
|
-
/// for-macro then calls `coll.project(pos)` to materialize the
|
|
762
|
-
/// `ref(Bucket)` borrow for the body.
|
|
763
|
-
impl(
|
|
764
|
-
forall(K : Type, V : Type),
|
|
765
|
-
where(K <: (Eq(K), Hash)),
|
|
766
|
-
HashMap(K, V),
|
|
767
|
-
iter : (fn(self : Self) -> HashMapPosIter(K, V))(
|
|
768
|
-
HashMapPosIter(K, V)(_map : self, _index : usize(0))
|
|
769
|
-
)
|
|
770
|
-
);
|
|
771
692
|
/// Clone implementation for HashMap — deep-clones all key-value entries.
|
|
772
693
|
impl(
|
|
773
694
|
forall(K : Type, V : Type),
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
//! ListView — a SAFE window over an `ArrayList(T)`.
|
|
2
|
+
//!
|
|
3
|
+
//! The safe replacement for borrowed slices (plans/SLICE_REWORK.md §3):
|
|
4
|
+
//! a ListView holds the Rc'd backing list and indexes through the LIVE
|
|
5
|
+
//! handle. By construction it cannot dangle:
|
|
6
|
+
//! - the view's Rc keeps the backing object alive (reassigning the
|
|
7
|
+
//! original variable doesn't matter),
|
|
8
|
+
//! - every access re-reads the CURRENT buffer through the handle, so
|
|
9
|
+
//! realloc-on-growth cannot leave a stale pointer,
|
|
10
|
+
//! - shrinkage is caught by bounds checks (a clean `.None`, never UB),
|
|
11
|
+
//! - alias mutation is VISIBLE (alias semantics, not a snapshot).
|
|
12
|
+
//!
|
|
13
|
+
//! Cost model: copying a view = one Rc incref; access = one extra
|
|
14
|
+
//! indirection + bounds check. No copy-on-write.
|
|
15
|
+
{ ArrayList } :: import("./array_list.yo");
|
|
16
|
+
ListView :: (fn(comptime(T) : Type) -> comptime(Type))(
|
|
17
|
+
struct(
|
|
18
|
+
_backing : ArrayList(T),
|
|
19
|
+
_offset : usize,
|
|
20
|
+
_len : usize
|
|
21
|
+
)
|
|
22
|
+
);
|
|
23
|
+
impl(
|
|
24
|
+
forall(T : Type),
|
|
25
|
+
ListView(T),
|
|
26
|
+
/// Create a view of `[offset, offset+len)` over `backing`. The window is
|
|
27
|
+
/// clamped to the backing's CURRENT length.
|
|
28
|
+
new : (fn(backing : ArrayList(T), offset : usize, len : usize) -> Self)({
|
|
29
|
+
blen := backing.len();
|
|
30
|
+
o := cond((offset > blen) => blen, true => offset);
|
|
31
|
+
available := (blen - o);
|
|
32
|
+
l := cond((len > available) => available, true => len);
|
|
33
|
+
Self(_backing : backing, _offset : o, _len : l)
|
|
34
|
+
}),
|
|
35
|
+
/// View of the whole list.
|
|
36
|
+
of : (fn(backing : ArrayList(T)) -> Self)({
|
|
37
|
+
n := backing.len();
|
|
38
|
+
Self(_backing : backing, _offset : usize(0), _len : n)
|
|
39
|
+
}),
|
|
40
|
+
/// The view's length (fixed at construction; may exceed what the
|
|
41
|
+
/// backing currently holds if it shrank — reads past it yield .None).
|
|
42
|
+
len : (fn(self : Self) -> usize)(self._len),
|
|
43
|
+
is_empty : (fn(self : Self) -> bool)(self._len == usize(0)),
|
|
44
|
+
/// Read element `i` THROUGH the live backing. Bounds-checked against
|
|
45
|
+
/// both the view window and the backing's current length.
|
|
46
|
+
get : (fn(self : Self, i : usize) -> Option(T))(
|
|
47
|
+
cond(
|
|
48
|
+
(i >= self._len) => Option(T).None,
|
|
49
|
+
true => self._backing.get(self._offset + i)
|
|
50
|
+
)
|
|
51
|
+
),
|
|
52
|
+
/// A sub-view of this view (still aliasing the same backing).
|
|
53
|
+
/// (Params avoid the names of sibling methods bound earlier in this
|
|
54
|
+
/// impl — e.g. `len` — which cannot be shadowed.)
|
|
55
|
+
view : (fn(self : Self, sub_offset : usize, sub_len : usize) -> Self)({
|
|
56
|
+
o := cond((sub_offset > self._len) => self._len, true => sub_offset);
|
|
57
|
+
available := (self._len - o);
|
|
58
|
+
l := cond((sub_len > available) => available, true => sub_len);
|
|
59
|
+
Self(_backing : self._backing, _offset : (self._offset + o), _len : l)
|
|
60
|
+
}),
|
|
61
|
+
/// Owned copy of the window's CURRENT contents.
|
|
62
|
+
to_list : (fn(self : Self) -> ArrayList(T))({
|
|
63
|
+
out := ArrayList(T).new();
|
|
64
|
+
i := usize(0);
|
|
65
|
+
while(i < self._len, i = (i + usize(1)), {
|
|
66
|
+
match(
|
|
67
|
+
self._backing.get(self._offset + i),
|
|
68
|
+
.Some(v) => {
|
|
69
|
+
___ := out.push(v);
|
|
70
|
+
},
|
|
71
|
+
.None => ()
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
out
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
export(ListView);
|
package/std/crypto/random.yo
CHANGED
|
@@ -55,9 +55,9 @@ extern(
|
|
|
55
55
|
// ============================================================================
|
|
56
56
|
// Fill a buffer with cryptographically secure random bytes.
|
|
57
57
|
// ============================================================================
|
|
58
|
-
random_bytes :: (fn(buf :
|
|
59
|
-
buf_ptr := buf.ptr
|
|
60
|
-
size := buf.len
|
|
58
|
+
random_bytes :: (fn(buf : RawSlice(u8), exn : Exception) -> unit)({
|
|
59
|
+
buf_ptr := buf.ptr;
|
|
60
|
+
size := buf.len;
|
|
61
61
|
cond(
|
|
62
62
|
(platform == Platform.Macos) => {
|
|
63
63
|
__yo_arc4random_buf(buf_ptr, size);
|
|
@@ -109,7 +109,7 @@ export(random_bytes);
|
|
|
109
109
|
// ============================================================================
|
|
110
110
|
random_u32 :: (fn(exn : Exception) -> u32)({
|
|
111
111
|
buf := Array(u8, usize(4)).fill(u8(0));
|
|
112
|
-
random_bytes(
|
|
112
|
+
random_bytes(RawSlice(u8)(ptr : &(buf(usize(0))), len : usize(4)), exn);
|
|
113
113
|
u32(buf(usize(0))) |
|
|
114
114
|
(u32(buf(usize(1))) << u32(8)) |
|
|
115
115
|
(u32(buf(usize(2))) << u32(16)) |
|
|
@@ -142,7 +142,7 @@ export(random_u32, random_u64, random_f64, random_range);
|
|
|
142
142
|
uuid_v4 :: (fn(exn : Exception) -> String)({
|
|
143
143
|
bytes := ArrayList(u8).with_capacity(usize(16));
|
|
144
144
|
buf := Array(u8, usize(16)).fill(u8(0));
|
|
145
|
-
random_bytes(
|
|
145
|
+
random_bytes(RawSlice(u8)(ptr : &(buf(usize(0))), len : usize(16)), exn);
|
|
146
146
|
// Set version bits (v4)
|
|
147
147
|
buf(usize(6)) = ((buf(usize(6)) & u8(0x0F)) | u8(0x40));
|
|
148
148
|
// Set variant bits
|