diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ccfde5d..64bc0a5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# Unreleased + +* Remove ModuleProgram and the parsing of Arguments and Witnesses from the core compiler [#323](https://github.com/BlockstreamResearch/SimplicityHL/pull/323) + # 0.6.0-rc.0 - 2026-04-24 * Add imports and dependency resolution, including `pub`/`use` syntax, re-exports, aliases, transitive dependencies, collision diagnostics, functional tests, examples, and `simc --dep` for compiling multi-file programs. [#264](https://github.com/BlockstreamResearch/SimplicityHL/pull/264) diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index da5a9941..c4bea838 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -55,13 +55,6 @@ test = false doc = false bench = false -[[bin]] -name = "parse_witness_module_rtt" -path = "fuzz_targets/parse_witness_module_rtt.rs" -test = false -doc = false -bench = false - [[bin]] name = "reconstruct_value" path = "fuzz_targets/reconstruct_value.rs" diff --git a/fuzz/fuzz_targets/parse_witness_json_rtt.rs b/fuzz/fuzz_targets/parse_witness_json_rtt.rs index ee9ceeec..ddb9e6b3 100644 --- a/fuzz/fuzz_targets/parse_witness_json_rtt.rs +++ b/fuzz/fuzz_targets/parse_witness_json_rtt.rs @@ -17,20 +17,3 @@ fn main() {} #[cfg(fuzzing)] libfuzzer_sys::fuzz_target!(|data: simplicityhl::WitnessValues| do_test(data)); - -#[cfg(test)] -mod test { - use simplicityhl::{parse::ParseFromStr, WitnessValues}; - #[test] - fn test() { - let witness_text = r#"mod witness { - const A: u32 = 1; - const B: u32 = 2; - const C: u32 = 3; - }"#; - - let witness_values = WitnessValues::parse_from_str(witness_text) - .expect("parsing of valid string should work"); - super::do_test(witness_values); - } -} diff --git a/fuzz/fuzz_targets/parse_witness_module_rtt.rs b/fuzz/fuzz_targets/parse_witness_module_rtt.rs deleted file mode 100644 index 2b6e5201..00000000 --- a/fuzz/fuzz_targets/parse_witness_module_rtt.rs +++ /dev/null @@ -1,38 +0,0 @@ -#![cfg_attr(fuzzing, no_main)] - -#[cfg(any(fuzzing, test))] -fn do_test(witness_values: simplicityhl::WitnessValues) { - use simplicityhl::parse::ParseFromStr; - use simplicityhl::WitnessValues; - - let witness_text = witness_values.to_string(); - let parsed_witness_text = - WitnessValues::parse_from_str(&witness_text).expect("Witness module should be parseable"); - assert_eq!( - witness_values, parsed_witness_text, - "Witness module should parse to original witness values" - ); -} - -#[cfg(not(fuzzing))] -fn main() {} - -#[cfg(fuzzing)] -libfuzzer_sys::fuzz_target!(|data: simplicityhl::WitnessValues| do_test(data)); - -#[cfg(test)] -mod test { - use simplicityhl::{parse::ParseFromStr, WitnessValues}; - #[test] - fn test() { - let witness_text = r#"mod witness { - const A: u32 = 1; - const B: u32 = 2; - const C: u32 = 3; - }"#; - - let witness_values = WitnessValues::parse_from_str(witness_text) - .expect("parsing of valid string should work"); - super::do_test(witness_values); - } -} diff --git a/justfile b/justfile index 6086ec49..a24d033a 100644 --- a/justfile +++ b/justfile @@ -38,7 +38,6 @@ check_fuzz: just fuzz display_parse_tree just fuzz parse_value_rtt just fuzz parse_witness_json_rtt - just fuzz parse_witness_module_rtt just fuzz reconstruct_value # Build fuzz tests diff --git a/src/ast.rs b/src/ast.rs index 0ab29779..3a839360 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -19,7 +19,7 @@ use crate::types::{ AliasedType, ResolvedType, StructuralType, TypeConstructible, TypeDeconstructible, UIntType, }; use crate::value::{UIntValue, Value}; -use crate::witness::{Parameters, WitnessTypes, WitnessValues}; +use crate::witness::{Parameters, WitnessTypes}; use crate::{driver, impl_eq_hash, parse}; /// A program consists of the main function. @@ -1568,72 +1568,6 @@ impl AbstractSyntaxTree for Match { } } -fn analyze_named_module( - name: ModuleName, - from: &parse::ModuleProgram, -) -> Result, RichError> { - let unit = ResolvedType::unit(); - - // IMPORTANT! If modules allow imports, then we need to consider - // passing the resolution conetxt by calling `Scope::new(resolutions)` - let mut scope = Scope::default(); - let items = from - .items() - .iter() - .map(|s| ModuleItem::analyze(s, &unit, &mut scope)) - .collect::, RichError>>()?; - debug_assert!(scope.is_topmost()); - let mut iter = items.into_iter().filter_map(|item| match item { - ModuleItem::Module(module) if module.name == name => Some(module), - _ => None, - }); - let Some(witness_module) = iter.next() else { - return Ok(HashMap::new()); // "not present" is equivalent to empty - }; - if iter.next().is_some() { - return Err(Error::ModuleRedefined(name)).with_span(from); - } - let mut map = HashMap::new(); - for assignment in witness_module.assignments() { - if map.contains_key(assignment.name()) { - return Err(Error::WitnessReassigned(assignment.name().shallow_clone())) - .with_span(assignment); - } - map.insert( - assignment.name().shallow_clone(), - assignment.value().clone(), - ); - } - Ok(map) -} - -impl WitnessValues { - pub fn analyze(from: &parse::ModuleProgram) -> Result { - analyze_named_module(ModuleName::witness(), from).map(Self::from) - } -} - -impl crate::witness::Arguments { - pub fn analyze(from: &parse::ModuleProgram) -> Result { - analyze_named_module(ModuleName::param(), from).map(Self::from) - } -} - -impl AbstractSyntaxTree for ModuleItem { - type From = parse::ModuleItem; - - fn analyze(from: &Self::From, ty: &ResolvedType, scope: &mut Scope) -> Result { - assert!(ty.is_unit(), "Items cannot return anything"); - assert!(scope.is_topmost(), "Items live in the topmost scope only"); - match from { - parse::ModuleItem::Ignored => Ok(Self::Ignored), - parse::ModuleItem::Module(witness_module) => { - Module::analyze(witness_module, ty, scope).map(Self::Module) - } - } - } -} - impl AbstractSyntaxTree for Module { type From = parse::Module; diff --git a/src/parse.rs b/src/parse.rs index cff32f5f..c391eaf7 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -617,34 +617,6 @@ impl MatchPattern { } } -/// Program root when parsing modules. -#[derive(Clone, Debug)] -pub struct ModuleProgram { - items: Arc<[ModuleItem]>, - span: Span, -} - -impl ModuleProgram { - /// Access the items of the program. - pub fn items(&self) -> &[ModuleItem] { - &self.items - } - - /// Access the span of the program. - pub fn span(&self) -> &Span { - &self.span - } -} - -impl_eq_hash!(ModuleProgram; items); - -/// Item when parsing modules. -#[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub enum ModuleItem { - Ignored, - Module(Module), -} - #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct Module { name: ModuleName, @@ -2091,32 +2063,6 @@ impl Match { } } -impl ChumskyParse for ModuleItem { - fn parser<'tokens, 'src: 'tokens, I>() -> impl Parser<'tokens, I, Self, ParseError<'src>> + Clone - where - I: ValueInput<'tokens, Token = Token<'src>, Span = Span>, - { - let module = Module::parser().map(Self::Module); - - module - } -} - -impl ChumskyParse for ModuleProgram { - fn parser<'tokens, 'src: 'tokens, I>() -> impl Parser<'tokens, I, Self, ParseError<'src>> + Clone - where - I: ValueInput<'tokens, Token = Token<'src>, Span = Span>, - { - ModuleItem::parser() - .repeated() - .collect::>() - .map_with(|items, e| Self { - items: Arc::from(items), - span: e.span(), - }) - } -} - impl ChumskyParse for Module { fn parser<'tokens, 'src: 'tokens, I>() -> impl Parser<'tokens, I, Self, ParseError<'src>> + Clone where @@ -2227,12 +2173,6 @@ impl AsRef for Match { } } -impl AsRef for ModuleProgram { - fn as_ref(&self) -> &Span { - &self.span - } -} - impl AsRef for Module { fn as_ref(&self) -> &Span { &self.span diff --git a/src/witness.rs b/src/witness.rs index a5e1d553..3d02f460 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -3,7 +3,6 @@ use std::fmt; use std::sync::Arc; use crate::error::{Error, RichError, WithContent, WithSpan}; -use crate::parse; use crate::parse::ParseFromStr; use crate::str::WitnessName; use crate::types::{AliasedType, ResolvedType}; @@ -67,12 +66,6 @@ macro_rules! impl_name_value_map { } } - impl ParseFromStr for $wrapper { - fn parse_from_str(s: &str) -> Result { - parse::ModuleProgram::parse_from_str(s).and_then(|x| Self::analyze(&x)) - } - } - impl fmt::Display for $wrapper { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use itertools::Itertools; @@ -284,28 +277,6 @@ fn main() { } } - #[test] - fn missing_witness_module() { - match WitnessValues::parse_from_str("") { - Ok(v) => assert!( - v.iter().next().is_none(), - "empty witness module was parsed as nonempty" - ), - Err(error) => panic!("Missing witness module was falsely rejected: {error}"), - } - } - - #[test] - fn redefined_witness_module() { - let s = r#"mod witness {} mod witness {}"#; - match WitnessValues::parse_from_str(s) { - Ok(_) => panic!("Redefined witness module was falsely accepted"), - Err(error) => assert!(error - .to_string() - .contains("Module `witness` is defined twice")), - } - } - #[test] fn witness_to_string() { let witness = WitnessValues::from(HashMap::from([