optimizer: more optimizations for unary operations

I rewrote finish_optimize_application2 (actually, most of the changes just reorder parts of the previous version).

Previously, the optimizer simplified the application of some unary functions inside let,
for example (car (let () ... (cons 1 2)) => (let () ... 1). This commit extends this to begin forms,
like (car (begin ... (cons 1 2)) => (begin ... 1).

Also, constant folding and some reductions were only availed in the direct case, for example
(procedure? car) => #t. With this commit these reductions are extended to the expressions
inside let and begin, for example (procedure? (let () (begin ... car))) => (let () (begin ... #t).

And now the unary application of list* and values is removed when the expression is in a OPT_CONTEXT_SINGLED context, for example (let ([x (values (f))]) (g x)) => (let ([x (f)]) (g x)).

One of the technical problems is that in expression like '(rator (let (...) ... rand))', the extracted 'rand' is in the wrong coordinates, so it must be handled carefully.