forked from Orchid/orchid
Added support for defining macros in Rust within the macro system
Also fixed a lot of bugs
This commit is contained in:
@@ -10,10 +10,10 @@ use std::rc::Rc;
|
||||
use async_fn_stream::try_stream;
|
||||
use camino::Utf8PathBuf;
|
||||
use clap::{Parser, Subcommand};
|
||||
use futures::{Stream, TryStreamExt, io};
|
||||
use futures::{FutureExt, Stream, TryStreamExt, io};
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::Reporter;
|
||||
use orchid_base::format::{FmtCtxImpl, Format, take_first};
|
||||
use orchid_base::format::{FmtCtxImpl, Format, fmt, take_first};
|
||||
use orchid_base::location::SrcRange;
|
||||
use orchid_base::logging::{LogStrategy, Logger};
|
||||
use orchid_base::name::{NameLike, VPath};
|
||||
@@ -29,6 +29,7 @@ use orchid_host::parse::{HostParseCtxImpl, parse_item, parse_items};
|
||||
use orchid_host::parsed::{Item, ItemKind, ParsTokTree, ParsedMember, ParsedModule};
|
||||
use orchid_host::subprocess::ext_command;
|
||||
use orchid_host::system::init_systems;
|
||||
use orchid_host::tree::{MemberKind, Module, RootData};
|
||||
use substack::Substack;
|
||||
use tokio::io::{AsyncBufReadExt, BufReader, stdin};
|
||||
use tokio::task::{LocalSet, spawn_local};
|
||||
@@ -61,6 +62,12 @@ pub enum Commands {
|
||||
file: Utf8PathBuf,
|
||||
},
|
||||
Repl,
|
||||
ModTree {
|
||||
#[arg(long)]
|
||||
proj: Option<Utf8PathBuf>,
|
||||
#[arg(long)]
|
||||
prefix: Option<String>,
|
||||
},
|
||||
Exec {
|
||||
#[arg(long)]
|
||||
proj: Option<Utf8PathBuf>,
|
||||
@@ -226,6 +233,53 @@ async fn main() -> io::Result<ExitCode> {
|
||||
}
|
||||
}
|
||||
},
|
||||
Commands::ModTree { proj, prefix } => {
|
||||
let reporter = Reporter::new();
|
||||
let (mut root, _systems) = init_systems(&args.system, &extensions).await.unwrap();
|
||||
if let Some(proj_path) = proj {
|
||||
let path = proj_path.into_std_path_buf();
|
||||
match parse_folder(&root, path, sym!(src; i).await, &reporter, ctx.clone()).await {
|
||||
Ok(r) => root = r,
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
*exit_code1.borrow_mut() = ExitCode::FAILURE;
|
||||
return;
|
||||
},
|
||||
}
|
||||
}
|
||||
let prefix = match prefix {
|
||||
Some(pref) => VPath::parse(&pref, i).await,
|
||||
None => VPath::new([]),
|
||||
};
|
||||
let root_data = root.0.read().await;
|
||||
print_mod(&root_data.root, prefix, &root_data).await;
|
||||
async fn print_mod(module: &Module, path: VPath, root: &RootData) {
|
||||
let indent = " ".repeat(path.len());
|
||||
for (key, tgt) in &module.imports {
|
||||
match tgt {
|
||||
Ok(tgt) => println!("{indent}import {key} => {}", tgt.target),
|
||||
Err(opts) => println!(
|
||||
"{indent}import {key} conflicts between {}",
|
||||
opts.iter().map(|i| &i.target).join(" ")
|
||||
),
|
||||
}
|
||||
}
|
||||
for (key, mem) in &module.members {
|
||||
let new_path = path.clone().name_with_suffix(key.clone()).to_sym(&root.ctx.i).await;
|
||||
match mem.kind(root.ctx.clone(), &root.consts).await {
|
||||
MemberKind::Module(module) => {
|
||||
println!("{indent}module {key} {{");
|
||||
print_mod(module, VPath::new(new_path.segs()), root).boxed_local().await;
|
||||
println!("{indent}}}")
|
||||
},
|
||||
MemberKind::Const => {
|
||||
let value = root.consts.get(&new_path).expect("Missing const!");
|
||||
println!("{indent}const {key} = {}", fmt(value, &root.ctx.i).await)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Commands::Exec { proj, code } => {
|
||||
let reporter = Reporter::new();
|
||||
let path = sym!(usercode; i).await;
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use futures::FutureExt;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::{OrcRes, Reporter, async_io_err, mk_errv, os_str_to_string};
|
||||
use orchid_base::error::{OrcRes, Reporter, async_io_err, os_str_to_string};
|
||||
use orchid_base::location::SrcRange;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::parse::Snippet;
|
||||
@@ -29,16 +29,6 @@ pub async fn parse_folder(
|
||||
async fn recur(path: &Path, ns: Sym, rep: &Reporter, ctx: Ctx) -> OrcRes<Option<ParsedModule>> {
|
||||
let sr = SrcRange::new(0..0, &ns);
|
||||
if path.is_dir() {
|
||||
let Some(name_os) = path.file_name() else {
|
||||
return Err(mk_errv(
|
||||
ctx.i.i("Could not read directory name").await,
|
||||
format!("Path {} ends in ..", path.to_string_lossy()),
|
||||
[sr],
|
||||
));
|
||||
};
|
||||
let name = ctx.i.i(os_str_to_string(name_os, &ctx.i, [sr]).await?).await;
|
||||
let ns = ns.suffix([name.clone()], &ctx.i).await;
|
||||
let sr = SrcRange::new(0..0, &ns);
|
||||
let mut items = Vec::new();
|
||||
let mut stream = match fs::read_dir(path).await {
|
||||
Err(err) => return Err(async_io_err(err, &ctx.i, [sr]).await),
|
||||
@@ -53,6 +43,10 @@ pub async fn parse_folder(
|
||||
continue;
|
||||
},
|
||||
};
|
||||
let os_name = entry.path().file_stem().expect("File name could not be read").to_owned();
|
||||
let name = ctx.i.i(os_str_to_string(&os_name, &ctx.i, [sr.clone()]).await?).await;
|
||||
let ns = ns.suffix([name.clone()], &ctx.i).await;
|
||||
let sr = SrcRange::new(0..0, &ns);
|
||||
match recur(&entry.path(), ns.clone(), rep, ctx.clone()).boxed_local().await {
|
||||
Err(e) => {
|
||||
rep.report(e);
|
||||
@@ -64,10 +58,6 @@ pub async fn parse_folder(
|
||||
}
|
||||
Ok(Some(ParsedModule::new(false, items)))
|
||||
} else if path.extension() == Some(OsStr::new("orc")) {
|
||||
let name_os = path.file_stem().expect("If there is an extension, there must be a stem");
|
||||
let name = ctx.i.i(os_str_to_string(name_os, &ctx.i, [sr]).await?).await;
|
||||
let ns = ns.suffix([name], &ctx.i).await;
|
||||
let sr = SrcRange::new(0..0, &ns);
|
||||
let mut file = match File::open(path).await {
|
||||
Err(e) => return Err(async_io_err(e, &ctx.i, [sr]).await),
|
||||
Ok(file) => file,
|
||||
|
||||
Reference in New Issue
Block a user