@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.
- package/LICENSE +21 -0
- package/README.md +275 -2
- package/bin/mash.ts +253 -0
- package/dist/bin/mash.d.ts +39 -0
- package/dist/bin/mash.d.ts.map +1 -0
- package/dist/bin/mash.js +281 -0
- package/dist/bin/mash.js.map +1 -0
- package/dist/src/analysis/analyze.d.ts +97 -0
- package/dist/src/analysis/analyze.d.ts.map +1 -0
- package/dist/src/analysis/analyze.js +1406 -0
- package/dist/src/analysis/analyze.js.map +1 -0
- package/dist/src/analysis/fs.d.ts +39 -0
- package/dist/src/analysis/fs.d.ts.map +1 -0
- package/dist/src/analysis/fs.js +117 -0
- package/dist/src/analysis/fs.js.map +1 -0
- package/dist/src/analysis/outputs.d.ts +16 -0
- package/dist/src/analysis/outputs.d.ts.map +1 -0
- package/dist/src/analysis/outputs.js +277 -0
- package/dist/src/analysis/outputs.js.map +1 -0
- package/dist/src/analysis/value.d.ts +76 -0
- package/dist/src/analysis/value.d.ts.map +1 -0
- package/dist/src/analysis/value.js +248 -0
- package/dist/src/analysis/value.js.map +1 -0
- package/dist/src/behaviors/defs/core.d.ts +15 -0
- package/dist/src/behaviors/defs/core.d.ts.map +1 -0
- package/dist/src/behaviors/defs/core.js +1084 -0
- package/dist/src/behaviors/defs/core.js.map +1 -0
- package/dist/src/behaviors/defs/devtools.d.ts +9 -0
- package/dist/src/behaviors/defs/devtools.d.ts.map +1 -0
- package/dist/src/behaviors/defs/devtools.js +432 -0
- package/dist/src/behaviors/defs/devtools.js.map +1 -0
- package/dist/src/behaviors/defs/macos.d.ts +12 -0
- package/dist/src/behaviors/defs/macos.d.ts.map +1 -0
- package/dist/src/behaviors/defs/macos.js +454 -0
- package/dist/src/behaviors/defs/macos.js.map +1 -0
- package/dist/src/behaviors/defs/tools.d.ts +9 -0
- package/dist/src/behaviors/defs/tools.d.ts.map +1 -0
- package/dist/src/behaviors/defs/tools.js +639 -0
- package/dist/src/behaviors/defs/tools.js.map +1 -0
- package/dist/src/behaviors/dsl.d.ts +95 -0
- package/dist/src/behaviors/dsl.d.ts.map +1 -0
- package/dist/src/behaviors/dsl.js +267 -0
- package/dist/src/behaviors/dsl.js.map +1 -0
- package/dist/src/behaviors/index.d.ts +12 -0
- package/dist/src/behaviors/index.d.ts.map +1 -0
- package/dist/src/behaviors/index.js +18 -0
- package/dist/src/behaviors/index.js.map +1 -0
- package/dist/src/behaviors/registry.d.ts +45 -0
- package/dist/src/behaviors/registry.d.ts.map +1 -0
- package/dist/src/behaviors/registry.js +266 -0
- package/dist/src/behaviors/registry.js.map +1 -0
- package/dist/src/behaviors/roles.d.ts +29 -0
- package/dist/src/behaviors/roles.d.ts.map +1 -0
- package/dist/src/behaviors/roles.js +198 -0
- package/dist/src/behaviors/roles.js.map +1 -0
- package/dist/src/behaviors/types.d.ts +120 -0
- package/dist/src/behaviors/types.d.ts.map +1 -0
- package/dist/src/behaviors/types.js +12 -0
- package/dist/src/behaviors/types.js.map +1 -0
- package/dist/src/index.d.ts +27 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +24 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/integrations/deepsea.d.ts +121 -0
- package/dist/src/integrations/deepsea.d.ts.map +1 -0
- package/dist/src/integrations/deepsea.js +199 -0
- package/dist/src/integrations/deepsea.js.map +1 -0
- package/dist/src/machine.d.ts +139 -0
- package/dist/src/machine.d.ts.map +1 -0
- package/dist/src/machine.js +400 -0
- package/dist/src/machine.js.map +1 -0
- package/dist/src/parser/ast.d.ts +369 -0
- package/dist/src/parser/ast.d.ts.map +1 -0
- package/dist/src/parser/ast.js +17 -0
- package/dist/src/parser/ast.js.map +1 -0
- package/dist/src/parser/parser.d.ts +48 -0
- package/dist/src/parser/parser.d.ts.map +1 -0
- package/dist/src/parser/parser.js +1950 -0
- package/dist/src/parser/parser.js.map +1 -0
- package/dist/src/policy/effects.d.ts +86 -0
- package/dist/src/policy/effects.d.ts.map +1 -0
- package/dist/src/policy/effects.js +53 -0
- package/dist/src/policy/effects.js.map +1 -0
- package/dist/src/policy/policy.d.ts +130 -0
- package/dist/src/policy/policy.d.ts.map +1 -0
- package/dist/src/policy/policy.js +532 -0
- package/dist/src/policy/policy.js.map +1 -0
- package/dist/src/printer/doc.d.ts +151 -0
- package/dist/src/printer/doc.d.ts.map +1 -0
- package/dist/src/printer/doc.js +409 -0
- package/dist/src/printer/doc.js.map +1 -0
- package/dist/src/printer/highlight.d.ts +53 -0
- package/dist/src/printer/highlight.d.ts.map +1 -0
- package/dist/src/printer/highlight.js +339 -0
- package/dist/src/printer/highlight.js.map +1 -0
- package/dist/src/printer/html.d.ts +72 -0
- package/dist/src/printer/html.d.ts.map +1 -0
- package/dist/src/printer/html.js +423 -0
- package/dist/src/printer/html.js.map +1 -0
- package/dist/src/printer/print.d.ts +63 -0
- package/dist/src/printer/print.d.ts.map +1 -0
- package/dist/src/printer/print.js +484 -0
- package/dist/src/printer/print.js.map +1 -0
- package/dist/src/printer/summary.d.ts +50 -0
- package/dist/src/printer/summary.d.ts.map +1 -0
- package/dist/src/printer/summary.js +621 -0
- package/dist/src/printer/summary.js.map +1 -0
- package/dist/src/trace/events.d.ts +183 -0
- package/dist/src/trace/events.d.ts.map +1 -0
- package/dist/src/trace/events.js +9 -0
- package/dist/src/trace/events.js.map +1 -0
- package/dist/src/trace/progress.d.ts +58 -0
- package/dist/src/trace/progress.d.ts.map +1 -0
- package/dist/src/trace/progress.js +83 -0
- package/dist/src/trace/progress.js.map +1 -0
- package/dist/src/vm/arith.d.ts +29 -0
- package/dist/src/vm/arith.d.ts.map +1 -0
- package/dist/src/vm/arith.js +258 -0
- package/dist/src/vm/arith.js.map +1 -0
- package/dist/src/vm/builtins.d.ts +31 -0
- package/dist/src/vm/builtins.d.ts.map +1 -0
- package/dist/src/vm/builtins.js +1773 -0
- package/dist/src/vm/builtins.js.map +1 -0
- package/dist/src/vm/emulate.d.ts +75 -0
- package/dist/src/vm/emulate.d.ts.map +1 -0
- package/dist/src/vm/emulate.js +380 -0
- package/dist/src/vm/emulate.js.map +1 -0
- package/dist/src/vm/expand.d.ts +68 -0
- package/dist/src/vm/expand.d.ts.map +1 -0
- package/dist/src/vm/expand.js +744 -0
- package/dist/src/vm/expand.js.map +1 -0
- package/dist/src/vm/external.d.ts +34 -0
- package/dist/src/vm/external.d.ts.map +1 -0
- package/dist/src/vm/external.js +228 -0
- package/dist/src/vm/external.js.map +1 -0
- package/dist/src/vm/fifo.d.ts +66 -0
- package/dist/src/vm/fifo.d.ts.map +1 -0
- package/dist/src/vm/fifo.js +232 -0
- package/dist/src/vm/fifo.js.map +1 -0
- package/dist/src/vm/interp.d.ts +209 -0
- package/dist/src/vm/interp.d.ts.map +1 -0
- package/dist/src/vm/interp.js +1641 -0
- package/dist/src/vm/interp.js.map +1 -0
- package/dist/src/vm/io.d.ts +180 -0
- package/dist/src/vm/io.d.ts.map +1 -0
- package/dist/src/vm/io.js +502 -0
- package/dist/src/vm/io.js.map +1 -0
- package/dist/src/vm/pattern.d.ts +46 -0
- package/dist/src/vm/pattern.d.ts.map +1 -0
- package/dist/src/vm/pattern.js +498 -0
- package/dist/src/vm/pattern.js.map +1 -0
- package/dist/src/vm/proc.d.ts +94 -0
- package/dist/src/vm/proc.d.ts.map +1 -0
- package/dist/src/vm/proc.js +130 -0
- package/dist/src/vm/proc.js.map +1 -0
- package/dist/src/vm/state.d.ts +104 -0
- package/dist/src/vm/state.d.ts.map +1 -0
- package/dist/src/vm/state.js +233 -0
- package/dist/src/vm/state.js.map +1 -0
- package/dist/src/vm/test.d.ts +11 -0
- package/dist/src/vm/test.d.ts.map +1 -0
- package/dist/src/vm/test.js +277 -0
- package/dist/src/vm/test.js.map +1 -0
- package/package.json +63 -4
- package/src/analysis/analyze.ts +1395 -0
- package/src/analysis/fs.ts +121 -0
- package/src/analysis/outputs.ts +242 -0
- package/src/analysis/value.ts +264 -0
- package/src/behaviors/defs/core.ts +970 -0
- package/src/behaviors/defs/devtools.ts +400 -0
- package/src/behaviors/defs/macos.ts +426 -0
- package/src/behaviors/defs/tools.ts +596 -0
- package/src/behaviors/dsl.ts +293 -0
- package/src/behaviors/index.ts +19 -0
- package/src/behaviors/registry.ts +261 -0
- package/src/behaviors/roles.ts +187 -0
- package/src/behaviors/types.ts +127 -0
- package/src/index.ts +27 -0
- package/src/integrations/deepsea.ts +259 -0
- package/src/machine.ts +483 -0
- package/src/parser/ast.ts +472 -0
- package/src/parser/parser.ts +1826 -0
- package/src/policy/effects.ts +102 -0
- package/src/policy/policy.ts +578 -0
- package/src/printer/doc.ts +454 -0
- package/src/printer/highlight.ts +283 -0
- package/src/printer/html.ts +441 -0
- package/src/printer/print.ts +528 -0
- package/src/printer/summary.ts +601 -0
- package/src/trace/events.ts +102 -0
- package/src/trace/progress.ts +119 -0
- package/src/vm/arith.ts +236 -0
- package/src/vm/builtins.ts +1590 -0
- package/src/vm/emulate.ts +337 -0
- package/src/vm/expand.ts +721 -0
- package/src/vm/external.ts +265 -0
- package/src/vm/fifo.ts +226 -0
- package/src/vm/interp.ts +1623 -0
- package/src/vm/io.ts +570 -0
- package/src/vm/pattern.ts +477 -0
- package/src/vm/proc.ts +147 -0
- package/src/vm/state.ts +267 -0
- 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'])
|