diff options
Diffstat (limited to 'source/20-codegen-compiler/CodegenModel.cpp')
-rw-r--r-- | source/20-codegen-compiler/CodegenModel.cpp | 732 |
1 files changed, 0 insertions, 732 deletions
diff --git a/source/20-codegen-compiler/CodegenModel.cpp b/source/20-codegen-compiler/CodegenModel.cpp deleted file mode 100644 index 303ad4e..0000000 --- a/source/20-codegen-compiler/CodegenModel.cpp +++ /dev/null @@ -1,732 +0,0 @@ -#include "CodegenModel.hpp" - -#include "CodegenUtils.hpp" -#include "SQLiteHelper.hpp" - -#include <Macros.hpp> -#include <ScopeGuard.hpp> -#include <Utils.hpp> - -#include <robin_hood.h> -#include <cassert> -#include <cstdint> -#include <stdexcept> -#include <string> -#include <variant> - -using namespace std::literals; - -// TODO only delete unused records from model instead of regenerating all records every time - -struct SomeDecl { - std::variant<DeclStruct, DeclFunction, DeclEnum> v; -}; - -class CodegenRuntimeModel::Private { - friend class CodegenArchiveModel; - -public: - // We want address stability for everything - robin_hood::unordered_node_map<std::string, SomeDecl, StringHash, StringEqual> decls; - robin_hood::unordered_node_map<std::string, DeclNamespace, StringHash, StringEqual> namespaces; -}; - -// A number for `PRAGMA user_vesrion`, representing the current database version. Increment when the table format changes. -#define CURRENT_DATABASE_VERSION 1 -constexpr int64_t kGlobalNamespaceId = 1; - -namespace { -void PrintErrMsgIfPresent(char*& errMsg) { - if (errMsg) { - printf("SQLite error: %s\n", errMsg); - sqlite3_free(errMsg); - } -} -} // namespace - -class CodegenArchiveModel::Private { - friend class CodegenRuntimeModel; - -public: - // NOTE: this must be the first field, because we want it to destruct after all other statement fields - SQLiteDatabase database; - /* Core Statements */ - SQLiteStatement beginTransactionStmt; - SQLiteStatement commitTransactionStmt; - SQLiteStatement rollbackTransactionStmt; - SQLiteStatement findFileStmt; - SQLiteStatement storeFileStmt; - SQLiteStatement findNamespaceStmt; - SQLiteStatement getNamespaceStmt; - SQLiteStatement storeNamespaceStmt; - /* Component Statements, initalized on demand */ - SQLiteStatement storeStructStmt; - SQLiteStatement storeStructBaseClassStmt; - SQLiteStatement storeStructPropertyStmt; - // TODO store method - SQLiteStatement storeEnumStmt; - SQLiteStatement storeEnumElmStmt; - SQLiteStatement deleteFunctionDeclByFilenameStmt; - SQLiteStatement deleteStructDeclByFilenameStmt; - SQLiteStatement deleteEnumDeclByFilenameStmt; - // TODO - // SQLiteStatement getRootClassStmt; - - void InitializeDatabase() { - char* errMsg = nullptr; - - int result = sqlite3_exec(database, "PRAGMA user_version = " STRINGIFY(CURRENT_DATABASE_VERSION), nullptr, nullptr, &errMsg); - PrintErrMsgIfPresent(errMsg); - assert(result == SQLITE_OK); - - // TODO unique with overloading, and container structs - result = sqlite3_exec(database, R"""( -BEGIN TRANSACTION; -CREATE TABLE Files( - -- NOTE: SQLite forbids foreign keys referencing the implicit `rowid` column, we have to create an alias for it - Id INTEGER PRIMARY KEY, - FileName TEXT, - UNIQUE (FileName) -); - -CREATE TABLE Namespaces( - Id INTEGER PRIMARY KEY, - ParentNamespaceId INTEGER REFERENCES Namespaces(Id), - Name TEXT, - UNIQUE (ParentNamespaceId, Name) -); - -CREATE TABLE DeclFunctions( - Id INTEGER PRIMARY KEY, - FileId INTEGER REFERENCES Files(Id) ON DELETE CASCADE, - NamespaceId INTEGER REFERENCES Namespaces(Id), - Name TEXT -); -CREATE TABLE DeclFunctionParameters( - FunctionId INTEGER REFERENCES DeclFunctions(Id) ON DELETE CASCADE, - Name TEXT, - Type TEXT, - UNIQUE (FunctionId, Name) -); - -CREATE TABLE DeclStructs( - Id INTEGER PRIMARY KEY, - FileId INTEGER REFERENCES Files(Id) ON DELETE CASCADE, - NamespaceId INTEGER REFERENCES Namespaces(Id), - Name TEXT, - IsMetadataMarked INTEGER -); -CREATE TABLE DeclStructBaseClassRelations( - StructId INTEGER REFERENCES DeclStructs(Id) ON DELETE CASCADE, - -- NOTE: intentionally not foreign keys, because we want relations to still exist even if the base class is deleted - -- we do validation after a complete regeneration pass, on reads - ParentStructNamespaceId INTEGER, - ParentStructName TEXT, - UNIQUE (StructId, ParentStructNamespaceId, ParentStructName) -); -CREATE TABLE DeclStructProperties( - StructId INTEGER REFERENCES DeclStructs(Id) ON DELETE CASCADE, - Name TEXT, - Type TEXT, - -- NOTE: getter and setter may or may not be methods; search the DeclStructMethods table if needed - GetterName TEXT, - SetterName TEXT, - IsPlainField INTEGER GENERATED ALWAYS AS (GetterName = '' AND SetterName = '') VIRTUAL, - IsMetadataMarked INTEGER -); -CREATE TABLE DeclStructMethods( - Id INTEGER PRIMARY KEY, - StructId INTEGER REFERENCES DeclStructs(Id) ON DELETE CASCADE, - Name TEXT, - Type TEXT, - IsConst INTEGER, - IsMetadataMarked INTEGER -); -CREATE TABLE DeclStructMethodParameters( - MethodId INTEGER REFERENCES DeclStructMethods(Id) ON DELETE CASCADE, - Name TEXT, - Type TEXT, - UNIQUE (MethodId, Name) -); - -CREATE TABLE DeclEnums( - Id INTEGER PRIMARY KEY, -FileId INTEGER REFERENCES Files(Id) ON DELETE CASCADE, - NamespaceId INTEGER REFERENCES Namespaces(Id), - Name TEXT, - UnderlyingType TEXT -); -CREATE TABLE DeclEnumElements( - EnumId INTEGER REFERENCES DeclEnums(Id) ON DELETE CASCADE, - Name TEXT, - Value INTEGER, - UNIQUE (EnumId, Name) -); - -CREATE INDEX Index_DeclFunctions_FileId ON DeclFunctions(FileId); -CREATE INDEX Index_DeclStructs_FileId ON DeclStructs(FileId); -CREATE INDEX Index_DeclEnums_FileId ON DeclEnums(FileId); - -CREATE UNIQUE INDEX Index_DeclFunctions_Identity ON DeclFunctions(NamespaceId, Name); - -CREATE UNIQUE INDEX Index_DeclStruct_Identity ON DeclStructs(NamespaceId, Name); -CREATE UNIQUE INDEX Index_DeclStructProperties_Identity ON DeclStructProperties(StructId, Name); -CREATE UNIQUE INDEX Index_DeclStructMethods_Identity ON DeclStructMethods(StructId, Name); - -CREATE UNIQUE INDEX Index_DeclEnums_Identity ON DeclEnums(NamespaceId, Name); - --- Special global namespace that has no parent, and Id should always be 1 -INSERT INTO Namespaces(Id, ParentNamespaceId, Name) -VALUES (1, NULL, '<global namespace>'); - -COMMIT TRANSACTION; -)""", - nullptr, - nullptr, - &errMsg); - PrintErrMsgIfPresent(errMsg); - assert(result == SQLITE_OK); - } - - void BeginTransaction() { - int result = sqlite3_step(beginTransactionStmt); - assert(result == SQLITE_DONE); - sqlite3_reset(beginTransactionStmt); - } - - void CommitTransaction() { - int result = sqlite3_step(commitTransactionStmt); - assert(result == SQLITE_DONE); - sqlite3_reset(commitTransactionStmt); - } - - void RollbackTransaction() { - int result = sqlite3_step(rollbackTransactionStmt); - assert(result == SQLITE_DONE); - sqlite3_reset(rollbackTransactionStmt); - } - - /// \return Row ID of the namespace, or 0 if it currently doesn't exist. - int64_t FindNamespace(const DeclNamespace* ns) { - if (!ns) { - return kGlobalNamespaceId; - } - - return FindNamespaceImpl(*ns); - } - - /// \return Row ID of the namespace. - int64_t FindOrStoreNamespace(const DeclNamespace* ns) { - if (!ns) { - return kGlobalNamespaceId; - } - - if (auto rowId = FindNamespaceImpl(*ns); rowId != 0) { - return rowId; - } - - SQLiteRunningStatement rt(storeNamespaceStmt); - rt.BindArguments(FindOrStoreNamespace(ns->container), ns->name); - - rt.StepAndCheck(SQLITE_ROW); - - auto [nsId] = rt.ResultColumns<int64_t>(); - return nsId; - } - - std::string GetNamespaceFullName(int64_t nsId) const { - return GetNamespaceFullNameImpl(nsId, nullptr, 0); - } - - std::string GetDeclFullName(int64_t nsId, std::string_view declName) const { - return GetNamespaceFullNameImpl(nsId, declName.data(), declName.size()); - } - - /// \return Row ID of the file, or 0 if it currently doesn't exist. - int64_t FindFile(std::string_view filename) { - SQLiteRunningStatement rt(findFileStmt); - rt.BindArguments(filename); - - int result = rt.Step(); - - if (result == SQLITE_ROW) { - auto [fileId] = rt.ResultColumns<int64_t>(); - return fileId; - } else { - return 0; - } - } - - /// \return Row ID of the file - int64_t FindOrStoreFile(std::string_view filename) { - if (auto id = FindFile(filename); id != 0) { - return id; - } - - SQLiteRunningStatement rt(storeFileStmt); - rt.BindArguments(filename); - - rt.StepAndCheck(SQLITE_ROW); - - auto [fileId] = rt.ResultColumns<int64_t>(); - return fileId; - } - - /// \return Row ID of the file, or 0 if not found. - int64_t FindOrStoreFile(/*nullable*/ const SourceFile* file) { - if (!file) { - return 0; - } - return FindOrStoreFile(file->filename); - } - -private: - // TODO maybe merge with Utils::MakeFullName? - std::string GetNamespaceFullNameImpl(int64_t nsId, const char* append, size_t appendLength) const { - std::vector<std::string> namespaceNames; - size_t fullnameLength = 0; - - sqlite3_stmt* stmt = getNamespaceStmt; - int64_t currentNsId = nsId; - while (true) { - SQLiteRunningStatement rt(getNamespaceStmt); - rt.BindArguments(currentNsId); - - rt.StepAndCheck(SQLITE_ROW); - - auto [id, parentNamespaceId, name] = rt.ResultColumns<int64_t, int64_t, std::string>(); - currentNsId = parentNamespaceId; - fullnameLength += name.size() + 2; - namespaceNames.push_back(std::move(name)); - - if (parentNamespaceId == kGlobalNamespaceId) { - break; - } - } - if (append) { - // Already has the '::' at the end - fullnameLength += appendLength; - } else { - fullnameLength -= 2; - } - - std::string fullname; - fullname.reserve(fullnameLength); - - for (auto it = namespaceNames.rbegin(); it != namespaceNames.rend(); ++it) { - fullname.append(*it); - if (append || std::next(it) != namespaceNames.rend()) { - fullname.append("::"); - } - } - if (append) { - fullname += std::string_view(append, appendLength); - } - - return fullname; - } - - int64_t FindNamespaceImpl(const DeclNamespace& ns) { - int64_t parentNsRowId; - if (ns.container) { - parentNsRowId = FindNamespaceImpl(*ns.container); - if (parentNsRowId == 0) { - // Parent namespace doesn't exist in database, shortcircuit - return 0; - } - } else { - parentNsRowId = kGlobalNamespaceId; - } - - return FindNamespaceImpl(ns, parentNsRowId); - } - - int64_t FindNamespaceImpl(const DeclNamespace& ns, int64_t parentNsRowId) { - sqlite3_stmt* stmt = findNamespaceStmt; - SQLiteRunningStatement rt(findNamespaceStmt); - rt.BindArguments(parentNsRowId, ns.name); - - int result = rt.Step(); - if (result == SQLITE_ROW) { - auto [nsId] = rt.ResultColumns<int64_t>(); - return nsId; - } else { - return 0; - } - } -}; - -CodegenRuntimeModel::CodegenRuntimeModel() - : m{ new Private() } // -{ -} - -CodegenRuntimeModel::~CodegenRuntimeModel() { - delete m; -} - -#define STORE_DECL_OF_TYPE(DeclType, fullname, decl) \ - auto [iter, success] = m->decls.try_emplace(std::move(fullname), SomeDecl{ .v = std::move(decl) }); \ - auto& key = iter->first; \ - auto& val = iter->second; \ - auto& declRef = std::get<DeclType>(val.v); \ - declRef.fullname = &key; \ - return &declRef - -DeclEnum* CodegenRuntimeModel::AddEnum(std::string fullname, DeclEnum decl) { -#if CODEGEN_DEBUG_PRINT - printf("Committed enum '%s'\n", decl.name.c_str()); - for (auto& elm : decl.elements) { - printf(" - element %s = %" PRId64 "\n", elm.name.c_str(), elm.value); - } -#endif - - STORE_DECL_OF_TYPE(DeclEnum, fullname, decl); -} - -DeclStruct* CodegenRuntimeModel::AddStruct(std::string fullname, DeclStruct decl) { -#if CODEGEN_DEBUG_PRINT - printf("Committed struct '%s'\n", decl.name.c_str()); - printf(" Base classes:\n"); - for (auto& base : decl.baseClasses) { - printf(" - %.*s\n", PRINTF_STRING_VIEW(base->name)); - } -#endif - - STORE_DECL_OF_TYPE(DeclStruct, fullname, decl); -} - -#define FIND_DECL_OF_TYPE(DeclType) \ - auto iter = m->decls.find(name); \ - if (iter != m->decls.end()) { \ - auto& some = iter->second.v; \ - if (auto decl = std::get_if<DeclType>(&some)) { \ - return decl; \ - } \ - } \ - return nullptr - -const DeclEnum* CodegenRuntimeModel::FindEnum(std::string_view name) const { - FIND_DECL_OF_TYPE(DeclEnum); -} - -const DeclStruct* CodegenRuntimeModel::FindStruct(std::string_view name) const { - FIND_DECL_OF_TYPE(DeclStruct); -} - -DeclNamespace* CodegenRuntimeModel::AddNamespace(DeclNamespace ns) { - auto path = Utils::MakeFullName(""sv, &ns); - auto [iter, success] = m->namespaces.try_emplace(std::move(path), std::move(ns)); - auto& nsRef = iter->second; - if (success) { - nsRef.fullname = &iter->first; - } - return &nsRef; -} - -const DeclNamespace* CodegenRuntimeModel::FindNamespace(std::string_view fullname) const { - auto iter = m->namespaces.find(fullname); - if (iter != m->namespaces.end()) { - return &iter->second; - } else { - return nullptr; - } -} - -DeclNamespace* CodegenRuntimeModel::FindNamespace(std::string_view name) { - return const_cast<DeclNamespace*>(const_cast<const CodegenRuntimeModel*>(this)->FindNamespace(name)); -} - -CodegenArchiveModel::CodegenArchiveModel(std::string_view dbPath) - : m{ new Private() } // -{ - std::string zstrPath(dbPath); - int reuslt = sqlite3_open(zstrPath.c_str(), &m->database); - if (reuslt != SQLITE_OK) { - std::string msg; - msg += "Failed to open SQLite3 database, error message:\n"; - msg += sqlite3_errmsg(m->database); - throw std::runtime_error(msg); - } - - // NOTE: These pragmas are not persistent, so we need to set them every time - // As of SQLite3 3.38.5, it defaults to foreign_keys = OFF, so we need this to be on for ON DELETE CASCADE and etc. to work - sqlite3_exec(m->database, "PRAGMA foreign_keys = ON", nullptr, nullptr, nullptr); - // This database is used for a buildsystem and can be regenerated at any time. We don't care for the slightest about data integrity, we just want fast updates - sqlite3_exec(m->database, "PRAGMA synchronous = OFF", nullptr, nullptr, nullptr); - sqlite3_exec(m->database, "PRAGMA journal_mode = MEMORY", nullptr, nullptr, nullptr); - - { - SQLiteStatement readVersionStmt; - readVersionStmt.InitializeLazily(m->database, "PRAGMA user_version"sv); - - int result = sqlite3_step(readVersionStmt); - assert(result == SQLITE_ROW); - int currentDatabaseVersion = sqlite3_column_int(readVersionStmt, 0); - - result = sqlite3_step(readVersionStmt); - assert(result == SQLITE_DONE); - - if (currentDatabaseVersion == 0) { - // Newly created database, initialize it - m->InitializeDatabase(); - } else if (currentDatabaseVersion == CURRENT_DATABASE_VERSION) { - // Same version, no need to do anything - } else { - INPLACE_FMT(msg, "Incompatbile database versions %d (in file) vs %d (expected).", currentDatabaseVersion, CURRENT_DATABASE_VERSION); - throw std::runtime_error(msg); - } - } - - // Initialize core statements - m->beginTransactionStmt.Initialize(m->database, "BEGIN TRANSACTION"); - m->commitTransactionStmt.Initialize(m->database, "COMMIT TRANSACTION"); - m->rollbackTransactionStmt.Initialize(m->database, "ROLLBACK TRANSACTION"); - m->findFileStmt.Initialize(m->database, "SELECT Id FROM Files WHERE FileName = ?1"); - m->storeFileStmt.Initialize(m->database, "INSERT INTO Files(FileName) VALUES (?1) RETURNING Id"); - m->findNamespaceStmt.Initialize(m->database, "SELECT Id FROM Namespaces WHERE ParentNamespaceId = ?1 AND Name = ?2"); - m->getNamespaceStmt.Initialize(m->database, "SELECT * FROM Namespaces WHERE Id = ?1"sv); - m->storeNamespaceStmt.Initialize(m->database, "INSERT INTO Namespaces(ParentNamespaceId, Name) VALUES (?1, ?2) RETURNING Id"); -} - -CodegenArchiveModel::~CodegenArchiveModel() { - delete m; -} - -void CodegenArchiveModel::DeleteDeclsRelatedToFile(std::string_view filename) { - // -Argument- -Description- - // ?1 The filename to delete - m->deleteFunctionDeclByFilenameStmt.InitializeLazily(m->database, "DELETE FROM DeclFunctions WHERE FileId = (SELECT Id FROM Files WHERE FileName = ?1)"sv); - m->deleteStructDeclByFilenameStmt.InitializeLazily(m->database, "DELETE FROM DeclStructs WHERE FileId = (SELECT Id FROM Files WHERE FileName = ?1);"sv); - m->deleteEnumDeclByFilenameStmt.InitializeLazily(m->database, "DELETE FROM DeclEnums WHERE FileId = (SELECT Id FROM Files WHERE FileName = ?1);"sv); - - m->BeginTransaction(); - auto stmtList = { - m->deleteFunctionDeclByFilenameStmt.stmt, - m->deleteStructDeclByFilenameStmt.stmt, - m->deleteEnumDeclByFilenameStmt.stmt, - }; - for (auto& stmt : stmtList) { - SQLiteRunningStatement rt(stmt); - rt.BindArguments(filename); - rt.StepUntilDone(); - } - m->CommitTransaction(); -} - -void CodegenArchiveModel::Store(const CodegenRuntimeModel& cgModel) { - auto& cgm = cgModel.GetPimpl(); - - struct Visiter { - CodegenArchiveModel* self; - - void operator()(const DeclStruct& decl) const { - self->StoreStruct(decl); - } - void operator()(const DeclFunction& decl) const { - self->StoreFunction(decl); - } - void operator()(const DeclEnum& decl) const { - self->StoreEnum(decl); - } - } visiter; - visiter.self = this; - - m->BeginTransaction(); - - for (auto&& [DISCARD, ns] : cgm.namespaces) { - // This will insert the namespace if it doesn't exist, or no-op (fetches data) if it already exists - m->FindOrStoreNamespace(&ns); - } - for (auto&& [DISCARD, value] : cgm.decls) { - std::visit(visiter, value.v); - } - - m->CommitTransaction(); -} - -void CodegenArchiveModel::LoadInto(CodegenRuntimeModel& model) const { - // TODO -} - -CodegenRuntimeModel CodegenArchiveModel::Load() const { - CodegenRuntimeModel cgModel; - - // TODO files - // TODO namespaces - - robin_hood::unordered_map<int64_t, DeclStruct*> structsById; - robin_hood::unordered_map<int64_t, DeclMemberVariable*> propertiesById; - robin_hood::unordered_map<int64_t, DeclMemberFunction*> methodsById; - - { // Load structs - SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructs"sv); - SQLiteRunningStatement rt(stmt); - while (true) { - int result = rt.StepAndCheckError(); - if (result == SQLITE_DONE) break; - assert(result == SQLITE_ROW); - - auto [id, fileId, nsId, name] = rt.ResultColumns<int64_t, int64_t, int64_t, std::string_view>(); - - auto decl = cgModel.AddStruct(m->GetDeclFullName(nsId, name), DeclStruct{}); - structsById.try_emplace(id, decl); - } - } - { // Load struct's base classes - SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructBaseClassRelations"); - SQLiteRunningStatement rt(stmt); - while (true) { - int result = rt.StepAndCheckError(); - if (result == SQLITE_DONE) break; - assert(result == SQLITE_ROW); - - auto [structId, parentStructNsId, parentStructName] = rt.ResultColumns<int64_t, int64_t, std::string_view>(); - - auto declThis = structsById.at(structId); - auto declParent = cgModel.FindStruct(parentStructName); // TODO namespace - declThis->baseClasses.push_back(declParent); - } - } - { // Load struct properties - SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructProperties"sv); - SQLiteRunningStatement rt(stmt); - while (true) { - int result = rt.StepAndCheckError(); - if (result == SQLITE_DONE) break; - assert(result == SQLITE_ROW); - - // TODO - } - } - { // Load struct methods - SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructMethods"sv); - SQLiteRunningStatement rt(stmt); - while (true) { - int result = rt.StepAndCheckError(); - if (result == SQLITE_DONE) break; - assert(result == SQLITE_ROW); - - // TODO - } - } - { // Load method params - SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructMethodParameters"sv); - SQLiteRunningStatement rt(stmt); - while (true) { - int result = rt.StepAndCheckError(); - if (result == SQLITE_DONE) break; - assert(result == SQLITE_ROW); - - // TODO - } - } - - return cgModel; -} - -void CodegenArchiveModel::StoreStruct(const DeclStruct& decl) { - // -Argument- -Description- - // ?1 Namespace ID - // ?2 Struct name - // ?3 File ID containing the struct - // ?4 Is this struct marked for metadata generation? - m->storeStructStmt.InitializeLazily(m->database, R"""( -INSERT INTO DeclStructs(NamespaceId, Name, FileId, IsMetadataMarked) -VALUES (?1, ?2, ?3, ?4) -ON CONFLICT DO UPDATE SET - FileId = ?3, - IsMetadataMarked = ?4 -RETURNING Id -)"""sv); - - // -Argument- -Description- - // ?1 Struct ID - // ?2 Parent struct's namespace ID - // ?3 Parent struct's name - m->storeStructBaseClassStmt.InitializeLazily(m->database, R"""( -INSERT INTO DeclStructBaseClassRelations(StructId, ParentStructNamespaceId, ParentStructName) -VALUES (?1, ?2, ?3) -)"""sv); - - // -Argument- -Description- - // ?1 Struct ID - // ?2 Property name - // ?3 Property type - // ?4 Getter name (optional) - // ?5 Setter name (optional) - // ?6 Is this property marked for metadata generation? - m->storeStructPropertyStmt.InitializeLazily(m->database, R"""( -INSERT INTO DeclStructProperties(StructId, Name, Type, GetterName, SetterName, IsMetadataMarked) -VALUES (?1, ?2, ?3, ?4, ?5, ?6) -)"""sv); - - SQLiteRunningStatement rt(m->storeStructStmt); - rt.BindArguments(m->FindOrStoreNamespace(decl.container), decl.name, m->FindOrStoreFile(decl.sourceFile), decl.generating); - rt.StepAndCheck(SQLITE_ROW); - auto [structId] = rt.ResultColumns<int64_t>(); - - for (auto& baseClass : decl.baseClasses) { - SQLiteRunningStatement rt(m->storeStructBaseClassStmt); - rt.BindArguments(structId, m->FindOrStoreNamespace(baseClass->container), baseClass->name); - rt.StepUntilDone(); - } - - for (auto& property : decl.memberVariables) { - SQLiteRunningStatement rt(m->storeStructPropertyStmt); - rt.BindArguments( - structId, - property.name, - property.type, - property.getterName, - property.setterName, - // Since DeclMemberVariable entries currently only exist if it's marked BRUSSEL_PROPERTY - true); - rt.StepUntilDone(); - } - - for (auto& method : decl.memberFunctions) { - // TODO - } -} - -void CodegenArchiveModel::StoreFunction(const DeclFunction& decl) { - // TODO -} - -void CodegenArchiveModel::StoreEnum(const DeclEnum& decl) { - // -Argument- -Description- - // ?1 Namespace ID - // ?2 Enum name - // ?3 Enum underlying type - // ?4 File ID containing the enum - m->storeEnumStmt.InitializeLazily(m->database, R"""( -INSERT INTO DeclEnums(NamespaceId, Name, UnderlyingType, FileId) -VALUES (?1, ?2, ?3, ?4) -ON CONFLICT DO UPDATE SET - UnderlyingType = ?3, - FileId = ?4 -RETURNING Id -)"""sv); - - // -Argument- -Description- - // ?1 Container enum's id - // ?2 Enum element name - // ?3 Enum element value - m->storeEnumElmStmt.InitializeLazily(m->database, R"""( -INSERT INTO DeclEnumElements(EnumId, Name, Value) -VALUES (?1, ?2, ?3) -ON CONFLICT DO UPDATE SET Value=?3 -)"""sv); - - SQLiteRunningStatement rt(m->storeEnumStmt); - rt.BindArguments(m->FindOrStoreNamespace(decl.container), decl.name, decl.GetUnderlyingTypeName(), m->FindOrStoreFile(decl.sourceFile)); - rt.StepAndCheck(SQLITE_ROW); - auto [enumId] = rt.ResultColumns<int64_t>(); - - for (auto& elm : decl.elements) { - SQLiteRunningStatement rt(m->storeEnumElmStmt); - rt.BindArguments(enumId, elm.name, elm.value); - rt.StepUntilDone(); - } -} |