grammar: introduce bitwise ops & shifts; retire legacy >> ARROW
- Tokenizer: add tokens for << >> & | ^ (SHIFT_LEFT/RIGHT, BIT_AND/OR/XOR); keep ||, &&, |> - Parser: precedence layers for bit ops (| ^ &) and shift (<< >>); remove >> Arrow production - AST: add BitAnd/BitOr/BitXor/Shr with Display - MIR builder: map bit ops and Shr to MIR BinaryOp - Interpreter: implement integer-only bit ops and shifts, mask shift count to 0..63 Compatibility: legacy >> Arrow removed from parser; use |> for pipeline.
This commit is contained in:
@ -329,12 +329,46 @@ impl NyashInterpreter {
|
||||
crate::runtime::semantics::coerce_to_i64(left_val.as_ref()),
|
||||
crate::runtime::semantics::coerce_to_i64(right_val.as_ref()),
|
||||
) {
|
||||
return Ok(Box::new(IntegerBox::new(li.wrapping_shl(ri as u32))));
|
||||
let sh = (ri as u32) & 63;
|
||||
return Ok(Box::new(IntegerBox::new(li.wrapping_shl(sh))));
|
||||
}
|
||||
Err(RuntimeError::TypeError {
|
||||
message: format!("Shift-left '<<' requires integers (got {} and {})", left_val.type_name(), right_val.type_name())
|
||||
})
|
||||
}
|
||||
BinaryOperator::Shr => {
|
||||
if let (Some(li), Some(ri)) = (
|
||||
crate::runtime::semantics::coerce_to_i64(left_val.as_ref()),
|
||||
crate::runtime::semantics::coerce_to_i64(right_val.as_ref()),
|
||||
) {
|
||||
let sh = (ri as u32) & 63;
|
||||
return Ok(Box::new(IntegerBox::new(((li as u64) >> sh) as i64)));
|
||||
}
|
||||
Err(RuntimeError::TypeError {
|
||||
message: format!("Shift-right '>>' requires integers (got {} and {})", left_val.type_name(), right_val.type_name())
|
||||
})
|
||||
}
|
||||
BinaryOperator::BitAnd => {
|
||||
if let (Some(li), Some(ri)) = (
|
||||
crate::runtime::semantics::coerce_to_i64(left_val.as_ref()),
|
||||
crate::runtime::semantics::coerce_to_i64(right_val.as_ref()),
|
||||
) { return Ok(Box::new(IntegerBox::new(li & ri))); }
|
||||
Err(RuntimeError::TypeError { message: format!("Bitwise '&' requires integers (got {} and {})", left_val.type_name(), right_val.type_name()) })
|
||||
}
|
||||
BinaryOperator::BitOr => {
|
||||
if let (Some(li), Some(ri)) = (
|
||||
crate::runtime::semantics::coerce_to_i64(left_val.as_ref()),
|
||||
crate::runtime::semantics::coerce_to_i64(right_val.as_ref()),
|
||||
) { return Ok(Box::new(IntegerBox::new(li | ri))); }
|
||||
Err(RuntimeError::TypeError { message: format!("Bitwise '|' requires integers (got {} and {})", left_val.type_name(), right_val.type_name()) })
|
||||
}
|
||||
BinaryOperator::BitXor => {
|
||||
if let (Some(li), Some(ri)) = (
|
||||
crate::runtime::semantics::coerce_to_i64(left_val.as_ref()),
|
||||
crate::runtime::semantics::coerce_to_i64(right_val.as_ref()),
|
||||
) { return Ok(Box::new(IntegerBox::new(li ^ ri))); }
|
||||
Err(RuntimeError::TypeError { message: format!("Bitwise '^' requires integers (got {} and {})", left_val.type_name(), right_val.type_name()) })
|
||||
}
|
||||
|
||||
BinaryOperator::Less => {
|
||||
let result = CompareBox::less(left_val.as_ref(), right_val.as_ref());
|
||||
|
||||
@ -256,17 +256,44 @@ impl NyashInterpreter {
|
||||
Ok(Box::new(BoolBox::new(self.is_truthy(right_val))))
|
||||
}
|
||||
},
|
||||
|
||||
BinaryOperator::Shl => {
|
||||
if let (Some(li), Some(ri)) = (
|
||||
left_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
right_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
) {
|
||||
Ok(Box::new(IntegerBox::new(li.value.wrapping_shl(ri.value as u32))))
|
||||
Ok(Box::new(IntegerBox::new(li.value.wrapping_shl((ri.value as u32) & 63))))
|
||||
} else {
|
||||
Err(RuntimeError::InvalidOperation { message: format!("Shift-left '<<' requires integers (got {} and {})", left_val.type_name(), right_val.type_name()) })
|
||||
}
|
||||
},
|
||||
BinaryOperator::Shr => {
|
||||
if let (Some(li), Some(ri)) = (
|
||||
left_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
right_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
) {
|
||||
Ok(Box::new(IntegerBox::new(((li.value as u64) >> ((ri.value as u32) & 63)) as i64)))
|
||||
} else {
|
||||
Err(RuntimeError::InvalidOperation { message: format!("Shift-right '>>' requires integers (got {} and {})", left_val.type_name(), right_val.type_name()) })
|
||||
}
|
||||
},
|
||||
BinaryOperator::BitAnd => {
|
||||
if let (Some(li), Some(ri)) = (
|
||||
left_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
right_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
) { Ok(Box::new(IntegerBox::new(li.value & ri.value))) } else { Err(RuntimeError::InvalidOperation { message: format!("Bitwise '&' requires integers (got {} and {})", left_val.type_name(), right_val.type_name()) }) }
|
||||
},
|
||||
BinaryOperator::BitOr => {
|
||||
if let (Some(li), Some(ri)) = (
|
||||
left_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
right_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
) { Ok(Box::new(IntegerBox::new(li.value | ri.value))) } else { Err(RuntimeError::InvalidOperation { message: format!("Bitwise '|' requires integers (got {} and {})", left_val.type_name(), right_val.type_name()) }) }
|
||||
},
|
||||
BinaryOperator::BitXor => {
|
||||
if let (Some(li), Some(ri)) = (
|
||||
left_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
right_val.as_any().downcast_ref::<IntegerBox>(),
|
||||
) { Ok(Box::new(IntegerBox::new(li.value ^ ri.value))) } else { Err(RuntimeError::InvalidOperation { message: format!("Bitwise '^' requires integers (got {} and {})", left_val.type_name(), right_val.type_name()) }) }
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user