diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-04-18 20:34:39 +1200 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-04-18 20:34:39 +1200 |
commit | 373c512397dde9c767ac65453780931a84704ce4 (patch) | |
tree | c2f5844f73cf571be3dcc2832bf25ac71cbfdca9 /src | |
parent | e6961f8f122908518bb55de6f3943ceb80305785 (diff) | |
download | torque-asm-373c512397dde9c767ac65453780931a84704ce4.zip |
Implement <len> operator for expressions
The <len> operator returns the width of an integer in bits, using the
same calculation as for packing an integer into a bit field.
Diffstat (limited to 'src')
-rw-r--r-- | src/stages/bytecode.rs | 6 | ||||
-rw-r--r-- | src/types/expression_stack.rs | 9 | ||||
-rw-r--r-- | src/types/operator.rs | 3 |
3 files changed, 13 insertions, 5 deletions
diff --git a/src/stages/bytecode.rs b/src/stages/bytecode.rs index e4464a1..1d27b28 100644 --- a/src/stages/bytecode.rs +++ b/src/stages/bytecode.rs @@ -162,11 +162,7 @@ impl BytecodeParser { *value } }; - let value_width = match field_value.cmp(&0) { - std::cmp::Ordering::Less => (-field_value).ilog2() + 2, - std::cmp::Ordering::Equal => 0, - std::cmp::Ordering::Greater => field_value.ilog2() + 1, - }; + let value_width = width(field_value); if field.width < value_width { let error = BytecodeError::ValueTooWide(field.width, value_width); self.errors.push(Tracked::from(error, field_source.clone())); diff --git a/src/types/expression_stack.rs b/src/types/expression_stack.rs index 4d26eb2..d14d808 100644 --- a/src/types/expression_stack.rs +++ b/src/types/expression_stack.rs @@ -61,11 +61,20 @@ impl ExpressionStack { Operator::BitOr => { pop!(b); pop!(a); push!(a | b) }, Operator::BitXor => { pop!(b); pop!(a); push!(a ^ b) }, Operator::BitNot => { pop!(a); push!(!a) }, + Operator::Length => { pop!(a); push!(width(a) as isize) }, } return Ok(()); } } +/// Find the number of bits required to hold an integer. +pub fn width(value: isize) -> u32 { + match value.cmp(&0) { + std::cmp::Ordering::Less => (-value).ilog2() + 2, + std::cmp::Ordering::Equal => 0, + std::cmp::Ordering::Greater => value.ilog2() + 1, + } +} pub enum StackError { Underflow, diff --git a/src/types/operator.rs b/src/types/operator.rs index a7e7b9b..af607e3 100644 --- a/src/types/operator.rs +++ b/src/types/operator.rs @@ -18,6 +18,7 @@ pub enum Operator { BitOr, BitXor, BitNot, + Length, } impl Operator { @@ -55,6 +56,7 @@ impl Operator { "<or>" => Some(Operator::BitOr), "<xor>" => Some(Operator::BitXor), "<not>" => Some(Operator::BitNot), + "<len>" => Some(Operator::Length), _ => None, } } @@ -81,6 +83,7 @@ impl std::fmt::Display for Operator { Operator::BitOr => "<or>", Operator::BitXor => "<xor>", Operator::BitNot => "<not>", + Operator::Length => "<len>", }; write!(f, "{string}") } |