The Database struct is the core of MCC’s incremental compilation system, powered by the Salsa framework. It tracks queries and their dependencies, enabling efficient recomputation when inputs change.
The Db trait is automatically implemented for any type that implements salsa::Database. All pipeline functions accept &dyn Db to remain agnostic to the concrete database type.
// Parsing is trackedlet ast = mcc::parse(&db, file); // Cached if `file` hasn't changed// Lowering is trackedlet tacky = mcc::lowering::lower_program(&db, file); // Cached if AST is unchanged// Codegen is trackedlet asm = mcc::codegen::generate_assembly(&db, tacky); // Cached if TAC is unchanged
Salsa memoizes results and only recomputes when dependencies change.
use mcc::{Database, SourceFile, Text};let db = Database::default();// First compilationlet file = SourceFile::new(&db, "main.c".into(), "int main() { return 0; }".into());let ast1 = mcc::parse(&db, file);let tacky1 = mcc::lowering::lower_program(&db, file);// Modify the sourcefile.set_contents(&db).to("int main() { return 42; }".into());// Salsa detects the change and recomputes only affected stageslet ast2 = mcc::parse(&db, file); // Re-parsedlet tacky2 = mcc::lowering::lower_program(&db, file); // Re-lowered
In practice, you’d create a new SourceFile rather than mutating it, since SourceFile is typically treated as immutable. The example above shows the conceptual model.
use mcc::{Database, SourceFile, Text, Ast};fn parse_file(db: &Database, src: &str) -> Ast<'_> { let file = SourceFile::new(db, "input.c".into(), src.into()); mcc::parse(db, file)}// The returned Ast borrows from the databaselet db = Database::default();let ast = parse_file(&db, "int x;");// `ast` is valid as long as `db` is alive
Database is Clone but not Send or Sync by default. For multi-threaded use:
The current Database implementation is designed for single-threaded use. Parallel compilation is not yet supported. Clone the database if you need isolated compilation sessions.