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.
- package/README.md +32 -7
- package/README.ru.md +32 -7
- package/dist/ast/declarations.d.ts +20 -1
- package/dist/ast/expressions.d.ts +31 -1
- package/dist/ast/markup.d.ts +6 -1
- package/dist/ast/statements.d.ts +25 -1
- package/dist/auto-import.d.ts +11 -0
- package/dist/auto-import.js +81 -0
- package/dist/breaks.d.ts +6 -0
- package/dist/breaks.js +36 -0
- package/dist/build.d.ts +7 -0
- package/dist/build.js +23 -2
- package/dist/checker/array-literals.d.ts +6 -0
- package/dist/checker/array-literals.js +59 -0
- package/dist/checker/assignments.d.ts +7 -0
- package/dist/checker/assignments.js +48 -8
- package/dist/checker/base.d.ts +2 -1
- package/dist/checker/base.js +6 -12
- package/dist/checker/builtins.js +15 -5
- package/dist/checker/bytes.d.ts +2 -2
- package/dist/checker/bytes.js +2 -2
- package/dist/checker/calls.js +3 -0
- package/dist/checker/channel-objects.d.ts +3 -0
- package/dist/checker/channel-objects.js +40 -0
- package/dist/checker/channels.d.ts +1 -0
- package/dist/checker/channels.js +16 -2
- package/dist/checker/checker.d.ts +1 -1
- package/dist/checker/checker.js +19 -0
- package/dist/checker/class-members.d.ts +22 -0
- package/dist/checker/class-members.js +105 -0
- package/dist/checker/classes.d.ts +5 -4
- package/dist/checker/classes.js +41 -12
- package/dist/checker/closing.d.ts +21 -0
- package/dist/checker/closing.js +164 -0
- package/dist/checker/completion.d.ts +2 -2
- package/dist/checker/completion.js +2 -2
- package/dist/checker/context.d.ts +19 -0
- package/dist/checker/control-flow.d.ts +6 -0
- package/dist/checker/control-flow.js +34 -0
- package/dist/checker/declarations.js +1 -0
- package/dist/checker/decode.d.ts +8 -0
- package/dist/checker/decode.js +32 -0
- package/dist/checker/error-results.d.ts +6 -0
- package/dist/checker/error-results.js +31 -0
- package/dist/checker/expressions.d.ts +5 -1
- package/dist/checker/expressions.js +13 -34
- package/dist/checker/flow.js +8 -4
- package/dist/checker/helpers.d.ts +1 -1
- package/dist/checker/helpers.js +9 -2
- package/dist/checker/iterables.d.ts +3 -1
- package/dist/checker/iterables.js +13 -0
- package/dist/checker/iterators.d.ts +4 -1
- package/dist/checker/iterators.js +12 -4
- package/dist/checker/json.d.ts +5 -0
- package/dist/checker/json.js +92 -0
- package/dist/checker/loops.js +23 -3
- package/dist/checker/members.js +7 -0
- package/dist/checker/operators.d.ts +2 -2
- package/dist/checker/operators.js +7 -5
- package/dist/checker/queues.d.ts +2 -2
- package/dist/checker/queues.js +2 -2
- package/dist/checker/resolution.js +5 -3
- package/dist/checker/signals.d.ts +8 -0
- package/dist/checker/signals.js +48 -0
- package/dist/checker/statements.d.ts +5 -0
- package/dist/checker/statements.js +19 -0
- package/dist/checker/topics.d.ts +6 -0
- package/dist/checker/topics.js +17 -0
- package/dist/checker/transfer.d.ts +3 -1
- package/dist/checker/transfer.js +25 -5
- package/dist/checker/try.d.ts +6 -0
- package/dist/checker/try.js +19 -0
- package/dist/checker/types/constructors.d.ts +1 -1
- package/dist/checker/types/constructors.js +2 -2
- package/dist/checker/types/generics.js +1 -1
- package/dist/checker/types/iterables.d.ts +13 -0
- package/dist/checker/types/iterables.js +52 -0
- package/dist/checker/types/model.d.ts +25 -0
- package/dist/checker/types/params.js +22 -3
- package/dist/checker/types/printing.js +4 -3
- package/dist/checker/types/relations.js +19 -25
- package/dist/checker/types/topic.d.ts +6 -0
- package/dist/checker/types/topic.js +23 -0
- package/dist/checker/types.d.ts +2 -0
- package/dist/checker/types.js +2 -0
- package/dist/cli.js +18 -36
- package/dist/codegen/calls.d.ts +23 -0
- package/dist/codegen/calls.js +88 -7
- package/dist/codegen/control-statements.d.ts +19 -3
- package/dist/codegen/control-statements.js +105 -20
- package/dist/codegen/decode.d.ts +14 -0
- package/dist/codegen/decode.js +93 -0
- package/dist/codegen/emitter.d.ts +10 -41
- package/dist/codegen/emitter.js +9 -4
- package/dist/codegen/expressions.d.ts +9 -0
- package/dist/codegen/expressions.js +15 -24
- package/dist/codegen/js.d.ts +2 -2
- package/dist/codegen/js.js +5 -2
- package/dist/codegen/options.d.ts +40 -0
- package/dist/codegen/options.js +1 -0
- package/dist/codegen/runtime.d.ts +7 -5
- package/dist/codegen/runtime.js +28 -20
- package/dist/codegen/simple-statements.d.ts +10 -4
- package/dist/codegen/simple-statements.js +40 -15
- package/dist/codegen/statements.js +64 -4
- package/dist/codegen/try.d.ts +5 -0
- package/dist/codegen/try.js +40 -0
- package/dist/compile.d.ts +9 -0
- package/dist/compile.js +19 -6
- package/dist/completion.d.ts +4 -2
- package/dist/completion.js +10 -5
- package/dist/declarations.js +32 -6
- package/dist/decorator-copy.js +5 -2
- package/dist/goroutines.d.ts +1 -1
- package/dist/goroutines.js +5 -4
- package/dist/index.d.ts +6 -2
- package/dist/index.js +14 -5
- package/dist/lexer/base.d.ts +2 -0
- package/dist/lexer/base.js +6 -1
- package/dist/lexer/lexer.js +3 -0
- package/dist/lexer/literals.d.ts +5 -0
- package/dist/lexer/literals.js +51 -1
- package/dist/lexer/markup.js +3 -4
- package/dist/lexer/tables.js +2 -0
- package/dist/lexer/token.d.ts +4 -3
- package/dist/lexer/token.js +0 -2
- package/dist/loader.js +40 -13
- package/dist/parser/base.d.ts +4 -0
- package/dist/parser/base.js +2 -1
- package/dist/parser/classes.d.ts +2 -0
- package/dist/parser/classes.js +88 -23
- package/dist/parser/control-flow.d.ts +3 -1
- package/dist/parser/control-flow.js +21 -24
- package/dist/parser/declarations.d.ts +7 -4
- package/dist/parser/declarations.js +45 -6
- package/dist/parser/expressions.js +27 -3
- package/dist/parser/jumps.d.ts +11 -0
- package/dist/parser/jumps.js +77 -0
- package/dist/parser/literals.d.ts +9 -0
- package/dist/parser/literals.js +45 -6
- package/dist/parser/markup.js +1 -1
- package/dist/parser/simple-statements.d.ts +1 -1
- package/dist/parser/simple-statements.js +16 -9
- package/dist/parser/statements.d.ts +0 -3
- package/dist/parser/statements.js +22 -25
- package/dist/parser/syntax.d.ts +11 -1
- package/dist/parser/syntax.js +16 -2
- package/dist/parser/types.js +8 -3
- package/dist/project-modules.d.ts +12 -0
- package/dist/project-modules.js +106 -0
- package/dist/run-file.d.ts +6 -0
- package/dist/run-file.js +111 -0
- package/dist/runtime/sources.js +11 -5
- package/dist/runtime-module.d.ts +1 -0
- package/dist/runtime-module.js +3 -0
- package/dist/source-map.d.ts +17 -0
- package/dist/source-map.js +75 -0
- package/dist/ts-types.d.ts +4 -0
- package/dist/ts-types.js +20 -3
- package/dist/typescript/convert-objects.d.ts +2 -1
- package/dist/typescript/convert-objects.js +18 -9
- package/dist/vite.js +13 -5
- package/dist/walk-types.js +1 -0
- package/dist/walk.d.ts +0 -2
- package/dist/walk.js +11 -28
- package/package.json +1 -1
- package/src/runtime/chan.js +15 -5
- package/src/runtime/channel.js +28 -0
- package/src/runtime/classes.js +32 -0
- package/src/runtime/core.js +10 -1
- package/src/runtime/decode.js +190 -0
- package/src/runtime/go.js +14 -5
- package/src/runtime/index.js +6 -0
- package/src/runtime/select.js +14 -9
- package/src/runtime/signals.js +59 -0
- package/src/runtime/threads.js +32 -5
- package/src/runtime/topic.js +118 -0
- package/src/runtime/try.js +45 -0
package/src/runtime/threads.js
CHANGED
|
@@ -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(
|
|
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
|
+
}
|