forked from Orchid/orchid
Various progress, doesnt compile
Added prelude, made lambdas a single-token prefix like NS, made progress on implementations, removed const line type
This commit is contained in:
@@ -21,6 +21,7 @@ orchid-extension = { version = "0.1.0", path = "../orchid-extension", features =
|
||||
] }
|
||||
ordered-float = "5.0.0"
|
||||
rust_decimal = "1.36.0"
|
||||
substack = "1.1.1"
|
||||
tokio = { version = "1.43.0", features = ["full"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// mod macros;
|
||||
mod macros;
|
||||
mod std;
|
||||
|
||||
pub use std::number::num_atom::{Float, HomoArray, Int, Num};
|
||||
|
||||
94
orchid-std/src/macros/instantiate_tpl.rs
Normal file
94
orchid-std/src/macros/instantiate_tpl.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
use std::borrow::Cow;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
use futures::AsyncWrite;
|
||||
use itertools::Itertools;
|
||||
use never::Never;
|
||||
use orchid_extension::atom::{Atomic, TypAtom};
|
||||
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant, get_own_instance};
|
||||
use orchid_extension::conv::{ToExpr, TryFromExpr};
|
||||
use orchid_extension::expr::Expr;
|
||||
use orchid_extension::gen_expr::GExpr;
|
||||
use orchid_extension::system::SysCtx;
|
||||
|
||||
use crate::macros::mactree::{MacTok, MacTree};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InstantiateTplCall {
|
||||
pub(crate) tpl: MacTree,
|
||||
pub(crate) argc: usize,
|
||||
pub(crate) argv: Vec<MacTree>,
|
||||
}
|
||||
impl Atomic for InstantiateTplCall {
|
||||
type Variant = OwnedVariant;
|
||||
type Data = ();
|
||||
}
|
||||
impl OwnedAtom for InstantiateTplCall {
|
||||
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||
/// TODO: get serialization done for mactree
|
||||
type Refs = Vec<Expr>;
|
||||
async fn serialize(
|
||||
&self,
|
||||
ctx: SysCtx,
|
||||
write: Pin<&mut (impl AsyncWrite + ?Sized)>,
|
||||
) -> Self::Refs {
|
||||
todo!()
|
||||
}
|
||||
async fn deserialize(ctx: impl DeserializeCtx, refs: Self::Refs) -> Self { todo!() }
|
||||
// Technically must be supported but shouldn't actually ever be called
|
||||
async fn call_ref(&self, arg: Expr) -> GExpr {
|
||||
eprintln!(
|
||||
"Copying partially applied instantiate_tpl call. This is an internal value.\
|
||||
\nIt should be fully consumed within generated code."
|
||||
);
|
||||
self.clone().call(arg).await
|
||||
}
|
||||
async fn call(mut self, arg: Expr) -> GExpr {
|
||||
let arg = match TypAtom::try_from_expr(arg).await {
|
||||
Err(e) => return Err::<Never, _>(e).to_expr(),
|
||||
Ok(t) => get_own_instance(t).await,
|
||||
};
|
||||
self.argv.push(arg);
|
||||
if self.argv.len() < self.argc {
|
||||
return self.to_expr();
|
||||
}
|
||||
instantiate_tpl(&self.tpl, &mut self.argv.into_iter(), &mut false).to_expr()
|
||||
}
|
||||
}
|
||||
fn instantiate_tpl(
|
||||
tpl: &MacTree,
|
||||
argv: &mut impl Iterator<Item = MacTree>,
|
||||
changed: &mut bool,
|
||||
) -> MacTree {
|
||||
let tok = match &*tpl.tok {
|
||||
MacTok::Slot => {
|
||||
*changed = true;
|
||||
return argv.next().expect("Not enough arguments to fill all slots!");
|
||||
},
|
||||
MacTok::Lambda(arg, body) => MacTok::Lambda(
|
||||
ro(changed, |changed| instantiate_tpl(arg, argv, changed)),
|
||||
instantiate_tpl_v(body, argv, changed),
|
||||
),
|
||||
MacTok::Name(_) | MacTok::Value(_) => return tpl.clone(),
|
||||
MacTok::Ph(_) => panic!("instantiate_tpl received a placeholder"),
|
||||
MacTok::S(p, body) => MacTok::S(*p, instantiate_tpl_v(body, argv, changed)),
|
||||
};
|
||||
if *changed { MacTree { pos: tpl.pos.clone(), tok: Rc::new(tok) } } else { tpl.clone() }
|
||||
}
|
||||
fn instantiate_tpl_v(
|
||||
tpl: &[MacTree],
|
||||
argv: &mut impl Iterator<Item = MacTree>,
|
||||
changed: &mut bool,
|
||||
) -> Vec<MacTree> {
|
||||
tpl.iter().map(|tree| ro(changed, |changed| instantiate_tpl(tree, argv, changed))).collect_vec()
|
||||
}
|
||||
|
||||
/// reverse "or". Inside, the flag is always false, but raising it will raise
|
||||
/// the outside flag too.
|
||||
fn ro<T>(flag: &mut bool, cb: impl FnOnce(&mut bool) -> T) -> T {
|
||||
let mut new_flag = false;
|
||||
let val = cb(&mut new_flag);
|
||||
*flag |= new_flag;
|
||||
val
|
||||
}
|
||||
59
orchid-std/src/macros/let_line.rs
Normal file
59
orchid-std/src/macros/let_line.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
use futures::future::LocalBoxFuture;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::{OrcRes, mk_errv};
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::parse::{Comment, ParseCtx, Parsed, expect_tok, token_errv, try_pop_no_fluff};
|
||||
use orchid_extension::gen_expr::GExpr;
|
||||
use orchid_extension::parser::{
|
||||
ConstCtx, GenSnippet, ParsCtx, ParsedLine, ParsedLineKind, ParsedMem, ParsedMemKind, Parser,
|
||||
};
|
||||
use substack::Substack;
|
||||
|
||||
type ExprGenerator =
|
||||
Box<dyn for<'a> FnOnce(ConstCtx, Substack<'a, Sym>) -> LocalBoxFuture<'a, GExpr>>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LetLine;
|
||||
impl Parser for LetLine {
|
||||
const LINE_HEAD: &'static str = "let";
|
||||
async fn parse<'a>(
|
||||
ctx: ParsCtx<'a>,
|
||||
exported: bool,
|
||||
comments: Vec<Comment>,
|
||||
line: GenSnippet<'a>,
|
||||
) -> OrcRes<Vec<ParsedLine>> {
|
||||
let Parsed { output: name_tok, tail } = try_pop_no_fluff(&ctx, line).await?;
|
||||
let Some(name) = name_tok.as_name() else {
|
||||
let err = token_errv(&ctx, name_tok, "Constant must have a name", |t| {
|
||||
format!("Expected a name but found {t}")
|
||||
});
|
||||
return Err(err.await);
|
||||
};
|
||||
let Parsed { tail, .. } = expect_tok(&ctx, tail, ctx.i().i("=").await).await?;
|
||||
fn do_tokv(line: GenSnippet<'_>) -> ExprGenerator {
|
||||
let first: ExprGenerator = if let Some((idx, arg)) =
|
||||
line.iter().enumerate().find_map(|(i, x)| Some((i, x.as_lambda()?)))
|
||||
{
|
||||
Box::new(move |ctx, stack| Box::pin(async move {
|
||||
let name = ctx.names([])
|
||||
}))
|
||||
} else {
|
||||
|
||||
};
|
||||
todo!()
|
||||
}
|
||||
let expr_generator = do_tokv(tail);
|
||||
Ok(vec![ParsedLine {
|
||||
comments,
|
||||
sr: line.sr(),
|
||||
kind: ParsedLineKind::Mem(ParsedMem {
|
||||
exported,
|
||||
name,
|
||||
kind: ParsedMemKind::cnst(async |ctx| expr_generator(ctx, Substack::Bottom).await),
|
||||
}),
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
||||
fn update_names(tree: MacTree)
|
||||
20
orchid-std/src/macros/macro_lib.rs
Normal file
20
orchid-std/src/macros/macro_lib.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use orchid_extension::atom::TypAtom;
|
||||
use orchid_extension::atom_owned::get_own_instance;
|
||||
use orchid_extension::tree::{GenMember, comments, fun, prefix};
|
||||
|
||||
use crate::Int;
|
||||
use crate::macros::instantiate_tpl::InstantiateTplCall;
|
||||
use crate::macros::mactree::MacTree;
|
||||
|
||||
pub fn gen_macro_lib() -> Vec<GenMember> {
|
||||
prefix("macros", [comments(
|
||||
["This is an internal function, you can't obtain a value of its argument type.", "hidden"],
|
||||
fun(true, "instantiate_tpl", |tpl: TypAtom<MacTree>, right: Int| async move {
|
||||
InstantiateTplCall {
|
||||
tpl: get_own_instance(tpl).await,
|
||||
argc: right.0.try_into().unwrap(),
|
||||
argv: Vec::new(),
|
||||
}
|
||||
}),
|
||||
)])
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
use never::Never;
|
||||
use orchid_base::interner::Interner;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::reqnot::Receipt;
|
||||
use orchid_extension::atom::AtomDynfo;
|
||||
use orchid_extension::entrypoint::ExtReq;
|
||||
use orchid_extension::fs::DeclFs;
|
||||
use orchid_extension::lexer::LexerObj;
|
||||
use orchid_extension::parser::ParserObj;
|
||||
use orchid_extension::system::{System, SystemCard};
|
||||
use orchid_extension::system_ctor::SystemCtor;
|
||||
use orchid_extension::tree::GenMember;
|
||||
|
||||
use crate::macros::let_line::LetLine;
|
||||
use crate::macros::macro_lib::gen_macro_lib;
|
||||
use crate::macros::mactree_lexer::MacTreeLexer;
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -27,8 +30,8 @@ impl SystemCard for MacroSystem {
|
||||
}
|
||||
impl System for MacroSystem {
|
||||
async fn request(_: ExtReq<'_>, req: Self::Req) -> Receipt<'_> { match req {} }
|
||||
fn vfs() -> orchid_extension::fs::DeclFs { DeclFs::Mod(&[]) }
|
||||
async fn prelude(_: &Interner) -> Vec<Sym> { vec![] }
|
||||
fn lexers() -> Vec<LexerObj> { vec![&MacTreeLexer] }
|
||||
fn parsers() -> Vec<ParserObj> { vec![] }
|
||||
fn env() -> Vec<GenMember> { vec![] }
|
||||
fn parsers() -> Vec<ParserObj> { vec![&LetLine] }
|
||||
fn env() -> Vec<GenMember> { gen_macro_lib() }
|
||||
}
|
||||
|
||||
@@ -39,7 +39,9 @@ pub enum MacTok {
|
||||
/// Only permitted in arguments to `instantiate_tpl`
|
||||
Slot,
|
||||
Value(Expr),
|
||||
Lambda(Vec<MacTree>, Vec<MacTree>),
|
||||
Lambda(MacTree, Vec<MacTree>),
|
||||
/// Only permitted in "pattern" values produced by macro blocks, which are
|
||||
/// never accessed as variables by usercode
|
||||
Ph(Ph),
|
||||
}
|
||||
impl Format for MacTok {
|
||||
@@ -50,7 +52,7 @@ impl Format for MacTok {
|
||||
tl_cache!(Rc<Variants>: Rc::new(Variants::default()
|
||||
.unbounded("\\{0b}.{1l}")
|
||||
.bounded("(\\{0b}.{1b})"))),
|
||||
[mtreev_fmt(arg, c).await, mtreev_fmt(b, c).await],
|
||||
[arg.print(c).await, mtreev_fmt(b, c).await],
|
||||
),
|
||||
Self::Name(n) => format!("{n}").into(),
|
||||
Self::Ph(ph) => format!("{ph}").into(),
|
||||
@@ -96,3 +98,41 @@ pub enum PhKind {
|
||||
Scalar,
|
||||
Vector { at_least_one: bool, priority: u8 },
|
||||
}
|
||||
|
||||
pub fn map_mactree(
|
||||
tpl: &MacTree,
|
||||
map: &mut impl FnMut(MacTree) -> Option<MacTree>,
|
||||
argv: &mut impl Iterator<Item = MacTree>,
|
||||
changed: &mut bool,
|
||||
) -> MacTree {
|
||||
let tok = match &*tpl.tok {
|
||||
MacTok::Slot => {
|
||||
*changed = true;
|
||||
return argv.next().expect("Not enough arguments to fill all slots!");
|
||||
},
|
||||
MacTok::Lambda(arg, body) => MacTok::Lambda(
|
||||
ro(changed, |changed| instantiate_tpl(arg, argv, changed)),
|
||||
instantiate_tpl_v(body, argv, changed),
|
||||
),
|
||||
MacTok::Name(_) | MacTok::Value(_) => return tpl.clone(),
|
||||
MacTok::Ph(_) => panic!("instantiate_tpl received a placeholder"),
|
||||
MacTok::S(p, body) => MacTok::S(*p, instantiate_tpl_v(body, argv, changed)),
|
||||
};
|
||||
if *changed { MacTree { pos: tpl.pos.clone(), tok: Rc::new(tok) } } else { tpl.clone() }
|
||||
}
|
||||
pub fn map_mactree_v(
|
||||
tpl: &[MacTree],
|
||||
argv: &mut impl Iterator<Item = MacTree>,
|
||||
changed: &mut bool,
|
||||
) -> Vec<MacTree> {
|
||||
tpl.iter().map(|tree| ro(changed, |changed| instantiate_tpl(tree, argv, changed))).collect_vec()
|
||||
}
|
||||
|
||||
/// reverse "or". Inside, the flag is always false, but raising it will raise
|
||||
/// the outside flag too.
|
||||
fn ro<T>(flag: &mut bool, cb: impl FnOnce(&mut bool) -> T) -> T {
|
||||
let mut new_flag = false;
|
||||
let val = cb(&mut new_flag);
|
||||
*flag |= new_flag;
|
||||
val
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
mod instantiate_tpl;
|
||||
mod let_line;
|
||||
mod macro_lib;
|
||||
mod macro_system;
|
||||
pub mod mactree;
|
||||
mod mactree_lexer;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use never::Never;
|
||||
use orchid_base::interner::Interner;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::reqnot::Receipt;
|
||||
use orchid_base::sym;
|
||||
use orchid_extension::atom::{AtomDynfo, AtomicFeatures};
|
||||
use orchid_extension::entrypoint::ExtReq;
|
||||
use orchid_extension::lexer::LexerObj;
|
||||
@@ -36,4 +39,5 @@ impl System for StdSystem {
|
||||
fn lexers() -> Vec<LexerObj> { vec![&StringLexer, &NumLexer] }
|
||||
fn parsers() -> Vec<ParserObj> { vec![] }
|
||||
fn env() -> Vec<GenMember> { merge_trivial([gen_num_lib(), gen_str_lib()]) }
|
||||
async fn prelude(i: &Interner) -> Vec<Sym> { vec![sym!(std; i).await] }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user