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#[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// ----------------------------------------------------------------------------
27// Assign 
28// ----------------------------------------------------------------------------
29
30// x = 1 ----------------------------------------------------------------------
31
32#[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
181// x += y ----------------------------------------------------------------------
182
183pub 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}