each type of AST list is 'walked' separately

i.e. an AST list of statements is traversed in its own
`walk_statement_list` function.
parser can recover from errors using setjmp/longjmp

this may not be the best error recovery solution,
but it appears to work just fine. if an error occurs
while parsing a statement, the parser longjmps back to
attempt to parse more statements.
one alternative would be to propogate an error if one occurs
while parsing a statement, but that would require checking
the result of every recursive parser function call.
all functions are now function literals

this is a clean side-effect of the shorthand declaration
syntax, e.g.

    main := func int ([str] args) {
        for arg in args {
            print args
        }
        return 42
    }