mech_interpreter/stdlib/assign/
tuple.rs1#[macro_use]
2use crate::stdlib::*;
3use self::assign::*;
4
5use crate::*;
6
7#[derive(Debug)]
10pub struct TupleAssign<T> {
11 pub sink: Ref<T>, pub source: Ref<T> }
14
15impl<T> MechFunctionImpl for TupleAssign<T>
16where
17 T: Debug + Clone + Sync + Send + PartialEq + 'static,
18 Ref<T>: ToValue,
19{
20 fn solve(&self) {
21 let source_ptr = self.source.as_ptr();
22 let sink_ptr = self.sink.as_mut_ptr();
23 unsafe {
24 *sink_ptr = (*source_ptr).clone();
25 }
26 }
27
28 fn out(&self) -> Value {
29 self.sink.to_value()
30 }
31
32 fn to_string(&self) -> String {
33 format!("{:#?}", self)
34 }
35}
36
37#[cfg(feature = "compiler")]
38impl<T> MechFunctionCompiler for TupleAssign<T>
39where
40 T: CompileConst + ConstElem + AsValueKind,
41{
42 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
43 let name = format!("TupleAssign<{}>", T::as_value_kind());
44 compile_unop!(
45 name,
46 self.sink,
47 self.source,
48 ctx,
49 FeatureFlag::Builtin(FeatureKind::Assign)
50 );
51 }
52}
53
54fn impl_tuple_assign_fxn(
57 tuple: Value,
58 source: Value,
59 index: usize, ) -> MResult<Box<dyn MechFunction>> {
61
62 match &tuple {
63 Value::Tuple(tuple_ref) => {
64 let tuple = tuple_ref.borrow();
65
66 if index >= tuple.size() {
67 return Err(MechError2::new(
68 TupleIndexOutOfBoundsError {
69 ix: index + 1,
70 len: tuple.size(),
71 },
72 None,
73 ).with_compiler_loc());
74 }
75
76 let sink = tuple.elements[index].clone();
77
78 match (&*sink, &source) {
79
80 #[cfg(feature = "bool")]
81 (Value::Bool(sink), Value::Bool(source)) => {
82 Ok(Box::new(TupleAssign {
83 sink: sink.clone(),
84 source: source.clone(),
85 }))
86 }
87
88 #[cfg(feature = "i64")]
89 (Value::I64(sink), Value::I64(source)) => {
90 Ok(Box::new(TupleAssign {
91 sink: sink.clone(),
92 source: source.clone(),
93 }))
94 }
95
96 #[cfg(feature = "f64")]
97 (Value::F64(sink), Value::F64(source)) => {
98 Ok(Box::new(TupleAssign {
99 sink: sink.clone(),
100 source: source.clone(),
101 }))
102 }
103
104 #[cfg(feature = "string")]
105 (Value::String(sink), Value::String(source)) => {
106 Ok(Box::new(TupleAssign {
107 sink: sink.clone(),
108 source: source.clone(),
109 }))
110 }
111
112 _ => Err(MechError2::new(
113 TupleElementKindMismatchError {
114 expected: sink.kind(),
115 actual: source.kind(),
116 },
117 None,
118 ).with_compiler_loc()),
119 }
120 }
121
122 _ => Err(MechError2::new(
123 DestructureExpectedTupleError {
124 value: tuple.kind(),
125 },
126 None,
127 ).with_compiler_loc()),
128 }
129}
130
131pub struct TupleAssignScalar {}
134
135impl NativeFunctionCompiler for TupleAssignScalar {
136 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
137
138 if arguments.len() != 3 {
139 return Err(MechError2::new(
140 IncorrectNumberOfArguments {
141 expected: 3,
142 found: arguments.len(),
143 },
144 None,
145 ).with_compiler_loc());
146 }
147
148 let tuple = arguments[0].clone();
149 let source = arguments[1].clone();
150 let index_val = arguments[2].clone();
151
152 let index = match &index_val {
153 Value::Index(ix) => {
154 let ix = *ix.borrow() as isize;
155 if ix <= 0 {
156 return Err(MechError2::new(
157 TupleIndexOutOfBoundsError {
158 ix: ix as usize,
159 len: 0,
160 },
161 None,
162 ).with_compiler_loc());
163 }
164 (ix - 1) as usize
165 }
166
167 _ => {
168 return Err(MechError2::new(
169 UnhandledFunctionArgumentKind3 {
170 arg: (tuple.kind(), source.kind(), index_val.kind()),
171 fxn_name: "tuple/assign".to_string(),
172 },
173 None,
174 ).with_compiler_loc());
175 }
176 };
177
178 match impl_tuple_assign_fxn(tuple.clone(), source.clone(), index) {
179 Ok(fxn) => Ok(fxn),
180
181 Err(_) => match &tuple {
182 Value::MutableReference(tuple_ref) => {
183 impl_tuple_assign_fxn(tuple_ref.borrow().clone(), source, index)
184 }
185
186 _ => Err(MechError2::new(
187 UnhandledFunctionArgumentKind3 {
188 arg: (arguments[0].kind(), arguments[1].kind(), arguments[2].kind()),
189 fxn_name: "tuple/assign".to_string(),
190 },
191 None,
192 ).with_compiler_loc()),
193 },
194 }
195 }
196}
197
198#[derive(Debug, Clone)]
201pub struct TupleElementKindMismatchError {
202 pub expected: ValueKind,
203 pub actual: ValueKind,
204}
205
206impl MechErrorKind2 for TupleElementKindMismatchError {
207 fn name(&self) -> &str {
208 "TupleElementKindMismatch"
209 }
210
211 fn message(&self) -> String {
212 format!(
213 "Tuple element kind mismatch: expected {:?}, found {:?}",
214 self.expected, self.actual
215 )
216 }
217}