80 lines
2.4 KiB
Rust
80 lines
2.4 KiB
Rust
use itertools::{Itertools, chain};
|
|
use orchid_base::error::{OrcRes, mk_errv};
|
|
use orchid_base::interner::{IStr, is};
|
|
use orchid_base::name::Sym;
|
|
use orchid_base::parse::{
|
|
Import, Parsed, Snippet, expect_tok, line_items, parse_multiname, token_errv,
|
|
};
|
|
use orchid_base::tree::{Paren, Token};
|
|
use orchid_extension::parser::{
|
|
PTokTree, ParsCtx, ParsedLine, ParsedLineKind, p_tree2gen, p_v2gen,
|
|
};
|
|
|
|
pub async fn parse_impls(
|
|
_: &ParsCtx<'_>,
|
|
lines: &mut Vec<ParsedLine>,
|
|
impls: &mut Vec<(Sym, IStr)>,
|
|
body_tt: &PTokTree,
|
|
) -> OrcRes<()> {
|
|
let body = match &body_tt.tok {
|
|
Token::S(Paren::Round, body) => line_items(Snippet::new(body_tt, body)).await,
|
|
Token::S(ptyp, _) => {
|
|
return Err(mk_errv(
|
|
is("Incorrect paren type").await,
|
|
format!("Expected () block, found {ptyp}"),
|
|
[body_tt.sr().pos()],
|
|
));
|
|
},
|
|
_ => {
|
|
return Err(
|
|
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(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().await, sr.clone()),
|
|
Ok(Some(Import { name: None, sr, .. })) => {
|
|
return Err(mk_errv(
|
|
is("impl line with globstar").await,
|
|
"::* is not permitted in a protocol impl",
|
|
[sr.pos()],
|
|
));
|
|
},
|
|
Err(e) => {
|
|
return Err(mk_errv(
|
|
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(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(is("let").await).at(line.sr())],
|
|
[Token::Name(cnst_name.clone()).at(name_sr)],
|
|
[Token::Name(is("=").await).at(line.sr())],
|
|
tail.iter().cloned().map(p_tree2gen),
|
|
])),
|
|
});
|
|
impls.push((name, cnst_name));
|
|
} else {
|
|
lines.push(ParsedLine {
|
|
sr: line.sr(),
|
|
comments,
|
|
kind: ParsedLineKind::Rec(p_v2gen(line.to_vec())),
|
|
});
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|