[sc-688] Add string resugaring of readback term

This commit is contained in:
Nicolas Abril 2024-05-15 18:35:30 +02:00
parent a763052c11
commit 2f7ae6c276
17 changed files with 143 additions and 15 deletions

View File

@ -85,6 +85,7 @@
"scopeless",
"scrutinee",
"snil",
"SOTA",
"stdext",
"struct",
"subcmd",

View File

@ -16,4 +16,5 @@ pub mod float_combinators;
pub mod linearize_matches;
pub mod linearize_vars;
pub mod resolve_refs;
pub mod resugar_string;
pub mod unique_names;

View File

@ -0,0 +1,125 @@
use crate::{
fun::{builtins, Num, Pattern, Tag, Term},
maybe_grow,
};
impl Term {
/// Converts lambda-encoded strings ending with String/nil to a string literals.
pub fn resugar_strings(&mut self) {
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.
match self {
// Nil: String/nil
Term::Ref { nam } if nam == builtins::SNIL => *self = Term::str(""),
// Cons: @a @* (a <num> <str>)
Term::Lam {
tag: Tag::Static,
pat: box Pattern::Var(Some(nam_cons_lam)),
bod:
box Term::Lam {
tag: Tag::Static,
pat: box Pattern::Var(None),
bod:
box Term::App {
tag: Tag::Static,
fun:
box Term::App {
tag: Tag::Static,
fun: box Term::Var { nam: nam_cons_app },
arg: box Term::Num { val: Num::U24(c) },
},
arg: nxt,
},
},
} if nam_cons_lam == nam_cons_app => {
let head = char::from_u32(*c).unwrap_or('.');
if let Some(str) = build_string(nxt, head.to_string()) {
*self = Term::str(&str);
} else {
// Not a string term, keep as-is.
}
}
// Cons: (String/cons <num> <str>)
Term::App {
tag: Tag::Static,
fun:
box Term::App {
tag: Tag::Static,
fun: box Term::Ref { nam },
arg: box Term::Num { val: Num::U24(c) },
},
arg: nxt,
} if nam == builtins::SCONS => {
let head = char::from_u32(*c).unwrap_or('.');
if let Some(str) = build_string(nxt, head.to_string()) {
*self = Term::str(&str);
} else {
// Not a string term, keep as-is.
}
}
_ => (),
}
for child in self.children_mut() {
child.resugar_strings();
}
})
}
}
fn build_string(term: &Term, mut s: String) -> Option<String> {
maybe_grow(|| {
match term {
// Nil: String/nil
Term::Ref { nam } if nam == builtins::SNIL => Some(s),
// Cons: @a @* (a <num> <str>)
Term::Lam {
tag: Tag::Static,
pat: box Pattern::Var(Some(nam_cons_lam)),
bod:
box Term::Lam {
tag: Tag::Static,
pat: box Pattern::Var(None),
bod:
box Term::App {
tag: Tag::Static,
fun:
box Term::App {
tag: Tag::Static,
fun: box Term::Var { nam: nam_cons_app },
arg: box Term::Num { val: Num::U24(c) },
},
arg: nxt,
},
},
} if nam_cons_lam == nam_cons_app => {
// New string character, append and recurse
let head = char::from_u32(*c).unwrap_or('.');
s.push(head);
build_string(nxt, s)
}
// Cons: (String/cons <num> <str>)
Term::App {
tag: Tag::Static,
fun:
box Term::App {
tag: Tag::Static,
fun: box Term::Ref { nam },
arg: box Term::Num { val: Num::U24(c) },
},
arg: nxt,
} if nam == builtins::SCONS => {
// New string character, append and recurse
let head = char::from_u32(*c).unwrap_or('.');
s.push(head);
build_string(nxt, s)
}
_ => {
// Not a string term, stop
None
}
}
})
}

View File

@ -215,6 +215,7 @@ pub fn readback_hvm_net(net: &Net, book: &Book, labels: &Labels, linear: bool) -
let net = hvmc_to_net(net);
let mut term = net_to_term(&net, book, labels, linear, &mut diags);
term.expand_generated(book);
term.resugar_strings();
(term, diags)
}

View File

@ -5,8 +5,8 @@ input_file: tests/golden_tests/cli/run_pretty.bend
Result:
λa switch a = a {
0: λa switch a {
0: (String/cons 98 (String/cons 97 String/nil));
_: λ* (String/cons 116 (String/cons 97 String/nil));
0: "ba";
_: λ* "ta";
};
_: λ* λb λ* (b 97 λc λ* (c 116 λd λ* (d 97 String/nil)));
_: λ* "ata";
}

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/chars.bend
---
λa λ* (a 4660 λb λ* (b 33 λc λ* (c 55 String/nil)))
"ሴ!7"

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/escape_sequences.bend
---
λa (Join (List/cons (String/cons 10 String/nil) (List/cons (String/cons 13 String/nil) (List/cons (String/cons 9 String/nil) (List/cons (String/cons 0 String/nil) (List/cons (String/cons 34 String/nil) (List/cons (String/cons 39 String/nil) (List/cons (String/cons 2814 String/nil) (List/cons (String/cons 92 String/nil) List/nil)))))))))
λa (Join (List/cons "\n" (List/cons "\r" (List/cons "\t" (List/cons "\0" (List/cons "\"" (List/cons "'" (List/cons "\u{afe}" (List/cons "\\" List/nil)))))))))

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/match_builtins.bend
---
{λa λ* (a 101 λb λ* (b 108 λc λ* (c 108 λd λ* (d 111 String/nil)))) λe λ* (e 119 λf λ* (f 111 λg λ* (g 114 λh λ* (h 108 λi λ* (i 100 String/nil)))))}
{"ello" "world"}

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/match_num_adt_tup_parser.bend
---
λ* λa (a {λb λ* (b 40 λc λ* (c 43 String/nil)) *})
λ* λa (a {"(+" *})

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/nested_list_and_string.bend
---
λa λb λ* (b a λc λ* (c λ* 2 λd λ* (d λe λ* (e λf λ* (f 7 λg λ* (g λh λ* (h 49 λi λ* (i 50 λj λ* (j 51 λk λ* (k 52 String/nil)))) λl λ* (l 9 List/nil))) λm λ* (m a (String/cons * (String/cons 52 (String/cons 50 String/nil))))) List/nil)))
λa λb λ* (b a λc λ* (c λ* 2 λd λ* (d λe λ* (e λf λ* (f 7 λg λ* (g "1234" λl λ* (l 9 List/nil))) λm λ* (m a (String/cons * "42"))) List/nil)))

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/nested_str.bend
---
λa λb λc λd λ* (d λe λ* (e 97 λf λ* (f 98 String/nil)) λg λ* (g λh λ* (h 99 λi λ* (i 100 String/nil)) String/nil))
λa λb λc λd λ* (d "ab" λg λ* (g "cd" ""))

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/readback_list_other_ctr.bend
---
λa λ* (a λb λ* (b 97 λc (c 98 λd λ* (d 99 String/nil))) λe λ* (e 1 λf (f 2 λg λ* (g 3 λh λ* (h 4 List/nil)))))
λa λ* (a λb λ* (b 97 λc (c 98 "c")) λe λ* (e 1 λf (f 2 λg λ* (g 3 λh λ* (h 4 List/nil)))))

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/str_concat.bend
---
λa λ* (a 104 λb λ* (b 101 λc λ* (c 108 λd λ* (d 108 λe λ* (e 111 λf λ* (f 32 λg λ* (g 119 λh λ* (h 111 λi λ* (i 114 λj λ* (j 108 λk λ* (k 100 String/nil)))))))))))
"hello world"

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/tup_list_strings.bend
---
{λa λ* (a {λb λ* (b 102 λc λ* (c 111 λd λ* (d 111 String/nil))) 0} λe λ* (e {λf λ* (f 102 λg λ* (g 111 λh λ* (h 111 String/nil))) 0} λi λ* (i {λj λ* (j 102 λk λ* (k 111 λl λ* (l 111 String/nil))) 1} List/nil))) 4}
{λa λ* (a {"foo" 0} λe λ* (e {"foo" 0} λi λ* (i {"foo" 1} List/nil))) 4}

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/unaplied_str.bend
---
λa λb λc λ* (c a λd λ* (d 98 λe λ* (e 99 λf λ* (f b String/nil))))
λa λb λc λ* (c a λd λ* (d 98 λe λ* (e 99 λf λ* (f b ""))))

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/world.bend
---
λa λ* (a 127758 String/nil)
"🌎"

View File

@ -2,4 +2,4 @@
source: tests/golden_tests.rs
input_file: tests/golden_tests/run_file/wrong_string.bend
---
λa λ* (a λ* 4 λb λ* (b * String/nil))
λa λ* (a λ* 4 λb λ* (b * ""))