--- /dev/null
+"use strict";\r
+module.exports = codegen;\r
+\r
+/**\r
+ * Begins generating a function.\r
+ * @memberof util\r
+ * @param {string[]} functionParams Function parameter names\r
+ * @param {string} [functionName] Function name if not anonymous\r
+ * @returns {Codegen} Appender that appends code to the function's body\r
+ */\r
+function codegen(functionParams, functionName) {\r
+\r
+ /* istanbul ignore if */\r
+ if (typeof functionParams === "string") {\r
+ functionName = functionParams;\r
+ functionParams = undefined;\r
+ }\r
+\r
+ var body = [];\r
+\r
+ /**\r
+ * Appends code to the function's body or finishes generation.\r
+ * @typedef Codegen\r
+ * @type {function}\r
+ * @param {string|Object.<string,*>} [formatStringOrScope] Format string or, to finish the function, an object of additional scope variables, if any\r
+ * @param {...*} [formatParams] Format parameters\r
+ * @returns {Codegen|Function} Itself or the generated function if finished\r
+ * @throws {Error} If format parameter counts do not match\r
+ */\r
+\r
+ function Codegen(formatStringOrScope) {\r
+ // note that explicit array handling below makes this ~50% faster\r
+\r
+ // finish the function\r
+ if (typeof formatStringOrScope !== "string") {\r
+ var source = toString();\r
+ if (codegen.verbose)\r
+ console.log("codegen: " + source); // eslint-disable-line no-console\r
+ source = "return " + source;\r
+ if (formatStringOrScope) {\r
+ var scopeKeys = Object.keys(formatStringOrScope),\r
+ scopeParams = new Array(scopeKeys.length + 1),\r
+ scopeValues = new Array(scopeKeys.length),\r
+ scopeOffset = 0;\r
+ while (scopeOffset < scopeKeys.length) {\r
+ scopeParams[scopeOffset] = scopeKeys[scopeOffset];\r
+ scopeValues[scopeOffset] = formatStringOrScope[scopeKeys[scopeOffset++]];\r
+ }\r
+ scopeParams[scopeOffset] = source;\r
+ return Function.apply(null, scopeParams).apply(null, scopeValues); // eslint-disable-line no-new-func\r
+ }\r
+ return Function(source)(); // eslint-disable-line no-new-func\r
+ }\r
+\r
+ // otherwise append to body\r
+ var formatParams = new Array(arguments.length - 1),\r
+ formatOffset = 0;\r
+ while (formatOffset < formatParams.length)\r
+ formatParams[formatOffset] = arguments[++formatOffset];\r
+ formatOffset = 0;\r
+ formatStringOrScope = formatStringOrScope.replace(/%([%dfijs])/g, function replace($0, $1) {\r
+ var value = formatParams[formatOffset++];\r
+ switch ($1) {\r
+ case "d": case "f": return String(Number(value));\r
+ case "i": return String(Math.floor(value));\r
+ case "j": return JSON.stringify(value);\r
+ case "s": return String(value);\r
+ }\r
+ return "%";\r
+ });\r
+ if (formatOffset !== formatParams.length)\r
+ throw Error("parameter count mismatch");\r
+ body.push(formatStringOrScope);\r
+ return Codegen;\r
+ }\r
+\r
+ function toString(functionNameOverride) {\r
+ return "function " + (functionNameOverride || functionName || "") + "(" + (functionParams && functionParams.join(",") || "") + "){\n " + body.join("\n ") + "\n}";\r
+ }\r
+\r
+ Codegen.toString = toString;\r
+ return Codegen;\r
+}\r
+\r
+/**\r
+ * Begins generating a function.\r
+ * @memberof util\r
+ * @function codegen\r
+ * @param {string} [functionName] Function name if not anonymous\r
+ * @returns {Codegen} Appender that appends code to the function's body\r
+ * @variation 2\r
+ */\r
+\r
+/**\r
+ * When set to `true`, codegen will log generated code to console. Useful for debugging.\r
+ * @name util.codegen.verbose\r
+ * @type {boolean}\r
+ */\r
+codegen.verbose = false;\r