1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//! A method object represents an object's method call (currently only for built-ins)

use super::{Dict, Object, RefValue, Value};
use crate::vm::*;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Method {
    pub(super) object: RefValue,
    pub(super) method: RefValue,
}

impl Object for Method {
    fn name(&self) -> &'static str {
        "method"
    }

    fn repr(&self) -> String {
        let mut repr = self.method.repr();
        if repr.starts_with("<") && repr.ends_with(">") {
            repr = repr[1..repr.len() - 1].to_string();
        }

        format!(
            "<{} {} of {} object at {:#x}>",
            self.name(),
            repr,
            self.object.name(),
            self.object.id()
        )
    }

    fn is_callable(&self, without_arguments: bool) -> bool {
        self.method.is_callable(without_arguments)
    }

    fn is_consuming(&self) -> bool {
        self.method.is_consuming()
    }

    fn call_direct(
        &self,
        context: &mut Context,
        args: usize,
        nargs: Option<Dict>,
    ) -> Result<Accept, Reject> {
        // A method call injects the relating "this" object into the stack and calls the method afterwards.
        context.stack.insert(
            context.stack.len() - args,
            Capture::Value(self.object.clone(), None, 0),
        );

        self.method.call_direct(context, args + 1, nargs)
    }
}

impl From<Method> for RefValue {
    fn from(method: Method) -> Self {
        Value::Object(Box::new(method)).into()
    }
}