forked from Orchid/orchid
Infra for debugging and testing
This commit is contained in:
@@ -1,2 +1,8 @@
|
|||||||
[alias]
|
[alias]
|
||||||
xtask = "run --quiet --package xtask --"
|
xtask = "run --quiet --package xtask --"
|
||||||
|
orcx = "xtask orcx"
|
||||||
|
|
||||||
|
[env]
|
||||||
|
ORCHID_EXTENSIONS = "target/debug/orchid-std"
|
||||||
|
ORCHID_DEFAULT_SYSTEMS = "orchid::std"
|
||||||
|
ORCHID_LOG_BUFFERS = "true"
|
||||||
|
|||||||
@@ -1,5 +1,2 @@
|
|||||||
[System.Environment]::SetEnvironmentVariable("ORCHID_LOG_BUFFERS", "true")
|
|
||||||
cargo build -p orchid-std
|
cargo build -p orchid-std
|
||||||
cargo run -p orcx -- `
|
cargo run -p orcx -- lex --file .\examples\hello-world\main.orc
|
||||||
--extension .\target\debug\orchid-std.exe --system orchid::std `
|
|
||||||
lex --file .\examples\hello-world\main.orc
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ use async_std::channel::{Receiver, Sender};
|
|||||||
use async_std::stream;
|
use async_std::stream;
|
||||||
use async_std::sync::Mutex;
|
use async_std::sync::Mutex;
|
||||||
use futures::future::{LocalBoxFuture, join_all};
|
use futures::future::{LocalBoxFuture, join_all};
|
||||||
use futures::task::LocalSpawn;
|
|
||||||
use futures::{FutureExt, StreamExt};
|
use futures::{FutureExt, StreamExt};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
async-stream = "0.3.6"
|
async-stream = "0.3.6"
|
||||||
camino = "1.1.9"
|
camino = "1.1.9"
|
||||||
clap = { version = "4.5.24", features = ["derive"] }
|
clap = { version = "4.5.24", features = ["derive", "env"] }
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
orchid-base = { version = "0.1.0", path = "../orchid-base" }
|
orchid-base = { version = "0.1.0", path = "../orchid-base" }
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::process::Command;
|
use std::process::{Command, ExitCode};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use async_stream::try_stream;
|
use async_stream::try_stream;
|
||||||
@@ -16,7 +16,7 @@ use orchid_base::tree::ttv_fmt;
|
|||||||
use orchid_host::ctx::Ctx;
|
use orchid_host::ctx::Ctx;
|
||||||
use orchid_host::extension::Extension;
|
use orchid_host::extension::Extension;
|
||||||
use orchid_host::lex::lex;
|
use orchid_host::lex::lex;
|
||||||
use orchid_host::parse::{self, ParseCtx, ParseCtxImpl, parse_items};
|
use orchid_host::parse::{ParseCtxImpl, parse_items};
|
||||||
use orchid_host::subprocess::ext_command;
|
use orchid_host::subprocess::ext_command;
|
||||||
use orchid_host::system::init_systems;
|
use orchid_host::system::init_systems;
|
||||||
use substack::Substack;
|
use substack::Substack;
|
||||||
@@ -25,9 +25,9 @@ use tokio::task::{LocalSet, spawn_local};
|
|||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version, about, long_about)]
|
#[command(version, about, long_about)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
#[arg(short, long)]
|
#[arg(short, long, env = "ORCHID_EXTENSIONS", value_delimiter = ';')]
|
||||||
extension: Vec<Utf8PathBuf>,
|
extension: Vec<Utf8PathBuf>,
|
||||||
#[arg(short, long)]
|
#[arg(short, long, env = "ORCHID_DEFAULT_SYSTEMS", value_delimiter = ';')]
|
||||||
system: Vec<String>,
|
system: Vec<String>,
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: Commands,
|
command: Commands,
|
||||||
@@ -51,7 +51,12 @@ fn get_all_extensions<'a>(
|
|||||||
ctx: &'a Ctx,
|
ctx: &'a Ctx,
|
||||||
) -> impl Stream<Item = io::Result<Extension>> + 'a {
|
) -> impl Stream<Item = io::Result<Extension>> + 'a {
|
||||||
try_stream! {
|
try_stream! {
|
||||||
for exe in args.extension.iter() {
|
for ext_path in args.extension.iter() {
|
||||||
|
let exe = if cfg!(windows) {
|
||||||
|
ext_path.with_extension("exe")
|
||||||
|
} else {
|
||||||
|
ext_path.clone()
|
||||||
|
};
|
||||||
let init = ext_command(Command::new(exe.as_os_str()), logger.clone(), ctx.clone()).await
|
let init = ext_command(Command::new(exe.as_os_str()), logger.clone(), ctx.clone()).await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ext = Extension::new(init, logger.clone(), ctx.clone())?;
|
let ext = Extension::new(init, logger.clone(), ctx.clone())?;
|
||||||
@@ -62,7 +67,8 @@ fn get_all_extensions<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn main() {
|
async fn main() -> io::Result<ExitCode> {
|
||||||
|
let mut code = ExitCode::SUCCESS;
|
||||||
LocalSet::new()
|
LocalSet::new()
|
||||||
.run_until(async {
|
.run_until(async {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
@@ -93,11 +99,22 @@ async fn main() {
|
|||||||
let pctx = ParseCtxImpl { reporter: &reporter, systems: &systems };
|
let pctx = ParseCtxImpl { reporter: &reporter, systems: &systems };
|
||||||
let snip = Snippet::new(first, &lexemes, &ctx.i);
|
let snip = Snippet::new(first, &lexemes, &ctx.i);
|
||||||
let ptree = parse_items(&pctx, Substack::Bottom, snip).await.unwrap();
|
let ptree = parse_items(&pctx, Substack::Bottom, snip).await.unwrap();
|
||||||
|
if let Some(errv) = reporter.errv() {
|
||||||
|
eprintln!("{errv}");
|
||||||
|
code = ExitCode::FAILURE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ptree.is_empty() {
|
||||||
|
eprintln!("File empty only after parsing, but no errors were reported");
|
||||||
|
code = ExitCode::FAILURE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
for item in ptree {
|
for item in ptree {
|
||||||
println!("{item:?}")
|
println!("{item:?}")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await;
|
||||||
|
Ok(code)
|
||||||
}
|
}
|
||||||
|
|||||||
48
xtask/src/check_api_refs.rs
Normal file
48
xtask/src/check_api_refs.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::fs::{DirEntry, File};
|
||||||
|
use std::io::{self, Read};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::Args;
|
||||||
|
|
||||||
|
pub fn check_api_refs(_args: &Args) -> io::Result<()> {
|
||||||
|
walk_wsp(&mut |_| Ok(true), &mut |file| {
|
||||||
|
if file.path().extension() == Some(OsStr::new("rs")) && file.file_name() != "lib.rs" {
|
||||||
|
let mut contents = String::new();
|
||||||
|
File::open(file.path())?.read_to_string(&mut contents)?;
|
||||||
|
for (l, line) in contents.lines().enumerate() {
|
||||||
|
if !line.trim().starts_with("use") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let Some(c) = line.find("orchid_api") else { continue };
|
||||||
|
if Some(c) == line.find("orchid_api_") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let dname = file.path().to_string_lossy().to_string();
|
||||||
|
eprintln!("orchid_api imported in {dname} at {};{}", l + 1, c + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_wsp(
|
||||||
|
dir_filter: &mut impl FnMut(&DirEntry) -> io::Result<bool>,
|
||||||
|
file_handler: &mut impl FnMut(DirEntry) -> io::Result<()>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
return recurse(&env::current_dir()?, dir_filter, file_handler);
|
||||||
|
fn recurse(
|
||||||
|
dir: &Path,
|
||||||
|
dir_filter: &mut impl FnMut(&DirEntry) -> io::Result<bool>,
|
||||||
|
file_handler: &mut impl FnMut(DirEntry) -> io::Result<()>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
for file in dir.read_dir()?.collect::<Result<Vec<_>, _>>()? {
|
||||||
|
if file.metadata()?.is_dir() && dir_filter(&file)? {
|
||||||
|
recurse(&file.path(), dir_filter, file_handler)?;
|
||||||
|
}
|
||||||
|
file_handler(file)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
use std::env;
|
mod check_api_refs;
|
||||||
use std::ffi::OsStr;
|
mod orcx;
|
||||||
use std::fs::{DirEntry, File};
|
|
||||||
use std::io::{self, Read};
|
use std::io;
|
||||||
use std::path::Path;
|
|
||||||
use std::process::ExitCode;
|
use std::process::ExitCode;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
use check_api_refs::check_api_refs;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use orcx::orcx;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
@@ -19,51 +20,19 @@ pub struct Args {
|
|||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
CheckApiRefs,
|
CheckApiRefs,
|
||||||
|
Orcx {
|
||||||
|
#[arg(trailing_var_arg = true, num_args = 1..)]
|
||||||
|
subcommand: Vec<String>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static EXIT_OK: AtomicBool = AtomicBool::new(true);
|
pub static EXIT_OK: AtomicBool = AtomicBool::new(true);
|
||||||
|
|
||||||
fn main() -> io::Result<ExitCode> {
|
fn main() -> io::Result<ExitCode> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
match args.command {
|
match &args.command {
|
||||||
Commands::CheckApiRefs => walk_wsp(&mut |_| Ok(true), &mut |file| {
|
Commands::CheckApiRefs => check_api_refs(&args)?,
|
||||||
if file.path().extension() == Some(OsStr::new("rs")) && file.file_name() != "lib.rs" {
|
Commands::Orcx { subcommand } => orcx(&args, subcommand)?,
|
||||||
let mut contents = String::new();
|
|
||||||
File::open(file.path())?.read_to_string(&mut contents)?;
|
|
||||||
for (l, line) in contents.lines().enumerate() {
|
|
||||||
if !line.trim().starts_with("use") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let Some(c) = line.find("orchid_api") else { continue };
|
|
||||||
if Some(c) == line.find("orchid_api_") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let dname = file.path().to_string_lossy().to_string();
|
|
||||||
eprintln!("orchid_api imported in {dname} at {};{}", l + 1, c + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})?,
|
|
||||||
}
|
}
|
||||||
Ok(if EXIT_OK.load(Ordering::Relaxed) { ExitCode::SUCCESS } else { ExitCode::FAILURE })
|
Ok(if EXIT_OK.load(Ordering::Relaxed) { ExitCode::SUCCESS } else { ExitCode::FAILURE })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_wsp(
|
|
||||||
dir_filter: &mut impl FnMut(&DirEntry) -> io::Result<bool>,
|
|
||||||
file_handler: &mut impl FnMut(DirEntry) -> io::Result<()>,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
return recurse(&env::current_dir()?, dir_filter, file_handler);
|
|
||||||
fn recurse(
|
|
||||||
dir: &Path,
|
|
||||||
dir_filter: &mut impl FnMut(&DirEntry) -> io::Result<bool>,
|
|
||||||
file_handler: &mut impl FnMut(DirEntry) -> io::Result<()>,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
for file in dir.read_dir()?.collect::<Result<Vec<_>, _>>()? {
|
|
||||||
if file.metadata()?.is_dir() && dir_filter(&file)? {
|
|
||||||
recurse(&file.path(), dir_filter, file_handler)?;
|
|
||||||
}
|
|
||||||
file_handler(file)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
19
xtask/src/orcx.rs
Normal file
19
xtask/src/orcx.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
|
use crate::{Args, EXIT_OK};
|
||||||
|
|
||||||
|
pub fn orcx(_args: &Args, subcommand: &[String]) -> io::Result<()> {
|
||||||
|
eprintln!("running orcx {}", subcommand.join(" "));
|
||||||
|
let status = Command::new("cargo").args(["build", "-p", "orchid-std"]).status()?;
|
||||||
|
if status.success() {
|
||||||
|
let status = Command::new("cargo")
|
||||||
|
.args(["run", "-p", "orcx", "--"].into_iter().chain(subcommand.iter().map(|s| s.as_str())))
|
||||||
|
.status()?;
|
||||||
|
EXIT_OK.store(status.success(), Ordering::Relaxed);
|
||||||
|
} else {
|
||||||
|
EXIT_OK.store(false, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user