New macro system and stdlib additions
This commit is contained in:
77
orchid-std/src/std/protocol/proto_parser.rs
Normal file
77
orchid-std/src/std/protocol/proto_parser.rs
Normal 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)])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user