mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
feat: CLI 支持 REPL 编译到字节码
This commit is contained in:
@@ -21,11 +21,23 @@ struct Cli {
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
Eval { code: String },
|
||||
Run { file: String },
|
||||
Compile { file: String },
|
||||
Bench { suite: Option<String> },
|
||||
Test { suite: Option<String> },
|
||||
Eval {
|
||||
code: String,
|
||||
},
|
||||
Run {
|
||||
file: String,
|
||||
},
|
||||
Compile {
|
||||
#[arg(short = 'e')]
|
||||
expr: Option<String>,
|
||||
file: Option<String>,
|
||||
},
|
||||
Bench {
|
||||
suite: Option<String>,
|
||||
},
|
||||
Test {
|
||||
suite: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
@@ -34,7 +46,7 @@ fn main() -> ExitCode {
|
||||
match cli.command {
|
||||
Some(Commands::Eval { code }) => eval(&code),
|
||||
Some(Commands::Run { file }) => run(&file),
|
||||
Some(Commands::Compile { file }) => compile(&file),
|
||||
Some(Commands::Compile { expr, file }) => compile(expr, file),
|
||||
Some(Commands::Bench { .. }) => not_implemented("bench"),
|
||||
Some(Commands::Test { .. }) => not_implemented("test"),
|
||||
None => repl(),
|
||||
@@ -43,15 +55,24 @@ fn main() -> ExitCode {
|
||||
|
||||
fn eval(code: &str) -> ExitCode {
|
||||
let allocator = Allocator::default();
|
||||
match oxide_parser::parse(&allocator, code) {
|
||||
Ok(program) => {
|
||||
println!("{program:#?}");
|
||||
ExitCode::SUCCESS
|
||||
}
|
||||
let program = match oxide_parser::parse(&allocator, code) {
|
||||
Ok(p) => p,
|
||||
Err(errors) => {
|
||||
for err in &errors {
|
||||
eprintln!("{}", Red.paint(err.to_string()));
|
||||
}
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
let compiler = Compiler::new();
|
||||
match compiler.compile(&program) {
|
||||
Ok(module) => {
|
||||
print!("{module}");
|
||||
ExitCode::SUCCESS
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("{}", Red.paint(err));
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
}
|
||||
@@ -67,13 +88,23 @@ fn run(file: &str) -> ExitCode {
|
||||
}
|
||||
}
|
||||
|
||||
fn compile(file: &str) -> ExitCode {
|
||||
let source = match fs::read_to_string(file) {
|
||||
Ok(s) => s,
|
||||
Err(err) => {
|
||||
eprintln!("{}", Red.paint(format!("Cannot read {file}: {err}")));
|
||||
return ExitCode::FAILURE;
|
||||
fn compile(expr: Option<String>, file: Option<String>) -> ExitCode {
|
||||
let source = if let Some(code) = expr {
|
||||
code
|
||||
} else if let Some(path) = file {
|
||||
match fs::read_to_string(&path) {
|
||||
Ok(s) => s,
|
||||
Err(err) => {
|
||||
eprintln!("{}", Red.paint(format!("Cannot read {path}: {err}")));
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!(
|
||||
"{}",
|
||||
Red.paint("compile requires -e '<code>' or a file path")
|
||||
);
|
||||
return ExitCode::FAILURE;
|
||||
};
|
||||
|
||||
let allocator = Allocator::default();
|
||||
|
||||
@@ -10,8 +10,8 @@ fn eval_simple_expression() {
|
||||
assert!(output.status.success(), "eval 1+2 should exit 0");
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
assert!(
|
||||
stdout.contains("Program"),
|
||||
"output should contain AST node: {stdout}"
|
||||
stdout.contains("HALT"),
|
||||
"output should contain HALT bytecode: {stdout}"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ fn run_file() {
|
||||
assert!(output.status.success(), "run hello.js should exit 0");
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
assert!(
|
||||
stdout.contains("Program"),
|
||||
"run output should contain AST node"
|
||||
stdout.contains("HALT"),
|
||||
"run output should contain bytecode: {stdout}"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user