@taliesinb/mash 0.0.0-stage → 0.1.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 (203) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +275 -2
  3. package/bin/mash.ts +253 -0
  4. package/dist/bin/mash.d.ts +39 -0
  5. package/dist/bin/mash.d.ts.map +1 -0
  6. package/dist/bin/mash.js +281 -0
  7. package/dist/bin/mash.js.map +1 -0
  8. package/dist/src/analysis/analyze.d.ts +97 -0
  9. package/dist/src/analysis/analyze.d.ts.map +1 -0
  10. package/dist/src/analysis/analyze.js +1406 -0
  11. package/dist/src/analysis/analyze.js.map +1 -0
  12. package/dist/src/analysis/fs.d.ts +39 -0
  13. package/dist/src/analysis/fs.d.ts.map +1 -0
  14. package/dist/src/analysis/fs.js +117 -0
  15. package/dist/src/analysis/fs.js.map +1 -0
  16. package/dist/src/analysis/outputs.d.ts +16 -0
  17. package/dist/src/analysis/outputs.d.ts.map +1 -0
  18. package/dist/src/analysis/outputs.js +277 -0
  19. package/dist/src/analysis/outputs.js.map +1 -0
  20. package/dist/src/analysis/value.d.ts +76 -0
  21. package/dist/src/analysis/value.d.ts.map +1 -0
  22. package/dist/src/analysis/value.js +248 -0
  23. package/dist/src/analysis/value.js.map +1 -0
  24. package/dist/src/behaviors/defs/core.d.ts +15 -0
  25. package/dist/src/behaviors/defs/core.d.ts.map +1 -0
  26. package/dist/src/behaviors/defs/core.js +1084 -0
  27. package/dist/src/behaviors/defs/core.js.map +1 -0
  28. package/dist/src/behaviors/defs/devtools.d.ts +9 -0
  29. package/dist/src/behaviors/defs/devtools.d.ts.map +1 -0
  30. package/dist/src/behaviors/defs/devtools.js +432 -0
  31. package/dist/src/behaviors/defs/devtools.js.map +1 -0
  32. package/dist/src/behaviors/defs/macos.d.ts +12 -0
  33. package/dist/src/behaviors/defs/macos.d.ts.map +1 -0
  34. package/dist/src/behaviors/defs/macos.js +454 -0
  35. package/dist/src/behaviors/defs/macos.js.map +1 -0
  36. package/dist/src/behaviors/defs/tools.d.ts +9 -0
  37. package/dist/src/behaviors/defs/tools.d.ts.map +1 -0
  38. package/dist/src/behaviors/defs/tools.js +639 -0
  39. package/dist/src/behaviors/defs/tools.js.map +1 -0
  40. package/dist/src/behaviors/dsl.d.ts +95 -0
  41. package/dist/src/behaviors/dsl.d.ts.map +1 -0
  42. package/dist/src/behaviors/dsl.js +267 -0
  43. package/dist/src/behaviors/dsl.js.map +1 -0
  44. package/dist/src/behaviors/index.d.ts +12 -0
  45. package/dist/src/behaviors/index.d.ts.map +1 -0
  46. package/dist/src/behaviors/index.js +18 -0
  47. package/dist/src/behaviors/index.js.map +1 -0
  48. package/dist/src/behaviors/registry.d.ts +45 -0
  49. package/dist/src/behaviors/registry.d.ts.map +1 -0
  50. package/dist/src/behaviors/registry.js +266 -0
  51. package/dist/src/behaviors/registry.js.map +1 -0
  52. package/dist/src/behaviors/roles.d.ts +29 -0
  53. package/dist/src/behaviors/roles.d.ts.map +1 -0
  54. package/dist/src/behaviors/roles.js +198 -0
  55. package/dist/src/behaviors/roles.js.map +1 -0
  56. package/dist/src/behaviors/types.d.ts +120 -0
  57. package/dist/src/behaviors/types.d.ts.map +1 -0
  58. package/dist/src/behaviors/types.js +12 -0
  59. package/dist/src/behaviors/types.js.map +1 -0
  60. package/dist/src/index.d.ts +27 -0
  61. package/dist/src/index.d.ts.map +1 -0
  62. package/dist/src/index.js +24 -0
  63. package/dist/src/index.js.map +1 -0
  64. package/dist/src/integrations/deepsea.d.ts +121 -0
  65. package/dist/src/integrations/deepsea.d.ts.map +1 -0
  66. package/dist/src/integrations/deepsea.js +199 -0
  67. package/dist/src/integrations/deepsea.js.map +1 -0
  68. package/dist/src/machine.d.ts +139 -0
  69. package/dist/src/machine.d.ts.map +1 -0
  70. package/dist/src/machine.js +400 -0
  71. package/dist/src/machine.js.map +1 -0
  72. package/dist/src/parser/ast.d.ts +369 -0
  73. package/dist/src/parser/ast.d.ts.map +1 -0
  74. package/dist/src/parser/ast.js +17 -0
  75. package/dist/src/parser/ast.js.map +1 -0
  76. package/dist/src/parser/parser.d.ts +48 -0
  77. package/dist/src/parser/parser.d.ts.map +1 -0
  78. package/dist/src/parser/parser.js +1950 -0
  79. package/dist/src/parser/parser.js.map +1 -0
  80. package/dist/src/policy/effects.d.ts +86 -0
  81. package/dist/src/policy/effects.d.ts.map +1 -0
  82. package/dist/src/policy/effects.js +53 -0
  83. package/dist/src/policy/effects.js.map +1 -0
  84. package/dist/src/policy/policy.d.ts +130 -0
  85. package/dist/src/policy/policy.d.ts.map +1 -0
  86. package/dist/src/policy/policy.js +532 -0
  87. package/dist/src/policy/policy.js.map +1 -0
  88. package/dist/src/printer/doc.d.ts +151 -0
  89. package/dist/src/printer/doc.d.ts.map +1 -0
  90. package/dist/src/printer/doc.js +409 -0
  91. package/dist/src/printer/doc.js.map +1 -0
  92. package/dist/src/printer/highlight.d.ts +53 -0
  93. package/dist/src/printer/highlight.d.ts.map +1 -0
  94. package/dist/src/printer/highlight.js +339 -0
  95. package/dist/src/printer/highlight.js.map +1 -0
  96. package/dist/src/printer/html.d.ts +72 -0
  97. package/dist/src/printer/html.d.ts.map +1 -0
  98. package/dist/src/printer/html.js +423 -0
  99. package/dist/src/printer/html.js.map +1 -0
  100. package/dist/src/printer/print.d.ts +63 -0
  101. package/dist/src/printer/print.d.ts.map +1 -0
  102. package/dist/src/printer/print.js +484 -0
  103. package/dist/src/printer/print.js.map +1 -0
  104. package/dist/src/printer/summary.d.ts +50 -0
  105. package/dist/src/printer/summary.d.ts.map +1 -0
  106. package/dist/src/printer/summary.js +621 -0
  107. package/dist/src/printer/summary.js.map +1 -0
  108. package/dist/src/trace/events.d.ts +183 -0
  109. package/dist/src/trace/events.d.ts.map +1 -0
  110. package/dist/src/trace/events.js +9 -0
  111. package/dist/src/trace/events.js.map +1 -0
  112. package/dist/src/trace/progress.d.ts +58 -0
  113. package/dist/src/trace/progress.d.ts.map +1 -0
  114. package/dist/src/trace/progress.js +83 -0
  115. package/dist/src/trace/progress.js.map +1 -0
  116. package/dist/src/vm/arith.d.ts +29 -0
  117. package/dist/src/vm/arith.d.ts.map +1 -0
  118. package/dist/src/vm/arith.js +258 -0
  119. package/dist/src/vm/arith.js.map +1 -0
  120. package/dist/src/vm/builtins.d.ts +31 -0
  121. package/dist/src/vm/builtins.d.ts.map +1 -0
  122. package/dist/src/vm/builtins.js +1773 -0
  123. package/dist/src/vm/builtins.js.map +1 -0
  124. package/dist/src/vm/emulate.d.ts +75 -0
  125. package/dist/src/vm/emulate.d.ts.map +1 -0
  126. package/dist/src/vm/emulate.js +380 -0
  127. package/dist/src/vm/emulate.js.map +1 -0
  128. package/dist/src/vm/expand.d.ts +68 -0
  129. package/dist/src/vm/expand.d.ts.map +1 -0
  130. package/dist/src/vm/expand.js +744 -0
  131. package/dist/src/vm/expand.js.map +1 -0
  132. package/dist/src/vm/external.d.ts +34 -0
  133. package/dist/src/vm/external.d.ts.map +1 -0
  134. package/dist/src/vm/external.js +228 -0
  135. package/dist/src/vm/external.js.map +1 -0
  136. package/dist/src/vm/fifo.d.ts +66 -0
  137. package/dist/src/vm/fifo.d.ts.map +1 -0
  138. package/dist/src/vm/fifo.js +232 -0
  139. package/dist/src/vm/fifo.js.map +1 -0
  140. package/dist/src/vm/interp.d.ts +209 -0
  141. package/dist/src/vm/interp.d.ts.map +1 -0
  142. package/dist/src/vm/interp.js +1641 -0
  143. package/dist/src/vm/interp.js.map +1 -0
  144. package/dist/src/vm/io.d.ts +180 -0
  145. package/dist/src/vm/io.d.ts.map +1 -0
  146. package/dist/src/vm/io.js +502 -0
  147. package/dist/src/vm/io.js.map +1 -0
  148. package/dist/src/vm/pattern.d.ts +46 -0
  149. package/dist/src/vm/pattern.d.ts.map +1 -0
  150. package/dist/src/vm/pattern.js +498 -0
  151. package/dist/src/vm/pattern.js.map +1 -0
  152. package/dist/src/vm/proc.d.ts +94 -0
  153. package/dist/src/vm/proc.d.ts.map +1 -0
  154. package/dist/src/vm/proc.js +130 -0
  155. package/dist/src/vm/proc.js.map +1 -0
  156. package/dist/src/vm/state.d.ts +104 -0
  157. package/dist/src/vm/state.d.ts.map +1 -0
  158. package/dist/src/vm/state.js +233 -0
  159. package/dist/src/vm/state.js.map +1 -0
  160. package/dist/src/vm/test.d.ts +11 -0
  161. package/dist/src/vm/test.d.ts.map +1 -0
  162. package/dist/src/vm/test.js +277 -0
  163. package/dist/src/vm/test.js.map +1 -0
  164. package/package.json +63 -4
  165. package/src/analysis/analyze.ts +1395 -0
  166. package/src/analysis/fs.ts +121 -0
  167. package/src/analysis/outputs.ts +242 -0
  168. package/src/analysis/value.ts +264 -0
  169. package/src/behaviors/defs/core.ts +970 -0
  170. package/src/behaviors/defs/devtools.ts +400 -0
  171. package/src/behaviors/defs/macos.ts +426 -0
  172. package/src/behaviors/defs/tools.ts +596 -0
  173. package/src/behaviors/dsl.ts +293 -0
  174. package/src/behaviors/index.ts +19 -0
  175. package/src/behaviors/registry.ts +261 -0
  176. package/src/behaviors/roles.ts +187 -0
  177. package/src/behaviors/types.ts +127 -0
  178. package/src/index.ts +27 -0
  179. package/src/integrations/deepsea.ts +259 -0
  180. package/src/machine.ts +483 -0
  181. package/src/parser/ast.ts +472 -0
  182. package/src/parser/parser.ts +1826 -0
  183. package/src/policy/effects.ts +102 -0
  184. package/src/policy/policy.ts +578 -0
  185. package/src/printer/doc.ts +454 -0
  186. package/src/printer/highlight.ts +283 -0
  187. package/src/printer/html.ts +441 -0
  188. package/src/printer/print.ts +528 -0
  189. package/src/printer/summary.ts +601 -0
  190. package/src/trace/events.ts +102 -0
  191. package/src/trace/progress.ts +119 -0
  192. package/src/vm/arith.ts +236 -0
  193. package/src/vm/builtins.ts +1590 -0
  194. package/src/vm/emulate.ts +337 -0
  195. package/src/vm/expand.ts +721 -0
  196. package/src/vm/external.ts +265 -0
  197. package/src/vm/fifo.ts +226 -0
  198. package/src/vm/interp.ts +1623 -0
  199. package/src/vm/io.ts +570 -0
  200. package/src/vm/pattern.ts +477 -0
  201. package/src/vm/proc.ts +147 -0
  202. package/src/vm/state.ts +267 -0
  203. package/src/vm/test.ts +253 -0
@@ -0,0 +1,472 @@
1
+ /**
2
+ * The mash AST. Every node carries a numeric `id` (unique within one parse,
3
+ * assigned in source order) and a `span` of UTF-16 offsets into the parsed
4
+ * source, so runtime trace events, static-analysis findings and UI
5
+ * highlighting can all refer to exact source ranges.
6
+ *
7
+ * Design notes:
8
+ * - Trivial wrappers are collapsed: a `Pipeline` node exists only for two or
9
+ * more stages (or a negated / timed one), an `AndOr` only for two or more
10
+ * pipelines. A statement's `command` may therefore be any `Command`.
11
+ * - Redirections live on the command they apply to (simple or compound), as
12
+ * in the bash grammar.
13
+ * - Words keep their quoting structure (`WordPart`s) so expansion, globbing
14
+ * and static analysis can tell quoted from unquoted text.
15
+ */
16
+
17
+ export interface Span {
18
+ /** Inclusive start offset into the source. */
19
+ start: number
20
+ /** Exclusive end offset into the source. */
21
+ end: number
22
+ }
23
+
24
+ interface NodeBase {
25
+ id: number
26
+ span: Span
27
+ }
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Script and statements
31
+ // ---------------------------------------------------------------------------
32
+
33
+ export interface Script extends NodeBase {
34
+ type: 'Script'
35
+ body: Stmt[]
36
+ /**
37
+ * With `parse(src, { partial: true })`: the syntax error that stopped
38
+ * parsing. `body` then holds the complete statements on lines before it —
39
+ * what bash, reading line by line, would run before reporting the error.
40
+ */
41
+ error?: import('./parser.ts').ParseError
42
+ /**
43
+ * Comments in source order (`#` to end of line, without the newline). Not
44
+ * part of the program; kept for the pretty-printer. Comments inside
45
+ * backquotes have approximate spans.
46
+ */
47
+ comments?: Comment[]
48
+ }
49
+
50
+ export interface Comment {
51
+ span: Span
52
+ text: string
53
+ }
54
+
55
+ /** One list element, terminated by `;`, `&`, a newline, or the end of its list. */
56
+ export interface Stmt extends NodeBase {
57
+ type: 'Stmt'
58
+ command: Command
59
+ /** Terminated by `&`: run asynchronously. */
60
+ background: boolean
61
+ }
62
+
63
+ export type Command =
64
+ | SimpleCommand
65
+ | Pipeline
66
+ | AndOr
67
+ | Subshell
68
+ | Group
69
+ | If
70
+ | Loop
71
+ | For
72
+ | ArithFor
73
+ | Select
74
+ | Case
75
+ | FunctionDef
76
+ | ArithCommand
77
+ | CondCommand
78
+
79
+ export type CompoundCommand = Subshell | Group | If | Loop | For | ArithFor | Select | Case | ArithCommand | CondCommand
80
+
81
+ export interface Pipeline extends NodeBase {
82
+ type: 'Pipeline'
83
+ stages: Command[]
84
+ /** `pipeStderr[i]`: the pipe after stage i is `|&`. Length `stages.length - 1`. */
85
+ pipeStderr: boolean[]
86
+ /** Prefixed by `!`. */
87
+ negated: boolean
88
+ /** Prefixed by the `time` keyword. */
89
+ timed: boolean
90
+ }
91
+
92
+ export interface AndOr extends NodeBase {
93
+ type: 'AndOr'
94
+ /** Two or more items. */
95
+ items: Command[]
96
+ /** `ops[i]` joins `items[i]` and `items[i+1]`. */
97
+ ops: ('&&' | '||')[]
98
+ }
99
+
100
+ export interface SimpleCommand extends NodeBase {
101
+ type: 'SimpleCommand'
102
+ /** Prefix assignments (`A=1 B=2 cmd`), or a bare assignment statement. */
103
+ assigns: Assign[]
104
+ /**
105
+ * Command name and arguments. `Assign` entries appear only after a literal
106
+ * declaration builtin (`declare`, `local`, `export`, `readonly`, `typeset`),
107
+ * e.g. `local -a xs=(1 2)`.
108
+ */
109
+ words: (Word | Assign)[]
110
+ redirs: Redirect[]
111
+ }
112
+
113
+ // ---------------------------------------------------------------------------
114
+ // Compound commands
115
+ // ---------------------------------------------------------------------------
116
+
117
+ export interface Subshell extends NodeBase {
118
+ type: 'Subshell'
119
+ body: Stmt[]
120
+ redirs: Redirect[]
121
+ }
122
+
123
+ export interface Group extends NodeBase {
124
+ type: 'Group'
125
+ body: Stmt[]
126
+ redirs: Redirect[]
127
+ }
128
+
129
+ export interface IfClause {
130
+ cond: Stmt[]
131
+ body: Stmt[]
132
+ }
133
+
134
+ export interface If extends NodeBase {
135
+ type: 'If'
136
+ clauses: IfClause[]
137
+ elseBody: Stmt[] | null
138
+ redirs: Redirect[]
139
+ }
140
+
141
+ export interface Loop extends NodeBase {
142
+ type: 'Loop'
143
+ kind: 'while' | 'until'
144
+ cond: Stmt[]
145
+ body: Stmt[]
146
+ redirs: Redirect[]
147
+ }
148
+
149
+ export interface For extends NodeBase {
150
+ type: 'For'
151
+ variable: string
152
+ /** `null` when the `in` clause is absent (iterate over "$@"). */
153
+ items: Word[] | null
154
+ body: Stmt[]
155
+ redirs: Redirect[]
156
+ }
157
+
158
+ export interface ArithFor extends NodeBase {
159
+ type: 'ArithFor'
160
+ init: ArithExpr | null
161
+ cond: ArithExpr | null
162
+ step: ArithExpr | null
163
+ body: Stmt[]
164
+ redirs: Redirect[]
165
+ }
166
+
167
+ export interface Select extends NodeBase {
168
+ type: 'Select'
169
+ variable: string
170
+ items: Word[] | null
171
+ body: Stmt[]
172
+ redirs: Redirect[]
173
+ }
174
+
175
+ export interface CaseItem extends NodeBase {
176
+ type: 'CaseItem'
177
+ patterns: Word[]
178
+ body: Stmt[]
179
+ /** `;;` stop, `;&` fall through, `;;&` test the next patterns. */
180
+ terminator: ';;' | ';&' | ';;&'
181
+ }
182
+
183
+ export interface Case extends NodeBase {
184
+ type: 'Case'
185
+ word: Word
186
+ items: CaseItem[]
187
+ redirs: Redirect[]
188
+ }
189
+
190
+ export interface FunctionDef extends NodeBase {
191
+ type: 'FunctionDef'
192
+ name: string
193
+ body: CompoundCommand
194
+ }
195
+
196
+ export interface ArithCommand extends NodeBase {
197
+ type: 'ArithCommand'
198
+ expr: ArithExpr
199
+ redirs: Redirect[]
200
+ }
201
+
202
+ export interface CondCommand extends NodeBase {
203
+ type: 'CondCommand'
204
+ expr: CondExpr
205
+ redirs: Redirect[]
206
+ }
207
+
208
+ // ---------------------------------------------------------------------------
209
+ // Assignments and redirections
210
+ // ---------------------------------------------------------------------------
211
+
212
+ export interface ArrayElem {
213
+ /** `[key]=value` form; key is a word (assoc) or arithmetic text (indexed), resolved at runtime. */
214
+ index: Word | null
215
+ value: Word
216
+ }
217
+
218
+ export interface ArrayLiteral extends NodeBase {
219
+ type: 'ArrayLiteral'
220
+ elems: ArrayElem[]
221
+ }
222
+
223
+ export interface Assign extends NodeBase {
224
+ type: 'Assign'
225
+ name: string
226
+ /** `name[index]=...`; the raw subscript as a word (expanded at runtime). */
227
+ index: Word | null
228
+ /** `+=` */
229
+ append: boolean
230
+ /** `null` for `name=` with nothing after (empty string) or for bare `declare name`. */
231
+ value: Word | ArrayLiteral | null
232
+ }
233
+
234
+ export type RedirectOp =
235
+ | '<' | '>' | '>>' | '>|' | '<>'
236
+ | '<&' | '>&'
237
+ | '&>' | '&>>'
238
+ | '<<' | '<<-' | '<<<'
239
+
240
+ export interface HereDoc {
241
+ delimiter: string
242
+ /** The delimiter was quoted: the body is literal (no expansions). */
243
+ quoted: boolean
244
+ /** The body, as a word. For unquoted delimiters it carries expansions. */
245
+ body: Word
246
+ }
247
+
248
+ export interface Redirect extends NodeBase {
249
+ type: 'Redirect'
250
+ op: RedirectOp
251
+ /** Explicit fd number (`2>`), or null for the operator's default. */
252
+ fd: number | null
253
+ /** `{name}>file`: allocate an fd and store it in variable `name`. */
254
+ fdVar: string | null
255
+ /** The file, fd number (`>&2`), `-` (close), or here-string word. For heredocs, the delimiter word. */
256
+ target: Word
257
+ heredoc: HereDoc | null
258
+ }
259
+
260
+ // ---------------------------------------------------------------------------
261
+ // Words
262
+ // ---------------------------------------------------------------------------
263
+
264
+ export interface Word extends NodeBase {
265
+ type: 'Word'
266
+ parts: WordPart[]
267
+ }
268
+
269
+ export type WordPart =
270
+ | Lit
271
+ | SglQuoted
272
+ | Escaped
273
+ | DblQuoted
274
+ | ParamExp
275
+ | CmdSubst
276
+ | ArithExp
277
+ | ProcSubst
278
+
279
+ /** Unquoted literal text. Glob, brace and tilde expansion apply to it. */
280
+ export interface Lit extends NodeBase {
281
+ type: 'Lit'
282
+ value: string
283
+ }
284
+
285
+ /** `'...'` or, with `ansi`, `$'...'` (value already decoded). */
286
+ export interface SglQuoted extends NodeBase {
287
+ type: 'SglQuoted'
288
+ value: string
289
+ ansi: boolean
290
+ }
291
+
292
+ /** A backslash-escaped character outside double quotes (`\*`). */
293
+ export interface Escaped extends NodeBase {
294
+ type: 'Escaped'
295
+ value: string
296
+ }
297
+
298
+ /** `"..."`: inner parts are Lit (quoted text), ParamExp, CmdSubst, ArithExp. */
299
+ export interface DblQuoted extends NodeBase {
300
+ type: 'DblQuoted'
301
+ parts: WordPart[]
302
+ /** `$"..."` locale string (treated as plain double quotes). */
303
+ locale: boolean
304
+ }
305
+
306
+ export type ParamOp =
307
+ | { kind: 'default' | 'assign' | 'error' | 'alternative'; colon: boolean; word: Word | null }
308
+ | { kind: 'removePrefix' | 'removeSuffix'; longest: boolean; pattern: Word }
309
+ | { kind: 'replace'; mode: 'first' | 'all' | 'prefix' | 'suffix'; pattern: Word; replacement: Word | null }
310
+ | { kind: 'case'; upper: boolean; all: boolean; pattern: Word | null }
311
+ | { kind: 'substring'; offset: ArithExpr; length: ArithExpr | null }
312
+ | { kind: 'transform'; operator: string }
313
+
314
+ export interface ParamExp extends NodeBase {
315
+ type: 'ParamExp'
316
+ /** `$x` (true) vs `${x}` (false). */
317
+ short: boolean
318
+ /** Variable name, positional digit(s), or special parameter (`@ * # ? - $ ! 0`). */
319
+ name: string
320
+ /** `${a[i]}`: subscript word; `@`/`*` subscripts are represented literally. */
321
+ index: Word | null
322
+ /** `${#x}` */
323
+ length: boolean
324
+ /** `${!x}` indirection; with index `@`/`*` it means "keys of array". */
325
+ indirect: boolean
326
+ /** `${!prefix*}` / `${!prefix@}`: names of variables with this prefix. */
327
+ prefixNames: '*' | '@' | null
328
+ op: ParamOp | null
329
+ }
330
+
331
+ export interface CmdSubst extends NodeBase {
332
+ type: 'CmdSubst'
333
+ body: Stmt[]
334
+ backquote: boolean
335
+ }
336
+
337
+ export interface ArithExp extends NodeBase {
338
+ type: 'ArithExp'
339
+ expr: ArithExpr
340
+ }
341
+
342
+ export interface ProcSubst extends NodeBase {
343
+ type: 'ProcSubst'
344
+ direction: '<' | '>'
345
+ body: Stmt[]
346
+ }
347
+
348
+ // ---------------------------------------------------------------------------
349
+ // Arithmetic
350
+ // ---------------------------------------------------------------------------
351
+
352
+ export type ArithExpr =
353
+ | ArithNum
354
+ | ArithVar
355
+ | ArithWord
356
+ | ArithUnary
357
+ | ArithBinary
358
+ | ArithAssign
359
+ | ArithTernary
360
+ | ArithIncDec
361
+ | ArithGroup
362
+
363
+ export interface ArithNum extends NodeBase {
364
+ type: 'ArithNum'
365
+ /** Source text (`0x1f`, `8#17`, `42`). */
366
+ text: string
367
+ }
368
+
369
+ export interface ArithVar extends NodeBase {
370
+ type: 'ArithVar'
371
+ name: string
372
+ index: ArithExpr | null
373
+ }
374
+
375
+ /** A `$`-expansion inside arithmetic; bash expands it textually before evaluation. */
376
+ export interface ArithWord extends NodeBase {
377
+ type: 'ArithWord'
378
+ word: Word
379
+ }
380
+
381
+ export interface ArithUnary extends NodeBase {
382
+ type: 'ArithUnary'
383
+ op: '-' | '+' | '!' | '~'
384
+ operand: ArithExpr
385
+ }
386
+
387
+ export type ArithBinaryOp =
388
+ | '+' | '-' | '*' | '/' | '%' | '**'
389
+ | '<<' | '>>' | '&' | '|' | '^'
390
+ | '<' | '>' | '<=' | '>=' | '==' | '!='
391
+ | '&&' | '||' | ','
392
+
393
+ export interface ArithBinary extends NodeBase {
394
+ type: 'ArithBinary'
395
+ op: ArithBinaryOp
396
+ left: ArithExpr
397
+ right: ArithExpr
398
+ }
399
+
400
+ export interface ArithAssign extends NodeBase {
401
+ type: 'ArithAssign'
402
+ op: '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '<<=' | '>>=' | '&=' | '|=' | '^='
403
+ target: ArithVar
404
+ value: ArithExpr
405
+ }
406
+
407
+ export interface ArithTernary extends NodeBase {
408
+ type: 'ArithTernary'
409
+ cond: ArithExpr
410
+ then: ArithExpr
411
+ else: ArithExpr
412
+ }
413
+
414
+ export interface ArithIncDec extends NodeBase {
415
+ type: 'ArithIncDec'
416
+ op: '++' | '--'
417
+ prefix: boolean
418
+ target: ArithVar
419
+ }
420
+
421
+ export interface ArithGroup extends NodeBase {
422
+ type: 'ArithGroup'
423
+ expr: ArithExpr
424
+ }
425
+
426
+ // ---------------------------------------------------------------------------
427
+ // [[ conditional expressions ]]
428
+ // ---------------------------------------------------------------------------
429
+
430
+ export type CondExpr = CondWord | CondUnary | CondBinary | CondNot | CondAndOr | CondGroup
431
+
432
+ export interface CondWord extends NodeBase {
433
+ type: 'CondWord'
434
+ word: Word
435
+ }
436
+
437
+ export interface CondUnary extends NodeBase {
438
+ type: 'CondUnary'
439
+ /** `-f`, `-d`, `-z`, `-n`, `-v`, ... */
440
+ op: string
441
+ operand: Word
442
+ }
443
+
444
+ export interface CondBinary extends NodeBase {
445
+ type: 'CondBinary'
446
+ /** `==`, `=`, `!=`, `=~`, `<`, `>`, `-eq`, `-nt`, ... */
447
+ op: string
448
+ left: Word
449
+ right: Word
450
+ }
451
+
452
+ export interface CondNot extends NodeBase {
453
+ type: 'CondNot'
454
+ operand: CondExpr
455
+ }
456
+
457
+ export interface CondAndOr extends NodeBase {
458
+ type: 'CondAndOr'
459
+ op: '&&' | '||'
460
+ left: CondExpr
461
+ right: CondExpr
462
+ }
463
+
464
+ export interface CondGroup extends NodeBase {
465
+ type: 'CondGroup'
466
+ expr: CondExpr
467
+ }
468
+
469
+ export type Node =
470
+ | Script | Stmt | Command | CaseItem | Assign | ArrayLiteral | Redirect | Word | WordPart | ArithExpr | CondExpr
471
+
472
+ export const DECL_BUILTINS: ReadonlySet<string> = new Set(['declare', 'typeset', 'local', 'export', 'readonly'])