mech_interpreter/stdlib/assign/
map.rs1#[macro_use]
2use crate::stdlib::*;
3use self::assign::*;
4
5#[derive(Debug)]
6pub struct MapAssign<T> {
7 pub sink: Ref<T>, pub source: Ref<T>, }
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 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 let value = map.map.entry(key.clone()).or_insert_with(|| {
62 source.clone()
63 }).clone();
64
65 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}