Reduce deep nesting some more

This commit is contained in:
Rangi42
2025-07-19 13:44:58 -04:00
parent 7086b8aeff
commit bf69043a1d
6 changed files with 167 additions and 174 deletions

View File

@@ -131,8 +131,8 @@ std::string Diagnostics<L, W>::processWarningFlag(char const *flag) {
auto [flagState, param] = getInitialWarningState(rootFlag); auto [flagState, param] = getInitialWarningState(rootFlag);
// Try to match the flag against a parametric warning // Try to match the flag against a parametric warning
// If there was an equals sign, it will have set `param`; if not, `param` will be 0, which // If there was an equals sign, it will have set `param`; if not, `param` will be 0,
// applies to all levels // which applies to all levels
for (ParamWarning<W> const &paramWarning : paramWarnings) { for (ParamWarning<W> const &paramWarning : paramWarnings) {
W baseID = paramWarning.firstID; W baseID = paramWarning.firstID;
uint8_t maxParam = paramWarning.lastID - baseID + 1; uint8_t maxParam = paramWarning.lastID - baseID + 1;
@@ -173,33 +173,35 @@ std::string Diagnostics<L, W>::processWarningFlag(char const *flag) {
return rootFlag; return rootFlag;
} }
// Try to match against a non-parametric warning, unless there was an equals sign if (param.has_value()) {
if (!param.has_value()) { warnx("Unknown warning flag parameter \"%s\"", rootFlag.c_str());
// Try to match against a "meta" warning return rootFlag;
for (WarningFlag<L> const &metaWarning : metaWarnings) { }
if (rootFlag != metaWarning.name) {
continue;
}
// Set each of the warning flags that meets this level // Try to match against a "meta" warning
for (W id : EnumSeq(W::NB_WARNINGS)) { for (WarningFlag<L> const &metaWarning : metaWarnings) {
if (metaWarning.level >= warningFlags[id].level) { if (rootFlag != metaWarning.name) {
state.metaStates[id].update(flagState); continue;
}
}
return rootFlag;
} }
// Try to match the flag against a "normal" flag // Set each of the warning flags that meets this level
for (W id : EnumSeq(W::NB_PLAIN_WARNINGS)) { for (W id : EnumSeq(W::NB_WARNINGS)) {
if (rootFlag == warningFlags[id].name) { if (metaWarning.level >= warningFlags[id].level) {
state.flagStates[id].update(flagState); state.metaStates[id].update(flagState);
return rootFlag;
} }
} }
return rootFlag;
}
// Try to match against a "normal" flag
for (W id : EnumSeq(W::NB_PLAIN_WARNINGS)) {
if (rootFlag == warningFlags[id].name) {
state.flagStates[id].update(flagState);
return rootFlag;
}
} }
warnx("Unknown warning flag \"%s\"", flag); warnx("Unknown warning flag \"%s\"", rootFlag.c_str());
return rootFlag; return rootFlag;
} }

View File

@@ -24,7 +24,7 @@ static inline void unreachable_() {
#ifdef _MSC_VER #ifdef _MSC_VER
#define assume(x) __assume(x) #define assume(x) __assume(x)
#else #else
// `[[gnu::assume()]]` for GCC or compatible also has insufficient support (GCC 13+ only) // `[[gnu::assume()]]` for GCC or compatible also has insufficient support (GCC 13+ only)
#define assume(x) \ #define assume(x) \
do { \ do { \
if (!(x)) { \ if (!(x)) { \

View File

@@ -41,10 +41,8 @@ struct Charmap {
auto [nodeIdx, mapping] = std::move(prefixes.top()); auto [nodeIdx, mapping] = std::move(prefixes.top());
prefixes.pop(); prefixes.pop();
CharmapNode const &node = nodes[nodeIdx]; CharmapNode const &node = nodes[nodeIdx];
if (node.isTerminal()) { if (node.isTerminal() && !callback(nodeIdx, mapping)) {
if (!callback(nodeIdx, mapping)) { return false;
return false;
}
} }
for (unsigned c = 0; c < std::size(node.next); c++) { for (unsigned c = 0; c < std::size(node.next); c++) {
if (size_t nextIdx = node.next[c]; nextIdx) { if (size_t nextIdx = node.next[c]; nextIdx) {

View File

@@ -641,7 +641,6 @@ static uint32_t readBracketedMacroArgNum() {
} }
std::string symName; std::string symName;
for (; continuesIdentifier(c); c = peek()) { for (; continuesIdentifier(c); c = peek()) {
symName += c; symName += c;
shiftChar(); shiftChar();
@@ -883,14 +882,21 @@ static void shiftChar() {
static int nextChar() { static int nextChar() {
int c = peek(); int c = peek();
// If not at EOF, advance read position
if (c != EOF) { if (c != EOF) {
shiftChar(); shiftChar();
} }
return c; return c;
} }
template<typename P>
static int skipChars(P predicate) {
int c = peek();
for (; predicate(c); c = peek()) {
shiftChar();
}
return c;
}
static void handleCRLF(int c) { static void handleCRLF(int c) {
if (c == '\r' && peek() == '\n') { if (c == '\r' && peek() == '\n') {
shiftChar(); shiftChar();
@@ -1032,10 +1038,7 @@ static uint32_t readFractionalPart(uint32_t integer) {
if (divisor > (UINT32_MAX - (c - '0')) / 10) { if (divisor > (UINT32_MAX - (c - '0')) / 10) {
warning(WARNING_LARGE_CONSTANT, "Precision of fixed-point constant is too large"); warning(WARNING_LARGE_CONSTANT, "Precision of fixed-point constant is too large");
// Discard any additional digits // Discard any additional digits
shiftChar(); skipChars([](int d) { return (d >= '0' && d <= '9') || d == '_'; });
while (c = peek(), (c >= '0' && c <= '9') || c == '_') {
shiftChar();
}
break; break;
} }
value = value * 10 + (c - '0'); value = value * 10 + (c - '0');
@@ -1443,84 +1446,8 @@ static void appendExpandedString(std::string &str, std::string const &expanded)
static void appendCharInLiteral(std::string &str, int c) { static void appendCharInLiteral(std::string &str, int c) {
bool rawMode = lexerState->mode == LEXER_RAW; bool rawMode = lexerState->mode == LEXER_RAW;
switch (c) { // Symbol interpolation
case '\\': // Character escape or macro arg if (c == '{') {
c = peek();
switch (c) {
// Character escape
case '\\':
case '"':
case '\'':
case '{':
case '}':
if (rawMode) {
str += '\\';
}
str += c;
shiftChar();
break;
case 'n':
str += rawMode ? "\\n" : "\n";
shiftChar();
break;
case 'r':
str += rawMode ? "\\r" : "\r";
shiftChar();
break;
case 't':
str += rawMode ? "\\t" : "\t";
shiftChar();
break;
case '0':
if (rawMode) {
str += "\\0";
} else {
str += '\0';
}
shiftChar();
break;
// Line continuation
case ' ':
case '\t':
case '\r':
case '\n':
discardLineContinuation();
break;
// Macro arg
case '@':
case '#':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '<':
shiftChar();
if (std::shared_ptr<std::string> arg = readMacroArg(c); arg) {
appendExpandedString(str, *arg);
}
break;
case EOF: // Can't really print that one
error("Illegal character escape at end of input");
str += '\\';
break;
default:
error("Illegal character escape %s", printChar(c));
str += c;
shiftChar();
break;
}
break;
case '{': // Symbol interpolation
// We'll be exiting the string/character scope, so re-enable expansions // We'll be exiting the string/character scope, so re-enable expansions
// (Not interpolations, since they're handled by the function itself...) // (Not interpolations, since they're handled by the function itself...)
lexerState->disableMacroArgs = false; lexerState->disableMacroArgs = false;
@@ -1528,10 +1455,86 @@ static void appendCharInLiteral(std::string &str, int c) {
appendExpandedString(str, *interpolation); appendExpandedString(str, *interpolation);
} }
lexerState->disableMacroArgs = true; lexerState->disableMacroArgs = true;
return;
}
// Regular characters will just get copied
if (c != '\\') {
str += c;
return;
}
c = peek();
switch (c) {
// Character escape
case '\\':
case '"':
case '\'':
case '{':
case '}':
if (rawMode) {
str += '\\';
}
str += c;
shiftChar();
break;
case 'n':
str += rawMode ? "\\n" : "\n";
shiftChar();
break;
case 'r':
str += rawMode ? "\\r" : "\r";
shiftChar();
break;
case 't':
str += rawMode ? "\\t" : "\t";
shiftChar();
break;
case '0':
if (rawMode) {
str += "\\0";
} else {
str += '\0';
}
shiftChar();
break; break;
default: // Regular characters will just get copied // Line continuation
case ' ':
case '\t':
case '\r':
case '\n':
discardLineContinuation();
break;
// Macro arg
case '@':
case '#':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '<':
shiftChar();
if (std::shared_ptr<std::string> arg = readMacroArg(c); arg) {
appendExpandedString(str, *arg);
}
break;
case EOF: // Can't really print that one
error("Illegal character escape at end of input");
str += '\\';
break;
default:
error("Illegal character escape %s", printChar(c));
str += c; str += c;
shiftChar();
break; break;
} }
} }
@@ -1583,37 +1586,38 @@ static void readString(std::string &str, bool rawString) {
continue; continue;
} }
// Close the string and return if it's terminated if (c != '"') {
if (c == '"') { // Append the character or handle special ones
if (!multiline) { if (rawString) {
if (rawMode) {
str += c;
}
return;
}
// Only """ ends a multi-line string
if (peek() != '"') {
str += c; str += c;
continue; } else {
appendCharInLiteral(str, c);
} }
shiftChar(); continue;
if (peek() != '"') { }
str += "\"\"";
continue; // Close the string and return if it's terminated
} if (!multiline) {
shiftChar();
if (rawMode) { if (rawMode) {
str += "\"\"\""; str += c;
} }
return; return;
} }
// Only """ ends a multi-line string
// Append the character or handle special ones if (peek() != '"') {
if (rawString) {
str += c; str += c;
} else { continue;
appendCharInLiteral(str, c);
} }
shiftChar();
if (peek() != '"') {
str += "\"\"";
continue;
}
shiftChar();
if (rawMode) {
str += "\"\"\"";
}
return;
} }
} }
@@ -1629,27 +1633,25 @@ static void readCharacter(std::string &str) {
} }
for (;;) { for (;;) {
int c = peek(); switch (int c = peek(); c) {
case '\r':
// '\r', '\n' or EOF ends a character early case '\n':
if (c == EOF || c == '\r' || c == '\n') { case EOF:
// '\r', '\n' or EOF ends a character early
error("Unterminated character"); error("Unterminated character");
return; return;
} case '\'':
// Close the character and return if it's terminated
// We'll be staying in the character, so we can safely consume the char shiftChar();
shiftChar();
// Close the character and return if it's terminated
if (c == '\'') {
if (rawMode) { if (rawMode) {
str += c; str += c;
} }
return; return;
default:
// Append the character or handle special ones
shiftChar();
appendCharInLiteral(str, c);
} }
// Append the character or handle special ones
appendCharInLiteral(str, c);
} }
} }
@@ -2347,14 +2349,7 @@ static Token yylex_SKIP_TO_ENDR() {
} }
} }
// Skip whitespace c = skipChars(isWhitespace);
for (;;) {
c = peek();
if (!isWhitespace(c)) {
break;
}
shiftChar();
}
if (!startsIdentifier(c)) { if (!startsIdentifier(c)) {
continue; continue;
@@ -2489,19 +2484,18 @@ Capture lexer_CaptureRept() {
case T_(POP_REPT): case T_(POP_REPT):
case T_(POP_FOR): case T_(POP_FOR):
depth++; depth++;
// Ignore the rest of that line break; // Ignore the rest of that line
break;
case T_(POP_ENDR): case T_(POP_ENDR):
if (!depth) { if (depth) {
endCapture(capture); depth--;
// The final ENDR has been captured, but we don't want it! break; // Ignore the rest of that line
// We know we have read exactly "ENDR", not e.g. an EQUS
capture.span.size -= literal_strlen("ENDR");
return capture;
} }
depth--; endCapture(capture);
break; // The final ENDR has been captured, but we don't want it!
// We know we have read exactly "ENDR", not e.g. an EQUS
capture.span.size -= literal_strlen("ENDR");
return capture;
default: default:
break; break;

View File

@@ -1032,8 +1032,7 @@ static void
// This should be guaranteed from the size cap... // This should be guaranteed from the size cap...
static_assert(0x10000 * BANK_SIZE <= SSIZE_MAX, "Max input file size too large for OS"); static_assert(0x10000 * BANK_SIZE <= SSIZE_MAX, "Max input file size too large for OS");
// Compute number of banks and ROMX len from file size // Compute number of banks and ROMX len from file size
nbBanks = (fileSize + (BANK_SIZE - 1)) / BANK_SIZE; nbBanks = (fileSize + (BANK_SIZE - 1)) / BANK_SIZE; // ceil(fileSize / BANK_SIZE)
// = ceil(totalRomxLen / BANK_SIZE)
totalRomxLen = fileSize >= BANK_SIZE ? fileSize - BANK_SIZE : 0; totalRomxLen = fileSize >= BANK_SIZE ? fileSize - BANK_SIZE : 0;
} else if (rom0Len == BANK_SIZE) { } else if (rom0Len == BANK_SIZE) {
// Copy ROMX when reading a pipe, and we're not at EOF yet // Copy ROMX when reading a pipe, and we're not at EOF yet

View File

@@ -20,12 +20,12 @@
// The solvers here are picked from the paper at https://arxiv.org/abs/1605.00558: // The solvers here are picked from the paper at https://arxiv.org/abs/1605.00558:
// "Algorithms for the Pagination Problem, a Bin Packing with Overlapping Items" // "Algorithms for the Pagination Problem, a Bin Packing with Overlapping Items"
// Their formulation of the problem consists in packing "tiles" into "pages"; here is a // Their formulation of the problem consists in packing "tiles" into "pages".
// correspondence table for our application of it: // Here is a correspondence table for our application of it:
// Paper | RGBGFX // Paper | RGBGFX
// ------+------- // ------+-------
// Tile | Proto-palette // Tile | Proto-palette
// Page | Palette // Page | Palette
// A reference to a proto-palette, and attached attributes for sorting purposes // A reference to a proto-palette, and attached attributes for sorting purposes
struct ProtoPalAttrs { struct ProtoPalAttrs {