unitdc/interpreter/
ops_macros.rs

1use crate::quantity::units::{BaseUnit, DerivedUnit};
2
3use super::{Interpreter, InterpreterError, InterpreterResult};
4
5impl<'a> Interpreter<'a> {
6    /// Defines a new base unit.
7    ///
8    /// For example to define a unit "usd" (US Dollar), you would do:
9    /// `@base(usd)`
10    pub fn op_macro_baseunit(&mut self, arg: &str) -> InterpreterResult<()> {
11        let symbol = arg.trim();
12
13        if self.unit_system.lookup_unit(symbol).is_some() {
14            return Err(InterpreterError::AlreadyDefined(symbol.to_string()));
15        }
16
17        self.unit_system.push_base_unit(BaseUnit {
18            symbol: symbol.to_string(),
19        });
20
21        Ok(())
22    }
23    /// Defines a new derived unit.
24    ///
25    /// This is done by popping a "scale" and then an "offset" from the stack.
26    /// For example, to define a new unit "mpg" (miles per gallon), you would do:
27    /// `0 (mi) 1 (gal) / 1 (mi) 1 (gal) / @derived(mpg)`
28    pub fn op_macro_derivedunit(&mut self, arg: &str) -> InterpreterResult<()> {
29        let symbol = arg.trim();
30
31        let scale = self.stack.pop().ok_or(InterpreterError::StackUnderflow)?;
32        let offset = self.stack.pop().ok_or(InterpreterError::StackUnderflow)?;
33
34        if self.unit_system.lookup_unit(symbol).is_some() {
35            return Err(InterpreterError::AlreadyDefined(symbol.to_string()));
36        }
37
38        self.unit_system.push_derived_unit(DerivedUnit {
39            symbol: symbol.to_string(),
40            scale: scale.number,
41            offset: offset.number,
42            exponents: offset.unit,
43        });
44
45        Ok(())
46    }
47}