1#[macro_use]
2use crate::stdlib::*;
3
4#[cfg(feature = "matrix")]
5pub mod matrix;
6#[cfg(feature = "record")]
7pub mod record;
8#[cfg(feature = "table")]
9pub mod table;
10#[cfg(feature = "map")]
11pub mod map;
12#[cfg(feature = "tuple")]
13pub mod tuple;
14
15#[cfg(feature = "matrix")]
16pub use self::matrix::*;
17#[cfg(feature = "record")]
18pub use self::record::*;
19#[cfg(feature = "table")]
20pub use self::table::*;
21#[cfg(feature = "map")]
22pub use self::map::*;
23#[cfg(feature = "tuple")]
24pub use self::tuple::*;
25
26#[derive(Debug)]
33struct Assign<T> {
34 sink: Ref<T>,
35 source: Ref<T>,
36}
37impl<T> MechFunctionImpl for Assign<T>
38where
39 T: Clone + Debug,
40 Ref<T>: ToValue
41{
42 fn solve(&self) {
43 let source_ptr = self.source.as_ptr();
44 let sink_ptr = self.sink.as_mut_ptr();
45 unsafe {
46 *sink_ptr = (*source_ptr).clone();
47 }
48 }
49 fn out(&self) -> Value { self.sink.to_value() }
50 fn to_string(&self) -> String { format!("{:#?}", self) }
51}
52#[cfg(feature = "compiler")]
53impl<T> MechFunctionCompiler for Assign<T>
54where
55 T: CompileConst + ConstElem + AsValueKind,
56{
57 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
58 let name = format!("Assign<{}>", T::as_value_kind());
59 compile_unop!(name, self.sink, self.source, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );
60 }
61}
62
63#[macro_export]
64macro_rules! impl_assign_value_match_arms {
65 ($arg:expr,$($value_kind:ident, $feature:tt);+ $(;)?) => {
66 paste::paste! {
67 match $arg {
68 $(
69 #[cfg(feature = $feature)]
70 (Value::$value_kind(sink), Value::$value_kind(source)) => Ok(Box::new(Assign{ sink: sink.clone(), source: source.clone() })),
71 #[cfg(all(feature = $feature, feature = "matrix1"))]
72 (Value::[<Matrix $value_kind>](Matrix::Matrix1(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix1(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
73 #[cfg(all(feature = $feature, feature = "matrix2"))]
74 (Value::[<Matrix $value_kind>](Matrix::Matrix2(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix2(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
75 #[cfg(all(feature = $feature, feature = "matrix2x3"))]
76 (Value::[<Matrix $value_kind>](Matrix::Matrix2x3(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix2x3(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
77 #[cfg(all(feature = $feature, feature = "matrix3x2"))]
78 (Value::[<Matrix $value_kind>](Matrix::Matrix3x2(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix3x2(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
79 #[cfg(all(feature = $feature, feature = "matrix3"))]
80 (Value::[<Matrix $value_kind>](Matrix::Matrix3(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix3(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
81 #[cfg(all(feature = $feature, feature = "matrix4"))]
82 (Value::[<Matrix $value_kind>](Matrix::Matrix4(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix4(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
83 #[cfg(all(feature = $feature, feature = "matrixd"))]
84 (Value::[<Matrix $value_kind>](Matrix::DMatrix(sink)), Value::[<Matrix $value_kind>](Matrix::DMatrix(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
85 #[cfg(all(feature = $feature, feature = "vector2"))]
86 (Value::[<Matrix $value_kind>](Matrix::Vector2(sink)), Value::[<Matrix $value_kind>](Matrix::Vector2(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
87 #[cfg(all(feature = $feature, feature = "vector3"))]
88 (Value::[<Matrix $value_kind>](Matrix::Vector3(sink)), Value::[<Matrix $value_kind>](Matrix::Vector3(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
89 #[cfg(all(feature = $feature, feature = "vector4"))]
90 (Value::[<Matrix $value_kind>](Matrix::Vector4(sink)), Value::[<Matrix $value_kind>](Matrix::Vector4(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
91 #[cfg(all(feature = $feature, feature = "vectord"))]
92 (Value::[<Matrix $value_kind>](Matrix::DVector(sink)), Value::[<Matrix $value_kind>](Matrix::DVector(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
93 #[cfg(all(feature = $feature, feature = "row_vector2"))]
94 (Value::[<Matrix $value_kind>](Matrix::RowVector2(sink)), Value::[<Matrix $value_kind>](Matrix::RowVector2(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
95 #[cfg(all(feature = $feature, feature = "row_vector3"))]
96 (Value::[<Matrix $value_kind>](Matrix::RowVector3(sink)), Value::[<Matrix $value_kind>](Matrix::RowVector3(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
97 #[cfg(all(feature = $feature, feature = "row_vector4"))]
98 (Value::[<Matrix $value_kind>](Matrix::RowVector4(sink)), Value::[<Matrix $value_kind>](Matrix::RowVector4(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
99 #[cfg(all(feature = $feature, feature = "row_vectord"))]
100 (Value::[<Matrix $value_kind>](Matrix::RowDVector(sink)), Value::[<Matrix $value_kind>](Matrix::RowDVector(source))) => Ok(Box::new(Assign{sink: sink.clone(), source: source.clone()})),
101 )+
102 (sink, source) => Err(MechError2::new(
103 UnhandledFunctionArgumentKind2 {arg: (sink.kind(), source.kind()), fxn_name: "assign".to_string() },
104 None
105 ).with_compiler_loc()
106 ),
107 }
108 }
109 };
110}
111
112fn assign_value_fxn(sink: Value, source: Value) -> MResult<Box<dyn MechFunction>> {
113 impl_assign_value_match_arms!(
114 (sink, source),
115 Bool, "bool";
116 String, "string";
117 U8, "u8";
118 U16, "u16";
119 U32, "u32";
120 U64, "u64";
121 U128, "u128";
122 I8, "i8";
123 I16, "i16";
124 I32, "i32";
125 I64, "i64";
126 U128, "u128";
127 F32, "f32";
128 F64, "f64";
129 R64, "rational";
130 C64, "complex";
131 )
132}
133
134pub struct AssignValue {}
135impl NativeFunctionCompiler for AssignValue {
136 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
137 if arguments.len() <= 1 {
138 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
139 }
140 let sink = arguments[0].clone();
141 let source = arguments[1].clone();
142 match assign_value_fxn(sink.clone(),source.clone()) {
143 Ok(fxn) => Ok(fxn),
144 Err(x) => {
145 match (sink,source) {
146 (Value::MutableReference(sink),Value::MutableReference(source)) => { assign_value_fxn(sink.borrow().clone(),source.borrow().clone()) },
147 (sink,Value::MutableReference(source)) => { assign_value_fxn(sink.clone(),source.borrow().clone()) },
148 (Value::MutableReference(sink),source) => { assign_value_fxn(sink.borrow().clone(),source.clone()) },
149 (sink,source) => Err(MechError2::new(
150 UnhandledFunctionArgumentKind2 { arg: (sink.kind(), source.kind()), fxn_name: "assign".to_string() },
151 None
152 ).with_compiler_loc()
153 ),
154 }
155 }
156 }
157 }
158}
159
160pub struct AssignColumn {}
161impl NativeFunctionCompiler for AssignColumn {
162 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
163 if arguments.len() < 1 {
164 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
165 }
166 let src = &arguments[0];
167 match src.kind().deref_kind() {
168 #[cfg(feature = "table")]
169 ValueKind::Table(_,_) => AssignTableColumn{}.compile(&arguments),
170 #[cfg(feature = "record")]
171 ValueKind::Record(_) => AssignRecordField{}.compile(&arguments),
172 _ => Err(MechError2::new(
173 UnhandledFunctionArgumentKind1 { arg: src.kind(), fxn_name: "assign/column".to_string() },
174 None
175 ).with_compiler_loc()
176 ),
177 }
178 }
179}
180
181pub fn add_assign_value_fxn(sink: Value, source: Value) -> MResult<Box<dyn MechFunction>> {
184 match sink {
185 #[cfg(feature = "table")]
186 Value::Table(_) => add_assign_table_fxn(sink, source),
187 #[cfg(feature = "math_add_assign")]
188 _ => add_assign_math_fxn(sink, source),
189 _ => Err(MechError2::new(
190 UnhandledFunctionArgumentKind2 { arg: (sink.kind(), source.kind()), fxn_name: "assign/add".to_string() },
191 None
192 ).with_compiler_loc()
193 ),
194 }
195}
196
197pub struct AddAssignValue {}
198impl NativeFunctionCompiler for AddAssignValue {
199 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
200 if arguments.len() <= 1 {
201 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
202 }
203 let sink = arguments[0].clone();
204 let source = arguments[1].clone();
205 match add_assign_value_fxn(sink.clone(),source.clone()) {
206 Ok(fxn) => Ok(fxn),
207 Err(x) => {
208 match (sink,source) {
209 (Value::MutableReference(sink),Value::MutableReference(source)) => { add_assign_value_fxn(sink.borrow().clone(),source.borrow().clone()) },
210 (sink,Value::MutableReference(source)) => { add_assign_value_fxn(sink.clone(),source.borrow().clone()) },
211 (Value::MutableReference(sink),source) => { add_assign_value_fxn(sink.borrow().clone(),source.clone()) },
212 (sink,source) => Err(MechError2::new(
213 UnhandledFunctionArgumentKind2 { arg: (sink.kind(), source.kind()), fxn_name: "assign/add".to_string() },
214 None
215 ).with_compiler_loc()
216 ),
217 }
218 }
219 }
220 }
221}