#[macro_use]
use crate::stdlib::*;
#[derive(Debug)]
pub struct MapAccessField {
pub out: Value,
pub source: Ref<MechMap>,
}
impl MechFunctionImpl for MapAccessField {
fn solve(&self) {
()
}
fn out(&self) -> Value {self.out.clone()}
fn to_string(&self) -> String {format!("{:#?}", self)}
}
#[cfg(feature = "compiler")]
impl MechFunctionCompiler for MapAccessField {
fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
let mut registers = [0, 0];
registers[0] = compile_register!(self.out, ctx);
registers[1] = compile_register_brrw!(self.source, ctx);
ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Access));
ctx.emit_unop(
hash_str("MapAccessField"),
registers[0],
registers[1],
);
return Ok(registers[0]);
}
}
pub fn impl_access_map_fxn(source: Value, key: Value) -> MResult<Box<dyn MechFunction>> {
match (source, key) {
(Value::Map(map), key) => {
let map_ref = map.borrow();
match map_ref.map.get(&key) {
Some(value) => Ok(Box::new(MapAccessField {
out: value.clone(),
source: map.clone(),
})),
None => Err(MechError::new(
UndefinedMapKeyError { key: key.to_string() },
None,
).with_compiler_loc()),
}
}
(source, key) => Err(MechError::new(
UnhandledFunctionArgumentKind2 {
arg: (source.kind(), key.kind()),
fxn_name: "MapAccess".to_string(),
},
None,
).with_compiler_loc()),
}
}
pub struct MapAccess {}
impl NativeFunctionCompiler for MapAccess {
fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
if arguments.len() != 2 {
return Err(MechError::new(
IncorrectNumberOfArguments {
expected: 2,
found: arguments.len(),
},
None,
).with_compiler_loc());
}
let src = &arguments[0];
let key = &arguments[1];
match src.kind().deref_kind() {
#[cfg(feature = "map")]
ValueKind::Map(key_kind, _) => {
if key.kind() != *key_kind {
return Err(MechError::new(
UnhandledFunctionArgumentKind2 { arg: (src.kind(), key.kind()), fxn_name: "MapAccess".to_string() },
None,
).with_compiler_loc());
}
}
_ => unreachable!(),
};
match impl_access_map_fxn(src.clone(), key.clone()) {
Ok(fxn) => Ok(fxn),
Err(_) => {
match src {
Value::MutableReference(map) => {
impl_access_map_fxn(map.borrow().clone(), key.clone())
}
_ => Err(MechError::new(
UnhandledFunctionArgumentKind2 {
arg: (src.kind(), key.kind()),
fxn_name: "MapAccess".to_string(),
},
None,
).with_compiler_loc()),
}
}
}
}
}
#[derive(Debug, Clone)]
pub struct UndefinedMapKeyError {
pub key: String,
}
impl MechErrorKind for UndefinedMapKeyError {
fn name(&self) -> &str {
"UndefinedMapKey"
}
fn message(&self) -> String {
format!("Key id `{}` not found in key_index.", self.key)
}
}