diff --git a/src/interpreter/eval.rs b/src/interpreter/eval.rs index 6ecbbec..4ca75ea 100644 --- a/src/interpreter/eval.rs +++ b/src/interpreter/eval.rs @@ -90,9 +90,9 @@ impl super::Interpreter { fn eval_get(&mut self, object: Expr, name: String) -> Result { let obj = self.evaluate(object)?; match obj { - Value::Object(map) => { - match map.borrow().get(&name) { - Some(val) => Ok(val.clone()), + Value::Object(_) => { + match obj.get(&name) { + Some(val) => Ok(val), None => Err(RuntimeError::RuntimeError { message: format!("Undefined property '{}'", name), token: None, @@ -215,19 +215,18 @@ impl super::Interpreter { let obj = self.evaluate(object)?; let rhs = self.evaluate(value)?; match obj { - Value::Object(map) => { + Value::Object(_) => { let val = match op { AssignOp::Equal => rhs, _ => { - let map_borrow = map.borrow(); - let current = map_borrow.get(&name).ok_or_else(|| RuntimeError::RuntimeError { + let current = obj.get(&name).ok_or_else(|| RuntimeError::RuntimeError { message: format!("Property '{}' does not exist", name), token: None, })?; - self.apply_assign_op(current.clone(), rhs, op)? + self.apply_assign_op(current, rhs, op)? } }; - map.borrow_mut().insert(name, val.clone()); + obj.set(&name, val.clone())?; Ok(val) } _ => Err(RuntimeError::RuntimeError { @@ -241,7 +240,7 @@ impl super::Interpreter { let target = self.evaluate(array)?; let idx_val = self.evaluate(index)?; // Object index access: obj["key"] - if let Value::Object(map) = &target { + if let Value::Object(_) = &target { let key = match &idx_val { Value::String(s) => s.clone(), _ => return Err(RuntimeError::RuntimeError { @@ -249,7 +248,7 @@ impl super::Interpreter { token: None, }), }; - return map.borrow().get(&key).cloned().ok_or_else(|| RuntimeError::RuntimeError { + return target.get(&key).ok_or_else(|| RuntimeError::RuntimeError { message: format!("Undefined property '{}'", key), token: None, }); @@ -282,7 +281,7 @@ impl super::Interpreter { let idx_val = self.evaluate(index)?; let rhs = self.evaluate(value)?; // Object index assignment: obj["key"] = value - if let Value::Object(map) = &target { + if let Value::Object(_) = &target { let key = match &idx_val { Value::String(s) => s.clone(), _ => return Err(RuntimeError::RuntimeError { @@ -293,15 +292,14 @@ impl super::Interpreter { let val = match op { AssignOp::Equal => rhs, _ => { - let map_borrow = map.borrow(); - let current = map_borrow.get(&key).ok_or_else(|| RuntimeError::RuntimeError { + let current = target.get(&key).ok_or_else(|| RuntimeError::RuntimeError { message: format!("Property '{}' does not exist", key), token: None, })?; - self.apply_assign_op(current.clone(), rhs, op)? + self.apply_assign_op(current, rhs, op)? } }; - map.borrow_mut().insert(key, val.clone()); + target.set(&key, val.clone())?; return Ok(val); } let i = self.as_array_index(&idx_val)?; diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 3cbe3da..57a6101 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -33,6 +33,28 @@ pub enum Signal { Continue, // continue 信号 } +impl Value { + pub fn get(&self, key: &str) -> Option { + match self { + Value::Object(obj) => obj.borrow().get(key).cloned(), + _ => None, + } + } + + pub fn set(&self, key: &str, val: Value) -> Result<(), crate::error::RuntimeError> { + match self { + Value::Object(obj) => { + obj.borrow_mut().insert(key.to_string(), val); + Ok(()) + }, + _ => Err(crate::error::RuntimeError::RuntimeError { + message: "Only objects have properties".to_string(), + token: None, + }), + } + } +} + impl std::fmt::Debug for Value { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self {