aontu 0.63.0 → 0.65.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 (101) hide show
  1. package/README.md +8 -8
  2. package/dist/agentsmd.js +3 -3
  3. package/dist/agentsmd.js.map +1 -1
  4. package/dist/aontu.d.ts +3 -3
  5. package/dist/aontu.js +4 -6
  6. package/dist/aontu.js.map +1 -1
  7. package/dist/aontumodel.js +6 -12
  8. package/dist/aontumodel.js.map +1 -1
  9. package/dist/casing.d.ts +5 -0
  10. package/dist/casing.js +90 -0
  11. package/dist/casing.js.map +1 -0
  12. package/dist/cli.d.ts +16 -3
  13. package/dist/cli.js +653 -455
  14. package/dist/cli.js.map +1 -1
  15. package/dist/compat.d.ts +7 -0
  16. package/dist/compat.js +113 -0
  17. package/dist/compat.js.map +1 -0
  18. package/dist/helpdoc.js +5 -5
  19. package/dist/helpdoc.js.map +1 -1
  20. package/dist/hints.js +14 -5
  21. package/dist/hints.js.map +1 -1
  22. package/dist/lang.d.ts +1 -0
  23. package/dist/lang.js +8 -0
  24. package/dist/lang.js.map +1 -1
  25. package/dist/lsp.d.ts +1 -1
  26. package/dist/mcp.js +0 -36
  27. package/dist/mcp.js.map +1 -1
  28. package/dist/mod.d.ts +18 -3
  29. package/dist/mod.js +117 -46
  30. package/dist/mod.js.map +1 -1
  31. package/dist/pkg-net.d.ts +227 -0
  32. package/dist/pkg-net.js +1598 -0
  33. package/dist/pkg-net.js.map +1 -0
  34. package/dist/pkg-zip.d.ts +8 -0
  35. package/dist/pkg-zip.js +196 -0
  36. package/dist/pkg-zip.js.map +1 -0
  37. package/dist/pkg.d.ts +159 -0
  38. package/dist/pkg.js +767 -0
  39. package/dist/pkg.js.map +1 -0
  40. package/dist/profile.d.ts +9 -0
  41. package/dist/profile.js +28 -0
  42. package/dist/profile.js.map +1 -0
  43. package/dist/report-sarif.js +1 -1
  44. package/dist/report-sarif.js.map +1 -1
  45. package/dist/subsume.d.ts +3 -1
  46. package/dist/subsume.js +2 -0
  47. package/dist/subsume.js.map +1 -1
  48. package/dist/trace.d.ts +21 -0
  49. package/dist/trace.js +107 -0
  50. package/dist/trace.js.map +1 -0
  51. package/dist/tsconfig.tsbuildinfo +1 -1
  52. package/dist/unify.js +1 -6
  53. package/dist/unify.js.map +1 -1
  54. package/dist/val/CmpFuncVal.d.ts +2 -0
  55. package/dist/val/CmpFuncVal.js +47 -13
  56. package/dist/val/CmpFuncVal.js.map +1 -1
  57. package/dist/val/NomFuncVal.js +11 -13
  58. package/dist/val/NomFuncVal.js.map +1 -1
  59. package/dist/val/ReferFuncVal.js +3 -0
  60. package/dist/val/ReferFuncVal.js.map +1 -1
  61. package/package.json +1 -1
  62. package/skill/SKILL.md +3 -3
  63. package/skill/error-codes.md +4 -4
  64. package/skill/examples.md +4 -4
  65. package/skill/grammar-card.md +1 -1
  66. package/skill/init/check.sh +2 -2
  67. package/skill/tasks.md +14 -12
  68. package/src/agentsmd.ts +3 -3
  69. package/src/aontu.ts +3 -8
  70. package/src/aontumodel.ts +6 -12
  71. package/src/casing.ts +95 -0
  72. package/src/cli.ts +758 -495
  73. package/src/compat.ts +148 -0
  74. package/src/helpdoc.ts +5 -5
  75. package/src/hints.ts +14 -7
  76. package/src/lang.ts +9 -1
  77. package/src/mcp.ts +0 -39
  78. package/src/mod.ts +142 -51
  79. package/src/pkg-net.ts +1945 -0
  80. package/src/pkg-zip.ts +228 -0
  81. package/src/pkg.ts +1018 -0
  82. package/src/profile.ts +42 -0
  83. package/src/report-sarif.ts +1 -1
  84. package/src/subsume.ts +2 -2
  85. package/src/trace.ts +157 -0
  86. package/src/unify.ts +1 -6
  87. package/src/val/CmpFuncVal.ts +66 -20
  88. package/src/val/NomFuncVal.ts +3 -5
  89. package/src/val/ReferFuncVal.ts +4 -0
  90. package/dist/lower.d.ts +0 -23
  91. package/dist/lower.js +0 -528
  92. package/dist/lower.js.map +0 -1
  93. package/dist/mod-tool.d.ts +0 -58
  94. package/dist/mod-tool.js +0 -403
  95. package/dist/mod-tool.js.map +0 -1
  96. package/dist/render.d.ts +0 -53
  97. package/dist/render.js +0 -432
  98. package/dist/render.js.map +0 -1
  99. package/src/lower.ts +0 -586
  100. package/src/mod-tool.ts +0 -561
  101. package/src/render.ts +0 -580
package/src/lower.ts DELETED
@@ -1,586 +0,0 @@
1
- /* Copyright (c) 2025 Richard Rodger, MIT License */
2
-
3
-
4
- import { exactJSON } from './exactjson'
5
- import type { RenderLoss } from './render'
6
-
7
-
8
- // The lowering's view of one unit: the merged profile, the family it
9
- // names, and the report the losses go to.
10
- export type LowerCtx = {
11
- profile: any
12
- family: string
13
- unit: string
14
- lossy: RenderLoss[]
15
- }
16
-
17
-
18
- function ln(at: number, text: string): any {
19
- return { k: 'line', at, n: [text] }
20
- }
21
-
22
- const BLANK = { k: 'blank' }
23
-
24
-
25
- // --- identifiers -------------------------------------------------------
26
-
27
- function isUpper(c: string): boolean {
28
- return 'A' <= c && c <= 'Z'
29
- }
30
-
31
- function isLower(c: string): boolean {
32
- return 'a' <= c && c <= 'z'
33
- }
34
-
35
- function isDigit(c: string): boolean {
36
- return '0' <= c && c <= '9'
37
- }
38
-
39
- function isASCII(c: string): boolean {
40
- return (c.codePointAt(0) as number) < 0x80
41
- }
42
-
43
- export function splitWords(name: string): string[] {
44
- const words: string[] = []
45
- let cur = ''
46
- const chars = Array.from(name)
47
- for (let i = 0; i < chars.length; i++) {
48
- const c = chars[i]
49
- if ('_' === c || '-' === c || ' ' === c) {
50
- if ('' !== cur) {
51
- words.push(cur)
52
- }
53
- cur = ''
54
- continue
55
- }
56
- if ('' !== cur) {
57
- const prev = chars[i - 1]
58
- const next = chars[i + 1]
59
- const boundary = isASCII(c) && isASCII(prev) && (
60
- (isUpper(c) && (isLower(prev) || isDigit(prev))) ||
61
- (isDigit(c) !== isDigit(prev)) ||
62
- (isUpper(c) && isUpper(prev) && undefined !== next && isLower(next)))
63
- if (boundary) {
64
- words.push(cur)
65
- cur = ''
66
- }
67
- }
68
- cur += c
69
- }
70
- if ('' !== cur) {
71
- words.push(cur)
72
- }
73
- return words
74
- }
75
-
76
- export function lowerASCII(s: string): string {
77
- return Array.from(s).map((c) =>
78
- isUpper(c) ? String.fromCharCode(c.charCodeAt(0) + 32) : c).join('')
79
- }
80
-
81
- export function upperASCII(s: string): string {
82
- return Array.from(s).map((c) =>
83
- isLower(c) ? String.fromCharCode(c.charCodeAt(0) - 32) : c).join('')
84
- }
85
-
86
- // A word capitalised: the acronym set wins, so `id` is `ID` under a
87
- // profile that lists it and `Id` under one that does not.
88
- export function capitalise(word: string, acronyms: string[]): string {
89
- const low = lowerASCII(word)
90
- for (const a of acronyms) {
91
- if (lowerASCII(a) === low) {
92
- return a
93
- }
94
- }
95
- const chars = Array.from(low)
96
- return upperASCII(chars[0]) + chars.slice(1).join('')
97
- }
98
-
99
- // THE CASE STYLES of aontu:render's %case, over the words.
100
- export function caseName(name: string, style: string, acronyms: string[]): string {
101
- if ('as-is' === style) {
102
- return name
103
- }
104
- const words = splitWords(name)
105
- if (0 === words.length) {
106
- return name
107
- }
108
- if ('snake' === style) {
109
- return words.map(lowerASCII).join('_')
110
- }
111
- if ('screaming' === style) {
112
- return words.map(upperASCII).join('_')
113
- }
114
- if ('kebab' === style) {
115
- return words.map(lowerASCII).join('-')
116
- }
117
- const caps = words.map((w) => capitalise(w, acronyms))
118
- if ('pascal' === style) {
119
- return caps.join('')
120
- }
121
- // camel: the first word lower, and never an acronym.
122
- return lowerASCII(words[0]) + caps.slice(1).join('')
123
- }
124
-
125
- export function ident(
126
- name: string, role: string, ctx: LowerCtx, path: string, bare: boolean
127
- ): string {
128
- const rules = ctx.profile.ident ?? {}
129
- const style: string = rules.case?.[role] ?? 'as-is'
130
- const acronyms: string[] = rules.acronyms ?? []
131
- let out = caseName(name, style, acronyms)
132
- if (bare && (rules.reserved ?? []).includes(out)) {
133
- ctx.lossy.push({
134
- unit: ctx.unit, path, tier: 1, construct: 'reserved',
135
- reason: out + ' is reserved in ' + ctx.profile.lang + '; renamed ' + out + '_',
136
- })
137
- out += '_'
138
- }
139
- return out
140
- }
141
-
142
-
143
- // --- literals ----------------------------------------------------------
144
-
145
- function hex4(n: number): string {
146
- return '\\u' + n.toString(16).padStart(4, '0')
147
- }
148
-
149
- // A string literal: the profile's quote, and one pass over the code
150
- // points through its escape table. A control character the table does
151
- // not name is a \u escape; so are the quote and the backslash when the
152
- // table is silent about them; everything else, non-ASCII and astral
153
- // included, is verbatim.
154
- export function quote(s: string, profile: any): string {
155
- const q: string = profile.str?.quote ?? '"'
156
- const table: any = profile.str?.escape ?? {}
157
- let out = q
158
- for (const c of Array.from(s)) {
159
- const cp = c.codePointAt(0) as number
160
- const esc = table[String(cp)]
161
- if ('string' === typeof esc) {
162
- out += esc
163
- }
164
- else if (cp < 0x20 || 0x7f === cp || c === q || '\\' === c) {
165
- out += hex4(cp)
166
- }
167
- else {
168
- out += c
169
- }
170
- }
171
- return out + q
172
- }
173
-
174
- // A literal value as the target spells it: a string quoted, a number
175
- // through exactJSON (no second number formatter), a boolean as is, and
176
- // null as the family's null.
177
- export function literal(v: any, ctx: LowerCtx): string {
178
- if ('string' === typeof v) {
179
- return quote(v, ctx.profile)
180
- }
181
- if (null === v) {
182
- return 'go' === ctx.family ? 'nil' : 'null'
183
- }
184
- if ('boolean' === typeof v) {
185
- return v ? 'true' : 'false'
186
- }
187
- return exactJSON(v)
188
- }
189
-
190
-
191
- // --- types -------------------------------------------------------------
192
-
193
- type Expr = { text: string, prec: number }
194
-
195
- function form(ctx: LowerCtx, name: string): any {
196
- return ctx.profile.types?.[name] ?? { open: '', close: '', prec: 9, childPrec: 0 }
197
- }
198
-
199
- function under(inner: Expr, f: any): string {
200
- return inner.prec < f.childPrec ? '(' + inner.text + ')' : inner.text
201
- }
202
-
203
- function loss(ctx: LowerCtx, path: string, construct: string, reason: string): void {
204
- ctx.lossy.push({ unit: ctx.unit, path, tier: 1, construct, reason })
205
- }
206
-
207
- // The primitive kind a literal set shares, for a family with no
208
- // literal type: strings, integers, floats, booleans, null, or any.
209
- function litPrim(of: any[]): string {
210
- const kinds = of.map((v) => null === v ? 'null' : typeof v)
211
- const first = kinds[0]
212
- if (!kinds.every((k) => k === first)) {
213
- return 'any'
214
- }
215
- if ('number' === first) {
216
- return of.every((v) => Number.isInteger(v)) ? 'int' : 'float'
217
- }
218
- return 'string' === first ? 'string' : 'boolean' === first ? 'bool' : 'null'
219
- }
220
-
221
- function prim(ctx: LowerCtx, name: string): string {
222
- return ctx.profile.types?.prim?.[name] ?? name
223
- }
224
-
225
- // THE TYPE EXPRESSION, from the profile's type forms (D6): an atom has
226
- // prec 9; a form is `open + inner + close`, its precedence its own, its
227
- // inner parenthesised below childPrec. A `text` leaf is verbatim
228
- // target syntax and tier 3, as a text declaration is.
229
- export function typeExpr(t: any, ctx: LowerCtx, path: string): Expr {
230
- const k: string = t.k
231
- if ('prim' === k) {
232
- return { text: prim(ctx, t.prim), prec: 9 }
233
- }
234
- if ('ref' === k) {
235
- return { text: ident(t.name, 'record', ctx, path, false), prec: 9 }
236
- }
237
- if ('text' === k) {
238
- ctx.lossy.push({
239
- unit: ctx.unit, path, tier: 3, construct: 'text',
240
- reason: 'verbatim ' + t.lang + ': the renderer checks nothing in it',
241
- })
242
- return { text: t.text, prec: 9 }
243
- }
244
- if ('list' === k) {
245
- const f = form(ctx, 'list')
246
- return { text: f.open + under(typeExpr(t.n, ctx, path + '.n'), f) + f.close, prec: f.prec }
247
- }
248
- if ('map' === k) {
249
- const f = form(ctx, 'map')
250
- const key = under(typeExpr(t.key, ctx, path + '.key'), f)
251
- const of = under(typeExpr(t.n, ctx, path + '.n'), f)
252
- const sep = 'go' === ctx.family ? ']' : ', '
253
- return { text: f.open + key + sep + of + f.close, prec: f.prec }
254
- }
255
- if ('opt' === k) {
256
- const f = form(ctx, 'opt')
257
- return { text: f.open + under(typeExpr(t.n, ctx, path + '.n'), f) + f.close, prec: f.prec }
258
- }
259
- if ('union' === k) {
260
- if ('go' === ctx.family) {
261
- loss(ctx, path, 'union', 'go has no union type: any')
262
- return { text: prim(ctx, 'any'), prec: 9 }
263
- }
264
- const f = form(ctx, 'union')
265
- const members = t.n.map((m: any, i: number) =>
266
- under(typeExpr(m, ctx, path + '.n.' + i), f))
267
- return { text: f.open + members.join(' | ') + f.close, prec: f.prec }
268
- }
269
- // lit
270
- if ('go' === ctx.family) {
271
- const p = litPrim(t.n)
272
- loss(ctx, path, 'lit', 'go has no literal type: ' + p)
273
- return { text: prim(ctx, p), prec: 9 }
274
- }
275
- const f = form(ctx, 'lit')
276
- const lits = t.n.map((v: any) => literal(v, ctx))
277
- return { text: f.open + lits.join(' | ') + f.close, prec: f.prec }
278
- }
279
-
280
-
281
- // --- comments ----------------------------------------------------------
282
-
283
- // A doc comment as pieces at a depth: the profile's doc form -- open,
284
- // a prefix per line, close -- and the line form when a profile has no
285
- // doc form. A deprecation is the last line, in the family's spelling.
286
- function doc(d: any, at: number, ctx: LowerCtx): any[] {
287
- if (null == d) {
288
- return []
289
- }
290
- const forms = ctx.profile.comment ?? {}
291
- const f = forms.doc ?? forms.line ?? { prefix: '// ' }
292
- const prefix: string = f.prefix ?? ''
293
- const lines: string[] = String(d.text).split('\n')
294
- if (null != d.deprecated) {
295
- const dep = d.deprecated
296
- const note = [dep.msg, dep.use ? 'use ' + dep.use : '', dep.since ? 'since ' + dep.since : '']
297
- .filter((s: string) => s).join('; ')
298
- lines.push('go' === ctx.family ? 'Deprecated: ' + note : '@deprecated ' + note)
299
- }
300
- const out: any[] = []
301
- if (null != f.open) {
302
- out.push(ln(at, f.open))
303
- }
304
- for (const l of lines) {
305
- out.push(ln(at, (prefix + l).replace(/[ \t]+$/, '')))
306
- }
307
- if (null != f.close) {
308
- out.push(ln(at, f.close))
309
- }
310
- return out
311
- }
312
-
313
- function checks(list: any[] | undefined, path: string, ctx: LowerCtx): void {
314
- (list ?? []).forEach((c: any, i: number) => {
315
- loss(ctx, path + '.check.' + i, 'check',
316
- 'the check ' + c.c + ' is not enforced by the ' + ctx.profile.lang + ' type system')
317
- })
318
- }
319
-
320
-
321
- // --- the unit header ---------------------------------------------------
322
-
323
- // The path from one unit's directory to another unit, for a TypeScript
324
- // import: `./other` beside, `../shared/x` across, the extension gone.
325
- function relImport(from: string, to: string): string {
326
- const a = from.split('/').slice(0, -1)
327
- const b = to.split('/')
328
- const file = (b.pop() as string).replace(/\.[^.]*$/, '')
329
- let i = 0
330
- while (i < a.length && i < b.length && a[i] === b[i]) {
331
- i++
332
- }
333
- const up = a.slice(i).map(() => '..')
334
- const parts = [...up, ...b.slice(i), file]
335
- return (0 === up.length ? './' : '') + parts.join('/')
336
- }
337
-
338
- // Imports derived from `{k:"ref", unit}` nodes, in order of first
339
- // appearance, grouped by unit -- TypeScript only: a Go reference names
340
- // a type in the same package.
341
- function derivedImports(unit: any): any[] {
342
- const groups: any[] = []
343
- const visit = (t: any): void => {
344
- if (null == t || 'object' !== typeof t) {
345
- return
346
- }
347
- if (Array.isArray(t)) {
348
- t.forEach(visit)
349
- return
350
- }
351
- if ('ref' === t.k && 'string' === typeof t.unit) {
352
- let g = groups.find((x) => x.from === t.unit)
353
- if (undefined === g) {
354
- g = { from: t.unit, names: [] }
355
- groups.push(g)
356
- }
357
- if (!g.names.includes(t.name)) {
358
- g.names.push(t.name)
359
- }
360
- return
361
- }
362
- for (const key of ['type', 'n', 'key', 'returns', 'fields', 'params']) {
363
- visit(t[key])
364
- }
365
- }
366
- visit(unit.decls)
367
- return groups
368
- }
369
-
370
- // The banner from `code.source`, the package clause, and the imports:
371
- // what stands before the declarations, each part followed by a blank.
372
- export function lowerHeader(unit: any, source: any, ctx: LowerCtx): any[] {
373
- const parts: any[][] = []
374
- const banner: string | undefined = ctx.profile.banner
375
- if (null != banner && null != source?.path) {
376
- const prefix: string = ctx.profile.comment?.line?.prefix ?? ''
377
- parts.push([prefix + banner.split('{path}').join(source.path)
378
- .split('{hash}').join(source.hash ?? '')])
379
- }
380
- if ('go' === ctx.family && 'string' === typeof unit.pkg) {
381
- parts.push(['package ' + unit.pkg])
382
- }
383
- const imports: any[] = [...(unit.imports ?? [])]
384
- if ('typescript' === ctx.family) {
385
- for (const g of derivedImports(unit)) {
386
- imports.push({
387
- from: relImport(unit.path, g.from),
388
- names: g.names.map((n: string) => ident(n, 'record', ctx, '', false)),
389
- })
390
- }
391
- }
392
- if (0 < imports.length) {
393
- const lines: any[] = []
394
- if ('go' === ctx.family) {
395
- const spell = (im: any) =>
396
- (null == im.alias ? '' : im.alias + ' ') + quote(im.from, ctx.profile)
397
- if (1 === imports.length) {
398
- lines.push('import ' + spell(imports[0]))
399
- }
400
- else {
401
- lines.push('import (')
402
- for (const im of imports) {
403
- lines.push(ln(1, spell(im)))
404
- }
405
- lines.push(')')
406
- }
407
- }
408
- else {
409
- for (const im of imports) {
410
- const from = quote(im.from, ctx.profile)
411
- if (Array.isArray(im.names) && 0 < im.names.length) {
412
- lines.push('import { ' + im.names.join(', ') + ' } from ' + from + ';')
413
- }
414
- else if (null != im.alias) {
415
- lines.push('import * as ' + im.alias + ' from ' + from + ';')
416
- }
417
- else {
418
- lines.push('import ' + from + ';')
419
- }
420
- }
421
- }
422
- parts.push(lines)
423
- }
424
- // The parts, a blank between each two; the fold puts the blank
425
- // after the last when a declaration follows.
426
- const out: any[] = []
427
- parts.forEach((part, i) => {
428
- if (0 < i) {
429
- out.push(BLANK)
430
- }
431
- out.push(...part)
432
- })
433
- return out
434
- }
435
-
436
-
437
- // --- declarations ------------------------------------------------------
438
-
439
- // A body fragment's pieces, one level deeper: a bare string is a line
440
- // at depth 1, a line or a raw keeps its shape at `at + 1`, a blank is
441
- // a blank.
442
- function nest(pieces: any[]): any[] {
443
- return pieces.map((p) => 'string' === typeof p ? ln(1, p)
444
- : 'blank' === p.k ? p : { ...p, at: (p.at ?? 0) + 1 })
445
- }
446
-
447
- function params(list: any[], ctx: LowerCtx, path: string): string {
448
- return list.map((p: any, i: number) => {
449
- const ppath = path + '.params.' + i
450
- const name = ident(p.name, 'param', ctx, ppath + '.name', true)
451
- const type = typeExpr(p.type, ctx, ppath + '.type').text
452
- if ('go' === ctx.family) {
453
- if (undefined !== p.default) {
454
- loss(ctx, ppath + '.default', 'default',
455
- 'go has no default parameter: the default of ' + p.name + ' is dropped')
456
- }
457
- return name + ' ' + type
458
- }
459
- return name + ': ' + type +
460
- (undefined === p.default ? '' : ' = ' + literal(p.default, ctx))
461
- }).join(', ')
462
- }
463
-
464
- // The lowering of one declaration to pieces. A `frag` and a `text`
465
- // never arrive here: the fold takes those itself.
466
- export function lowerDecl(decl: any, path: string, ctx: LowerCtx): any[] {
467
- const go = 'go' === ctx.family
468
- const out: any[] = []
469
- const k: string = decl.k
470
-
471
- if ('record' === k) {
472
- const name = ident(decl.name, 'record', ctx, path + '.name', true)
473
- out.push(...doc(decl.doc, 0, ctx))
474
- out.push(go ? 'type ' + name + ' struct {' : 'export interface ' + name + ' {')
475
- decl.fields.forEach((f: any, i: number) => {
476
- const fpath = path + '.fields.' + i
477
- out.push(...doc(f.doc, 1, ctx))
478
- const fname = ident(f.name, 'field', ctx, fpath + '.name', false)
479
- const type = typeExpr(f.type, ctx, fpath + '.type')
480
- checks(f.check, fpath, ctx)
481
- const opt = true === f.optional
482
- if (go) {
483
- const star = opt && 'opt' !== f.type.k ? '*' : ''
484
- out.push(ln(1, fname + ' ' + star + type.text +
485
- ' `json:"' + f.name + (opt ? ',omitempty' : '') + '"`'))
486
- }
487
- else {
488
- out.push(ln(1, fname + (opt ? '?' : '') + ': ' + type.text + ';'))
489
- }
490
- if (undefined !== f.default) {
491
- loss(ctx, fpath + '.default', 'default', 'a field default is not expressed by a ' +
492
- (go ? 'go struct' : 'typescript interface'))
493
- }
494
- })
495
- if (true === decl.open) {
496
- if (go) {
497
- loss(ctx, path + '.open', 'open', 'go has no open struct: extra keys are dropped')
498
- }
499
- else {
500
- out.push(ln(1, '[key: string]: unknown;'))
501
- }
502
- }
503
- checks(decl.check, path, ctx)
504
- out.push('}')
505
- return out
506
- }
507
-
508
- if ('enum' === k) {
509
- const name = ident(decl.name, 'enum', ctx, path + '.name', true)
510
- out.push(...doc(decl.doc, 0, ctx))
511
- const members: any[] = decl.members
512
- if (go) {
513
- const numeric = 0 < members.length &&
514
- members.every((m: any) => 'number' === typeof m.value)
515
- out.push('type ' + name + ' ' + prim(ctx, numeric ? 'int' : 'string'))
516
- out.push(BLANK, 'const (')
517
- members.forEach((m: any, i: number) => {
518
- out.push(...doc(m.doc, 1, ctx))
519
- const mname = name + ident(m.name, 'member', ctx, path + '.members.' + i + '.name', false)
520
- const value = undefined === m.value ? quote(m.name, ctx.profile) : literal(m.value, ctx)
521
- out.push(ln(1, mname + ' ' + name + ' = ' + value))
522
- })
523
- out.push(')')
524
- }
525
- else {
526
- out.push('export enum ' + name + ' {')
527
- members.forEach((m: any, i: number) => {
528
- out.push(...doc(m.doc, 1, ctx))
529
- const mname = ident(m.name, 'member', ctx, path + '.members.' + i + '.name', false)
530
- out.push(ln(1, mname + (undefined === m.value ? '' : ' = ' + literal(m.value, ctx)) + ','))
531
- })
532
- out.push('}')
533
- }
534
- return out
535
- }
536
-
537
- if ('alias' === k) {
538
- const name = ident(decl.name, 'alias', ctx, path + '.name', true)
539
- out.push(...doc(decl.doc, 0, ctx))
540
- const type = typeExpr(decl.type, ctx, path + '.type').text
541
- checks(decl.check, path, ctx)
542
- out.push(go ? 'type ' + name + ' ' + type : 'export type ' + name + ' = ' + type + ';')
543
- return out
544
- }
545
-
546
- if ('const' === k) {
547
- const name = ident(decl.name, 'const', ctx, path + '.name', true)
548
- out.push(...doc(decl.doc, 0, ctx))
549
- const type = null == decl.type ? undefined : typeExpr(decl.type, ctx, path + '.type').text
550
- const value = literal(decl.value, ctx)
551
- out.push(go
552
- ? 'const ' + name + (undefined === type ? '' : ' ' + type) + ' = ' + value
553
- : 'export const ' + name + (undefined === type ? '' : ': ' + type) + ' = ' + value + ';')
554
- return out
555
- }
556
-
557
- // func
558
- const name = ident(decl.name, 'func', ctx, path + '.name', true)
559
- out.push(...doc(decl.doc, 0, ctx))
560
- const sig = params(decl.params, ctx, path)
561
- const returns = null == decl.returns ? undefined : typeExpr(decl.returns, ctx, path + '.returns').text
562
- const abstract = 'abstract' === decl.body.k
563
- if (go) {
564
- out.push('func ' + name + '(' + sig + ')' + (undefined === returns ? '' : ' ' + returns) + ' {')
565
- if (abstract) {
566
- loss(ctx, path + '.body', 'abstract', 'go has no abstract function: the body panics')
567
- out.push(ln(1, 'panic(' + quote('abstract', ctx.profile) + ')'))
568
- }
569
- else {
570
- out.push(...nest(decl.body.n))
571
- }
572
- out.push('}')
573
- }
574
- else {
575
- const ret = ': ' + (returns ?? 'void')
576
- if (abstract) {
577
- out.push('export declare function ' + name + '(' + sig + ')' + ret + ';')
578
- }
579
- else {
580
- out.push('export function ' + name + '(' + sig + ')' + ret + ' {')
581
- out.push(...nest(decl.body.n))
582
- out.push('}')
583
- }
584
- }
585
- return out
586
- }