#[macro_use]
use crate::stdlib::*;
use self::assign::*;
#[derive(Debug)]
pub struct MapAssign<T> {
pub sink: Ref<T>, pub source: Ref<T>, }
impl<T> MechFunctionImpl for MapAssign<T>
where
T: Debug + Clone + Sync + Send + PartialEq + 'static,
Ref<T>: ToValue,
{
fn solve(&self) {
let source_ptr = self.source.as_ptr();
let sink_ptr = self.sink.as_mut_ptr();
unsafe {
*sink_ptr = (*source_ptr).clone();
}
}
fn out(&self) -> Value { self.sink.to_value()}
fn to_string(&self) -> String {format!("{:#?}", self)}
}
#[cfg(feature = "compiler")]
impl<T> MechFunctionCompiler for MapAssign<T>
where
T: CompileConst + ConstElem + AsValueKind,
{
fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
let name = format!("MapAssign<{}>", T::as_value_kind());
compile_unop!(name,self.sink,self.source,ctx,FeatureFlag::Builtin(FeatureKind::Assign));
}
}
fn impl_set_map_value_fxn(
sink: Value,
source: Value,
key: Value,
) -> MResult<Box<dyn MechFunction>> {
match &sink {
Value::Map(map_ref) => {
let mut map = map_ref.borrow_mut();
if key.kind() != map.key_kind {
return Err(MechError::new(
MapKeyKindMismatchError {
expected_kind: map.key_kind.clone(),
actual_kind: key.kind(),
},
None,
)
.with_compiler_loc());
}
let value = map.map.entry(key.clone()).or_insert_with(|| {
source.clone()
}).clone();
match (&value, &source) {
#[cfg(feature = "bool")]
(Value::Bool(sink), Value::Bool(source)) => {
Ok(Box::new(MapAssign { sink: sink.clone(), source: source.clone() }))
}
#[cfg(feature = "i64")]
(Value::I64(sink), Value::I64(source)) => {
Ok(Box::new(MapAssign { sink: sink.clone(), source: source.clone() }))
}
#[cfg(feature = "f64")]
(Value::F64(sink), Value::F64(source)) => {
Ok(Box::new(MapAssign { sink: sink.clone(), source: source.clone() }))
}
#[cfg(feature = "string")]
(Value::String(sink), Value::String(source)) => {
Ok(Box::new(MapAssign { sink: sink.clone(), source: source.clone() }))
}
_ => Err(MechError::new(
MapValueKindMismatchError {
expected_kind: map.value_kind.clone(),
actual_kind: source.kind(),
},
None,
)
.with_compiler_loc()),
}
}
_ => Err(MechError::new(
UnhandledFunctionArgumentKind3 {
arg: (sink.kind(), source.kind(), key.kind()),
fxn_name: "map/assign".to_string(),
},
None,
)
.with_compiler_loc()),
}
}
pub struct MapAssignScalar {}
impl NativeFunctionCompiler for MapAssignScalar {
fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
if arguments.len() < 3 {
return Err(MechError::new(
IncorrectNumberOfArguments {
expected: 3,
found: arguments.len(),
},
None,
)
.with_compiler_loc());
}
let sink = arguments[0].clone();
let source = arguments[1].clone();
let key = arguments[2].clone();
match impl_set_map_value_fxn(sink.clone(), source.clone(), key.clone()) {
Ok(fxn) => Ok(fxn),
Err(_) => match &sink {
Value::MutableReference(sink_ref) => {
impl_set_map_value_fxn(sink_ref.borrow().clone(), source, key)
}
_ => Err(MechError::new(
UnhandledFunctionArgumentKind3 {
arg: (arguments[0].kind(), arguments[1].kind(), arguments[2].kind()),
fxn_name: "map/assign".to_string(),
},
None,
)
.with_compiler_loc()),
},
}
}
}
#[derive(Debug, Clone)]
pub struct UndefinedMapKeyError {
pub key: ValueKind,
}
impl MechErrorKind for UndefinedMapKeyError {
fn name(&self) -> &str {
"UndefinedMapKey"
}
fn message(&self) -> String {
format!("Key {:?} is not defined in this map.", self.key)
}
}