// Generated by CoffeeScript 1.7.1 (function() { var Given, bind, defineGetter, __hasProp = {}.hasOwnProperty; bind = function(fn, self) { return function() { return fn.apply(self, arguments); }; }; defineGetter = function(obj, name, fn) { return Object.defineProperty(obj, name, { get: fn, configurable: true, enumerable: true }); }; Given = function(self) { var defineInBulk, defineOneVariable, entered, env, failOnReenter, funs, given, handler, isRedefinitionOf, isStackOverflowError, memoize, memos, privateEnv, redefine, resetEnv, topmostVariableBeingEvaluated, trapOuterEnvAccess, trapStackOverflow; privateEnv = {}; env = self || {}; funs = {}; memos = {}; topmostVariableBeingEvaluated = void 0; entered = function() { return topmostVariableBeingEvaluated != null; }; failOnReenter = function(name) { return function() { if (entered()) { throw new Error("Illegal attempt to use the Given environment object in the definition of '" + topmostVariableBeingEvaluated + "'; Use 'this' within value definitions."); } else { return privateEnv[name]; } }; }; handler = function(definitionFn, name) { var f1, f2, f3, f4; f1 = bind(definitionFn, privateEnv); f2 = trapStackOverflow(name); f3 = trapOuterEnvAccess(name); f4 = memoize(name); return function() { return f4(function() { return f3(function() { return f2(function() { return f1(); }); }); }); }; }; resetEnv = function() { var name; for (name in privateEnv) { if (!__hasProp.call(privateEnv, name)) continue; if (name !== 'given') { delete env[name]; } } funs = {}; memos = {}; return privateEnv = {}; }; memoize = function(name) { return function(fn) { var memo; memo = memos[name]; if (memo != null) { return memo; } else { return memos[name] = fn(); } }; }; isStackOverflowError = function(err) { var message; message = (typeof err === 'string' ? err : err != null ? err.message : void 0) || ''; return message.match(/\bstack|recursion\b/); }; trapStackOverflow = function(name) { return function(fn) { var err; try { return fn(); } catch (_error) { err = _error; if (isStackOverflowError(err)) { throw new Error("recursive definition of variable '" + name + "' detected"); } else { throw err; } } }; }; trapOuterEnvAccess = function(name) { return function(fn) { topmostVariableBeingEvaluated = name; try { return fn(); } finally { topmostVariableBeingEvaluated = void 0; } }; }; redefine = function(name, fn) { var newEnv, newFn, oldFn; newEnv = Object.create(privateEnv); oldFn = funs[name]; defineGetter(newEnv, name, bind(oldFn, privateEnv)); newFn = bind(fn, newEnv); defineGetter(privateEnv, name, newFn); return newFn; }; isRedefinitionOf = function(name) { return funs[name] != null; }; defineOneVariable = function(name, definitionFn) { if (name === 'given') { throw new Error('cannot redefine given'); } if (!(definitionFn instanceof Function)) { throw new Error("definition of \"" + name + "\" is not a function"); } memos = {}; if (isRedefinitionOf(name)) { definitionFn = redefine(name, definitionFn); } else { defineGetter(privateEnv, name, handler(definitionFn, name)); defineGetter(env, name, failOnReenter(name)); } return funs[name] = definitionFn; }; defineInBulk = function(definitions) { var definition, name, _results; _results = []; for (name in definitions) { if (!__hasProp.call(definitions, name)) continue; definition = definitions[name]; _results.push(defineOneVariable(name, definition)); } return _results; }; given = function() { var args, name, thing; args = [].slice.apply(arguments); if (typeof args[0] === 'object') { return defineInBulk(args[0]); } else { name = args[0], thing = args[1]; return defineOneVariable(name, thing); } }; Object.defineProperties(given, { clear: { writable: false, configurable: false, value: resetEnv }, __isGiven__: { writable: false, configurable: false, value: true } }); return given; }; Given.isGiven = function(obj) { return (obj != null ? obj.__isGiven__ : void 0) || false; }; if ((typeof module !== 'undefined') && (module.exports != null)) { module.exports = Given; } else { this.Given = Given; } }).call(this);