diff --git a/src/interpreter/value.rs b/src/interpreter/value.rs index 9fbdd0f..6413ed5 100644 --- a/src/interpreter/value.rs +++ b/src/interpreter/value.rs @@ -1,10 +1,17 @@ use std::{cell::RefCell, fmt::Display, rc::Rc}; +use lazy_static::lazy_static; + +use crate::{ + errors::{ErrorKind, SloxError, SloxResult}, + tokens::{Token, TokenType}, +}; + use super::{ classes::{Class, ClassRef, Instance, InstanceRef, PropertyCarrier}, functions::Function, native_fn::NativeFunction, - Callable, + Callable, InterpreterState, }; /// A value being handled by the interpreter. @@ -25,6 +32,17 @@ pub enum Object { Instance(InstanceRef), } +lazy_static! { + static ref TO_STRING_TOKEN: Token = { + let name = "to_string".to_owned(); + Token { + token_type: TokenType::Identifier(name.clone()), + lexeme: name, + line: 0, + } + }; +} + /* -------------------- * * Value implementation * * -------------------- */ @@ -106,6 +124,36 @@ impl Value { _ => ferr(), } } + + /// Convert a value into a string. This can only be done fully with an interpreter state, + /// because it might require calling an instance's to_string method. + pub fn convert_to_string( + &self, + es: &mut InterpreterState, + at_token: &Token, + ) -> SloxResult { + self.with_instance( + |inst| { + if let Ok(result) = inst.get(es, &TO_STRING_TOKEN) { + result + .with_callable( + |callable| callable.call(es, vec![]), + || { + Err(SloxError::with_token( + ErrorKind::Runtime, + at_token, + "to_string() isn't callable".to_owned(), + )) + }, + ) + .map(|r| r.to_string()) + } else { + Ok(inst.borrow().to_string()) + } + }, + || Ok(self.to_string()), + ) + } } impl PartialEq for Value {