forked from Orchid/orchid
First steps for the macro system
This commit is contained in:
156
orcx/src/main.rs
156
orcx/src/main.rs
@@ -13,22 +13,24 @@ use async_stream::try_stream;
|
||||
use camino::Utf8PathBuf;
|
||||
use clap::{Parser, Subcommand};
|
||||
use futures::{Stream, TryStreamExt, io};
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::Reporter;
|
||||
use orchid_base::format::{FmtCtxImpl, Format, take_first};
|
||||
use orchid_base::location::SrcRange;
|
||||
use orchid_base::logging::{LogStrategy, Logger};
|
||||
use orchid_base::parse::Snippet;
|
||||
use orchid_base::name::{NameLike, VPath};
|
||||
use orchid_base::parse::{Import, Snippet};
|
||||
use orchid_base::sym;
|
||||
use orchid_base::tree::ttv_fmt;
|
||||
use orchid_base::tree::{Token, ttv_fmt};
|
||||
use orchid_host::ctx::Ctx;
|
||||
use orchid_host::execute::{ExecCtx, ExecResult};
|
||||
use orchid_host::expr::PathSetBuilder;
|
||||
use orchid_host::expr::ExprKind;
|
||||
use orchid_host::extension::Extension;
|
||||
use orchid_host::lex::lex;
|
||||
use orchid_host::parse::{HostParseCtxImpl, parse_expr, parse_items};
|
||||
use orchid_host::parsed::{Item, ItemKind, ParsedMember, ParsedMemberKind, ParsedModule};
|
||||
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::Root;
|
||||
use substack::Substack;
|
||||
use tokio::task::{LocalSet, spawn_local};
|
||||
|
||||
@@ -147,56 +149,90 @@ async fn main() -> io::Result<ExitCode> {
|
||||
println!("{}", take_first(&item.print(&FmtCtxImpl { i }).await, true))
|
||||
}
|
||||
},
|
||||
Commands::Repl => loop {
|
||||
let (root, systems) = init_systems(&args.system, &extensions).await.unwrap();
|
||||
print!("\\.> ");
|
||||
std::io::stdout().flush().unwrap();
|
||||
let mut prompt = String::new();
|
||||
stdin().read_line(&mut prompt).await.unwrap();
|
||||
eprintln!("lexing");
|
||||
let lexemes =
|
||||
lex(i.i(prompt.trim()).await, sym!(usercode; i).await, &systems, ctx).await.unwrap();
|
||||
eprintln!("lexed");
|
||||
if args.logs {
|
||||
println!("lexed: {}", take_first(&ttv_fmt(&lexemes, &FmtCtxImpl { i }).await, true));
|
||||
}
|
||||
let path = sym!(usercode; i).await;
|
||||
let reporter = Reporter::new();
|
||||
let parse_ctx = HostParseCtxImpl {
|
||||
ctx: ctx.clone(),
|
||||
rep: &reporter,
|
||||
src: path.clone(),
|
||||
systems: &systems[..],
|
||||
};
|
||||
let parse_res = parse_expr(
|
||||
&parse_ctx,
|
||||
path.clone(),
|
||||
PathSetBuilder::new(),
|
||||
Snippet::new(&lexemes[0], &lexemes),
|
||||
)
|
||||
.await;
|
||||
eprintln!("parsed");
|
||||
let expr = match reporter.merge(parse_res) {
|
||||
Ok(expr) => expr,
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
Commands::Repl => {
|
||||
let mut counter = 0;
|
||||
let mut imports = Vec::new();
|
||||
let usercode_path = sym!(usercode; i).await;
|
||||
loop {
|
||||
counter += 1;
|
||||
let (mut root, systems) = init_systems(&args.system, &extensions).await.unwrap();
|
||||
print!("\\.> ");
|
||||
std::io::stdout().flush().unwrap();
|
||||
let mut prompt = String::new();
|
||||
stdin().read_line(&mut prompt).await.unwrap();
|
||||
let name = i.i(&format!("_{counter}")).await;
|
||||
let path = usercode_path.suffix([name.clone()], i).await;
|
||||
let mut lexemes =
|
||||
lex(i.i(prompt.trim()).await, path.clone(), &systems, ctx).await.unwrap();
|
||||
let Some(discr) = lexemes.first() else { continue };
|
||||
if args.logs {
|
||||
println!("lexed: {}", take_first(&ttv_fmt(&lexemes, &FmtCtxImpl { i }).await, true));
|
||||
}
|
||||
let prefix_sr = SrcRange::zw(path.clone(), 0);
|
||||
let process_lexemes = async |lexemes: &[ParsTokTree]| {
|
||||
let snippet = Snippet::new(&lexemes[0], lexemes);
|
||||
let reporter = Reporter::new();
|
||||
let parse_ctx = HostParseCtxImpl {
|
||||
ctx: ctx.clone(),
|
||||
rep: &reporter,
|
||||
src: path.clone(),
|
||||
systems: &systems[..],
|
||||
};
|
||||
let parse_result = parse_item(&parse_ctx, Substack::Bottom, vec![], snippet).await;
|
||||
match reporter.merge(parse_result) {
|
||||
Ok(items) => Some(items),
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
None
|
||||
},
|
||||
}
|
||||
};
|
||||
let add_imports = |items: &mut Vec<Item>, imports: &[Import]| {
|
||||
items.extend(imports.iter().map(|import| Item::new(import.sr.clone(), import.clone())));
|
||||
};
|
||||
if discr.is_kw(i.i("import").await) {
|
||||
let Some(import_lines) = process_lexemes(&lexemes).await else { continue };
|
||||
imports.extend(import_lines.into_iter().map(|it| match it.kind {
|
||||
ItemKind::Import(imp) => imp,
|
||||
_ => panic!("Expected imports from import line"),
|
||||
}));
|
||||
continue;
|
||||
},
|
||||
};
|
||||
let mut xctx = ExecCtx::new(ctx.clone(), logger.clone(), root.clone(), expr).await;
|
||||
eprintln!("executed");
|
||||
xctx.set_gas(Some(1000));
|
||||
xctx.execute().await;
|
||||
match xctx.result() {
|
||||
ExecResult::Value(val) =>
|
||||
println!("{}", take_first(&val.print(&FmtCtxImpl { i }).await, false)),
|
||||
ExecResult::Err(e) => println!("error: {e}"),
|
||||
ExecResult::Gas(_) => println!("Ran out of gas!"),
|
||||
}
|
||||
if !discr.is_kw(i.i("let").await) {
|
||||
let prefix = [i.i("export").await, i.i("let").await, name.clone(), i.i("=").await];
|
||||
lexemes.splice(0..0, prefix.map(|n| Token::Name(n).at(prefix_sr.clone())));
|
||||
}
|
||||
let Some(mut new_lines) = process_lexemes(&lexemes).await else { continue };
|
||||
let const_decl = new_lines.iter().exactly_one().expect("Multiple lines from let");
|
||||
let input_sr = const_decl.sr.map_range(|_| 0..0);
|
||||
let const_name = match &const_decl.kind {
|
||||
ItemKind::Member(ParsedMember { name: const_name, .. }) => const_name.clone(),
|
||||
_ => panic!("Expected exactly one constant declaration from let"),
|
||||
};
|
||||
add_imports(&mut new_lines, &imports);
|
||||
imports.push(Import::new(input_sr.clone(), VPath::new(path.segs()), const_name.clone()));
|
||||
let new_module = ParsedModule::new(true, new_lines);
|
||||
let reporter = Reporter::new();
|
||||
root = root.add_parsed(&new_module, path.clone(), &reporter).await;
|
||||
eprintln!("parsed");
|
||||
let entrypoint =
|
||||
ExprKind::Const(path.suffix([const_name.clone()], i).await).at(input_sr.pos());
|
||||
let mut xctx = ExecCtx::new(ctx.clone(), logger.clone(), root.clone(), entrypoint).await;
|
||||
eprintln!("executed");
|
||||
xctx.set_gas(Some(1000));
|
||||
xctx.execute().await;
|
||||
match xctx.result() {
|
||||
ExecResult::Value(val) =>
|
||||
println!("{const_name} = {}", take_first(&val.print(&FmtCtxImpl { i }).await, false)),
|
||||
ExecResult::Err(e) => println!("error: {e}"),
|
||||
ExecResult::Gas(_) => println!("Ran out of gas!"),
|
||||
}
|
||||
}
|
||||
},
|
||||
Commands::Execute { proj, code } => {
|
||||
let reporter = Reporter::new();
|
||||
let path = sym!(usercode::entrypoint; i).await;
|
||||
let prefix_sr = SrcRange::zw(path.clone(), 0);
|
||||
let (mut root, systems) = init_systems(&args.system, &extensions).await.unwrap();
|
||||
if let Some(proj_path) = proj {
|
||||
let path = PathBuf::from(proj_path.into_std_path_buf());
|
||||
@@ -209,8 +245,7 @@ async fn main() -> io::Result<ExitCode> {
|
||||
},
|
||||
}
|
||||
}
|
||||
let lexemes = lex(i.i(code.trim()).await, path.clone(), &systems, ctx).await.unwrap();
|
||||
let snippet = Snippet::new(&lexemes[0], &lexemes);
|
||||
let mut lexemes = lex(i.i(code.trim()).await, path.clone(), &systems, ctx).await.unwrap();
|
||||
if args.logs {
|
||||
println!("lexed: {}", take_first(&ttv_fmt(&lexemes, &FmtCtxImpl { i }).await, true));
|
||||
}
|
||||
@@ -220,21 +255,22 @@ async fn main() -> io::Result<ExitCode> {
|
||||
src: path.clone(),
|
||||
systems: &systems[..],
|
||||
};
|
||||
let parse_res = parse_expr(&parse_ctx, path.clone(), PathSetBuilder::new(), snippet).await;
|
||||
let expr = match reporter.merge(parse_res) {
|
||||
Ok(expr) => expr,
|
||||
let prefix =
|
||||
[i.i("export").await, i.i("let").await, i.i("entrypoint").await, i.i("=").await];
|
||||
lexemes.splice(0..0, prefix.map(|n| Token::Name(n).at(prefix_sr.clone())));
|
||||
let snippet = Snippet::new(&lexemes[0], &lexemes);
|
||||
let parse_res = parse_item(&parse_ctx, Substack::Bottom, vec![], snippet).await;
|
||||
let entrypoint = match reporter.merge(parse_res) {
|
||||
Ok(items) => ParsedModule::new(true, items),
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
*exit_code1.borrow_mut() = ExitCode::FAILURE;
|
||||
return;
|
||||
},
|
||||
};
|
||||
let parsed_root = ParsedModule::new(true, [Item::new(
|
||||
snippet.sr(),
|
||||
ParsedMember::new(true, i.i("entrypoint").await, expr.clone()),
|
||||
)]);
|
||||
let reporter = Reporter::new();
|
||||
let root = root.add_parsed(&parsed_root, sym!(usercode; i).await, &reporter).await;
|
||||
let root = root.add_parsed(&entrypoint, path.clone(), &reporter).await;
|
||||
let expr = ExprKind::Const(sym!(usercode::entrypoint; i).await).at(prefix_sr.pos());
|
||||
let mut xctx = ExecCtx::new(ctx.clone(), logger.clone(), root, expr).await;
|
||||
xctx.set_gas(Some(1000));
|
||||
xctx.execute().await;
|
||||
|
||||
@@ -39,7 +39,7 @@ pub async fn parse_folder(
|
||||
));
|
||||
};
|
||||
let name = ctx.i.i(os_str_to_string(name_os, &ctx.i, [sr]).await?).await;
|
||||
let ns = ns.push(name.clone(), &ctx.i).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 {
|
||||
@@ -67,7 +67,7 @@ pub async fn parse_folder(
|
||||
} 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.push(name, &ctx.i).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),
|
||||
|
||||
Reference in New Issue
Block a user