slvm/vm/
call_collection.rs

1use crate::{GVm, Handle, VMError, VMResult, Value};
2
3impl<ENV> GVm<ENV> {
4    pub(crate) fn call_map(
5        &mut self,
6        handle: Handle,
7        first_reg: u16,
8        num_args: u16,
9    ) -> VMResult<Value> {
10        match num_args {
11            1 => {
12                let map = self.heap().get_map(handle);
13                let res = if let Some(val) = map.get(self, self.register(first_reg as usize + 1)) {
14                    val
15                } else {
16                    Value::Nil
17                };
18                Ok(res)
19            }
20            2 => {
21                let map = self.heap().get_map(handle);
22                let res = if let Some(val) = map.get(self, self.register(first_reg as usize + 1)) {
23                    val
24                } else {
25                    self.register(first_reg as usize + 2)
26                };
27                Ok(res)
28            }
29            _ => Err(VMError::new_vm("Map wrong number of arguments.")),
30        }
31    }
32
33    pub(crate) fn call_vector(
34        &mut self,
35        handle: Handle,
36        first_reg: u16,
37        num_args: u16,
38    ) -> VMResult<Value> {
39        match num_args {
40            1 => {
41                let v = self.heap().get_vector(handle);
42                let idx = self.register(first_reg as usize + 1).get_int(self)?;
43                let idx = if idx >= 0 { idx } else { v.len() as i64 + idx };
44                let res = if idx >= 0 {
45                    if let Some(val) = v.get(idx as usize) {
46                        *val
47                    } else {
48                        Value::Nil
49                    }
50                } else {
51                    Value::Nil
52                };
53                Ok(res)
54            }
55            2 => {
56                let v = self.heap().get_vector(handle);
57                let idx = self.register(first_reg as usize + 1).get_int(self)?;
58                let idx = if idx >= 0 { idx } else { v.len() as i64 + idx };
59                let res = if idx >= 0 {
60                    if let Some(val) = v.get(idx as usize) {
61                        *val
62                    } else {
63                        self.register(first_reg as usize + 2)
64                    }
65                } else {
66                    self.register(first_reg as usize + 2)
67                };
68                Ok(res)
69            }
70            _ => Err(VMError::new_vm("Vector wrong number of arguments.")),
71        }
72    }
73
74    pub(crate) fn call_list(
75        &mut self,
76        head: Value,
77        first_reg: u16,
78        num_args: u16,
79    ) -> VMResult<Value> {
80        match num_args {
81            1 => {
82                let idx = self.register(first_reg as usize + 1).get_int(self)?;
83                let res = if idx >= 0 {
84                    if let Some((mut car_out, mut cdr)) = head.get_pair(self) {
85                        for _ in 0..idx {
86                            if let Some((car, cdr_in)) = cdr.get_pair(self) {
87                                car_out = car;
88                                cdr = cdr_in;
89                            } else {
90                                return Err(VMError::new_vm("list: invalid index."));
91                            }
92                        }
93                        car_out
94                    } else {
95                        return Err(VMError::new_vm("Not a list."));
96                    }
97                } else {
98                    return Err(VMError::new_vm("A list requires a positive index."));
99                };
100                Ok(res)
101            }
102            _ => Err(VMError::new_vm("List wrong number of arguments.")),
103        }
104    }
105}