mech_interpreter/stdlib/access/
map.rs

1#[macro_use]
2use crate::stdlib::*;
3
4#[derive(Debug)]
5pub struct MapAccessField {
6  pub out: Value,
7  pub source: Ref<MechMap>,
8}
9
10impl MechFunctionImpl for MapAccessField {
11  fn solve(&self) {
12    ()
13  }
14  fn out(&self) -> Value {self.out.clone()}
15  fn to_string(&self) -> String {format!("{:#?}", self)}
16}
17#[cfg(feature = "compiler")]
18impl MechFunctionCompiler for MapAccessField {
19    fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
20        let mut registers = [0, 0];
21        registers[0] = compile_register!(self.out, ctx);
22        registers[1] = compile_register_brrw!(self.source, ctx);
23        ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Access));
24        ctx.emit_unop(
25          hash_str("MapAccessField"),
26          registers[0],
27          registers[1],
28        );
29        return Ok(registers[0]);
30    }
31    }
32
33pub fn impl_access_map_fxn(source: Value, key: Value) -> MResult<Box<dyn MechFunction>> {
34  match (source, key) {
35
36    (Value::Map(map), key) => {
37      let map_ref = map.borrow();
38
39      match map_ref.map.get(&key) {
40        Some(value) => Ok(Box::new(MapAccessField {
41          out: value.clone(),
42          source: map.clone(),
43        })),
44        None => Err(MechError2::new(
45          UndefinedMapKeyError { key: key.to_string() },
46          None,
47        ).with_compiler_loc()),
48      }
49    }
50
51    (source, key) => Err(MechError2::new(
52      UnhandledFunctionArgumentKind2 {
53        arg: (source.kind(), key.kind()),
54        fxn_name: "MapAccess".to_string(),
55      },
56      None,
57    ).with_compiler_loc()),
58  }
59}
60
61pub struct MapAccess {}
62
63impl NativeFunctionCompiler for MapAccess {
64  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
65    if arguments.len() != 2 {
66      return Err(MechError2::new(
67        IncorrectNumberOfArguments {
68          expected: 2,
69          found: arguments.len(),
70        },
71        None,
72      ).with_compiler_loc());
73    }
74
75    let src = &arguments[0];
76    let key = &arguments[1];
77
78    // Verify that the key as the right kind for the map
79    match src.kind().deref_kind() {
80      #[cfg(feature = "map")]
81      ValueKind::Map(key_kind, _) => {
82        if key.kind() != *key_kind {
83          return Err(MechError2::new(
84            UnhandledFunctionArgumentKind2 { arg: (src.kind(), key.kind()), fxn_name: "MapAccess".to_string() },
85            None,
86          ).with_compiler_loc());
87        }
88      }
89      _ => unreachable!(),
90    };
91
92    match impl_access_map_fxn(src.clone(), key.clone()) {
93      Ok(fxn) => Ok(fxn),
94      Err(_) => {
95        match src {
96          Value::MutableReference(map) => {
97            impl_access_map_fxn(map.borrow().clone(), key.clone())
98          }
99          _ => Err(MechError2::new(
100            UnhandledFunctionArgumentKind2 {
101              arg: (src.kind(), key.kind()),
102              fxn_name: "MapAccess".to_string(),
103            },
104            None,
105          ).with_compiler_loc()),
106        }
107      }
108    }
109  }
110}
111
112#[derive(Debug, Clone)]
113pub struct UndefinedMapKeyError {
114  pub key: String,
115}
116
117impl MechErrorKind2 for UndefinedMapKeyError {
118  fn name(&self) -> &str {
119    "UndefinedMapKey"
120  }
121  fn message(&self) -> String {
122    format!("Key id `{}` not found in key_index.", self.key)
123  }
124}