| 1 | ---
|
| 2 | in_progress: yes
|
| 3 | css_files: ../../web/base.css ../../web/manual.css ../../web/toc.css
|
| 4 | ---
|
| 5 |
|
| 6 | List of Errors in the OSH Interpreter
|
| 7 | =====================================
|
| 8 |
|
| 9 | <div id="toc">
|
| 10 | </div>
|
| 11 |
|
| 12 | Parse Error:
|
| 13 | Can be determined statically
|
| 14 | spec/parse-errors.test.sh
|
| 15 |
|
| 16 |
|
| 17 |
|
| 18 | TODO: 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 |
|
| 32 | Fatal Error:
|
| 33 | terminates the interpreter unconditionally, e.g. divide by zero does this in
|
| 34 | bash.
|
| 35 |
|
| 36 | Non-fatal error:
|
| 37 | terminates the current builtin and exits 1
|
| 38 |
|
| 39 | non-fatal errors can be turned into fatal errors.
|
| 40 |
|
| 41 | by Strict modes:
|
| 42 | set -o errexit
|
| 43 |
|
| 44 | strict modes can also things that are not errors at all into fatal errors
|
| 45 | set -o nounset
|
| 46 | set -o failglob
|
| 47 |
|
| 48 | Fatal errors can be turned into non-fatal ones!!!!
|
| 49 |
|
| 50 | by dparen:
|
| 51 |
|
| 52 | (( 1 / 0 ))
|
| 53 |
|
| 54 | by command sub -- although this involves another process so it's
|
| 55 | understandable!
|
| 56 |
|
| 57 | set -o errexit
|
| 58 | echo $(exit 1)
|
| 59 |
|
| 60 | ## Strict Modes
|
| 61 |
|
| 62 | strict_array
|
| 63 | strict_errexit
|
| 64 | strict_arith
|
| 65 |
|
| 66 | TODO: 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 |
|
| 73 | TODO:
|
| 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 |
|
| 82 | Related 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 |
|
| 96 | Idea:
|
| 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 |
|
| 106 | List 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 |
|
| 116 | echo $(( 1 / 0 ))
|
| 117 | echo 'after-$(())
|
| 118 | (( 1 / 0 ))
|
| 119 | echo 'after-$(())
|
| 120 |
|
| 121 |
|
| 122 | ## Arith Eval
|
| 123 |
|
| 124 | Divide by zero: $(( 1 / 0 ))
|
| 125 |
|
| 126 | ^
|
| 127 | Maybe: integer overflow. But we want big numbers.
|
| 128 |
|
| 129 | Type errors between integers and strings:
|
| 130 |
|
| 131 | x=foo
|
| 132 | $(( x * 2 )) # doesn't make sense, except in bash's crazy world.
|
| 133 |
|
| 134 | Invalid hex constant:
|
| 135 |
|
| 136 | x=0xabcg
|
| 137 | echo $(( x * 2 )) (fatal in bash)
|
| 138 |
|
| 139 | ## Bool Eval
|
| 140 |
|
| 141 | regcomp parse error:
|
| 142 |
|
| 143 | x=$(cat invalid-syntax.txt)
|
| 144 | [[ foo =~ $x ]]
|
| 145 |
|
| 146 | ## Word Eval
|
| 147 |
|
| 148 | IMPORTANT: Command sub error $(exit 1)
|
| 149 |
|
| 150 | User-requested error: ${undef?error}
|
| 151 |
|
| 152 | set -o nounset
|
| 153 |
|
| 154 | def _EmptyStrOrError(self, val, token=None):
|
| 155 | # calls `e_die()`
|
| 156 |
|
| 157 | Variants:
|
| 158 | nounset: index out of bounds ${a[3]}
|
| 159 | I guess same diagnostic?
|
| 160 |
|
| 161 | In bash you can set an index out of bounds, like
|
| 162 | b[2]=9
|
| 163 | Might want to have a mode for this?
|
| 164 |
|
| 165 | set -o failglob
|
| 166 | TODO: not implemented
|
| 167 | might need PWD diagnostic
|
| 168 |
|
| 169 |
|
| 170 |
|
| 171 | Redirects:
|
| 172 | Redirect to empty filename/descriptor ( or array)
|
| 173 |
|
| 174 | { break; }
|
| 175 | ^~~~~~ break only invalid inside loop, etc.
|
| 176 |
|
| 177 |
|
| 178 | NotImplementedError
|
| 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 |
|
| 198 | IMPORTANT: subshell error ( exit 1 )
|
| 199 |
|
| 200 | set -o errexit -- turns NON-FATAL error into FATAL error.
|
| 201 |
|
| 202 | set -o pipefail
|
| 203 | pipefail might need some fanciness for ${PIPESTATUS}
|
| 204 |
|
| 205 | Trying 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 |
|
| 213 | Trying to redeclare a variable? That can also be parse time.
|
| 214 | local x=1
|
| 215 | local x=2
|
| 216 |
|
| 217 | Type 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 |
|
| 231 | LHS evaluation:
|
| 232 | s='abc'
|
| 233 | s[1]=X # invalid because it's a string, not an array
|
| 234 |
|
| 235 |
|
| 236 | Invalid descriptor:
|
| 237 |
|
| 238 |
|
| 239 | fd=$(cat invalid.txt)
|
| 240 | echo foo 2>& $fd
|
| 241 |
|
| 242 | ### Builtins
|
| 243 |
|
| 244 | In core/builtins.py:
|
| 245 |
|
| 246 | util.usage('...')
|
| 247 | return 1
|
| 248 |
|
| 249 | A usage error is a runtime error that results in the builtin returning 1.
|
| 250 |
|
| 251 | Builtin 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 |
|
| 256 | Although we might want to highlight the extra args.
|
| 257 |
|
| 258 |
|
| 259 |
|
| 260 | ## Syscall Failures
|
| 261 |
|
| 262 | Fatal error from system calls:
|
| 263 | fork() could fail in theory
|
| 264 |
|
| 265 | Some 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 |
|
| 273 | Runtime: Stack Too Deep (catch infinite recursion)
|
| 274 | Out of memory: should not happen with OSH, but maybe with Oil
|
| 275 |
|
| 276 | Runtime Parse Errors
|
| 277 | --------------------
|
| 278 |
|
| 279 | The way bash works 0x$var can be a hex literal.
|
| 280 | so var=xx makes this invalid. hex/octal/decimal have this problem.
|
| 281 |
|
| 282 |
|
| 283 | Parse Time Errors
|
| 284 | -----------------
|
| 285 |
|
| 286 | regcomp() errors (sometimes at parse time; other times at runtime)
|
| 287 |
|
| 288 | Need to show stack trace for "source" like Python. Prototype this.
|
| 289 |
|
| 290 | Also might show which token thing caused you to be in arith parse state, like:
|
| 291 |
|
| 292 | $((echo hi))
|
| 293 | ^~ ^~
|
| 294 | Arith Invalid token
|
| 295 |
|
| 296 |
|