From 6ca6a0eb1e11145b368e1d26435659d9377500ce Mon Sep 17 00:00:00 2001 From: Liberxue Date: Wed, 11 Sep 2024 23:01:21 +0800 Subject: [PATCH 1/7] Refactor string resugaring with visitor pattern and improved error handling * Introduce trait, allowing definition of visitors for different Term processing logics. * Create struct to wrap user-provided cons handling functions, implementing the trait. * Implement struct to handle default cons patterns, also implementing the trait. * Replace with type, better expressing success or failure semantics. * Utilize Rust's pattern matching and method to simplify error handling process. --- src/fun/transform/resugar_string.rs | 388 +++++++++++++--------------- 1 file changed, 179 insertions(+), 209 deletions(-) diff --git a/src/fun/transform/resugar_string.rs b/src/fun/transform/resugar_string.rs index 031bdf0f1..70974a769 100644 --- a/src/fun/transform/resugar_string.rs +++ b/src/fun/transform/resugar_string.rs @@ -3,238 +3,208 @@ use crate::{ maybe_grow, AdtEncoding, }; +/// Trait for visiting Term structures and extracting character and tail information. +trait TermVisitor { + fn visit<'a>(&self, term: &'a Term) -> Result<(char, &'a Term), ()>; +} + +/// Wrapper for custom cons handler functions. +struct ConsHandler(F); + +impl TermVisitor for ConsHandler +where + F: for<'a> Fn(&'a Term) -> Option<(char, &'a Term)>, +{ + fn visit<'a>(&self, term: &'a Term) -> Result<(char, &'a Term), ()> { + self.0(term).ok_or(()) + } +} +/// Default handler for cons operations. +struct DefaultConsHandler; + +impl TermVisitor for DefaultConsHandler { + fn visit<'a>(&self, term: &'a Term) -> Result<(char, &'a Term), ()> { + match term { + Term::App { tag: Tag::Static, fun, arg: tail } => { + let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() else { return Err(()) }; + let (Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = (fun.as_ref(), head.as_ref()) else { + return Err(()); + }; + if nam != builtins::SCONS { + return Err(()); + }; + let head_char = char::try_from(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + Ok((head_char, tail)) + } + _ => Err(()), + } + } +} + impl Term { /// Converts lambda-encoded strings ending with String/nil to a string literals. pub fn resugar_strings(&mut self, adt_encoding: AdtEncoding) { match adt_encoding { - AdtEncoding::Scott => self.resugar_strings_scott(), - AdtEncoding::NumScott => self.resugar_strings_num_scott(), + AdtEncoding::Scott => self.resugar_strings_with(Self::try_resugar_cons_scott, Self::build_string_scott), + AdtEncoding::NumScott => { + self.resugar_strings_with(Self::try_resugar_cons_num_scott, Self::build_string_num_scott) + } } } - /// Converts num-scott-encoded strings ending with String/nil to a string literals. - fn resugar_strings_num_scott(&mut self) { + /// Helper method to resugar strings with specific cons and build functions. + fn resugar_strings_with( + &mut self, + try_resugar_cons: fn(&mut Term) -> bool, + build_string: fn(&Term, String) -> Option, + ) { maybe_grow(|| { - // Search for a String/cons pattern in the term and try to build a string from that point on. - // If successful, replace the term with the string. - // If not, keep as-is. - - // Nil: String/nil - if let Term::Ref { nam } = self { - if nam == builtins::SNIL { - *self = Term::str(""); - } - } - // Cons: @x (x CONS_TAG ) - if let Term::Lam { tag: Tag::Static, pat, bod } = self { - if let Pattern::Var(Some(var_lam)) = pat.as_mut() { - if let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_mut() { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_mut() { - if let Term::App { tag: Tag::Static, fun, arg } = fun.as_mut() { - if let Term::Var { nam: var_app } = fun.as_mut() { - if let Term::Ref { nam: Name(nam) } = arg.as_mut() { - if let Term::Num { val: Num::U24(head) } = head.as_mut() { - if var_lam == var_app && nam == builtins::SCONS_TAG_REF { - let head = char::from_u32(*head).unwrap_or(char::REPLACEMENT_CHARACTER); - if let Some(str) = build_string_num_scott(tail, head.to_string()) { - *self = Term::str(&str); - } else { - // Not a string term, keep as-is. - } - } - } - } - } - } - } - } - } - } - // Cons: (String/cons ) - if let Term::App { tag: Tag::Static, fun, arg: tail } = self { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_mut() { - if let Term::Ref { nam } = fun.as_mut() { - if let Term::Num { val: Num::U24(head) } = head.as_mut() { - if nam == builtins::SCONS { - let head = char::from_u32(*head).unwrap_or(char::REPLACEMENT_CHARACTER); - if let Some(str) = build_string_num_scott(tail, head.to_string()) { - *self = Term::str(&str); - } else { - // Not a string term, keep as-is. - } - } - } - } + if !self.try_resugar_nil() && !try_resugar_cons(self) && !self.try_resugar_cons_common(build_string) { + for child in self.children_mut() { + child.resugar_strings_with(try_resugar_cons, build_string); } } - - for child in self.children_mut() { - child.resugar_strings_num_scott(); - } }) } - /// Converts scott-encoded strings ending with String/nil to a string literals. - fn resugar_strings_scott(&mut self) { + /// Attempts to resugar a nil term. Nil: String/nil + fn try_resugar_nil(&mut self) -> bool { + matches!(self, Term::Ref { nam } if nam == builtins::SNIL).then(|| *self = Term::str("")).is_some() + } + + /// Attempts to resugar a Scott-encoded cons term. + fn try_resugar_cons_scott(term: &mut Term) -> bool { + // Pattern matching to extract the necessary components Cons: @x (x CONS_TAG ) + let Term::Lam { tag: Tag::Static, pat: outer_pat, bod } = term else { return false }; + let Pattern::Var(None) = outer_pat.as_ref() else { return false }; + let Term::Lam { tag: Tag::Static, pat: inner_pat, bod: inner_bod } = bod.as_mut() else { return false }; + let Pattern::Var(Some(var_lam)) = inner_pat.as_ref() else { return false }; + let Term::App { tag: Tag::Static, fun, arg: tail } = inner_bod.as_mut() else { return false }; + let Term::App { tag: Tag::Static, fun: inner_fun, arg: head } = fun.as_mut() else { return false }; + let (Term::Var { nam: var_app }, Term::Num { val: Num::U24(head_val) }) = + (inner_fun.as_mut(), head.as_mut()) + else { + return false; + }; + if var_lam != var_app { + return false; + }; + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + Self::build_string_scott(tail, head_char.to_string()).map(|str| *term = Term::str(&str)).is_some() + } + + /// Attempts to resugar a NumScott-encoded cons term. + fn try_resugar_cons_num_scott(term: &mut Term) -> bool { + // Pattern matching to extract the necessary components Cons: (String/cons ) + let Term::Lam { tag: Tag::Static, pat, bod } = term else { return false }; + let Pattern::Var(Some(var_lam)) = pat.as_ref() else { return false }; + let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_mut() else { return false }; + let Term::App { tag: Tag::Static, fun: inner_fun, arg: head } = fun.as_mut() else { return false }; + let Term::App { tag: Tag::Static, fun: inner_inner_fun, arg } = inner_fun.as_mut() else { return false }; + let (Term::Var { nam: var_app }, Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = + (inner_inner_fun.as_mut(), arg.as_mut(), head.as_mut()) + else { + return false; + }; + + if var_lam != var_app || nam != builtins::SCONS_TAG_REF { + return false; + }; + + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + Self::build_string_num_scott(tail, head_char.to_string()).map(|str| *term = Term::str(&str)).is_some() + } + + /// Attempts to resugar a common cons term. + fn try_resugar_cons_common(&mut self, build_string_fn: fn(&Term, String) -> Option) -> bool { + let Term::App { tag: Tag::Static, fun, arg: tail } = self else { return false }; + let Term::App { tag: Tag::Static, fun: inner_fun, arg: head } = fun.as_mut() else { return false }; + let (Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = (inner_fun.as_ref(), head.as_ref()) + else { + return false; + }; + if nam != builtins::SCONS { + return false; + }; + + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + build_string_fn(tail, head_char.to_string()).map(|str| *self = Term::str(&str)).is_some() + } + + /// Generic string building function that uses custom and default cons handlers. + fn build_string_generic(term: &Term, mut s: String, cons_handler: F) -> Option + where + F: for<'a> Fn(&'a Term) -> Option<(char, &'a Term)>, + { maybe_grow(|| { - // Search for a String/cons pattern in the term and try to build a string from that point on. - // If successful, replace the term with the string. - // If not, keep as-is. - - // Nil: String/nil - if let Term::Ref { nam } = self { - if nam == builtins::SNIL { - *self = Term::str(""); - } - } - // Cons: @* @c (c ) - if let Term::Lam { tag: Tag::Static, pat, bod } = self { - if let Pattern::Var(None) = pat.as_mut() { - if let Term::Lam { tag: Tag::Static, pat, bod } = bod.as_mut() { - if let Pattern::Var(Some(var_lam)) = pat.as_mut() { - if let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_mut() { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_mut() { - if let Term::Var { nam: var_app } = fun.as_mut() { - if let Term::Num { val: Num::U24(head) } = head.as_mut() { - if var_lam == var_app { - let head = char::from_u32(*head).unwrap_or(char::REPLACEMENT_CHARACTER); - if let Some(str) = build_string_scott(tail, head.to_string()) { - *self = Term::str(&str); - } else { - // Not a string term, keep as-is. - } - } - } - } - } + let custom_handler = ConsHandler(cons_handler); + let default_handler = DefaultConsHandler; + let mut current = term; + loop { + match current { + // If we've reached the end of the string (nil), return the built string + Term::Ref { nam } if nam == builtins::SNIL => return Some(s), + _ => { + // Try custom handler first, then fall back to default handler + let result = custom_handler.visit(current).or_else(|_| default_handler.visit(current)); + match result { + Ok((head, tail)) => { + s.push(head); + current = tail; } + Err(_) => return None, // If both handlers fail, the term is not a valid string } } } } - // Cons: (String/cons ) - if let Term::App { tag: Tag::Static, fun, arg: tail } = self { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_mut() { - if let Term::Ref { nam } = fun.as_mut() { - if let Term::Num { val: Num::U24(head) } = head.as_mut() { - if nam == builtins::SCONS { - let head = char::from_u32(*head).unwrap_or(char::REPLACEMENT_CHARACTER); - if let Some(str) = build_string_num_scott(tail, head.to_string()) { - *self = Term::str(&str); - } else { - // Not a string term, keep as-is. - } - } - } - } - } - } - - for child in self.children_mut() { - child.resugar_strings_scott(); - } }) } -} -fn build_string_num_scott(term: &Term, mut s: String) -> Option { - maybe_grow(|| { - // Nil: String/nil - if let Term::Ref { nam } = term { - if nam == builtins::SNIL { - return Some(s); - } - } - // Cons: @x (x CONS_TAG ) - if let Term::Lam { tag: Tag::Static, pat, bod } = term { - if let Pattern::Var(Some(var_lam)) = pat.as_ref() { - if let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { - if let Term::App { tag: Tag::Static, fun, arg } = fun.as_ref() { - if let Term::Var { nam: var_app } = fun.as_ref() { - if let Term::Ref { nam } = arg.as_ref() { - if let Term::Num { val: Num::U24(head) } = head.as_ref() { - if var_lam == var_app && nam == builtins::SCONS_TAG_REF { - // New string character, append and recurse - let head = char::from_u32(*head).unwrap_or(char::REPLACEMENT_CHARACTER); - s.push(head); - return build_string_num_scott(tail, s); - } - } - } - } - } - } - } - } - } - // Cons: (String/cons ) - if let Term::App { tag: Tag::Static, fun, arg: tail } = term { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { - if let Term::Ref { nam } = fun.as_ref() { - if let Term::Num { val: Num::U24(head) } = head.as_ref() { - if nam == builtins::SCONS { - // New string character, append and recurse - let head = char::from_u32(*head).unwrap_or(char::REPLACEMENT_CHARACTER); - s.push(head); - return build_string_num_scott(tail, s); - } - } - } - } - } - // Not a string term, stop - None - }) -} + /// Builds a string from a NumScott-encoded term. + fn build_string_num_scott(term: &Term, s: String) -> Option { + Self::build_string_generic(term, s, |term| { + let Term::Lam { tag: Tag::Static, pat, bod } = term else { return None }; + let Pattern::Var(Some(var_lam)) = pat.as_ref() else { return None }; + let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() else { return None }; + let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() else { return None }; + let Term::App { tag: Tag::Static, fun, arg } = fun.as_ref() else { return None }; + let ( + Term::Var { nam: var_app }, + Term::Ref { nam: Name(ref_nam) }, + Term::Num { val: Num::U24(head_val) }, + ) = (fun.as_ref(), arg.as_ref(), head.as_ref()) + else { + return None; + }; -fn build_string_scott(term: &Term, mut s: String) -> Option { - maybe_grow(|| { - // Nil: String/nil - if let Term::Ref { nam } = term { - if nam == builtins::SNIL { - return Some(s); + if var_lam == var_app && ref_nam == builtins::SCONS_TAG_REF { + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + Some((head_char, tail)) + } else { + None } - } - // Cons: @* @c (c ) - if let Term::Lam { tag: Tag::Static, pat, bod } = term { - if let Pattern::Var(None) = pat.as_ref() { - if let Term::Lam { tag: Tag::Static, pat, bod } = bod.as_ref() { - if let Pattern::Var(Some(var_lam)) = pat.as_ref() { - if let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { - if let Term::Var { nam: var_app } = fun.as_ref() { - if let Term::Num { val: Num::U24(head) } = head.as_ref() { - if var_lam == var_app { - // New string character, append and recurse - let head = char::from_u32(*head).unwrap_or(char::REPLACEMENT_CHARACTER); - s.push(head); - return build_string_scott(tail, s); - } - } - } - } - } - } - } - } - } - // Cons: (String/cons ) - if let Term::App { tag: Tag::Static, fun, arg: tail } = term { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { - if let Term::Ref { nam } = fun.as_ref() { - if let Term::Num { val: Num::U24(head) } = head.as_ref() { - if nam == builtins::SCONS { - // New string character, append and recurse - let head = char::from_u32(*head).unwrap_or(char::REPLACEMENT_CHARACTER); - s.push(head); - return build_string_scott(tail, s); - } - } - } + }) + } + + /// Builds a string from a Scott-encoded term. + fn build_string_scott(term: &Term, s: String) -> Option { + Self::build_string_generic(term, s, |term| { + let Term::Lam { tag: Tag::Static, pat, bod } = term else { return None }; + let Pattern::Var(None) = pat.as_ref() else { return None }; + let Term::Lam { tag: Tag::Static, pat, bod } = bod.as_ref() else { return None }; + let Pattern::Var(Some(var_lam)) = pat.as_ref() else { return None }; + let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() else { return None }; + let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() else { return None }; + let (Term::Var { nam: var_app }, Term::Num { val: Num::U24(head_val) }) = (fun.as_ref(), head.as_ref()) + else { + return None; + }; + if var_lam == var_app { + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + Some((head_char, tail)) + } else { + None } - } - // Not a string term, stop - None - }) + }) + } } From e77412af95aaebce4f7012dc2af2e20bb580422d Mon Sep 17 00:00:00 2001 From: Liberxue Date: Thu, 12 Sep 2024 00:38:03 +0800 Subject: [PATCH 2/7] Refactor string resugaring remove visitor pattern keep if tree mimics the shape of the AST visualize the structure --- src/fun/transform/resugar_string.rs | 97 +++++++++++------------------ 1 file changed, 37 insertions(+), 60 deletions(-) diff --git a/src/fun/transform/resugar_string.rs b/src/fun/transform/resugar_string.rs index 70974a769..068b0a6f4 100644 --- a/src/fun/transform/resugar_string.rs +++ b/src/fun/transform/resugar_string.rs @@ -1,46 +1,8 @@ use crate::{ - fun::{builtins, Name, Num, Pattern, Tag, Term}, + fun::{builtins, Num, Pattern, Tag, Term}, maybe_grow, AdtEncoding, }; -/// Trait for visiting Term structures and extracting character and tail information. -trait TermVisitor { - fn visit<'a>(&self, term: &'a Term) -> Result<(char, &'a Term), ()>; -} - -/// Wrapper for custom cons handler functions. -struct ConsHandler(F); - -impl TermVisitor for ConsHandler -where - F: for<'a> Fn(&'a Term) -> Option<(char, &'a Term)>, -{ - fn visit<'a>(&self, term: &'a Term) -> Result<(char, &'a Term), ()> { - self.0(term).ok_or(()) - } -} -/// Default handler for cons operations. -struct DefaultConsHandler; - -impl TermVisitor for DefaultConsHandler { - fn visit<'a>(&self, term: &'a Term) -> Result<(char, &'a Term), ()> { - match term { - Term::App { tag: Tag::Static, fun, arg: tail } => { - let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() else { return Err(()) }; - let (Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = (fun.as_ref(), head.as_ref()) else { - return Err(()); - }; - if nam != builtins::SCONS { - return Err(()); - }; - let head_char = char::try_from(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); - Ok((head_char, tail)) - } - _ => Err(()), - } - } -} - impl Term { /// Converts lambda-encoded strings ending with String/nil to a string literals. pub fn resugar_strings(&mut self, adt_encoding: AdtEncoding) { @@ -86,9 +48,11 @@ impl Term { else { return false; }; + if var_lam != var_app { return false; }; + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); Self::build_string_scott(tail, head_char.to_string()).map(|str| *term = Term::str(&str)).is_some() } @@ -123,6 +87,7 @@ impl Term { else { return false; }; + if nam != builtins::SCONS { return false; }; @@ -131,28 +96,41 @@ impl Term { build_string_fn(tail, head_char.to_string()).map(|str| *self = Term::str(&str)).is_some() } - /// Generic string building function that uses custom and default cons handlers. - fn build_string_generic(term: &Term, mut s: String, cons_handler: F) -> Option + /// common string building function that uses custom and default cons handlers. + /// pattern keep if tree mimics the shape of the AST visualize the structure + fn build_string(term: &Term, mut s: String, cons_handler: F) -> Option where - F: for<'a> Fn(&'a Term) -> Option<(char, &'a Term)>, + F: Fn(&Term) -> Option<(char, &Term)>, { maybe_grow(|| { - let custom_handler = ConsHandler(cons_handler); - let default_handler = DefaultConsHandler; let mut current = term; loop { match current { - // If we've reached the end of the string (nil), return the built string Term::Ref { nam } if nam == builtins::SNIL => return Some(s), _ => { - // Try custom handler first, then fall back to default handler - let result = custom_handler.visit(current).or_else(|_| default_handler.visit(current)); - match result { - Ok((head, tail)) => { - s.push(head); - current = tail; + if let Some((head, tail)) = cons_handler(current) { + s.push(head); + current = tail; + } else if let Term::App { tag: Tag::Static, fun, arg: tail } = current { + if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { + if let (Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = + (fun.as_ref(), head.as_ref()) + { + if nam == builtins::SCONS { + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + s.push(head_char); + current = tail; + } else { + return None; + } + } else { + return None; + } + } else { + return None; } - Err(_) => return None, // If both handlers fail, the term is not a valid string + } else { + return None; } } } @@ -162,22 +140,19 @@ impl Term { /// Builds a string from a NumScott-encoded term. fn build_string_num_scott(term: &Term, s: String) -> Option { - Self::build_string_generic(term, s, |term| { + Self::build_string(term, s, |term| { let Term::Lam { tag: Tag::Static, pat, bod } = term else { return None }; let Pattern::Var(Some(var_lam)) = pat.as_ref() else { return None }; let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() else { return None }; let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() else { return None }; let Term::App { tag: Tag::Static, fun, arg } = fun.as_ref() else { return None }; - let ( - Term::Var { nam: var_app }, - Term::Ref { nam: Name(ref_nam) }, - Term::Num { val: Num::U24(head_val) }, - ) = (fun.as_ref(), arg.as_ref(), head.as_ref()) + let (Term::Var { nam: var_app }, Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = + (fun.as_ref(), arg.as_ref(), head.as_ref()) else { return None; }; - if var_lam == var_app && ref_nam == builtins::SCONS_TAG_REF { + if var_lam == var_app && nam == builtins::SCONS_TAG_REF { let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); Some((head_char, tail)) } else { @@ -188,7 +163,7 @@ impl Term { /// Builds a string from a Scott-encoded term. fn build_string_scott(term: &Term, s: String) -> Option { - Self::build_string_generic(term, s, |term| { + Self::build_string(term, s, |term| { let Term::Lam { tag: Tag::Static, pat, bod } = term else { return None }; let Pattern::Var(None) = pat.as_ref() else { return None }; let Term::Lam { tag: Tag::Static, pat, bod } = bod.as_ref() else { return None }; @@ -199,6 +174,7 @@ impl Term { else { return None; }; + if var_lam == var_app { let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); Some((head_char, tail)) @@ -208,3 +184,4 @@ impl Term { }) } } + From 4d4eabeb18a2ae49d7b42b7717a8f3d60a1b47ff Mon Sep 17 00:00:00 2001 From: Liberxue Date: Thu, 12 Sep 2024 00:51:28 +0800 Subject: [PATCH 3/7] Refactor string resugaring remove visitor pattern keep if tree mimics the shape of the AST visualize the structure --- src/fun/transform/resugar_string.rs | 75 ++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/src/fun/transform/resugar_string.rs b/src/fun/transform/resugar_string.rs index 068b0a6f4..36656a370 100644 --- a/src/fun/transform/resugar_string.rs +++ b/src/fun/transform/resugar_string.rs @@ -1,5 +1,5 @@ use crate::{ - fun::{builtins, Num, Pattern, Tag, Term}, + fun::{builtins, Name, Num, Pattern, Tag, Term}, maybe_grow, AdtEncoding, }; @@ -97,7 +97,7 @@ impl Term { } /// common string building function that uses custom and default cons handlers. - /// pattern keep if tree mimics the shape of the AST visualize the structure + /// pattern keep if tree mimics the shape of the AST visualize the structure #713 fn build_string(term: &Term, mut s: String, cons_handler: F) -> Option where F: Fn(&Term) -> Option<(char, &Term)>, @@ -105,35 +105,62 @@ impl Term { maybe_grow(|| { let mut current = term; loop { - match current { - Term::Ref { nam } if nam == builtins::SNIL => return Some(s), - _ => { - if let Some((head, tail)) = cons_handler(current) { - s.push(head); - current = tail; - } else if let Term::App { tag: Tag::Static, fun, arg: tail } = current { + // Nil: String/nil + if let Term::Ref { nam } = current { + if nam == builtins::SNIL { + return Some(s); + } + } + + // Try custom cons handler + if let Some((head, tail)) = cons_handler(current) { + s.push(head); + current = tail; + continue; + } + + // Cons: @x (x CONS_TAG ) + if let Term::Lam { tag: Tag::Static, pat, bod } = current { + if let Pattern::Var(Some(var_lam)) = pat.as_ref() { + if let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() { if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { - if let (Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = - (fun.as_ref(), head.as_ref()) - { - if nam == builtins::SCONS { - let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); - s.push(head_char); - current = tail; - } else { - return None; + if let Term::App { tag: Tag::Static, fun, arg } = fun.as_ref() { + if let Term::Var { nam: var_app } = fun.as_ref() { + if let Term::Ref { nam } = arg.as_ref() { + if let Term::Num { val: Num::U24(head_val) } = head.as_ref() { + if var_lam == var_app && nam == builtins::SCONS_TAG_REF { + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + s.push(head_char); + current = tail; + continue; + } + } + } } - } else { - return None; } - } else { - return None; } - } else { - return None; } } } + + // Cons: (String/cons ) + if let Term::App { tag: Tag::Static, fun, arg: tail } = current { + if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { + if let Term::Ref { nam } = fun.as_ref() { + if let Term::Num { val: Num::U24(head_val) } = head.as_ref() { + if nam == builtins::SCONS { + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + s.push(head_char); + current = tail; + continue; + } + } + } + } + } + + // Not a string term, stop + return None; } }) } From a09ada64f1652985b3f129d70f8f5def32acc502 Mon Sep 17 00:00:00 2001 From: Liberxue Date: Thu, 12 Sep 2024 21:49:04 +0800 Subject: [PATCH 4/7] #714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization --- src/fun/transform/resugar_list.rs | 7 +- src/fun/transform/resugar_string.rs | 170 ++++++++++++++++++++++------ 2 files changed, 137 insertions(+), 40 deletions(-) diff --git a/src/fun/transform/resugar_list.rs b/src/fun/transform/resugar_list.rs index 5cc273a26..e71aaa41f 100644 --- a/src/fun/transform/resugar_list.rs +++ b/src/fun/transform/resugar_list.rs @@ -79,7 +79,7 @@ impl Term { /// Converts scott-encoded lists ending with List/Nil to list literals. fn resugar_lists_scott(&mut self) { maybe_grow(|| { - // Search for a List/Cons pattern in the term and try to build a list from that point on. + // Searc h for a List/Cons pattern in the term and try to build a list from that point on. // If successful, replace the term with the list. // If not, keep as-is. @@ -124,7 +124,7 @@ impl Term { match l { Ok(l) => *self = Term::List { els: l.into_iter().map(|x| *x).collect() }, // Was not a list term, keep as-is. - Err(mut l) => { + Err(mut l) => { *head = l.pop().unwrap(); assert!(l.is_empty()) } @@ -241,7 +241,7 @@ fn build_list_scott(term: &mut Term, mut l: Vec>) -> Result ) if let Term::App { tag: Tag::Static, fun, arg: tail } = term { if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_mut() { @@ -266,3 +266,4 @@ fn build_list_scott(term: &mut Term, mut l: Vec>) -> Result self.resugar_strings_with(Self::try_resugar_cons_scott, Self::build_string_scott), - AdtEncoding::NumScott => { - self.resugar_strings_with(Self::try_resugar_cons_num_scott, Self::build_string_num_scott) - } + AdtEncoding::Scott => self.try_resugar_strings_with(Self::resugar_strings_scott), + AdtEncoding::NumScott => self.try_resugar_strings_with(Self::resugar_strings_num_scott), } } - /// Helper method to resugar strings with specific cons and build functions. - fn resugar_strings_with( - &mut self, - try_resugar_cons: fn(&mut Term) -> bool, - build_string: fn(&Term, String) -> Option, - ) { + /// Converts encoded strings to string literals using the provided extraction function. + /// This method recursively processes the term structure. + fn try_resugar_strings_with(&mut self, extract_fn: fn(&Term) -> Option<(char, &Term)>) { maybe_grow(|| { - if !self.try_resugar_nil() && !try_resugar_cons(self) && !self.try_resugar_cons_common(build_string) { + // Try to resugar nil or cons patterns. If unsuccessful, recurse into child terms. + if !self.try_resugar_strings_nil() && !self.try_resugar_strings_cons(extract_fn) { for child in self.children_mut() { - child.resugar_strings_with(try_resugar_cons, build_string); + child.try_resugar_strings_with(extract_fn); } } }) } - /// Attempts to resugar a nil term. Nil: String/nil - fn try_resugar_nil(&mut self) -> bool { + /// Attempts to resugar a nil term (String/nil) to an empty string literal. + fn try_resugar_strings_nil(&mut self) -> bool { matches!(self, Term::Ref { nam } if nam == builtins::SNIL).then(|| *self = Term::str("")).is_some() } +<<<<<<< HEAD /// Attempts to resugar a Scott-encoded cons term. fn try_resugar_cons_scott(term: &mut Term) -> bool { // Pattern matching to extract the necessary components Cons: @x (x CONS_TAG ) @@ -55,30 +53,25 @@ impl Term { let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); Self::build_string_scott(tail, head_char.to_string()).map(|str| *term = Term::str(&str)).is_some() +======= + /// Attempts to resugar a cons term to a string literal. + /// This method tries both the provided extraction function and the common extraction method. + fn try_resugar_strings_cons(&mut self, extract_fn: fn(&Term) -> Option<(char, &Term)>) -> bool { + self + .try_resugar_strings_cons_with(extract_fn) + .or_else(|| self.try_resugar_strings_cons_common()) + .map(|str| *self = Term::str(&str)) + .is_some() +>>>>>>> 6b0dd50b (#714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization) } - /// Attempts to resugar a NumScott-encoded cons term. - fn try_resugar_cons_num_scott(term: &mut Term) -> bool { - // Pattern matching to extract the necessary components Cons: (String/cons ) - let Term::Lam { tag: Tag::Static, pat, bod } = term else { return false }; - let Pattern::Var(Some(var_lam)) = pat.as_ref() else { return false }; - let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_mut() else { return false }; - let Term::App { tag: Tag::Static, fun: inner_fun, arg: head } = fun.as_mut() else { return false }; - let Term::App { tag: Tag::Static, fun: inner_inner_fun, arg } = inner_fun.as_mut() else { return false }; - let (Term::Var { nam: var_app }, Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = - (inner_inner_fun.as_mut(), arg.as_mut(), head.as_mut()) - else { - return false; - }; - - if var_lam != var_app || nam != builtins::SCONS_TAG_REF { - return false; - }; - - let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); - Self::build_string_num_scott(tail, head_char.to_string()).map(|str| *term = Term::str(&str)).is_some() + /// Attempts to resugar a cons term using the provided extraction function. + fn try_resugar_strings_cons_with(&self, extract_fn: fn(&Term) -> Option<(char, &Term)>) -> Option { + extract_fn(self) + .and_then(|(head_char, tail)| Self::build_strings_common(tail, head_char.to_string(), extract_fn)) } +<<<<<<< HEAD /// Attempts to resugar a common cons term. fn try_resugar_cons_common(&mut self, build_string_fn: fn(&Term, String) -> Option) -> bool { let Term::App { tag: Tag::Static, fun, arg: tail } = self else { return false }; @@ -140,6 +133,42 @@ impl Term { } } } +======= + /// Attempts to resugar a cons term using the common extraction method. + fn try_resugar_strings_cons_common(&self) -> Option { + if let Term::App { tag: Tag::Static, fun, arg: tail } = self { + if let Term::App { tag: Tag::Static, fun: inner_fun, arg: head } = fun.as_ref() { + if let (Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = + (inner_fun.as_ref(), head.as_ref()) + { + if nam == builtins::SCONS { + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + return Self::build_strings_common(tail, head_char.to_string(), Self::extract_strings_common); + } + } + } + } + None + } + + /// Builds a string from a term structure using the provided extraction function. + fn build_strings_common( + term: &Term, + mut s: String, + extract_fn: fn(&Term) -> Option<(char, &Term)>, + ) -> Option { + maybe_grow(|| { + let mut current = term; + loop { + match current { + // If we reach a nil term, we've completed the string + Term::Ref { nam } if nam == builtins::SNIL => return Some(s), + _ => { + // Extract the next character and continue building the string + let (head, next) = extract_fn(current).or_else(|| Self::extract_strings_common(current))?; + s.push(head); + current = next; +>>>>>>> 6b0dd50b (#714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization) } } @@ -165,6 +194,7 @@ impl Term { }) } +<<<<<<< HEAD /// Builds a string from a NumScott-encoded term. fn build_string_num_scott(term: &Term, s: String) -> Option { Self::build_string(term, s, |term| { @@ -184,10 +214,35 @@ impl Term { Some((head_char, tail)) } else { None +======= + /// Extracts a character and the remaining term from a Scott-encoded string term. + /// The structure of this function mimics the shape of the AST for easier visualization. + fn resugar_strings_scott(term: &Term) -> Option<(char, &Term)> { + if let Term::Lam { tag: Tag::Static, pat: outer_pat, bod } = term { + if let Pattern::Var(None) = outer_pat.as_ref() { + if let Term::Lam { tag: Tag::Static, pat: inner_pat, bod: inner_bod } = bod.as_ref() { + if let Pattern::Var(Some(var_lam)) = inner_pat.as_ref() { + if let Term::App { tag: Tag::Static, fun, arg: tail } = inner_bod.as_ref() { + if let Term::App { tag: Tag::Static, fun: inner_fun, arg: head } = fun.as_ref() { + if let (Term::Var { nam: var_app }, Term::Num { val: Num::U24(head_val) }) = + (inner_fun.as_ref(), head.as_ref()) + { + if var_lam == var_app { + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + return Some((head_char, tail)); + } + } + } + } + } + } +>>>>>>> 6b0dd50b (#714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization) } - }) + } + None } +<<<<<<< HEAD /// Builds a string from a Scott-encoded term. fn build_string_scott(term: &Term, s: String) -> Option { Self::build_string(term, s, |term| { @@ -207,8 +262,49 @@ impl Term { Some((head_char, tail)) } else { None +======= + /// Extracts a character and the remaining term from a NumScott-encoded string term. + /// The structure of this function mimics the shape of the AST for easier visualization. + fn resugar_strings_num_scott(term: &Term) -> Option<(char, &Term)> { + if let Term::Lam { tag: Tag::Static, pat, bod } = term { + if let Pattern::Var(Some(var_lam)) = pat.as_ref() { + if let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() { + if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { + if let Term::App { tag: Tag::Static, fun, arg } = fun.as_ref() { + if let ( + Term::Var { nam: var_app }, + Term::Ref { nam: Name(ref_nam) }, + Term::Num { val: Num::U24(head_val) }, + ) = (fun.as_ref(), arg.as_ref(), head.as_ref()) + { + if var_lam == var_app && ref_nam == builtins::SCONS_TAG_REF { + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + return Some((head_char, tail)); + } + } + } + } + } +>>>>>>> 6b0dd50b (#714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization) } - }) + } + None + } + + /// Extracts a character and the remaining term from a common-encoded string term. + /// The structure of this function mimics the shape of the AST for easier visualization. + fn extract_strings_common(term: &Term) -> Option<(char, &Term)> { + if let Term::App { tag: Tag::Static, fun, arg: tail } = term { + if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { + if let (Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = (fun.as_ref(), head.as_ref()) { + if nam == builtins::SCONS { + let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); + return Some((head_char, tail)); + } + } + } + } + None } } From 22e7d941bae6e6c1b25ea691fe9c4500377f534c Mon Sep 17 00:00:00 2001 From: Liberxue Date: Thu, 12 Sep 2024 22:04:53 +0800 Subject: [PATCH 5/7] #714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization --- src/fun/transform/resugar_list.rs | 6 +- src/fun/transform/resugar_string.rs | 155 ---------------------------- 2 files changed, 3 insertions(+), 158 deletions(-) diff --git a/src/fun/transform/resugar_list.rs b/src/fun/transform/resugar_list.rs index e71aaa41f..e343b4ea2 100644 --- a/src/fun/transform/resugar_list.rs +++ b/src/fun/transform/resugar_list.rs @@ -79,7 +79,7 @@ impl Term { /// Converts scott-encoded lists ending with List/Nil to list literals. fn resugar_lists_scott(&mut self) { maybe_grow(|| { - // Searc h for a List/Cons pattern in the term and try to build a list from that point on. + // Searc h for a List/Cons pattern in the term and try to build a list from that point on. // If successful, replace the term with the list. // If not, keep as-is. @@ -124,7 +124,7 @@ impl Term { match l { Ok(l) => *self = Term::List { els: l.into_iter().map(|x| *x).collect() }, // Was not a list term, keep as-is. - Err(mut l) => { + Err(mut l) => { *head = l.pop().unwrap(); assert!(l.is_empty()) } @@ -241,7 +241,7 @@ fn build_list_scott(term: &mut Term, mut l: Vec>) -> Result ) if let Term::App { tag: Tag::Static, fun, arg: tail } = term { if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_mut() { diff --git a/src/fun/transform/resugar_string.rs b/src/fun/transform/resugar_string.rs index 77dfad0f7..ec47533c9 100644 --- a/src/fun/transform/resugar_string.rs +++ b/src/fun/transform/resugar_string.rs @@ -5,7 +5,6 @@ use crate::{ impl Term { /// Converts lambda-encoded strings ending with String/nil to string literals. - /// This method chooses the appropriate resugaring function based on the ADT encoding. pub fn resugar_strings(&mut self, adt_encoding: AdtEncoding) { match adt_encoding { AdtEncoding::Scott => self.try_resugar_strings_with(Self::resugar_strings_scott), @@ -14,7 +13,6 @@ impl Term { } /// Converts encoded strings to string literals using the provided extraction function. - /// This method recursively processes the term structure. fn try_resugar_strings_with(&mut self, extract_fn: fn(&Term) -> Option<(char, &Term)>) { maybe_grow(|| { // Try to resugar nil or cons patterns. If unsuccessful, recurse into child terms. @@ -31,38 +29,13 @@ impl Term { matches!(self, Term::Ref { nam } if nam == builtins::SNIL).then(|| *self = Term::str("")).is_some() } -<<<<<<< HEAD - /// Attempts to resugar a Scott-encoded cons term. - fn try_resugar_cons_scott(term: &mut Term) -> bool { - // Pattern matching to extract the necessary components Cons: @x (x CONS_TAG ) - let Term::Lam { tag: Tag::Static, pat: outer_pat, bod } = term else { return false }; - let Pattern::Var(None) = outer_pat.as_ref() else { return false }; - let Term::Lam { tag: Tag::Static, pat: inner_pat, bod: inner_bod } = bod.as_mut() else { return false }; - let Pattern::Var(Some(var_lam)) = inner_pat.as_ref() else { return false }; - let Term::App { tag: Tag::Static, fun, arg: tail } = inner_bod.as_mut() else { return false }; - let Term::App { tag: Tag::Static, fun: inner_fun, arg: head } = fun.as_mut() else { return false }; - let (Term::Var { nam: var_app }, Term::Num { val: Num::U24(head_val) }) = - (inner_fun.as_mut(), head.as_mut()) - else { - return false; - }; - - if var_lam != var_app { - return false; - }; - - let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); - Self::build_string_scott(tail, head_char.to_string()).map(|str| *term = Term::str(&str)).is_some() -======= /// Attempts to resugar a cons term to a string literal. - /// This method tries both the provided extraction function and the common extraction method. fn try_resugar_strings_cons(&mut self, extract_fn: fn(&Term) -> Option<(char, &Term)>) -> bool { self .try_resugar_strings_cons_with(extract_fn) .or_else(|| self.try_resugar_strings_cons_common()) .map(|str| *self = Term::str(&str)) .is_some() ->>>>>>> 6b0dd50b (#714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization) } /// Attempts to resugar a cons term using the provided extraction function. @@ -71,69 +44,6 @@ impl Term { .and_then(|(head_char, tail)| Self::build_strings_common(tail, head_char.to_string(), extract_fn)) } -<<<<<<< HEAD - /// Attempts to resugar a common cons term. - fn try_resugar_cons_common(&mut self, build_string_fn: fn(&Term, String) -> Option) -> bool { - let Term::App { tag: Tag::Static, fun, arg: tail } = self else { return false }; - let Term::App { tag: Tag::Static, fun: inner_fun, arg: head } = fun.as_mut() else { return false }; - let (Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = (inner_fun.as_ref(), head.as_ref()) - else { - return false; - }; - - if nam != builtins::SCONS { - return false; - }; - - let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); - build_string_fn(tail, head_char.to_string()).map(|str| *self = Term::str(&str)).is_some() - } - - /// common string building function that uses custom and default cons handlers. - /// pattern keep if tree mimics the shape of the AST visualize the structure #713 - fn build_string(term: &Term, mut s: String, cons_handler: F) -> Option - where - F: Fn(&Term) -> Option<(char, &Term)>, - { - maybe_grow(|| { - let mut current = term; - loop { - // Nil: String/nil - if let Term::Ref { nam } = current { - if nam == builtins::SNIL { - return Some(s); - } - } - - // Try custom cons handler - if let Some((head, tail)) = cons_handler(current) { - s.push(head); - current = tail; - continue; - } - - // Cons: @x (x CONS_TAG ) - if let Term::Lam { tag: Tag::Static, pat, bod } = current { - if let Pattern::Var(Some(var_lam)) = pat.as_ref() { - if let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { - if let Term::App { tag: Tag::Static, fun, arg } = fun.as_ref() { - if let Term::Var { nam: var_app } = fun.as_ref() { - if let Term::Ref { nam } = arg.as_ref() { - if let Term::Num { val: Num::U24(head_val) } = head.as_ref() { - if var_lam == var_app && nam == builtins::SCONS_TAG_REF { - let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); - s.push(head_char); - current = tail; - continue; - } - } - } - } - } - } - } -======= /// Attempts to resugar a cons term using the common extraction method. fn try_resugar_strings_cons_common(&self) -> Option { if let Term::App { tag: Tag::Static, fun, arg: tail } = self { @@ -168,53 +78,12 @@ impl Term { let (head, next) = extract_fn(current).or_else(|| Self::extract_strings_common(current))?; s.push(head); current = next; ->>>>>>> 6b0dd50b (#714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization) } } - - // Cons: (String/cons ) - if let Term::App { tag: Tag::Static, fun, arg: tail } = current { - if let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() { - if let Term::Ref { nam } = fun.as_ref() { - if let Term::Num { val: Num::U24(head_val) } = head.as_ref() { - if nam == builtins::SCONS { - let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); - s.push(head_char); - current = tail; - continue; - } - } - } - } - } - - // Not a string term, stop - return None; } }) } -<<<<<<< HEAD - /// Builds a string from a NumScott-encoded term. - fn build_string_num_scott(term: &Term, s: String) -> Option { - Self::build_string(term, s, |term| { - let Term::Lam { tag: Tag::Static, pat, bod } = term else { return None }; - let Pattern::Var(Some(var_lam)) = pat.as_ref() else { return None }; - let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() else { return None }; - let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() else { return None }; - let Term::App { tag: Tag::Static, fun, arg } = fun.as_ref() else { return None }; - let (Term::Var { nam: var_app }, Term::Ref { nam }, Term::Num { val: Num::U24(head_val) }) = - (fun.as_ref(), arg.as_ref(), head.as_ref()) - else { - return None; - }; - - if var_lam == var_app && nam == builtins::SCONS_TAG_REF { - let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); - Some((head_char, tail)) - } else { - None -======= /// Extracts a character and the remaining term from a Scott-encoded string term. /// The structure of this function mimics the shape of the AST for easier visualization. fn resugar_strings_scott(term: &Term) -> Option<(char, &Term)> { @@ -236,33 +105,11 @@ impl Term { } } } ->>>>>>> 6b0dd50b (#714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization) } } None } -<<<<<<< HEAD - /// Builds a string from a Scott-encoded term. - fn build_string_scott(term: &Term, s: String) -> Option { - Self::build_string(term, s, |term| { - let Term::Lam { tag: Tag::Static, pat, bod } = term else { return None }; - let Pattern::Var(None) = pat.as_ref() else { return None }; - let Term::Lam { tag: Tag::Static, pat, bod } = bod.as_ref() else { return None }; - let Pattern::Var(Some(var_lam)) = pat.as_ref() else { return None }; - let Term::App { tag: Tag::Static, fun, arg: tail } = bod.as_ref() else { return None }; - let Term::App { tag: Tag::Static, fun, arg: head } = fun.as_ref() else { return None }; - let (Term::Var { nam: var_app }, Term::Num { val: Num::U24(head_val) }) = (fun.as_ref(), head.as_ref()) - else { - return None; - }; - - if var_lam == var_app { - let head_char = char::from_u32(*head_val).unwrap_or(char::REPLACEMENT_CHARACTER); - Some((head_char, tail)) - } else { - None -======= /// Extracts a character and the remaining term from a NumScott-encoded string term. /// The structure of this function mimics the shape of the AST for easier visualization. fn resugar_strings_num_scott(term: &Term) -> Option<(char, &Term)> { @@ -285,7 +132,6 @@ impl Term { } } } ->>>>>>> 6b0dd50b (#714Refactor Transform String Resugar Term Scott && keep function mimics the shape of the AST for easier visualization) } } None @@ -307,4 +153,3 @@ impl Term { None } } - From 411c658a640a949f1d532fbda614373343a374d9 Mon Sep 17 00:00:00 2001 From: Liber <5831248+Liberxue@users.noreply.github.com> Date: Tue, 17 Sep 2024 21:16:34 +0800 Subject: [PATCH 6/7] Update src/fun/transform/resugar_list.rs && fix comments Co-authored-by: Nicolas Abril --- src/fun/transform/resugar_list.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fun/transform/resugar_list.rs b/src/fun/transform/resugar_list.rs index e343b4ea2..b33d41395 100644 --- a/src/fun/transform/resugar_list.rs +++ b/src/fun/transform/resugar_list.rs @@ -79,7 +79,7 @@ impl Term { /// Converts scott-encoded lists ending with List/Nil to list literals. fn resugar_lists_scott(&mut self) { maybe_grow(|| { - // Searc h for a List/Cons pattern in the term and try to build a list from that point on. + // Search for a List/Cons pattern in the term and try to build a list from that point on. // If successful, replace the term with the list. // If not, keep as-is. From f680237093609c1dd12c528964d46f70a325f61e Mon Sep 17 00:00:00 2001 From: liber Date: Tue, 17 Sep 2024 22:12:54 +0800 Subject: [PATCH 7/7] Refactor string resugaring remove visitor pattern keep if tree mimics the shape of the AST visualize the structure && cargo fmt --- src/fun/transform/resugar_list.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fun/transform/resugar_list.rs b/src/fun/transform/resugar_list.rs index b33d41395..5cc273a26 100644 --- a/src/fun/transform/resugar_list.rs +++ b/src/fun/transform/resugar_list.rs @@ -266,4 +266,3 @@ fn build_list_scott(term: &mut Term, mut l: Vec>) -> Result