<html>
<head>
<title>Counter Monad</title>
<script src="CounterMonad.js" ></script>
</head>
<body>
<h1>Counter Monad</h1>
</body>
</html>
var CounterOp = {
UP : 117,
DOWN : 100,
unit : function() {
return "";
},
mult : function(x, y) {
return ("" + x + y);
}
};
var Counter = {
QUEUE_MODE : 1,
DIRECT_MODE : 0,
UPPER_BOUND : 9,
_mode : undefined,
_value : undefined,
_operations : undefined,
_action : undefined
};
var BoundedCounterAction = {
doUp : function() {
if (Counter._value < Counter.UPPER_BOUND) Counter._value++;
},
doDown : function() {
if (Counter._value > 0) Counter._value--;
},
name : "BoundedCounterAction"
};
var CyclicCounterAction = {
doUp : function() {
if (Counter._value < Counter.UPPER_BOUND) {
Counter._value++;
} else {
Counter._value = 0;
}
},
doDown : function() {
if (Counter._value > 0) {
Counter._value--;
} else {
Counter._value = Counter.UPPER_BOUND;
}
},
name : "CyclicCounterAction"
};
Counter.init = function(action) {
Counter._mode = Counter.QUEUE_MODE;
Counter._value = 0;
Counter._operations = CounterOp.unit();
if (action) {
Counter._action = action;
} else {
Counter._action = BoundedCounterAction;
}
};
Counter.setMode = function(mode) {
Counter._mode = mode;
};
Counter.operate = function (op) {
var old = Counter._operations;
Counter._operations = CounterOp.mult(old, op);
if (Counter._mode == Counter.DIRECT_MODE) {
Counter.execOperations();
}
};
Counter.execOperations = function() {
var ops = Counter._operations;
for (var i = 0; i < ops.length; i++) {
var op = ops.charCodeAt(i);
switch (op) {
case CounterOp.UP:
Counter._action.doUp(); break;
case CounterOp.DOWN:
Counter._action.doDown(); break;
default: throw "Unbelievable!";
}
}
Counter._operations = CounterOp.unit();
};
function start(a) {
Counter.init(a);
}
function u() {
Counter.operate("u");
}
function d() {
Counter.operate("d");
}
function x() {
Counter.execOperations();
}
function q() {
return Counter._operations;
}
function v() {
return Counter._value;
}
function qmode(f) {
if (f) {
Counter.setMode(Counter.QUEUE_MODE);
} else {
x();
Counter.setMode(Counter.DIRECT_MODE);
}
};