rooklang 0.0.0-stage → 0.3.1

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 +195 -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 +105 -4
@@ -0,0 +1,164 @@
1
+ import { isKeyword } from "../lexer/token.js";
2
+ import { DecoratorParser } from "./decorators.js";
3
+ import { MODIFIERS } from "./syntax.js";
4
+ // Classes and their members, interfaces and `type` aliases.
5
+ export class ClassParser extends DecoratorParser {
6
+ parseClass(start, exported) {
7
+ this.expect('class');
8
+ const name = this.parseIdentifier('class name');
9
+ const typeParams = this.parseTypeParams();
10
+ let superClass = null;
11
+ if (this.accept('extends')) {
12
+ superClass = this.withContext({ noObjectLiteral: true }, () => this.parsePostfix(this.parsePrimary()));
13
+ }
14
+ const interfaces = [];
15
+ if (this.acceptWord('implements')) {
16
+ do {
17
+ const interfaceName = this.parseIdentifier('interface name');
18
+ interfaces.push({
19
+ kind: 'TypeReference',
20
+ name: interfaceName,
21
+ typeArgs: this.parseTypeArgs(),
22
+ ...this.span(interfaceName.start),
23
+ });
24
+ } while (this.accept(','));
25
+ }
26
+ this.expect('{');
27
+ const members = [];
28
+ this.withContext({ topLevel: false, inAsync: false }, () => {
29
+ this.parseSeparated(() => this.check('}'), () => {
30
+ members.push(...this.parseClassMember());
31
+ });
32
+ });
33
+ this.expect('}');
34
+ return {
35
+ kind: 'ClassDeclaration',
36
+ exported,
37
+ name,
38
+ typeParams,
39
+ superClass,
40
+ implements: interfaces,
41
+ members,
42
+ ...this.span(start),
43
+ };
44
+ }
45
+ parseClassMember() {
46
+ const start = this.peek().start;
47
+ let visibility = null;
48
+ let isStatic = false;
49
+ // Modifiers are contextual: `static` is a modifier only when a member name follows it.
50
+ while (this.peek().kind === 'Identifier' && MODIFIERS.has(this.peek().text)) {
51
+ const following = this.peek(1);
52
+ if (following.kind !== 'Identifier' && !isKeyword(following.kind))
53
+ break;
54
+ const modifier = this.next();
55
+ if (modifier.text === 'static') {
56
+ if (isStatic)
57
+ this.error('duplicate "static" modifier', modifier.start, modifier.end);
58
+ isStatic = true;
59
+ }
60
+ else {
61
+ if (visibility)
62
+ this.error('duplicate visibility modifier', modifier.start, modifier.end);
63
+ visibility = modifier.text;
64
+ }
65
+ }
66
+ // `async load()`; a method named `async` is `async()`.
67
+ const asyncToken = this.check('async') && this.peek(1).kind !== '(' ? this.next() : null;
68
+ const async = asyncToken !== null;
69
+ if (this.checkWord('constructor') && this.peek(1).kind === '(') {
70
+ this.next();
71
+ if (isStatic)
72
+ this.error('constructors cannot be static', start, this.span(start).end);
73
+ if (async)
74
+ this.error('a constructor cannot be async', start, this.span(start).end);
75
+ const params = this.parseParams(false);
76
+ const resultsStart = this.peek().start;
77
+ if (this.parseResults().length > 0) {
78
+ this.error('constructors cannot have result types', resultsStart, this.span(start).end);
79
+ }
80
+ const body = this.parseFunctionBody();
81
+ return [
82
+ {
83
+ kind: 'ConstructorDeclaration',
84
+ visibility: visibility ?? 'public',
85
+ params,
86
+ body,
87
+ ...this.span(start),
88
+ },
89
+ ];
90
+ }
91
+ const name = this.parsePropertyName('member name');
92
+ if (this.check('(')) {
93
+ const params = this.parseParams(false);
94
+ const results = this.parseResults();
95
+ const body = this.parseFunctionBody(async);
96
+ return [
97
+ {
98
+ kind: 'MethodDeclaration',
99
+ visibility: visibility ?? 'public',
100
+ isStatic,
101
+ ...(async ? { async } : {}),
102
+ name,
103
+ params,
104
+ results,
105
+ body,
106
+ ...this.span(start),
107
+ },
108
+ ];
109
+ }
110
+ if (asyncToken)
111
+ this.error('only methods can be async', asyncToken.start, asyncToken.end);
112
+ // Fields: `name string`, `count = 0`, `x, y number`.
113
+ const names = [name];
114
+ while (this.accept(','))
115
+ names.push(this.parsePropertyName('field name'));
116
+ const type = this.canStartType() ? this.parseType() : null;
117
+ const value = this.accept('=') ? this.parseExpression() : null;
118
+ const span = this.span(start);
119
+ if (type === null && value === null) {
120
+ this.error(`field "${name.name}" needs a type or a value`, span.start, span.end);
121
+ }
122
+ else if (names.length > 1 && value !== null) {
123
+ this.error('a value can only be given to a single field', span.start, span.end);
124
+ }
125
+ this.endStatement();
126
+ return names.map((fieldName) => ({
127
+ kind: 'FieldDeclaration',
128
+ visibility: visibility ?? 'public',
129
+ isStatic,
130
+ name: fieldName,
131
+ type,
132
+ value,
133
+ ...span,
134
+ }));
135
+ }
136
+ parseInterface(start, exported) {
137
+ this.expect('interface');
138
+ const name = this.parseIdentifier('interface name');
139
+ const typeParams = this.parseTypeParams();
140
+ const members = this.parseTypeMembers();
141
+ return {
142
+ kind: 'InterfaceDeclaration',
143
+ exported,
144
+ name,
145
+ typeParams,
146
+ members,
147
+ ...this.span(start),
148
+ };
149
+ }
150
+ parseTypeAlias(start, exported) {
151
+ this.expect('type');
152
+ const name = this.parseIdentifier('type name');
153
+ const typeParams = this.parseTypeParams();
154
+ const type = this.parseType();
155
+ return {
156
+ kind: 'TypeAliasDeclaration',
157
+ exported,
158
+ name,
159
+ typeParams,
160
+ type,
161
+ ...this.span(start),
162
+ };
163
+ }
164
+ }
@@ -0,0 +1,29 @@
1
+ import type * as ast from '../ast.ts';
2
+ import { StatementParser } from './statements.ts';
3
+ export declare abstract class ControlFlowParser extends StatementParser {
4
+ protected parseIf(): ast.IfStatement;
5
+ protected parseFor(): ast.ForStatement | ast.ForInStatement;
6
+ /** The rest of a `for` statement that starts at `start`, after the keyword. */
7
+ private parseForAfter;
8
+ /** `for x in` or `for i, x in`. */
9
+ protected isForInHeader(): boolean;
10
+ /** `{` (infinite loop), `cond {`, or `init; cond; update {`. */
11
+ protected parseForHeader(): [
12
+ ast.SimpleStatement | null,
13
+ ast.Expression | null,
14
+ ast.SimpleStatement | null
15
+ ];
16
+ protected parseForIn(start: number, go?: boolean): ast.ForInStatement;
17
+ /** `go for i, v in items { }`: the parts of the array run as goroutines, and the loop waits. */
18
+ protected parseGoFor(): ast.ForStatement | ast.ForInStatement;
19
+ protected parseLoopBody(): ast.BlockStatement;
20
+ protected parseSwitch(): ast.SwitchStatement;
21
+ /** `select { case v = <-ch: ... case ch <- v: ... default: ... }`; it waits, as `await` does. */
22
+ protected parseSelect(): ast.SelectStatement;
23
+ /** `v = <-ch`, `v, ok = <-ch`, `<-ch` or `ch <- v`; the names are new variables of the case. */
24
+ private parseSelectOperation;
25
+ protected parseBreakOrContinue(): ast.BreakStatement | ast.ContinueStatement;
26
+ protected parseThrow(): ast.ThrowStatement;
27
+ protected parseTry(): ast.TryStatement;
28
+ protected parseDefer(): ast.DeferStatement;
29
+ }
@@ -0,0 +1,232 @@
1
+ import { StatementParser } from "./statements.js";
2
+ // if, for, switch, break and continue, throw, try and defer.
3
+ export class ControlFlowParser extends StatementParser {
4
+ parseIf() {
5
+ const start = this.next().start;
6
+ const condition = this.parseHeaderExpression();
7
+ const consequent = this.parseBlock();
8
+ let alternate = null;
9
+ this.checkSameLine('else');
10
+ if (this.accept('else')) {
11
+ alternate = this.check('if') ? this.parseIf() : this.parseBlock();
12
+ }
13
+ return { kind: 'IfStatement', condition, consequent, alternate, ...this.span(start) };
14
+ }
15
+ parseFor() {
16
+ return this.parseForAfter(this.next().start);
17
+ }
18
+ /** The rest of a `for` statement that starts at `start`, after the keyword. */
19
+ parseForAfter(start) {
20
+ if (this.isForInHeader())
21
+ return this.parseForIn(start);
22
+ const [init, condition, update] = this.withContext({ noObjectLiteral: true }, () => this.parseForHeader());
23
+ const body = this.parseLoopBody();
24
+ return { kind: 'ForStatement', init, condition, update, body, ...this.span(start) };
25
+ }
26
+ /** `for x in` or `for i, x in`. */
27
+ isForInHeader() {
28
+ if (!this.check('Identifier'))
29
+ return false;
30
+ if (this.peek(1).kind === 'in')
31
+ return true;
32
+ return (this.peek(1).kind === ',' && this.peek(2).kind === 'Identifier' && this.peek(3).kind === 'in');
33
+ }
34
+ /** `{` (infinite loop), `cond {`, or `init; cond; update {`. */
35
+ parseForHeader() {
36
+ if (this.check('{'))
37
+ return [null, null, null];
38
+ const init = this.check(';') ? null : this.parseSimpleStatement();
39
+ if (init?.kind === 'ExpressionStatement' && this.check('{')) {
40
+ return [null, init.expression, null];
41
+ }
42
+ this.expect(';', '";" or "{"');
43
+ const condition = this.check(';') ? null : this.parseExpression();
44
+ this.expect(';');
45
+ const update = this.check('{') ? null : this.parseSimpleStatement();
46
+ return [init, condition, update];
47
+ }
48
+ parseForIn(start, go = false) {
49
+ let key = null;
50
+ let value = this.parseIdentifier('loop variable');
51
+ if (this.accept(',')) {
52
+ key = value;
53
+ value = this.parseIdentifier('loop variable');
54
+ }
55
+ this.expect('in');
56
+ const iterable = this.parseHeaderExpression();
57
+ if (!go) {
58
+ const body = this.parseLoopBody();
59
+ return { kind: 'ForInStatement', key, value, iterable, body, ...this.span(start) };
60
+ }
61
+ // The parts run at once in workers: nothing can leave the loop but `continue`.
62
+ const body = this.withContext({ inLoop: true, inBreakable: false, inGoFor: true }, () => this.parseBlock());
63
+ return { kind: 'ForInStatement', key, value, iterable, body, go, ...this.span(start) };
64
+ }
65
+ /** `go for i, v in items { }`: the parts of the array run as goroutines, and the loop waits. */
66
+ parseGoFor() {
67
+ const start = this.next().start;
68
+ const keyword = this.next();
69
+ this.requireAsync('go for', start, keyword.end);
70
+ if (this.isForInHeader())
71
+ return this.parseForIn(start, true);
72
+ this.error('"go for" goes over an array: write "go for i, v in items { ... }"', start, keyword.end);
73
+ return this.parseForAfter(start);
74
+ }
75
+ parseLoopBody() {
76
+ return this.withContext({ inLoop: true, inBreakable: true }, () => this.parseBlock());
77
+ }
78
+ parseSwitch() {
79
+ const start = this.next().start;
80
+ const discriminant = this.check('{') ? null : this.parseHeaderExpression();
81
+ this.expect('{');
82
+ const cases = [];
83
+ let hasDefault = false;
84
+ while (!this.check('}') && !this.check('EOF')) {
85
+ if (this.accept(';'))
86
+ continue;
87
+ const caseStart = this.peek().start;
88
+ let tests = [];
89
+ if (this.accept('default')) {
90
+ if (hasDefault) {
91
+ this.error('multiple "default" cases in switch', caseStart, this.span(caseStart).end);
92
+ }
93
+ hasDefault = true;
94
+ }
95
+ else {
96
+ this.expect('case', '"case", "default" or "}"');
97
+ tests = this.parseExpressionList();
98
+ }
99
+ this.expect(':');
100
+ const body = this.withContext({ topLevel: false, inBreakable: true }, () => this.parseStatements(() => this.check('case') || this.check('default') || this.check('}')));
101
+ cases.push({ kind: 'SwitchCase', tests, body, ...this.span(caseStart) });
102
+ }
103
+ this.expect('}');
104
+ return { kind: 'SwitchStatement', discriminant, cases, ...this.span(start) };
105
+ }
106
+ /** `select { case v = <-ch: ... case ch <- v: ... default: ... }`; it waits, as `await` does. */
107
+ parseSelect() {
108
+ const keyword = this.next();
109
+ this.requireAsync('select', keyword.start, keyword.end);
110
+ this.expect('{');
111
+ const cases = [];
112
+ let hasDefault = false;
113
+ while (!this.check('}') && !this.check('EOF')) {
114
+ if (this.accept(';'))
115
+ continue;
116
+ const caseStart = this.peek().start;
117
+ let names = [];
118
+ let operation = null;
119
+ if (this.accept('default')) {
120
+ if (hasDefault) {
121
+ this.error('multiple "default" cases in select', caseStart, this.span(caseStart).end);
122
+ }
123
+ hasDefault = true;
124
+ }
125
+ else {
126
+ this.expect('case', '"case", "default" or "}"');
127
+ [names, operation] = this.parseSelectOperation();
128
+ }
129
+ this.expect(':');
130
+ const body = this.withContext({ topLevel: false, inBreakable: true }, () => this.parseStatements(() => this.check('case') || this.check('default') || this.check('}')));
131
+ cases.push({ kind: 'SelectCase', names, operation, body, ...this.span(caseStart) });
132
+ }
133
+ this.expect('}');
134
+ return { kind: 'SelectStatement', cases, ...this.span(keyword.start) };
135
+ }
136
+ /** `v = <-ch`, `v, ok = <-ch`, `<-ch` or `ch <- v`; the names are new variables of the case. */
137
+ parseSelectOperation() {
138
+ const start = this.peek().start;
139
+ const names = [];
140
+ if (this.check('Identifier') && (this.peek(1).kind === '=' || this.peek(1).kind === ',')) {
141
+ do
142
+ names.push(this.parseIdentifier());
143
+ while (this.accept(','));
144
+ this.expect('=');
145
+ if (names.length > 2) {
146
+ this.error('a receive gives at most two values: "case v, ok = <-ch:"', start, this.span(start).end);
147
+ }
148
+ }
149
+ const first = this.parseExpression();
150
+ if (names.length === 0 && this.check('<-')) {
151
+ this.next();
152
+ const value = this.parseExpression();
153
+ return [names, { kind: 'SendStatement', channel: first, value, ...this.span(start) }];
154
+ }
155
+ if (first.kind !== 'UnaryExpression' || first.operator !== '<-') {
156
+ return this.failAt('a case of select receives, "case v = <-ch:", or sends, "case ch <- v:"', first.start, first.end);
157
+ }
158
+ return [names, first];
159
+ }
160
+ parseBreakOrContinue() {
161
+ const token = this.next();
162
+ let statement;
163
+ if (token.kind === 'break') {
164
+ if (!this.context.inBreakable) {
165
+ this.error(this.context.inGoFor
166
+ ? '"break" cannot stop "go for": its parts run at once in workers; skip an element with "continue"'
167
+ : '"break" outside of a loop or switch', token.start, token.end);
168
+ }
169
+ statement = { kind: 'BreakStatement', start: token.start, end: token.end };
170
+ }
171
+ else {
172
+ if (!this.context.inLoop)
173
+ this.error('"continue" outside of a loop', token.start, token.end);
174
+ statement = { kind: 'ContinueStatement', start: token.start, end: token.end };
175
+ }
176
+ this.endStatement();
177
+ return statement;
178
+ }
179
+ parseThrow() {
180
+ const start = this.next().start;
181
+ const argument = this.parseExpression();
182
+ const statement = { kind: 'ThrowStatement', argument, ...this.span(start) };
183
+ this.endStatement();
184
+ return statement;
185
+ }
186
+ parseTry() {
187
+ const start = this.next().start;
188
+ const block = this.parseBlock();
189
+ let handler = null;
190
+ let finalizer = null;
191
+ this.checkSameLine('catch');
192
+ if (this.check('catch')) {
193
+ const catchStart = this.next().start;
194
+ if (this.check('('))
195
+ this.fail('write "catch e {" without parentheses');
196
+ const param = this.check('Identifier') ? this.parseIdentifier() : null;
197
+ const body = this.parseBlock();
198
+ handler = { kind: 'CatchClause', param, body, ...this.span(catchStart) };
199
+ }
200
+ this.checkSameLine('finally');
201
+ if (this.accept('finally'))
202
+ finalizer = this.parseBlock();
203
+ if (handler === null && finalizer === null) {
204
+ this.error('"try" needs a "catch" or "finally" block', start, block.start);
205
+ }
206
+ return { kind: 'TryStatement', block, handler, finalizer, ...this.span(start) };
207
+ }
208
+ parseDefer() {
209
+ const start = this.next().start;
210
+ if (!this.context.inFunction) {
211
+ this.error('"defer" outside of a function', start, this.span(start).end);
212
+ }
213
+ else if (this.context.inGoFor) {
214
+ this.error('"defer" cannot be used in the body of "go for": it runs in workers, apart from the function; defer it before the loop', start, this.span(start).end);
215
+ }
216
+ if (this.check('{')) {
217
+ const body = this.withContext({ inDefer: true, inAsync: false, inLoop: false, inBreakable: false }, () => this.parseBlock());
218
+ return { kind: 'DeferStatement', body, ...this.span(start) };
219
+ }
220
+ const call = this.withContext({ inDefer: true, inAsync: false }, () => this.parseExpression());
221
+ if (call.kind !== 'CallExpression') {
222
+ this.failAt('"defer" needs a function call or a block', call.start, call.end);
223
+ }
224
+ const statement = {
225
+ kind: 'DeferStatement',
226
+ body: call,
227
+ ...this.span(start),
228
+ };
229
+ this.endStatement();
230
+ return statement;
231
+ }
232
+ }
@@ -0,0 +1,27 @@
1
+ import type * as ast from '../ast.ts';
2
+ import { ControlFlowParser } from './control-flow.ts';
3
+ export declare abstract class DeclarationParser extends ControlFlowParser {
4
+ protected parseImport(): ast.ImportDeclaration;
5
+ protected parseImportSpecifier(): ast.ImportSpecifier;
6
+ protected parseExport(): ast.Statement;
7
+ protected parseFuncDeclaration(start: number, exported: boolean): ast.FuncDeclaration;
8
+ /**
9
+ * `<T any, U Shape>` after a name; `<K, V any>` gives both the constraint, as in Go.
10
+ */
11
+ protected parseTypeParams(): ast.TypeParameter[];
12
+ /**
13
+ * `(a, b number, c string)`. Names without a type take the type of the next typed name, as in
14
+ * Go; only arrow functions may leave types out entirely.
15
+ */
16
+ protected parseParams(typesOptional: boolean, allowDefaults?: boolean, allowRest?: boolean): ast.Parameter[];
17
+ /** `...attrs`: the attributes that a component passes on to one of its elements. */
18
+ private parseRestParam;
19
+ /** Result types after a parameter list: nothing, `T`, or `(T1, T2)`. */
20
+ protected parseResults(): ast.TypeNode[];
21
+ /** `comp Name(properties) { ...; return <markup> }`, maybe after decorators. */
22
+ protected parseComponent(start: number, exported: boolean, htmlTag?: ast.HtmlTag | null, decorators?: ast.DecoratorUse[]): ast.ComponentDeclaration;
23
+ /** Like a function body, but its own statements may also declare `state`, `ref` and `mount()`. */
24
+ protected parseComponentBody(): ast.BlockStatement;
25
+ /** A statement at the top level of a component or a decorator. */
26
+ protected parseComponentStatement(): ast.Statement;
27
+ }