78 lines
2.4 KiB
Rust
78 lines
2.4 KiB
Rust
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::coroutine_exec::exec;
|
|
use orchid_extension::gen_expr::{call, new_atom, 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(line).await?;
|
|
expect_end(tail).await?;
|
|
if exported {
|
|
return Err(mk_errv(
|
|
is("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 = 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]).await)).await);
|
|
}
|
|
new_atom(Tag { id, impls: Rc::new(new_impls) })
|
|
})
|
|
.await
|
|
}));
|
|
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)
|
|
}
|
|
}
|
|
|
|
#[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(line).await?;
|
|
let Token::Name(name) = &name_tt.tok else {
|
|
return Err(mk_errv(is("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)])
|
|
}
|
|
}
|