src/bookofnim/helloworld/modules/exceptionHandlingDocs

Source   Edit  

exception handling, debugging, documentation

TLDR

  • docgen:
    • having * after - (like on this line) will break htmldocs rst parser
      • you must escape it with backticks * or backslash *
      • error reported as Error: '*' expected
    • pretty prints code in the html
    • back ticks and back slashes e.g. *.nims can escape special chars
    • if reusing rsts (e.g. for github readmes)
      • make sure to add an empty line before the first indented list item
      • IMO always externalize readme.rst files so their viewable in github & in html docs
  • exceptions
    • all custom exceptions should ref a specific error/CatchableERror/Defect/and lastly Exception
      • Exception is the base type for CatachableError (exceptions) and Defect (non catchable)
      • has to be allocated on the heap (requires ref) because their lifetime is unknown
    • raise keyword for throwing an exception/defect
      • causes execution to cease until caught or program exits
      • e.g. raise errInstance
      • e.g. raise newException(OSError, "Oops! did i do that?")
      • raising without an error rethrows the previous exception
    • compile with --panics:on to make defects unrecoverable
    • tracebacks:
      • each line in the stack track is a call to a procedure
  • assert
    • -d:danger or --asertions:off to remove from compilation
    • --assertions:on to keep them in compiled output
  • doAssert
    • always on regardless of flags
    • can be used to check for specific errors with doAssertRaises(woop): block
    • useful for hard checks & design by contract
  • drnim
    • requires koch to be setup

links

TODOs

errorMessageWriter (var) called instead of stdmsg.write when printing stacktrace
onUnhandledException (var) override default behavior: write stacktrace to stderr then quit(1)
outOfMemHook (var) override default behavior: write err msg then terminate (see docs for example)
unhandledExceptionHook (var) override default behavior: write err msg then terminate
localRaiseHook: same as globalRaiseHook but on a thread local level
  globalRaiseHook (var) influence exception handling on a global level
  ^ if not nil, every raise statement calls this hook
  ^ if returns false, exception is caught and does not propagate

Exception Handling

  • interesting stuff
    • getStackTrace() only works for debug builds
    • getStackTrace(e) of a specific exception
    • getStackTraceEntries() doesnt work for the js backend

Defect types

  • AccessViolationDefect invalid memory access
  • ArithmeticDefect any kin dof arithmetic error
  • AssertionDefect assertion returns false
  • DeadThreadDefect sending a msg to a dead thread
  • Defect abstract type representing all uncatchable errors (anything mappable to a quit/trap/exit operation)
  • DivByZeroDefect int div by 0
  • FieldDefect field is not accessible because its discriminants value does not fit
  • FloatDivByZeroDefect float div by 0
  • FloatInexactDefect operation cant be represented with infinite precision, e.g. 2.0/3.0, log(1.1)
  • FloatingPointDefect base type for floating point defects
  • FloatInvalidOpDefect invalid ops according to IEEE, e.g. 0.0/0.0
  • FloatOverflowDefect stackoverflow.com
  • FloatUnderflowDefect stackunderflow.com
  • IndexDefect array index out of bounds
  • NilAccessDefect dereferences of nil pointers (only raised when segfaults is imported)
  • ObjectAssignmentDefect object being assigned to its parent object
  • ObjectConversionDefect converting to an incompatible type
  • OutOfMemDefect failed to allocate memory
  • OverflowDefect runtime integer stackoverflows.com, results too big for the provided bits
  • RangeDefect range check error
  • ReraiseDefect if there is no exception to reraise
  • StackOverflowDefect when the hardware used for a subroutine stackoverflows.com

Error (exception) types

  • CatchableError abstract type for all catchable exceptions
  • EOFError occurred
  • IOError occcurred
  • KeyError key cannot be found in a table/set/strtabs
  • LibraryError dynamic library doesnt load
  • OSError operating system service failure
  • ResourceExhaustedError when resource request cant be fulfilled
  • ValueError string/object conversion

try/except/finally

  • like most things can be an expression and assigned to a var
  • the try + except must all be of the same type
  • if theres a finally, it must return void

defer

  • alternative try finally statement that avoids lexical nesting + scoping flexibility
  • all statements after defer will be within an implicit try block
  • top level defers arent supported (must be within a block/proc/etc)

assert

  • useful for guard, pre & post conditions if using design by contract
  • i think drnim even extends this further

documentation

  • starting a line with ## creates a title that appears in the left sidebar
  • both --- and === need to be the same length of whatever they're underlining
    • === creates an underline
    • --- creates a subtitle and appears undearneath the previous title in the sidebar
  • low(openArray) creates an html #fragment ?
  • starting a line with .. code-block:: Nim creates a codeblock for stuff indented beneath it
  • starting a line with .. image:: woopwoop.com/image.gif creates an image
  • include another doc file .. include:: ./system_overview.rst
  • .. _LinkName: some.url.com can be referenced as LinkName_

runnableExamples

  • example code to be formatted and displayed in html docs
  • ignored in release/debug, but parsed during docgen:
    • will aggregate all into a separate module, compile, test
    • ensures only exported symbols exist
      • errors if private symbols are included

Example:

import src/bookofnim/helloworld/modules/exceptionHandlingDocs
var iam = GoodApplications(pubfield: "yes u are", prvfield: "I know I am") ## \
  ## example of creating a good application
discard repr iam

Types

GoodApplications = object
  pubfield*: string          ## public: included in docs
  prvfield*: string
especially things like custom types may need additional abbreviations to describe their purpose Source   Edit  
LearningError = object of CatchableError
Source   Edit  

Vars

err: ref OSError
requires ref! only ref objects can be raised Source   Edit  
wrong`gensym12 = false
Source   Edit  

Lets

badcode = "ishardtomaintain"
doc comment on next line Source   Edit  
goodcode = "isdocumented"
doc comment on same line Source   Edit  

Consts

begin`gensym12 = "expected raising \'KeyError\', instead"
Source   Edit  
loc`gensym9 = (filename: "exceptionHandlingDocs.nim", line: 260, column: 0)
Source   Edit  
loc`gensym11 = (filename: "exceptionHandlingDocs.nim", line: 263, column: 0)
Source   Edit  
msgEnd`gensym12 = " by: \nraise newException(KeyError, \"key error\")"
Source   Edit  
ploc`gensym9 = "exceptionHandlingDocs.nim(260, 1)"
Source   Edit  
ploc`gensym11 = "exceptionHandlingDocs.nim(263, 1)"
Source   Edit  

Procs

proc deferExample(): auto {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc maybeThrows(x: int): int {....raises: [ValueError], tags: [], forbids: [].}
only value errors are allowed Source   Edit  
proc neverThrows(): string {....raises: [], tags: [], forbids: [].}
we set raises to empty list Source   Edit  

Templates

template raisedForeign`gensym12() {.gensym.}
Source   Edit