temp commit
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use futures::FutureExt;
|
||||
use futures::future::join_all;
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::{OrcRes, Reporter, mk_err, mk_errv};
|
||||
use orchid_base::error::{OrcRes, Reporter, mk_errv};
|
||||
use orchid_base::format::fmt;
|
||||
use orchid_base::interner::{Interner, Tok};
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::name::{Sym, VPath};
|
||||
use orchid_base::parse::{
|
||||
Comment, Import, ParseCtx, Parsed, Snippet, expect_end, line_items, parse_multiname,
|
||||
try_pop_no_fluff,
|
||||
@@ -17,7 +14,7 @@ use substack::Substack;
|
||||
|
||||
use crate::ctx::Ctx;
|
||||
use crate::expr::{Expr, ExprKind, PathSetBuilder};
|
||||
use crate::parsed::{Item, ItemKind, ParsTokTree, ParsedMember, ParsedMemberKind, ParsedModule};
|
||||
use crate::parsed::{Item, ItemKind, ParsedMember, ParsedMemberKind, ParsedModule};
|
||||
use crate::system::System;
|
||||
|
||||
type ParsSnippet<'a> = Snippet<'a, Expr, Expr>;
|
||||
@@ -27,28 +24,23 @@ pub struct HostParseCtxImpl<'a> {
|
||||
pub src: Sym,
|
||||
pub systems: &'a [System],
|
||||
pub reporter: &'a Reporter,
|
||||
pub interner: &'a Interner,
|
||||
pub consts: RefCell<HashMap<Sym, Vec<ParsTokTree>>>,
|
||||
}
|
||||
|
||||
impl ParseCtx for HostParseCtxImpl<'_> {
|
||||
fn reporter(&self) -> &Reporter { self.reporter }
|
||||
fn i(&self) -> &Interner { self.interner }
|
||||
fn i(&self) -> &Interner { &self.ctx.i }
|
||||
}
|
||||
|
||||
impl HostParseCtx for HostParseCtxImpl<'_> {
|
||||
fn ctx(&self) -> &Ctx { &self.ctx }
|
||||
fn systems(&self) -> impl Iterator<Item = &System> { self.systems.iter() }
|
||||
async fn save_const(&self, path: Substack<'_, Tok<String>>, value: Vec<ParsTokTree>) {
|
||||
let name = Sym::new(path.unreverse(), self.interner).await.unwrap();
|
||||
self.consts.borrow_mut().insert(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HostParseCtx: ParseCtx {
|
||||
#[must_use]
|
||||
fn ctx(&self) -> &Ctx;
|
||||
#[must_use]
|
||||
fn systems(&self) -> impl Iterator<Item = &System>;
|
||||
async fn save_const(&self, path: Substack<'_, Tok<String>>, value: Vec<ParsTokTree>);
|
||||
}
|
||||
|
||||
pub async fn parse_items(
|
||||
@@ -73,33 +65,10 @@ pub async fn parse_item(
|
||||
n if *n == ctx.i().i("export").await => match try_pop_no_fluff(ctx, postdisc).await? {
|
||||
Parsed { output: TokTree { tok: Token::Name(n), .. }, tail } =>
|
||||
parse_exportable_item(ctx, path, comments, true, n.clone(), tail).await,
|
||||
Parsed { output: TokTree { tok: Token::S(Paren::Round, body), .. }, tail } => {
|
||||
expect_end(ctx, tail).await?;
|
||||
let mut ok = Vec::new();
|
||||
for tt in body {
|
||||
let sr = tt.sr.clone();
|
||||
match &tt.tok {
|
||||
Token::Name(n) =>
|
||||
ok.push(Item { comments: comments.clone(), sr, kind: ItemKind::Export(n.clone()) }),
|
||||
Token::NS(..) => ctx.reporter().report(mk_err(
|
||||
ctx.i().i("Compound export").await,
|
||||
"Cannot export compound names (names containing the :: separator)",
|
||||
[sr.pos().into()],
|
||||
)),
|
||||
t => ctx.reporter().report(mk_err(
|
||||
ctx.i().i("Invalid export").await,
|
||||
format!("Invalid export target {}", fmt(t, ctx.i()).await),
|
||||
[sr.pos().into()],
|
||||
)),
|
||||
}
|
||||
}
|
||||
expect_end(ctx, tail).await?;
|
||||
Ok(ok)
|
||||
},
|
||||
Parsed { output, tail: _ } => Err(mk_errv(
|
||||
ctx.i().i("Malformed export").await,
|
||||
"`export` can either prefix other lines or list names inside ( )",
|
||||
[output.sr.pos().into()],
|
||||
[output.sr()],
|
||||
)),
|
||||
},
|
||||
n if *n == ctx.i().i("import").await => {
|
||||
@@ -115,7 +84,7 @@ pub async fn parse_item(
|
||||
Some(_) => Err(mk_errv(
|
||||
ctx.i().i("Expected a line type").await,
|
||||
"All lines must begin with a keyword",
|
||||
[item.sr().pos().into()],
|
||||
[item.sr()],
|
||||
)),
|
||||
None => unreachable!("These lines are filtered and aggregated in earlier stages"),
|
||||
}
|
||||
@@ -138,22 +107,25 @@ pub async fn parse_exportable_item<'a>(
|
||||
discr: Tok<String>,
|
||||
tail: ParsSnippet<'a>,
|
||||
) -> OrcRes<Vec<Item>> {
|
||||
let path_sym = Sym::new(path.unreverse(), ctx.i()).await.expect("Files should have a namespace");
|
||||
let kind = if discr == ctx.i().i("mod").await {
|
||||
let (name, body) = parse_module(ctx, path, tail).await?;
|
||||
ItemKind::Member(ParsedMember { name, full_name: path_sym, kind: ParsedMemberKind::Mod(body) })
|
||||
ItemKind::Member(ParsedMember { name, exported, kind: ParsedMemberKind::Mod(body) })
|
||||
} else if discr == ctx.i().i("const").await {
|
||||
let name = parse_const(ctx, tail, path.clone()).await?;
|
||||
ItemKind::Member(ParsedMember { name, full_name: path_sym, kind: ParsedMemberKind::Const })
|
||||
let (name, expr) = parse_const(ctx, tail, path.clone()).await?;
|
||||
ItemKind::Member(ParsedMember { name, exported, kind: ParsedMemberKind::ParsedConst(expr) })
|
||||
} else if let Some(sys) = ctx.systems().find(|s| s.can_parse(discr.clone())) {
|
||||
let line = sys.parse(path_sym, tail.to_vec(), exported, comments).await?;
|
||||
return parse_items(ctx, path, Snippet::new(tail.prev(), &line)).await;
|
||||
return sys
|
||||
.parse(path, tail.to_vec(), exported, comments, &mut async |stack, lines| {
|
||||
let source = Snippet::new(lines.first().unwrap(), &lines);
|
||||
parse_items(ctx, stack, source).await
|
||||
})
|
||||
.await;
|
||||
} else {
|
||||
let ext_lines = ctx.systems().flat_map(System::line_types).join(", ");
|
||||
return Err(mk_errv(
|
||||
ctx.i().i("Unrecognized line type").await,
|
||||
format!("Line types are: const, mod, macro, grammar, {ext_lines}"),
|
||||
[tail.prev().sr.pos().into()],
|
||||
[tail.prev().sr()],
|
||||
));
|
||||
};
|
||||
Ok(vec![Item { comments, sr: tail.sr(), kind }])
|
||||
@@ -170,7 +142,7 @@ pub async fn parse_module<'a>(
|
||||
return Err(mk_errv(
|
||||
ctx.i().i("Missing module name").await,
|
||||
format!("A name was expected, {} was found", fmt(output, ctx.i()).await),
|
||||
[output.sr.pos().into()],
|
||||
[output.sr()],
|
||||
));
|
||||
},
|
||||
};
|
||||
@@ -180,7 +152,7 @@ pub async fn parse_module<'a>(
|
||||
return Err(mk_errv(
|
||||
ctx.i().i("Expected module body").await,
|
||||
format!("A ( block ) was expected, {} was found", fmt(output, ctx.i()).await),
|
||||
[output.sr.pos().into()],
|
||||
[output.sr()],
|
||||
));
|
||||
};
|
||||
let path = path.push(name.clone());
|
||||
@@ -191,13 +163,13 @@ pub async fn parse_const<'a>(
|
||||
ctx: &impl HostParseCtx,
|
||||
tail: ParsSnippet<'a>,
|
||||
path: Substack<'_, Tok<String>>,
|
||||
) -> OrcRes<Tok<String>> {
|
||||
) -> OrcRes<(Tok<String>, Expr)> {
|
||||
let Parsed { output, tail } = try_pop_no_fluff(ctx, tail).await?;
|
||||
let Some(name) = output.as_name() else {
|
||||
return Err(mk_errv(
|
||||
ctx.i().i("Missing module name").await,
|
||||
format!("A name was expected, {} was found", fmt(output, ctx.i()).await),
|
||||
[output.sr.pos().into()],
|
||||
[output.sr()],
|
||||
));
|
||||
};
|
||||
let Parsed { output, tail } = try_pop_no_fluff(ctx, tail).await?;
|
||||
@@ -205,12 +177,15 @@ pub async fn parse_const<'a>(
|
||||
return Err(mk_errv(
|
||||
ctx.i().i("Missing = separator").await,
|
||||
format!("Expected = , found {}", fmt(output, ctx.i()).await),
|
||||
[output.sr.pos().into()],
|
||||
[output.sr()],
|
||||
));
|
||||
}
|
||||
try_pop_no_fluff(ctx, tail).await?;
|
||||
ctx.save_const(path, tail[..].to_vec()).await;
|
||||
Ok(name)
|
||||
// ctx.save_const(path, tail[..].to_vec()).await;
|
||||
let final_path =
|
||||
VPath::new(path.unreverse()).name_with_suffix(name.clone()).to_sym(ctx.i()).await;
|
||||
let val = parse_expr(ctx, final_path, PathSetBuilder::new(), tail).await?;
|
||||
Ok((name, val))
|
||||
}
|
||||
|
||||
pub async fn parse_expr(
|
||||
@@ -223,7 +198,7 @@ pub async fn parse_expr(
|
||||
.or_else(|| tail.iter().enumerate().rev().find(|(_, tt)| !tt.is_fluff()))
|
||||
else {
|
||||
return Err(mk_errv(ctx.i().i("Empty expression").await, "Expression ends abruptly here", [
|
||||
tail.sr().pos().into(),
|
||||
tail.sr(),
|
||||
]));
|
||||
};
|
||||
let (function, value) = tail.split_at(last_idx as u32);
|
||||
@@ -241,7 +216,7 @@ pub async fn parse_expr(
|
||||
Token::Handle(expr) => Ok(expr.clone()),
|
||||
Token::NS(n, nametail) => {
|
||||
let mut nametail = nametail;
|
||||
let mut segments = path.iter().chain([n]).cloned().collect_vec();
|
||||
let mut segments = vec![n.clone()];
|
||||
while let Token::NS(n, newtail) = &nametail.tok {
|
||||
segments.push(n.clone());
|
||||
nametail = newtail;
|
||||
@@ -250,7 +225,7 @@ pub async fn parse_expr(
|
||||
return Err(mk_errv(
|
||||
ctx.i().i("Loose namespace prefix in constant").await,
|
||||
"Namespace prefixes in constants must be followed by names",
|
||||
[pos.into()],
|
||||
[pos],
|
||||
));
|
||||
};
|
||||
segments.push(n.clone());
|
||||
@@ -261,13 +236,27 @@ pub async fn parse_expr(
|
||||
return Err(mk_errv(
|
||||
ctx.i().i("Complex lambda binding in constant").await,
|
||||
"Lambda args in constants must be identified by a single name",
|
||||
[pos.into()],
|
||||
[pos],
|
||||
));
|
||||
};
|
||||
let lambda_builder = psb.lambda(arg);
|
||||
let body = parse_expr(ctx, path.clone(), lambda_builder.stack(), tail).boxed_local().await?;
|
||||
Ok(ExprKind::Lambda(lambda_builder.collect(), body).at(pos.clone()))
|
||||
},
|
||||
_ => todo!("AAAAAA"), // TODO: todo
|
||||
Token::S(Paren::Round, body) =>
|
||||
parse_expr(ctx, path, psb, Snippet::new(head, body)).boxed_local().await,
|
||||
Token::S(..) =>
|
||||
return Err(mk_errv(
|
||||
ctx.i().i("Constants may only contain (), not [] or {}").await,
|
||||
"It seems like you are trying to call a macro. Consider a 'let' line",
|
||||
[pos],
|
||||
)),
|
||||
Token::Name(n) =>
|
||||
if psb.register_arg(n) {
|
||||
Ok(ExprKind::Arg.at(pos))
|
||||
} else {
|
||||
Ok(ExprKind::Const(Sym::new([n.clone()], ctx.i()).await.unwrap()).at(pos))
|
||||
},
|
||||
Token::NewExpr(ex) => Ok(ex.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user