Skip to content

Commit ead2fd4

Browse files
Sdoba16LesterEvSe
authored andcommitted
Refactoring, tests, bug-fixing
1 parent 0ce31e9 commit ead2fd4

51 files changed

Lines changed: 345 additions & 131 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn add(a: u32, b: u32) -> (bool, u32) {
2+
jet::add_32(a, b)
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn add(a: u32, b: u32) -> (bool, u32) {
2+
jet::add_32(b, a)
3+
}

examples/collisions/main.simf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use math::add;
2+
3+
fn main() {
4+
let result: (bool, u32) = add(20, 20);
5+
}

examples/visibility/helper.simf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn do_something_private() {
2+
let x: u32 = 42;
3+
}
4+
5+
pub fn do_something_public() {
6+
do_something_private();
7+
}

examples/visibility/main.simf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use secret_lib::do_something_public;
2+
3+
fn main() {
4+
do_something_public();
5+
}

src/ast.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,14 +1540,18 @@ impl AbstractSyntaxTree for Match {
15401540
}
15411541
}
15421542

1543+
/// Analyze a parsed module program to extract assignments for a specific module.
1544+
///
1545+
/// This function searches the parsed program for a module matching the given `name`.
1546+
/// If found, it evaluates the module's assignments and returns them as a map of
1547+
/// witness names to their constant values. If the module is not present, an empty
1548+
/// map is returned.
15431549
fn analyze_named_module(
15441550
name: ModuleName,
15451551
from: &parse::ModuleProgram,
15461552
) -> Result<HashMap<WitnessName, Value>, RichError> {
15471553
let unit = ResolvedType::unit();
15481554

1549-
// IMPORTANT! If modules allow imports, then we need to consider
1550-
// passing the resolution conetxt by calling `Scope::new(resolutions)`
15511555
let mut scope = Scope::default();
15521556
let items = from
15531557
.items()

src/driver.rs

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,17 @@ impl_eq_hash!(TypeAlias; name, ty);
313313
#[derive(Debug)]
314314
pub enum C3Error {
315315
CycleDetected(Vec<String>),
316-
InconsistentLinearization { module: String },
316+
/// Error for inconsistent MRO.
317+
/// This can happen if the dependency graph has a shape that makes the
318+
/// order of parent classes ambiguous.
319+
/// Example: A depends on B and C, and B also depends on C.
320+
/// The linearization of A is A + merge(linearization(B), linearization(C), [B, C]).
321+
/// If B appears before C in one parent's linearization but C appears before B
322+
/// in another's, the merge will fail.
323+
InconsistentLinearization {
324+
module: String,
325+
conflicts: Vec<Vec<String>>,
326+
},
317327
}
318328

319329
impl fmt::Display for C3Error {
@@ -322,8 +332,22 @@ impl fmt::Display for C3Error {
322332
C3Error::CycleDetected(cycle) => {
323333
write!(f, "Circular dependency detected: {:?}", cycle.join(" -> "))
324334
}
325-
C3Error::InconsistentLinearization { module } => {
326-
write!(f, "Inconsistent resolution order for module '{:?}'", module)
335+
C3Error::InconsistentLinearization { module, conflicts } => {
336+
writeln!(f, "Inconsistent resolution order for module '{}'", module)?;
337+
writeln!(
338+
f,
339+
"The compiler could not resolve the following conflicting import constraints:"
340+
)?;
341+
342+
// Loop through the matrix and print each conflicting sequence
343+
for conflict in conflicts {
344+
writeln!(f, " [{}]", conflict.join(", "))?;
345+
}
346+
347+
write!(
348+
f,
349+
"Try reordering your `use` statements to avoid cross-wiring."
350+
)
327351
}
328352
}
329353
}
@@ -489,12 +513,26 @@ impl ProjectGraph {
489513
seqs.push(line);
490514
}
491515

492-
seqs.push(parents.clone());
493-
494516
let mut result = vec![module];
495-
let merged = merge(seqs).ok_or(C3Error::InconsistentLinearization {
496-
module: self.modules[module].source.name().to_string(),
497-
})?;
517+
let merged = match merge(seqs) {
518+
Ok(m) => m,
519+
Err(conflicts) => {
520+
// Map the failing usize sequences into readable module names
521+
let conflict_names: Vec<Vec<String>> = conflicts
522+
.into_iter()
523+
.map(|seq| {
524+
seq.into_iter()
525+
.map(|id| self.modules[id].source.name().to_string())
526+
.collect()
527+
})
528+
.collect();
529+
530+
return Err(C3Error::InconsistentLinearization {
531+
module: self.modules[module].source.name().to_string(),
532+
conflicts: conflict_names,
533+
});
534+
}
535+
};
498536

499537
result.extend(merged);
500538

@@ -720,13 +758,18 @@ impl ProjectGraph {
720758
}
721759
}
722760

723-
fn merge(mut seqs: Vec<Vec<usize>>) -> Option<Vec<usize>> {
761+
/// C3 Merge Algorithm
762+
///
763+
/// Merges a list of sequences (parent linearizations) into a single sequence.
764+
/// The algorithm ensures that the local precedence order of each sequence is preserved.
765+
// Change the return type to Result
766+
fn merge(mut seqs: Vec<Vec<usize>>) -> Result<Vec<usize>, Vec<Vec<usize>>> {
724767
let mut result = Vec::new();
725768

726769
loop {
727770
seqs.retain(|s| !s.is_empty());
728771
if seqs.is_empty() {
729-
return Some(result);
772+
return Ok(result);
730773
}
731774

732775
let mut candidate = None;
@@ -740,7 +783,9 @@ fn merge(mut seqs: Vec<Vec<usize>>) -> Option<Vec<usize>> {
740783
}
741784
}
742785

743-
let head = candidate?;
786+
let Some(head) = candidate else {
787+
return Err(seqs);
788+
};
744789

745790
result.push(head);
746791

@@ -881,7 +926,6 @@ pub(crate) mod tests {
881926
use std::path::Path;
882927
use tempfile::TempDir;
883928

884-
// ProjectGraph::new tests
885929
// Creates a file with specific content in the temp directory
886930
pub(crate) fn create_simf_file(dir: &Path, rel_path: &str, content: &str) -> PathBuf {
887931
let full_path = dir.join(rel_path);
@@ -898,7 +942,6 @@ pub(crate) mod tests {
898942
}
899943

900944
// Helper to mock the initial root program parsing
901-
// (Assuming your parser works via a helper function)
902945
fn parse_root(path: &Path) -> (parse::Program, SourceFile) {
903946
// 1. Read file
904947
let content = std::fs::read_to_string(path).expect("Failed to read root file for parsing");

src/error.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@ pub enum Error {
443443
FileNotFound(PathBuf),
444444
UnresolvedItem(Identifier),
445445
PrivateItem(String),
446+
NameCollision(String),
447+
DependencyCycle(Vec<String>),
448+
InconsistentLinearization(String, Vec<Vec<String>>),
446449
MainNoInputs,
447450
MainNoOutput,
448451
MainRequired,
@@ -535,6 +538,18 @@ impl fmt::Display for Error {
535538
f,
536539
"File `{}` not found", path.to_string_lossy()
537540
),
541+
Error::DependencyCycle(cycle) => {
542+
let path_str = cycle.join(" -> ");
543+
write!(f, "Cyclic dependency detected: {path_str}")
544+
},
545+
Error::InconsistentLinearization(module, conflicts) => {
546+
writeln!(f, "Inconsistent module resolution (linearization failed) for module `{module}`.")?;
547+
writeln!(f, "The compiler could not resolve the following conflicting import constraints:")?;
548+
for conflict in conflicts {
549+
writeln!(f, " [{}]", conflict.join(", "))?;
550+
}
551+
write!(f, "Try reordering your `use` statements to avoid cross-wiring.")
552+
},
538553
Error::MainNoInputs => write!(
539554
f,
540555
"Main function takes no input parameters"
@@ -563,6 +578,10 @@ impl fmt::Display for Error {
563578
f,
564579
"Item `{name}` is private"
565580
),
581+
Error::NameCollision(name) => write!(
582+
f,
583+
"The name `{name}` is defined multiple times in this scope"
584+
),
566585
Error::InvalidNumberOfArguments(expected, found) => write!(
567586
f,
568587
"Expected {expected} arguments, found {found} arguments"
@@ -634,7 +653,7 @@ impl fmt::Display for Error {
634653
Error::ArgumentTypeMismatch(name, declared, assigned) => write!(
635654
f,
636655
"Parameter `{name}` was declared with type `{declared}` but its assigned argument is of type `{assigned}`"
637-
),
656+
)
638657
}
639658
}
640659
}

0 commit comments

Comments
 (0)