slvm/vm/
call_collection.rs

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use crate::{GVm, Handle, VMError, VMResult, Value};

impl<ENV> GVm<ENV> {
    pub(crate) fn call_map(
        &mut self,
        handle: Handle,
        first_reg: u16,
        num_args: u16,
    ) -> VMResult<Value> {
        match num_args {
            1 => {
                let map = self.heap().get_map(handle);
                let res = if let Some(val) = map.get(self, self.register(first_reg as usize + 1)) {
                    val
                } else {
                    Value::Nil
                };
                Ok(res)
            }
            2 => {
                let map = self.heap().get_map(handle);
                let res = if let Some(val) = map.get(self, self.register(first_reg as usize + 1)) {
                    val
                } else {
                    self.register(first_reg as usize + 2)
                };
                Ok(res)
            }
            _ => Err(VMError::new_vm("Map wrong number of arguments.")),
        }
    }

    pub(crate) fn call_vector(
        &mut self,
        handle: Handle,
        first_reg: u16,
        num_args: u16,
    ) -> VMResult<Value> {
        match num_args {
            1 => {
                let v = self.heap().get_vector(handle);
                let idx = self.register(first_reg as usize + 1).get_int(self)?;
                let idx = if idx >= 0 { idx } else { v.len() as i64 + idx };
                let res = if idx >= 0 {
                    if let Some(val) = v.get(idx as usize) {
                        *val
                    } else {
                        Value::Nil
                    }
                } else {
                    Value::Nil
                };
                Ok(res)
            }
            2 => {
                let v = self.heap().get_vector(handle);
                let idx = self.register(first_reg as usize + 1).get_int(self)?;
                let idx = if idx >= 0 { idx } else { v.len() as i64 + idx };
                let res = if idx >= 0 {
                    if let Some(val) = v.get(idx as usize) {
                        *val
                    } else {
                        self.register(first_reg as usize + 2)
                    }
                } else {
                    self.register(first_reg as usize + 2)
                };
                Ok(res)
            }
            _ => Err(VMError::new_vm("Vector wrong number of arguments.")),
        }
    }

    pub(crate) fn call_list(
        &mut self,
        head: Value,
        first_reg: u16,
        num_args: u16,
    ) -> VMResult<Value> {
        match num_args {
            1 => {
                let idx = self.register(first_reg as usize + 1).get_int(self)?;
                let res = if idx >= 0 {
                    if let Some((mut car_out, mut cdr)) = head.get_pair(self) {
                        for _ in 0..idx {
                            if let Some((car, cdr_in)) = cdr.get_pair(self) {
                                car_out = car;
                                cdr = cdr_in;
                            } else {
                                return Err(VMError::new_vm("list: invalid index."));
                            }
                        }
                        car_out
                    } else {
                        return Err(VMError::new_vm("Not a list."));
                    }
                } else {
                    return Err(VMError::new_vm("A list requires a positive index."));
                };
                Ok(res)
            }
            _ => Err(VMError::new_vm("List wrong number of arguments.")),
        }
    }
}