diff options
Diffstat (limited to 'source/20-codegen-compiler/CodegenModel.cpp')
-rw-r--r-- | source/20-codegen-compiler/CodegenModel.cpp | 169 |
1 files changed, 148 insertions, 21 deletions
diff --git a/source/20-codegen-compiler/CodegenModel.cpp b/source/20-codegen-compiler/CodegenModel.cpp index 4a9a8f8..97a53b8 100644 --- a/source/20-codegen-compiler/CodegenModel.cpp +++ b/source/20-codegen-compiler/CodegenModel.cpp @@ -100,8 +100,13 @@ public: /* Component Statements, initalized on demand */ SQLiteStatement findNamespaceStmt; SQLiteStatement findOrStoreNamespaceStmt; + SQLiteStatement storeStructStmt; + SQLiteStatement storeStructBaseClassStmt; + SQLiteStatement storeStructPropertyStmt; + // TODO store method SQLiteStatement storeEnumStmt; SQLiteStatement storeEnumElmStmt; + SQLiteStatement deleteFunctionDeclByFilenameStmt; SQLiteStatement deleteStructDeclByFilenameStmt; SQLiteStatement deleteEnumDeclByFilenameStmt; @@ -112,6 +117,7 @@ public: PrintErrMsgIfPresent(errMsg); assert(result == SQLITE_OK); + // TODO unique with overloading, and container structs result = sqlite3_exec(database, R"""( BEGIN TRANSACTION; CREATE TABLE Namespaces( @@ -122,13 +128,57 @@ CREATE TABLE Namespaces( UNIQUE (ParentNamespaceId, Name) ); +CREATE TABLE DeclFunctions( + Id INTEGER PRIMARY KEY, + NamespaceId INTEGER REFERENCES Namespaces(Id), + Name TEXT, + FileName 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, NamespaceId INTEGER REFERENCES Namespaces(Id), - ParentStructId INTEGER REFERENCES DeclStructs(Id), Name TEXT, FileName TEXT, - UNIQUE (NamespaceId, Name) + 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( @@ -136,8 +186,7 @@ CREATE TABLE DeclEnums( NamespaceId INTEGER REFERENCES Namespaces(Id), Name TEXT, UnderlyingType TEXT, - FileName TEXT, - UNIQUE (NamespaceId, Name) + FileName TEXT ); CREATE TABLE DeclEnumElements( EnumId INTEGER REFERENCES DeclEnums(Id) ON DELETE CASCADE, @@ -146,10 +195,17 @@ CREATE TABLE DeclEnumElements( UNIQUE (EnumId, Name) ); -CREATE INDEX Index_DeclStructs_FileName - ON DeclStructs(FileName); -CREATE INDEX Index_DeclEnums_FileName - ON DeclEnums(FileName); +CREATE INDEX Index_DeclFunctions_FileName ON DeclFunctions(FileName); +CREATE INDEX Index_DeclStructs_FileName ON DeclStructs(FileName); +CREATE INDEX Index_DeclEnums_FileName ON DeclEnums(FileName); + +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); INSERT INTO Namespaces(Id, ParentNamespaceId, Name) VALUES @@ -363,6 +419,13 @@ CodegenModelArchive::CodegenModelArchive(std::string_view dbPath) 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); @@ -385,13 +448,6 @@ CodegenModelArchive::CodegenModelArchive(std::string_view dbPath) } } - // NOTE: These pragmas are not persistent, so we need to set them every time - // SQLite3 as of 2022-06-24 defaults to foreign_keys = OFF, 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); - m->beginTransactionStmt.InitializeLazily(m->database, "BEGIN TRANSACTION"); m->commitTransactionStmt.InitializeLazily(m->database, "COMMIT TRANSACTION"); m->rollbackTransactionStmt.InitializeLazily(m->database, "ROLLBACK TRANSACTION"); @@ -404,11 +460,13 @@ CodegenModelArchive::~CodegenModelArchive() { void CodegenModelArchive::DeleteDeclsRelatedToFile(std::string_view filename) { // -Argument- -Description- // ?1 The filename to delete + m->deleteFunctionDeclByFilenameStmt.InitializeLazily(m->database, "DELETE FROM DeclFunctions WHERE FileName = ?1"sv); m->deleteStructDeclByFilenameStmt.InitializeLazily(m->database, "DELETE FROM DeclStructs WHERE FileName = ?1;"sv); m->deleteEnumDeclByFilenameStmt.InitializeLazily(m->database, "DELETE FROM DeclEnums WHERE FileName = ?1;"sv); m->BeginTransaction(); auto stmtList = { + m->deleteFunctionDeclByFilenameStmt.stmt, m->deleteStructDeclByFilenameStmt.stmt, m->deleteEnumDeclByFilenameStmt.stmt, }; @@ -454,7 +512,76 @@ void CodegenModelArchive::Store(const CodegenModel& cgInput) { } void CodegenModelArchive::StoreStruct(const DeclStruct& decl) { - // TODO + // -Argument- -Description- + // ?1 Namespace ID + // ?2 Struct name + // ?3 File containing the struct + m->storeStructStmt.InitializeLazily(m->database, R"""( +INSERT INTO DeclStructs(NamespaceId, Name, FileName, IsMetadataMarked) + VALUES (?1, ?2, ?3, TRUE) + ON CONFLICT DO UPDATE SET + FileName = ?3 + 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) + m->storeStructPropertyStmt.InitializeLazily(m->database, R"""( +INSERT INTO DeclStructProperties(StructId, Name, Type, GetterName, SetterName, IsMetadataMarked) + VALUES (?1, ?2, ?3, ?4, ?5, TRUE) +)"""sv); + + sqlite3_bind_int64(m->storeStructStmt, 1, m->FindNamespace(decl.container)); + sqlite3_bind_text(m->storeStructStmt, 2, decl.name.c_str(), decl.name.size(), nullptr); + if (decl.sourceFile) { + sqlite3_bind_text(m->storeStructStmt, 3, decl.sourceFile->filename.data(), decl.sourceFile->filename.size(), nullptr); + } else { + sqlite3_bind_text(m->storeStructStmt, 3, "", 0, nullptr); + } + int result = sqlite3_step(m->storeStructStmt); + assert(result == SQLITE_ROW); + int64_t structId = sqlite3_column_int64(m->storeStructStmt, 0); + sqlite3_reset(m->storeStructStmt); + sqlite3_clear_bindings(m->storeStructStmt); + + for (auto& baseClass : decl.baseClasses) { + sqlite3_bind_int64(m->storeStructBaseClassStmt, 1, structId); + sqlite3_bind_int64(m->storeStructBaseClassStmt, 2, m->FindNamespace(baseClass->container)); + sqlite3_bind_text(m->storeStructBaseClassStmt, 3, baseClass->name.c_str(), baseClass->name.size(), nullptr); + int result = sqlite3_step(m->storeStructBaseClassStmt); + assert(result == SQLITE_DONE); + sqlite3_reset(m->storeStructBaseClassStmt); + sqlite3_clear_bindings(m->storeStructBaseClassStmt); + } + + for (auto& property : decl.memberVariables) { + sqlite3_bind_int64(m->storeStructPropertyStmt, 1, structId); + sqlite3_bind_text(m->storeStructPropertyStmt, 2, property.name.c_str(), property.name.size(), nullptr); + sqlite3_bind_text(m->storeStructPropertyStmt, 3, property.type.c_str(), property.type.size(), nullptr); + sqlite3_bind_text(m->storeStructPropertyStmt, 4, property.getterName.c_str(), property.getterName.size(), nullptr); + sqlite3_bind_text(m->storeStructPropertyStmt, 5, property.setterName.c_str(), property.setterName.size(), nullptr); + int result = sqlite3_step(m->storeStructPropertyStmt); + assert(result == SQLITE_DONE); + sqlite3_reset(m->storeStructPropertyStmt); + sqlite3_clear_bindings(m->storeStructPropertyStmt); + } + + for (auto& method : decl.memberFunctions) { + // TODO + } } void CodegenModelArchive::StoreFunction(const DeclFunction& decl) { @@ -473,7 +600,7 @@ INSERT INTO DeclEnums(NamespaceId, Name, UnderlyingType, FileName) ON CONFLICT DO UPDATE SET UnderlyingType = ?3, FileName = ?4 - RETURNING Id; + RETURNING Id )"""sv); // -Argument- -Description- @@ -483,7 +610,7 @@ INSERT INTO DeclEnums(NamespaceId, Name, UnderlyingType, FileName) m->storeEnumElmStmt.InitializeLazily(m->database, R"""( INSERT INTO DeclEnumElements(EnumId, Name, Value) VALUES (?1, ?2, ?3) - ON CONFLICT DO UPDATE SET Value=?3; + ON CONFLICT DO UPDATE SET Value=?3 )"""sv); sqlite3_bind_int(m->storeEnumStmt, 1, m->FindNamespace(decl.container)); @@ -492,16 +619,16 @@ INSERT INTO DeclEnumElements(EnumId, Name, Value) if (decl.sourceFile) { sqlite3_bind_text(m->storeEnumStmt, 4, decl.sourceFile->filename.data(), decl.sourceFile->filename.size(), nullptr); } else { - sqlite3_bind_text(m->storeEnumElmStmt, 4, "", 0, nullptr); + sqlite3_bind_text(m->storeEnumStmt, 4, "", 0, nullptr); } int result = sqlite3_step(m->storeEnumStmt); assert(result == SQLITE_ROW); - auto EnumId = sqlite3_column_int64(m->storeEnumStmt, 0); + auto enumId = sqlite3_column_int64(m->storeEnumStmt, 0); sqlite3_reset(m->storeEnumStmt); sqlite3_clear_bindings(m->storeEnumStmt); for (auto& elm : decl.elements) { - sqlite3_bind_int64(m->storeEnumElmStmt, 1, EnumId); + sqlite3_bind_int64(m->storeEnumElmStmt, 1, enumId); sqlite3_bind_text(m->storeEnumElmStmt, 2, elm.name.c_str(), elm.name.size(), nullptr); sqlite3_bind_int64(m->storeEnumElmStmt, 3, elm.value); int result = sqlite3_step(m->storeEnumElmStmt); |