slvm/vm/
call_collection.rs1use 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}