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