Implemented tuple unpacking to tie together V

To implement function calls it was nescessary to implement a
mapping from arguments to function parameters.

    f(1,2,3) => fn f(a,b,c) ...

The general problem can be solved by implementing generalized
a sort of tuple unpacking. This is implemented through directly
compiling into unpacking bytecode rather than other methods such as
using template tables due to easy integration into the parser and
ability to reuse variable definitions in functions.

Unfortunately determining if unpacking is occurring is very
annoying due to syntatical ambiguities until very late in the line.
For example when we see `[a,b,c,d]`, we still aren't sure if we
should perform unpacking `[a,b,c,d]=[1,2,3,4]` or if we are simply
creating a table. This can be solved by requiring the let keyword
for all unpacks. This way unpacking can be determined at the first
bracket. In theory someone could do `let [a,b,c][0] = 10` or similar,
but that seems very unlikely/just unreasonable in general and can
be replaced by `let ([a,b,c])[0] = 10`.

Unpacking can currently occur in three use cases.
Function definitions, unpacking statements, and for loops:

    (fn(a,b) print(a,b))(0,1)
    for (k,v : [1,2,3]) print(k,v)
    let [a,b] = [0,1]

Due to the structure of the parser and lack of syntactic ambiguities,
it was trivial to implement recursive unpacking in all cases. This leads
to interesting uses.

    let [[a,b],[c,[d,e]]] = [[1,2],[3,[4,5]]]
    (fn([a,b],[c,[d,e]]) print args)([1,2],[3,[4,5]])
    for (k,[a,b,c] : [[0,0,0],[1,1,1]]) a+b+c

Due to the amount to usage sharing, unpacking has several strange
nuances. Because functions are called via table passing, it is easy to
pass in keyword arguments. However this requires keyword mapping as
well.

    let [a,b,c] = [3,4,5,a:2]; print a  =>  2
    (fn(a,b,c) print a)(3,4,5,a:2) => 2

This could be very expensive to execute in bytecode due to the repeated
lookups and could lead to quite a bit of bloat. To speed this up, the
opcode VLOOKDN was added. VLOOKDN first looks up the keyword in the
passed table and takes in a integer as a second lookup on failure.
This can take advantage of the common list/range case in usual function
calls and avoid the keyword overhead.

This at first seems a bit hacky, but is an important optimization (and
simplification) since unpacking must occur in practically every function
call.

It could also take advantage of the bulk nature of table unpacking and
only check for a list once, but rather than complicating the bytecode
that much, we can just let the branch predicter take care of it.

Additionally to the unpacking implementation, for loops have been
implemented with the addition of the VITER opcode, which simply
obtains an iteration function. This marks the completion of the core
control flow components.