Interpreter - Initial implementation of bound methods
This commit is contained in:
parent
a2986a1342
commit
542bc56aad
2 changed files with 63 additions and 1 deletions
|
@ -2,7 +2,7 @@ use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{ErrorKind, SloxError, SloxResult},
|
errors::{ErrorKind, SloxError, SloxResult},
|
||||||
tokens::Token,
|
tokens::{Token, TokenType},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{functions::Function, Callable, InterpreterState, Value};
|
use super::{functions::Function, Callable, InterpreterState, Value};
|
||||||
|
@ -24,6 +24,13 @@ pub struct Instance {
|
||||||
fields: HashMap<String, Value>,
|
fields: HashMap<String, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A method bound to an instance.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct BoundMethod {
|
||||||
|
instance: Value,
|
||||||
|
method: String,
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------- *
|
/* -------------------- *
|
||||||
* Class implementation *
|
* Class implementation *
|
||||||
* -------------------- */
|
* -------------------- */
|
||||||
|
@ -88,6 +95,18 @@ impl Instance {
|
||||||
pub(super) fn set(&mut self, name: &Token, value: Value) {
|
pub(super) fn set(&mut self, name: &Token, value: Value) {
|
||||||
self.fields.insert(name.lexeme.clone(), value);
|
self.fields.insert(name.lexeme.clone(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_method<F, Rt>(&self, name: &str, f: F) -> Rt
|
||||||
|
where
|
||||||
|
F: FnOnce(&Function) -> Rt,
|
||||||
|
{
|
||||||
|
let cls = self.class.borrow();
|
||||||
|
let method = cls
|
||||||
|
.methods
|
||||||
|
.get(name)
|
||||||
|
.expect(&format!("Method {} not found", name));
|
||||||
|
f(method)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Instance {
|
impl Display for Instance {
|
||||||
|
@ -95,3 +114,42 @@ impl Display for Instance {
|
||||||
f.write_fmt(format_args!("<Instance of {}>", self.class.borrow(),))
|
f.write_fmt(format_args!("<Instance of {}>", self.class.borrow(),))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------- *
|
||||||
|
* Bound method implementation *
|
||||||
|
* --------------------------- */
|
||||||
|
|
||||||
|
impl BoundMethod {
|
||||||
|
fn with_method<F, Rt>(&self, f: F) -> Rt
|
||||||
|
where
|
||||||
|
F: FnOnce(&Function) -> Rt,
|
||||||
|
{
|
||||||
|
self.instance.with_instance(
|
||||||
|
|instance| instance.with_method(&self.method, f),
|
||||||
|
|| panic!("Instance value does not contain an instance"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn this_token(&self) -> Token {
|
||||||
|
Token {
|
||||||
|
token_type: TokenType::This,
|
||||||
|
lexeme: "this".to_owned(),
|
||||||
|
line: self.with_method(|method| method.name().expect("Method has no name").line),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Callable for BoundMethod {
|
||||||
|
fn arity(&self) -> usize {
|
||||||
|
self.with_method(|m| m.arity())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, itpr_state: &mut InterpreterState, arguments: Vec<Value>) -> SloxResult<Value> {
|
||||||
|
let mut this_env = InterpreterState::create_child(itpr_state);
|
||||||
|
this_env
|
||||||
|
.environment
|
||||||
|
.borrow_mut()
|
||||||
|
.define(&self.this_token(), Some(self.instance.clone()))?;
|
||||||
|
self.with_method(|m| m.call(&mut this_env, arguments))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,10 @@ impl Function {
|
||||||
env: environment,
|
env: environment,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn name(&self) -> Option<&Token> {
|
||||||
|
self.name.as_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Callable for Function {
|
impl Callable for Function {
|
||||||
|
|
Loading…
Reference in a new issue