OILS / doc / old / errors.md View on Github | oilshell.org

296 lines, 187 significant
1---
2in_progress: yes
3css_files: ../../web/base.css ../../web/manual.css ../../web/toc.css
4---
5
6List of Errors in the OSH Interpreter
7=====================================
8
9<div id="toc">
10</div>
11
12Parse Error:
13 Can be determined statically
14 spec/parse-errors.test.sh
15
16
17
18TODO: See test/runtime-errors.sh. Merge them here.
19
20## Syntax Errors in Oil String Literals
21
22- `parse_backslash`
23 - no octal
24 - no `\z`
25 - no `\u{invalid`
26
27- `parse_backticks`
28 - use "$(echo hi)"` and not backticks
29
30## Fatal vs. Non-Fatal
31
32Fatal Error:
33 terminates the interpreter unconditionally, e.g. divide by zero does this in
34 bash.
35
36Non-fatal error:
37 terminates the current builtin and exits 1
38
39non-fatal errors can be turned into fatal errors.
40
41by Strict modes:
42 set -o errexit
43
44strict modes can also things that are not errors at all into fatal errors
45 set -o nounset
46 set -o failglob
47
48Fatal errors can be turned into non-fatal ones!!!!
49
50by dparen:
51
52 (( 1 / 0 ))
53
54by command sub -- although this involves another process so it's
55understandable!
56
57 set -o errexit
58 echo $(exit 1)
59
60## Strict Modes
61
62strict_array
63strict_errexit
64strict_arith
65
66TODO: strict-word-eval?
67 for unicode errors
68 for subshell negative indices? I think this is most consistent right now.
69
70
71## Parse Error API
72
73TODO:
74
75 p_die() internally
76
77
78 w = w_parser.ReadWord()
79 if w is None:
80 do something with w_parser.Error()
81
82Related to memory management API:
83
84 # arena is the out param
85 arena = pool.NewArena()
86 c_parser = cmd_parse.CommandParser(w_parser, arena)
87 bool ok = c_parser.Parse()
88 if ok:
89 arena.RootNode() # turns indexes into pointers?
90 arena.Deallocate() # d
91 else:
92 c_parser.Error() # Is this still a stack?
93
94## Runtime Error API: error codes + error contexts?
95
96Idea:
97
98- Should we have a table of errors for metaprogramming?
99 - assign each one of these a code, and decide what to do based on a table?
100 - then have an error CONTEXT
101 - based on spec tests?
102
103 - and error context takes an error code, looks it up in a table, and decides
104 whether to catch or to reraise!
105
106List of contexts:
107
108- assignment a=$() exit code
109- command sub $()
110- subshell ()
111- pipeline? ls | { foo; exit 1; }
112- dparen (( )) vs. arith sub $(( ))
113
114## Problem in bash: Context affects a lot
115
116echo $(( 1 / 0 ))
117echo 'after-$(())
118(( 1 / 0 ))
119echo 'after-$(())
120
121
122## Arith Eval
123
124Divide by zero: $(( 1 / 0 ))
125
126 ^
127Maybe: integer overflow. But we want big numbers.
128
129Type errors between integers and strings:
130
131 x=foo
132 $(( x * 2 )) # doesn't make sense, except in bash's crazy world.
133
134Invalid hex constant:
135
136 x=0xabcg
137 echo $(( x * 2 )) (fatal in bash)
138
139## Bool Eval
140
141regcomp parse error:
142
143x=$(cat invalid-syntax.txt)
144[[ foo =~ $x ]]
145
146## Word Eval
147
148IMPORTANT: Command sub error $(exit 1)
149
150User-requested error: ${undef?error}
151
152set -o nounset
153
154 def _EmptyStrOrError(self, val, token=None):
155 # calls `e_die()`
156
157Variants:
158 nounset: index out of bounds ${a[3]}
159 I guess same diagnostic?
160
161In bash you can set an index out of bounds, like
162b[2]=9
163Might want to have a mode for this?
164
165set -o failglob
166 TODO: not implemented
167 might need PWD diagnostic
168
169
170
171Redirects:
172 Redirect to empty filename/descriptor ( or array)
173
174{ break; }
175 ^~~~~~ break only invalid inside loop, etc.
176
177
178NotImplementedError
179 - e.g for var ref ${!a}
180 - bash associative arrays? I think we want most of that
181 - $"" ?
182 - |& not yet done
183 - ;;& for case -- although parsing it is all of the work I guess
184 - some could be parse time errors too though?
185
186
187- String Slicing and String Length require valid utf-8 characters
188
189 s=$(cat invalid.txt)
190 echo ${#s} # code points
191 echo ${s:1:3} # code points
192
193- Slicing: Index is negative. ${foo: -4} and ${foo: 1 : -4} aren't supported
194 right now, unlike bash and zsh.
195
196## Command Exec
197
198IMPORTANT: subshell error ( exit 1 )
199
200set -o errexit -- turns NON-FATAL error into FATAL error.
201
202set -o pipefail
203 pipefail might need some fanciness for ${PIPESTATUS}
204
205Trying to set readonly variable:
206 readonly foo=bar
207 foo=x
208 (could any of this be done at compile time?)
209
210 - this needs two locations: where the assignment was, and where it was
211 declared readonly.
212
213Trying to redeclare a variable? That can also be parse time.
214local x=1
215local x=2
216
217Type errors between Str and StrArray: -- strict-array controls this
218 EvalWordToString calls e_die()`
219
220 echo foo > "$@"
221 ^-- # Should have what it evaluated to? # This could be static too
222
223 case "$@" in
224 "$@") echo bad;;
225 esac
226
227 ${undef:-"$@"} is OK, but ${var%"$@"} doesn't make sense really.
228 ${v/"$@"/"$@"}
229
230
231LHS evaluation:
232 s='abc'
233 s[1]=X # invalid because it's a string, not an array
234
235
236Invalid descriptor:
237
238
239fd=$(cat invalid.txt)
240echo foo 2>& $fd
241
242### Builtins
243
244In core/builtins.py:
245
246 util.usage('...')
247 return 1
248
249A usage error is a runtime error that results in the builtin returning 1.
250
251Builtin has too many arguments -- but this falls under the errexit rule
252 cd foo bar baz
253 continue "$@"
254(Parse error: continue 1 2 3)
255
256Although we might want to highlight the extra args.
257
258
259
260## Syscall Failures
261
262Fatal error from system calls:
263 fork() could fail in theory
264
265Some are not failures:
266
267 stat() [[ -f /tmp/foo ]]
268 cd /ff chdir() # exit code 1
269 cat <nonexistent # This is just exit code 1
270
271## Interpreter Failures
272
273Runtime: Stack Too Deep (catch infinite recursion)
274Out of memory: should not happen with OSH, but maybe with Oil
275
276Runtime Parse Errors
277--------------------
278
279The way bash works 0x$var can be a hex literal.
280so var=xx makes this invalid. hex/octal/decimal have this problem.
281
282
283Parse Time Errors
284-----------------
285
286regcomp() errors (sometimes at parse time; other times at runtime)
287
288Need to show stack trace for "source" like Python. Prototype this.
289
290Also might show which token thing caused you to be in arith parse state, like:
291
292$((echo hi))
293^~ ^~
294Arith Invalid token
295
296