From 3e4aea0d78a1eaba08dfdc653f709817446c347b Mon Sep 17 00:00:00 2001 From: Emmanuel Benoit Date: Mon, 9 Jan 2023 11:19:42 +0100 Subject: [PATCH] Interpreter - Working bound methods --- src/interpreter/classes.rs | 32 ++++++++++++++++++++++++++++---- src/interpreter/interpretable.rs | 2 +- src/interpreter/value.rs | 11 ++++++++++- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/interpreter/classes.rs b/src/interpreter/classes.rs index 494d0a8..acf0a70 100644 --- a/src/interpreter/classes.rs +++ b/src/interpreter/classes.rs @@ -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::{ errors::{ErrorKind, SloxError, SloxResult}, @@ -77,12 +82,16 @@ impl Instance { } } - pub(super) fn get(&self, name: &Token) -> SloxResult { + pub(super) fn get(&self, this_value: &Value, name: &Token) -> SloxResult { if let Some(value) = self.fields.get(&name.lexeme) { return Ok(value.clone()); } - if let Some(method) = self.class.borrow().methods.get(&name.lexeme) { - return Ok(Value::from(method.clone())); + if self.class.borrow().methods.get(&name.lexeme).is_some() { + let bound_method = BoundMethod { + instance: this_value.clone(), + method: name.lexeme.clone(), + }; + return Ok(Value::from(bound_method)); } Err(SloxError::with_token( @@ -150,6 +159,21 @@ impl Callable for BoundMethod { .environment .borrow_mut() .define(&self.this_token(), Some(self.instance.clone()))?; + println!("{:?}", this_env.locals); 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!( + "", + self.method, instance + )) + }, + || panic!("Instance value does not contain an instance"), + ) + } +} diff --git a/src/interpreter/interpretable.rs b/src/interpreter/interpretable.rs index fa35f8b..e781ad7 100644 --- a/src/interpreter/interpretable.rs +++ b/src/interpreter/interpretable.rs @@ -539,7 +539,7 @@ impl ExprNode { ) -> InterpreterResult { let instance = get_expr.instance.interpret(itpr_state)?.result(); 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"), ) } diff --git a/src/interpreter/value.rs b/src/interpreter/value.rs index 7f1b8cd..0de565a 100644 --- a/src/interpreter/value.rs +++ b/src/interpreter/value.rs @@ -1,7 +1,7 @@ use std::{cell::RefCell, fmt::Display, rc::Rc}; use super::{ - classes::{Class, ClassRef, Instance}, + classes::{Class, ClassRef, Instance, BoundMethod}, functions::Function, native_fn::NativeFunction, Callable, @@ -23,6 +23,7 @@ pub enum Object { LoxFunction(Function), Class(ClassRef), Instance(Instance), + BoundMethod(BoundMethod), } /* -------------------- * @@ -56,6 +57,7 @@ impl Value { Object::LoxFunction(func) => fok(func), Object::Class(class) => fok(class), Object::Instance(_) => ferr(), + Object::BoundMethod(bm) => fok(bm), } } @@ -148,6 +150,12 @@ impl From for Value { } } +impl From for Value { + fn from(value: BoundMethod) -> Self { + Value::Object(Rc::new(RefCell::new(Object::BoundMethod(value)))) + } +} + /* --------------------- * * Object implementation * * --------------------- */ @@ -159,6 +167,7 @@ impl Display for Object { Object::LoxFunction(func) => func.fmt(f), Object::Class(cls) => cls.borrow().fmt(f), Object::Instance(inst) => inst.fmt(f), + Object::BoundMethod(bm) => bm.fmt(f), } } }