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,97 @@
1
+ import { MarkupLexer } from "./markup.js";
2
+ /**
3
+ * The start of a declaration: a property name, a colon and then a space or a value, `color: ` or
4
+ * `color:{`. With a name right after the colon it is a selector, `a:hover`, so `{` there opens a
5
+ * nested rule.
6
+ */
7
+ const DECLARATION = /^\s*-{0,2}[a-zA-Z_][\w-]*\s*:(?:\s|[^\w\-:\\]|$)/;
8
+ export class StyleLexer extends MarkupLexer {
9
+ /**
10
+ * `style {` at the start of a statement starts CSS: the identifier `style` has just been read at
11
+ * `start`. Elsewhere `style` is an ordinary name.
12
+ */
13
+ startStyle(start) {
14
+ const before = this.tokens.at(-2);
15
+ const startsStatement = before === undefined || before.kind === ';' || before.kind === '{' || before.kind === '}';
16
+ const brace = /^[ \t]*\{/.exec(this.text.slice(this.pos));
17
+ if (!startsStatement || !brace)
18
+ return;
19
+ const open = this.pos + brace[0].length - 1;
20
+ this.push('{', open, open + 1);
21
+ this.modes.push({ kind: 'css', start, depth: 0, item: '' });
22
+ }
23
+ /** CSS text up to a value from code or to the `}` that closes the block. */
24
+ scanCss(mode) {
25
+ const t = this.text;
26
+ const start = this.pos;
27
+ let i = start;
28
+ const flush = (end) => {
29
+ if (end > start) {
30
+ const text = t.slice(start, end);
31
+ this.tokens.push({ kind: 'CssText', value: text, text, start, end });
32
+ }
33
+ };
34
+ while (i < t.length) {
35
+ const c = t[i];
36
+ if (c === '/' && t[i + 1] === '*') {
37
+ const end = t.indexOf('*/', i + 2);
38
+ if (end === -1) {
39
+ this.error('unterminated comment in CSS', i, i + 2);
40
+ i = t.length;
41
+ }
42
+ else {
43
+ i = end + 2;
44
+ }
45
+ }
46
+ else if (c === '"' || c === "'") {
47
+ const end = this.cssStringEnd(i);
48
+ mode.item += t.slice(i, end);
49
+ i = end;
50
+ }
51
+ else if (c === '{' && mode.depth > 0 && DECLARATION.test(mode.item)) {
52
+ // A value from code: the item gets a stand-in, so that the next `{` is a value too.
53
+ flush(i);
54
+ this.push('{', i, i + 1);
55
+ mode.item += '0';
56
+ this.modes.push({ kind: 'expression', braces: 0 });
57
+ return;
58
+ }
59
+ else if (c === '{') {
60
+ mode.depth++;
61
+ mode.item = '';
62
+ i++;
63
+ }
64
+ else if (c === '}' && mode.depth === 0) {
65
+ flush(i);
66
+ this.push('}', i, i + 1);
67
+ this.modes.pop();
68
+ return;
69
+ }
70
+ else if (c === '}' || c === ';') {
71
+ if (c === '}')
72
+ mode.depth--;
73
+ mode.item = '';
74
+ i++;
75
+ }
76
+ else {
77
+ mode.item += c;
78
+ i++;
79
+ }
80
+ }
81
+ flush(i);
82
+ this.pos = i;
83
+ }
84
+ /** The end of a CSS string that starts at `start`, after its closing quote. */
85
+ cssStringEnd(start) {
86
+ const t = this.text;
87
+ const quote = t[start];
88
+ let i = start + 1;
89
+ while (i < t.length && t[i] !== quote && t[i] !== '\n')
90
+ i += t[i] === '\\' ? 2 : 1;
91
+ if (t[i] !== quote) {
92
+ this.error('unterminated string in CSS', start, i);
93
+ return i;
94
+ }
95
+ return i + 1;
96
+ }
97
+ }
@@ -0,0 +1,53 @@
1
+ import type { TokenKind } from './token.ts';
2
+ /**
3
+ * A line break after one of these tokens ends the statement, so the lexer inserts a semicolon
4
+ * there (the same rule as in Go).
5
+ */
6
+ export declare const ENDS_STATEMENT: ReadonlySet<TokenKind>;
7
+ /**
8
+ * Tokens that end a value: after them `<` means "less than", elsewhere it starts markup. The
9
+ * language has no `<...>` generics or casts, so this is never ambiguous.
10
+ */
11
+ export declare const ENDS_VALUE: ReadonlySet<TokenKind>;
12
+ /** Tag and attribute names: `div`, `my-widget`, `aria-label`, `bind:value`. */
13
+ export declare const JSX_NAME: RegExp;
14
+ export declare const ENTITIES: Readonly<Record<string, string>>;
15
+ /** Decodes HTML entities in markup text: `&amp;`, `&#169;`, `&#xA9;`. */
16
+ export declare function decodeEntities(text: string): string;
17
+ export declare const IDENTIFIER: RegExp;
18
+ export declare const SIMPLE_ESCAPES: Readonly<Record<string, string>>;
19
+ export type CharTest = (c: string | undefined) => boolean;
20
+ export declare const isDigit: CharTest;
21
+ export declare const isHexDigit: CharTest;
22
+ export declare const isOctalDigit: CharTest;
23
+ export declare const isBinaryDigit: CharTest;
24
+ /**
25
+ * What the lexer is inside of, innermost last. `start` is where the template or element begins,
26
+ * for error messages; `braces` counts unclosed `{` inside a substitution or expression.
27
+ */
28
+ export type Mode = {
29
+ kind: 'template';
30
+ start: number;
31
+ braces: number;
32
+ } | {
33
+ kind: 'expression';
34
+ braces: number;
35
+ } | {
36
+ kind: 'tag';
37
+ start: number;
38
+ } | {
39
+ kind: 'content';
40
+ start: number;
41
+ } | {
42
+ kind: 'closingTag';
43
+ start: number;
44
+ } | {
45
+ kind: 'css';
46
+ start: number;
47
+ depth: number;
48
+ item: string;
49
+ };
50
+ export type MarkupMode = Extract<Mode, {
51
+ kind: 'tag' | 'content' | 'closingTag';
52
+ }>;
53
+ export declare function isMarkup(mode: Mode | undefined): mode is MarkupMode;
@@ -0,0 +1,101 @@
1
+ // Tables of the lexer: which tokens end a statement or a value, entities, escapes, modes.
2
+ /**
3
+ * A line break after one of these tokens ends the statement, so the lexer inserts a semicolon
4
+ * there (the same rule as in Go).
5
+ */
6
+ export const ENDS_STATEMENT = new Set([
7
+ 'Identifier',
8
+ 'Number',
9
+ 'BigInt',
10
+ 'String',
11
+ 'Template',
12
+ 'TemplateTail',
13
+ 'true',
14
+ 'false',
15
+ 'null',
16
+ 'this',
17
+ 'return',
18
+ 'break',
19
+ 'continue',
20
+ '++',
21
+ '--',
22
+ ')',
23
+ ']',
24
+ '}',
25
+ 'JsxTagEnd',
26
+ 'JsxSelfClose',
27
+ ]);
28
+ /**
29
+ * Tokens that end a value: after them `<` means "less than", elsewhere it starts markup. The
30
+ * language has no `<...>` generics or casts, so this is never ambiguous.
31
+ */
32
+ export const ENDS_VALUE = new Set([
33
+ 'Identifier',
34
+ 'Number',
35
+ 'BigInt',
36
+ 'String',
37
+ 'Template',
38
+ 'TemplateTail',
39
+ 'true',
40
+ 'false',
41
+ 'null',
42
+ 'this',
43
+ 'super',
44
+ '++',
45
+ '--',
46
+ ')',
47
+ ']',
48
+ '}',
49
+ 'JsxTagEnd',
50
+ 'JsxSelfClose',
51
+ ]);
52
+ /** Tag and attribute names: `div`, `my-widget`, `aria-label`, `bind:value`. */
53
+ export const JSX_NAME = /[\p{ID_Start}$_][\p{ID_Continue}$\-:.]*/uy;
54
+ export const ENTITIES = {
55
+ amp: '&',
56
+ lt: '<',
57
+ gt: '>',
58
+ quot: '"',
59
+ apos: "'",
60
+ nbsp: '\u00a0',
61
+ copy: '©',
62
+ times: '×',
63
+ middot: '·',
64
+ hellip: '…',
65
+ mdash: '—',
66
+ ndash: '–',
67
+ laquo: '«',
68
+ raquo: '»',
69
+ };
70
+ /** Decodes HTML entities in markup text: `&amp;`, `&#169;`, `&#xA9;`. */
71
+ export function decodeEntities(text) {
72
+ return text.replace(/&(#x[0-9a-fA-F]+|#[0-9]+|[a-zA-Z]+);/g, (entity, name) => {
73
+ if (name.startsWith('#')) {
74
+ const code = name[1] === 'x' ? parseInt(name.slice(2), 16) : parseInt(name.slice(1), 10);
75
+ return code <= 0x10ffff ? String.fromCodePoint(code) : entity;
76
+ }
77
+ return Object.hasOwn(ENTITIES, name) ? ENTITIES[name] : entity;
78
+ });
79
+ }
80
+ export const IDENTIFIER = /[\p{ID_Start}$_][\p{ID_Continue}$‌‍]*/uy;
81
+ export const SIMPLE_ESCAPES = {
82
+ n: '\n',
83
+ t: '\t',
84
+ r: '\r',
85
+ b: '\b',
86
+ f: '\f',
87
+ v: '\v',
88
+ '0': '\0',
89
+ '\\': '\\',
90
+ "'": "'",
91
+ '"': '"',
92
+ '`': '`',
93
+ $: '$',
94
+ };
95
+ export const isDigit = (c) => c !== undefined && c >= '0' && c <= '9';
96
+ export const isHexDigit = (c) => c !== undefined && /^[0-9a-fA-F]$/.test(c);
97
+ export const isOctalDigit = (c) => c !== undefined && c >= '0' && c <= '7';
98
+ export const isBinaryDigit = (c) => c === '0' || c === '1';
99
+ export function isMarkup(mode) {
100
+ return mode?.kind === 'tag' || mode?.kind === 'content' || mode?.kind === 'closingTag';
101
+ }
@@ -0,0 +1,42 @@
1
+ export declare const KEYWORDS: readonly ["func", "comp", "go", "chan", "return", "let", "const", "type", "interface", "class", "extends", "new", "this", "super", "if", "else", "for", "in", "break", "continue", "switch", "case", "default", "defer", "try", "catch", "finally", "throw", "import", "export", "null", "true", "false", "typeof", "instanceof", "async", "await", "map"];
2
+ export declare const PUNCTUATORS: readonly ["{", "}", "(", ")", "[", "]", ";", ",", ":", ".", "...", "?", "?.", "??", "=>", "=", "+=", "-=", "*=", "/=", "%=", "**=", "&=", "|=", "^=", "<<=", ">>=", ">>>=", "&&=", "||=", "??=", "==", "!=", "<", "<-", ">", "<=", ">=", "+", "-", "*", "/", "%", "**", "++", "--", "&", "|", "^", "~", "<<", ">>", ">>>", "&&", "||", "!", "@"];
3
+ export type Keyword = (typeof KEYWORDS)[number];
4
+ export type Punctuator = (typeof PUNCTUATORS)[number];
5
+ /**
6
+ * Token kinds whose `value` holds string contents. Template literals are split around
7
+ * substitutions: `a${x}b${y}c` becomes TemplateHead("a") x TemplateMiddle("b") y TemplateTail("c"),
8
+ * and a template without substitutions is a single Template token. In markup, JsxText is the text
9
+ * between tags and JsxString an attribute value in quotes; both have HTML entities decoded. CssText is
10
+ * the raw text of a `style { ... }` block between the values from code.
11
+ */
12
+ export type StringKind = 'String' | 'Template' | 'TemplateHead' | 'TemplateMiddle' | 'TemplateTail' | 'JsxText' | 'JsxString' | 'CssText';
13
+ /**
14
+ * Tokens of markup such as `<a href="/">text</a>`: JsxTagOpen `<`, JsxCloseTagOpen `</`, JsxName
15
+ * (tag and attribute names, which may contain `-` and `:`), JsxTagEnd `>` and JsxSelfClose `/>`.
16
+ * Expressions inside markup use the ordinary `{`, `}` and `=` tokens.
17
+ */
18
+ export type JsxKind = 'JsxTagOpen' | 'JsxCloseTagOpen' | 'JsxName' | 'JsxTagEnd' | 'JsxSelfClose';
19
+ /** Keywords and punctuators use their own text as the kind, e.g. `func` or `+=`. */
20
+ export type TokenKind = 'Identifier' | 'Number' | 'BigInt' | StringKind | JsxKind | 'EOF' | Keyword | Punctuator;
21
+ interface TokenBase {
22
+ /** Source text. Empty for automatically inserted semicolons and EOF. */
23
+ text: string;
24
+ start: number;
25
+ end: number;
26
+ }
27
+ export interface NumberToken extends TokenBase {
28
+ kind: 'Number';
29
+ value: number;
30
+ }
31
+ export interface StringToken extends TokenBase {
32
+ kind: StringKind;
33
+ /** Contents with escapes resolved, without quotes and `${` / `}` delimiters. */
34
+ value: string;
35
+ }
36
+ export interface SimpleToken extends TokenBase {
37
+ kind: Exclude<TokenKind, 'Number' | StringKind>;
38
+ }
39
+ export type Token = NumberToken | StringToken | SimpleToken;
40
+ export declare function isKeyword(word: string): word is Keyword;
41
+ export declare function isPunctuator(text: string): text is Punctuator;
42
+ export {};
@@ -0,0 +1,108 @@
1
+ export const KEYWORDS = [
2
+ 'func',
3
+ 'comp',
4
+ 'go',
5
+ 'chan',
6
+ 'return',
7
+ 'let',
8
+ 'const',
9
+ 'type',
10
+ 'interface',
11
+ 'class',
12
+ 'extends',
13
+ 'new',
14
+ 'this',
15
+ 'super',
16
+ 'if',
17
+ 'else',
18
+ 'for',
19
+ 'in',
20
+ 'break',
21
+ 'continue',
22
+ 'switch',
23
+ 'case',
24
+ 'default',
25
+ 'defer',
26
+ 'try',
27
+ 'catch',
28
+ 'finally',
29
+ 'throw',
30
+ 'import',
31
+ 'export',
32
+ 'null',
33
+ 'true',
34
+ 'false',
35
+ 'typeof',
36
+ 'instanceof',
37
+ 'async',
38
+ 'await',
39
+ // Reserved for future use.
40
+ 'map',
41
+ ];
42
+ export const PUNCTUATORS = [
43
+ '{',
44
+ '}',
45
+ '(',
46
+ ')',
47
+ '[',
48
+ ']',
49
+ ';',
50
+ ',',
51
+ ':',
52
+ '.',
53
+ '...',
54
+ '?',
55
+ '?.',
56
+ '??',
57
+ '=>',
58
+ '=',
59
+ '+=',
60
+ '-=',
61
+ '*=',
62
+ '/=',
63
+ '%=',
64
+ '**=',
65
+ '&=',
66
+ '|=',
67
+ '^=',
68
+ '<<=',
69
+ '>>=',
70
+ '>>>=',
71
+ '&&=',
72
+ '||=',
73
+ '??=',
74
+ '==',
75
+ '!=',
76
+ '<',
77
+ '<-',
78
+ '>',
79
+ '<=',
80
+ '>=',
81
+ '+',
82
+ '-',
83
+ '*',
84
+ '/',
85
+ '%',
86
+ '**',
87
+ '++',
88
+ '--',
89
+ '&',
90
+ '|',
91
+ '^',
92
+ '~',
93
+ '<<',
94
+ '>>',
95
+ '>>>',
96
+ '&&',
97
+ '||',
98
+ '!',
99
+ '@',
100
+ ];
101
+ const KEYWORD_SET = new Set(KEYWORDS);
102
+ const PUNCTUATOR_SET = new Set(PUNCTUATORS);
103
+ export function isKeyword(word) {
104
+ return KEYWORD_SET.has(word);
105
+ }
106
+ export function isPunctuator(text) {
107
+ return PUNCTUATOR_SET.has(text);
108
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/loader.js ADDED
@@ -0,0 +1,50 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { registerHooks } from 'node:module';
4
+ import { join } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { isMainThread } from 'node:worker_threads';
7
+ import { displayPath } from "./build.js";
8
+ import { compileFile } from "./compile-file.js";
9
+ // `rook run` imports this module first (`node --import`): Node then imports `.rk` files,
10
+ // compiled when they load, and `app.rk?goroutines` is the worker module of `go` in app.rk.
11
+ // The worker threads of `go` import it too, since they get the `--import` of the process. The main
12
+ // thread compiles a module before any worker needs it, so it leaves the code of each module and
13
+ // of its worker module in ROOK_RUN_CACHE, a directory of the run, and the workers take it from
14
+ // there: compiling again, with the types, would take each of them as long. ROOK_NO_CHECK turns
15
+ // type checking off, and ROOK_MARKUP, 1 or 0, markup and components on or off for every file.
16
+ const typeCheck = process.env['ROOK_NO_CHECK'] === undefined;
17
+ const markupSetting = process.env['ROOK_MARKUP'];
18
+ const markup = markupSetting === undefined ? undefined : markupSetting === '1';
19
+ const cache = process.env['ROOK_RUN_CACHE'];
20
+ /** The file of the cache for the code of a URL, query included. */
21
+ function cached(url) {
22
+ return cache ? join(cache, `${createHash('sha1').update(url).digest('hex')}.js`) : null;
23
+ }
24
+ registerHooks({
25
+ load(url, context, nextLoad) {
26
+ const { protocol, pathname, search } = new URL(url);
27
+ if (protocol !== 'file:' || !pathname.endsWith('.rk'))
28
+ return nextLoad(url, context);
29
+ const file = cached(url);
30
+ if (!isMainThread && file && existsSync(file)) {
31
+ return { format: 'module', source: readFileSync(file, 'utf8'), shortCircuit: true };
32
+ }
33
+ const moduleUrl = new URL(pathname, url).href;
34
+ const path = displayPath(fileURLToPath(moduleUrl));
35
+ const result = compileFile(path, {
36
+ rewriteImports: false,
37
+ typeCheck,
38
+ markup,
39
+ quiet: !isMainThread,
40
+ });
41
+ if (isMainThread && cache) {
42
+ writeFileSync(cached(moduleUrl), result.code);
43
+ if (result.worker !== undefined) {
44
+ writeFileSync(cached(`${moduleUrl}?goroutines`), result.worker);
45
+ }
46
+ }
47
+ const source = search === '?goroutines' ? (result.worker ?? '') : result.code;
48
+ return { format: 'module', source, shortCircuit: true };
49
+ },
50
+ });
@@ -0,0 +1,5 @@
1
+ import type { Type } from './checker/types.ts';
2
+ /** Array methods that change the array. */
3
+ export declare const ARRAY_MUTATORS: ReadonlySet<string>;
4
+ /** Whether calling `method` may change a value of this type. */
5
+ export declare function mayChange(type: Type | undefined, method: string): boolean;
@@ -0,0 +1,81 @@
1
+ // Which methods change the value they are called on and which only read it. The generator updates
2
+ // markup after changes; the checker forbids changes of values that are read-only.
3
+ /** Array methods that change the array. */
4
+ export const ARRAY_MUTATORS = new Set([
5
+ 'copyWithin',
6
+ 'fill',
7
+ 'pop',
8
+ 'push',
9
+ 'reverse',
10
+ 'shift',
11
+ 'sort',
12
+ 'splice',
13
+ 'unshift',
14
+ ]);
15
+ /** Methods known to only read, for values that are not arrays or whose type is not known. */
16
+ const READ_METHODS = new Set([
17
+ 'at',
18
+ 'charAt',
19
+ 'concat',
20
+ 'endsWith',
21
+ 'entries',
22
+ 'every',
23
+ 'filter',
24
+ 'find',
25
+ 'findIndex',
26
+ 'findLast',
27
+ 'findLastIndex',
28
+ 'flat',
29
+ 'flatMap',
30
+ 'forEach',
31
+ 'getTime',
32
+ 'includes',
33
+ 'indexOf',
34
+ 'join',
35
+ 'keys',
36
+ 'lastIndexOf',
37
+ 'map',
38
+ 'padEnd',
39
+ 'padStart',
40
+ 'reduce',
41
+ 'reduceRight',
42
+ 'repeat',
43
+ 'replace',
44
+ 'replaceAll',
45
+ 'slice',
46
+ 'some',
47
+ 'split',
48
+ 'startsWith',
49
+ 'substring',
50
+ 'toFixed',
51
+ 'toISOString',
52
+ 'toLocaleDateString',
53
+ 'toLocaleString',
54
+ 'toLocaleTimeString',
55
+ 'toLowerCase',
56
+ 'toReversed',
57
+ 'toSorted',
58
+ 'toSpliced',
59
+ 'toString',
60
+ 'toUpperCase',
61
+ 'trim',
62
+ 'trimEnd',
63
+ 'trimStart',
64
+ 'valueOf',
65
+ 'values',
66
+ 'with',
67
+ ]);
68
+ /** Whether calling `method` may change a value of this type. */
69
+ export function mayChange(type, method) {
70
+ const known = type?.kind === 'nullable' ? type.type : type;
71
+ switch (known?.kind) {
72
+ case 'string':
73
+ case 'number':
74
+ case 'bool':
75
+ return false;
76
+ case 'array':
77
+ return ARRAY_MUTATORS.has(method);
78
+ default:
79
+ return ARRAY_MUTATORS.has(method) || !READ_METHODS.has(method);
80
+ }
81
+ }
@@ -0,0 +1,3 @@
1
+ import { type ImportResult } from './checker/checker.ts';
2
+ /** Finds the types exported by a `.rk` module imported from the file `fromFile`. */
3
+ export declare function loadModuleExports(fromFile: string, specifier: string, markup?: boolean): ImportResult;
@@ -0,0 +1,49 @@
1
+ import { readFileSync, statSync } from 'node:fs';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { check } from "./checker/checker.js";
4
+ import { markupFor } from "./config.js";
5
+ import { parse } from "./parser/parser.js";
6
+ import { importDeclarations, libraryFor } from "./typescript/importer.js";
7
+ /** Exports of checked modules, by path; reused while the file does not change. */
8
+ const cache = new Map();
9
+ const loading = new Set();
10
+ /** Finds the types exported by a `.rk` module imported from the file `fromFile`. */
11
+ export function loadModuleExports(fromFile, specifier, markup) {
12
+ if (!specifier.startsWith('./') && !specifier.startsWith('../'))
13
+ return undefined;
14
+ const path = resolve(dirname(fromFile), specifier);
15
+ let version;
16
+ try {
17
+ const stats = statSync(path);
18
+ version = `${stats.mtimeMs}:${stats.size}`;
19
+ }
20
+ catch {
21
+ return { error: `cannot find module "${specifier}"` };
22
+ }
23
+ const cached = cache.get(path);
24
+ if (cached?.version === version)
25
+ return { exports: cached.exports };
26
+ // An import cycle: the module is being checked further up the chain, so it is untyped here.
27
+ if (loading.has(path))
28
+ return undefined;
29
+ loading.add(path);
30
+ try {
31
+ // The markup of the CLI or the Vite plugin, else that of the package of the module.
32
+ const { program, diagnostics } = parse(readFileSync(path, 'utf8'), {
33
+ markup: markup ?? markupFor(path),
34
+ });
35
+ // Syntax errors in the imported module are reported when that module itself is compiled.
36
+ if (diagnostics.length > 0)
37
+ return undefined;
38
+ const { exports } = check(program, {
39
+ importModule: (next) => loadModuleExports(path, next, markup),
40
+ importDeclarations: (next) => importDeclarations(path, next),
41
+ library: libraryFor(path),
42
+ });
43
+ cache.set(path, { version, exports });
44
+ return { exports };
45
+ }
46
+ finally {
47
+ loading.delete(path);
48
+ }
49
+ }
@@ -0,0 +1,23 @@
1
+ import type * as ast from './ast.ts';
2
+ /** Names assigned anywhere inside `node`: `x = ...`, `x += ...`, `x++`. */
3
+ export declare function assignedNames(node: ast.Node, names?: Set<string>): Set<string>;
4
+ /** Whether an identifier with one of `names` occurs in `node`, whatever it refers to. */
5
+ export declare function mentionsName(node: ast.Node, names: ReadonlySet<string>): boolean;
6
+ /** Every name declared inside `node`: parameters and all local declarations, nested ones too. */
7
+ export declare function declaredNames(node: ast.Node): Set<string>;
8
+ /** Names a component or a decorator uses as values but does not declare: those come from the module. */
9
+ export declare function freeNames(component: {
10
+ params: readonly ast.Parameter[];
11
+ body: ast.BlockStatement;
12
+ }): Set<string>;
13
+ /** Names declared directly in a list of statements: they hide outer names in the whole block. */
14
+ export declare function declaredIn(statements: readonly ast.Statement[]): string[];
15
+ /** Names declared at the top level of a module, imports included: what its code can use. */
16
+ export declare function topLevelNames(program: ast.Program): Set<string>;
17
+ /**
18
+ * Names used as values, as opposed to declared names, property names and types. A capitalized tag
19
+ * is a value unless `isComponent` says it names a component: `<Page />` with a variable `Page`.
20
+ */
21
+ export declare function collectValueNames(node: ast.Node, names: Set<string>, isComponent?: (name: string) => boolean): void;
22
+ /** The components that the code in `node` uses as values: `content: Intro`. */
23
+ export declare function componentValues(node: ast.Node, isComponent: (name: string) => boolean): string[];