Interpreter - Working bound methods

This commit is contained in:
Emmanuel BENOîT 2023-01-09 11:19:42 +01:00
parent 542bc56aad
commit 3e4aea0d78
3 changed files with 39 additions and 6 deletions

View file

@ -1,4 +1,9 @@
use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc}; use std::{
cell::RefCell,
collections::HashMap,
fmt::Display,
rc::Rc,
};
use crate::{ use crate::{
errors::{ErrorKind, SloxError, SloxResult}, errors::{ErrorKind, SloxError, SloxResult},
@ -77,12 +82,16 @@ impl Instance {
} }
} }
pub(super) fn get(&self, 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.get(&name.lexeme) {
return Ok(value.clone()); return Ok(value.clone());
} }
if let Some(method) = self.class.borrow().methods.get(&name.lexeme) { if self.class.borrow().methods.get(&name.lexeme).is_some() {
return Ok(Value::from(method.clone())); let bound_method = BoundMethod {
instance: this_value.clone(),
method: name.lexeme.clone(),
};
return Ok(Value::from(bound_method));
} }
Err(SloxError::with_token( Err(SloxError::with_token(
@ -150,6 +159,21 @@ impl Callable for BoundMethod {
.environment .environment
.borrow_mut() .borrow_mut()
.define(&self.this_token(), Some(self.instance.clone()))?; .define(&self.this_token(), Some(self.instance.clone()))?;
println!("{:?}", this_env.locals);
self.with_method(|m| m.call(&mut this_env, arguments)) self.with_method(|m| m.call(&mut this_env, arguments))
} }
} }
impl Display for BoundMethod {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.instance.with_instance(
|instance| {
f.write_fmt(format_args!(
"<Bound method {} of {}>",
self.method, instance
))
},
|| panic!("Instance value does not contain an instance"),
)
}
}

View file

@ -539,7 +539,7 @@ impl ExprNode {
) -> InterpreterResult { ) -> InterpreterResult {
let instance = get_expr.instance.interpret(itpr_state)?.result(); let instance = get_expr.instance.interpret(itpr_state)?.result();
instance.with_instance( instance.with_instance(
|instance| instance.get(&get_expr.name).map(|v| v.into()), |inst| inst.get(&instance, &get_expr.name).map(|v| v.into()),
|| error(&get_expr.name, "only instances have properties"), || error(&get_expr.name, "only instances have properties"),
) )
} }

View file

@ -1,7 +1,7 @@
use std::{cell::RefCell, fmt::Display, rc::Rc}; use std::{cell::RefCell, fmt::Display, rc::Rc};
use super::{ use super::{
classes::{Class, ClassRef, Instance}, classes::{Class, ClassRef, Instance, BoundMethod},
functions::Function, functions::Function,
native_fn::NativeFunction, native_fn::NativeFunction,
Callable, Callable,
@ -23,6 +23,7 @@ pub enum Object {
LoxFunction(Function), LoxFunction(Function),
Class(ClassRef), Class(ClassRef),
Instance(Instance), Instance(Instance),
BoundMethod(BoundMethod),
} }
/* -------------------- * /* -------------------- *
@ -56,6 +57,7 @@ impl Value {
Object::LoxFunction(func) => fok(func), Object::LoxFunction(func) => fok(func),
Object::Class(class) => fok(class), Object::Class(class) => fok(class),
Object::Instance(_) => ferr(), Object::Instance(_) => ferr(),
Object::BoundMethod(bm) => fok(bm),
} }
} }
@ -148,6 +150,12 @@ impl From<Instance> for Value {
} }
} }
impl From<BoundMethod> for Value {
fn from(value: BoundMethod) -> Self {
Value::Object(Rc::new(RefCell::new(Object::BoundMethod(value))))
}
}
/* --------------------- * /* --------------------- *
* Object implementation * * Object implementation *
* --------------------- */ * --------------------- */
@ -159,6 +167,7 @@ impl Display for Object {
Object::LoxFunction(func) => func.fmt(f), Object::LoxFunction(func) => func.fmt(f),
Object::Class(cls) => cls.borrow().fmt(f), Object::Class(cls) => cls.borrow().fmt(f),
Object::Instance(inst) => inst.fmt(f), Object::Instance(inst) => inst.fmt(f),
Object::BoundMethod(bm) => bm.fmt(f),
} }
} }
} }