mech_interpreter/stdlib/access/
tuple.rs

1#[macro_use]
2use crate::stdlib::*;
3
4// Tuple Access --------------------------------------------------------------
5
6#[derive(Debug)]
7struct TupleAccessElement {
8  out: Value,
9}
10
11impl MechFunctionImpl for TupleAccessElement {
12  fn solve(&self) {
13    ()
14  }
15  fn out(&self) -> Value { self.out.clone() }
16  fn to_string(&self) -> String { format!("{:#?}", self) }
17}
18#[cfg(feature = "compiler")]
19impl MechFunctionCompiler for TupleAccessElement {
20  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
21    let mut registers = [0];
22    registers[0] = compile_register!(self.out, ctx);
23    ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Tuple));
24    ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Access));
25    ctx.emit_nullop(
26      hash_str(stringify!("TupleAccessElement")),
27      registers[0],
28    );
29    return Ok(registers[0]);
30  }
31}
32  
33pub struct TupleAccess {}
34impl NativeFunctionCompiler for TupleAccess{
35  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
36    if arguments.len() < 2 {
37      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
38    }
39    let ix1 = &arguments[1];
40    let src = &arguments[0];
41    match (src.clone(),ix1.clone()) {
42      (Value::Tuple(tpl), Value::Index(ix)) => {
43        let tpl_brrw = tpl.borrow();
44        let ix_brrw = ix.borrow();
45        if *ix_brrw > tpl_brrw.elements.len() || *ix_brrw < 1 {
46            return Err(MechError2::new(
47                TupleIndexOutOfBoundsError { ix: *ix_brrw, len: tpl_brrw.elements.len() },
48                None
49              ).with_compiler_loc());
50        }
51        let element = tpl_brrw.elements[*ix_brrw - 1].clone();
52        let new_fxn = TupleAccessElement{ out: *element };
53        Ok(Box::new(new_fxn))
54      },
55      (Value::MutableReference(tpl), Value::Index(ix)) => {
56        match &*tpl.borrow() {
57          Value::Tuple(ref tpl) => {
58            let ix_brrw = ix.borrow();
59            let tpl_brrw = tpl.borrow();
60            if *ix_brrw > tpl_brrw.elements.len() || *ix_brrw < 1 {
61              return Err(MechError2::new(
62                  TupleIndexOutOfBoundsError { ix: *ix_brrw, len: tpl_brrw.elements.len() },
63                  None
64                ).with_compiler_loc());
65            }
66            let element = tpl_brrw.elements[*ix_brrw - 1].clone();
67            let new_fxn = TupleAccessElement{ out: *element };
68            Ok(Box::new(new_fxn))
69          },
70          _ => Err(MechError2::new(
71              UnhandledFunctionArgumentKind2 { arg: (src.kind(), ix1.kind()), fxn_name: "access/tuple-element".to_string() },
72              None
73            ).with_compiler_loc()
74          ),
75        }
76      },
77      _ => todo!(),
78    }
79  }
80}