mech_interpreter/stdlib/assign/
map.rs

1#[macro_use] 
2use crate::stdlib::*; 
3use self::assign::*;
4
5#[derive(Debug)]
6pub struct MapAssign<T> {
7  pub sink: Ref<T>,   // map value slot
8  pub source: Ref<T>, // rhs value
9}
10
11impl<T> MechFunctionImpl for MapAssign<T>
12where
13  T: Debug + Clone + Sync + Send + PartialEq + 'static,
14  Ref<T>: ToValue,
15{
16  fn solve(&self) {
17    let source_ptr = self.source.as_ptr();
18    let sink_ptr = self.sink.as_mut_ptr();
19    unsafe {
20      *sink_ptr = (*source_ptr).clone();
21    }
22  }
23  fn out(&self) -> Value { self.sink.to_value()}
24  fn to_string(&self) -> String {format!("{:#?}", self)}
25}
26
27#[cfg(feature = "compiler")]
28impl<T> MechFunctionCompiler for MapAssign<T>
29where
30  T: CompileConst + ConstElem + AsValueKind,
31{
32  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
33    let name = format!("MapAssign<{}>", T::as_value_kind());
34    compile_unop!(name,self.sink,self.source,ctx,FeatureFlag::Builtin(FeatureKind::Assign));
35  }
36}
37
38
39fn impl_set_map_value_fxn(
40  sink: Value,
41  source: Value,
42  key: Value,
43) -> MResult<Box<dyn MechFunction>> {
44  match &sink {
45    Value::Map(map_ref) => {
46      let mut map = map_ref.borrow_mut();
47
48      // Key kind check
49      if key.kind() != map.key_kind {
50        return Err(MechError2::new(
51          MapKeyKindMismatchError {
52            expected_kind: map.key_kind.clone(),
53            actual_kind: key.kind(),
54          },
55          None,
56        )
57        .with_compiler_loc());
58      }
59
60      // Get existing value slot or insert a default value
61      let value = map.map.entry(key.clone()).or_insert_with(|| {
62        source.clone()
63      }).clone();
64
65      // Dispatch by concrete value type
66      match (&value, &source) {
67        #[cfg(feature = "bool")]
68        (Value::Bool(sink), Value::Bool(source)) => {
69          Ok(Box::new(MapAssign { sink: sink.clone(), source: source.clone() }))
70        }
71
72        #[cfg(feature = "i64")]
73        (Value::I64(sink), Value::I64(source)) => {
74          Ok(Box::new(MapAssign { sink: sink.clone(), source: source.clone() }))
75        }
76
77        #[cfg(feature = "f64")]
78        (Value::F64(sink), Value::F64(source)) => {
79          Ok(Box::new(MapAssign { sink: sink.clone(), source: source.clone() }))
80        }
81
82        #[cfg(feature = "string")]
83        (Value::String(sink), Value::String(source)) => {
84          Ok(Box::new(MapAssign { sink: sink.clone(), source: source.clone() }))
85        }
86
87        _ => Err(MechError2::new(
88          MapValueKindMismatchError {
89            expected_kind: map.value_kind.clone(),
90            actual_kind: source.kind(),
91          },
92          None,
93        )
94        .with_compiler_loc()),
95      }
96    }
97
98    _ => Err(MechError2::new(
99      UnhandledFunctionArgumentKind3 {
100        arg: (sink.kind(), source.kind(), key.kind()),
101        fxn_name: "map/assign".to_string(),
102      },
103      None,
104    )
105    .with_compiler_loc()),
106  }
107}
108
109
110pub struct MapAssignScalar {}
111
112impl NativeFunctionCompiler for MapAssignScalar {
113  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
114    if arguments.len() < 3 {
115      return Err(MechError2::new(
116        IncorrectNumberOfArguments {
117          expected: 3,
118          found: arguments.len(),
119        },
120        None,
121      )
122      .with_compiler_loc());
123    }
124
125    let sink = arguments[0].clone();
126    let source = arguments[1].clone();
127    let key = arguments[2].clone();
128
129    match impl_set_map_value_fxn(sink.clone(), source.clone(), key.clone()) {
130      Ok(fxn) => Ok(fxn),
131
132      Err(_) => match &sink {
133        Value::MutableReference(sink_ref) => {
134          impl_set_map_value_fxn(sink_ref.borrow().clone(), source, key)
135        }
136        _ => Err(MechError2::new(
137          UnhandledFunctionArgumentKind3 {
138            arg: (arguments[0].kind(), arguments[1].kind(), arguments[2].kind()),
139            fxn_name: "map/assign".to_string(),
140          },
141          None,
142        )
143        .with_compiler_loc()),
144      },
145    }
146  }
147}
148
149
150#[derive(Debug, Clone)]
151pub struct UndefinedMapKeyError {
152  pub key: ValueKind,
153}
154
155impl MechErrorKind2 for UndefinedMapKeyError {
156  fn name(&self) -> &str {
157    "UndefinedMapKey"
158  }
159
160  fn message(&self) -> String {
161    format!("Key {:?} is not defined in this map.", self.key)
162  }
163}