summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-04-18 20:34:39 +1200
committerBen Bridle <ben@derelict.engineering>2025-04-18 20:34:39 +1200
commit373c512397dde9c767ac65453780931a84704ce4 (patch)
treec2f5844f73cf571be3dcc2832bf25ac71cbfdca9
parente6961f8f122908518bb55de6f3943ceb80305785 (diff)
downloadtorque-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.
-rw-r--r--src/stages/bytecode.rs6
-rw-r--r--src/types/expression_stack.rs9
-rw-r--r--src/types/operator.rs3
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}")
}