Refactor: Replace UntypedNode with SyntaxNode
This commit replaces the `UntypedNode` enum with the more accurately named `SyntaxNode`. This change is primarily for clarity and better reflects the role of these nodes as representing the structure of the source code prior to semantic analysis. The corresponding enum `UntypedKind` has also been renamed to `SyntaxKind` to maintain consistency. No functional changes are introduced by this refactoring; it is purely a renaming and organizational update.
This commit is contained in:
+171
-171
@@ -1,171 +1,171 @@
|
||||
use clap::Parser;
|
||||
use myc::ast::environment::Environment;
|
||||
use myc::utils::tester;
|
||||
use std::fs;
|
||||
use std::io::{self, IsTerminal, Read};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about = "MYC AST Compiler & Benchmarker", long_about = None)]
|
||||
struct Cli {
|
||||
/// The script file to run or benchmark
|
||||
#[arg(value_name = "FILE")]
|
||||
file: Option<PathBuf>,
|
||||
|
||||
/// Run a script string directly
|
||||
#[arg(short, long)]
|
||||
eval: Option<String>,
|
||||
|
||||
/// Run benchmarks (Only allowed in Release mode)
|
||||
#[arg(short, long)]
|
||||
bench: bool,
|
||||
|
||||
/// Update the benchmark baseline (Only allowed in Release mode)
|
||||
#[arg(short, long)]
|
||||
update_bench: bool,
|
||||
|
||||
/// Dump the compiled AST
|
||||
#[arg(short, long)]
|
||||
dump: bool,
|
||||
|
||||
/// Run with TracingObserver enabled
|
||||
#[arg(short, long)]
|
||||
trace: bool,
|
||||
|
||||
/// Library directories to load before execution
|
||||
#[arg(short, long)]
|
||||
lib: Vec<PathBuf>,
|
||||
|
||||
/// Disable optimization
|
||||
#[arg(long)]
|
||||
no_opt: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
let mut env = Environment::new();
|
||||
env.optimization = !cli.no_opt;
|
||||
|
||||
// Load libraries (Now just search paths)
|
||||
for lib_path in &cli.lib {
|
||||
env.add_search_path(lib_path);
|
||||
}
|
||||
|
||||
if cli.bench || cli.update_bench {
|
||||
if cfg!(debug_assertions) {
|
||||
eprintln!("❌ ERROR: Benchmarks must be run in Release mode!");
|
||||
eprintln!(" Use: cargo run --release --bin ast -- --bench");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
println!("🚀 Running benchmarks in RELEASE mode...\n");
|
||||
let filter = cli
|
||||
.file
|
||||
.as_ref()
|
||||
.and_then(|p| p.file_name())
|
||||
.map(|n| n.to_string_lossy().to_string());
|
||||
let results = tester::run_benchmarks(cli.update_bench, filter.as_deref());
|
||||
for res in results {
|
||||
let diff = res
|
||||
.diff_pct
|
||||
.map_or(String::new(), |d| format!(" ({:+.1}%)", d));
|
||||
println!("{}: {} - {:?}{}", res.status, res.name, res.median, diff);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the source code to execute
|
||||
let source = if let Some(script_str) = cli.eval {
|
||||
Some(script_str)
|
||||
} else if let Some(file_path) = cli.file {
|
||||
if file_path.to_str() == Some("-") {
|
||||
read_stdin()
|
||||
} else {
|
||||
match fs::read_to_string(&file_path) {
|
||||
Ok(content) => Some(content),
|
||||
Err(e) => {
|
||||
eprintln!("Error reading file {:?}: {}", file_path, e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if !io::stdin().is_terminal() {
|
||||
read_stdin()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(content) = source {
|
||||
if cli.dump {
|
||||
match env.dump_ast(&content) {
|
||||
Ok(dump) => println!("{}", dump),
|
||||
Err(e) => eprintln!("Error dumping AST: {}", e),
|
||||
}
|
||||
} else if cli.trace {
|
||||
execute_trace(&env, &content);
|
||||
} else {
|
||||
execute(&env, &content);
|
||||
}
|
||||
} else {
|
||||
println!("MYC AST Compiler CLI. Use --help for usage.");
|
||||
}
|
||||
}
|
||||
|
||||
fn read_stdin() -> Option<String> {
|
||||
let mut buffer = String::new();
|
||||
match io::stdin().read_to_string(&mut buffer) {
|
||||
Ok(_) => Some(buffer),
|
||||
Err(e) => {
|
||||
eprintln!("Error reading from stdin: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn execute(env: &Environment, source: &str) {
|
||||
let result = env.compile(source);
|
||||
for diag in &result.diagnostics.items {
|
||||
let level = format!("{:?}", diag.level).to_uppercase();
|
||||
let loc = diag
|
||||
.identity
|
||||
.as_ref()
|
||||
.and_then(|id| id.location)
|
||||
.map(|l| format!(" at {}:{}", l.line, l.col))
|
||||
.unwrap_or_default();
|
||||
eprintln!("{}{} : {}", level, loc, diag.message);
|
||||
}
|
||||
|
||||
if result.diagnostics.has_errors() {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
match env.run_script_compiled(result.ast.unwrap()) {
|
||||
Ok(res) => println!("{}", res),
|
||||
Err(e) => {
|
||||
eprintln!("Runtime Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_trace(env: &Environment, source: &str) {
|
||||
match env.run_debug(source) {
|
||||
Ok((Ok(result), logs)) => {
|
||||
for line in logs {
|
||||
println!("{}", line);
|
||||
}
|
||||
println!("Result: {}", result);
|
||||
}
|
||||
Ok((Err(e), logs)) => {
|
||||
for line in logs {
|
||||
println!("{}", line);
|
||||
}
|
||||
eprintln!("Runtime Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Compilation Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
use clap::Parser;
|
||||
use myc::ast::environment::Environment;
|
||||
use myc::utils::tester;
|
||||
use std::fs;
|
||||
use std::io::{self, IsTerminal, Read};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about = "MYC AST Compiler & Benchmarker", long_about = None)]
|
||||
struct Cli {
|
||||
/// The script file to run or benchmark
|
||||
#[arg(value_name = "FILE")]
|
||||
file: Option<PathBuf>,
|
||||
|
||||
/// Run a script string directly
|
||||
#[arg(short, long)]
|
||||
eval: Option<String>,
|
||||
|
||||
/// Run benchmarks (Only allowed in Release mode)
|
||||
#[arg(short, long)]
|
||||
bench: bool,
|
||||
|
||||
/// Update the benchmark baseline (Only allowed in Release mode)
|
||||
#[arg(short, long)]
|
||||
update_bench: bool,
|
||||
|
||||
/// Dump the compiled AST
|
||||
#[arg(short, long)]
|
||||
dump: bool,
|
||||
|
||||
/// Run with TracingObserver enabled
|
||||
#[arg(short, long)]
|
||||
trace: bool,
|
||||
|
||||
/// Library directories to load before execution
|
||||
#[arg(short, long)]
|
||||
lib: Vec<PathBuf>,
|
||||
|
||||
/// Disable optimization
|
||||
#[arg(long)]
|
||||
no_opt: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
let mut env = Environment::new();
|
||||
env.optimization = !cli.no_opt;
|
||||
|
||||
// Load libraries (Now just search paths)
|
||||
for lib_path in &cli.lib {
|
||||
env.add_search_path(lib_path);
|
||||
}
|
||||
|
||||
if cli.bench || cli.update_bench {
|
||||
if cfg!(debug_assertions) {
|
||||
eprintln!("❌ ERROR: Benchmarks must be run in Release mode!");
|
||||
eprintln!(" Use: cargo run --release --bin ast -- --bench");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
println!("🚀 Running benchmarks in RELEASE mode...\n");
|
||||
let filter = cli
|
||||
.file
|
||||
.as_ref()
|
||||
.and_then(|p| p.file_name())
|
||||
.map(|n| n.to_string_lossy().to_string());
|
||||
let results = tester::run_benchmarks(cli.update_bench, filter.as_deref());
|
||||
for res in results {
|
||||
let diff = res
|
||||
.diff_pct
|
||||
.map_or(String::new(), |d| format!(" ({:+.1}%)", d));
|
||||
println!("{}: {} - {:?}{}", res.status, res.name, res.median, diff);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the source code to execute
|
||||
let source = if let Some(script_str) = cli.eval {
|
||||
Some(script_str)
|
||||
} else if let Some(file_path) = cli.file {
|
||||
if file_path.to_str() == Some("-") {
|
||||
read_stdin()
|
||||
} else {
|
||||
match fs::read_to_string(&file_path) {
|
||||
Ok(content) => Some(content),
|
||||
Err(e) => {
|
||||
eprintln!("Error reading file {:?}: {}", file_path, e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if !io::stdin().is_terminal() {
|
||||
read_stdin()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(content) = source {
|
||||
if cli.dump {
|
||||
match env.dump_ast(&content) {
|
||||
Ok(dump) => println!("{}", dump),
|
||||
Err(e) => eprintln!("Error dumping AST: {}", e),
|
||||
}
|
||||
} else if cli.trace {
|
||||
execute_trace(&env, &content);
|
||||
} else {
|
||||
execute(&env, &content);
|
||||
}
|
||||
} else {
|
||||
println!("MYC AST Compiler CLI. Use --help for usage.");
|
||||
}
|
||||
}
|
||||
|
||||
fn read_stdin() -> Option<String> {
|
||||
let mut buffer = String::new();
|
||||
match io::stdin().read_to_string(&mut buffer) {
|
||||
Ok(_) => Some(buffer),
|
||||
Err(e) => {
|
||||
eprintln!("Error reading from stdin: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn execute(env: &Environment, source: &str) {
|
||||
let result = env.compile(source);
|
||||
for diag in &result.diagnostics.items {
|
||||
let level = format!("{:?}", diag.level).to_uppercase();
|
||||
let loc = diag
|
||||
.identity
|
||||
.as_ref()
|
||||
.and_then(|id| id.location)
|
||||
.map(|l| format!(" at {}:{}", l.line, l.col))
|
||||
.unwrap_or_default();
|
||||
eprintln!("{}{} : {}", level, loc, diag.message);
|
||||
}
|
||||
|
||||
if result.diagnostics.has_errors() {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
match env.run_script_compiled(result.ast.unwrap()) {
|
||||
Ok(res) => println!("{}", res),
|
||||
Err(e) => {
|
||||
eprintln!("Runtime Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_trace(env: &Environment, source: &str) {
|
||||
match env.run_debug(source) {
|
||||
Ok((Ok(result), logs)) => {
|
||||
for line in logs {
|
||||
println!("{}", line);
|
||||
}
|
||||
println!("Result: {}", result);
|
||||
}
|
||||
Ok((Err(e), logs)) => {
|
||||
for line in logs {
|
||||
println!("{}", line);
|
||||
}
|
||||
eprintln!("Runtime Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Compilation Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user