New macro system and stdlib additions

This commit is contained in:
2025-11-21 14:25:03 +01:00
parent b77653f841
commit 603efef28e
230 changed files with 3033 additions and 16640 deletions

View File

@@ -0,0 +1,77 @@
use std::rc::Rc;
use hashbrown::HashMap;
use orchid_base::error::{OrcRes, mk_errv};
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};
use crate::std::protocol::parse_impls::parse_impls;
use crate::std::protocol::types::Tag;
#[derive(Default)]
pub struct AsProtoParser;
impl Parser for AsProtoParser {
const LINE_HEAD: &'static str = "as_proto";
async fn parse<'a>(
pcx: ParsCtx<'a>,
exported: bool,
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?;
if exported {
return Err(mk_errv(
i().i("Exported internal line").await,
"as_proto cannot be exported, the type shares the enclosing module's visibility",
[line.sr().pos()],
));
}
let mut lines = Vec::new();
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;
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);
}
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)])
}));
Ok(lines)
}
}
#[derive(Default)]
pub struct ProtoParser;
impl Parser for ProtoParser {
const LINE_HEAD: &'static str = "proto";
async fn parse<'a>(
ctx: ParsCtx<'a>,
exported: bool,
cmts: Vec<Comment>,
line: PSnippet<'a>,
) -> OrcRes<Vec<ParsedLine>> {
let Parsed { output: name_tt, tail } = try_pop_no_fluff(&ctx, 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
.sr()
.pos()]));
};
let lines = AsProtoParser::parse(ctx, false, cmts.clone(), tail).await?;
Ok(vec![ParsedLine::module(&line.sr(), &cmts, exported, name, true, lines)])
}
}