Intern strings used as identifiers (for labels, constants, macros, charmaps, etc) (#1980)

This commit is contained in:
Rangi
2026-05-25 16:22:29 -04:00
committed by GitHub
parent ed19806434
commit cfa0adf295
22 changed files with 341 additions and 218 deletions
+4 -3
View File
@@ -13,7 +13,8 @@
#include "linkdefs.hpp" // AssertionType, RPNCommand
#include "asm/rpn.hpp" // Expression
#include "asm/intern.hpp" // InternedStr
#include "asm/rpn.hpp" // Expression
struct AlignmentSpec {
uint8_t alignment;
@@ -54,8 +55,8 @@ std::string act_StringFormat(
std::string const &spec, std::vector<std::variant<uint32_t, std::string>> const &args
);
std::string act_SectionName(std::string const &symName);
std::string act_SectionName(InternedStr symName);
void act_CompoundAssignment(std::string const &symName, RPNCommand op, int32_t constValue);
void act_CompoundAssignment(InternedStr symName, RPNCommand op, int32_t constValue);
#endif // RGBDS_ASM_ACTIONS_HPP
+5 -4
View File
@@ -10,13 +10,14 @@
#include <string_view>
#include <vector>
#include "asm/intern.hpp"
void charmap_Init();
bool charmap_ForEach(
void (*mapFunc)(std::string const &),
void (*charFunc)(std::string const &, std::vector<int32_t>)
void (*mapFunc)(InternedStr), void (*charFunc)(std::string const &, std::vector<int32_t>)
);
void charmap_New(std::string const &name, std::string const *baseName);
void charmap_Set(std::string const &name);
void charmap_New(InternedStr name, InternedStr const *baseName);
void charmap_Set(InternedStr name);
void charmap_Push();
void charmap_Pop();
void charmap_CheckStack();
+3 -4
View File
@@ -15,6 +15,7 @@
#include "linkdefs.hpp"
#include "asm/intern.hpp"
#include "asm/lexer.hpp"
struct FileStackNode {
@@ -68,12 +69,10 @@ bool fstk_FailedOnMissingInclude();
bool yywrap();
bool fstk_RunInclude(std::string const &path, bool isQuiet);
void fstk_RunMacro(
std::string const &macroName, std::shared_ptr<MacroArgs> macroArgs, bool isQuiet
);
void fstk_RunMacro(InternedStr macroName, std::shared_ptr<MacroArgs> macroArgs, bool isQuiet);
void fstk_RunRept(uint32_t count, int32_t reptLineNo, ContentSpan const &span, bool isQuiet);
void fstk_RunFor(
std::string const &symName,
InternedStr symName,
int32_t start,
int32_t stop,
int32_t step,
+34
View File
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
#ifndef RGBDS_ASM_INTERN_HPP
#define RGBDS_ASM_INTERN_HPP
#include <stddef.h>
#include <string>
#include <string_view>
#include <utility> // hash
class InternedStr {
size_t index;
public:
constexpr InternedStr() : index(static_cast<size_t>(-1)) {}
explicit constexpr InternedStr(size_t index_) : index(index_) {}
std::string const &str() const;
char const *c_str() const { return str().c_str(); }
bool operator==(InternedStr const &rhs) const { return index == rhs.index; }
template<typename T>
friend struct std::hash;
};
template<>
struct std::hash<InternedStr> {
size_t operator()(InternedStr const &str) const { return std::hash<size_t>{}(str.index); }
};
InternedStr intern(std::string_view str);
#endif // RGBDS_ASM_INTERN_HPP
+3 -1
View File
@@ -14,6 +14,8 @@
#include "platform.hpp" // SSIZE_MAX
#include "asm/intern.hpp"
// This value is a compromise between `LexerState` allocation performance when reading the entire
// file works, and buffering performance when it doesn't (e.g. when piping a file into RGBASM).
static constexpr size_t LEXER_BUF_SIZE = 64;
@@ -32,7 +34,7 @@ enum LexerMode {
};
struct Expansion {
std::optional<std::string> name;
std::optional<InternedStr> name;
std::shared_ptr<std::string> contents;
size_t offset; // Cursor into `contents`
+6 -4
View File
@@ -10,16 +10,18 @@
#include "linkdefs.hpp"
#include "asm/intern.hpp"
struct Symbol;
struct RPNValue {
RPNCommand command; // The RPN_* command ID
std::variant<std::monostate, uint8_t, uint32_t, std::string> data; // Data after the ID, if any
std::variant<std::monostate, uint8_t, uint32_t, InternedStr> data; // Data after the ID, if any
RPNValue(RPNCommand cmd);
RPNValue(RPNCommand cmd, uint8_t val);
RPNValue(RPNCommand cmd, uint32_t val);
RPNValue(RPNCommand cmd, std::string const &name);
RPNValue(RPNCommand cmd, InternedStr name);
void appendEncoded(std::vector<uint8_t> &buffer) const;
};
@@ -40,8 +42,8 @@ struct Expression {
bool isDiffConstant(Symbol const *symName) const;
void makeNumber(uint32_t value);
void makeSymbol(std::string const &symName);
void makeBankSymbol(std::string const &symName);
void makeSymbol(InternedStr symName);
void makeBankSymbol(InternedStr symName);
void makeBankSection(std::string const &sectName);
void makeSizeOfSection(std::string const &sectName);
void makeStartOfSection(std::string const &sectName);
+2 -1
View File
@@ -11,6 +11,7 @@
#include <string>
#include <vector>
#include "intern.hpp"
#include "linkdefs.hpp"
struct Expression;
@@ -107,6 +108,6 @@ void sect_PushSection();
void sect_PopSection();
void sect_CheckStack();
std::string sect_PushSectionFragmentLiteral();
InternedStr sect_PushSectionFragmentLiteral();
#endif // RGBDS_ASM_SECTION_HPP
+20 -21
View File
@@ -10,6 +10,7 @@
#include <utility>
#include <variant>
#include "asm/intern.hpp"
#include "asm/lexer.hpp"
#include "asm/section.hpp"
@@ -26,7 +27,7 @@ struct Symbol; // Forward declaration for `sym_IsPC`
bool sym_IsPC(Symbol const *sym); // Forward declaration for `getSection`
struct Symbol {
std::string name;
InternedStr name;
SymbolType type;
bool isBuiltin;
bool isExported; // Not relevant for SYM_MACRO or SYM_EQUS
@@ -68,36 +69,34 @@ struct Symbol {
uint32_t getConstantValue() const;
};
bool sym_IsDotScope(std::string const &symName);
bool sym_IsDotScope(InternedStr symName);
void sym_ForEach(void (*callback)(Symbol &));
Symbol *sym_AddLocalLabel(std::string const &symName);
Symbol *sym_AddLabel(std::string const &symName);
Symbol *sym_AddLocalLabel(InternedStr symName);
Symbol *sym_AddLabel(InternedStr symName);
Symbol *sym_AddAnonLabel();
std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg);
void sym_Export(std::string const &symName);
Symbol *sym_AddEqu(std::string const &symName, int32_t value);
Symbol *sym_RedefEqu(std::string const &symName, int32_t value);
Symbol *sym_AddVar(std::string const &symName, int32_t value);
InternedStr sym_MakeAnonLabelName(uint32_t ofs, bool neg);
void sym_Export(InternedStr symName);
Symbol *sym_AddEqu(InternedStr symName, int32_t value);
Symbol *sym_RedefEqu(InternedStr symName, int32_t value);
Symbol *sym_AddVar(InternedStr symName, int32_t value);
int32_t sym_GetRSValue();
void sym_SetRSValue(int32_t value);
// Find a symbol by exact name, bypassing expansion checks
Symbol *sym_FindExactSymbol(std::string const &symName);
Symbol *sym_FindExactSymbol(InternedStr symName);
// Find a symbol, possibly scoped, by name
Symbol *sym_FindScopedSymbol(std::string const &symName);
Symbol *sym_FindScopedSymbol(InternedStr symName);
// Find a scoped symbol by name; do not return `@` or `_NARG` when they have no value
Symbol *sym_FindScopedValidSymbol(std::string const &symName);
Symbol *sym_FindScopedValidSymbol(InternedStr symName);
Symbol const *sym_GetPC();
Symbol *sym_AddMacro(
std::string const &symName, int32_t defLineNo, ContentSpan const &span, bool isQuiet
);
Symbol *sym_Ref(std::string const &symName);
Symbol *sym_AddString(std::string const &symName, std::shared_ptr<std::string> value);
Symbol *sym_RedefString(std::string const &symName, std::shared_ptr<std::string> value);
void sym_Purge(std::string const &symName);
bool sym_IsPurgedExact(std::string const &symName);
bool sym_IsPurgedScoped(std::string const &symName);
Symbol *sym_AddMacro(InternedStr symName, int32_t defLineNo, ContentSpan const &span, bool isQuiet);
Symbol *sym_Ref(InternedStr symName);
Symbol *sym_AddString(InternedStr symName, std::shared_ptr<std::string> value);
Symbol *sym_RedefString(InternedStr symName, std::shared_ptr<std::string> value);
void sym_Purge(InternedStr symName);
bool sym_IsPurgedExact(InternedStr symName);
bool sym_IsPurgedScoped(InternedStr symName);
void sym_Init(time_t now);
// Functions to save and restore the current label scopes.