Skip to content

Commit

Permalink
Use function names to identify branches.
Browse files Browse the repository at this point in the history
Now when a named function is used as a step, the named function is added
to the context of the cadence. It can be requested by name through step
function parameters like any other context object.

Instead of receiving the step function itself, however, the user
receives a wrapper that will record the arguments passed to the step
function. When the current step function has completed, the wrapper will
move the cadence to the wrapped step function. The step function will be
invoked with the recorded parameters.

If the `cadence` function is passed the wrapper as the first argument,
it will create a callback that will move the cadence to wrapped step
function if it is invoked. The wrapped step function will be used to
infer the context names of results given to the callbacks.

We changed the behavior of `cadence` when it is invoked with a direct
reference to a step function as it's first argument to match that of
being invoked with a wrapped named step function as the first argument.
Calling `cadence` with a direct reference to a step function will return
a callback that will move the cadence to the referenced function if it
is invoked. The wrapped step function will be used to infer the context
names of results given to the callbacks.

Closes #24.
  • Loading branch information
flatheadmill committed Jul 6, 2012
1 parent 527e531 commit a219b06
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 18 deletions.
52 changes: 47 additions & 5 deletions deltree.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ var deltree = cadence(function (cadence, directory) {
fs.readdir(directory, cadence());
}, function (error) {
if (error.code != "ENOENT") cadence(error);
else cadence(null);
}, function shift (files) {
else cadence(null, []);
}, function shift (files, rmdir) {
if (files.length) return path.resolve(directory, files.shift());
else cadence(rmdir);
else rmdir();
}, function (file) {
fs.stat(file, cadence());
}, function (stat, file) {
}, function (stat, file, shift) {
if (stat.isDirectory()) deltree(file, cadence(shift));
else fs.unlink(file, cadence(shift));
}, function rmdir () {
Expand All @@ -22,7 +22,7 @@ var deltree = cadence(function (cadence, directory) {
fs.readdir(directory, cadence());
}, function (error) {
if (error.code != "ENOENT") cadence(error);
else cadence(null);
else cadence(null, []);
}, function (files) {
files.forEach(function () {
cadence(function () {
Expand All @@ -36,3 +36,45 @@ var deltree = cadence(function (cadence, directory) {
fs.rmdir(directory, cadence());
});
});

var deltree = cadence(function (cadence, directory)
cadence(function () {
fs.readdir(directory, cadence());
}, function (error, files) {
if (error) {
if (error.code != "ENOENT") throw error;
cadence(null);
} else {
files.forEach(function (file, i) {
fs.stat(path.resolve(directory, file), cadence({ file: file, stat: cadence(0) }));
});
}
}, function (objects) {
objects.forEach(function (object) {
if (object.stat.isDirectory()) deltree(object.file, cadence());
else fs.unlink(object.file, cadence());
});
}, cadence);
});


var deltree = cadence(function (cadence, directory)
cadence(function () {
fs.readdir(directory, cadence());
}, function (error, files) {
// Messy.
if (error) {
if (error.code != "ENOENT") throw error;
cadence(null);
} else {
files.forEach(function (file, i) {
fs.stat(path.resolve(directory, file), cadence(i));
});
}
}, function (stats, files) {
files.forEach(function (file, i) {
if (stat[i].isDirectory()) deltree(file, cadence());
else fs.unlink(file, cadence());
});
}, cadence);
});
32 changes: 22 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function factory (options) {
, abended
, key
, arg
, context = extend({}, context)
, context = {}
;

firstSteps = flatten(vargs);
Expand All @@ -39,7 +39,7 @@ function factory (options) {
return factory(extend({}, options, callback));
}

firstSteps = firstSteps.map(function (step) { return parameterize(step) });
firstSteps = firstSteps.map(function (step) { return parameterize(step, context) });

return execute;

Expand Down Expand Up @@ -75,17 +75,20 @@ function factory (options) {
var invocation;

function cadence () {
var vargs = __slice.call(arguments, 0), i = -1, step;
var vargs = __slice.call(arguments, 0), i = -1, step, original;
if (vargs.length == 1 && Array.isArray(vargs[0]) && !vargs[0].length) return;
vargs = flatten(vargs);
if (vargs.length == 1 && typeof vargs[0] == "function") {
original = vargs[0].original || vargs[0];
for (i = invocation.arguments[0].length - 1; step = invocation.arguments[0][i]; i--) {
if (vargs[0] === step.original || vargs[0] === step) break;
if (original === step || original === step.original) break;
}
}
if (~i) {
invocation.arguments[1] = i;
} else if (!vargs.length || vargs.every(function (arg) { return typeof vargs[0] == "string" })) {
vargs.shift();
}
if (!vargs.length || vargs.every(function (arg) { return typeof vargs[0] == "string" })) {
var names = vargs;
invocation.count++;
return (function (invocation) {
Expand All @@ -95,9 +98,14 @@ function factory (options) {
thrown.apply(this, [ error ].concat(invocation.arguments));
} else {
invocation.callbacks.push({ names: names, vargs: vargs });
// Indicates that the function has completed, so we need create
// the callbacks for parallel cadences now, the next increment of
// the called counter, which may be the last.
if (vargs[0] == invoke) {
cadences.slice(0).forEach(function (steps) {
invoke(steps.map(parameterize), 0, Object.create(invocation.context), [], cadence());
var subtext = Object.create(invocation.context);
steps = steps.map(function (step) { return parameterize(step, subtext) });
invoke(steps, 0, subtext, [], cadence());
});
}
}
Expand All @@ -111,11 +119,15 @@ function factory (options) {
}
}

function parameterize (f) {
var $ = /^function\s*[^(]*\(([^)]*)\)/.exec(f.toString());
function parameterize (step, context) {
var $ = /^function\s*[^(]*\(([^)]*)\)/.exec(step.toString()), original;
if (!$) throw new Error("bad function");
f.parameters = $[1].split(/\s*,\s/);
return f;
if (step.name) {
context[step.name] = function () { cadence(step).apply(this, [ null ].concat(__slice.call(arguments, 0))) }
context[step.name].original = step;
}
step.parameters = $[1].split(/\s*,\s/);
return step;
}

// Test if a program name matches one of our special names. We support
Expand Down
43 changes: 40 additions & 3 deletions t/cadence/jump.t
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node

require('proof')(1, function (equal) {
require('proof')(5, function (equal) {
var fs = require('fs'), cadence = require("../../index")();

cadence(function (cadence) {
Expand All @@ -10,9 +10,46 @@ require('proof')(1, function (equal) {
}, inc = function (count) {
cadence()(null, count + 1);
}, function (count) {
if (count != 10) cadence(inc);
if (count != 10) cadence(inc)();
}, function (count) {
equal(10, count, "jump");
equal(10, count, "var");
});
})();

cadence(function (cadence) {
cadence(function () {
cadence()(null, 0);
}, function inc (count) {
cadence()(null, count + 1);
}, function (count, inc) {
if (count != 10) cadence(inc)();
}, function (count) {
equal(10, count, "deferred");
});
})();

cadence(function (cadence) {
cadence(function () {
cadence()(null, 0);
}, function inc (count) {
cadence()(null, count + 1);
}, function (count, inc) {
if (count != 10) inc();
}, function (count) {
equal(10, count, "invoked");
});
})();

cadence(function (cadence) {
cadence(function () {
cadence()(null, 0, "a");
}, function inc (count, letter) {
cadence()(null, count + 1);
}, function (count, inc) {
if (count != 10) inc(count, "b");
}, function (count, letter) {
equal(10, count, "invoked");
equal("b", letter, "parameterized");
});
})();
});

0 comments on commit a219b06

Please sign in to comment.