use std::rc::Rc; use orchid_base::format::fmt; use orchid_base::sym; use orchid_extension::atom::ForeignAtom; use orchid_extension::context::i; use orchid_extension::conv::ToExpr; use orchid_extension::coroutine_exec::exec; use orchid_extension::expr::Expr; use orchid_extension::gen_expr::{call, sym_ref}; use orchid_extension::tree::{GenMember, cnst, comments, fun, prefix}; use super::str_atom::StrAtom; use crate::OrcString; use crate::std::protocol::types::get_impl; use crate::std::string::to_string::{AsStrTag, ToStringMethod}; pub fn gen_str_lib() -> Vec { prefix("std::string", [ comments( ["Concatenate two strings"], fun(true, "concat", async |left: OrcString, right: OrcString| { StrAtom::new(Rc::new(left.get_string().await.to_string() + &right.get_string().await)) }), ), comments( ["Converts a value to string. This function is used in interpolation. \ It supports the std::string::to_string protocol in Orchid, \ the std::string::to_string request in Rust, \ and expression debug printing as a fallback (print_atom for Atomic implementors in Rust).\n\n\ This function is infallible."], fun(true, "to_str", async |input: Expr| { exec(async move |mut h| { if let Ok(atom) = h.exec::(input.clone()).await { if let Some(str) = atom.request(ToStringMethod).await { return StrAtom::new(Rc::new(str)).to_gen().await; } let proto_ref = sym_ref(sym!(std::string::to_string::__protocol_tag__; i())); let proto = h.exec(proto_ref).await.expect("This protocol is defined in this system"); if let Ok(cb) = get_impl(atom.clone(), proto).await { return call(cb.to_gen().await, [atom.to_gen().await]).to_gen().await; } } return StrAtom::new(Rc::new(fmt(&input, &i()).await)).to_gen().await; }) .await }), ), prefix("to_string", [ cnst(true, "__type_tag__", AsStrTag), fun(true, "resolve", async |atom: ForeignAtom| { exec(async |mut h| { let proto = h.exec(sym_ref(sym!(std::string::to_string; i()))).await?; Ok(call(get_impl(atom.clone(), proto).await?.to_gen().await, [atom.to_gen().await])) }) .await }), ]), ]) }