Last active
August 29, 2015 14:21
-
-
Save egonelbre/47e0eecb796ba47e44d4 to your computer and use it in GitHub Desktop.
injection based
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
DCI = {}; | |
if(typeof window !== 'undefined'){ window.DCI = DCI; } | |
if(typeof global !== 'undefined'){ global.DCI = DCI; } | |
(function(DCI){ | |
DCI.Context = function(init, roles){ | |
var sfn = ""; | |
sfn += "\tvar $C = {};\n"; | |
sfn += "\tvar " + Object.keys(roles).join(", ") + ";\n"; | |
var fixMethod = function(fn){ | |
fn = fn.toString(); | |
for(var roleName in roles){ | |
var role = roles[roleName]; | |
for(var fnName in role){ | |
// replaces Role.method(arg1,arg2,arg3) with | |
// with DCI.bindings(Role).get($C).Role.method.call(Role, arg1, arg2, arg3); | |
var rx = new RegExp( "(?!\\.)" + roleName + "\\s*\\.\\s*" + fnName + "\\s*\\(", "g"); | |
fn = fn.replace(rx, "DCI.bindings("+ roleName + ").get($C)." + roleName + "." + fnName + ".call("+ roleName + ","); | |
} | |
var rx = new RegExp("(?!\\.)(" + roleName + "\\s*=\\s*[^;]+;)", "g"); | |
var binding = "" + | |
"DCI.unbind(" + roleName + ", $C, '" + roleName + "');" + | |
"$1" + | |
"DCI.bind(" + roleName + ", $C, '" + roleName + "', $C" + roleName + ");"; | |
fn = fn.replace(rx, binding); | |
} | |
// hack-fix Role$method.call(Arg,) | |
fn = fn.replace(/,\)/g, ")"); | |
return fn; | |
}; | |
for(var roleName in roles){ | |
var decl = "{\n"; | |
if(!roles.hasOwnProperty(roleName)) continue; | |
var roleDecl = roles[roleName]; | |
var fns = []; | |
for(var fnName in roleDecl){ | |
if(!roleDecl.hasOwnProperty(fnName)) continue; | |
fns.push("\t" + fnName + ":" + fixMethod(roleDecl[fnName])); | |
} | |
sfn += "\tvar $C" + roleName + " = {\n\t" + fns.join(",\n\t") + "\t\n\t};\n"; | |
} | |
sfn += " return (" + fixMethod(init) + ").apply(null, arguments);"; | |
if(true){ | |
console.info("GENERATED", "\n" + sfn); | |
} | |
return (new Function(sfn)); | |
} | |
DCI.bindings = function(player){ | |
if(typeof player.___ === "undefined"){ | |
player['___'] = new WeakMap(); | |
} | |
return player['___']; | |
} | |
DCI.bind = function(player, context, roleName, roleDecl){ | |
if(player == null){ return; } | |
if(typeof player !== 'object'){ | |
if(Object.keys(roleDecl).length != 0){ | |
throw new Error('Only objects may have role methods.'); | |
} | |
return; | |
} | |
var bindings = DCI.bindings(player); | |
//TODO: check for naming conflicts | |
var roles = bindings.get(context) || {}; | |
roles[roleName] = roleDecl; | |
bindings.set(context, roles); | |
}; | |
DCI.unbind = function(player, context, roleName){ | |
if(player == null){ return; } | |
if(typeof player !== 'object'){ return; } | |
var bindings = DCI.bindings(player); | |
if(!bindings.has(context)){ | |
return; | |
} | |
var roles = bindings.get(context); | |
delete(roles[roleName]); | |
bindings.set(context, roles); | |
}; | |
})(DCI); |
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
<script src="dci.js"></script> | |
<script src="transfer.js"></script> |
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
function Account(code, balance) { | |
return { | |
get code(){ return code; }, | |
get balance(){ return balance; }, | |
increase: function(by){ balance += by; }, | |
decrease: function(by){ balance -= by; } | |
}; | |
} | |
function Bank(){ | |
var accounts = {}; | |
return { | |
openAccount: function(code, initialBalance){ | |
accounts[code] = Account(code, initialBalance); | |
}, | |
accountByCode: function(code){ | |
return accounts[code]; | |
} | |
}; | |
} | |
Transfer = DCI.Context( | |
function(bank, from, to, amount) { | |
Amount = amount; | |
Source = bank.accountByCode(from); | |
Destination = bank.accountByCode(to); | |
Source.give(); | |
}, { | |
Amount: {}, | |
Source: { | |
give: function() { | |
if(Source.balance < Amount){ | |
throw new Error("Insufficient funds."); | |
} | |
Source.decrease(Amount); | |
Destination.receive(); | |
} | |
}, | |
Destination: { | |
receive: function() { | |
Destination.increase(Amount); | |
} | |
} | |
}); | |
var bank = Bank(); | |
bank.openAccount("alice", 132); | |
bank.openAccount("bob", 23); | |
console.log("Before:"); | |
console.log("alice ", bank.accountByCode("alice").balance); | |
console.log("bob ", bank.accountByCode("bob").balance); | |
Transfer(bank, "alice", "bob", 100); | |
console.log("After:"); | |
console.log("alice", bank.accountByCode("alice").balance); | |
console.log("bob", bank.accountByCode("bob").balance); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment