Skip to content

Commit 8096546

Browse files
committed
feat: enable +/-
1 parent abb2e49 commit 8096546

File tree

18 files changed

+462
-40
lines changed

18 files changed

+462
-40
lines changed

libs/@local/hashql/mir/src/body/constant/mod.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,11 @@
2727
//! while preserving the semantics of complex primitive types that should not be
2828
//! evaluated at compile time.
2929
30-
mod int;
31-
3230
use core::fmt;
3331

3432
use hashql_core::value::Primitive;
3533

36-
pub use self::int::{Int, TryFromIntegerError, TryFromPrimitiveError};
37-
use crate::def::DefId;
34+
use crate::{def::DefId, interpret::value::Int};
3835

3936
/// A constant value in the HashQL MIR.
4037
///

libs/@local/hashql/mir/src/body/rvalue/binary.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ use crate::body::operand::Operand;
1515
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1616
pub enum BinOp {
1717
/// The `+` operator (addition).
18-
Add(!),
18+
Add,
1919
/// The `-` operator (subtraction).
20-
Sub(!),
20+
Sub,
2121
/// The `*` operator (multiplication).
2222
Mul(!),
2323
/// The `/` operator (division).
@@ -56,6 +56,8 @@ impl BinOp {
5656
#[must_use]
5757
pub const fn as_str(self) -> &'static str {
5858
match self {
59+
Self::Add => "+",
60+
Self::Sub => "-",
5961
Self::BitAnd => "&",
6062
Self::BitOr => "|",
6163
Self::Eq => "==",
@@ -70,6 +72,8 @@ impl BinOp {
7072
#[must_use]
7173
pub const fn as_symbol(self) -> Symbol<'static> {
7274
match self {
75+
Self::Add => sym::symbol::add,
76+
Self::Sub => sym::symbol::sub,
7377
Self::BitAnd => sym::symbol::ampersand,
7478
Self::BitOr => sym::symbol::pipe,
7579
Self::Eq => sym::symbol::eq,

libs/@local/hashql/mir/src/builder/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl<'env, 'heap> BaseBuilder<'env, 'heap> {
3838

3939
/// Creates an integer constant operand.
4040
#[must_use]
41-
pub fn const_int(self, value: i64) -> Operand<'heap> {
41+
pub fn const_int(self, value: i128) -> Operand<'heap> {
4242
Operand::Constant(Constant::Int(value.into()))
4343
}
4444

libs/@local/hashql/mir/src/builder/operand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ impl<'heap> BuildOperand<'heap, f64> for OperandBuilder<'_, 'heap> {
2121
}
2222
}
2323

24-
impl<'heap> BuildOperand<'heap, i64> for OperandBuilder<'_, 'heap> {
25-
fn build_operand(&self, value: i64) -> Operand<'heap> {
24+
impl<'heap> BuildOperand<'heap, i128> for OperandBuilder<'_, 'heap> {
25+
fn build_operand(&self, value: i128) -> Operand<'heap> {
2626
self.base.const_int(value)
2727
}
2828
}

libs/@local/hashql/mir/src/interpret/error.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ use hashql_diagnostics::{
1818
};
1919
use hashql_hir::node::operation::UnOp;
2020

21-
use super::value::{Ptr, Value, ValueTypeName};
21+
use super::value::{Int, Ptr, Value, ValueTypeName};
2222
use crate::body::{
23-
constant::Int,
2423
local::{Local, LocalDecl},
2524
place::FieldIndex,
2625
rvalue::BinOp,

libs/@local/hashql/mir/src/interpret/locals.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,13 +396,16 @@ mod tests {
396396
use super::Locals;
397397
use crate::{
398398
body::{
399-
constant::{Constant, Int},
399+
constant::Constant,
400400
local::{Local, LocalDecl, LocalSlice, LocalVec},
401401
operand::Operand,
402402
place::{FieldIndex, Place},
403403
},
404404
intern::Interner,
405-
interpret::{error::RuntimeError, value::Value},
405+
interpret::{
406+
error::RuntimeError,
407+
value::{Int, Value},
408+
},
406409
};
407410

408411
fn fill_decl(decl: &mut LocalVec<LocalDecl<'_>>, max_index: Local) {

libs/@local/hashql/mir/src/interpret/runtime.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,40 @@ impl<'ctx, 'heap, A: Allocator + Clone> Runtime<'ctx, 'heap, A> {
324324
let rhs = frame.locals.operand(right)?;
325325

326326
let value = match op {
327+
BinOp::Add => {
328+
return match (lhs.as_ref(), rhs.as_ref()) {
329+
(Value::Integer(lhs), Value::Integer(rhs)) => Ok(Value::from(lhs + rhs)),
330+
(Value::Integer(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs + rhs)),
331+
(Value::Number(lhs), Value::Integer(rhs)) => Ok(Value::Number(lhs + rhs)),
332+
(Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs + rhs)),
333+
_ => Err(RuntimeError::BinaryTypeMismatch(Box::new(
334+
BinaryTypeMismatch {
335+
op,
336+
lhs_expected: TypeName::terse("Number"),
337+
rhs_expected: TypeName::terse("Number"),
338+
lhs: lhs.into_owned(),
339+
rhs: rhs.into_owned(),
340+
},
341+
))),
342+
};
343+
}
344+
BinOp::Sub => {
345+
return match (lhs.as_ref(), rhs.as_ref()) {
346+
(Value::Integer(lhs), Value::Integer(rhs)) => Ok(Value::from(lhs - rhs)),
347+
(Value::Integer(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs - rhs)),
348+
(Value::Number(lhs), Value::Integer(rhs)) => Ok(Value::Number(lhs - rhs)),
349+
(Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs - rhs)),
350+
_ => Err(RuntimeError::BinaryTypeMismatch(Box::new(
351+
BinaryTypeMismatch {
352+
op,
353+
lhs_expected: TypeName::terse("Number"),
354+
rhs_expected: TypeName::terse("Number"),
355+
lhs: lhs.into_owned(),
356+
rhs: rhs.into_owned(),
357+
},
358+
))),
359+
};
360+
}
327361
BinOp::BitAnd => {
328362
return match (lhs.as_ref(), rhs.as_ref()) {
329363
(Value::Integer(lhs), Value::Integer(rhs)) => Ok(Value::Integer(lhs & rhs)),

libs/@local/hashql/mir/src/interpret/tests.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@ use hashql_core::{
2222
r#type::{TypeId, environment::Environment},
2323
};
2424

25-
use super::{CallStack, Runtime, RuntimeConfig, error::InterpretDiagnostic, value::Value};
25+
use super::{
26+
CallStack, Runtime, RuntimeConfig,
27+
error::InterpretDiagnostic,
28+
value::{Int, Value},
29+
};
2630
use crate::{
2731
body::{
2832
Body,
29-
constant::{Constant, Int},
33+
constant::Constant,
3034
operand::Operand,
3135
rvalue::{Aggregate, AggregateKind, RValue},
3236
},

libs/@local/hashql/mir/src/body/constant/int.rs renamed to libs/@local/hashql/mir/src/interpret/value/int.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use core::{
22
error::Error,
33
fmt::{self, Display},
44
num::TryFromIntError,
5-
ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Neg, Not},
5+
ops::{Add, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Neg, Not, Sub},
66
};
77

88
use hashql_core::value::{Integer, Primitive};
@@ -642,6 +642,58 @@ impl Neg for Int {
642642
}
643643
}
644644

645+
impl Add for Int {
646+
type Output = Numeric;
647+
648+
#[inline]
649+
#[expect(clippy::float_arithmetic)]
650+
fn add(self, rhs: Self) -> Self::Output {
651+
let (value, overflow) = self.as_int().overflowing_add(rhs.as_int());
652+
653+
if overflow {
654+
Numeric::Num(Num::from(self.as_f64() + rhs.as_f64()))
655+
} else {
656+
Numeric::Int(Self::from_value_unchecked(value))
657+
}
658+
}
659+
}
660+
661+
impl Add<Num> for Int {
662+
type Output = Num;
663+
664+
#[inline]
665+
#[expect(clippy::float_arithmetic)]
666+
fn add(self, rhs: Num) -> Self::Output {
667+
Num::from(self.as_f64() + rhs.as_f64())
668+
}
669+
}
670+
671+
impl Sub for Int {
672+
type Output = Numeric;
673+
674+
#[inline]
675+
#[expect(clippy::float_arithmetic)]
676+
fn sub(self, rhs: Self) -> Self::Output {
677+
let (value, overflow) = self.as_int().overflowing_sub(rhs.as_int());
678+
679+
if overflow {
680+
Numeric::Num(Num::from(self.as_f64() - rhs.as_f64()))
681+
} else {
682+
Numeric::Int(Self::from_value_unchecked(value))
683+
}
684+
}
685+
}
686+
687+
impl Sub<Num> for Int {
688+
type Output = Num;
689+
690+
#[inline]
691+
#[expect(clippy::float_arithmetic)]
692+
fn sub(self, rhs: Num) -> Self::Output {
693+
Num::from(self.as_f64() - rhs.as_f64())
694+
}
695+
}
696+
645697
impl BitOr for Int {
646698
type Output = Self;
647699

@@ -692,6 +744,10 @@ impl BitXorAssign for Int {
692744

693745
forward_ref_unop!(impl Not::not for Int);
694746
forward_ref_unop!(impl Neg::neg for Int);
747+
forward_ref_binop!(impl Add<Int>::add for Int);
748+
forward_ref_binop!(impl Add<Num>::add for Int);
749+
forward_ref_binop!(impl Sub<Int>::sub for Int);
750+
forward_ref_binop!(impl Sub<Num>::sub for Int);
695751
forward_ref_binop!(impl BitOr<Int>::bitor for Int);
696752
forward_ref_binop!(impl BitAnd<Int>::bitand for Int);
697753
forward_ref_binop!(impl BitXor<Int>::bitxor for Int);
@@ -707,7 +763,7 @@ mod tests {
707763
clippy::float_cmp
708764
)]
709765

710-
use crate::{body::constant::Int, interpret::value::Numeric};
766+
use crate::interpret::value::{Int, Numeric};
711767

712768
#[test]
713769
fn neg_positive() {

libs/@local/hashql/mir/src/interpret/value/list.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use core::{alloc::Allocator, cmp, iter::FusedIterator};
44

55
use imbl::shared_ptr::RcK;
66

7-
use super::Value;
8-
use crate::body::constant::Int;
7+
use super::{Int, Value};
98

109
/// An ordered list of values.
1110
#[derive(Debug, Clone)]

0 commit comments

Comments
 (0)