diff --git a/Cargo.lock b/Cargo.lock index d418338f..0318fe95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1712,7 +1712,7 @@ dependencies = [ [[package]] name = "rue-ast" -version = "0.8.0" +version = "0.8.1" dependencies = [ "paste", "rue-parser", @@ -1720,7 +1720,7 @@ dependencies = [ [[package]] name = "rue-cli" -version = "0.8.0" +version = "0.8.1" dependencies = [ "anyhow", "chialisp", @@ -1738,7 +1738,7 @@ dependencies = [ [[package]] name = "rue-compiler" -version = "0.8.0" +version = "0.8.1" dependencies = [ "clvmr", "expect-test", @@ -1763,14 +1763,14 @@ dependencies = [ [[package]] name = "rue-diagnostic" -version = "0.8.0" +version = "0.8.1" dependencies = [ "thiserror 2.0.14", ] [[package]] name = "rue-hir" -version = "0.8.0" +version = "0.8.1" dependencies = [ "derive_more", "expect-test", @@ -1787,14 +1787,14 @@ dependencies = [ [[package]] name = "rue-lexer" -version = "0.8.0" +version = "0.8.1" dependencies = [ "expect-test", ] [[package]] name = "rue-lir" -version = "0.8.0" +version = "0.8.1" dependencies = [ "chialisp", "clvm-traits", @@ -1811,7 +1811,7 @@ dependencies = [ [[package]] name = "rue-lsp" -version = "0.8.0" +version = "0.8.1" dependencies = [ "indexmap", "rowan", @@ -1827,7 +1827,7 @@ dependencies = [ [[package]] name = "rue-options" -version = "0.8.0" +version = "0.8.1" dependencies = [ "serde", "thiserror 2.0.14", @@ -1836,7 +1836,7 @@ dependencies = [ [[package]] name = "rue-parser" -version = "0.8.0" +version = "0.8.1" dependencies = [ "derive_more", "expect-test", @@ -1851,7 +1851,7 @@ dependencies = [ [[package]] name = "rue-tests" -version = "0.8.0" +version = "0.8.1" dependencies = [ "anyhow", "chialisp", @@ -1868,7 +1868,7 @@ dependencies = [ [[package]] name = "rue-types" -version = "0.8.0" +version = "0.8.1" dependencies = [ "clvmr", "derive_more", @@ -1883,7 +1883,7 @@ dependencies = [ [[package]] name = "rue-wasm" -version = "0.8.0" +version = "0.8.1" dependencies = [ "chialisp", "clvmr", diff --git a/Cargo.toml b/Cargo.toml index c0d04494..d34230bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,15 +42,15 @@ cast_possible_truncation = "allow" case_sensitive_file_extension_comparisons = "allow" [workspace.dependencies] -rue-lexer = { path = "crates/rue-lexer", version = "0.8.0" } -rue-parser = { path = "crates/rue-parser", version = "0.8.0" } -rue-diagnostic = { path = "crates/rue-diagnostic", version = "0.8.0" } -rue-ast = { path = "crates/rue-ast", version = "0.8.0" } -rue-compiler = { path = "crates/rue-compiler", version = "0.8.0" } -rue-options = { path = "crates/rue-options", version = "0.8.0" } -rue-lir = { path = "crates/rue-lir", version = "0.8.0" } -rue-hir = { path = "crates/rue-hir", version = "0.8.0" } -rue-types = { path = "crates/rue-types", version = "0.8.0" } +rue-lexer = { path = "crates/rue-lexer", version = "0.8.1" } +rue-parser = { path = "crates/rue-parser", version = "0.8.1" } +rue-diagnostic = { path = "crates/rue-diagnostic", version = "0.8.1" } +rue-ast = { path = "crates/rue-ast", version = "0.8.1" } +rue-compiler = { path = "crates/rue-compiler", version = "0.8.1" } +rue-options = { path = "crates/rue-options", version = "0.8.1" } +rue-lir = { path = "crates/rue-lir", version = "0.8.1" } +rue-hir = { path = "crates/rue-hir", version = "0.8.1" } +rue-types = { path = "crates/rue-types", version = "0.8.1" } anyhow = "1.0.98" clvm-traits = "0.28.1" clvm-utils = "0.28.1" diff --git a/crates/rue-ast/Cargo.toml b/crates/rue-ast/Cargo.toml index 1accaf04..46be2989 100644 --- a/crates/rue-ast/Cargo.toml +++ b/crates/rue-ast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-ast" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "An implementation of the Abstract Syntax Tree for the Rue compiler." diff --git a/crates/rue-cli/Cargo.toml b/crates/rue-cli/Cargo.toml index eecb1735..a8d6f9f2 100644 --- a/crates/rue-cli/Cargo.toml +++ b/crates/rue-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-cli" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "A CLI tool for invoking the Rue compiler." diff --git a/crates/rue-cli/src/main.rs b/crates/rue-cli/src/main.rs index b2b51be8..48a151b6 100644 --- a/crates/rue-cli/src/main.rs +++ b/crates/rue-cli/src/main.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, fs, path::{Path, PathBuf}, process, @@ -17,7 +17,7 @@ use clvmr::{ }; use colored::Colorize; use rue_compiler::{Compiler, FileTree, normalize_path}; -use rue_diagnostic::DiagnosticSeverity; +use rue_diagnostic::{DiagnosticSeverity, SourceKind}; use rue_lir::DebugDialect; use rue_options::{Manifest, find_project}; @@ -35,6 +35,7 @@ pub struct InitArgs { } #[derive(Debug, Parser)] +#[allow(clippy::struct_excessive_bools)] pub struct BuildArgs { file: Option, #[clap(short, long)] @@ -43,8 +44,12 @@ pub struct BuildArgs { debug: bool, #[clap(short = 'x', long)] hex: bool, - #[clap(long)] + #[clap(short, long)] hash: bool, + #[clap(short, long)] + split: bool, + #[clap(short, long)] + all: bool, } #[derive(Debug, Parser)] @@ -109,10 +114,11 @@ fn build(args: BuildArgs) -> Result<()> { process::exit(1); }; - if project.manifest.is_some_and(|manifest| { + if project.manifest.as_ref().is_some_and(|manifest| { manifest .compiler .version + .as_ref() .is_some_and(|version| version != env!("CARGO_PKG_VERSION")) }) { eprintln!("{}", "Project version mismatch".red().bold()); @@ -159,47 +165,208 @@ fn build(args: BuildArgs) -> Result<()> { process::exit(1); } - let program = if let Some(export) = args.export { - let Some(program) = tree - .exports( + if args.all { + if args.export.is_some() { + eprintln!("{}", "Cannot use `--export` with `--all`".red().bold()); + process::exit(1); + } + + let dist_dir = project + .manifest + .as_ref() + .and_then(|manifest| manifest.compiler.dist_dir.clone()) + .map(PathBuf::from); + + if let Some(dist_dir) = &dist_dir + && !dist_dir.exists() + { + fs::create_dir_all(dist_dir)?; + } + + let mut file_names = HashSet::new(); + let mut outputs = HashMap::new(); + + for file in tree.all_files() { + let SourceKind::File(file_path) = &file.source.kind else { + continue; + }; + let file_path = Path::new(file_path); + let file_name = file_path.file_name().unwrap().to_string_lossy().to_string(); + + let exports = tree.exports( &mut ctx, &mut allocator, - file_kind.as_ref(), - Some(&export), + Some(&file.source.kind), + None, &base_path, - )? - .into_iter() - .next() - else { - eprintln!("{}", format!("Export `{export}` not found").red().bold()); + )?; + + let main = tree.main( + &mut ctx, + &mut allocator, + &file.source.kind, + base_path.clone(), + )?; + + let mut exports = if main_kind + .as_ref() + .is_some_and(|main| main == &file.source.kind) + { + exports + .into_iter() + .map(|export| { + ( + if dist_dir.is_some() { + export.name + } else { + format!("{file_name}_{}", export.name) + }, + export.ptr, + ) + }) + .collect::>() + } else { + vec![] + }; + + if let Some(main) = main { + exports.push(( + file_name + .strip_suffix(".rue") + .unwrap_or(&file_name) + .to_string(), + main, + )); + } + + for (name, ptr) in exports { + if dist_dir.is_some() && !file_names.insert(name.clone()) { + eprintln!( + "{}", + format!("Duplicate export with name `{name}`, aborting") + .red() + .bold() + ); + process::exit(1); + } + + let hex = hex::encode(node_to_bytes(&allocator, ptr)?); + + let mut output = String::new(); + + if args.split { + let chars = hex.chars().collect::>(); + let chunks = chars.chunks(64); + for chunk in chunks { + output.push_str(&chunk.iter().collect::()); + output.push('\n'); + } + } else { + output.push_str(&hex); + output.push('\n'); + } + + let path = if let Some(dist_dir) = &dist_dir { + dist_dir + .join(format!("{name}.rue.hex")) + .to_string_lossy() + .to_string() + } else { + file_path + .parent() + .unwrap() + .join(format!("{name}.rue.hex")) + .to_string_lossy() + .to_string() + }; + + outputs.insert(PathBuf::from(path), output); + + if args.hash { + let hash = tree_hash(&allocator, ptr).to_string(); + + let path = if let Some(dist_dir) = &dist_dir { + dist_dir + .join(format!("{name}.rue.hash")) + .to_string_lossy() + .to_string() + } else { + file_path + .parent() + .unwrap() + .join(format!("{name}.rue.hash")) + .to_string_lossy() + .to_string() + }; + + outputs.insert(PathBuf::from(path), format!("{hash}\n")); + } + } + } + + for (path, output) in outputs { + fs::write(path, output)?; + } + } else { + let program = if let Some(export) = args.export { + let Some(program) = tree + .exports( + &mut ctx, + &mut allocator, + file_kind.as_ref(), + Some(&export), + &base_path, + )? + .into_iter() + .next() + else { + eprintln!("{}", format!("Export `{export}` not found").red().bold()); + process::exit(1); + }; + + program.ptr + } else if let Some(main_kind) = main_kind + && let Some(ptr) = tree.main(&mut ctx, &mut allocator, &main_kind, base_path)? + { + ptr + } else { + eprintln!( + "{}", + "No `main` function found (you can specify an entrypoint with `--export`)" + .red() + .bold() + ); process::exit(1); }; - program.ptr - } else if let Some(main_kind) = main_kind - && let Some(ptr) = tree.main(&mut ctx, &mut allocator, &main_kind, base_path)? - { - ptr - } else { - eprintln!( - "{}", - "No `main` function found (you can specify an entrypoint with `--export`)" - .red() - .bold() - ); - process::exit(1); - }; + if args.hex { + let hex = hex::encode(node_to_bytes(&allocator, program)?); - if args.hex && args.hash { - println!("{}", hex::encode(node_to_bytes(&allocator, program)?)); - println!(); - println!("{}", tree_hash(&allocator, program)); - } else if args.hex { - println!("{}", hex::encode(node_to_bytes(&allocator, program)?)); - } else if args.hash { - println!("{}", tree_hash(&allocator, program)); - } else { - println!("{}", disassemble(&allocator, program, None)); + if args.split { + let chars = hex.chars().collect::>(); + let chunks = chars.chunks(64); + for chunk in chunks { + println!("{}", chunk.iter().collect::()); + } + } else { + println!("{hex}"); + } + } else if args.split { + eprintln!("{}", "Cannot use `--split` without `--hex`".red().bold()); + process::exit(1); + } + + if args.hex && args.hash { + println!(); + } + + if args.hash { + println!("{}", tree_hash(&allocator, program)); + } + + if !args.hex && !args.hash { + println!("{}", disassemble(&allocator, program, None)); + } } Ok(()) diff --git a/crates/rue-compiler/Cargo.toml b/crates/rue-compiler/Cargo.toml index 367d85bb..dc5b8a20 100644 --- a/crates/rue-compiler/Cargo.toml +++ b/crates/rue-compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-compiler" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "A compiler for the Rue programming language." diff --git a/crates/rue-diagnostic/Cargo.toml b/crates/rue-diagnostic/Cargo.toml index 31d7e232..054d4607 100644 --- a/crates/rue-diagnostic/Cargo.toml +++ b/crates/rue-diagnostic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-diagnostic" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "All of the potential diagnostics that can be emitted by the Rue compiler." diff --git a/crates/rue-hir/Cargo.toml b/crates/rue-hir/Cargo.toml index c369ac96..1c6ed100 100644 --- a/crates/rue-hir/Cargo.toml +++ b/crates/rue-hir/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-hir" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "Provides a high-level intermediate representation of the Rue programming language." diff --git a/crates/rue-lexer/Cargo.toml b/crates/rue-lexer/Cargo.toml index 25c05a86..e58b85fd 100644 --- a/crates/rue-lexer/Cargo.toml +++ b/crates/rue-lexer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-lexer" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "A lexer for the Rue programming language." diff --git a/crates/rue-lir/Cargo.toml b/crates/rue-lir/Cargo.toml index 6f080546..39681e58 100644 --- a/crates/rue-lir/Cargo.toml +++ b/crates/rue-lir/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-lir" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "Provides a low-level intermediate representation that compiles to CLVM." diff --git a/crates/rue-lsp/Cargo.toml b/crates/rue-lsp/Cargo.toml index 6bcd57fe..2156cc08 100644 --- a/crates/rue-lsp/Cargo.toml +++ b/crates/rue-lsp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-lsp" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "A language server protocol (LSP) implementation for the Rue programming language." diff --git a/crates/rue-options/Cargo.toml b/crates/rue-options/Cargo.toml index c2ef4bb1..1c7d540a 100644 --- a/crates/rue-options/Cargo.toml +++ b/crates/rue-options/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-options" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "Provides a way to configure the Rue compiler." diff --git a/crates/rue-options/src/manifest.rs b/crates/rue-options/src/manifest.rs index d1734d29..6f02c3f8 100644 --- a/crates/rue-options/src/manifest.rs +++ b/crates/rue-options/src/manifest.rs @@ -13,6 +13,8 @@ pub struct CompilerSection { pub entrypoint: String, #[serde(skip_serializing_if = "Option::is_none")] pub std: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub dist_dir: Option, } impl Default for CompilerSection { @@ -21,6 +23,7 @@ impl Default for CompilerSection { version: Some(env!("CARGO_PKG_VERSION").to_string()), entrypoint: "puzzles".to_string(), std: None, + dist_dir: None, } } } diff --git a/crates/rue-parser/Cargo.toml b/crates/rue-parser/Cargo.toml index 3d6b9ee0..5912bc4a 100644 --- a/crates/rue-parser/Cargo.toml +++ b/crates/rue-parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-parser" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "A parser for the Rue programming language." diff --git a/crates/rue-tests/Cargo.toml b/crates/rue-tests/Cargo.toml index 1d6ae1fd..7bc7222f 100644 --- a/crates/rue-tests/Cargo.toml +++ b/crates/rue-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-tests" -version = "0.8.0" +version = "0.8.1" edition = "2024" publish = false license = "Apache-2.0" diff --git a/crates/rue-types/Cargo.toml b/crates/rue-types/Cargo.toml index 0dadf77f..7ae91553 100644 --- a/crates/rue-types/Cargo.toml +++ b/crates/rue-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-types" -version = "0.8.0" +version = "0.8.1" edition = "2024" license = "Apache-2.0" description = "A type system for the Rue programming language." diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 1030a7f4..807db646 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rue-wasm" -version = "0.8.0" +version = "0.8.1" edition = "2024" publish = false license = "Apache-2.0"