aontu 0.63.0 → 0.64.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 (61) hide show
  1. package/README.md +6 -6
  2. package/dist/aontu.d.ts +3 -3
  3. package/dist/aontu.js +4 -6
  4. package/dist/aontu.js.map +1 -1
  5. package/dist/aontumodel.js +6 -12
  6. package/dist/aontumodel.js.map +1 -1
  7. package/dist/casing.d.ts +5 -0
  8. package/dist/casing.js +90 -0
  9. package/dist/casing.js.map +1 -0
  10. package/dist/cli.d.ts +2 -2
  11. package/dist/cli.js +147 -335
  12. package/dist/cli.js.map +1 -1
  13. package/dist/helpdoc.js +1 -1
  14. package/dist/helpdoc.js.map +1 -1
  15. package/dist/hints.js +3 -0
  16. package/dist/hints.js.map +1 -1
  17. package/dist/lsp.d.ts +1 -1
  18. package/dist/mcp.js +0 -36
  19. package/dist/mcp.js.map +1 -1
  20. package/dist/mod-tool.js +16 -1
  21. package/dist/mod-tool.js.map +1 -1
  22. package/dist/profile.d.ts +9 -0
  23. package/dist/profile.js +28 -0
  24. package/dist/profile.js.map +1 -0
  25. package/dist/trace.d.ts +21 -0
  26. package/dist/trace.js +107 -0
  27. package/dist/trace.js.map +1 -0
  28. package/dist/tsconfig.tsbuildinfo +1 -1
  29. package/dist/unify.js +1 -6
  30. package/dist/unify.js.map +1 -1
  31. package/dist/val/CmpFuncVal.d.ts +2 -0
  32. package/dist/val/CmpFuncVal.js +47 -13
  33. package/dist/val/CmpFuncVal.js.map +1 -1
  34. package/dist/val/NomFuncVal.js +11 -13
  35. package/dist/val/NomFuncVal.js.map +1 -1
  36. package/dist/val/ReferFuncVal.js +3 -0
  37. package/dist/val/ReferFuncVal.js.map +1 -1
  38. package/package.json +1 -1
  39. package/skill/tasks.md +9 -7
  40. package/src/aontu.ts +3 -8
  41. package/src/aontumodel.ts +6 -12
  42. package/src/casing.ts +95 -0
  43. package/src/cli.ts +162 -359
  44. package/src/helpdoc.ts +1 -1
  45. package/src/hints.ts +3 -0
  46. package/src/mcp.ts +0 -39
  47. package/src/mod-tool.ts +18 -1
  48. package/src/profile.ts +42 -0
  49. package/src/trace.ts +157 -0
  50. package/src/unify.ts +1 -6
  51. package/src/val/CmpFuncVal.ts +66 -20
  52. package/src/val/NomFuncVal.ts +3 -5
  53. package/src/val/ReferFuncVal.ts +4 -0
  54. package/dist/lower.d.ts +0 -23
  55. package/dist/lower.js +0 -528
  56. package/dist/lower.js.map +0 -1
  57. package/dist/render.d.ts +0 -53
  58. package/dist/render.js +0 -432
  59. package/dist/render.js.map +0 -1
  60. package/src/lower.ts +0 -586
  61. package/src/render.ts +0 -580
package/src/mcp.ts CHANGED
@@ -25,7 +25,6 @@ import { jsonSchema } from './jsonschema'
25
25
  import { relationCheck } from './relation'
26
26
  import { reachCheck } from './reach'
27
27
  import { view } from './view'
28
- import { render } from './render'
29
28
  import { patch } from './patch'
30
29
 
31
30
 
@@ -600,44 +599,6 @@ const TOOLS: ToolDef[] = [
600
599
  at: null == a.at ? undefined : str(a.at), path: paths.source,
601
600
  }),
602
601
  },
603
- {
604
- name: 'render',
605
- description:
606
- 'Render a document that evaluates to an aontu:code instance: ' +
607
- 'evaluate it, vet the value at `at` against the bundled ' +
608
- 'vocabulary, and fold code.units into bytes. Returns verdict ' +
609
- '(ok | lossy | error), the units -- each a path, a language and ' +
610
- 'its text -- and a `lossy` list of what the renderer could not ' +
611
- 'check (a fragment says nothing about the target\'s syntax; a ' +
612
- 'text escape or a raw block is verbatim). The tool never writes: ' +
613
- 'the caller receives the units as text and places them itself.',
614
- properties: {
615
- source: { type: 'string', description: 'The document' },
616
- at: {
617
- type: 'string',
618
- description: 'Render the value at this path of the document ($.a.b)',
619
- },
620
- unit: {
621
- type: 'string',
622
- description: 'Render only the unit with this path',
623
- },
624
- strict: {
625
- type: 'boolean',
626
- description: 'Refuse the opaque escapes (a text declaration, a raw block)',
627
- },
628
- },
629
- required: ['source'],
630
- docs: ['source'],
631
- refuse: (_a, finding) =>
632
- ({ verdict: 'error', units: [], lossy: [], errors: [finding] }),
633
- run: (a, _trust, paths) =>
634
- render(str(a.source), {
635
- at: null == a.at ? undefined : str(a.at),
636
- unit: null == a.unit ? undefined : str(a.unit),
637
- strict: true === a.strict,
638
- path: paths.source,
639
- }),
640
- },
641
602
  ]
642
603
 
643
604
 
package/src/mod-tool.ts CHANGED
@@ -502,7 +502,24 @@ export function modManifest(
502
502
  }
503
503
 
504
504
  const newSrc = readFileSync(main, 'utf8')
505
- const canon = options.eval(newSrc, main).hash
505
+ const got = options.eval(newSrc, main)
506
+
507
+ // Nothing to pin: `tidy` refuses the same way.
508
+ if (!got.ok) {
509
+ return {
510
+ verdict: 'error',
511
+ mod,
512
+ version: self.version,
513
+ canon: '',
514
+ config: MODULE_CONFIG_MEDIA_TYPE,
515
+ files: [],
516
+ annotations: {},
517
+ missing: [self.main],
518
+ findings: [],
519
+ }
520
+ }
521
+
522
+ const canon = got.hash
506
523
 
507
524
  const report: ModManifestReport = {
508
525
  verdict: 'ok',
package/src/profile.ts ADDED
@@ -0,0 +1,42 @@
1
+ /* Copyright (c) 2026 Richard Rodger, MIT License */
2
+
3
+
4
+ import { Aontu } from './aontu'
5
+ import { vet, failureFinding } from './vet'
6
+ import { hcanon } from './hcanon'
7
+ import { includeOpts } from './utility'
8
+
9
+ import type { IncludeOptions } from './utility'
10
+ import type { VetFinding } from './vet'
11
+
12
+
13
+ export type ProfileOptions = IncludeOptions & {
14
+ // Where the document CAME FROM, so a relative `@"file"` load inside
15
+ // it resolves from its own directory.
16
+ path?: string
17
+ }
18
+
19
+
20
+ const PROFILE_VOCABULARY = '@"aontu:profile"'
21
+
22
+
23
+ // A language declared as data, vetted, or the findings that refuse it.
24
+ export function loadProfile(src: string, options?: ProfileOptions):
25
+ { profile?: any, errors?: VetFinding[] } {
26
+ const opts = options ?? {}
27
+ const aontu = new Aontu(includeOpts(opts))
28
+ const actx = aontu.ctx({ collect: true })
29
+ const root: any = aontu.unify(src, { path: opts.path, collect: true }, actx)
30
+ if (0 < actx.err.length || true === root?.isNil) {
31
+ return { errors: [failureFinding(actx, opts.path, root)] }
32
+ }
33
+ const report = vet(PROFILE_VOCABULARY, hcanon(root))
34
+ if ('valid' !== report.verdict) {
35
+ return { errors: report.findings }
36
+ }
37
+ // The meet: the vocabulary requires `lang`, so a value the vet
38
+ // admitted has a `Lang`.
39
+ const instance = new Aontu().generate(
40
+ PROFILE_VOCABULARY + '\naontu: Lang: ' + hcanon(root.peg.aontu.peg.Lang))
41
+ return { profile: instance.aontu.Lang }
42
+ }
package/src/trace.ts ADDED
@@ -0,0 +1,157 @@
1
+ /* Copyright (c) 2026 Richard Rodger, MIT License */
2
+
3
+
4
+ import type { Val } from './type'
5
+
6
+ import { Aontu } from './aontu'
7
+ import { cmpCodePoint } from './keyorder'
8
+ import { includeOpts } from './utility'
9
+ import { anchorAt, failureFinding } from './vet'
10
+ import { makeNilErr } from './err'
11
+
12
+ import type { IncludeOptions } from './utility'
13
+ import type { VetFinding } from './vet'
14
+
15
+
16
+ export type TraceOptions = IncludeOptions & {
17
+ path?: string
18
+ at?: string
19
+ }
20
+
21
+
22
+ export type TraceReport = {
23
+ verdict: 'ok' | 'error'
24
+ trace: TraceEntry[]
25
+ errors?: VetFinding[]
26
+ }
27
+
28
+
29
+ // WHAT A TRACE ENTRY CARRIES. The file it reached, the rule set that
30
+ // wrote it, and the model node the dispatch matched.
31
+ export type TraceEntry = {
32
+ at: string
33
+ file: string
34
+ node: string
35
+ rule: string
36
+ }
37
+
38
+
39
+ function walkVals(root: any, fn: (v: any, path: string[]) => void): void {
40
+ const walk = (v: any, path: string[]): void => {
41
+ fn(v, path)
42
+ if (true === v.isList && null != v.peg) {
43
+ for (let i = 0; i < v.peg.length; i++) {
44
+ walk(v.peg[i], [...path, String(i)])
45
+ }
46
+ }
47
+ else if (true === v.isMap && null != v.peg) {
48
+ for (const k of Object.keys(v.peg).sort(cmpCodePoint)) {
49
+ if (!v.aliasKeys?.includes(k)) {
50
+ walk(v.peg[k], [...path, k])
51
+ }
52
+ }
53
+ }
54
+ }
55
+ walk(root, [])
56
+ }
57
+
58
+
59
+ function addr(path: string[]): string {
60
+ return '$' + path.map((seg) => '.' + seg).join('')
61
+ }
62
+
63
+
64
+ function scalar(v: any): string | undefined {
65
+ return (true === v?.isScalar && 'string' === typeof v.peg) ? v.peg : undefined
66
+ }
67
+
68
+
69
+ function fileName(v: any): string | undefined {
70
+ if (true !== v?.isMap) {
71
+ return undefined
72
+ }
73
+ return 'File' === scalar(v.peg?.cmp) ? scalar(v.peg?.props?.peg?.name) :
74
+ undefined
75
+ }
76
+
77
+
78
+ // THE INNERMOST FILE WINS: the longest matching prefix, not the first.
79
+ function enclosing(files: { at: string, name: string }[],
80
+ path: string): string | undefined {
81
+ let best: string | undefined
82
+ let long = -1
83
+ for (const f of files) {
84
+ if ((path === f.at || path.startsWith(f.at + '.')) && f.at.length > long) {
85
+ best = f.name
86
+ long = f.at.length
87
+ }
88
+ }
89
+ return best
90
+ }
91
+
92
+
93
+ // Every piece a dispatch stamped, attributed to the file it reached.
94
+ // One pass: `walkVals` is depth-first in document order, so a file is
95
+ // always seen before the marks beneath it.
96
+ function traceTree(root: Val): TraceEntry[] {
97
+ const files: { at: string, name: string }[] = []
98
+ const marks: { at: string, mark: any }[] = []
99
+ walkVals(root, (v: any, path: string[]) => {
100
+ const name = fileName(v)
101
+ if (undefined !== name) {
102
+ files.push({ at: addr(path), name })
103
+ }
104
+ if (null != v.emitted) {
105
+ marks.push({ at: addr(path), mark: v.emitted })
106
+ }
107
+ })
108
+
109
+ const out: TraceEntry[] = []
110
+ for (const m of marks) {
111
+ const file = enclosing(files, m.at)
112
+ if (undefined === file) {
113
+ continue
114
+ }
115
+ out.push({ at: m.at, file, node: m.mark.node, rule: m.mark.rule })
116
+ }
117
+ return out
118
+ }
119
+
120
+
121
+ // THE MARKS ARE OPT-IN. `emit` stamps a piece only when the context
122
+ // carries a `reads` set, so the verb asks for one the way `render
123
+ // --trace` did.
124
+ function traceRun(src: string, options?: TraceOptions): TraceReport {
125
+ const opts = options ?? {}
126
+ const aontu = new Aontu(includeOpts(opts))
127
+ const actx = aontu.ctx({ collect: true, reads: new Set<string>() })
128
+ const root: any = aontu.unify(
129
+ src, { path: opts.path, collect: true }, actx)
130
+ if (0 < actx.err.length || true === root?.isNil) {
131
+ return {
132
+ verdict: 'error', trace: [],
133
+ errors: [failureFinding(actx, opts.path, root)],
134
+ }
135
+ }
136
+
137
+ let node: any = root
138
+ const at = opts.at ?? '$.out'
139
+ const found: any = anchorAt(root, at)
140
+ if (null == found) {
141
+ const nil: any = makeNilErr(actx, 'no_path', root, undefined, 'at')
142
+ actx.err.push(nil)
143
+ return {
144
+ verdict: 'error', trace: [],
145
+ errors: [failureFinding(actx, opts.path, root)],
146
+ }
147
+ }
148
+ node = found
149
+
150
+ return { verdict: 'ok', trace: traceTree(node) }
151
+ } /* node:coverage ignore next 6 */
152
+
153
+
154
+ export {
155
+ traceTree,
156
+ traceRun,
157
+ }
package/src/unify.ts CHANGED
@@ -67,6 +67,7 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
67
67
  && !a.isConjunct && !a.isDisjunct
68
68
  && !a.isRef && !a.isPref && !a.isFunc && !a.isExpect
69
69
  && !a.isTop && !b.isTop
70
+ && !a.isRefer
70
71
  && !a.isRel && !a.isGraphAtom && !a.isRecurse) {
71
72
  // The deprecation record survives the fast path too (G3):
72
73
  // `deprecate(5) & 5` short-circuits here.
@@ -242,12 +243,6 @@ function riders(a: any, b: any, to: any): void {
242
243
  to.origin = org
243
244
  }
244
245
  }
245
- if (null == to.emitted) {
246
- const emt = av.emitted ?? bv.emitted
247
- if (null != emt) {
248
- to.emitted = emt
249
- }
250
- }
251
246
  }
252
247
 
253
248
 
@@ -25,60 +25,78 @@ type CmpDef = {
25
25
  children: string[]
26
26
  text?: string
27
27
  // Whether that prop is required. `project`'s folder is the one that
28
- // is not: Jostraca defaults it to `.`, and the data path must not be
29
- // stricter than the component it drives.
28
+ // is not: Jostraca defaults it to `.`.
30
29
  req: boolean
30
+ // Whether that prop is a SPAN of target text rather than a name. A
31
+ // blank line is a span; a folder called "" is a mistake.
32
+ span?: boolean
31
33
  // A prop that must be present and must be a list.
32
34
  bag?: string
35
+ // Hand-kept: no jostraca dependency to derive it from.
36
+ props: string[]
33
37
  }
34
38
 
39
+
40
+ const SPAN_PROPS =
41
+ ['arg', 'src', 'name', 'indent', 'extra', 'replace', 'raw']
42
+
35
43
  const CMP_DEF: Record<string, CmpDef> = {
36
44
  // The output root. Its `folder` is refused an absolute path or a
37
45
  // `..` segment on the Jostraca side, where the tree is data.
38
46
  project: {
39
47
  cmp: 'Project', text: 'folder', req: false,
40
48
  children: ['project', 'folder', 'file', 'copyfiles'],
49
+ props: ['name', 'folder'],
41
50
  },
42
51
  folder: {
43
52
  cmp: 'Folder', text: 'name', req: true,
44
53
  children: ['folder', 'file', 'copyfiles'],
54
+ props: ['name'],
45
55
  },
46
56
  file: {
47
57
  cmp: 'File', text: 'name', req: true,
48
58
  children: ['content', 'line', 'fragment', 'inject', 'listitems', 'copyfiles'],
59
+ props: ['name', 'exclude', 'mode'],
49
60
  },
50
61
  content: {
51
- cmp: 'Content', text: 'src', req: true,
62
+ cmp: 'Content', text: 'src', req: true, span: true,
52
63
  children: [],
64
+ props: SPAN_PROPS,
53
65
  },
54
66
  // A span with a newline added, which is the whole difference.
55
67
  line: {
56
- cmp: 'Line', text: 'src', req: true,
68
+ cmp: 'Line', text: 'src', req: true, span: true,
57
69
  children: [],
70
+ props: SPAN_PROPS,
58
71
  },
59
72
  // A file read from disk with its `<[SLOT]>` markers filled.
60
73
  fragment: {
61
74
  cmp: 'Fragment', text: 'from', req: true,
62
75
  children: ['slot', 'content', 'line', 'listitems'],
76
+ props: ['from', 'indent', 'replace', 'eject'],
63
77
  },
64
78
  slot: {
65
79
  cmp: 'Slot', text: 'name', req: true,
66
80
  children: ['content', 'line', 'fragment', 'listitems'],
81
+ props: ['name'],
67
82
  },
68
83
  // A body written between markers in a file that already exists.
69
84
  inject: {
70
85
  cmp: 'Inject', text: 'name', req: true,
71
86
  children: ['content', 'line', 'listitems'],
87
+ props: ['name', 'markers', 'exclude'],
72
88
  },
73
89
  // `Copy` under a name aontu has free: `copy` is taken by the builtin
74
90
  // that copies a VALUE, and a file copy is a different verb.
75
91
  copyfiles: {
76
92
  cmp: 'CopyFiles', text: 'from', req: true,
77
93
  children: [],
94
+ props: ['from', 'to', 'replace', 'exclude'],
78
95
  },
79
96
  listitems: {
80
97
  cmp: 'ListItems', req: true, bag: 'item',
81
98
  children: ['content', 'line', 'fragment'],
99
+ props: ['item', 'line', 'indent'],
82
100
  },
83
101
  }
84
102
 
@@ -100,6 +118,29 @@ function nodeCmp(v: any): string | undefined {
100
118
  }
101
119
 
102
120
 
121
+ function cmpNode(cmp: string, props: Val, children: Val,
122
+ ctx: AontuContext): MapVal {
123
+ const node = new MapVal({ peg: { cmp: new StringVal({ peg: cmp }, ctx), props, children } }, ctx)
124
+ node.closed = true
125
+ return node
126
+ }
127
+
128
+
129
+ // A bare string child is a LINE: `Content` writes no newline, and the
130
+ // emit mark rides across or `aontu trace` loses the line's rule.
131
+ function lineNode(from: any, src: string, ctx: AontuContext): MapVal {
132
+ const node = cmpNode(
133
+ CMP_DEF.line.cmp,
134
+ new MapVal({ peg: { src: new StringVal({ peg: src }, ctx) } }, ctx),
135
+ new ListVal({ peg: [] }, ctx),
136
+ ctx)
137
+ if (null != from?.emitted) {
138
+ ; (node as any).emitted = from.emitted
139
+ }
140
+ return node
141
+ }
142
+
143
+
103
144
  function propText(props: any, key: string): string | undefined {
104
145
  const v: any = props?.peg?.[key]
105
146
  return (true === v?.isScalar && 'string' === typeof v.peg) ? v.peg : undefined
@@ -109,9 +150,7 @@ function propText(props: any, key: string): string | undefined {
109
150
  class CmpFuncVal extends FuncBaseVal {
110
151
  isCmpFunc = true
111
152
 
112
- // The component this call builds: the function's own name, which is
113
- // also the `cmp` key of the node and the Jostraca component the
114
- // bridge looks up.
153
+ // The function's own name, which is also the node's `cmp` key.
115
154
  cmp: string
116
155
 
117
156
  constructor(
@@ -151,13 +190,21 @@ class CmpFuncVal extends FuncBaseVal {
151
190
  return makeNilErr(ctx, 'invalid-arg', this, spec, 'spec')
152
191
  }
153
192
 
193
+ // An unknown prop is a silently dropped `indent` or `mode`.
194
+ for (const key of Object.keys((props as any).peg)) {
195
+ if (!def.props.includes(key)) {
196
+ return makeNilErr(ctx, 'invalid-arg', this, props, key)
197
+ }
198
+ }
199
+
154
200
  if (undefined !== def.text) {
155
201
  const text = propText(props, def.text)
156
- if (def.req && (undefined === text || '' === text)) {
202
+ if (def.req &&
203
+ (undefined === text || ('' === text && true !== def.span))) {
157
204
  return makeNilErr(ctx, 'invalid-arg', this, props, def.text)
158
205
  }
159
206
  if (!def.req && undefined !== (props as any).peg?.[def.text] &&
160
- undefined === text) {
207
+ (undefined === text || ('' === text && true !== def.span))) {
161
208
  return makeNilErr(ctx, 'invalid-arg', this, props, def.text)
162
209
  }
163
210
  }
@@ -188,6 +235,15 @@ class CmpFuncVal extends FuncBaseVal {
188
235
  }
189
236
  continue
190
237
  }
238
+ const text = (true === (kid as any)?.isScalar &&
239
+ 'string' === typeof (kid as any).peg) ? (kid as any).peg : undefined
240
+ if (undefined !== text) {
241
+ if (!def.children.includes('line')) {
242
+ return kid
243
+ }
244
+ flat.push(lineNode(kid, text, ctx))
245
+ continue
246
+ }
191
247
  const kcmp = nodeCmp(kid)
192
248
  if (undefined === kcmp || !def.children.includes(kcmp)) {
193
249
  return kid
@@ -206,17 +262,7 @@ class CmpFuncVal extends FuncBaseVal {
206
262
  return makeNilErr(ctx, 'invalid-arg', this, kids, 'children')
207
263
  }
208
264
 
209
- const node = new MapVal({
210
- peg: {
211
- cmp: new StringVal({ peg: def.cmp }, ctx),
212
- props,
213
- children,
214
- }
215
- }, ctx)
216
-
217
- node.closed = true
218
-
219
- return this.place(node)
265
+ return this.place(cmpNode(def.cmp, props, children, ctx))
220
266
  }
221
267
 
222
268
  } /* node:coverage ignore next 3 */
@@ -17,7 +17,7 @@ import {
17
17
  caseName,
18
18
  lowerASCII,
19
19
  capitalise,
20
- } from '../lower'
20
+ } from '../casing'
21
21
 
22
22
  import { MapVal } from './MapVal'
23
23
  import { StringVal } from './StringVal'
@@ -36,10 +36,8 @@ const NOM_STYLES = [
36
36
  'upper', // USER_ID
37
37
  ]
38
38
 
39
- // nom's style name -> the `%case` style `caseName` serves. `upper` and
40
- // `text` are nom's spellings: `screaming` is what `aontu:render` calls
41
- // SCREAMING_SNAKE and that name is pinned cross-port, so the mapping
42
- // lives here rather than in the shared vocabulary.
39
+ // nom's style name -> the case style `caseName` serves. `upper` and
40
+ // `text` are nom's spellings.
43
41
  const CASENAME_STYLES: Record<string, string> = {
44
42
  camel: 'camel',
45
43
  kebab: 'kebab',
@@ -181,6 +181,10 @@ class ReferVal extends FeatureVal {
181
181
  return makeNilErr(ctx, this.addrcode, this, peer, 'refer')
182
182
  }
183
183
 
184
+ if (true === p.isFunc) {
185
+ return peer.unify(this, ctx)
186
+ }
187
+
184
188
  return this.with(ctx, {
185
189
  held: null == this.held ? peer : unite(ctx, this.held, peer, 'refer-held'),
186
190
  }, this)
package/dist/lower.d.ts DELETED
@@ -1,23 +0,0 @@
1
- import type { RenderLoss } from './render';
2
- export type LowerCtx = {
3
- profile: any;
4
- family: string;
5
- unit: string;
6
- lossy: RenderLoss[];
7
- };
8
- export declare function splitWords(name: string): string[];
9
- export declare function lowerASCII(s: string): string;
10
- export declare function upperASCII(s: string): string;
11
- export declare function capitalise(word: string, acronyms: string[]): string;
12
- export declare function caseName(name: string, style: string, acronyms: string[]): string;
13
- export declare function ident(name: string, role: string, ctx: LowerCtx, path: string, bare: boolean): string;
14
- export declare function quote(s: string, profile: any): string;
15
- export declare function literal(v: any, ctx: LowerCtx): string;
16
- type Expr = {
17
- text: string;
18
- prec: number;
19
- };
20
- export declare function typeExpr(t: any, ctx: LowerCtx, path: string): Expr;
21
- export declare function lowerHeader(unit: any, source: any, ctx: LowerCtx): any[];
22
- export declare function lowerDecl(decl: any, path: string, ctx: LowerCtx): any[];
23
- export {};