feat: REPL 改进 — 消除全量历史拼接 + 单 VM 持久

This commit is contained in:
2026-08-21 22:31:33 +08:00
parent c514ab35a3
commit cf57285ebb
+45 -14
View File
@@ -19,6 +19,7 @@ use oxide_types::object::JsObject;
use oxide_vm::vm_error; use oxide_vm::vm_error;
use oxide_vm::vm_pool::VmPool; use oxide_vm::vm_pool::VmPool;
use oxide_vm::JsValue; use oxide_vm::JsValue;
use oxide_vm::vm::Vm;
mod bench; mod bench;
@@ -363,15 +364,14 @@ fn repl() -> ExitCode {
}; };
let kernel = make_kernel(false, false); let kernel = make_kernel(false, false);
let pool = make_pool(&kernel); let mut vm = Vm::with_kernel_core(Arc::clone(&kernel));
let mut source = String::new();
let mut input_buf = String::new(); let mut input_buf = String::new();
loop { loop {
let prompt = if input_buf.is_empty() { "oxide> " } else { "...> " }; let prompt = if input_buf.is_empty() { "oxide> " } else { "...> " };
match rl.readline(prompt) { match rl.readline(prompt) {
Ok(line) => { Ok(line) => {
let trimmed = line.trim(); let trimmed = line.trim().to_string();
if trimmed.is_empty() { if trimmed.is_empty() {
continue; continue;
} }
@@ -379,29 +379,23 @@ fn repl() -> ExitCode {
println!("exit"); println!("exit");
return ExitCode::SUCCESS; return ExitCode::SUCCESS;
} }
rl.add_history_entry(trimmed).ok(); rl.add_history_entry(&trimmed).ok();
if !input_buf.is_empty() { if !input_buf.is_empty() {
input_buf.push('\n'); input_buf.push('\n');
} }
input_buf.push_str(trimmed); input_buf.push_str(&trimmed);
let balance = bracket_balance(&input_buf); let balance = bracket_balance(&input_buf);
if balance > 0 { if balance > 0 {
continue; continue;
} }
let mut full_code = source.clone(); let result = eval_repl(&input_buf, &kernel, &mut vm);
if !full_code.is_empty() {
full_code.push(';');
}
full_code.push_str(&input_buf);
let result = eval(&full_code, &kernel, &pool);
input_buf.clear(); input_buf.clear();
if result == ExitCode::SUCCESS { if result == ExitCode::FAILURE {
source = full_code; // eval_repl already printed error; keep buffer cleared.
} }
} }
Err(ReadlineError::Interrupted) => { Err(ReadlineError::Interrupted) => {
@@ -420,6 +414,43 @@ fn repl() -> ExitCode {
} }
} }
} }
fn eval_repl(code: &str, kernel: &Arc<KernelCore>, vm: &mut Vm) -> ExitCode {
let allocator = Allocator::default();
let program = match oxide_parser::parse(&allocator, code) {
Ok(p) => p,
Err(errors) => {
for err in &errors {
compiler_error!("parse error: {}", err);
eprintln!("{}", Red.paint(err.to_string()));
}
return ExitCode::FAILURE;
}
};
let compiler = Compiler::new();
let hash = compiled_module_hash(&program);
let module = match kernel.code_forge().get_or_insert_with(hash, || compiler.compile(&program)) {
Ok(m) => m,
Err(err) => {
compiler_error!("compile error: {}", err);
eprintln!("{}", Red.paint(err));
return ExitCode::FAILURE;
}
};
match vm.run(&module) {
Ok(result) => {
format_result(vm, kernel.perm_interner().as_ref(), kernel.shape_forge().as_ref(), result);
ExitCode::SUCCESS
}
Err(err) => {
vm_error!("runtime error: {}", err);
eprintln!("{}", Red.paint(err));
ExitCode::FAILURE
}
}
}
fn not_implemented(command: &str) -> ExitCode { fn not_implemented(command: &str) -> ExitCode {
use ansi_term::Colour::Yellow; use ansi_term::Colour::Yellow;
kernel_info!("command not yet implemented: {}", command); kernel_info!("command not yet implemented: {}", command);