feat: CLI 支持 JSON 对象输出

This commit is contained in:
爱特每羊队
2026-06-07 23:47:59 +08:00
parent 69945b9610
commit 9041edeb13
3 changed files with 61 additions and 31 deletions
+1
View File
@@ -12,6 +12,7 @@ path = "src/main.rs"
[dependencies]
oxide_parser = { path = "../oxide_parser" }
oxide_types = { path = "../oxide_types" }
oxide_compiler = { path = "../oxide_compiler" }
oxide_vm = { path = "../oxide_vm" }
oxide_kernel = { path = "../oxide_kernel" }
+59 -31
View File
@@ -8,8 +8,10 @@ use ansi_term::Colour::Red;
use clap::{Parser, Subcommand};
use oxide_compiler::compiler::Compiler;
use oxide_kernel::kernel::{KernelConfig, OxideKernel};
use oxide_kernel::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
use oxide_kernel::string_forge::StringForge;
use oxide_parser::Allocator;
use oxide_types::object::JsObject;
use oxide_vm::vm_pool::VmPool;
use oxide_vm::JsValue;
@@ -106,7 +108,7 @@ fn eval(code: &str, kernel: &Arc<OxideKernel>, pool: &Arc<VmPool>) -> ExitCode {
let mut guard = pool.spawn();
match guard.vm_mut().run(&module) {
Ok(result) => {
format_result(kernel.string_forge().as_ref(), result);
format_result(kernel.string_forge().as_ref(), kernel.shape_forge().as_ref(), result);
ExitCode::SUCCESS
}
Err(err) => {
@@ -116,52 +118,78 @@ fn eval(code: &str, kernel: &Arc<OxideKernel>, pool: &Arc<VmPool>) -> ExitCode {
}
}
fn format_result(string_forge: &StringForge, val: JsValue) {
fn format_result(string_forge: &StringForge, shape_forge: &ShapeForge, val: JsValue) {
println!("{}", format_js_value(string_forge, shape_forge, val));
}
fn format_js_value(string_forge: &StringForge, shape_forge: &ShapeForge, val: JsValue) -> String {
if val.is_string() {
if let Some(s) = string_forge.lookup(val.as_string_index()) {
println!("\"{s}\"");
format!("\"{s}\"")
} else {
println!("{val}");
format!("{val}")
}
} else if val.is_object() {
let obj = unsafe { &*val.as_js_object_ptr() };
if obj.is_function() {
println!("[Function]");
"[Function]".to_string()
} else if obj.is_array() {
format_array(string_forge, shape_forge, obj)
} else {
print!("{{");
let count = obj.prop_count() as usize;
let mut first = true;
for i in 0..count.min(4) {
let prop_val = obj.get_prop_at(i as u8);
if prop_val.is_undefined() {
continue;
}
if !first {
print!(", ");
}
first = false;
print!("{:?}: ", i);
print_value(string_forge, prop_val);
}
println!("}}");
format_object(string_forge, shape_forge, obj)
}
} else if val.is_undefined() {
println!("undefined");
"undefined".to_string()
} else {
println!("{val}");
format!("{val}")
}
}
fn print_value(string_forge: &StringForge, val: JsValue) {
if val.is_string() {
if let Some(s) = string_forge.lookup(val.as_string_index()) {
print!("\"{s}\"");
} else {
print!("{val}");
fn format_object(string_forge: &StringForge, shape_forge: &ShapeForge, obj: &JsObject) -> String {
let mut entries = Vec::new();
let shape_id = obj.shape_id();
let mut shape_ids = Vec::new();
let mut cursor = Some(shape_id);
while let Some(id) = cursor {
if id == EMPTY_SHAPE_ID {
break;
}
if let Some(shape) = shape_forge.get_shape(id) {
cursor = shape.parent;
if shape.property_name != u32::MAX {
shape_ids.push(id);
}
} else {
break;
}
} else {
print!("{val}");
}
let mut pos: u8 = 0;
for id in shape_ids.iter().rev() {
if let Some(shape) = shape_forge.get_shape(*id) {
if shape.property_name != 0 {
let prop_val = obj.get_prop_at(pos);
if prop_val.is_undefined() {
pos += 1;
continue;
}
let name = string_forge.lookup(shape.property_name).unwrap_or_default();
let val_str = format_js_value(string_forge, shape_forge, prop_val);
entries.push(format!("\"{name}\": {val_str}"));
}
}
pos += 1;
}
format!("{{{}}}", entries.join(", "))
}
fn format_array(string_forge: &StringForge, shape_forge: &ShapeForge, obj: &JsObject) -> String {
let len = obj.prop_vec_len();
let mut items = Vec::new();
for i in 0..len {
let val = obj.get_prop_at(i as u8);
items.push(format_js_value(string_forge, shape_forge, val));
}
format!("[{}]", items.join(", "))
}
fn run(file: &str, kernel: &Arc<OxideKernel>, pool: &Arc<VmPool>) -> ExitCode {