feat: Enhance VM with dynamic type conversion and comprehensive method support
- Add dynamic bool conversion for BoxRef(BoolBox)→bool and BoxRef(VoidBox)→false - Implement String concatenation with Bool and BoxRef types via toString() - Add Void/Bool comparison support (Eq/Ne only) to prevent VM crashes - Implement comprehensive ArrayBox methods in VM: - push/pop/length/get/set/remove - contains/indexOf/clear/join/sort/reverse/slice - Implement comprehensive MapBox methods in VM: - set/get/has/delete/keys/values/size/clear - Add SocketBox timeout methods (acceptTimeout/recvTimeout) - Update VM documentation with all new operations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -963,6 +963,14 @@ impl VM {
|
||||
}
|
||||
},
|
||||
|
||||
(VMValue::String(l), VMValue::Bool(r)) => {
|
||||
// String + Bool concatenation
|
||||
match op {
|
||||
BinaryOp::Add => Ok(VMValue::String(format!("{}{}", l, r))),
|
||||
_ => Err(VMError::TypeError("String-bool operations only support addition".to_string())),
|
||||
}
|
||||
},
|
||||
|
||||
(VMValue::String(l), VMValue::String(r)) => {
|
||||
// String concatenation
|
||||
match op {
|
||||
@ -1239,6 +1247,113 @@ impl VM {
|
||||
}
|
||||
}
|
||||
|
||||
// ArrayBox methods (minimal set)
|
||||
if let Some(array_box) = box_value.as_any().downcast_ref::<crate::boxes::array::ArrayBox>() {
|
||||
match method {
|
||||
"push" => {
|
||||
if let Some(v) = _args.get(0) { return Ok(array_box.push(v.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: push(value) requires 1 arg")));
|
||||
},
|
||||
"pop" => { return Ok(array_box.pop()); },
|
||||
"length" | "len" => { return Ok(array_box.length()); },
|
||||
"get" => {
|
||||
if let Some(i) = _args.get(0) { return Ok(array_box.get(i.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: get(index) requires 1 arg")));
|
||||
},
|
||||
"set" => {
|
||||
if _args.len() >= 2 { return Ok(array_box.set(_args[0].clone_or_share(), _args[1].clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: set(index, value) requires 2 args")));
|
||||
},
|
||||
"remove" => {
|
||||
if let Some(i) = _args.get(0) { return Ok(array_box.remove(i.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: remove(index) requires 1 arg")));
|
||||
},
|
||||
"contains" => {
|
||||
if let Some(v) = _args.get(0) { return Ok(array_box.contains(v.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: contains(value) requires 1 arg")));
|
||||
},
|
||||
"indexOf" => {
|
||||
if let Some(v) = _args.get(0) { return Ok(array_box.indexOf(v.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: indexOf(value) requires 1 arg")));
|
||||
},
|
||||
"clear" => { return Ok(array_box.clear()); },
|
||||
"join" => {
|
||||
if let Some(sep) = _args.get(0) { return Ok(array_box.join(sep.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: join(sep) requires 1 arg")));
|
||||
},
|
||||
"sort" => { return Ok(array_box.sort()); },
|
||||
"reverse" => { return Ok(array_box.reverse()); },
|
||||
"slice" => {
|
||||
if _args.len() >= 2 { return Ok(array_box.slice(_args[0].clone_or_share(), _args[1].clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: slice(start, end) requires 2 args")));
|
||||
},
|
||||
_ => return Ok(Box::new(VoidBox::new())),
|
||||
}
|
||||
}
|
||||
|
||||
// MapBox methods (minimal set)
|
||||
if let Some(map_box) = box_value.as_any().downcast_ref::<crate::boxes::map_box::MapBox>() {
|
||||
match method {
|
||||
"set" => {
|
||||
if _args.len() >= 2 { return Ok(map_box.set(_args[0].clone_or_share(), _args[1].clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: set(key, value) requires 2 args")));
|
||||
},
|
||||
"get" => {
|
||||
if let Some(k) = _args.get(0) { return Ok(map_box.get(k.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: get(key) requires 1 arg")));
|
||||
},
|
||||
"has" => {
|
||||
if let Some(k) = _args.get(0) { return Ok(map_box.has(k.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: has(key) requires 1 arg")));
|
||||
},
|
||||
"delete" | "remove" => {
|
||||
if let Some(k) = _args.get(0) { return Ok(map_box.delete(k.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: delete(key) requires 1 arg")));
|
||||
},
|
||||
"keys" => { return Ok(map_box.keys()); },
|
||||
"values" => { return Ok(map_box.values()); },
|
||||
"size" => { return Ok(map_box.size()); },
|
||||
"clear" => { return Ok(map_box.clear()); },
|
||||
_ => return Ok(Box::new(VoidBox::new())),
|
||||
}
|
||||
}
|
||||
|
||||
// SocketBox methods (minimal set + timeout variants)
|
||||
if let Some(sock) = box_value.as_any().downcast_ref::<crate::boxes::socket_box::SocketBox>() {
|
||||
match method {
|
||||
"bind" => {
|
||||
if _args.len() >= 2 { return Ok(sock.bind(_args[0].clone_or_share(), _args[1].clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: bind(address, port) requires 2 args")));
|
||||
},
|
||||
"listen" => {
|
||||
if let Some(b) = _args.get(0) { return Ok(sock.listen(b.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: listen(backlog) requires 1 arg")));
|
||||
},
|
||||
"accept" => { return Ok(sock.accept()); },
|
||||
"acceptTimeout" | "accept_timeout" => {
|
||||
if let Some(ms) = _args.get(0) { return Ok(sock.accept_timeout(ms.clone_or_share())); }
|
||||
return Ok(Box::new(crate::box_trait::VoidBox::new()));
|
||||
},
|
||||
"connect" => {
|
||||
if _args.len() >= 2 { return Ok(sock.connect(_args[0].clone_or_share(), _args[1].clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("Error: connect(address, port) requires 2 args")));
|
||||
},
|
||||
"read" => { return Ok(sock.read()); },
|
||||
"recvTimeout" | "recv_timeout" => {
|
||||
if let Some(ms) = _args.get(0) { return Ok(sock.recv_timeout(ms.clone_or_share())); }
|
||||
return Ok(Box::new(StringBox::new("")));
|
||||
},
|
||||
"write" => {
|
||||
if let Some(d) = _args.get(0) { return Ok(sock.write(d.clone_or_share())); }
|
||||
return Ok(Box::new(crate::box_trait::BoolBox::new(false)));
|
||||
},
|
||||
"close" => { return Ok(sock.close()); },
|
||||
"isServer" | "is_server" => { return Ok(sock.is_server()); },
|
||||
"isConnected" | "is_connected" => { return Ok(sock.is_connected()); },
|
||||
_ => return Ok(Box::new(VoidBox::new())),
|
||||
}
|
||||
}
|
||||
|
||||
// IntegerBox methods
|
||||
if let Some(integer_box) = box_value.as_any().downcast_ref::<IntegerBox>() {
|
||||
match method {
|
||||
|
||||
Reference in New Issue
Block a user