@shd101wyy/yo 0.1.14 → 0.1.16

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 (60) hide show
  1. package/README.md +43 -1
  2. package/out/cjs/index.cjs +581 -601
  3. package/out/cjs/yo-cli.cjs +739 -733
  4. package/out/cjs/yo-lsp.cjs +11615 -0
  5. package/out/esm/index.mjs +530 -550
  6. package/out/types/src/cache.d.ts +2 -0
  7. package/out/types/src/codegen/exprs/return.d.ts +1 -1
  8. package/out/types/src/codegen/types/generation.d.ts +0 -2
  9. package/out/types/src/codegen/utils/index.d.ts +2 -8
  10. package/out/types/src/doc/extractor.d.ts +4 -0
  11. package/out/types/src/evaluator/builtins/rc-fns.d.ts +0 -5
  12. package/out/types/src/evaluator/context.d.ts +7 -3
  13. package/out/types/src/evaluator/trait-checking.d.ts +2 -0
  14. package/out/types/src/evaluator/types/object.d.ts +2 -1
  15. package/out/types/src/evaluator/types/struct.d.ts +2 -1
  16. package/out/types/src/evaluator/types/utils.d.ts +3 -8
  17. package/out/types/src/evaluator/values/impl.d.ts +9 -1
  18. package/out/types/src/expr.d.ts +1 -2
  19. package/out/types/src/function-value.d.ts +1 -0
  20. package/out/types/src/lsp/completion.d.ts +3 -0
  21. package/out/types/src/lsp/definition.d.ts +3 -0
  22. package/out/types/src/lsp/diagnostics.d.ts +6 -0
  23. package/out/types/src/lsp/document-manager.d.ts +31 -0
  24. package/out/types/src/lsp/folding.d.ts +3 -0
  25. package/out/types/src/lsp/hover.d.ts +3 -0
  26. package/out/types/src/lsp/inlay-hints.d.ts +3 -0
  27. package/out/types/src/lsp/references.d.ts +3 -0
  28. package/out/types/src/lsp/rename.d.ts +16 -0
  29. package/out/types/src/lsp/server.d.ts +1 -0
  30. package/out/types/src/lsp/signature-help.d.ts +3 -0
  31. package/out/types/src/lsp/symbols.d.ts +3 -0
  32. package/out/types/src/lsp/utils.d.ts +11 -0
  33. package/out/types/src/tests/lsp.test.d.ts +1 -0
  34. package/out/types/src/tests/version.test.d.ts +1 -0
  35. package/out/types/src/types/creators.d.ts +2 -3
  36. package/out/types/src/types/definitions.d.ts +3 -6
  37. package/out/types/src/types/guards.d.ts +5 -2
  38. package/out/types/src/types/tags.d.ts +0 -1
  39. package/out/types/src/version-cache.d.ts +7 -0
  40. package/out/types/src/version.d.ts +5 -0
  41. package/out/types/tsconfig.tsbuildinfo +1 -1
  42. package/package.json +3 -1
  43. package/scripts/build-site.ts +32 -15
  44. package/scripts/check-liburing.js +2 -2
  45. package/std/imm/list.yo +254 -0
  46. package/std/imm/map.yo +917 -0
  47. package/std/imm/set.yo +179 -0
  48. package/std/imm/sorted_map.yo +595 -0
  49. package/std/imm/sorted_set.yo +202 -0
  50. package/std/imm/string.yo +667 -0
  51. package/std/imm/vec.yo +456 -0
  52. package/std/prelude.yo +22 -5
  53. package/std/sync/channel.yo +92 -44
  54. package/std/sync/cond.yo +5 -1
  55. package/std/sync/mutex.yo +5 -1
  56. package/std/sync/once.yo +2 -1
  57. package/std/sync/rwlock.yo +2 -1
  58. package/std/sync/waitgroup.yo +2 -1
  59. package/out/types/src/codegen/exprs/arc.d.ts +0 -5
  60. package/out/types/src/evaluator/calls/arc.d.ts +0 -15
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shd101wyy/yo",
3
3
  "displayName": "Yo",
4
- "version": "0.1.14",
4
+ "version": "0.1.16",
5
5
  "main": "./out/cjs/index.cjs",
6
6
  "module": "./out/esm/index.mjs",
7
7
  "types": "./out/types/src/index.d.ts",
@@ -48,6 +48,8 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "markdown_yo": "0.0.4",
51
+ "vscode-languageserver": "^9.0.1",
52
+ "vscode-languageserver-textdocument": "^1.0.12",
51
53
  "yargs": "^17.7.2"
52
54
  },
53
55
  "devDependencies": {
@@ -20,18 +20,19 @@ import * as fs from "fs";
20
20
  import * as path from "path";
21
21
  import { createRenderer } from "markdown_yo";
22
22
  import type { MarkdownRenderer } from "markdown_yo";
23
- import { execSync } from "child_process";
23
+ import { execFileSync } from "child_process";
24
24
 
25
25
  const ROOT = path.resolve(import.meta.dir, "..");
26
26
  const GITHUB_REPO = "https://github.com/shd101wyy/Yo";
27
27
 
28
28
  // Detect the latest release tag for stable links.
29
29
  // Falls back to "main" if no tags exist or git fails.
30
- function getLatestTag(): string {
30
+ export function getLatestTag(rootDir: string = ROOT): string {
31
31
  try {
32
- const result = execSync("git describe --tags --abbrev=0 2>/dev/null", {
33
- cwd: ROOT,
32
+ const result = execFileSync("git", ["describe", "--tags", "--abbrev=0"], {
33
+ cwd: rootDir,
34
34
  encoding: "utf-8",
35
+ stdio: ["ignore", "pipe", "ignore"],
35
36
  timeout: 5000,
36
37
  }).trim();
37
38
  return result || "main";
@@ -43,6 +44,16 @@ function getLatestTag(): string {
43
44
  const GITHUB_REF = getLatestTag();
44
45
  const GITHUB_BLOB = `${GITHUB_REPO}/blob/${GITHUB_REF}`;
45
46
 
47
+ export function getStdDocCommand(rootDir: string = ROOT): {
48
+ command: string;
49
+ args: string[];
50
+ } {
51
+ return {
52
+ command: "node",
53
+ args: [path.join(rootDir, "out", "cjs", "yo-cli.cjs"), "doc", "std/"],
54
+ };
55
+ }
56
+
46
57
  // ── Parse args ───────────────────────────────────────────────────────
47
58
 
48
59
  let outputDir = path.join(ROOT, "site");
@@ -399,7 +410,7 @@ function injectHomeLinks(stdDir: string): void {
399
410
 
400
411
  // ── Main ─────────────────────────────────────────────────────────────
401
412
 
402
- async function main(): Promise<void> {
413
+ export async function main(): Promise<void> {
403
414
  console.log("Building documentation site...");
404
415
  console.log(` Output: ${outputDir}`);
405
416
 
@@ -449,12 +460,16 @@ async function main(): Promise<void> {
449
460
  const stdOutputDir = path.join(outputDir, "std");
450
461
 
451
462
  try {
452
- const yoCli = path.join(ROOT, "yo-cli");
453
- execSync(`${yoCli} doc std/ --output "${stdOutputDir}"`, {
454
- cwd: ROOT,
455
- stdio: ["pipe", "pipe", "inherit"],
456
- timeout: 120_000,
457
- });
463
+ const stdDocCommand = getStdDocCommand();
464
+ execFileSync(
465
+ stdDocCommand.command,
466
+ [...stdDocCommand.args, "--output", stdOutputDir],
467
+ {
468
+ cwd: ROOT,
469
+ stdio: ["ignore", "inherit", "inherit"],
470
+ timeout: 600_000,
471
+ }
472
+ );
458
473
  console.log(" ✓ Standard library docs generated");
459
474
  } catch (err) {
460
475
  console.error(
@@ -492,7 +507,9 @@ function getTotalSize(dir: string): number {
492
507
  return Math.round(total / 1024);
493
508
  }
494
509
 
495
- main().catch((err) => {
496
- console.error("Fatal error:", err);
497
- process.exit(1);
498
- });
510
+ if (import.meta.main) {
511
+ main().catch((err) => {
512
+ console.error("Fatal error:", err);
513
+ process.exit(1);
514
+ });
515
+ }
@@ -9,9 +9,9 @@ const fs = require("fs");
9
9
  function checkLiburing() {
10
10
  const platform = os.platform();
11
11
 
12
- // Only check on Linux
12
+ // Only check on Linux. Other platforms don't use io_uring, so keep postinstall
13
+ // quiet instead of printing a Linux-specific note.
13
14
  if (platform !== "linux") {
14
- console.log("ℹ️ Async I/O with io_uring is only supported on Linux.");
15
15
  return;
16
16
  }
17
17
 
@@ -0,0 +1,254 @@
1
+ //! Persistent immutable singly-linked list with O(1) prepend, head, and tail.
2
+ //!
3
+ //! `List(T)` is a cons list backed by `atomic object` nodes for thread-safe
4
+ //! structural sharing. Multiple lists can share tails with no copying.
5
+ //!
6
+ //! All elements must implement `Send` to guarantee thread safety.
7
+ //!
8
+ //! # Examples
9
+ //!
10
+ //! ```rust
11
+ //! { List } :: import "std/imm/list";
12
+ //!
13
+ //! xs := List(i32).new();
14
+ //! xs = xs.prepend(i32(3)).prepend(i32(2)).prepend(i32(1));
15
+ //! assert((xs.head().unwrap() == i32(1)), "head is 1");
16
+ //! assert((xs.len() == usize(3)), "length is 3");
17
+ //! ```
18
+
19
+ { GlobalAllocator } :: import "../allocator.yo";
20
+ { malloc, free } :: GlobalAllocator;
21
+ { memcpy } :: import "../libc/string.yo";
22
+
23
+ /// Internal cons cell — atomic object for thread-safe structural sharing.
24
+ ListNode :: (fn(comptime(T) : Type, where(T <: Send)) -> comptime(Type))(
25
+ atomic object(
26
+ _value : T,
27
+ _next : Option(Self)
28
+ )
29
+ );
30
+
31
+ // Manual Acyclic impl — ListNode is self-referential, so auto-derivation skips it.
32
+ // This is safe because ListNode is immutable: all operations create new nodes and never
33
+ // mutate existing ones, making it impossible to form cycles at runtime.
34
+ impl(forall(T : Type), where(T <: Send), ListNode(T), Acyclic());
35
+
36
+ /// Persistent immutable singly-linked list.
37
+ ///
38
+ /// A value-type wrapper around an optional chain of `ListNode` atomic objects.
39
+ /// Cheap to copy (just a pointer + length). All "modification" operations
40
+ /// return a new `List` that shares structure with the original.
41
+ List :: (fn(comptime(T) : Type, where(T <: Send)) -> comptime(Type))(
42
+ struct(
43
+ _head : Option(ListNode(T)),
44
+ _len : usize
45
+ )
46
+ );
47
+
48
+ impl(forall(T : Type), where(T <: Send), List(T),
49
+ /// Create an empty list.
50
+ new : (fn() -> Self)(
51
+ Self(_head: .None, _len: usize(0))
52
+ ),
53
+
54
+ /// Return the number of elements.
55
+ len : (fn(self : Self) -> usize)(
56
+ self._len
57
+ ),
58
+
59
+ /// Return `true` if the list is empty.
60
+ is_empty : (fn(self : Self) -> bool)(
61
+ (self._len == usize(0))
62
+ ),
63
+
64
+ /// Return a new list with `value` at the front. O(1).
65
+ prepend : (fn(self : Self, value : T) -> Self)(
66
+ Self(
67
+ _head: .Some(ListNode(T)(_value: value, _next: self._head)),
68
+ _len: (self._len + usize(1))
69
+ )
70
+ ),
71
+
72
+ /// Return the first element, or `.None` if empty. O(1).
73
+ head : (fn(self : Self) -> Option(T))(
74
+ match(self._head,
75
+ .Some(node) => .Some(node._value),
76
+ .None => .None
77
+ )
78
+ ),
79
+
80
+ /// Return a new list without the first element. O(1).
81
+ /// Returns an empty list if already empty.
82
+ tail : (fn(self : Self) -> Self)(
83
+ match(self._head,
84
+ .Some(node) => Self(_head: node._next, _len: (self._len - usize(1))),
85
+ .None => self
86
+ )
87
+ ),
88
+
89
+ /// Access element at `index`. O(n).
90
+ /// Returns `.None` if index is out of bounds.
91
+ get : (fn(self : Self, index : usize) -> Option(T))({
92
+ if((index >= self._len), {
93
+ return .None;
94
+ });
95
+ (current : Option(ListNode(T))) = self._head;
96
+ (i : usize) = usize(0);
97
+ while runtime(true), {
98
+ match(current,
99
+ .Some(node) => {
100
+ if((i == index), {
101
+ return .Some(node._value);
102
+ });
103
+ current = node._next;
104
+ i = (i + usize(1));
105
+ },
106
+ .None => {
107
+ return .None;
108
+ }
109
+ );
110
+ };
111
+ .None
112
+ }),
113
+
114
+ /// Return a new list with elements in reverse order. O(n).
115
+ reverse : (fn(self : Self) -> Self)({
116
+ (result : Self) = Self.new();
117
+ (current : Option(ListNode(T))) = self._head;
118
+ while runtime(current.is_some()), {
119
+ (node : ListNode(T)) = current.unwrap();
120
+ result = result.prepend(node._value);
121
+ current = node._next;
122
+ };
123
+ result
124
+ }),
125
+
126
+ /// Concatenate two lists. O(n) where n = self.len().
127
+ /// The resulting list contains all elements of `self` followed by `other`.
128
+ concat : (fn(self : Self, other : Self) -> Self)({
129
+ reversed := self.reverse();
130
+ (result : Self) = other;
131
+ (current : Option(ListNode(T))) = reversed._head;
132
+ while runtime(current.is_some()), {
133
+ (node : ListNode(T)) = current.unwrap();
134
+ result = result.prepend(node._value);
135
+ current = node._next;
136
+ };
137
+ result
138
+ }),
139
+
140
+ /// Apply a function to each element, producing a new list. O(n).
141
+ map : (fn(forall(U : Type), self : Self, f : Impl(Fn(a : T) -> U), where(U <: Send)) -> List(U))({
142
+ (result : List(U)) = List(U).new();
143
+ (current : Option(ListNode(T))) = self._head;
144
+ while runtime(current.is_some()), {
145
+ (node : ListNode(T)) = current.unwrap();
146
+ result = result.prepend(f(node._value));
147
+ current = node._next;
148
+ };
149
+ result.reverse()
150
+ }),
151
+
152
+ /// Keep only elements satisfying the predicate. O(n).
153
+ filter : (fn(self : Self, f : Impl(Fn(a : T) -> bool)) -> Self)({
154
+ (result : Self) = Self.new();
155
+ (current : Option(ListNode(T))) = self._head;
156
+ while runtime(current.is_some()), {
157
+ (node : ListNode(T)) = current.unwrap();
158
+ if(f(node._value), {
159
+ result = result.prepend(node._value);
160
+ });
161
+ current = node._next;
162
+ };
163
+ result.reverse()
164
+ }),
165
+
166
+ /// Left fold over the list. O(n).
167
+ fold : (fn(forall(U : Type), self : Self, init : U, f : Impl(Fn(acc : U, item : T) -> U)) -> U)({
168
+ (acc : U) = init;
169
+ (current : Option(ListNode(T))) = self._head;
170
+ while runtime(current.is_some()), {
171
+ (node : ListNode(T)) = current.unwrap();
172
+ acc = f(acc, node._value);
173
+ current = node._next;
174
+ };
175
+ acc
176
+ }),
177
+
178
+ /// Execute a function for each element. O(n).
179
+ for_each : (fn(self : Self, f : Impl(Fn(a : T) -> unit)) -> unit)({
180
+ (current : Option(ListNode(T))) = self._head;
181
+ while runtime(current.is_some()), {
182
+ (node : ListNode(T)) = current.unwrap();
183
+ f(node._value);
184
+ current = node._next;
185
+ };
186
+ }),
187
+
188
+ /// Check if the list contains a value. O(n).
189
+ /// Requires T to implement Eq.
190
+ contains : (fn(self : Self, value : T, where(T <: Eq(T))) -> bool)({
191
+ (current : Option(ListNode(T))) = self._head;
192
+ while runtime(true), {
193
+ match(current,
194
+ .Some(node) => {
195
+ if((node._value == value), {
196
+ return true;
197
+ });
198
+ current = node._next;
199
+ },
200
+ .None => {
201
+ return false;
202
+ }
203
+ );
204
+ };
205
+ false
206
+ }),
207
+
208
+ /// Build a list from a slice. O(n).
209
+ from_slice : (fn(s : Slice(T)) -> Self)({
210
+ (result : Self) = Self.new();
211
+ (i : usize) = s.len();
212
+ while ((i > usize(0))), {
213
+ i = (i - usize(1));
214
+ result = result.prepend(s(i));
215
+ };
216
+ result
217
+ })
218
+ );
219
+
220
+ /// Equality: two lists are equal if they have the same length and elements.
221
+ impl(forall(T : Type), where(T <: (Send, Eq(T))), List(T), Eq(List(T))(
222
+ (==) : (fn(lhs : Self, rhs : Self) -> bool)({
223
+ if((lhs._len != rhs._len), {
224
+ return false;
225
+ });
226
+ (l : Option(ListNode(T))) = lhs._head;
227
+ (r : Option(ListNode(T))) = rhs._head;
228
+ while runtime(true), {
229
+ match(l,
230
+ .Some(ln) => match(r,
231
+ .Some(rn) => {
232
+ if((ln._value != rn._value), {
233
+ return false;
234
+ });
235
+ l = ln._next;
236
+ r = rn._next;
237
+ },
238
+ .None => {
239
+ return false;
240
+ }
241
+ ),
242
+ .None => {
243
+ return true;
244
+ }
245
+ );
246
+ };
247
+ true
248
+ })
249
+ ));
250
+
251
+ export
252
+ List,
253
+ ListNode
254
+ ;