Last active
December 21, 2015 15:29
-
-
Save susisu/6327237 to your computer and use it in GitHub Desktop.
お察し下さい
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright(c) 2013 Susisu | |
for Node.js | |
*/ | |
var fs = require("fs"); | |
function main() | |
{ | |
async( | |
mseq( | |
async( | |
_set("hoge")(readFile(_("hoge.txt"))), | |
_set("fuga")(readFile(_("fuga.txt"))) | |
), | |
_if(_do(function(){return this.hoge && this.fuga;}), | |
print(_do(function() | |
{ | |
return this.hoge.toString().toUpperCase() + ", " | |
+ this.fuga.toString().toUpperCase(); | |
}) | |
), | |
print(_("failed to open file(s)")) | |
) | |
), | |
mbind( | |
_("piyo.txt"), | |
readFile(_return()), | |
_do(function(arg){return arg.toString();}), | |
print(_return()) | |
) | |
).play({}); | |
} | |
/* | |
Action, the unit of process | |
*/ | |
function Action(func) | |
{ | |
this.func = func; | |
this.value = undefined; | |
this.onComplete = undefined; | |
} | |
Object.defineProperty(Action.prototype, "play", { | |
value: function(env, arg) | |
{ | |
this.func.call(env, arg); | |
} | |
}); | |
Object.defineProperty(Action.prototype, "complete", { | |
value: function() | |
{ | |
if(this.onComplete) | |
{ | |
this.onComplete(); | |
this.onComplete = null; | |
} | |
} | |
}); | |
/* | |
do nothing, return void | |
*/ | |
function _void() | |
{ | |
var action = new Action(function(arg) | |
{ | |
action.complete(); | |
}); | |
return action; | |
} | |
/* | |
do something | |
*/ | |
function _do(func) | |
{ | |
var action = new Action(function(arg) | |
{ | |
action.value = func.call(this, arg); | |
action.complete(); | |
}); | |
return action; | |
} | |
/* | |
assign | |
*/ | |
function assign(name) | |
{ | |
var action = new Action(function(arg) | |
{ | |
this[name] = arg; | |
action.complete(); | |
}); | |
return action; | |
} | |
/* | |
set variable (syntax sugar of 'assign') | |
*/ | |
function _set(name) | |
{ | |
return function(value) | |
{ | |
return bind(value, assign(name)) | |
}; | |
} | |
/* | |
get variable | |
*/ | |
function _get(name) | |
{ | |
var action = new Action(function(arg) | |
{ | |
action.value = this[name]; | |
action.complete(); | |
}); | |
return action; | |
} | |
/* | |
convert non-action value to action | |
*/ | |
function _(value) | |
{ | |
var action = new Action(function(arg) | |
{ | |
action.value = value; | |
action.complete(); | |
}); | |
return action; | |
} | |
/* | |
do nothing | |
*/ | |
function _return() | |
{ | |
var action = new Action(function(arg) | |
{ | |
action.value = arg; | |
action.complete(); | |
}); | |
return action; | |
} | |
/* | |
a >>= b | |
*/ | |
function bind(a, b) | |
{ | |
var action = new Action(function(arg) | |
{ | |
var env = this; | |
a.onComplete = function() | |
{ | |
b.onComplete = function() | |
{ | |
action.value = b.value; | |
action.complete(); | |
}; | |
b.play(env, a.value); | |
}; | |
a.play(env, arg); | |
}); | |
return action; | |
} | |
/* | |
a >> b | |
*/ | |
function seq(a, b) | |
{ | |
var action = new Action(function(arg) | |
{ | |
var env = this; | |
a.onComplete = function() | |
{ | |
b.onComplete = function() | |
{ | |
action.value = b.value; | |
action.complete(); | |
}; | |
b.play(env); | |
}; | |
a.play(env, arg); | |
}); | |
return action; | |
} | |
/* | |
(((a >>= b) >>= c) >>= ...) | |
*/ | |
function mbind() | |
{ | |
if(arguments.length > 0) | |
{ | |
var t = arguments[0]; | |
for(var i = 1; i < arguments.length; i++) | |
{ | |
t = bind(t, arguments[i]) | |
} | |
return t; | |
} | |
else | |
{ | |
return _void(); | |
} | |
} | |
/* | |
(((a >> b) >> c) >> ...) | |
*/ | |
function mseq() | |
{ | |
if(arguments.length > 0) | |
{ | |
var t = arguments[0]; | |
for(var i = 1; i < arguments.length; i++) | |
{ | |
t = seq(t, arguments[i]) | |
} | |
return t; | |
} | |
else | |
{ | |
return _void(); | |
} | |
} | |
/* | |
do the actions asynchronously | |
*/ | |
function async() | |
{ | |
if(arguments.length > 0) | |
{ | |
var actions = arguments; | |
var action = new Action(function(arg) | |
{ | |
var n = 0; | |
function handler() | |
{ | |
n++; | |
if(n == actions.length) | |
{ | |
action.complete(); | |
} | |
} | |
for(var i = 0; i < actions.length; i++) | |
{ | |
actions[i].onComplete = handler; | |
actions[i].play(this, arg); | |
} | |
}); | |
return action; | |
} | |
else | |
{ | |
return _void(); | |
} | |
} | |
/* | |
if condition then a else b | |
*/ | |
function _if(condition, a, b) | |
{ | |
var action = new Action(function(arg) | |
{ | |
var env = this; | |
condition.onComplete = function() | |
{ | |
if(condition.value) | |
{ | |
a.onComplete = function() | |
{ | |
action.value = a.value; | |
action.complete(); | |
} | |
a.play(env); | |
} | |
else | |
{ | |
b.onComplete = function() | |
{ | |
action.value = b.value; | |
action.complete(); | |
} | |
b.play(env); | |
} | |
}; | |
condition.play(env); | |
}); | |
return action; | |
} | |
/* | |
read and return a file content | |
*/ | |
function readFile(path, stopOnError) | |
{ | |
var action = new Action(function(arg) | |
{ | |
fs.readFile(arg, function(err, file) | |
{ | |
if(err && stopOnError) | |
{ | |
console.log(err); | |
} | |
action.value = file; | |
action.complete(); | |
}); | |
}); | |
return bind(path, action); | |
} | |
/* | |
output to console.log | |
*/ | |
function print(content) | |
{ | |
var action = new Action(function(arg) | |
{ | |
console.log(arg); | |
action.complete(); | |
}); | |
return bind(content, action); | |
} | |
/* | |
call the main function | |
*/ | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment