From cf57285ebb58cfad7a97d6bf1b4595bf280c5679 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Fri, 21 Aug 2026 22:31:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20REPL=20=E6=94=B9=E8=BF=9B=20=E2=80=94?= =?UTF-8?q?=20=E6=B6=88=E9=99=A4=E5=85=A8=E9=87=8F=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E6=8B=BC=E6=8E=A5=20+=20=E5=8D=95=20VM=20=E6=8C=81=E4=B9=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_cli/src/main.rs | 59 +++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/crates/oxide_cli/src/main.rs b/crates/oxide_cli/src/main.rs index 0655f0d2..ce7e5955 100644 --- a/crates/oxide_cli/src/main.rs +++ b/crates/oxide_cli/src/main.rs @@ -19,6 +19,7 @@ use oxide_types::object::JsObject; use oxide_vm::vm_error; use oxide_vm::vm_pool::VmPool; use oxide_vm::JsValue; +use oxide_vm::vm::Vm; mod bench; @@ -363,15 +364,14 @@ fn repl() -> ExitCode { }; let kernel = make_kernel(false, false); - let pool = make_pool(&kernel); - let mut source = String::new(); + let mut vm = Vm::with_kernel_core(Arc::clone(&kernel)); let mut input_buf = String::new(); loop { let prompt = if input_buf.is_empty() { "oxide> " } else { "...> " }; match rl.readline(prompt) { Ok(line) => { - let trimmed = line.trim(); + let trimmed = line.trim().to_string(); if trimmed.is_empty() { continue; } @@ -379,29 +379,23 @@ fn repl() -> ExitCode { println!("exit"); return ExitCode::SUCCESS; } - rl.add_history_entry(trimmed).ok(); + rl.add_history_entry(&trimmed).ok(); if !input_buf.is_empty() { input_buf.push('\n'); } - input_buf.push_str(trimmed); + input_buf.push_str(&trimmed); let balance = bracket_balance(&input_buf); if balance > 0 { continue; } - let mut full_code = source.clone(); - if !full_code.is_empty() { - full_code.push(';'); - } - full_code.push_str(&input_buf); - - let result = eval(&full_code, &kernel, &pool); + let result = eval_repl(&input_buf, &kernel, &mut vm); input_buf.clear(); - if result == ExitCode::SUCCESS { - source = full_code; + if result == ExitCode::FAILURE { + // eval_repl already printed error; keep buffer cleared. } } Err(ReadlineError::Interrupted) => { @@ -420,6 +414,43 @@ fn repl() -> ExitCode { } } } + +fn eval_repl(code: &str, kernel: &Arc, 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 { use ansi_term::Colour::Yellow; kernel_info!("command not yet implemented: {}", command);