Re: Try/Catch

new topic     » goto parent     » topic index » view thread      » older message » newer message
mattlewis said...
petelomax said...
mattlewis said...
petelomax said...

In addition there will also be a new builtin, throw(atom code).

Why an atom and not an object? It could be useful to put lots of stuff in there.

Maybe for version 2. Can we not just get an int (full 32-bit) working first?

Though I still disagree on the argument for throw().

I concede. Once I thought of it, catch e ... throw(e) is a fairly compelling argument.

Here is a first stab at defining what an exception innards might look like (with something of a Phix bias)

catch e

The following constants can be used to examine the contents of an exception

  1. E_CODE (atom) hardware and operating system exceptions usually have bit #800000000 set, user exceptions can be any atom value.
  2. E_ADDR (atom) a machine address indicating where the exception ocurred
  3. E_RTN (integer) equivalent to routine_id(), an index to the symbol table identifying the routine (optional)
  4. E_LINE (integer) the source code line matching E_ADDR in E_RTN (optional)
  5. E_NAME (string) the human-readable name of E_RTN (optional/may be integer)


Only the first two elements are guaranteed to be present. Further user-defined elements may also be present. There is no upper limit to the length of an exception or the amount of detailed information it can contain, however the first five elements have predefined meanings.

throw(object e, object e6={})

if e6!={} then e must be atom and throw(e,e6) is equivalent to throw({e,-1,-1,-1,-1,e6}), modified as below.
if e is an atom, throw(e) is equivalent to throw({e,-1,-1,-1,-1}), modifed as below.
if e is a string, throw(e) is equivalent to throw({0,-1,-1,-1,-1,e}), "" (probably Phix only, and same as throw(0,"string")).
Otherwise e must be a sequence containing at least the first two elements, E_CODE and E_ADDR, type safe as above and any user-defined data in e[6..$].

  • if e[E_ADDR] is -1 it is replaced with the return address from the throw() call.
  • if e[E_RTN] is -1 it is replaced with a routine number from the current call stack.
  • if e[E_LINE] is -1 and e[E_ADDR] was -1, then the (new) value of e[ADDR]-1 is mapped to a line number in e[E_RTN] and stored in e[E_LINE].
  • if e[E_NAME] is -1 and e[E_RTN] was -1, the name is retrieved from the symbol table, however (in Phix) that will be a meaningless ttree index when interpreting and a proper string only when compiled.

Note that for hardware and operating system exceptions, e[E_ADDR] may correspond to a machine instruction emitted for the source code line, or the first byte of the next line, or somewhere deep in the heart of say kernel32.dll, or part of the internal workings of c_func, and therefore (in early versions at least) e[E_LINE] may be quite wrong. Such cases will need to be fixed on an ad hoc basis, either by subtracting 1 from e[E_ADDR] for selected e[E_CODE], emitting a judicious nop instruction, or hunting about in the call stack for the first thing that makes sense. If all such efforts are in vain, the runtime reserves the right to give up and return a two-element sequence. In short, you should not become over-reliant on the optional values e[E_LINE] and e[E_NAME]. You can however populate a throw() statement with made-up values.


mattlewis said...

I think this should be fairly straightforward for interpreted code. Not sure how you get this in the translator.

Let me know if you have any ideas, I'd prefer not to introduce unsurmountable incompatibilities.

Pete

edit (one month later): just noticed I missed out the constant E_USER=6.

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu