From cdaab4d0bcd6645ad4f0e05018538c620a51d901 Mon Sep 17 00:00:00 2001 From: Sdoba16 Date: Thu, 7 May 2026 14:42:20 +0300 Subject: [PATCH] Change SourceFile to CanonSourceFile in CompiledProgram and TemplateProgram to forbid passing SourceFile::anonymous --- src/driver/mod.rs | 22 ++++++++-------------- src/lib.rs | 25 +++++++++++++++++++------ src/main.rs | 7 +++---- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/driver/mod.rs b/src/driver/mod.rs index d693f008..08110d3d 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -39,7 +39,7 @@ use chumsky::container::Container; use crate::error::{Error, ErrorCollector, RichError, Span}; use crate::parse::{self, ParseFromStrWithErrors}; use crate::resolution::DependencyMap; -use crate::source::{CanonPath, CanonSourceFile, SourceFile}; +use crate::source::{CanonPath, CanonSourceFile}; pub use crate::driver::resolve_order::{FileScoped, Program, SymbolTable}; @@ -133,30 +133,25 @@ impl DependencyGraph { /// /// # Errors /// - /// This function will return an `Err(String)` only for critical internal compiler errors - /// (e.g., if a provided `SourceFile` is unexpectedly missing its underlying file path). + /// This function will return an `Err(String)` only for critical internal compiler errors. pub fn new( - root_source: SourceFile, + root_source: CanonSourceFile, dependency_map: Arc, root_program: &parse::Program, handler: &mut ErrorCollector, ) -> Result, String> { - let root_canon_source = CanonSourceFile::try_from(root_source)?; - let mut graph = Self { modules: vec![Module { - source: root_canon_source.clone(), + source: root_source.clone(), parsed_program: root_program.clone(), }], dependency_map, lookup: HashMap::new(), - paths: vec![root_canon_source.name().clone()], + paths: vec![root_source.name().clone()], dependencies: HashMap::new(), }; - graph - .lookup - .insert(root_canon_source.name().clone(), MAIN_MODULE); + graph.lookup.insert(root_source.name().clone(), MAIN_MODULE); graph.dependencies.insert(MAIN_MODULE, Vec::new()); let mut queue = VecDeque::new(); @@ -366,17 +361,16 @@ pub(crate) mod tests { let root_p = root_file_path.expect("main.simf must be defined in file list"); let main_canon_source = CanonSourceFile::new(root_p, Arc::from(root_content)); - let main_source = SourceFile::from(main_canon_source); let main_program_option = - parse::Program::parse_from_str_with_errors(main_source.clone(), &mut handler); + parse::Program::parse_from_str_with_errors(main_canon_source.clone(), &mut handler); let Some(main_program) = main_program_option else { return (None, HashMap::new(), ws, handler); }; let graph_option = - DependencyGraph::new(main_source, map, &main_program, &mut handler).unwrap(); + DependencyGraph::new(main_canon_source, map, &main_program, &mut handler).unwrap(); let mut file_ids = HashMap::new(); diff --git a/src/lib.rs b/src/lib.rs index 53107430..4b432d52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ use crate::driver::DependencyGraph; use crate::error::{ErrorCollector, WithContent, WithSource as _}; use crate::parse::ParseFromStrWithErrors; use crate::resolution::DependencyMap; +use crate::source::CanonSourceFile; use crate::source::SourceFile; pub use crate::types::ResolvedType; pub use crate::value::Value; @@ -57,14 +58,13 @@ pub struct TemplateProgram { } impl TemplateProgram { - // TODO: Consider passing `CanonSourceFile`` deeper into the driver to avoid paying the path canonicalization cost multiple times. /// Parse the template of a SimplicityHL program. /// /// ## Errors /// /// The string is not a valid SimplicityHL program. pub fn new_with_dep( - source: SourceFile, + source: CanonSourceFile, dependency_map: &DependencyMap, ) -> Result { let mut error_handler = ErrorCollector::new(); @@ -186,7 +186,7 @@ impl CompiledProgram { /// - [`TemplateProgram::new_with_dep`] /// - [`TemplateProgram::instantiate`] pub fn new_with_dep( - source: SourceFile, + source: CanonSourceFile, dependency_map: &DependencyMap, arguments: Arguments, include_debug_symbols: bool, @@ -424,7 +424,10 @@ pub(crate) mod tests { pub fn template_deps(prog_path: &Path, dependency_map: &DependencyMap) -> Self { let program_text = std::fs::read_to_string(prog_path).unwrap(); - let source = SourceFile::new(prog_path, Arc::from(program_text)); + let source = CanonSourceFile::new( + crate::source::CanonPath::canonicalize(prog_path).unwrap(), + Arc::from(program_text), + ); let program = match TemplateProgram::new_with_dep(source, dependency_map) { Ok(x) => x, @@ -737,6 +740,16 @@ pub(crate) mod tests { .assert_run_success(); } + #[test] + fn test_anonymous_source_compiles_without_dependencies() { + let code = "fn main() { assert!(true); }"; + let program = TemplateProgram::new(code); + assert!( + program.is_ok(), + "TemplateProgram::new should successfully compile anonymous source files without requiring canonical paths" + ); + } + #[test] fn cat() { TestCase::program_file("./examples/cat.simf") @@ -1157,9 +1170,9 @@ mod error_tests { .unwrap() } - fn source_file(path: &Path) -> SourceFile { + fn source_file(path: &Path) -> CanonSourceFile { let content = std::fs::read_to_string(path).expect("Failed to read test file"); - SourceFile::new(path, Arc::from(content)) + CanonSourceFile::new(canon(path), Arc::from(content)) } #[test] diff --git a/src/main.rs b/src/main.rs index 7ef79a3e..761900cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,9 +3,8 @@ use base64::engine::general_purpose::STANDARD; use clap::{Arg, ArgAction, Command}; use simplicityhl::{ - resolution::DependencyMapBuilder, - source::{CanonPath, SourceFile}, - AbiMeta, CompiledProgram, + resolution::DependencyMapBuilder, source::CanonPath, source::CanonSourceFile, AbiMeta, + CompiledProgram, }; use std::path::Path; use std::{env, fmt}; @@ -169,7 +168,7 @@ fn main() -> Result<(), Box> { } }; - let source = SourceFile::new(main_path.as_path(), std::sync::Arc::from(main_text)); + let source = CanonSourceFile::new(main_path.clone(), std::sync::Arc::from(main_text)); let compiled = match CompiledProgram::new_with_dep(source, &dependencies, args_opt, include_debug_symbols) {