diff --git a/crates/unitdc-web/ui/src/App.tsx b/crates/unitdc-web/ui/src/App.tsx index 70575b6..bfaa7f2 100644 --- a/crates/unitdc-web/ui/src/App.tsx +++ b/crates/unitdc-web/ui/src/App.tsx @@ -179,7 +179,7 @@ function App() { ) case 'message': return ( - <div key={index}>Message: {cell.text}</div> + <pre key={index}>{cell.text}</pre> ) } }) diff --git a/crates/unitdc-web/ui/src/components/Keyboard.tsx b/crates/unitdc-web/ui/src/components/Keyboard.tsx index 866ee47..2d6fcdd 100644 --- a/crates/unitdc-web/ui/src/components/Keyboard.tsx +++ b/crates/unitdc-web/ui/src/components/Keyboard.tsx @@ -127,6 +127,7 @@ export function Keyboard(props: KeyboardProps) { </div> <div className="keyboard-col"> <UiActionButton action="clear" text="CLR" /> + <TokenButton token="U" tokentype="operator" /> { ["m", "mol", "M", "Da"].map((token) => { return ( diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index ed0d449..5d7fc42 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -86,6 +86,7 @@ impl<'a> Interpreter<'a> { Token::Operator('d') => self.op_d()?, Token::Operator('r') => self.op_r()?, Token::Operator('s') => self.op_s()?, + Token::Operator('U') => self.op_upper_u()?, Token::VarRecall(name) => self.op_recall(&name)?, Token::VarStore(name) => self.op_store(&name)?, Token::MacroInvoke((name, args)) => match name.as_str() { diff --git a/src/interpreter/ops.rs b/src/interpreter/ops.rs index 2981fc6..5f90476 100644 --- a/src/interpreter/ops.rs +++ b/src/interpreter/ops.rs @@ -144,6 +144,27 @@ impl<'a> Interpreter<'a> { Ok(()) } + pub fn op_upper_u(&mut self) -> InterpreterResult<()> { + let mut output = String::from("Base units:\n"); + + for u in &self.unit_system.base_units() { + output.push_str(&format!("{}, ", u.symbol)); + } + output.pop(); + output.pop(); + output.push_str("\n\nDerived units:\n"); + + for u in &self.unit_system.derived_units() { + output.push_str(&format!( + "{} = {} ({}) + {}\n", + u.symbol, u.scale, u.exponents, u.offset + )); + } + + (self.output)(Output::Message(output)); + + Ok(()) + } pub fn op_s(&mut self) -> InterpreterResult<()> { let target = self.stack.pop().ok_or(InterpreterError::StackUnderflow)?; diff --git a/src/quantity/units.rs b/src/quantity/units.rs index 1950b29..695e86d 100644 --- a/src/quantity/units.rs +++ b/src/quantity/units.rs @@ -55,6 +55,22 @@ impl UnitSystem { pub fn push_derived_unit(&mut self, unit: DerivedUnit) { self.derived_units.insert(unit.symbol.clone(), unit); } + pub fn base_units(&self) -> Vec<BaseUnit> { + let mut base_units = Vec::new(); + for unit in self.base_units.values() { + base_units.push(unit.clone()); + } + base_units.sort_by(|a, b| a.symbol.cmp(&b.symbol)); + base_units + } + pub fn derived_units(&self) -> Vec<DerivedUnit> { + let mut derived_units = Vec::new(); + for unit in self.derived_units.values() { + derived_units.push(unit.clone()); + } + derived_units.sort_by(|a, b| format!("{}", a.exponents).cmp(&format!("{}", b.exponents))); + derived_units + } } #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] diff --git a/src/tokenizer/mod.rs b/src/tokenizer/mod.rs index 97a56da..da25a35 100644 --- a/src/tokenizer/mod.rs +++ b/src/tokenizer/mod.rs @@ -152,6 +152,7 @@ impl<R: std::io::Read> Tokenizer<R> { Some('d') => Ok(Some(Token::Operator('d'))), Some('r') => Ok(Some(Token::Operator('r'))), Some('s') => Ok(Some(Token::Operator('s'))), + Some('U') => Ok(Some(Token::Operator('U'))), Some('#') => { while let Some(c) = self.next_char().map_err(TokenizerError::IOError)? { match c {