Thursday, October 22, 2015

Compiling out Try/Catch/Throw

Below a piece of code I need to understand again. Screw me, not the foggiest.

namespace lambda (

    using system
    using list

    def reset: lambda = lambda_comb "_reset"

    /** The untry transform compiles out throw/catch statements by 
     *  supplying the 'exception handler' as the first argument to all
     *  functions. It also introduces a reset combinator for try/catch
     *  blocks.
     *
     *  - A definition gets one extra argument.
     *    .. F _ (def f = e) = def f = \x -> F x e
     *  - A any combinator is passed the handler.
     *    .. F x (X) = (X x)
     *  - A throw becomes an application of the exception handler to 
     *    the supplied value.
     *    .. F x (throw e) = x (F x e)
     *  - A try/catch block introduces the reset combinator
     *    .. F x (try e0 catch e1) = R (\s. (\y. F y e0) (\z. s (F x e1 z)))
     */
    def untry_transform: lambda_transform lambda =
        abs = [ v, l -> lambda_abs (list.single v) (lambda_alts (list.single l)) ];
        [ ef, lambda_def f l ->
            x = lambda_fresh_name nop;
            (_, l) = untry_transform x l;
            l = abs x l;
            l = lambda_def f l;
                (ef, l)
        | ef, lambda_comb t ->
            l = lambda_app (lambda_comb t) ef;
                (ef, l)
        | ef, lambda_try l0 l1 -> 
            y   = lambda_fresh_name nop;
            s   = lambda_fresh_name nop;
            z   = lambda_fresh_name nop;
            (_, l0) = untry_transform y  l0;
            (_, l1) = untry_transform ef l1;
            l0  = abs y l0;
            l1  = abs z (lambda_app s (lambda_app l1 z));
            l2  = abs s (lambda_app l0 l1);
            l   = lambda_app reset l2;
                (ef, l)
        | ef, lambda_throw l -> 
            (_, l) = untry_transform ef l;
            l = lambda_app ef l;
                (ef, l)
        | ef, l -> 
            lambda_child untry_transform ef l ]

    def untry: lambda -> lambda =
        [ l -> (_, l) = untry_transform (lambda_comb "nop") l; l ]

)

No comments:

Post a Comment