Monday, August 02, 2004

Instant Continuations

I've stumbled upon Jesse Ruderman's neat, instant JavaScript shell for Mozilla. No more software to download. No more writing that test.js file to publish by some web server. It's a great programmer efficiency tool that makes the browser-based rich-client world more bearable.

And now it's drop-dead easy to test continuations. Here's the JavaScript Continuations code again in one easy copy-&-paste block, with some extra helper print statements.


function capitalize(str) {
// #a - next line to be explained soon.
capitalizeReturns[capitalizeReturns.length] = __cont__;
return str.charAt(0).toUpperCase() + str.substring(1);
}

function prettify(firstName, lastName) {
// #b - next line to be explained soon.
prettifyReturn = __cont__;
firstName = capitalize(firstName);
lastName = capitalize(lastName);
return firstName + " " + lastName;
}

function formalName(personName, prefix) {
var parts = personName.split(',');
personName = prettify(parts[1], parts[0]);
return prefix + " " + personName
}

var __cont__ = null;
var prettifyReturn = null;
var capitalizeReturns = [];

print("1- " + formalName("bush,george", "President"));

///////////////////////////////////////

function continuate(funcName) {
var funcText = uneval(this[funcName]);
if (funcText.charAt(0) == '(')
funcText = funcText.slice(1, -1);
funcText = funcText.replace(/return\s*(.*?);/g, "return __cont__($1);");
while (true) {
var newStr = funcText.replace(/(var\s+)?(\w+)\s*=\s*(\w+)\s*\((.*?)\);/,
"return $3($4, function($2) {");
if (newStr == funcText) break;
funcText = newStr + ")}";
}
funcText = funcText.replace(/\{/, "{ var __cont__ = getContinuation(arguments); ");
return this[funcName] = eval("(" + funcText + ")");
}

function getContinuation(args) {
var cont = args[args.length - 1];
if (cont != null && typeof cont == "function")
return cont;
return function(res) { return res; }; // An identity function.
}

///////////////////////////////////////

continuate("formalName");
continuate("prettify");
continuate("capitalize");

print("continuated prettify - " + prettify);

var prettifyReturn = null; // holds the continuation to prettify()
var capitalizeReturns = []; // holds the continuations for capitalize()

print("a - " + formalName("bush,george", "President")); // returns "President George Bush"
print("b - " + prettifyReturn("Bill Clinton")); // returns "President Bill Clinton"
print("c - " + capitalizeReturns[0]("George H")); // returns "President George H Bush"
print("d - " + capitalizeReturns[1]("Washington")); // returns "President George Washington"