From 79c9719180cc7410e9458fcc1e8a657daf4c84f3 Mon Sep 17 00:00:00 2001 From: JR Lynn Date: Wed, 11 Mar 2026 11:05:21 +1100 Subject: [PATCH 1/2] Rename domain and range of a procedure signature --- src/formatting/formatter.rs | 16 ++++++------- src/language/types.rs | 4 ++-- src/parsing/checks/parser.rs | 32 ++++++++++++------------- src/parsing/checks/verify.rs | 40 +++++++++++++++---------------- src/parsing/parser.rs | 13 +++++++---- src/problem/messages.rs | 44 +++++++++++++++++------------------ tests/formatting/formatter.rs | 16 ++++++------- 7 files changed, 84 insertions(+), 81 deletions(-) diff --git a/src/formatting/formatter.rs b/src/formatting/formatter.rs index 9d572b48..21ca0803 100644 --- a/src/formatting/formatter.rs +++ b/src/formatting/formatter.rs @@ -536,11 +536,11 @@ impl<'i> Formatter<'i> { } pub fn append_signature(&mut self, signature: &'i Signature) { - self.append_genus(&signature.domain); + self.append_genus(&signature.requires); self.add_fragment_reference(Syntax::Neutral, " "); self.add_fragment_reference(Syntax::Structure, "->"); self.add_fragment_reference(Syntax::Neutral, " "); - self.append_genus(&signature.range); + self.append_genus(&signature.provides); } pub fn append_genus(&mut self, genus: &'i Genus) { @@ -1376,22 +1376,22 @@ mod check { let mut output = Formatter::new(78); output.append_signature(&Signature { - domain: Genus::Single(Forma("Alderaan")), - range: Genus::Single(Forma("AsteroidField")), + requires: Genus::Single(Forma("Alderaan")), + provides: Genus::Single(Forma("AsteroidField")), }); assert_eq!(output.to_string(), "Alderaan -> AsteroidField"); output.reset(); output.append_signature(&Signature { - domain: Genus::List(Forma("Clone")), - range: Genus::Single(Forma("Army")), + requires: Genus::List(Forma("Clone")), + provides: Genus::Single(Forma("Army")), }); assert_eq!(output.to_string(), "[Clone] -> Army"); output.reset(); let signature = Signature { - domain: Genus::Single(Forma("TaxationOfTradeRoutes")), - range: Genus::Tuple(vec![Forma("Rebels"), Forma("Empire")]), + requires: Genus::Single(Forma("TaxationOfTradeRoutes")), + provides: Genus::Tuple(vec![Forma("Rebels"), Forma("Empire")]), }; output.append_signature(&signature); assert_eq!( diff --git a/src/language/types.rs b/src/language/types.rs index 7e43d295..5d9cd773 100644 --- a/src/language/types.rs +++ b/src/language/types.rs @@ -87,8 +87,8 @@ pub enum Genus<'i> { #[derive(Eq, Debug, PartialEq)] pub struct Signature<'i> { - pub domain: Genus<'i>, - pub range: Genus<'i>, + pub requires: Genus<'i>, + pub provides: Genus<'i>, } // now types for procedure bodies diff --git a/src/parsing/checks/parser.rs b/src/parsing/checks/parser.rs index 1a4253f4..a29348d0 100644 --- a/src/parsing/checks/parser.rs +++ b/src/parsing/checks/parser.rs @@ -159,8 +159,8 @@ fn signatures() { assert_eq!( result, Ok(Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")) + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")) }) ); @@ -169,8 +169,8 @@ fn signatures() { assert_eq!( result, Ok(Signature { - domain: Genus::Single(Forma("Beans")), - range: Genus::Single(Forma("Coffee")) + requires: Genus::Single(Forma("Beans")), + provides: Genus::Single(Forma("Coffee")) }) ); @@ -179,8 +179,8 @@ fn signatures() { assert_eq!( result, Ok(Signature { - domain: Genus::List(Forma("Bits")), - range: Genus::Single(Forma("Bob")) + requires: Genus::List(Forma("Bits")), + provides: Genus::Single(Forma("Bob")) }) ); @@ -189,8 +189,8 @@ fn signatures() { assert_eq!( result, Ok(Signature { - domain: Genus::Single(Forma("Complex")), - range: Genus::Tuple(vec![Forma("Real"), Forma("Imaginary")]) + requires: Genus::Single(Forma("Complex")), + provides: Genus::Tuple(vec![Forma("Real"), Forma("Imaginary")]) }) ); } @@ -219,8 +219,8 @@ fn declaration_full() { Identifier("f"), None, Some(Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")) + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")) }) )) ); @@ -235,8 +235,8 @@ fn declaration_full() { Identifier("making_coffee"), None, Some(Signature { - domain: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), - range: Genus::List(Forma("Coffee")) + requires: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), + provides: Genus::List(Forma("Coffee")) }) )) ); @@ -292,8 +292,8 @@ making_coffee : Identifier("making_coffee"), None, Some(Signature { - domain: Genus::Single(Forma("Ingredients")), - range: Genus::Single(Forma("Coffee")) + requires: Genus::Single(Forma("Ingredients")), + provides: Genus::Single(Forma("Coffee")) }) )) ); @@ -315,8 +315,8 @@ making_coffee(b, m) : Identifier("making_coffee"), Some(vec![Identifier("b"), Identifier("m")]), Some(Signature { - domain: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), - range: Genus::Single(Forma("Coffee")) + requires: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), + provides: Genus::Single(Forma("Coffee")) }) )) ); diff --git a/src/parsing/checks/verify.rs b/src/parsing/checks/verify.rs index dc5ebfa8..ddc1f5c1 100644 --- a/src/parsing/checks/verify.rs +++ b/src/parsing/checks/verify.rs @@ -61,8 +61,8 @@ making_coffee : (Beans, Milk) -> Coffee name: Identifier("making_coffee"), parameters: None, signature: Some(Signature { - domain: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), - range: Genus::Single(Forma("Coffee")) + requires: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), + provides: Genus::Single(Forma("Coffee")) }), elements: vec![], }) @@ -88,8 +88,8 @@ second : C -> D name: Identifier("first"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")) + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")) }), elements: vec![], }) @@ -102,8 +102,8 @@ second : C -> D name: Identifier("second"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("C")), - range: Genus::Single(Forma("D")) + requires: Genus::Single(Forma("C")), + provides: Genus::Single(Forma("D")) }), elements: vec![], }) @@ -127,8 +127,8 @@ making_coffee(e) : Ingredients -> Coffee name: Identifier("making_coffee"), parameters: Some(vec![Identifier("e")]), signature: Some(Signature { - domain: Genus::Single(Forma("Ingredients")), - range: Genus::Single(Forma("Coffee")) + requires: Genus::Single(Forma("Ingredients")), + provides: Genus::Single(Forma("Coffee")) }), elements: vec![], }) @@ -159,8 +159,8 @@ This is the first one. name: Identifier("first"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")) + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")) }), elements: vec![ Element::Title("The First"), @@ -214,8 +214,8 @@ This is the first one. name: Identifier("first"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")) + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")) }), elements: vec![ Element::Title("The First"), @@ -280,8 +280,8 @@ This is the first one. name: Identifier("first"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")) + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")) }), elements: vec![ Element::Title("The First"), @@ -1287,8 +1287,8 @@ III. Implementation name: Identifier("requirements_and_architecture"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("Concept")), - range: Genus::Naked(vec![ + requires: Genus::Single(Forma("Concept")), + provides: Genus::Naked(vec![ Forma("Requirements"), Forma("Architecture") ]), @@ -1332,8 +1332,8 @@ III. Implementation name: Identifier("define_requirements"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("Concept")), - range: Genus::Single(Forma("Requirements")), + requires: Genus::Single(Forma("Concept")), + provides: Genus::Single(Forma("Requirements")), }), elements: vec![], }, @@ -1341,8 +1341,8 @@ III. Implementation name: Identifier("determine_architecture"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("Concept")), - range: Genus::Single(Forma("Architecture")), + requires: Genus::Single(Forma("Concept")), + provides: Genus::Single(Forma("Architecture")), }), elements: vec![], }, diff --git a/src/parsing/parser.rs b/src/parsing/parser.rs index f526b3f2..692d8bad 100644 --- a/src/parsing/parser.rs +++ b/src/parsing/parser.rs @@ -857,7 +857,7 @@ impl<'i> Parser<'i> { .ok_or(ParsingError::Expected( self.offset, 0, - "a Genus for the domain", + "a Genus for the requires", ))?; let two = cap @@ -865,19 +865,22 @@ impl<'i> Parser<'i> { .ok_or(ParsingError::Expected( self.offset, 0, - "a Genus for the range", + "a Genus for the provides", ))?; - let domain = validate_genus(one.as_str()).ok_or(ParsingError::InvalidGenus( + let requires = validate_genus(one.as_str()).ok_or(ParsingError::InvalidGenus( self.offset + one.start(), one.len(), ))?; - let range = validate_genus(two.as_str()).ok_or(ParsingError::InvalidGenus( + let provides = validate_genus(two.as_str()).ok_or(ParsingError::InvalidGenus( self.offset + two.start(), two.len(), ))?; - Ok(Signature { domain, range }) + Ok(Signature { + requires, + provides, + }) } fn parse_procedure_declaration( diff --git a/src/problem/messages.rs b/src/problem/messages.rs index 09a1ac4d..7bb30142 100644 --- a/src/problem/messages.rs +++ b/src/problem/messages.rs @@ -237,16 +237,16 @@ doesn't have an input or result, per se. ParsingError::InvalidSignature(_, _) => { let examples = vec![ Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")), + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")), }, Signature { - domain: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), - range: Genus::Single(Forma("Coffee")), + requires: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), + provides: Genus::Single(Forma("Coffee")), }, Signature { - domain: Genus::List(Forma("FunctionalRequirement")), - range: Genus::Single(Forma("Architecture")), + requires: Genus::List(Forma("FunctionalRequirement")), + provides: Genus::Single(Forma("Architecture")), }, ]; @@ -254,8 +254,8 @@ doesn't have an input or result, per se. "Invalid signature".to_string(), format!( r#" -Procedure signatures follow the pattern domain -> range, where domain and -range are genus. Some examples: +Procedure signatures follow the pattern requires -> provides, where requires +and provides are genus. Some examples: {} {} @@ -296,8 +296,8 @@ this form. name: Identifier("f"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")), + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")), }), elements: Vec::new(), }, @@ -305,8 +305,8 @@ this form. name: Identifier("implementation"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("Design")), - range: Genus::Single(Forma("Product")), + requires: Genus::Single(Forma("Design")), + provides: Genus::Single(Forma("Product")), }), elements: Vec::new(), }, @@ -314,8 +314,8 @@ this form. name: Identifier("make_coffee"), parameters: None, signature: Some(Signature { - domain: Genus::Naked(vec![Forma("Beans"), Forma("Milk")]), - range: Genus::Single(Forma("Coffee")), + requires: Genus::Naked(vec![Forma("Beans"), Forma("Milk")]), + provides: Genus::Single(Forma("Coffee")), }), elements: Vec::new(), }, @@ -323,8 +323,8 @@ this form. name: Identifier("make_coffee"), parameters: None, signature: Some(Signature { - domain: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), - range: Genus::Single(Forma("Coffee")), + requires: Genus::Tuple(vec![Forma("Beans"), Forma("Milk")]), + provides: Genus::Single(Forma("Coffee")), }), elements: Vec::new(), }, @@ -332,8 +332,8 @@ this form. name: Identifier("make_coffee"), parameters: Some(vec![Identifier("b"), Identifier("m")]), signature: Some(Signature { - domain: Genus::Naked(vec![Forma("Beans"), Forma("Milk")]), - range: Genus::Single(Forma("Coffee")), + requires: Genus::Naked(vec![Forma("Beans"), Forma("Milk")]), + provides: Genus::Single(Forma("Coffee")), }), elements: Vec::new(), }, @@ -392,8 +392,8 @@ Finally, variables can be assigned for the names of the input parameters: name: Identifier("lawsuit"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("Council")), - range: Genus::List(Forma("Penny")), + requires: Genus::Single(Forma("Council")), + provides: Genus::List(Forma("Penny")), }), elements: Vec::new(), }, @@ -401,8 +401,8 @@ Finally, variables can be assigned for the names of the input parameters: name: Identifier("lawsuit"), parameters: Some(vec![Identifier("c")]), signature: Some(Signature { - domain: Genus::Single(Forma("Council")), - range: Genus::List(Forma("Penny")), + requires: Genus::Single(Forma("Council")), + provides: Genus::List(Forma("Penny")), }), elements: Vec::new(), }, diff --git a/tests/formatting/formatter.rs b/tests/formatting/formatter.rs index c4f26a58..59a8fc28 100644 --- a/tests/formatting/formatter.rs +++ b/tests/formatting/formatter.rs @@ -47,8 +47,8 @@ mod verify { name: Identifier("first"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")), + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")), }), elements: vec![], }])), @@ -76,8 +76,8 @@ first : A -> B name: Identifier("first"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("A")), - range: Genus::Single(Forma("B")), + requires: Genus::Single(Forma("A")), + provides: Genus::Single(Forma("B")), }), elements: vec![], }, @@ -85,8 +85,8 @@ first : A -> B name: Identifier("second"), parameters: None, signature: Some(Signature { - domain: Genus::List(Forma("Thing")), - range: Genus::Tuple(vec![Forma("Who"), Forma("Where"), Forma("Why")]), + requires: Genus::List(Forma("Thing")), + provides: Genus::Tuple(vec![Forma("Who"), Forma("Where"), Forma("Why")]), }), elements: vec![], }, @@ -117,8 +117,8 @@ second : [Thing] -> (Who, Where, Why) name: Identifier("win_le_tour"), parameters: None, signature: Some(Signature { - domain: Genus::Single(Forma("Bicycle")), - range: Genus::Single(Forma("YellowJersey")), + requires: Genus::Single(Forma("Bicycle")), + provides: Genus::Single(Forma("YellowJersey")), }), elements: vec![Element::Steps(vec![ Scope::DependentBlock { From 3d184ea40e4495099619724e4e8ee796b1454699 Mon Sep 17 00:00:00 2001 From: Andrew Cowie Date: Wed, 11 Mar 2026 11:17:26 +1100 Subject: [PATCH 2/2] Rename template line to become domain line --- src/formatting/formatter.rs | 4 ++-- src/language/types.rs | 22 +++++++++++----------- src/parsing/checks/parser.rs | 10 +++++----- src/parsing/checks/verify.rs | 4 ++-- src/parsing/parser.rs | 21 +++++++++------------ src/problem/messages.rs | 6 +++--- tests/formatting/formatter.rs | 4 ++-- 7 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/formatting/formatter.rs b/src/formatting/formatter.rs index 21ca0803..2e0f05f8 100644 --- a/src/formatting/formatter.rs +++ b/src/formatting/formatter.rs @@ -434,9 +434,9 @@ impl<'i> Formatter<'i> { self.append_char('\n'); } - if let Some(template) = metadata.template { + if let Some(domain) = metadata.domain { self.append_str("& "); - self.append_str(template); + self.append_str(domain); self.append_char('\n'); } self.reset_syntax(); diff --git a/src/language/types.rs b/src/language/types.rs index 5d9cd773..4f3e5896 100644 --- a/src/language/types.rs +++ b/src/language/types.rs @@ -13,7 +13,7 @@ pub struct Metadata<'i> { pub version: u8, pub license: Option<&'i str>, pub copyright: Option<&'i str>, - pub template: Option<&'i str>, + pub domain: Option<&'i str>, } impl Default for Metadata<'_> { @@ -22,7 +22,7 @@ impl Default for Metadata<'_> { version: 1, license: None, copyright: None, - template: None, + domain: None, } } } @@ -234,7 +234,7 @@ pub(crate) fn validate_copyright(input: &str) -> Option<&str> { } } -pub(crate) fn validate_template(input: &str) -> Option<&str> { +pub(crate) fn validate_domain(input: &str) -> Option<&str> { let re = regex!(r"^[A-Za-z0-9.,\-]+$"); if re.is_match(input) { @@ -538,10 +538,10 @@ mod check { } #[test] - fn template_rules() { - assert_eq!(validate_template("checklist"), Some("checklist")); - assert_eq!(validate_template("checklist,v1"), Some("checklist,v1")); - assert_eq!(validate_template("checklist-v1.0"), Some("checklist-v1.0")); + fn domain_rules() { + assert_eq!(validate_domain("checklist"), Some("checklist")); + assert_eq!(validate_domain("checklist,v1"), Some("checklist,v1")); + assert_eq!(validate_domain("checklist-v1.0"), Some("checklist-v1.0")); } fn maker<'i>() -> Metadata<'i> { @@ -549,7 +549,7 @@ mod check { version: 1, license: None, copyright: None, - template: None, + domain: None, }; t1 @@ -561,7 +561,7 @@ mod check { version: 1, license: None, copyright: None, - template: None, + domain: None, }; assert_eq!(Metadata::default(), t1); @@ -570,7 +570,7 @@ mod check { version: 1, license: Some("MIT"), copyright: Some("ACME, Inc"), - template: Some("checklist"), + domain: Some("checklist"), }; let t3 = maker(); @@ -580,7 +580,7 @@ mod check { let t4 = Metadata { license: Some("MIT"), copyright: Some("ACME, Inc"), - template: Some("checklist"), + domain: Some("checklist"), ..t3 }; diff --git a/src/parsing/checks/parser.rs b/src/parsing/checks/parser.rs index a29348d0..c16ba147 100644 --- a/src/parsing/checks/parser.rs +++ b/src/parsing/checks/parser.rs @@ -87,18 +87,18 @@ fn header_spdx() { } #[test] -fn header_template() { +fn header_domain() { let mut input = Parser::new(); input.initialize("& checklist"); - assert!(is_template_line(input.source)); + assert!(is_domain_line(input.source)); - let result = input.read_template_line(); + let result = input.read_domain_line(); assert_eq!(result, Ok(Some("checklist"))); input.initialize("& nasa-flight-plan,v4.0"); - assert!(is_template_line(input.source)); + assert!(is_domain_line(input.source)); - let result = input.read_template_line(); + let result = input.read_domain_line(); assert_eq!(result, Ok(Some("nasa-flight-plan,v4.0"))); } diff --git a/src/parsing/checks/verify.rs b/src/parsing/checks/verify.rs index ddc1f5c1..ea1c230a 100644 --- a/src/parsing/checks/verify.rs +++ b/src/parsing/checks/verify.rs @@ -20,7 +20,7 @@ fn technique_header() { version: 1, license: None, copyright: None, - template: None + domain: None }) ); @@ -39,7 +39,7 @@ fn technique_header() { version: 1, license: Some("MIT"), copyright: Some("ACME, Inc"), - template: Some("checklist") + domain: Some("checklist") }) ); } diff --git a/src/parsing/parser.rs b/src/parsing/parser.rs index 692d8bad..fe8ae1ba 100644 --- a/src/parsing/parser.rs +++ b/src/parsing/parser.rs @@ -784,7 +784,7 @@ impl<'i> Parser<'i> { }) } - fn read_template_line(&mut self) -> Result, ParsingError> { + fn read_domain_line(&mut self) -> Result, ParsingError> { self.take_until(&['\n'], |inner| { let re = regex!(r"^&\s*(.+)$"); @@ -794,9 +794,9 @@ impl<'i> Parser<'i> { let one = cap .get(1) - .ok_or(ParsingError::Expected(inner.offset, 0, "a template name"))?; + .ok_or(ParsingError::Expected(inner.offset, 0, "a domain name"))?; - let result = validate_template(one.as_str()) + let result = validate_domain(one.as_str()) .ok_or(ParsingError::InvalidHeader(inner.offset, 0))?; Ok(Some(result)) }) @@ -821,9 +821,9 @@ impl<'i> Parser<'i> { (None, None) }; - // Process template line - let template = if is_template_line(self.source) { - let result = self.read_template_line()?; + // Process domain line + let domain = if is_domain_line(self.source) { + let result = self.read_domain_line()?; self.require_newline()?; result } else { @@ -834,7 +834,7 @@ impl<'i> Parser<'i> { version, license, copyright, - template, + domain, }) } @@ -877,10 +877,7 @@ impl<'i> Parser<'i> { two.len(), ))?; - Ok(Signature { - requires, - provides, - }) + Ok(Signature { requires, provides }) } fn parse_procedure_declaration( @@ -2635,7 +2632,7 @@ fn is_spdx_line(content: &str) -> bool { .starts_with('!') } -fn is_template_line(content: &str) -> bool { +fn is_domain_line(content: &str) -> bool { content .trim_ascii_start() .starts_with('&') diff --git a/src/problem/messages.rs b/src/problem/messages.rs index 7bb30142..68b9bd7a 100644 --- a/src/problem/messages.rs +++ b/src/problem/messages.rs @@ -101,9 +101,9 @@ the license statement, separated from it by a semicolon. Copyright statements typically list the year and then the name of the person or entity holding the copyright. -The third line optionally specifies the template to be used when rendering the -Technique. Common templates include {}, {}, and -{}. +The third line optionally specifies the domain or kind of Technique this is, +to be used when rendering the Technique. Common templates include +{}, {}, and {}. "#, formatted_example, renderer.style(crate::formatting::Syntax::Header, "MIT"), diff --git a/tests/formatting/formatter.rs b/tests/formatting/formatter.rs index 59a8fc28..0e61c7c2 100644 --- a/tests/formatting/formatter.rs +++ b/tests/formatting/formatter.rs @@ -24,7 +24,7 @@ mod verify { version: 1, license: Some("MIT"), copyright: None, - template: Some("checklist"), + domain: Some("checklist"), }), body: None, }; @@ -69,7 +69,7 @@ first : A -> B version: 1, license: Some("PD"), copyright: Some("2025 The First Procedure Society, Inc"), - template: None, + domain: None, }), body: Some(Technique::Procedures(vec![ Procedure {