2

I read lots of article already on how to translate call/cc into equivalent CPS style and kinda know the basic already but currently I don't understand how racket perform transformation with call/comp (a.k.a call-with-composable-continuation) and stuck here.

What I did first is attempt to translate this racket piece of code:

#lang racket/base

(let ([tag (make-continuation-prompt-tag)])
    (println "111")
    (println (string-append "222"
        (call-with-continuation-prompt
            (lambda ()
                (println (string-append "333"
                    (call-with-composable-continuation
                        (lambda (k)
                            (println (string-append "444" (k "555")))
                            ;; (abort-current-continuation tag "bbb")
                            "666")
                        tag)))
                "777")
            tag
            (lambda (k)
                (println (string-append "888" k))
                "aaa"
                )))))

Into equivalent JS code. Here my current attempt so far:

var prompt = (fn, tag, r0) => { // call-with-continuation-prompt
    // Incorrect
    // r0(fn((p0) => {
        // r0(p0);
    // }));
};

var comp = (fn, tag, r0) => { // call-with-composable-continuation
    // Incorrect
    // fn((pass, r1) => {
        // r0(r1(pass));
    // });
};

var abort = () => { // abort-current-continuation

};

((r0) => {
    console.log("111");
    ((r1) => {
        prompt((r2) => {
            ((r3)=>{
                comp((k, r4) => {
                    k("555", (r5) => {
                        console.log("444" + r5);
                        r4("666");
                    });
                }, "tag", r3);
            })
            ((p3) => {
                console.log("333" + p3);
                r2("777");
            });
        }, "tag", r1);
    })
    ((p1) => {
        console.log("222" + p1);
        r0();
    });
})
((p0) => {
    throw 0; // throw 0 to exit early
});

How should I fill prompt and comp here? Did I missed a CPS step? Is the transformation even possible?

Trung0246
  • 689
  • 1
  • 10
  • 21

1 Answers1

0

After a while with a lots of trial and error I came up with this solution:

var give = (p, rs, rt) => { // return value from function
    rs(p, rt);
};

var exit = (p, rr) => { // exit program?
    give(p, rr, rr);
};

var prompt = (fn, r_ab, r_cx) => {
    fn(
        (p_fn, r_fn) => {
            if (r_fn == null) // Check if we are aborting
                r_ab(p_fn, (p_ab, r_ab_) => {
                    give(p_ab, r_ab_, r_cx);
                });
            else
                give(p_fn, r_fn, r_cx);
        }
    );
};

var comp = (fn, r_cx) => {
    fn(
        (p_fn, r_fn) => { // Function composition
            r_cx(p_fn, (p_cc) => {
                give(p_cc, r_fn, (p_cx) => {
                    r_cx(p_cx, (p_out, r_out) => {
                        exit(p_out, r_out);
                    });
                });
            });
        },
        (p_fn, r_fn) => {
            give(p_fn, r_fn, r_cx);
        },
    );
};

var abort = (fn, rr) => {
    fn((p_fn) => {
        rr(p_fn, null);
    });
};

((r0) => {
    console.log("111");
    prompt(
        (r1) => {
            comp(
                (k, r2) => {
                    // return give("666", r2, r1); // Or comment k(...) and uncomment this
                    k(
                        "555",
                        (pk, rk_) => {
                            console.log("444" + pk);
                            /* <-- Flip between these two
                            abort(
                                (ra) => {
                                    ra("bbb");
                                },
                                r1
                            );
                            /*/
                            give("666", rk_, r2);
                            //*/
                        },
                    );
                },
                (p2, r2_) => {
                    console.log("333" + p2);
                    give("777", r2_, r1);
                },
            );
        },
        (pa, ra_) => {
            console.log("888" + pa);
            exit("aaa", ra_);
        },
        (p1, r1_) => {
            console.log("222" + p1);
            exit(0, r0); // Should end the program
        },
    );
})
((p0, r0_) => {
    give(p0, r0_, (p0_) => {
        console.log("out:  ", p0_);
    });
});

Honestly I'm still not sure if my implementation is correct for all possible cases with valid CPS. Any thought?

Trung0246
  • 689
  • 1
  • 10
  • 21