task_local context over context objects

- interner impls logically separate from API in orchid-base (default host interner still in base for testing)
- error reporting, logging, and a variety of other features passed down via context in extension, not yet in host to maintain library-ish profile, should consider options
- no global spawn mechanic, the host has a spawn function but extensions only get a stash for enqueuing async work in sync callbacks which is then explicitly, manually, and with strict order popped and awaited
- still deadlocks nondeterministically for some ungodly reason
This commit is contained in:
2026-01-01 14:54:29 +00:00
parent 06debb3636
commit 32d6237dc5
92 changed files with 2507 additions and 2223 deletions

View File

@@ -6,7 +6,6 @@ use orchid_base::name::Sym;
use orchid_base::number::Numeric;
use orchid_extension::atom::{AtomFactory, Atomic, AtomicFeatures, Supports, TAtom, ToAtom};
use orchid_extension::atom_thin::{ThinAtom, ThinVariant};
use orchid_extension::context::i;
use orchid_extension::conv::TryFromExpr;
use orchid_extension::expr::Expr;
use ordered_float::NotNan;
@@ -31,7 +30,7 @@ impl TryFromExpr for Int {
}
impl Supports<GetTagIdMethod> for Int {
async fn handle(&self, _: GetTagIdMethod) -> <GetTagIdMethod as Request>::Response {
Sym::parse("std::number::Int", &i()).await.unwrap().to_api()
Sym::parse("std::number::Int").await.unwrap().to_api()
}
}
impl Supports<ToStringMethod> for Int {

View File

@@ -3,13 +3,12 @@ use std::ops::RangeInclusive;
use orchid_base::error::OrcRes;
use orchid_base::number::{num_to_errv, parse_num};
use orchid_extension::atom::ToAtom;
use orchid_extension::context::i;
use orchid_extension::lexer::{LexContext, Lexer};
use orchid_extension::tree::{GenTokTree, x_tok};
use super::num_atom::Num;
#[derive(Default)]
#[derive(Debug, Default)]
pub struct NumLexer;
impl Lexer for NumLexer {
const CHAR_FILTER: &'static [RangeInclusive<char>] = &['0'..='9'];
@@ -18,7 +17,7 @@ impl Lexer for NumLexer {
let (chars, tail) = all.split_at(ends_at.unwrap_or(all.len()));
let fac = match parse_num(chars) {
Ok(numeric) => Num(numeric).to_atom_factory(),
Err(e) => return Err(num_to_errv(e, lxcx.pos(all), lxcx.src(), &i()).await),
Err(e) => return Err(num_to_errv(e, lxcx.pos(all), lxcx.src()).await),
};
Ok((tail, x_tok(fac).await.at(lxcx.pos_lt(chars.len(), tail))))
}

View File

@@ -4,10 +4,10 @@ use std::pin::Pin;
use futures::AsyncWrite;
use orchid_api_traits::Encode;
use orchid_base::error::mk_errv;
use orchid_base::interner::is;
use orchid_base::sym;
use orchid_extension::atom::{Atomic, ForeignAtom, TAtom};
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant};
use orchid_extension::context::i;
use orchid_extension::conv::{ToExpr, TryFromExpr};
use orchid_extension::expr::{Expr, ExprHandle};
use orchid_extension::gen_expr::{call, sym_ref};
@@ -30,7 +30,7 @@ impl OwnedAtom for OptAtom {
Self(ctx.read::<bool>().await.then(|| refs.into_iter().next().unwrap()))
}
async fn serialize(&self, write: Pin<&mut (impl AsyncWrite + ?Sized)>) -> Self::Refs {
self.0.is_some().encode(write).await;
self.0.is_some().encode(write).await.unwrap();
self.0.iter().cloned().collect()
}
}
@@ -50,9 +50,9 @@ impl<T: TryFromExpr> TryFromExpr for OrcOpt<T> {
impl<T: ToExpr + 'static> ToExpr for OrcOpt<T> {
async fn to_gen(self) -> orchid_extension::gen_expr::GExpr {
if let Some(val) = self.0 {
call(sym_ref(sym!(std::option::some; i())), [val.to_gen().await])
call(sym_ref(sym!(std::option::some)), [val.to_gen().await])
} else {
sym_ref(sym!(std::option::none; i()))
sym_ref(sym!(std::option::none))
}
}
}
@@ -64,11 +64,10 @@ pub fn gen_option_lib() -> Vec<GenMember> {
fun(true, "expect", async |opt: ForeignAtom, msg: OrcString| {
match OrcOpt::try_from_expr(opt.clone().ex()).await? {
OrcOpt(Some(ex)) => Ok::<Expr, _>(ex),
OrcOpt(None) => Err(mk_errv(
i().i("Unwrapped std::option::none").await,
msg.get_string().await.as_str(),
[opt.pos()],
)),
OrcOpt(None) =>
Err(mk_errv(is("Unwrapped std::option::none").await, msg.get_string().await.as_str(), [
opt.pos(),
])),
}
}),
])

View File

@@ -1,9 +1,9 @@
use itertools::{Itertools, chain};
use orchid_base::error::{OrcRes, mk_errv};
use orchid_base::interner::Tok;
use orchid_base::interner::{IStr, is};
use orchid_base::name::Sym;
use orchid_base::parse::{
Import, ParseCtx, Parsed, Snippet, expect_tok, line_items, parse_multiname, token_errv,
Import, Parsed, Snippet, expect_tok, line_items, parse_multiname, token_errv,
};
use orchid_base::tree::{Paren, Token};
use orchid_extension::parser::{
@@ -11,57 +11,54 @@ use orchid_extension::parser::{
};
pub async fn parse_impls(
ctx: &ParsCtx<'_>,
_: &ParsCtx<'_>,
lines: &mut Vec<ParsedLine>,
impls: &mut Vec<(Sym, Tok<String>)>,
impls: &mut Vec<(Sym, IStr)>,
body_tt: &PTokTree,
) -> OrcRes<()> {
let i = ctx.i().clone();
let body = match &body_tt.tok {
Token::S(Paren::Round, body) => line_items(ctx, Snippet::new(body_tt, body)).await,
Token::S(Paren::Round, body) => line_items(Snippet::new(body_tt, body)).await,
Token::S(ptyp, _) =>
return Err(mk_errv(
i.i("Incorrect paren type").await,
is("Incorrect paren type").await,
format!("Expected () block, found {ptyp}"),
[body_tt.sr().pos()],
)),
_ =>
return Err(
token_errv(ctx, body_tt, "Expected body", |s| {
format!("Expected (impl ...) block, found {s}")
})
.await,
token_errv(body_tt, "Expected body", |s| format!("Expected (impl ...) block, found {s}"))
.await,
),
};
for Parsed { tail: line, output: comments } in body {
if let Ok(Parsed { tail, .. }) = expect_tok(ctx, line, i.i("impl").await).await {
let Parsed { tail, output: name_tt } = parse_multiname(ctx, tail).await?;
if let Ok(Parsed { tail, .. }) = expect_tok(line, is("impl").await).await {
let Parsed { tail, output: name_tt } = parse_multiname(tail).await?;
let (name, name_sr) = match name_tt.into_iter().at_most_one() {
Ok(None) => panic!("multiname is always at least one name"),
Ok(Some(ref n @ Import { name: Some(_), ref sr, .. })) =>
(n.clone().mspath().to_sym(&i).await, sr.clone()),
(n.clone().mspath().to_sym().await, sr.clone()),
Ok(Some(Import { name: None, sr, .. })) =>
return Err(mk_errv(
i.i("impl line with globstar").await,
is("impl line with globstar").await,
"::* is not permitted in a protocol impl",
[sr.pos()],
)),
Err(e) =>
return Err(mk_errv(
i.i("Impl line with multiple protocol names").await,
is("Impl line with multiple protocol names").await,
"::() is not permitted in a protocol impl",
e.map(|i| i.sr.pos()),
)),
};
let Parsed { tail, .. } = expect_tok(ctx, tail, i.i("as").await).await?;
let cnst_name = i.i(&format!("{}{}", lines.len(), name.iter().join("__"))).await;
let Parsed { tail, .. } = expect_tok(tail, is("as").await).await?;
let cnst_name = is(&format!("{}{}", lines.len(), name.iter().join("__"))).await;
lines.push(ParsedLine {
comments,
sr: line.sr(),
kind: ParsedLineKind::Rec(Vec::from_iter(chain![
[Token::Name(i.i("let").await).at(line.sr())],
[Token::Name(is("let").await).at(line.sr())],
[Token::Name(cnst_name.clone()).at(name_sr)],
[Token::Name(i.i("=").await).at(line.sr())],
[Token::Name(is("=").await).at(line.sr())],
tail.iter().cloned().map(p_tree2gen),
])),
});

View File

@@ -2,10 +2,10 @@ use std::rc::Rc;
use hashbrown::HashMap;
use orchid_base::error::{OrcRes, mk_errv};
use orchid_base::interner::is;
use orchid_base::parse::{Comment, Parsed, expect_end, try_pop_no_fluff};
use orchid_base::sym;
use orchid_base::tree::Token;
use orchid_extension::context::i;
use orchid_extension::coroutine_exec::exec;
use orchid_extension::gen_expr::{call, sym_ref};
use orchid_extension::parser::{PSnippet, ParsCtx, ParsedLine, Parser};
@@ -23,11 +23,11 @@ impl Parser for AsProtoParser {
cmts: Vec<Comment>,
line: PSnippet<'a>,
) -> OrcRes<Vec<ParsedLine>> {
let Parsed { output: body_tt, tail } = try_pop_no_fluff(&pcx, line).await?;
expect_end(&pcx, tail).await?;
let Parsed { output: body_tt, tail } = try_pop_no_fluff(line).await?;
expect_end(tail).await?;
if exported {
return Err(mk_errv(
i().i("Exported internal line").await,
is("Exported internal line").await,
"as_proto cannot be exported, the type shares the enclosing module's visibility",
[line.sr().pos()],
));
@@ -36,20 +36,20 @@ impl Parser for AsProtoParser {
let mut impls = Vec::new();
parse_impls(&pcx, &mut lines, &mut impls, body_tt).await?;
let id = pcx.module();
let proto_tag_name = i().i("__protocol_tag__").await;
let proto_tag_path = id.suffix([proto_tag_name.clone()], &i()).await;
let proto_tag_name = is("__protocol_tag__").await;
let proto_tag_path = id.suffix([proto_tag_name.clone()]).await;
lines.push(ParsedLine::cnst(&line.sr(), &cmts, true, proto_tag_name, async |_ccx| {
exec(async move |mut h| {
let mut new_impls = HashMap::new();
for (k, v) in impls {
new_impls.insert(k.clone(), h.register(sym_ref(id.suffix([v], &i()).await)).await);
new_impls.insert(k.clone(), h.register(sym_ref(id.suffix([v]).await)).await);
}
Tag { id, impls: Rc::new(new_impls) }
})
.await
}));
lines.push(ParsedLine::cnst(&line.sr(), [], false, i().i("resolve").await, async move |_| {
call(sym_ref(sym!(std::protocol::resolve; i())), [sym_ref(proto_tag_path)])
lines.push(ParsedLine::cnst(&line.sr(), [], false, is("resolve").await, async move |_| {
call(sym_ref(sym!(std::protocol::resolve)), [sym_ref(proto_tag_path)])
}));
Ok(lines)
}
@@ -65,9 +65,9 @@ impl Parser for ProtoParser {
cmts: Vec<Comment>,
line: PSnippet<'a>,
) -> OrcRes<Vec<ParsedLine>> {
let Parsed { output: name_tt, tail } = try_pop_no_fluff(&ctx, line).await?;
let Parsed { output: name_tt, tail } = try_pop_no_fluff(line).await?;
let Token::Name(name) = &name_tt.tok else {
return Err(mk_errv(i().i("missing name for type").await, "A type needs a name", [name_tt
return Err(mk_errv(is("missing name for type").await, "A type needs a name", [name_tt
.sr()
.pos()]));
};

View File

@@ -2,10 +2,10 @@ use std::rc::Rc;
use hashbrown::HashMap;
use orchid_base::error::{OrcRes, mk_errv};
use orchid_base::interner::is;
use orchid_base::parse::{Comment, Parsed, expect_end, try_pop_no_fluff};
use orchid_base::sym;
use orchid_base::tree::Token;
use orchid_extension::context::i;
use orchid_extension::coroutine_exec::exec;
use orchid_extension::gen_expr::{call, sym_ref};
use orchid_extension::parser::{PSnippet, ParsCtx, ParsedLine, Parser};
@@ -23,11 +23,11 @@ impl Parser for AsTypeParser {
cmts: Vec<Comment>,
line: PSnippet<'a>,
) -> OrcRes<Vec<ParsedLine>> {
let Parsed { output: body_tt, tail } = try_pop_no_fluff(&ctx, line).await?;
expect_end(&ctx, tail).await?;
let Parsed { output: body_tt, tail } = try_pop_no_fluff(line).await?;
expect_end(tail).await?;
if exported {
return Err(mk_errv(
i().i("Exported internal line").await,
is("Exported internal line").await,
"as_type cannot be exported, the type shares the enclosing module's visibility",
[line.sr().pos()],
));
@@ -36,25 +36,25 @@ impl Parser for AsTypeParser {
let mut impls = Vec::new();
parse_impls(&ctx, &mut lines, &mut impls, body_tt).await?;
let id = ctx.module();
let type_tag_name = i().i("__type_tag__").await;
let type_tag_path = id.suffix([type_tag_name.clone()], &i()).await;
let type_tag_name = is("__type_tag__").await;
let type_tag_path = id.suffix([type_tag_name.clone()]).await;
lines.push(ParsedLine::cnst(&line.sr(), &cmts, true, type_tag_name, async |_ccx| {
exec(async move |mut h| {
let mut new_impls = HashMap::new();
for (k, v) in impls {
new_impls.insert(k.clone(), h.register(sym_ref(id.suffix([v], &i()).await)).await);
new_impls.insert(k.clone(), h.register(sym_ref(id.suffix([v]).await)).await);
}
Tag { id, impls: Rc::new(new_impls) }
})
.await
}));
let type_tag_path_1 = type_tag_path.clone();
lines.push(ParsedLine::cnst(&line.sr(), [], false, i().i("wrap").await, async move |_ccx| {
call(sym_ref(sym!(std::protocol::wrap; i())), [sym_ref(type_tag_path_1)])
lines.push(ParsedLine::cnst(&line.sr(), [], false, is("wrap").await, async move |_ccx| {
call(sym_ref(sym!(std::protocol::wrap)), [sym_ref(type_tag_path_1)])
}));
let type_tag_path_1 = type_tag_path.clone();
lines.push(ParsedLine::cnst(&line.sr(), [], false, i().i("unwrap").await, async move |_ccx| {
call(sym_ref(sym!(std::protocol::unwrap; i())), [sym_ref(type_tag_path_1)])
lines.push(ParsedLine::cnst(&line.sr(), [], false, is("unwrap").await, async move |_ccx| {
call(sym_ref(sym!(std::protocol::unwrap)), [sym_ref(type_tag_path_1)])
}));
Ok(lines)
}
@@ -70,9 +70,9 @@ impl Parser for TypeParser {
cmts: Vec<Comment>,
line: PSnippet<'a>,
) -> OrcRes<Vec<ParsedLine>> {
let Parsed { output: name_tt, tail } = try_pop_no_fluff(&ctx, line).await?;
let Parsed { output: name_tt, tail } = try_pop_no_fluff(line).await?;
let Token::Name(name) = &name_tt.tok else {
return Err(mk_errv(i().i("missing name for type").await, "A type needs a name", [name_tt
return Err(mk_errv(is("missing name for type").await, "A type needs a name", [name_tt
.sr()
.pos()]));
};

View File

@@ -7,10 +7,10 @@ use orchid_api_derive::Coding;
use orchid_api_traits::Request;
use orchid_base::error::{OrcRes, mk_errv};
use orchid_base::format::fmt;
use orchid_base::interner::is;
use orchid_base::name::Sym;
use orchid_extension::atom::{AtomMethod, Atomic, ForeignAtom, MethodSetBuilder, Supports, TAtom};
use orchid_extension::atom_owned::{OwnedAtom, OwnedVariant, own};
use orchid_extension::context::i;
use orchid_extension::conv::ToExpr;
use orchid_extension::expr::Expr;
use orchid_extension::gen_expr::call;
@@ -34,7 +34,7 @@ impl OwnedAtom for Tag {
}
impl Supports<GetImplMethod> for Tag {
async fn handle(&self, req: GetImplMethod) -> <GetImplMethod as Request>::Response {
self.impls.get(&Sym::from_api(req.0, &i()).await).map(|expr| expr.handle().ticket())
self.impls.get(&Sym::from_api(req.0).await).map(|expr| expr.handle().ticket())
}
}
#[derive(Clone, Debug, Coding)]
@@ -75,13 +75,13 @@ impl Supports<GetImplMethod> for Tagged {
pub async fn get_impl(receiver: ForeignAtom, proto: ForeignAtom) -> OrcRes<Expr> {
let Some(proto_id) = proto.request(GetTagIdMethod).await else {
return Err(mk_errv(i().i("Not a protocol").await, "Protocol does not have a tag ID", [
return Err(mk_errv(is("Not a protocol").await, "Protocol does not have a tag ID", [
proto.pos()
]));
};
let Some(impl_val_opt) = receiver.request(GetImplMethod(proto_id)).await else {
return Err(mk_errv(
i().i("Receiver not tagged").await,
is("Receiver not tagged").await,
"The receiver does not have a type tag",
[receiver.pos()],
));
@@ -91,14 +91,14 @@ pub async fn get_impl(receiver: ForeignAtom, proto: ForeignAtom) -> OrcRes<Expr>
}
let Some(type_id) = receiver.request(GetTagIdMethod).await else {
return Err(mk_errv(
i().i("Incorrect protocols implementation in extension").await,
is("Incorrect protocols implementation in extension").await,
"Atom provides an impl table but no tag ID",
[receiver.pos()],
));
};
let Some(impl_val_opt) = proto.request(GetImplMethod(type_id)).await else {
return Err(mk_errv(
i().i("Incorrect protocols implementation in extension").await,
is("Incorrect protocols implementation in extension").await,
"Proto table atom provides a tag ID but no impl table",
[receiver.pos()],
));
@@ -107,7 +107,7 @@ pub async fn get_impl(receiver: ForeignAtom, proto: ForeignAtom) -> OrcRes<Expr>
return Ok(Expr::deserialize(impl_val).await);
}
return Err(mk_errv(
i().i("Implementation not found").await,
is("Implementation not found").await,
"This protocol is not implemented for this receiver",
[receiver.pos(), proto.pos()],
));
@@ -126,13 +126,8 @@ pub fn gen_protocol_lib() -> Vec<GenMember> {
Ok(own_val.value.to_gen().await)
} else {
Err(mk_errv(
i().i("Type mismatch").await,
format!(
"{} has type {}, expected {}",
fmt(&value, &i()).await,
own_val.tag.id,
own_tag.id
),
is("Type mismatch").await,
format!("{} has type {}, expected {}", fmt(&value).await, own_val.tag.id, own_tag.id),
[value.pos()],
))
}

View File

@@ -6,16 +6,15 @@ use futures::AsyncWrite;
use futures::future::join_all;
use hashbrown::HashMap;
use orchid_api_traits::Encode;
use orchid_base::interner::Tok;
use orchid_base::interner::{IStr, es};
use orchid_extension::atom::Atomic;
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant};
use orchid_extension::context::i;
use orchid_extension::expr::Expr;
use crate::api;
#[derive(Clone)]
pub struct Record(pub Rc<HashMap<Tok<String>, Expr>>);
pub struct Record(pub Rc<HashMap<IStr, Expr>>);
impl Atomic for Record {
type Data = ();
type Variant = OwnedVariant;
@@ -25,13 +24,12 @@ impl OwnedAtom for Record {
async fn serialize(&self, write: Pin<&mut (impl AsyncWrite + ?Sized)>) -> Self::Refs {
let (keys, values) =
self.0.iter().map(|(k, v)| (k.to_api(), v.clone())).unzip::<_, _, Vec<_>, Vec<_>>();
keys.encode(write).await;
keys.encode(write).await.unwrap();
values
}
async fn deserialize(mut dctx: impl DeserializeCtx, refs: Self::Refs) -> Self {
let keys =
join_all(dctx.decode::<Vec<api::TStr>>().await.iter().map(|t| async { i().ex(*t).await }))
.await;
join_all(dctx.decode::<Vec<api::TStr>>().await.iter().map(|t| async { es(*t).await })).await;
Record(Rc::new(keys.into_iter().zip(refs).collect()))
}

View File

@@ -4,10 +4,10 @@ use orchid_api::TStrv;
use orchid_api_derive::{Coding, Hierarchy};
use orchid_api_traits::Request;
use orchid_base::error::mk_errv;
use orchid_base::interner::{es, is};
use orchid_base::name::{NameLike, Sym};
use orchid_extension::atom::{Atomic, Supports, TAtom};
use orchid_extension::atom_owned::{OwnedAtom, OwnedVariant, own};
use orchid_extension::context::i;
use orchid_extension::expr::{Expr, ExprHandle};
use orchid_extension::system::dep_req;
use orchid_extension::tree::{GenMember, fun, prefix};
@@ -51,10 +51,10 @@ pub async fn sym_expr(sym: Sym) -> Expr {
pub async fn gen_sym_lib() -> Vec<GenMember> {
prefix("std::refl::sym", [
fun(true, "from_str", async move |str: TAtom<IntStrAtom>| {
match Sym::parse(&i().ex(*str).await, &i()).await {
match Sym::parse(&es(*str).await).await {
Ok(sym) => Ok(SymAtom(sym)),
Err(_) => Err(mk_errv(
i().i("Cannot parse sym from empty string").await,
is("Cannot parse sym from empty string").await,
"Empty string passed to std::refl::sym::from_str",
[str.pos()],
)),

View File

@@ -3,12 +3,10 @@ use std::rc::Rc;
use futures::future::join_all;
use orchid_api_derive::{Coding, Hierarchy};
use orchid_base::name::Sym;
use orchid_base::reqnot::Receipt;
use orchid_base::reqnot::{Receipt, ReqHandle, ReqHandleExt};
use orchid_base::sym;
use orchid_extension::atom::{AtomDynfo, AtomicFeatures};
use orchid_extension::context::i;
use orchid_extension::conv::ToExpr;
use orchid_extension::entrypoint::ExtReq;
use orchid_extension::expr::Expr;
use orchid_extension::lexer::LexerObj;
use orchid_extension::parser::ParserObj;
@@ -39,14 +37,14 @@ pub enum StdReq {
CreateSymAtom(CreateSymAtom),
}
#[derive(Default)]
#[derive(Debug, Default)]
pub struct StdSystem;
impl SystemCtor for StdSystem {
type Deps = ();
type Instance = Self;
const NAME: &'static str = "orchid::std";
const VERSION: f64 = 0.00_01;
fn inst(_: ()) -> Self::Instance { Self }
fn inst(&self, _: ()) -> Self::Instance { Self }
}
impl SystemCard for StdSystem {
type Ctor = Self;
@@ -68,16 +66,16 @@ impl SystemCard for StdSystem {
}
}
impl System for StdSystem {
async fn request(xreq: ExtReq<'_>, req: Self::Req) -> Receipt<'_> {
async fn request<'a>(xreq: Box<dyn ReqHandle<'a> + 'a>, req: Self::Req) -> Receipt<'a> {
match req {
StdReq::CreateTuple(ref req @ CreateTuple(ref items)) => {
let tpl = Tuple(Rc::new(join_all(items.iter().copied().map(Expr::deserialize)).await));
let tk = tpl.to_expr().await.serialize().await;
xreq.handle(req, &tk).await
xreq.reply(req, &tk).await.unwrap()
},
StdReq::CreateSymAtom(ref req @ CreateSymAtom(sym_tok)) => {
let sym_atom = SymAtom(Sym::from_api(sym_tok, &i()).await);
xreq.handle(req, &sym_atom.to_expr().await.serialize().await).await
let sym_atom = SymAtom(Sym::from_api(sym_tok).await);
xreq.reply(req, &sym_atom.to_expr().await.serialize().await).await.unwrap()
},
}
}
@@ -94,7 +92,5 @@ impl System for StdSystem {
gen_sym_lib().await,
])
}
async fn prelude() -> Vec<Sym> {
vec![sym!(std; i()), sym!(std::tuple; i()), sym!(std::option; i())]
}
async fn prelude() -> Vec<Sym> { vec![sym!(std), sym!(std::tuple), sym!(std::option)] }
}

View File

@@ -8,10 +8,9 @@ use orchid_api_derive::Coding;
use orchid_api_traits::{Encode, Request};
use orchid_base::error::{OrcRes, mk_errv};
use orchid_base::format::{FmtCtx, FmtUnit};
use orchid_base::interner::Tok;
use orchid_base::interner::{IStr, es, is};
use orchid_extension::atom::{AtomMethod, Atomic, MethodSetBuilder, Supports, TAtom};
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant};
use orchid_extension::context::i;
use orchid_extension::conv::TryFromExpr;
use orchid_extension::expr::Expr;
@@ -52,7 +51,7 @@ impl OwnedAtom for StrAtom {
type Refs = ();
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
async fn serialize(&self, sink: Pin<&mut (impl AsyncWrite + ?Sized)>) -> Self::Refs {
self.deref().encode(sink).await
self.deref().encode(sink).await.unwrap()
}
async fn print_atom<'a>(&'a self, _: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
format!("{:?}", &*self.0).into()
@@ -63,36 +62,36 @@ impl OwnedAtom for StrAtom {
}
#[derive(Debug, Clone)]
pub struct IntStrAtom(pub(crate) Tok<String>);
pub struct IntStrAtom(pub(crate) IStr);
impl Atomic for IntStrAtom {
type Variant = OwnedVariant;
type Data = orchid_api::TStr;
}
impl From<Tok<String>> for IntStrAtom {
fn from(value: Tok<String>) -> Self { Self(value) }
impl From<IStr> for IntStrAtom {
fn from(value: IStr) -> Self { Self(value) }
}
impl OwnedAtom for IntStrAtom {
type Refs = ();
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(self.0.to_api()) }
async fn print_atom<'a>(&'a self, _: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
format!("{:?}i", *self.0).into()
format!("{:?}i", &*self.0).into()
}
async fn serialize(&self, write: Pin<&mut (impl AsyncWrite + ?Sized)>) {
self.0.encode(write).await
self.0.encode(write).await.unwrap()
}
async fn deserialize(mut dctx: impl DeserializeCtx, _: ()) -> Self {
let s = dctx.decode::<String>().await;
Self(i().i(&s).await)
Self(is(&s).await)
}
}
impl TryFromExpr for IntStrAtom {
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
Ok(IntStrAtom(i().ex(TAtom::<IntStrAtom>::try_from_expr(expr).await?.value).await))
Ok(IntStrAtom(es(TAtom::<IntStrAtom>::try_from_expr(expr).await?.value).await))
}
}
impl Supports<ToStringMethod> for IntStrAtom {
async fn handle(&self, _: ToStringMethod) -> <ToStringMethod as Request>::Response {
self.0.as_str().to_string()
self.0.to_string()
}
}
@@ -109,7 +108,7 @@ pub enum OrcStringKind {
impl OrcString {
pub async fn get_string(&self) -> Rc<String> {
match &self.kind {
OrcStringKind::Int(tok) => i().ex(**tok).await.rc(),
OrcStringKind::Int(tok) => es(**tok).await.rc(),
OrcStringKind::Val(atom) => atom.request(StringGetVal).await,
}
}
@@ -122,7 +121,7 @@ impl TryFromExpr for OrcString {
}
match TAtom::<IntStrAtom>::try_from_expr(expr).await {
Ok(t) => Ok(OrcString { kind: OrcStringKind::Int(t) }),
Err(e) => Err(mk_errv(i().i("A string was expected").await, "", e.pos_iter())),
Err(e) => Err(mk_errv(is("A string was expected").await, "", e.pos_iter())),
}
}
}

View File

@@ -1,12 +1,10 @@
use itertools::Itertools;
use orchid_base::error::{OrcErr, OrcErrv, OrcRes, mk_errv};
use orchid_base::interner::Interner;
use orchid_base::interner::is;
use orchid_base::location::SrcRange;
use orchid_base::name::Sym;
use orchid_base::parse::ParseCtx;
use orchid_base::sym;
use orchid_base::tree::{Paren, wrap_tokv};
use orchid_extension::context::i;
use orchid_extension::gen_expr::sym_ref;
use orchid_extension::lexer::{LexContext, Lexer, err_not_applicable};
use orchid_extension::parser::p_tree2gen;
@@ -36,10 +34,10 @@ struct StringError {
impl StringError {
/// Convert into project error for reporting
pub async fn into_proj(self, path: &Sym, pos: u32, i: &Interner) -> OrcErrv {
pub async fn into_proj(self, path: &Sym, pos: u32) -> OrcErrv {
let start = pos + self.pos;
mk_errv(
i.i("Failed to parse string").await,
is("Failed to parse string").await,
match self.kind {
StringErrorKind::NotHex => "Expected a hex digit",
StringErrorKind::BadCodePoint => "The specified number is not a Unicode code point",
@@ -95,7 +93,7 @@ fn parse_string(str: &str) -> Result<String, StringError> {
Ok(target)
}
#[derive(Default)]
#[derive(Debug, Default)]
pub struct StringLexer;
impl Lexer for StringLexer {
const CHAR_FILTER: &'static [std::ops::RangeInclusive<char>] = &['"'..='"', '`'..='`'];
@@ -114,18 +112,16 @@ impl Lexer for StringLexer {
) -> GenTokTree {
let str_val_res = parse_string(&str.split_off(0));
if let Err(e) = &str_val_res {
err.extend(e.clone().into_proj(ctx.src(), ctx.pos(tail) - str.len() as u32, ctx.i()).await);
err.extend(e.clone().into_proj(ctx.src(), ctx.pos(tail) - str.len() as u32).await);
}
let str_val = str_val_res.unwrap_or_default();
x_tok(IntStrAtom::from(ctx.i().i(&*str_val).await))
.await
.at(ctx.pos_lt(str.len() as u32, tail)) as GenTokTree
x_tok(IntStrAtom::from(is(&str_val).await)).await.at(ctx.pos_lt(str.len() as u32, tail))
as GenTokTree
}
let add_frag = |prev: Option<GenTokTree>, new: GenTokTree| async {
let Some(prev) = prev else { return new };
let concat_fn = ref_tok(sym!(std::string::concat; lctx.i()))
.await
.at(SrcRange::zw(prev.sr.path(), prev.sr.start()));
let concat_fn =
ref_tok(sym!(std::string::concat)).await.at(SrcRange::zw(prev.sr.path(), prev.sr.start()));
wrap_tokv([concat_fn, prev, new])
};
loop {
@@ -139,7 +135,7 @@ impl Lexer for StringLexer {
let (new_tail, tree) = lctx.recurse(rest).await?;
tail = new_tail;
// wrap the received token in a call to to_str
let to_str = sym_ref(sym!(std::string::to_str; i()));
let to_str = sym_ref(sym!(std::string::to_str));
let sr = tree.sr();
let inj_to_str_tok = GenTok::NewExpr(to_str).at(sr.map_range(|_| sr.start()..sr.start()));
let to_str_call = GenTok::S(Paren::Round, vec![inj_to_str_tok, p_tree2gen(tree)]).at(sr);
@@ -154,11 +150,9 @@ impl Lexer for StringLexer {
tail = ch.as_str();
} else {
let range = lctx.pos(all)..lctx.pos("");
return Err(mk_errv(
lctx.i().i("No string end").await,
"String never terminated with \"",
[SrcRange::new(range.clone(), lctx.src())],
));
return Err(mk_errv(is("No string end").await, "String never terminated with \"", [
SrcRange::new(range.clone(), lctx.src()),
]));
}
}
}

View File

@@ -3,7 +3,6 @@ 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;
@@ -35,13 +34,13 @@ pub fn gen_str_lib() -> Vec<GenMember> {
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_ref = sym_ref(sym!(std::string::to_string::__protocol_tag__));
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;
return StrAtom::new(Rc::new(fmt(&input).await)).to_gen().await;
})
.await
}),
@@ -50,7 +49,7 @@ pub fn gen_str_lib() -> Vec<GenMember> {
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?;
let proto = h.exec(sym_ref(sym!(std::string::to_string))).await?;
Ok(call(get_impl(atom.clone(), proto).await?.to_gen().await, [atom.to_gen().await]))
})
.await

View File

@@ -3,7 +3,6 @@ use orchid_api_traits::Request;
use orchid_base::name::Sym;
use orchid_extension::atom::{AtomMethod, Atomic, MethodSetBuilder, Supports};
use orchid_extension::atom_thin::{ThinAtom, ThinVariant};
use orchid_extension::context::i;
use crate::std::protocol::types::{GetImplMethod, GetTagIdMethod};
@@ -19,7 +18,7 @@ impl Atomic for AsStrTag {
impl ThinAtom for AsStrTag {}
impl Supports<GetTagIdMethod> for AsStrTag {
async fn handle(&self, _: GetTagIdMethod) -> <GetTagIdMethod as Request>::Response {
Sym::parse("std::string::to_string", &i()).await.unwrap().to_api()
Sym::parse("std::string::to_string").await.unwrap().to_api()
}
}
impl Supports<GetImplMethod> for AsStrTag {

View File

@@ -11,9 +11,9 @@ use orchid_api_derive::{Coding, Hierarchy};
use orchid_api_traits::Request;
use orchid_base::error::{OrcRes, mk_errv};
use orchid_base::format::{FmtCtx, FmtUnit, Format, Variants};
use orchid_base::interner::is;
use orchid_extension::atom::{Atomic, TAtom};
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant, own};
use orchid_extension::context::i;
use orchid_extension::conv::{ToExpr, TryFromExpr};
use orchid_extension::expr::{Expr, ExprHandle};
use orchid_extension::gen_expr::GExpr;
@@ -95,7 +95,7 @@ pub fn gen_tuple_lib() -> Vec<GenMember> {
return Ok(val.clone());
}
return Err(mk_errv(
i().i("Tuple index out of bounds").await,
is("Tuple index out of bounds").await,
format!("{} is out of bounds for Tuple{}", idx.0, tup.len()),
[idx.pos()],
));
@@ -109,7 +109,7 @@ pub fn gen_tuple_lib() -> Vec<GenMember> {
}
}
return Err(mk_errv(
i().i("Tuple index out of bounds").await,
is("Tuple index out of bounds").await,
format!("{} is out of bounds for Tuple{}", idx.0, tup.len()),
[idx.pos()],
));
@@ -145,7 +145,7 @@ pub struct Tpl<T>(pub T);
mod tpl_impls {
use itertools::Itertools;
use orchid_base::error::{OrcRes, mk_errv};
use orchid_extension::context::i;
use orchid_base::interner::is;
use orchid_extension::conv::{ToExpr, TryFromExpr};
use orchid_extension::expr::Expr;
use orchid_extension::gen_expr::GExpr;
@@ -160,7 +160,7 @@ mod tpl_impls {
let tpl = UntypedTuple::try_from_expr(expr.clone()).await?;
let Some([$( [< $t:lower >], )*]) = tpl.0.iter().cloned().collect_array() else {
return Err(mk_errv(
i().i("Tuple arity mismatch").await,
is("Tuple arity mismatch").await,
format!("Expected a {}-ary tuple, found {}-ary", $len, tpl.0.len()),
[expr.data().await.pos.clone()]
));