diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-10-15 14:12:37 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-10-15 14:12:37 +1300 |
commit | 80ad3f392706c4f6bddd37d317b2519bd0d6f579 (patch) | |
tree | 9b67f07dbbbd82506ab82d4e8f54ffc4965fd23f /src/types | |
parent | 29d0b855f5a089e9ac26f56410ae62b8775a2dfe (diff) | |
download | torque-asm-80ad3f392706c4f6bddd37d317b2519bd0d6f579.zip |
Add find operator for expressions
The <fnd> operator returns the index of the first element in a list
with the given value.
Diffstat (limited to 'src/types')
-rw-r--r-- | src/types/expression_stack.rs | 19 | ||||
-rw-r--r-- | src/types/operator.rs | 3 |
2 files changed, 22 insertions, 0 deletions
diff --git a/src/types/expression_stack.rs b/src/types/expression_stack.rs index f197ea7..e60dad7 100644 --- a/src/types/expression_stack.rs +++ b/src/types/expression_stack.rs @@ -69,6 +69,7 @@ impl ExpressionStack { Operator::BitNot => { pop!(a); push!(op_bit_not(a)) }, Operator::Length => { pop!(a); push!(op_length(a)) }, Operator::Index => { pop!(b); pop!(a); push!(op_index(a, b)) }, + Operator::Find => { pop!(b); pop!(a); push!(op_find(a, b)) }, Operator::Sum => { pop!(a); push!(op_sum(a)) }, Operator::Absolute => { pop!(a); push!(op_absolute(a)) }, Operator::Debug => { pop!(a); op_debug(&a, &source); push!(Ok(a)) }, @@ -192,6 +193,13 @@ fn op_index(l: IntermediateValue, r: IntermediateValue) -> Result<IntermediateVa false => Err(ExpressionError::IndexError(l.len(), r)), } } +fn op_find(l: IntermediateValue, r: IntermediateValue) -> Result<IntermediateValue, ExpressionError> { + let l = to_list(l)?; let r = to_isize(r)?; + match l.iter().position(|e| *e == r) { + Some(i) => Ok(from_isize(i as isize)), + None => Err(ExpressionError::FindError(l.len(), r)), + } +} fn op_sum(l: IntermediateValue) -> Result<IntermediateValue, ExpressionError> { let sum = match l { IntermediateValue::Integer(integer) => ones(*integer) as isize, @@ -243,6 +251,8 @@ pub enum ExpressionError { InvalidArgumentType(&'static str, &'static str), // (length, index) IndexError(usize, isize), + // (length, value) + FindError(usize, isize), } @@ -261,6 +271,15 @@ pub fn report_expression_error(error: &Tracked<ExpressionError>, source_code: &s &format!("Operator expected {expected} value, not {received} value"), ExpressionError::IndexError(length, index) => &format!("Could not access element {index} from a list of length {length}"), + ExpressionError::FindError(length, value) => { + let mut character = String::new(); + if let Ok(value) = u32::try_from(*value) { + if let Some(c) = char::from_u32(value) { + character = format!(" (character '{c}')"); + } + } + &format!("Could not find value {value}{character} in list of length {length}") + } }; report_source_issue(LogLevel::Error, &context, message); diff --git a/src/types/operator.rs b/src/types/operator.rs index 5bf82b2..e94c67d 100644 --- a/src/types/operator.rs +++ b/src/types/operator.rs @@ -20,6 +20,7 @@ pub enum Operator { BitNot, Length, Index, + Find, Sum, Absolute, Debug, @@ -62,6 +63,7 @@ impl Operator { "<not>" => Some(Operator::BitNot), "<len>" => Some(Operator::Length), "<nth>" => Some(Operator::Index), + "<fnd>" => Some(Operator::Find), "<sum>" => Some(Operator::Sum), "<abs>" => Some(Operator::Absolute), "<dbg>" => Some(Operator::Debug), @@ -93,6 +95,7 @@ impl std::fmt::Display for Operator { Operator::BitNot => "<not>", Operator::Length => "<len>", Operator::Index => "<nth>", + Operator::Find => "<fnd>", Operator::Sum => "<sum>", Operator::Absolute => "<abs>", Operator::Debug => "<dbg>", |