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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use std::any::Any;
use std::cmp::Ordering;
use object::Object;
use value::{Value, ValueContext};
use executor::ExecutorImpl;
use errors::{VMError, FieldNotFoundError};

impl Object for String {
    fn get_children(&self) -> Vec<usize> {
        Vec::new()
    }

    fn typename(&self) -> &str {
        "string"
    }

    fn as_any(&self) -> &Any {
        self as &Any
    }

    fn as_any_mut(&mut self) -> &mut Any {
        self as &mut Any
    }

    fn to_i64(&self) -> i64 {
        match self.as_str().parse::<i64>() {
            Ok(v) => v,
            Err(_) => panic!(VMError::from("Cannot parse as i64"))
        }
    }

    fn to_f64(&self) -> f64 {
        match self.as_str().parse::<f64>() {
            Ok(v) => v,
            Err(_) => panic!(VMError::from("Cannot parse as f64"))
        }
    }

    fn to_str(&self) -> &str {
        self.as_str()
    }

    fn to_bool(&self) -> bool {
        *self == ""
    }

    fn test_eq(&self, other: &ValueContext) -> bool {
        if let Some(other) = other.as_object_direct().as_any().downcast_ref::<Self>() {
            *other == *self
        } else {
            false
        }
    }

    fn compare(&self, other: &ValueContext) -> Option<Ordering> {
        if let Some(other) = other.as_object_direct().as_any().downcast_ref::<Self>() {
            self.partial_cmp(&other)
        } else {
            None
        }
    }

    fn call_field(&self, field_name: &str, executor: &mut ExecutorImpl) -> Value {
        match field_name {
            "__add__" => {
                let right = executor.get_current_frame().must_get_argument(0);
                let ret = self.clone() + ValueContext::new(&right, executor.get_object_pool()).to_str().as_ref();

                Value::Object(
                    executor.get_object_pool_mut().allocate(
                        Box::new(ret)
                    )
                )
            },
            _ => panic!(VMError::from(FieldNotFoundError::from_field_name(field_name)))
        }
    }
}