mech_interpreter/stdlib/assign/
mod.rs

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// ----------------------------------------------------------------------------
19// Assign 
20// ----------------------------------------------------------------------------
21
22// x = 1 ----------------------------------------------------------------------
23
24#[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
173// x += y ----------------------------------------------------------------------
174
175pub 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}