diff options
Diffstat (limited to 'source/20-codegen-compiler/CodegenModel.cpp')
-rw-r--r-- | source/20-codegen-compiler/CodegenModel.cpp | 177 |
1 files changed, 170 insertions, 7 deletions
diff --git a/source/20-codegen-compiler/CodegenModel.cpp b/source/20-codegen-compiler/CodegenModel.cpp index 0017b62..88439e8 100644 --- a/source/20-codegen-compiler/CodegenModel.cpp +++ b/source/20-codegen-compiler/CodegenModel.cpp @@ -16,6 +16,8 @@ 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; }; @@ -55,6 +57,10 @@ struct SQLiteStatement { SQLiteStatement() = default; + SQLiteStatement(sqlite3* database, std::string_view sql) { + Initialize(database, sql); + } + ~SQLiteStatement() { // NOTE: calling with NULL is a harmless no-op // NOTE: we don't care about the error code, because they are returned if the statement has errored in the most recent execution @@ -98,9 +104,10 @@ public: SQLiteStatement beginTransactionStmt; SQLiteStatement commitTransactionStmt; SQLiteStatement rollbackTransactionStmt; - SQLiteStatement storeFileStmt; SQLiteStatement findFileStmt; + SQLiteStatement storeFileStmt; SQLiteStatement findNamespaceStmt; + SQLiteStatement getNamespaceStmt; SQLiteStatement storeNamespaceStmt; /* Component Statements, initalized on demand */ SQLiteStatement storeStructStmt; @@ -112,6 +119,8 @@ public: SQLiteStatement deleteFunctionDeclByFilenameStmt; SQLiteStatement deleteStructDeclByFilenameStmt; SQLiteStatement deleteEnumDeclByFilenameStmt; + // TODO + // SQLiteStatement getRootClassStmt; void InitializeDatabase() { char* errMsg = nullptr; @@ -120,7 +129,6 @@ public: PrintErrMsgIfPresent(errMsg); assert(result == SQLITE_OK); - // TODO create a table of file names // TODO unique with overloading, and container structs result = sqlite3_exec(database, R"""( BEGIN TRANSACTION; @@ -140,7 +148,7 @@ CREATE TABLE Namespaces( CREATE TABLE DeclFunctions( Id INTEGER PRIMARY KEY, - FileId INTEGER REFERENCES Files(Id), + FileId INTEGER REFERENCES Files(Id) ON DELETE CASCADE, NamespaceId INTEGER REFERENCES Namespaces(Id), Name TEXT ); @@ -153,7 +161,7 @@ CREATE TABLE DeclFunctionParameters( CREATE TABLE DeclStructs( Id INTEGER PRIMARY KEY, - FileId INTEGER REFERENCES Files(Id), + FileId INTEGER REFERENCES Files(Id) ON DELETE CASCADE, NamespaceId INTEGER REFERENCES Namespaces(Id), Name TEXT, IsMetadataMarked INTEGER @@ -193,7 +201,7 @@ CREATE TABLE DeclStructMethodParameters( CREATE TABLE DeclEnums( Id INTEGER PRIMARY KEY, - FileId INTEGER REFERENCES Files(Id), +FileId INTEGER REFERENCES Files(Id) ON DELETE CASCADE, NamespaceId INTEGER REFERENCES Namespaces(Id), Name TEXT, UnderlyingType TEXT @@ -286,6 +294,55 @@ COMMIT TRANSACTION; return nsId; } + // TODO maybe merge with Utils::MakeFullName? + std::string GetNamespaceFullName(int64_t nsId) { + std::vector<std::string> namespaceNames; + size_t fullnameLength = 0; + + sqlite3_stmt* stmt = getNamespaceStmt; + int64_t currentNsId = nsId; + while (true) { + sqlite3_bind_int64(stmt, 1, currentNsId); + + int result = sqlite3_step(stmt); + DEFER { + sqlite3_reset(stmt); + sqlite3_clear_bindings(stmt); + }; + assert(result == SQLITE_ROW); + + /* 0th column Id */ + int64_t parentNamespaceId = sqlite3_column_int64(stmt, 1); + auto nameCstr = (const char*)sqlite3_column_text(stmt, 2); + + currentNsId = parentNamespaceId; + std::string name(nameCstr); + fullnameLength += name.size() + 2; + namespaceNames.push_back(std::move(name)); + + if (parentNamespaceId == kGlobalNamespaceId) { + break; + } + } + fullnameLength -= 2; + + std::string fullname; + fullname.reserve(fullnameLength); + + for (auto it = namespaceNames.rbegin(); it != namespaceNames.rend(); ++it) { + fullname.append(*it); + if (std::next(it) != namespaceNames.rend()) { + fullname.append("::"); + } + } + + return fullname; + } + + std::string GetDeclFullName(int64_t nsId, std::string_view declName) { + return GetNamespaceFullName(nsId).append(declName); + } + /// \return Row ID of the file, or 0 if it currently doesn't exist. int64_t FindFile(std::string_view filename) { sqlite3_stmt* stmt = findFileStmt; @@ -498,6 +555,7 @@ CodegenModelArchive::CodegenModelArchive(std::string_view dbPath) 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"); } @@ -528,8 +586,8 @@ void CodegenModelArchive::DeleteDeclsRelatedToFile(std::string_view filename) { m->CommitTransaction(); } -void CodegenModelArchive::Store(const CodegenModel& cgInput) { - auto& cgm = cgInput.GetPimpl(); +void CodegenModelArchive::Store(const CodegenModel& cgModel) { + auto& cgm = cgModel.GetPimpl(); struct Visiter { CodegenModelArchive* self; @@ -551,6 +609,7 @@ void CodegenModelArchive::Store(const CodegenModel& cgInput) { // TODO why are some namepsaces not found in StoreStruct or StoreEnum calls, if we don't use FindOrStoreNamespace there? // since we store all currently scanned namespaces into the model here, does that mean the parser is not correctly picking some of those up? // but if the parser is failing, than the DeclThing objects should have a null `container` field? + // [2022-07-15] I think this bug is fixed, it was caused by FindOrStoreNamespace() not calling sqlite3_reset(), causing a stmt execution state mixup between different namespaces 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); @@ -562,6 +621,110 @@ void CodegenModelArchive::Store(const CodegenModel& cgInput) { m->CommitTransaction(); } +void CodegenModelArchive::LoadInto(CodegenModel& model) const { + // TODO +} + +CodegenModel CodegenModelArchive::Load() const { + CodegenModel 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; + + // NOTE: this is basically { initializer; while(true) { body; } } in a short form + // Load structs + for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructs"sv);;) { + int result = sqlite3_step(stmt); + if (result == SQLITE_DONE) { + break; + } + + if (result == SQLITE_ROW) { + int64_t id = sqlite3_column_int64(stmt, 9); + int64_t fileId = sqlite3_column_int64(stmt, 1); + int64_t nsId = sqlite3_column_int64(stmt, 2); + std::string_view name((const char*)sqlite3_column_text(stmt, 3)); + + auto decl = cgModel.AddStruct(m->GetDeclFullName(nsId, name), DeclStruct{}); + structsById.try_emplace(id, decl); + + continue; + } + + // Executing the statement resulted in an error + assert(false); + } + // Load struct's base classes + for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructBaseClassRelations");;) { + int result = sqlite3_step(stmt); + if (result == SQLITE_DONE) { + break; + } + + if (result == SQLITE_ROW) { + int64_t structId = sqlite3_column_int64(stmt, 0); + int64_t parentStructNsId = sqlite3_column_int64(stmt, 1); + std::string_view parentStructName((const char*)sqlite3_column_text(stmt, 2)); + + auto declThis = structsById.at(structId); + auto declParent = cgModel.FindStruct(parentStructName); // TODO namespace + declThis->baseClasses.push_back(declParent); + + continue; + } + + assert(false); + } + // Load struct properties + for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructProperties"sv);;) { + int result = sqlite3_step(stmt); + if (result == SQLITE_DONE) { + break; + } + + if (result == SQLITE_ROW) { + // TODO + continue; + } + + assert(false); + } + // Load struct methods + for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructMethods"sv);;) { + int result = sqlite3_step(stmt); + if (result == SQLITE_DONE) { + break; + } + + if (result == SQLITE_ROW) { + // TODO + continue; + } + + assert(false); + } + // Load method params + for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructMethodParameters"sv);;) { + int result = sqlite3_step(stmt); + if (result == SQLITE_DONE) { + break; + } + + if (result == SQLITE_ROW) { + // TODO + continue; + } + + assert(false); + } + + return cgModel; +} + void CodegenModelArchive::StoreStruct(const DeclStruct& decl) { // -Argument- -Description- // ?1 Namespace ID |