refactor: restructure CLI into library crate and add semantic analysis phase
Restructure nxc-cli crate: - Extract main logic into lib.rs with main_entry() function - Move nexacore binary to separate bin/nexacore.rs file - Keep nxc binary in main.rs as thin wrapper Add semantic analysis to compilation pipeline: - Implement semantic analyzer with type checking and name resolution - Add Type enum with Int, Float, Bool, String, Void, Struct, Function, Error variants - Add typed AST nodes (TypedModule, TypedFunction
This commit is contained in:
@@ -5,14 +5,16 @@ edition.workspace = true
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "nxc"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "nexacore"
|
||||
path = "src/main.rs"
|
||||
path = "src/bin/nexacore.rs"
|
||||
|
||||
[dependencies]
|
||||
nxc-driver = { path = "../nxc-driver" }
|
||||
|
||||
|
||||
3
crates/nxc-cli/src/bin/nexacore.rs
Normal file
3
crates/nxc-cli/src/bin/nexacore.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() -> std::process::ExitCode {
|
||||
nxc_cli::main_entry()
|
||||
}
|
||||
86
crates/nxc-cli/src/lib.rs
Normal file
86
crates/nxc-cli/src/lib.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::process::ExitCode;
|
||||
|
||||
pub fn main_entry() -> ExitCode {
|
||||
match run() {
|
||||
Ok(()) => ExitCode::SUCCESS,
|
||||
Err(message) => {
|
||||
eprintln!("{message}");
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run() -> Result<(), String> {
|
||||
let mut args = env::args().skip(1);
|
||||
let Some(command) = args.next() else {
|
||||
print_help();
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
match command.as_str() {
|
||||
"check" | "build" => {
|
||||
let Some(path) = args.next() else {
|
||||
return Err(format!("usage: {} {command} <file.nx>", executable_name()));
|
||||
};
|
||||
|
||||
let output =
|
||||
nxc_driver::check_file(Path::new(&path)).map_err(format_driver_error)?;
|
||||
|
||||
if output.has_errors() {
|
||||
eprintln!("{}", output.render_diagnostics());
|
||||
return Err(format!(
|
||||
"check failed with {} diagnostic(s)",
|
||||
output.diagnostics.len()
|
||||
));
|
||||
}
|
||||
|
||||
let summary = output.summary();
|
||||
println!("checked {}", output.path.display());
|
||||
println!("tokens: {}", output.tokens.len());
|
||||
println!("items: {}", summary.items);
|
||||
println!("functions: {}", summary.functions);
|
||||
println!("structs: {}", summary.structs);
|
||||
Ok(())
|
||||
}
|
||||
"run" => Err("runtime execution is not implemented yet".to_string()),
|
||||
"new" => Err("project scaffolding is not implemented yet".to_string()),
|
||||
"test" => Err("test runner is not implemented yet".to_string()),
|
||||
"fmt" => Err("formatter is not implemented yet".to_string()),
|
||||
"add" => Err("package manager is not implemented yet".to_string()),
|
||||
"doc" => Err("docs generator is not implemented yet".to_string()),
|
||||
_ => Err(format!("unknown command: {command}")),
|
||||
}
|
||||
}
|
||||
|
||||
fn executable_name() -> String {
|
||||
env::args()
|
||||
.next()
|
||||
.and_then(|path| {
|
||||
Path::new(&path)
|
||||
.file_name()
|
||||
.map(|name| name.to_string_lossy().to_string())
|
||||
})
|
||||
.unwrap_or_else(|| "nxc".to_string())
|
||||
}
|
||||
|
||||
fn format_driver_error(error: nxc_driver::DriverError) -> String {
|
||||
match error {
|
||||
nxc_driver::DriverError::Io(io) => format!("io error: {io}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_help() {
|
||||
let name = executable_name();
|
||||
println!("NexaCore CLI");
|
||||
println!("usage:");
|
||||
println!(" {name} check <file.nx>");
|
||||
println!(" {name} build <file.nx>");
|
||||
println!(" {name} run <file.nx>");
|
||||
println!(" {name} new <name>");
|
||||
println!(" {name} test");
|
||||
println!(" {name} fmt");
|
||||
println!(" {name} add <package>");
|
||||
println!(" {name} doc");
|
||||
}
|
||||
@@ -1,87 +1,4 @@
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::process::ExitCode;
|
||||
|
||||
fn main() -> ExitCode {
|
||||
match run() {
|
||||
Ok(()) => ExitCode::SUCCESS,
|
||||
Err(message) => {
|
||||
eprintln!("{message}");
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run() -> Result<(), String> {
|
||||
let mut args = env::args().skip(1);
|
||||
let Some(command) = args.next() else {
|
||||
print_help();
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
match command.as_str() {
|
||||
"check" | "build" => {
|
||||
let Some(path) = args.next() else {
|
||||
return Err(format!("usage: {} {command} <file.nx>", executable_name()));
|
||||
};
|
||||
|
||||
let output =
|
||||
nxc_driver::check_file(Path::new(&path)).map_err(format_driver_error)?;
|
||||
|
||||
if output.has_errors() {
|
||||
eprintln!("{}", output.render_diagnostics());
|
||||
return Err(format!(
|
||||
"check failed with {} diagnostic(s)",
|
||||
output.diagnostics.len()
|
||||
));
|
||||
}
|
||||
|
||||
let summary = output.summary();
|
||||
println!("checked {}", output.path.display());
|
||||
println!("tokens: {}", output.tokens.len());
|
||||
println!("items: {}", summary.items);
|
||||
println!("functions: {}", summary.functions);
|
||||
println!("structs: {}", summary.structs);
|
||||
Ok(())
|
||||
}
|
||||
"run" => Err("runtime execution is not implemented yet".to_string()),
|
||||
"new" => Err("project scaffolding is not implemented yet".to_string()),
|
||||
"test" => Err("test runner is not implemented yet".to_string()),
|
||||
"fmt" => Err("formatter is not implemented yet".to_string()),
|
||||
"add" => Err("package manager is not implemented yet".to_string()),
|
||||
"doc" => Err("docs generator is not implemented yet".to_string()),
|
||||
_ => Err(format!("unknown command: {command}")),
|
||||
}
|
||||
}
|
||||
|
||||
fn executable_name() -> String {
|
||||
env::args()
|
||||
.next()
|
||||
.and_then(|path| {
|
||||
Path::new(&path)
|
||||
.file_name()
|
||||
.map(|name| name.to_string_lossy().to_string())
|
||||
})
|
||||
.unwrap_or_else(|| "nxc".to_string())
|
||||
}
|
||||
|
||||
fn format_driver_error(error: nxc_driver::DriverError) -> String {
|
||||
match error {
|
||||
nxc_driver::DriverError::Io(io) => format!("io error: {io}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_help() {
|
||||
let name = executable_name();
|
||||
println!("NexaCore CLI");
|
||||
println!("usage:");
|
||||
println!(" {name} check <file.nx>");
|
||||
println!(" {name} build <file.nx>");
|
||||
println!(" {name} run <file.nx>");
|
||||
println!(" {name} new <name>");
|
||||
println!(" {name} test");
|
||||
println!(" {name} fmt");
|
||||
println!(" {name} add <package>");
|
||||
println!(" {name} doc");
|
||||
fn main() -> std::process::ExitCode {
|
||||
nxc_cli::main_entry()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user