rooklang 0.0.0-stage → 0.3.0

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 (314) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -2
  3. package/README.ru.md +178 -0
  4. package/dist/ast/declarations.d.ts +185 -0
  5. package/dist/ast/declarations.js +1 -0
  6. package/dist/ast/expressions.d.ts +201 -0
  7. package/dist/ast/expressions.js +1 -0
  8. package/dist/ast/markup.d.ts +141 -0
  9. package/dist/ast/markup.js +1 -0
  10. package/dist/ast/statements.d.ts +173 -0
  11. package/dist/ast/statements.js +1 -0
  12. package/dist/ast.d.ts +18 -0
  13. package/dist/ast.js +18 -0
  14. package/dist/attrs.d.ts +8 -0
  15. package/dist/attrs.js +23 -0
  16. package/dist/browser.d.ts +30 -0
  17. package/dist/browser.js +36 -0
  18. package/dist/build.d.ts +48 -0
  19. package/dist/build.js +112 -0
  20. package/dist/checker/assignments.d.ts +14 -0
  21. package/dist/checker/assignments.js +197 -0
  22. package/dist/checker/base.d.ts +124 -0
  23. package/dist/checker/base.js +180 -0
  24. package/dist/checker/bigint.d.ts +15 -0
  25. package/dist/checker/bigint.js +85 -0
  26. package/dist/checker/builtins.d.ts +9 -0
  27. package/dist/checker/builtins.js +307 -0
  28. package/dist/checker/bytes.d.ts +11 -0
  29. package/dist/checker/bytes.js +72 -0
  30. package/dist/checker/calls.d.ts +23 -0
  31. package/dist/checker/calls.js +210 -0
  32. package/dist/checker/channel.d.ts +14 -0
  33. package/dist/checker/channel.js +44 -0
  34. package/dist/checker/channels.d.ts +9 -0
  35. package/dist/checker/channels.js +95 -0
  36. package/dist/checker/checker.d.ts +4 -0
  37. package/dist/checker/checker.js +22 -0
  38. package/dist/checker/classes.d.ts +24 -0
  39. package/dist/checker/classes.js +223 -0
  40. package/dist/checker/completion-names.d.ts +11 -0
  41. package/dist/checker/completion-names.js +100 -0
  42. package/dist/checker/completion.d.ts +25 -0
  43. package/dist/checker/completion.js +222 -0
  44. package/dist/checker/component-values.d.ts +11 -0
  45. package/dist/checker/component-values.js +88 -0
  46. package/dist/checker/components.d.ts +37 -0
  47. package/dist/checker/components.js +287 -0
  48. package/dist/checker/context.d.ts +196 -0
  49. package/dist/checker/context.js +35 -0
  50. package/dist/checker/control-flow.d.ts +24 -0
  51. package/dist/checker/control-flow.js +237 -0
  52. package/dist/checker/declarations.d.ts +26 -0
  53. package/dist/checker/declarations.js +259 -0
  54. package/dist/checker/decorator-exports.d.ts +5 -0
  55. package/dist/checker/decorator-exports.js +40 -0
  56. package/dist/checker/decorator-members.d.ts +28 -0
  57. package/dist/checker/decorator-members.js +140 -0
  58. package/dist/checker/decorator-wrappers.d.ts +20 -0
  59. package/dist/checker/decorator-wrappers.js +132 -0
  60. package/dist/checker/decorators.d.ts +28 -0
  61. package/dist/checker/decorators.js +265 -0
  62. package/dist/checker/dom-svg.d.ts +7 -0
  63. package/dist/checker/dom-svg.js +19 -0
  64. package/dist/checker/dom.d.ts +22 -0
  65. package/dist/checker/dom.js +361 -0
  66. package/dist/checker/expressions.d.ts +32 -0
  67. package/dist/checker/expressions.js +244 -0
  68. package/dist/checker/flow.d.ts +18 -0
  69. package/dist/checker/flow.js +134 -0
  70. package/dist/checker/forwarding.d.ts +15 -0
  71. package/dist/checker/forwarding.js +78 -0
  72. package/dist/checker/functions.d.ts +24 -0
  73. package/dist/checker/functions.js +154 -0
  74. package/dist/checker/go-for.d.ts +12 -0
  75. package/dist/checker/go-for.js +93 -0
  76. package/dist/checker/goroutines.d.ts +19 -0
  77. package/dist/checker/goroutines.js +110 -0
  78. package/dist/checker/helpers.d.ts +35 -0
  79. package/dist/checker/helpers.js +162 -0
  80. package/dist/checker/imports.d.ts +7 -0
  81. package/dist/checker/imports.js +83 -0
  82. package/dist/checker/initializers.d.ts +22 -0
  83. package/dist/checker/initializers.js +104 -0
  84. package/dist/checker/iterables.d.ts +5 -0
  85. package/dist/checker/iterables.js +17 -0
  86. package/dist/checker/iterators.d.ts +13 -0
  87. package/dist/checker/iterators.js +95 -0
  88. package/dist/checker/loops.d.ts +10 -0
  89. package/dist/checker/loops.js +82 -0
  90. package/dist/checker/markup.d.ts +28 -0
  91. package/dist/checker/markup.js +220 -0
  92. package/dist/checker/members.d.ts +29 -0
  93. package/dist/checker/members.js +233 -0
  94. package/dist/checker/operators.d.ts +13 -0
  95. package/dist/checker/operators.js +177 -0
  96. package/dist/checker/promise.d.ts +17 -0
  97. package/dist/checker/promise.js +49 -0
  98. package/dist/checker/refs.d.ts +26 -0
  99. package/dist/checker/refs.js +136 -0
  100. package/dist/checker/resolution.d.ts +23 -0
  101. package/dist/checker/resolution.js +173 -0
  102. package/dist/checker/statements.d.ts +28 -0
  103. package/dist/checker/statements.js +212 -0
  104. package/dist/checker/styles.d.ts +14 -0
  105. package/dist/checker/styles.js +49 -0
  106. package/dist/checker/transfer.d.ts +5 -0
  107. package/dist/checker/transfer.js +83 -0
  108. package/dist/checker/types/bytes.d.ts +4 -0
  109. package/dist/checker/types/bytes.js +51 -0
  110. package/dist/checker/types/classes.d.ts +22 -0
  111. package/dist/checker/types/classes.js +93 -0
  112. package/dist/checker/types/constructors.d.ts +27 -0
  113. package/dist/checker/types/constructors.js +129 -0
  114. package/dist/checker/types/generics.d.ts +20 -0
  115. package/dist/checker/types/generics.js +75 -0
  116. package/dist/checker/types/lazy.d.ts +30 -0
  117. package/dist/checker/types/lazy.js +92 -0
  118. package/dist/checker/types/model.d.ts +149 -0
  119. package/dist/checker/types/model.js +15 -0
  120. package/dist/checker/types/params.d.ts +7 -0
  121. package/dist/checker/types/params.js +220 -0
  122. package/dist/checker/types/printing.d.ts +6 -0
  123. package/dist/checker/types/printing.js +109 -0
  124. package/dist/checker/types/relations.d.ts +16 -0
  125. package/dist/checker/types/relations.js +294 -0
  126. package/dist/checker/types.d.ts +9 -0
  127. package/dist/checker/types.js +10 -0
  128. package/dist/cli.d.ts +2 -0
  129. package/dist/cli.js +193 -0
  130. package/dist/codegen/analysis.d.ts +18 -0
  131. package/dist/codegen/analysis.js +144 -0
  132. package/dist/codegen/attributes.d.ts +40 -0
  133. package/dist/codegen/attributes.js +227 -0
  134. package/dist/codegen/calls.d.ts +22 -0
  135. package/dist/codegen/calls.js +106 -0
  136. package/dist/codegen/chan-helpers.d.ts +2 -0
  137. package/dist/codegen/chan-helpers.js +253 -0
  138. package/dist/codegen/component-helpers.d.ts +33 -0
  139. package/dist/codegen/component-helpers.js +18 -0
  140. package/dist/codegen/component-props.d.ts +42 -0
  141. package/dist/codegen/component-props.js +173 -0
  142. package/dist/codegen/component-values.d.ts +27 -0
  143. package/dist/codegen/component-values.js +146 -0
  144. package/dist/codegen/components.d.ts +53 -0
  145. package/dist/codegen/components.js +268 -0
  146. package/dist/codegen/control-flow.d.ts +25 -0
  147. package/dist/codegen/control-flow.js +152 -0
  148. package/dist/codegen/control-statements.d.ts +28 -0
  149. package/dist/codegen/control-statements.js +226 -0
  150. package/dist/codegen/creation.d.ts +31 -0
  151. package/dist/codegen/creation.js +113 -0
  152. package/dist/codegen/early-returns.d.ts +59 -0
  153. package/dist/codegen/early-returns.js +244 -0
  154. package/dist/codegen/element-helpers.d.ts +12 -0
  155. package/dist/codegen/element-helpers.js +54 -0
  156. package/dist/codegen/elements.d.ts +71 -0
  157. package/dist/codegen/elements.js +293 -0
  158. package/dist/codegen/emitter.d.ts +135 -0
  159. package/dist/codegen/emitter.js +296 -0
  160. package/dist/codegen/expressions.d.ts +49 -0
  161. package/dist/codegen/expressions.js +262 -0
  162. package/dist/codegen/functions.d.ts +28 -0
  163. package/dist/codegen/functions.js +170 -0
  164. package/dist/codegen/go-helpers.d.ts +9 -0
  165. package/dist/codegen/go-helpers.js +307 -0
  166. package/dist/codegen/helpers.d.ts +10 -0
  167. package/dist/codegen/helpers.js +356 -0
  168. package/dist/codegen/imported.d.ts +38 -0
  169. package/dist/codegen/imported.js +71 -0
  170. package/dist/codegen/js.d.ts +20 -0
  171. package/dist/codegen/js.js +113 -0
  172. package/dist/codegen/mutations.d.ts +10 -0
  173. package/dist/codegen/mutations.js +102 -0
  174. package/dist/codegen/parallel.d.ts +7 -0
  175. package/dist/codegen/parallel.js +63 -0
  176. package/dist/codegen/reactive.d.ts +95 -0
  177. package/dist/codegen/reactive.js +280 -0
  178. package/dist/codegen/refs.d.ts +62 -0
  179. package/dist/codegen/refs.js +160 -0
  180. package/dist/codegen/select-helpers.d.ts +2 -0
  181. package/dist/codegen/select-helpers.js +135 -0
  182. package/dist/codegen/simple-statements.d.ts +42 -0
  183. package/dist/codegen/simple-statements.js +253 -0
  184. package/dist/codegen/statements.d.ts +22 -0
  185. package/dist/codegen/statements.js +142 -0
  186. package/dist/codegen/styles.d.ts +54 -0
  187. package/dist/codegen/styles.js +157 -0
  188. package/dist/codegen/syntax.d.ts +18 -0
  189. package/dist/codegen/syntax.js +70 -0
  190. package/dist/codegen/thread-helpers.d.ts +2 -0
  191. package/dist/codegen/thread-helpers.js +198 -0
  192. package/dist/codegen/updates.d.ts +51 -0
  193. package/dist/codegen/updates.js +201 -0
  194. package/dist/codegen/web-components.d.ts +20 -0
  195. package/dist/codegen/web-components.js +149 -0
  196. package/dist/compile-file.d.ts +11 -0
  197. package/dist/compile-file.js +24 -0
  198. package/dist/compile.d.ts +53 -0
  199. package/dist/compile.js +187 -0
  200. package/dist/completion.d.ts +10 -0
  201. package/dist/completion.js +134 -0
  202. package/dist/config.d.ts +2 -0
  203. package/dist/config.js +44 -0
  204. package/dist/css/hash.d.ts +1 -0
  205. package/dist/css/hash.js +10 -0
  206. package/dist/css/parse.d.ts +42 -0
  207. package/dist/css/parse.js +138 -0
  208. package/dist/css/print.d.ts +9 -0
  209. package/dist/css/print.js +35 -0
  210. package/dist/css/selectors.d.ts +29 -0
  211. package/dist/css/selectors.js +168 -0
  212. package/dist/declarations.d.ts +3 -0
  213. package/dist/declarations.js +207 -0
  214. package/dist/decorator-copy.d.ts +18 -0
  215. package/dist/decorator-copy.js +158 -0
  216. package/dist/decorators.d.ts +61 -0
  217. package/dist/decorators.js +241 -0
  218. package/dist/diagnostics.d.ts +17 -0
  219. package/dist/diagnostics.js +22 -0
  220. package/dist/go-for.d.ts +26 -0
  221. package/dist/go-for.js +155 -0
  222. package/dist/goroutines.d.ts +37 -0
  223. package/dist/goroutines.js +253 -0
  224. package/dist/html-tag.d.ts +21 -0
  225. package/dist/html-tag.js +103 -0
  226. package/dist/index.d.ts +33 -0
  227. package/dist/index.js +55 -0
  228. package/dist/inline-packages.d.ts +32 -0
  229. package/dist/inline-packages.js +129 -0
  230. package/dist/iterators.d.ts +10 -0
  231. package/dist/iterators.js +33 -0
  232. package/dist/lexer/base.d.ts +24 -0
  233. package/dist/lexer/base.js +87 -0
  234. package/dist/lexer/lexer.d.ts +8 -0
  235. package/dist/lexer/lexer.js +134 -0
  236. package/dist/lexer/literals.d.ts +18 -0
  237. package/dist/lexer/literals.js +203 -0
  238. package/dist/lexer/markup.d.ts +10 -0
  239. package/dist/lexer/markup.js +93 -0
  240. package/dist/lexer/style.d.ts +17 -0
  241. package/dist/lexer/style.js +97 -0
  242. package/dist/lexer/tables.d.ts +53 -0
  243. package/dist/lexer/tables.js +101 -0
  244. package/dist/lexer/token.d.ts +42 -0
  245. package/dist/lexer/token.js +108 -0
  246. package/dist/loader.d.ts +1 -0
  247. package/dist/loader.js +50 -0
  248. package/dist/methods.d.ts +5 -0
  249. package/dist/methods.js +81 -0
  250. package/dist/modules.d.ts +3 -0
  251. package/dist/modules.js +49 -0
  252. package/dist/names.d.ts +23 -0
  253. package/dist/names.js +267 -0
  254. package/dist/parser/base.d.ts +96 -0
  255. package/dist/parser/base.js +202 -0
  256. package/dist/parser/classes.d.ts +8 -0
  257. package/dist/parser/classes.js +164 -0
  258. package/dist/parser/control-flow.d.ts +29 -0
  259. package/dist/parser/control-flow.js +232 -0
  260. package/dist/parser/declarations.d.ts +27 -0
  261. package/dist/parser/declarations.js +238 -0
  262. package/dist/parser/decorators.d.ts +30 -0
  263. package/dist/parser/decorators.js +176 -0
  264. package/dist/parser/expressions.d.ts +15 -0
  265. package/dist/parser/expressions.js +255 -0
  266. package/dist/parser/literals.d.ts +27 -0
  267. package/dist/parser/literals.js +206 -0
  268. package/dist/parser/markup.d.ts +22 -0
  269. package/dist/parser/markup.js +193 -0
  270. package/dist/parser/parser.d.ts +14 -0
  271. package/dist/parser/parser.js +22 -0
  272. package/dist/parser/simple-statements.d.ts +22 -0
  273. package/dist/parser/simple-statements.js +156 -0
  274. package/dist/parser/statements.d.ts +37 -0
  275. package/dist/parser/statements.js +267 -0
  276. package/dist/parser/syntax.d.ts +51 -0
  277. package/dist/parser/syntax.js +173 -0
  278. package/dist/parser/types.d.ts +23 -0
  279. package/dist/parser/types.js +218 -0
  280. package/dist/recursion.d.ts +25 -0
  281. package/dist/recursion.js +170 -0
  282. package/dist/refs.d.ts +49 -0
  283. package/dist/refs.js +210 -0
  284. package/dist/run.d.ts +1 -0
  285. package/dist/run.js +21 -0
  286. package/dist/source.d.ts +15 -0
  287. package/dist/source.js +34 -0
  288. package/dist/style-modules.d.ts +17 -0
  289. package/dist/style-modules.js +49 -0
  290. package/dist/styles.d.ts +36 -0
  291. package/dist/styles.js +160 -0
  292. package/dist/svg.d.ts +8 -0
  293. package/dist/svg.js +77 -0
  294. package/dist/ts-types.d.ts +11 -0
  295. package/dist/ts-types.js +133 -0
  296. package/dist/typed-arrays.d.ts +8 -0
  297. package/dist/typed-arrays.js +43 -0
  298. package/dist/typescript/convert-base.d.ts +42 -0
  299. package/dist/typescript/convert-base.js +135 -0
  300. package/dist/typescript/convert-objects.d.ts +28 -0
  301. package/dist/typescript/convert-objects.js +245 -0
  302. package/dist/typescript/convert.d.ts +14 -0
  303. package/dist/typescript/convert.js +67 -0
  304. package/dist/typescript/importer.d.ts +37 -0
  305. package/dist/typescript/importer.js +152 -0
  306. package/dist/typescript/library.d.ts +23 -0
  307. package/dist/typescript/library.js +81 -0
  308. package/dist/vite.d.ts +11 -0
  309. package/dist/vite.js +86 -0
  310. package/dist/walk-types.d.ts +4 -0
  311. package/dist/walk-types.js +56 -0
  312. package/dist/walk.d.ts +5 -0
  313. package/dist/walk.js +315 -0
  314. package/package.json +104 -4
@@ -0,0 +1,106 @@
1
+ import { typedArrayOf } from "../checker/types.js";
2
+ import { isYieldCall } from "../iterators.js";
3
+ import { TYPED_ARRAYS, TYPED_ELEMENTS } from "../typed-arrays.js";
4
+ import { hasOptionalLink } from "./analysis.js";
5
+ import { ExpressionEmitter } from "./expressions.js";
6
+ import { ARROW, BINARY, POSTFIX } from "./syntax.js";
7
+ // Calls, `new`, array literals and conversions. A `[]byte` is a Uint8Array: a literal where the
8
+ // checker found one expected becomes `new Uint8Array([...])`, and the conversions of Go between
9
+ // text and its UTF-8 bytes use TextEncoder and TextDecoder, `[]byte(s)` and `string(data)`. In an
10
+ // iterator, a generator, `yield(v)` yields: its value is `true`, since a generator that the loop
11
+ // over it leaves is closed at that `yield` and goes no further, so `false` is never seen.
12
+ export class CallEmitter extends ExpressionEmitter {
13
+ call(node) {
14
+ // After `?.` the arguments may not be evaluated at all.
15
+ const conditional = node.optional || hasOptionalLink(node.callee);
16
+ const args = this.withHoisting(this.hoist && !conditional, () => this.elements(node.arguments));
17
+ if (this.isBuiltinError(node.callee) && !node.optional)
18
+ return `new Error(${args})`;
19
+ if (this.isStringConversion(node.callee))
20
+ return `new TextDecoder().decode(${args})`;
21
+ const yielded = this.yielded(node);
22
+ if (yielded !== null)
23
+ return `(${yielded}, true)`;
24
+ return `${this.expression(node.callee, POSTFIX)}${node.optional ? '?.' : ''}(${args})`;
25
+ }
26
+ /** `yield v` for `yield(v)` in an iterator, `yield [k, v]` for `yield(k, v)`; else `null`. */
27
+ yielded(node) {
28
+ if (!this.fn.iterator || !isYieldCall(node) || this.lookup('yield') !== 'param')
29
+ return null;
30
+ const values = node.arguments.map((argument) => this.expression(argument.kind === 'SpreadElement' ? argument.argument : argument, ARROW));
31
+ return values.length === 1 ? `yield ${values[0]}` : `yield [${values.join(', ')}]`;
32
+ }
33
+ expressionStatement(node) {
34
+ return this.yielded(node) ?? super.expressionStatement(node);
35
+ }
36
+ /** `if !yield(v) { return }`, the way an iterator of Go stops: in a generator, `yield v`. */
37
+ yieldStatement(node) {
38
+ const [only] = node.consequent.body;
39
+ const { condition } = node;
40
+ if (node.alternate ||
41
+ node.consequent.body.length !== 1 ||
42
+ only?.kind !== 'ReturnStatement' ||
43
+ only.values.length > 0 ||
44
+ condition.kind !== 'UnaryExpression' ||
45
+ condition.operator !== '!') {
46
+ return null;
47
+ }
48
+ return this.yielded(condition.argument);
49
+ }
50
+ /** `string(data)`, unless `string` is the name of a value here. */
51
+ isStringConversion(callee) {
52
+ return callee.kind === 'Identifier' && callee.name === 'string' && !this.lookup('string');
53
+ }
54
+ newExpression(node) {
55
+ return `new ${this.newCallee(node.callee)}(${this.elements(node.arguments)})`;
56
+ }
57
+ /** `new (f())()` and `new (a?.B)()` need parentheses around the class expression. */
58
+ newCallee(callee) {
59
+ let node = callee;
60
+ let needsParens = false;
61
+ while (true) {
62
+ if (node.kind === 'CallExpression') {
63
+ needsParens = true;
64
+ break;
65
+ }
66
+ if (node.kind !== 'MemberExpression' && node.kind !== 'IndexExpression')
67
+ break;
68
+ if (node.optional) {
69
+ needsParens = true;
70
+ break;
71
+ }
72
+ node = node.object;
73
+ }
74
+ return this.expression(callee, POSTFIX, needsParens);
75
+ }
76
+ arrayLiteral(node) {
77
+ const array = `[${this.elements(node.elements)}]`;
78
+ const type = this.options.types?.get(node);
79
+ const typed = type && typedArrayOf(type);
80
+ return typed ? `new ${typed}(${array})` : array;
81
+ }
82
+ /**
83
+ * `make([]float64, n)` → `new Float64Array(n)`; with `shared`, on a SharedArrayBuffer of its
84
+ * size in bytes, `new Float64Array($$shared(8 * n))`. Without types the name is the one written.
85
+ */
86
+ make(node) {
87
+ const type = this.options.types?.get(node);
88
+ const written = node.type.kind === 'ArrayType' && node.type.element.kind === 'TypeReference'
89
+ ? TYPED_ELEMENTS.get(node.type.element.name.name)
90
+ : node.type.kind === 'TypeReference'
91
+ ? node.type.name.name
92
+ : undefined;
93
+ const typed = (type && typedArrayOf(type)) ?? written ?? 'Array';
94
+ if (!node.shared)
95
+ return `new ${typed}(${this.expression(node.length, ARROW)})`;
96
+ const size = TYPED_ARRAYS.get(typed) ?? 1;
97
+ const bytes = size === 1
98
+ ? this.expression(node.length, ARROW)
99
+ : `${size} * ${this.expression(node.length, BINARY['*'] + 1)}`;
100
+ this.helpers.add('shared');
101
+ return `new ${typed}($$shared(${bytes}))`;
102
+ }
103
+ conversion(node) {
104
+ return `new TextEncoder().encode(${this.expression(node.argument, 0)})`;
105
+ }
106
+ }
@@ -0,0 +1,2 @@
1
+ export type ChanHelper = 'chan' | 'timers';
2
+ export declare const CHAN_HELPERS: Readonly<Record<ChanHelper, readonly string[]>>;
@@ -0,0 +1,253 @@
1
+ // The helpers of channels: sending, receiving and closing, here or in the thread that made the
2
+ // channel (thread-helpers.ts), and the queues of a channel. Receiving from a closed channel gives
3
+ // the zero value of its type, as in Go.
4
+ export const CHAN_HELPERS = {
5
+ chan: [
6
+ '$$registry().handle ??= { message: $$message, pump: $$pump };',
7
+ '',
8
+ 'function $$chan(size, zero) {',
9
+ ' const registry = $$registry();',
10
+ ' const id = `${registry.key}:${registry.channels++}`;',
11
+ ' const channel = { $$chan: id, size, zero };',
12
+ ' registry.states.set(id, {',
13
+ ' size,',
14
+ ' zero,',
15
+ ' buffer: [],',
16
+ ' receivers: [],',
17
+ ' senders: [],',
18
+ ' closed: false,',
19
+ ' holders: 1,',
20
+ ' busy: false,',
21
+ ' });',
22
+ ' $$adopt(channel);',
23
+ ' return channel;',
24
+ '}',
25
+ '',
26
+ '// A local operation waits in the queue of its channel; one of another thread asks the thread',
27
+ '// that made the channel.',
28
+ 'function $$send(channel, value) {',
29
+ ' const id = channel.$$chan;',
30
+ ' const owner = $$ownerOf(id);',
31
+ ' if (owner !== $$registry().key) return $$ask(owner, { op: "send", channel: id, value });',
32
+ ' return new Promise((resolve, reject) => $$wait(id, "senders", { value, done: resolve, fail: reject }));',
33
+ '}',
34
+ '',
35
+ 'function $$receive(channel, withOk = false) {',
36
+ ' const id = channel.$$chan;',
37
+ ' const owner = $$ownerOf(id);',
38
+ ' const received =',
39
+ ' owner !== $$registry().key',
40
+ ' ? $$ask(owner, { op: "receive", channel: id })',
41
+ ' : new Promise((resolve, reject) => $$wait(id, "receivers", { done: resolve, fail: reject }));',
42
+ ' return withOk ? received : received.then(([value]) => value);',
43
+ '}',
44
+ '',
45
+ '// Closing a channel of another thread fails this one if it was closed already, as a panic would.',
46
+ 'function $$close(channel) {',
47
+ ' const id = channel.$$chan;',
48
+ ' const owner = $$ownerOf(id);',
49
+ ' if (owner === $$registry().key) return $$closeHere(id);',
50
+ ' $$ask(owner, { op: "close", channel: id }).catch((error) => {',
51
+ ' setTimeout(() => {',
52
+ ' throw error;',
53
+ ' });',
54
+ ' });',
55
+ '}',
56
+ '',
57
+ 'function $$closeHere(id) {',
58
+ ' const state = $$registry().states.get(id);',
59
+ ' if (state.closed) throw new Error("close of a closed channel");',
60
+ ' state.closed = true;',
61
+ ' $$pump(id);',
62
+ '}',
63
+ '',
64
+ 'async function* $$range(channel) {',
65
+ ' while (true) {',
66
+ ' const [value, ok] = await $$receive(channel, true);',
67
+ ' if (!ok) return;',
68
+ ' yield value;',
69
+ ' }',
70
+ '}',
71
+ '',
72
+ 'function $$wait(id, queue, entry) {',
73
+ ' const state = $$registry().states.get(id);',
74
+ ' if (!state) return entry.fail?.($$stopped());',
75
+ ' state[queue].push(entry);',
76
+ ' $$pump(id);',
77
+ '}',
78
+ '',
79
+ '// The operations of other threads on the channels of this one.',
80
+ 'function $$message(from, data) {',
81
+ ' const answer = (value) => $$post(from, { answer: data.ask, value });',
82
+ ' const fail = (error) => $$post(from, { answer: data.ask, error });',
83
+ ' const select = { key: from, sid: data.sid };',
84
+ ' switch (data.op) {',
85
+ ' case "send":',
86
+ ' return $$wait(data.channel, "senders", { from, value: data.value, done: answer, fail });',
87
+ ' case "receive":',
88
+ ' return $$wait(data.channel, "receivers", { from, done: answer, fail });',
89
+ ' case "close":',
90
+ ' try {',
91
+ ' $$closeHere(data.channel);',
92
+ ' return answer();',
93
+ ' } catch (error) {',
94
+ ' return fail(error);',
95
+ ' }',
96
+ ' case "try":',
97
+ ' try {',
98
+ ' return answer($$try(data.channel, data.send, data.value));',
99
+ ' } catch (error) {',
100
+ ' return fail(error);',
101
+ ' }',
102
+ ' case "select":',
103
+ ' return $$select(data.cases, data.hasDefault).then(answer, fail);',
104
+ ' case "wait":',
105
+ ' return $$wait(data.channel, data.send ? "senders" : "receivers", {',
106
+ ' select,',
107
+ ' case: data.case,',
108
+ ' value: data.value,',
109
+ ' });',
110
+ ' case "cancel":',
111
+ ' return $$unwait(select, data.channels);',
112
+ ' case "lock":',
113
+ ' return answer($$lock(data.sid));',
114
+ ' case "unlock":',
115
+ ' return $$unlock(data.sid);',
116
+ ' case "commit":',
117
+ ' return $$commit(data.sid, data.case, data.result, data.error);',
118
+ ' }',
119
+ '}',
120
+ '',
121
+ '// Matches what waits in a channel: a receiver with a value of the buffer, a sender or the zero value',
122
+ '// after close; a sender with room in the buffer. A case of a select goes on only if its select',
123
+ '// has not gone on with another case, which the thread of the select tells.',
124
+ 'function $$pump(id) {',
125
+ ' const state = $$registry().states.get(id);',
126
+ ' while (state && !state.busy) {',
127
+ ' const [receiver] = state.receivers;',
128
+ ' const [sender] = state.senders;',
129
+ ' if (receiver && (state.buffer.length > 0 || state.closed)) {',
130
+ ' if (!$$pair(id, state, receiver, null)) return;',
131
+ ' } else if (receiver && sender) {',
132
+ ' if (!$$pair(id, state, receiver, sender)) return;',
133
+ ' } else if (sender && (state.closed || state.buffer.length < state.size)) {',
134
+ ' if (!$$pair(id, state, null, sender)) return;',
135
+ ' } else {',
136
+ ' return;',
137
+ ' }',
138
+ ' }',
139
+ '}',
140
+ '',
141
+ '// Whether the pump can go on at once: a pair whose selects are all in this thread is decided here.',
142
+ 'function $$pair(id, state, receiver, sender) {',
143
+ ' const entries = [receiver, sender].filter((entry) => entry !== null);',
144
+ ' const key = $$registry().key;',
145
+ ' if (entries.some((entry) => entry.select && entry.select.key !== key)) {',
146
+ ' $$pairLater(id, state, receiver, sender);',
147
+ ' return false;',
148
+ ' }',
149
+ ' const locks = entries.map((entry) => (entry.select ? $$lock(entry.select.sid) : "locked"));',
150
+ ' if (locks.every((lock) => lock === "locked")) {',
151
+ ' $$complete(state, receiver, sender);',
152
+ ' return true;',
153
+ ' }',
154
+ ' entries.forEach((entry, i) => locks[i] === "locked" && $$unlockAt(entry.select));',
155
+ ' return $$settle(id, state, entries, locks);',
156
+ '}',
157
+ '',
158
+ '// A pair with a select of another thread: the channel waits for the answers of that thread.',
159
+ 'async function $$pairLater(id, state, receiver, sender) {',
160
+ ' state.busy = true;',
161
+ ' const entries = [receiver, sender].filter((entry) => entry !== null);',
162
+ ' const locks = [];',
163
+ ' for (const { select } of entries) {',
164
+ ' const lock = !select',
165
+ ' ? "locked"',
166
+ ' : select.key === $$registry().key',
167
+ ' ? $$lock(select.sid)',
168
+ ' : await $$ask(select.key, { op: "lock", sid: select.sid }).catch(() => "done");',
169
+ ' locks.push(lock);',
170
+ ' if (lock !== "locked") break;',
171
+ ' }',
172
+ ' state.busy = false;',
173
+ ' if (locks.length === entries.length && locks.every((lock) => lock === "locked")) {',
174
+ ' $$complete(state, receiver, sender);',
175
+ ' } else {',
176
+ ' entries.forEach((entry, i) => locks[i] === "locked" && $$unlockAt(entry.select));',
177
+ ' if (!$$settle(id, state, entries, locks)) return;',
178
+ ' }',
179
+ ' $$pump(id);',
180
+ '}',
181
+ '',
182
+ '// After a pair that could not go on: a select that has gone on leaves the queue; one that another',
183
+ '// channel is deciding is tried again a little later.',
184
+ 'function $$settle(id, state, entries, locks) {',
185
+ ' entries.forEach((entry, i) => {',
186
+ ' if (locks[i] === "done") $$remove(state, entry);',
187
+ ' });',
188
+ ' if (locks.includes("done")) return true;',
189
+ ' setTimeout(() => $$pump(id), 1 + Math.random() * 4);',
190
+ ' return false;',
191
+ '}',
192
+ '',
193
+ 'function $$remove(state, entry) {',
194
+ ' for (const queue of [state.receivers, state.senders]) {',
195
+ ' const at = queue.indexOf(entry);',
196
+ ' if (at >= 0) queue.splice(at, 1);',
197
+ ' }',
198
+ '}',
199
+ '',
200
+ '// Takes the pair off the queues and passes the value.',
201
+ 'function $$complete(state, receiver, sender) {',
202
+ ' if (receiver) $$remove(state, receiver);',
203
+ ' if (sender) $$remove(state, sender);',
204
+ ' if (receiver) {',
205
+ ' const result =',
206
+ ' state.buffer.length > 0',
207
+ ' ? [state.buffer.shift(), true]',
208
+ ' : sender',
209
+ ' ? [sender.value, true]',
210
+ ' : [Array.isArray(state.zero) ? [] : state.zero, false];',
211
+ ' $$finish(receiver, result);',
212
+ ' if (sender) $$finish(sender);',
213
+ ' } else if (state.closed) {',
214
+ ' $$finish(sender, undefined, new Error("send on a closed channel"));',
215
+ ' } else {',
216
+ ' state.buffer.push(sender.value);',
217
+ ' $$finish(sender);',
218
+ ' }',
219
+ '}',
220
+ '',
221
+ 'function $$finish(entry, result, error) {',
222
+ ' const { select } = entry;',
223
+ ' if (!select) return error ? entry.fail(error) : entry.done(result);',
224
+ ' if (select.key === $$registry().key) return $$commit(select.sid, entry.case, result, error);',
225
+ ' $$post(select.key, { op: "commit", sid: select.sid, case: entry.case, result, error });',
226
+ '}',
227
+ '',
228
+ 'function $$unlockAt(select) {',
229
+ ' if (!select) return;',
230
+ ' if (select.key === $$registry().key) $$unlock(select.sid);',
231
+ ' else $$post(select.key, { op: "unlock", sid: select.sid });',
232
+ '}',
233
+ ],
234
+ timers: [
235
+ '// `after(ms)`: a channel that gets the time once, after `ms`. `tick(ms)`: one that gets it every',
236
+ '// `ms` until it is closed; a tick that finds the last one still there is dropped, as in Go.',
237
+ 'function $$after(ms) {',
238
+ ' const channel = $$chan(1, 0);',
239
+ ' setTimeout(() => $$send(channel, Date.now()), ms);',
240
+ ' return channel;',
241
+ '}',
242
+ '',
243
+ 'function $$tick(ms) {',
244
+ ' const channel = $$chan(1, 0);',
245
+ ' const timer = setInterval(() => {',
246
+ ' const state = $$registry().states.get(channel.$$chan);',
247
+ ' if (!state || state.closed) clearInterval(timer);',
248
+ ' else $$try(channel.$$chan, true, Date.now());',
249
+ ' }, ms);',
250
+ ' return channel;',
251
+ '}',
252
+ ],
253
+ };
@@ -0,0 +1,33 @@
1
+ import type * as ast from '../ast.ts';
2
+ import type { Reactive } from './reactive.ts';
3
+ /** How the code of a component ends: inlined into a block, or the body of a function. */
4
+ export type Ending = {
5
+ kind: 'inline';
6
+ setters: ReadonlyMap<string, string>;
7
+ } | {
8
+ kind: 'function';
9
+ props: readonly ast.Parameter[];
10
+ };
11
+ /**
12
+ * A component with an early `return`. The body runs once, so which markup it returns is decided
13
+ * once, when it is created. Each returned markup gets its own update, kept in `view`.
14
+ */
15
+ export interface EarlyReturns {
16
+ /** The function context of the body; a `return` in a nested function is that function's. */
17
+ fn: unknown;
18
+ result: string;
19
+ reactive: Reactive;
20
+ view: string;
21
+ /** Leaves the body: `break $$body3;` or `return [$$tree4, $$setTree5];` */
22
+ exit: string;
23
+ /** In a function: the function that sets the properties, declared once for every return. */
24
+ setter: string | null;
25
+ }
26
+ /** Marks where the setters of an inlined component with early returns go: before any return. */
27
+ export declare const SETTERS: string;
28
+ /** `f(a, undefined, undefined)` → `f(a)`: missing arguments are undefined anyway. */
29
+ export declare function withoutTrailingUndefined(args: string[]): string[];
30
+ /** Whether a component has `mount() { ... }`. */
31
+ export declare function hasMount(component: ast.ComponentDeclaration): boolean;
32
+ /** Whether a component returns before the end of its body. */
33
+ export declare function hasEarlyReturn(component: ast.ComponentDeclaration): boolean;
@@ -0,0 +1,18 @@
1
+ import { containsReturn } from "../recursion.js";
2
+ /** Marks where the setters of an inlined component with early returns go: before any return. */
3
+ export const SETTERS = String.fromCharCode(0xe002);
4
+ /** `f(a, undefined, undefined)` → `f(a)`: missing arguments are undefined anyway. */
5
+ export function withoutTrailingUndefined(args) {
6
+ let end = args.length;
7
+ while (end > 0 && args[end - 1] === 'undefined')
8
+ end--;
9
+ return args.slice(0, end);
10
+ }
11
+ /** Whether a component has `mount() { ... }`. */
12
+ export function hasMount(component) {
13
+ return component.body.body.some((statement) => statement.kind === 'MountStatement');
14
+ }
15
+ /** Whether a component returns before the end of its body. */
16
+ export function hasEarlyReturn(component) {
17
+ return component.body.body.slice(0, -1).some(containsReturn);
18
+ }
@@ -0,0 +1,42 @@
1
+ import type * as ast from '../ast.ts';
2
+ import { ControlFlowEmitter } from './control-flow.ts';
3
+ import { Reactive, type Live, type Source } from './reactive.ts';
4
+ import { type EarlyReturns } from './component-helpers.ts';
5
+ /** The properties of components: their values, spread objects, and calls of function components. */
6
+ export declare abstract class ComponentPropsEmitter extends ControlFlowEmitter {
7
+ protected readonly componentNames: Map<ast.ComponentDeclaration, Set<string>>;
8
+ protected earlyReturns: EarlyReturns | null;
9
+ /** Setters waiting for their place at the top of an inlined component, by its result. */
10
+ protected readonly pendingSetters: Map<string, string[]>;
11
+ /**
12
+ * In a component with `mount()`: the variable that gets its first node once the markup is
13
+ * created, so that `$$mount` can wait until that node is in the document.
14
+ */
15
+ protected mountNode: string | null;
16
+ /**
17
+ * A use of a recursive component: a call of its function. The parent's updates call the
18
+ * returned function with the new values of the properties that depend on its state.
19
+ */
20
+ protected callComponent(component: ast.ComponentDeclaration, values: ReadonlyMap<string, string>, reactiveProps: ReadonlyMap<string, [string, Set<Source>]>, live: Live | null, root?: string): string;
21
+ protected reactiveOf(component: ast.ComponentDeclaration, props: Iterable<string>): Reactive;
22
+ /**
23
+ * `title, kind = "info"`: parameters with their default values, each name with a prefix. A tag
24
+ * that takes the component from a value may leave out `children`: they are empty then.
25
+ */
26
+ protected parameters(params: readonly ast.Parameter[], prefix: string): string;
27
+ /** `{ title = $$title; ...updates of what reads it... }` */
28
+ protected setterBody(props: readonly string[], reactive: Reactive): string;
29
+ /** `return [node, (...) => { ... }]`: the node and the function that sets the properties. */
30
+ protected functionResult(result: string, reactive: Reactive, props: readonly ast.Parameter[]): void;
31
+ /**
32
+ * The value of a component property. Literals and names that the component does not redeclare
33
+ * go into its code as they are; anything else is computed before the block into a temporary.
34
+ */
35
+ protected prop(attribute: ast.JsxAttribute, component: ast.ComponentDeclaration): string;
36
+ protected propValue(value: ast.Expression, component: ast.ComponentDeclaration): string;
37
+ /**
38
+ * `<Product {...product} />`: properties that the object has get their values from it. Later
39
+ * attributes override them. The object is computed once, before the component's block.
40
+ */
41
+ protected spreadProps(argument: ast.Expression, component: ast.ComponentDeclaration, live: Live | null, values: Map<string, string>, reactiveProps: Map<string, [string, Set<Source>]>): void;
42
+ }
@@ -0,0 +1,173 @@
1
+ import { spreadFields } from "../checker/types.js";
2
+ import { declaredNames } from "../names.js";
3
+ import { isConstant, isSimple, rootName } from "./analysis.js";
4
+ import { ControlFlowEmitter } from "./control-flow.js";
5
+ import { Reactive, updatesOf } from "./reactive.js";
6
+ import { ARROW, indentMore, lowerFirst, POSTFIX, upperFirst } from "./syntax.js";
7
+ import { withoutTrailingUndefined } from "./component-helpers.js";
8
+ /** The properties of components: their values, spread objects, and calls of function components. */
9
+ export class ComponentPropsEmitter extends ControlFlowEmitter {
10
+ componentNames = new Map();
11
+ earlyReturns = null;
12
+ /** Setters waiting for their place at the top of an inlined component, by its result. */
13
+ pendingSetters = new Map();
14
+ /**
15
+ * In a component with `mount()`: the variable that gets its first node once the markup is
16
+ * created, so that `$$mount` can wait until that node is in the document.
17
+ */
18
+ mountNode = null;
19
+ /**
20
+ * A use of a recursive component: a call of its function. The parent's updates call the
21
+ * returned function with the new values of the properties that depend on its state.
22
+ */
23
+ callComponent(component, values, reactiveProps, live, root) {
24
+ const name = component.name.name;
25
+ const id = this.nextId();
26
+ const result = `$$${lowerFirst(name)}${id}`;
27
+ // A missing property with a default value is left undefined, so that the default applies.
28
+ const argument = (param) => values.get(param.name.name) ?? (param.defaultValue ? 'undefined' : 'null');
29
+ // The element a ref created for it goes last, as `$$root`.
30
+ const args = withoutTrailingUndefined([
31
+ ...component.params.map(argument),
32
+ ...(root === undefined ? [] : [root]),
33
+ ]);
34
+ const fn = this.functionNames.get(component) ?? `$$${name}`;
35
+ const call = `${fn}(${args.join(', ')})`;
36
+ if (!live || reactiveProps.size === 0) {
37
+ this.line(`const [${result}] = ${call};`);
38
+ return result;
39
+ }
40
+ const setter = `$$set${name}${id}`;
41
+ this.line(`const [${result}, ${setter}] = ${call};`);
42
+ const sources = new Set();
43
+ for (const [, propSources] of reactiveProps.values()) {
44
+ for (const source of propSources)
45
+ sources.add(source);
46
+ }
47
+ const settable = component.params.filter((param) => param.name.name !== 'children' && !param.rest);
48
+ const setterArgs = withoutTrailingUndefined(settable.map((param) => reactiveProps.get(param.name.name)?.[0] ?? argument(param)));
49
+ live.depend(sources, `${setter}(${setterArgs.join(', ')});`);
50
+ return result;
51
+ }
52
+ reactiveOf(component, props) {
53
+ return new Reactive(component, this.fn, props, (sourceName, kind) => {
54
+ const id = this.nextId();
55
+ // `$$card$price`, an argument of a decorator, is updated by `$$updateCard$price3`.
56
+ const update = `$$update${upperFirst(sourceName.replace(/^\$\$/, ''))}${id}`;
57
+ return { id, name: sourceName, kind, update, computations: [], dependents: [], writes: [] };
58
+ });
59
+ }
60
+ /**
61
+ * `title, kind = "info"`: parameters with their default values, each name with a prefix. A tag
62
+ * that takes the component from a value may leave out `children`: they are empty then.
63
+ */
64
+ parameters(params, prefix) {
65
+ return params
66
+ .map((param) => {
67
+ const name = `${prefix}${prefix ? param.name.name : this.name(param.name.name)}`;
68
+ if (param.defaultValue)
69
+ return `${name} = ${this.expression(param.defaultValue, ARROW)}`;
70
+ return param.name.name === 'children' && !param.rest
71
+ ? `${name} = document.createDocumentFragment()`
72
+ : name;
73
+ })
74
+ .join(', ');
75
+ }
76
+ /** `{ title = $$title; ...updates of what reads it... }` */
77
+ setterBody(props, reactive) {
78
+ const dependents = new Set();
79
+ for (const prop of props) {
80
+ const source = reactive.sources.get(prop);
81
+ for (const dependent of source ? updatesOf(source) : [])
82
+ dependents.add(dependent);
83
+ }
84
+ return this.block(() => {
85
+ for (const prop of props)
86
+ this.line(`${this.name(prop)} = $$${prop};`);
87
+ for (const dependent of dependents)
88
+ this.line(indentMore(dependent));
89
+ });
90
+ }
91
+ /** `return [node, (...) => { ... }]`: the node and the function that sets the properties. */
92
+ functionResult(result, reactive, props) {
93
+ if (props.length === 0) {
94
+ this.line(`return [${result}];`);
95
+ return;
96
+ }
97
+ const dependents = new Set();
98
+ for (const param of props) {
99
+ const source = reactive.sources.get(param.name.name);
100
+ for (const dependent of source ? updatesOf(source) : [])
101
+ dependents.add(dependent);
102
+ }
103
+ const setter = this.block(() => {
104
+ for (const param of props)
105
+ this.line(`${this.name(param.name.name)} = $$${param.name.name};`);
106
+ for (const dependent of dependents)
107
+ this.line(indentMore(dependent));
108
+ });
109
+ this.line(`return [${result}, (${this.parameters(props, '$$')}) => ${setter}];`);
110
+ }
111
+ /**
112
+ * The value of a component property. Literals and names that the component does not redeclare
113
+ * go into its code as they are; anything else is computed before the block into a temporary.
114
+ */
115
+ prop(attribute, component) {
116
+ const { value } = attribute;
117
+ if (value === null)
118
+ return 'true';
119
+ if (value.kind === 'EventHandler') {
120
+ const temp = this.temp();
121
+ this.line(`const ${temp} = ${this.handler(value)};`);
122
+ return temp;
123
+ }
124
+ return this.propValue(value, component);
125
+ }
126
+ propValue(value, component) {
127
+ // Arguments of a function component cannot be hidden by its names: they are not inlined.
128
+ let declared = this.functionComponents.has(component)
129
+ ? new Set()
130
+ : this.componentNames.get(component);
131
+ if (!declared) {
132
+ declared = declaredNames(component);
133
+ this.componentNames.set(component, declared);
134
+ }
135
+ const root = rootName(value);
136
+ if (isConstant(value) || (isSimple(value) && root !== null && !declared.has(root))) {
137
+ return this.expression(value, ARROW);
138
+ }
139
+ // A function given to the component runs later, not while the markup is being created.
140
+ const text = value.kind === 'ArrowFunction' || value.kind === 'FuncExpression'
141
+ ? this.withRendering(0, () => this.expression(value, ARROW))
142
+ : this.expression(value, ARROW);
143
+ const temp = this.temp();
144
+ this.line(`const ${temp} = ${text};`);
145
+ return temp;
146
+ }
147
+ /**
148
+ * `<Product {...product} />`: properties that the object has get their values from it. Later
149
+ * attributes override them. The object is computed once, before the component's block.
150
+ */
151
+ spreadProps(argument, component, live, values, reactiveProps) {
152
+ const type = this.typeOf(argument);
153
+ // Without a type, the object may have any of the properties.
154
+ const fields = type && type.kind !== 'any' && type.kind !== 'unknown' ? spreadFields(type) : null;
155
+ const params = component.params.filter((param) => param.name.name !== 'children' && (fields === null || fields.has(param.name.name)));
156
+ if (params.length === 0)
157
+ return;
158
+ const object = this.propValue(argument, component);
159
+ const sources = live?.dependencies(argument);
160
+ const liveObject = sources && sources.size > 0 ? this.liveExpression(argument, POSTFIX) : null;
161
+ for (const param of params) {
162
+ const { name } = param.name;
163
+ const read = `${object}.${name}`;
164
+ values.set(name, fields === null && param.defaultValue
165
+ ? `${read} ?? ${this.expression(param.defaultValue, POSTFIX)}`
166
+ : read);
167
+ if (sources && liveObject)
168
+ reactiveProps.set(name, [`${liveObject}.${name}`, sources]);
169
+ else
170
+ reactiveProps.delete(name);
171
+ }
172
+ }
173
+ }
@@ -0,0 +1,27 @@
1
+ import type * as ast from '../ast.ts';
2
+ import { ComponentPropsEmitter } from './component-props.ts';
3
+ import type { Live } from './reactive.ts';
4
+ /**
5
+ * Tags that take the component from a value: `<section.content title={title} />` calls the
6
+ * function of the component, `section.content(title)`, with the properties in the order of the
7
+ * type of the value, `comp(title string)`. Like the call of a function component, it returns the
8
+ * node and, when the parent's state changes a property, the function that sets them again. When
9
+ * the value itself depends on state, the component is created again each time it changes:
10
+ * `$$dynamic` keeps it between markers, in a block of its own.
11
+ */
12
+ export declare abstract class ComponentValueEmitter extends ComponentPropsEmitter {
13
+ /** Tags inside the blocks of `$$dynamic`: they call the component the block gets. */
14
+ private readonly fixedComponents;
15
+ protected valueTag(node: ast.ElementExpression, value: ast.Expression, live: Live | null): string;
16
+ /** `$$dynamic(() => page, ($$component3) => { ...; return [block, update]; })` */
17
+ private dynamicTag;
18
+ /** The call of the component; properties that depend on state are set again by its setter. */
19
+ private callValue;
20
+ /** The value of a property: literals and names as they are, other values in a temporary. */
21
+ private valueArgument;
22
+ /**
23
+ * A property of type `?T` may belong to one with a default value, which null must give: so null
24
+ * is passed as undefined, the value that takes the default.
25
+ */
26
+ private nullAsDefault;
27
+ }