rooklang 0.3.2 → 0.3.4

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 (178) hide show
  1. package/README.md +32 -7
  2. package/README.ru.md +32 -7
  3. package/dist/ast/declarations.d.ts +20 -1
  4. package/dist/ast/expressions.d.ts +31 -1
  5. package/dist/ast/markup.d.ts +6 -1
  6. package/dist/ast/statements.d.ts +25 -1
  7. package/dist/auto-import.d.ts +11 -0
  8. package/dist/auto-import.js +81 -0
  9. package/dist/breaks.d.ts +6 -0
  10. package/dist/breaks.js +36 -0
  11. package/dist/build.d.ts +7 -0
  12. package/dist/build.js +23 -2
  13. package/dist/checker/array-literals.d.ts +6 -0
  14. package/dist/checker/array-literals.js +59 -0
  15. package/dist/checker/assignments.d.ts +7 -0
  16. package/dist/checker/assignments.js +48 -8
  17. package/dist/checker/base.d.ts +2 -1
  18. package/dist/checker/base.js +6 -12
  19. package/dist/checker/builtins.js +15 -5
  20. package/dist/checker/bytes.d.ts +2 -2
  21. package/dist/checker/bytes.js +2 -2
  22. package/dist/checker/calls.js +3 -0
  23. package/dist/checker/channel-objects.d.ts +3 -0
  24. package/dist/checker/channel-objects.js +40 -0
  25. package/dist/checker/channels.d.ts +1 -0
  26. package/dist/checker/channels.js +16 -2
  27. package/dist/checker/checker.d.ts +1 -1
  28. package/dist/checker/checker.js +19 -0
  29. package/dist/checker/class-members.d.ts +22 -0
  30. package/dist/checker/class-members.js +105 -0
  31. package/dist/checker/classes.d.ts +5 -4
  32. package/dist/checker/classes.js +41 -12
  33. package/dist/checker/closing.d.ts +21 -0
  34. package/dist/checker/closing.js +164 -0
  35. package/dist/checker/completion.d.ts +2 -2
  36. package/dist/checker/completion.js +2 -2
  37. package/dist/checker/context.d.ts +19 -0
  38. package/dist/checker/control-flow.d.ts +6 -0
  39. package/dist/checker/control-flow.js +34 -0
  40. package/dist/checker/declarations.js +1 -0
  41. package/dist/checker/decode.d.ts +8 -0
  42. package/dist/checker/decode.js +32 -0
  43. package/dist/checker/error-results.d.ts +6 -0
  44. package/dist/checker/error-results.js +31 -0
  45. package/dist/checker/expressions.d.ts +5 -1
  46. package/dist/checker/expressions.js +13 -34
  47. package/dist/checker/flow.js +8 -4
  48. package/dist/checker/helpers.d.ts +1 -1
  49. package/dist/checker/helpers.js +9 -2
  50. package/dist/checker/iterables.d.ts +3 -1
  51. package/dist/checker/iterables.js +13 -0
  52. package/dist/checker/iterators.d.ts +4 -1
  53. package/dist/checker/iterators.js +12 -4
  54. package/dist/checker/json.d.ts +5 -0
  55. package/dist/checker/json.js +92 -0
  56. package/dist/checker/loops.js +23 -3
  57. package/dist/checker/members.js +7 -0
  58. package/dist/checker/operators.d.ts +2 -2
  59. package/dist/checker/operators.js +7 -5
  60. package/dist/checker/queues.d.ts +2 -2
  61. package/dist/checker/queues.js +2 -2
  62. package/dist/checker/resolution.js +5 -3
  63. package/dist/checker/signals.d.ts +8 -0
  64. package/dist/checker/signals.js +48 -0
  65. package/dist/checker/statements.d.ts +5 -0
  66. package/dist/checker/statements.js +19 -0
  67. package/dist/checker/topics.d.ts +6 -0
  68. package/dist/checker/topics.js +17 -0
  69. package/dist/checker/transfer.d.ts +3 -1
  70. package/dist/checker/transfer.js +25 -5
  71. package/dist/checker/try.d.ts +6 -0
  72. package/dist/checker/try.js +19 -0
  73. package/dist/checker/types/constructors.d.ts +1 -1
  74. package/dist/checker/types/constructors.js +2 -2
  75. package/dist/checker/types/generics.js +1 -1
  76. package/dist/checker/types/iterables.d.ts +13 -0
  77. package/dist/checker/types/iterables.js +52 -0
  78. package/dist/checker/types/model.d.ts +25 -0
  79. package/dist/checker/types/params.js +22 -3
  80. package/dist/checker/types/printing.js +4 -3
  81. package/dist/checker/types/relations.js +19 -25
  82. package/dist/checker/types/topic.d.ts +6 -0
  83. package/dist/checker/types/topic.js +23 -0
  84. package/dist/checker/types.d.ts +2 -0
  85. package/dist/checker/types.js +2 -0
  86. package/dist/cli.js +18 -36
  87. package/dist/codegen/calls.d.ts +23 -0
  88. package/dist/codegen/calls.js +88 -7
  89. package/dist/codegen/control-statements.d.ts +19 -3
  90. package/dist/codegen/control-statements.js +105 -20
  91. package/dist/codegen/decode.d.ts +14 -0
  92. package/dist/codegen/decode.js +93 -0
  93. package/dist/codegen/emitter.d.ts +10 -41
  94. package/dist/codegen/emitter.js +9 -4
  95. package/dist/codegen/expressions.d.ts +9 -0
  96. package/dist/codegen/expressions.js +15 -24
  97. package/dist/codegen/js.d.ts +2 -2
  98. package/dist/codegen/js.js +5 -2
  99. package/dist/codegen/options.d.ts +40 -0
  100. package/dist/codegen/options.js +1 -0
  101. package/dist/codegen/runtime.d.ts +7 -5
  102. package/dist/codegen/runtime.js +28 -20
  103. package/dist/codegen/simple-statements.d.ts +10 -4
  104. package/dist/codegen/simple-statements.js +40 -15
  105. package/dist/codegen/statements.js +64 -4
  106. package/dist/codegen/try.d.ts +5 -0
  107. package/dist/codegen/try.js +40 -0
  108. package/dist/compile.d.ts +9 -0
  109. package/dist/compile.js +19 -6
  110. package/dist/completion.d.ts +4 -2
  111. package/dist/completion.js +10 -5
  112. package/dist/declarations.js +32 -6
  113. package/dist/decorator-copy.js +5 -2
  114. package/dist/goroutines.d.ts +1 -1
  115. package/dist/goroutines.js +5 -4
  116. package/dist/index.d.ts +6 -2
  117. package/dist/index.js +14 -5
  118. package/dist/lexer/base.d.ts +2 -0
  119. package/dist/lexer/base.js +6 -1
  120. package/dist/lexer/lexer.js +3 -0
  121. package/dist/lexer/literals.d.ts +5 -0
  122. package/dist/lexer/literals.js +51 -1
  123. package/dist/lexer/markup.js +3 -4
  124. package/dist/lexer/tables.js +2 -0
  125. package/dist/lexer/token.d.ts +4 -3
  126. package/dist/lexer/token.js +0 -2
  127. package/dist/loader.js +40 -13
  128. package/dist/parser/base.d.ts +4 -0
  129. package/dist/parser/base.js +2 -1
  130. package/dist/parser/classes.d.ts +2 -0
  131. package/dist/parser/classes.js +88 -23
  132. package/dist/parser/control-flow.d.ts +3 -1
  133. package/dist/parser/control-flow.js +21 -24
  134. package/dist/parser/declarations.d.ts +7 -4
  135. package/dist/parser/declarations.js +45 -6
  136. package/dist/parser/expressions.js +27 -3
  137. package/dist/parser/jumps.d.ts +11 -0
  138. package/dist/parser/jumps.js +77 -0
  139. package/dist/parser/literals.d.ts +9 -0
  140. package/dist/parser/literals.js +45 -6
  141. package/dist/parser/markup.js +1 -1
  142. package/dist/parser/simple-statements.d.ts +1 -1
  143. package/dist/parser/simple-statements.js +16 -9
  144. package/dist/parser/statements.d.ts +0 -3
  145. package/dist/parser/statements.js +22 -25
  146. package/dist/parser/syntax.d.ts +11 -1
  147. package/dist/parser/syntax.js +16 -2
  148. package/dist/parser/types.js +8 -3
  149. package/dist/project-modules.d.ts +12 -0
  150. package/dist/project-modules.js +106 -0
  151. package/dist/run-file.d.ts +6 -0
  152. package/dist/run-file.js +111 -0
  153. package/dist/runtime/sources.js +11 -5
  154. package/dist/runtime-module.d.ts +1 -0
  155. package/dist/runtime-module.js +3 -0
  156. package/dist/source-map.d.ts +17 -0
  157. package/dist/source-map.js +75 -0
  158. package/dist/ts-types.d.ts +4 -0
  159. package/dist/ts-types.js +20 -3
  160. package/dist/typescript/convert-objects.d.ts +2 -1
  161. package/dist/typescript/convert-objects.js +18 -9
  162. package/dist/vite.js +13 -5
  163. package/dist/walk-types.js +1 -0
  164. package/dist/walk.d.ts +0 -2
  165. package/dist/walk.js +11 -28
  166. package/package.json +1 -1
  167. package/src/runtime/chan.js +15 -5
  168. package/src/runtime/channel.js +28 -0
  169. package/src/runtime/classes.js +32 -0
  170. package/src/runtime/core.js +10 -1
  171. package/src/runtime/decode.js +190 -0
  172. package/src/runtime/go.js +14 -5
  173. package/src/runtime/index.js +6 -0
  174. package/src/runtime/select.js +14 -9
  175. package/src/runtime/signals.js +59 -0
  176. package/src/runtime/threads.js +32 -5
  177. package/src/runtime/topic.js +118 -0
  178. package/src/runtime/try.js +45 -0
@@ -4,6 +4,7 @@
4
4
  // modules; the operations of a thread on the channels of another go straight to that thread
5
5
  // through a MessagePort, which the main thread sets up on the first need (go.js).
6
6
 
7
+ import { $$classOf, $$reclass } from './classes.js';
7
8
  import { $$Queue } from './queue.js';
8
9
 
9
10
  // The state of this thread that its modules share: the channels it made, its ports to the other
@@ -29,6 +30,12 @@ export function $$registry() {
29
30
  });
30
31
  }
31
32
 
33
+ // Channel.EMPTY, the zero value of channel types, has this id in every thread: it is closed, and
34
+ // no thread keeps it (channel.js).
35
+ export function $$isEmpty(id) {
36
+ return id === 'empty';
37
+ }
38
+
32
39
  // The key of the thread that made a channel, which keeps what it holds.
33
40
  export function $$ownerOf(id) {
34
41
  return id.slice(0, id.lastIndexOf(':'));
@@ -42,9 +49,11 @@ export function $$post(key, message) {
42
49
 
43
50
  if (registry.gone.has(key)) return;
44
51
 
45
- const { channels, moved } = $$walk(message);
52
+ const { channels, moved, instances } = $$walk(message);
46
53
 
47
54
  for (const channel of channels) $$hold(channel.$$chan, 1);
55
+ // The copies of the instances of data classes are listed in the copy, by reference.
56
+ if (instances.length > 0) message = { ...message, $$instances: instances };
48
57
 
49
58
  const port = registry.ports.get(key);
50
59
 
@@ -136,6 +145,7 @@ export function $$incoming(key, data) {
136
145
  const registry = $$registry();
137
146
 
138
147
  $$adopt(data);
148
+ $$reclassed(data);
139
149
  if ('answer' in data) {
140
150
  const request = registry.requests.get(data.answer);
141
151
 
@@ -166,6 +176,11 @@ export function $$hold(id, count) {
166
176
  if (state.holders <= 0) registry.states.delete(id);
167
177
  }
168
178
 
179
+ // A message with copies of the instances of data classes gives them their classes back.
180
+ export function $$reclassed(data) {
181
+ if (data.$$instances) $$reclass(data.$$instances);
182
+ }
183
+
169
184
  export function $$adopt(value) {
170
185
  const { held } = $$registry();
171
186
 
@@ -175,11 +190,19 @@ export function $$adopt(value) {
175
190
  // A copy in this thread. One that `own` the runtime, such as the arguments of `go` that wait for
176
191
  // a worker, moves its buffers on.
177
192
  export function $$copy(value, own = false) {
178
- const { channels, moved } = $$walk(value);
193
+ const { channels, moved, instances } = $$walk(value);
179
194
 
180
195
  for (const channel of channels) $$hold(channel.$$chan, 1);
181
196
 
182
- const copy = structuredClone(value, { transfer: moved });
197
+ const { copy, $$instances } = structuredClone(
198
+ { copy: value, $$instances: instances },
199
+ {
200
+ transfer: moved,
201
+ },
202
+ );
203
+
204
+ $$reclass($$instances);
205
+
183
206
  const { held } = $$registry();
184
207
 
185
208
  for (const channel of $$walk(copy, own).channels) held.register(channel, channel.$$chan);
@@ -200,7 +223,7 @@ export function $$transfer(value) {
200
223
  export function $$walk(
201
224
  value,
202
225
  own = false,
203
- found = { channels: new Set(), moved: [] },
226
+ found = { channels: new Set(), moved: [], instances: [] },
204
227
  seen = new Set(),
205
228
  ) {
206
229
  if (typeof value !== 'object' || value === null || seen.has(value)) return found;
@@ -221,8 +244,12 @@ export function $$walk(
221
244
  }
222
245
 
223
246
  if (Array.isArray(value.$$queue)) Object.setPrototypeOf(value, $$Queue.prototype);
247
+
248
+ const id = $$classOf(value);
249
+
250
+ if (id !== undefined) found.instances.push([value, id]);
224
251
  if (typeof value.$$chan === 'string') {
225
- found.channels.add(value);
252
+ if (!$$isEmpty(value.$$chan)) found.channels.add(value);
226
253
 
227
254
  return found;
228
255
  }
@@ -0,0 +1,118 @@
1
+ // Topics: values that go to the other tabs of a site, and to its workers, over a BroadcastChannel
2
+ // of their name. A topic is data, `{ $$topic: name, zero }`, so it goes to a worker as its name,
3
+ // and there it is a topic of its own. Each topic listens from its first receive on, into a channel
4
+ // without a limit, so that `<-t`, `for v in t` and `select` are those of channels. `Topic` has
5
+ // what Rook code and the code compiled from it do with topics, by name.
6
+
7
+ import { $$chan, $$closeHere, $$send } from './chan.js';
8
+ import { $$Channel } from './channel.js';
9
+ import { $$walk } from './threads.js';
10
+
11
+ export const $$Topic = Object.freeze({
12
+ // The zero value of topic types: it has no name, it is closed, and what is sent to it goes
13
+ // nowhere.
14
+ EMPTY: Object.freeze({ $$topic: null, zero: null }),
15
+ make: $$topic,
16
+ publish: $$publish,
17
+ listen: $$listen,
18
+ close: $$closeTopic,
19
+ });
20
+
21
+ // What the modules of a thread share: one BroadcastChannel for each name, so that the topics of
22
+ // this thread do not hear what it sends, as one BroadcastChannel does not hear itself; the channel
23
+ // that each topic listens into, and the topics that are closed.
24
+ function $$topics() {
25
+ return (globalThis[Symbol.for('rook.topics')] ??= {
26
+ names: new Map(),
27
+ channels: new WeakMap(),
28
+ closed: new WeakSet(),
29
+ });
30
+ }
31
+
32
+ export function $$topic(name, zero) {
33
+ return { $$topic: name, zero };
34
+ }
35
+
36
+ // `t <- v`: the value goes to the other threads that listen and is not kept here, so nothing waits.
37
+ export function $$publish(topic, value) {
38
+ if (topic.$$topic === null) return;
39
+ if ($$topics().closed.has(topic)) throw new Error('send on a closed topic');
40
+ $$named(topic.$$topic).channel.postMessage(value);
41
+ }
42
+
43
+ // The channel that a topic listens into, from the first receive on; a closed topic gives a closed
44
+ // one, and Topic.EMPTY gives Channel.EMPTY. A null topic turns off its case of `select`, as a null
45
+ // channel does.
46
+ export function $$listen(topic) {
47
+ if (topic === null) return null;
48
+ if (topic.$$topic === null) return $$Channel.EMPTY;
49
+
50
+ const { channels, closed } = $$topics();
51
+ let channel = channels.get(topic);
52
+
53
+ if (channel) return channel;
54
+ channel = $$chan(Infinity, topic.zero);
55
+ channels.set(topic, channel);
56
+ if (closed.has(topic)) $$closeHere(channel.$$chan);
57
+ else $$listening(topic, true);
58
+
59
+ return channel;
60
+ }
61
+
62
+ // `close(t)`: the topic stops listening and sending; what it has received can still be received.
63
+ export function $$closeTopic(topic) {
64
+ const { channels, closed } = $$topics();
65
+
66
+ if (topic.$$topic === null) return;
67
+ if (closed.has(topic)) throw new Error('close of a closed topic');
68
+ closed.add(topic);
69
+
70
+ const channel = channels.get(topic);
71
+
72
+ if (!channel) return;
73
+ $$closeHere(channel.$$chan);
74
+ $$listening(topic, false);
75
+ }
76
+
77
+ // The BroadcastChannel of a name and the topics of this thread that listen to it, each of which
78
+ // gets a copy of its own.
79
+ function $$named(name) {
80
+ const { names, channels } = $$topics();
81
+ const found = names.get(name);
82
+
83
+ if (found) return found;
84
+
85
+ const entry = { channel: new BroadcastChannel(name), listening: new Set() };
86
+
87
+ entry.channel.onmessage = ({ data }) => {
88
+ let first = true;
89
+
90
+ for (const topic of entry.listening) {
91
+ const value = first ? data : structuredClone(data);
92
+
93
+ first = false;
94
+ $$walk(value);
95
+ $$send(channels.get(topic), value);
96
+ }
97
+ };
98
+
99
+ names.set(name, entry);
100
+ $$keepAlive(entry);
101
+
102
+ return entry;
103
+ }
104
+
105
+ function $$listening(topic, on) {
106
+ const entry = $$named(topic.$$topic);
107
+
108
+ if (on) entry.listening.add(topic);
109
+ else entry.listening.delete(topic);
110
+ $$keepAlive(entry);
111
+ }
112
+
113
+ // In Node, a BroadcastChannel keeps the program running only while a topic listens to it, as a
114
+ // `tick` does until it is closed.
115
+ function $$keepAlive({ channel, listening }) {
116
+ if (listening.size > 0) channel.ref?.();
117
+ else channel.unref?.();
118
+ }
@@ -0,0 +1,45 @@
1
+ // `try expr`: an exception in the expression becomes the error of `(T, error)`. `results` is how
2
+ // many values the expression gives: 0 for none, and then the error comes alone, 1 for a value, more
3
+ // for several. With `withError` the last of them is an error already, as of `(User, error)` or of a
4
+ // function that returns only an error, and an exception takes its place.
5
+
6
+ export function $$catch(f, results = 1, withError = false) {
7
+ let value;
8
+
9
+ try {
10
+ value = f();
11
+ } catch (error) {
12
+ return failed(error, results, withError);
13
+ }
14
+
15
+ return succeeded(value, results, withError);
16
+ }
17
+
18
+ /** `try` of an expression that waits: a rejected Promise is caught as an exception is. */
19
+ export async function $$catchAsync(f, results = 1, withError = false) {
20
+ let value;
21
+
22
+ try {
23
+ value = await f();
24
+ } catch (error) {
25
+ return failed(error, results, withError);
26
+ }
27
+
28
+ return succeeded(value, results, withError);
29
+ }
30
+
31
+ function succeeded(value, results, withError) {
32
+ if (results === 0) return null;
33
+ if (withError) return value;
34
+
35
+ return results === 1 ? [value, null] : [...value, null];
36
+ }
37
+
38
+ /** JS can throw anything; what is not an Error becomes one, so that the error has a message. */
39
+ function failed(thrown, results, withError) {
40
+ const error = thrown instanceof Error ? thrown : new Error(String(thrown));
41
+
42
+ if (results === 0 || (withError && results === 1)) return error;
43
+
44
+ return [...Array(withError ? results - 1 : results).fill(null), error];
45
+ }