AuroraForEach/forEach.js

149 lines
6.8 KiB
JavaScript
Raw Normal View History

2021-10-07 16:11:30 +00:00
const fs = require("fs")
2021-10-15 00:55:48 +00:00
const kWantMaxSupportedElements = 100
const kMaxPairedElements = 10
2021-10-07 16:11:30 +00:00
const kMacroParamLimit = 127
2021-10-05 20:14:54 +00:00
function forN(n, cb) {
for (var i = 0; i < n; i++) {
cb(i)
}
}
2021-10-07 16:28:16 +00:00
function genArray(n) {
return [...Array(n).keys()]
}
2021-10-05 20:14:54 +00:00
function formatNJoin(n, start, join) {
2021-10-07 16:28:16 +00:00
return start + genArray(n).join(join)
2021-10-05 20:14:54 +00:00
}
function formatNJoinReverseSuffix(n, start, join, suffix) {
2021-10-07 16:28:16 +00:00
return start + genArray(n).reverse().join(suffix + join) + suffix
2021-10-05 20:14:54 +00:00
}
function formatNParamPattern(n, join) {
return formatNJoin(n, join, ", " + join)
}
function formatNParamPatternReverseSuffix(n, join, suffix) {
return formatNJoinReverseSuffix(n, join, ", " + join, suffix)
}
var textBuffer = ""
textBuffer +=
`/**
2022-02-05 05:44:12 +00:00
* X-Macro alternative. Defines AU_FOR_EACH[_THAT/_THIS][_N](expandable, ...args*N)
2021-10-05 20:14:54 +00:00
* Autogenerated by forEach.js; do not modify"
*/
2022-02-05 05:44:12 +00:00
#define _ZAUFE_FE_EXPAND(exp) exp
#define _ZAUFE_FE_ERROR(exp) ERROR. CHECK PARAMETER COUNT. DID YOU FORGET A COMMA?
2021-10-05 20:14:54 +00:00
`
2021-10-15 00:55:48 +00:00
forN(kMaxPairedElements, function(nElements) {
if (!nElements) return
2021-10-07 16:28:16 +00:00
var suffix = nElements != 1 ? "_" + (nElements): ""
2021-10-07 16:11:30 +00:00
2021-10-15 00:55:48 +00:00
var nElementsMulNCapped = Math.min(kMacroParamLimit - 3, kWantMaxSupportedElements * nElements)
2021-10-07 16:28:16 +00:00
var ignoreList = {}
forN(nElementsMulNCapped, function(i) {
2021-10-07 16:11:30 +00:00
if (i == 0) {
2022-02-05 05:44:12 +00:00
textBuffer += `#define _ZAUFE_FE_0${suffix}(expandable) \n`
ignoreList[`_ZAUFE_FE_0_FIRST${suffix}`] = true
ignoreList[`_ZAUFE_FE_0_THAT${suffix}`] = true
2021-10-07 16:28:16 +00:00
return
}
var X = formatNParamPattern(nElements, "X")
2021-10-07 16:28:16 +00:00
var iM1 = i - 1
var iM1Translated = i - nElements
2021-10-15 00:55:48 +00:00
if (i == nElements - 1) {
// Edge case: the trailing macro does not do anything
// We could hack in an _LAST callback here, should a need for it arise
2022-02-05 05:44:12 +00:00
textBuffer += `#define _ZAUFE_FE_${i}${suffix}(expandable)\n`
} else if ((i == 1) && (nElements != 1)) {
// Edge case: FOR_EACH_N(EXPANDABLE, ), where N has to be defined/has an element count of > 1, this is technically illegal
// However, we can just ignore empty element expansions in those instances
// We can simply use the first 'macro has 2 arguments' slot to hook these (EXPANDABLE, ) conditions
// AU_FOR_EACH CANNOT INTRINSICALLY TELL THE DIFFERENCE BETWEEN AN EMTPY VALUE AND ARG 0
textBuffer += `#define _ZAUFE_FE_${i}${suffix}(expandable, empty)\n`
} else if (i % nElements == 0) {
if (i == nElements) {
2021-10-15 00:55:48 +00:00
// Edge case: the last element does not accept any parameters
2022-02-05 05:44:12 +00:00
textBuffer += `#define _ZAUFE_FE_${i}${suffix}(expandable, ${X}) expandable(${X})\n`
} else {
2022-02-05 05:44:12 +00:00
textBuffer += `#define _ZAUFE_FE_${i}${suffix}(expandable, ${X}, ...) expandable(${X}) _ZAUFE_FE_EXPAND(_ZAUFE_FE_${iM1Translated}${suffix}(expandable, __VA_ARGS__))\n`
2021-10-05 20:14:54 +00:00
}
2021-10-07 16:28:16 +00:00
} else {
2022-02-05 05:44:12 +00:00
ignoreList[`_ZAUFE_FE_${i}${suffix}`] = true
2021-10-07 16:28:16 +00:00
}
2022-01-27 03:56:42 +00:00
2021-10-07 16:28:16 +00:00
var I2 = i + 1
2021-10-28 20:12:39 +00:00
// Similar to above
if (i < nElements) {
2022-02-05 05:44:12 +00:00
ignoreList[`_ZAUFE_FE_${i}_THAT${suffix}`] = true
ignoreList[`_ZAUFE_FE_${I2}_THAT${suffix}`] = true
} else if (i == nElements) {
2022-02-05 05:44:12 +00:00
ignoreList[`_ZAUFE_FE_${i}_THAT${suffix}`] = true
textBuffer += `#define _ZAUFE_FE_${I2}_THAT${suffix}(expandable, ctx, ${X}) expandable(ctx, ${X})\n`
} else if ((i % nElements) == 0) {
2021-10-28 20:12:39 +00:00
var offByOne = iM1Translated + 1
if (i == nElements) {
// Edge case: the last element does not accept any parameters
2022-02-05 05:44:12 +00:00
ignoreList[`_ZAUFE_FE_${I2}_THAT${suffix}`] = true // ? dont question it
textBuffer += `#define _ZAUFE_FE_${I2}_THAT${suffix}(expandable, ctx, ${X}) expandable(ctx, ${X})\n`
2021-10-28 20:12:39 +00:00
} else {
2022-02-05 05:44:12 +00:00
textBuffer += `#define _ZAUFE_FE_${I2}_THAT${suffix}(expandable, ctx, ${X}, ...) expandable(ctx, ${X}) _ZAUFE_FE_EXPAND(_ZAUFE_FE_${offByOne}_THAT${suffix}(expandable, ctx, __VA_ARGS__))\n`
2021-10-28 20:12:39 +00:00
}
} else {
2022-02-05 05:44:12 +00:00
ignoreList[`_ZAUFE_FE_${I2}_THAT${suffix}`] = true
2021-10-28 20:12:39 +00:00
}
2022-01-27 03:56:42 +00:00
2022-02-05 05:44:12 +00:00
ignoreList[`_ZAUFE_FE_${suffix}_THAT${suffix}`] = true
2021-10-28 20:12:39 +00:00
if (i == 1) {
2022-02-05 05:44:12 +00:00
textBuffer += `#define _ZAUFE_FE_${i}_FIRST${suffix}(first, second) \n`
2022-01-27 03:56:42 +00:00
}
if (i == nElements) {
2022-02-05 05:44:12 +00:00
textBuffer += `#define _ZAUFE_FE_${I2}_FIRST${suffix}(first, second, ${X}) first(${X}) _ZAUFE_FE_EXPAND(_ZAUFE_FE_${iM1Translated}${suffix}(second))\n`
2022-01-27 03:56:42 +00:00
} else if ((i % (nElements) == 0)) {
if (i == nElements) {
2022-02-05 05:44:12 +00:00
ignoreList[`_ZAUFE_FE_${I2}_FIRST${suffix}`] = true // ? dont question it
textBuffer += `#define _ZAUFE_FE_${I2}_FIRST${suffix}(first, second, ${X}) first(${X}) _ZAUFE_FE_EXPAND(_ZAUFE_FE_${iM1Translated}${suffix}(second))\n`
2021-10-06 23:40:55 +00:00
} else {
2022-02-05 05:44:12 +00:00
textBuffer += `#define _ZAUFE_FE_${I2}_FIRST${suffix}(first, second, ${X}, ...) first(${X}) _ZAUFE_FE_EXPAND(_ZAUFE_FE_${iM1Translated}${suffix}(second, __VA_ARGS__))\n`
2021-10-07 16:28:16 +00:00
}
2021-10-15 00:55:48 +00:00
} else {
2022-02-05 05:44:12 +00:00
ignoreList[`_ZAUFE_FE_${I2}_FIRST${suffix}`] = true
2021-10-05 20:14:54 +00:00
}
})
2021-10-15 00:55:48 +00:00
// Defines a macro that effectively choses a macro given an array of macros based on the number of input arguments
var getMacroParams = formatNParamPattern(nElementsMulNCapped, "_")
2022-02-05 05:44:12 +00:00
textBuffer += `#define _ZAUFE_GET_MACRO${suffix}(${getMacroParams}, NAME,...) NAME\n`
2021-10-05 20:14:54 +00:00
2021-10-15 00:55:48 +00:00
// Stringify the parameter portion of the prototype
2022-02-05 05:44:12 +00:00
var params = formatNParamPatternReverseSuffix(nElementsMulNCapped, "_ZAUFE_FE_", suffix)
var params2 = formatNParamPatternReverseSuffix(nElementsMulNCapped, "_ZAUFE_FE_", "_FIRST" + suffix)
var params3 = formatNParamPatternReverseSuffix(nElementsMulNCapped, "_ZAUFE_FE_", "_THAT" + suffix)
2021-10-06 23:40:55 +00:00
2022-02-05 05:44:12 +00:00
// Replace missing macro paramaters with the _ZAUFE_FE_ERROR macro
params = params .split(", ").map((str) => { return ignoreList[str] ? "_ZAUFE_FE_ERROR" : str}).join(", ")
params2 = params2.split(", ").map((str) => { return ignoreList[str] ? "_ZAUFE_FE_ERROR" : str}).join(", ")
params3 = params3.split(", ").map((str) => { return ignoreList[str] ? "_ZAUFE_FE_ERROR" : str}).join(", ")
2021-10-06 21:37:04 +00:00
2022-02-05 05:44:12 +00:00
textBuffer += `#define AU_FOR_EACH${suffix}(action, ...) _ZAUFE_FE_EXPAND(_ZAUFE_GET_MACRO${suffix}(_whydoweneedthis, __VA_ARGS__, ${params})(action,__VA_ARGS__))\n`
textBuffer += `#define AU_FOR_EACH_FIRST${suffix}(action, ...) _ZAUFE_FE_EXPAND(_ZAUFE_GET_MACRO${suffix}(_whydoweneedthis, __VA_ARGS__, ${params2})(action,__VA_ARGS__))\n`
textBuffer += `#define AU_FOR_EACH_THAT${suffix}(action, ...) _ZAUFE_FE_EXPAND(_ZAUFE_GET_MACRO${suffix}(_whydoweneedthis, __VA_ARGS__, ${params3})(action,__VA_ARGS__))\n`
2021-10-28 20:12:39 +00:00
2021-10-05 20:14:54 +00:00
textBuffer += "\n\n"
})
2021-10-15 00:55:48 +00:00
fs.writeFileSync("./Include/AuroraForEach.hpp", textBuffer)