Interpreter - Refactored instance to avoid runtime borrom problems

This commit is contained in:
Emmanuel BENOîT 2023-01-11 08:21:48 +01:00
parent c4f0f0f721
commit 47c4136c25
3 changed files with 6 additions and 23 deletions

View file

@ -21,7 +21,7 @@ pub type ClassRef = Rc<RefCell<Class>>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Instance { pub struct Instance {
class: Rc<RefCell<Class>>, class: Rc<RefCell<Class>>,
fields: HashMap<String, Value>, fields: RefCell<HashMap<String, Value>>,
} }
/* -------------------- * /* -------------------- *
@ -76,12 +76,12 @@ impl Instance {
fn new(class: ClassRef) -> Self { fn new(class: ClassRef) -> Self {
Self { Self {
class, class,
fields: HashMap::default(), fields: RefCell::new(HashMap::default()),
} }
} }
pub(super) fn get(&self, this_value: &Value, name: &Token) -> SloxResult<Value> { pub(super) fn get(&self, this_value: &Value, name: &Token) -> SloxResult<Value> {
if let Some(value) = self.fields.get(&name.lexeme) { if let Some(value) = self.fields.borrow().get(&name.lexeme) {
return Ok(value.clone()); return Ok(value.clone());
} }
if let Some(method) = self.class.borrow().methods.get(&name.lexeme) { if let Some(method) = self.class.borrow().methods.get(&name.lexeme) {
@ -96,8 +96,8 @@ impl Instance {
)) ))
} }
pub(super) fn set(&mut self, name: &Token, value: Value) { pub(super) fn set(&self, name: &Token, value: Value) {
self.fields.insert(name.lexeme.clone(), value); self.fields.borrow_mut().insert(name.lexeme.clone(), value);
} }
fn bind_method(&self, method: &Function, this_value: &Value) -> Function { fn bind_method(&self, method: &Function, this_value: &Value) -> Function {

View file

@ -553,7 +553,7 @@ impl ExprNode {
set_expr: &SetExpr, set_expr: &SetExpr,
) -> InterpreterResult { ) -> InterpreterResult {
let instance = set_expr.instance.interpret(itpr_state)?.result(); let instance = set_expr.instance.interpret(itpr_state)?.result();
instance.with_instance_mut( instance.with_instance(
|instance| { |instance| {
let value = set_expr.value.interpret(itpr_state)?.result(); let value = set_expr.value.interpret(itpr_state)?.result();
instance.set(&set_expr.name, value.clone()); instance.set(&set_expr.name, value.clone());

View file

@ -75,23 +75,6 @@ impl Value {
_ => ferr(), _ => ferr(),
} }
} }
/// Run some code against a mutable instance value. If the value does
/// not contain an instance, an error function will be called instead.
pub fn with_instance_mut<Fok, Ferr, Rt>(&self, fok: Fok, ferr: Ferr) -> Rt
where
Fok: FnOnce(&mut Instance) -> Rt,
Ferr: FnOnce() -> Rt,
{
let mut obj = match self {
Value::Object(obj_ref) => obj_ref.borrow_mut(),
_ => return ferr(),
};
match &mut *obj {
Object::Instance(inst) => fok(inst),
_ => ferr(),
}
}
} }
impl PartialEq for Value { impl PartialEq for Value {