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:
2025-07-31 00:30:41 +02:00
parent 19f2c6426a
commit 769c6cfc9f
31 changed files with 450 additions and 250 deletions

View File

@@ -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]

View File

@@ -1,4 +1,4 @@
// mod macros;
mod macros;
mod std;
pub use std::number::num_atom::{Float, HomoArray, Int, Num};

View 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
}

View 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)

View 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(),
}
}),
)])
}

View File

@@ -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() }
}

View File

@@ -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
}

View File

@@ -1,3 +1,6 @@
mod instantiate_tpl;
mod let_line;
mod macro_lib;
mod macro_system;
pub mod mactree;
mod mactree_lexer;

View File

@@ -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] }
}