mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
feat: REPL 改进 — 消除全量历史拼接 + 单 VM 持久
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user