From f6425fc37e6b661788f871796f32e4149a412e82 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 20:15:13 +0300 Subject: [PATCH] Embrace having megaintrinsic binops --- .rustfmt.toml | 0 reid/src/intrinsics.rs | 36 ----------------------------------- reid/src/mir/implement.rs | 30 ++++++++++++++++++++++------- reid/src/mir/typecheck.rs | 14 +++++++++----- reid/src/mir/typeinference.rs | 17 +++++++++++++++-- 5 files changed, 47 insertions(+), 50 deletions(-) create mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..e69de29 diff --git a/reid/src/intrinsics.rs b/reid/src/intrinsics.rs index 70c8752..c137c86 100644 --- a/reid/src/intrinsics.rs +++ b/reid/src/intrinsics.rs @@ -47,42 +47,6 @@ pub fn form_intrinsics() -> Vec { pub fn form_intrinsic_binops() -> Vec { let mut intrinsics = Vec::new(); - intrinsics.push(intrinsic_binop( - BinaryOperator::Add, - TypeKind::U8, - TypeKind::U8, - TypeKind::U8, - IntrinsicIAdd(TypeKind::U8), - )); - intrinsics.push(intrinsic_binop( - BinaryOperator::Add, - TypeKind::U32, - TypeKind::U32, - TypeKind::U32, - IntrinsicIAdd(TypeKind::U32), - )); - intrinsics.push(intrinsic_binop( - BinaryOperator::Add, - TypeKind::U16, - TypeKind::U16, - TypeKind::U16, - IntrinsicIAdd(TypeKind::U16), - )); - intrinsics.push(intrinsic_binop( - BinaryOperator::Div, - TypeKind::U16, - TypeKind::U16, - TypeKind::U16, - IntrinsicUDiv(TypeKind::U16), - )); - intrinsics.push(intrinsic_binop( - BinaryOperator::Mod, - TypeKind::U16, - TypeKind::U16, - TypeKind::U16, - IntrinsicUMod(TypeKind::U16), - )); - intrinsics } diff --git a/reid/src/mir/implement.rs b/reid/src/mir/implement.rs index f9204f6..a7fbe06 100644 --- a/reid/src/mir/implement.rs +++ b/reid/src/mir/implement.rs @@ -95,11 +95,11 @@ impl TypeKind { /// Return the type that is the result of a binary operator between two /// values of this type - pub fn simple_binop_type(&self, op: &BinaryOperator) -> TypeKind { - // TODO make some type of mechanism that allows to binop two values of - // differing types.. - // TODO Return None for arrays later - match op { + pub fn simple_binop_type(&self, op: &BinaryOperator) -> Option { + if !self.category().is_simple_maths() { + return None; + } + Some(match op { BinaryOperator::Add => self.clone(), BinaryOperator::Minus => self.clone(), BinaryOperator::Mult => self.clone(), @@ -107,7 +107,7 @@ impl TypeKind { BinaryOperator::Cmp(_) => TypeKind::Bool, BinaryOperator::Div => self.clone(), BinaryOperator::Mod => self.clone(), - } + }) } pub fn binop_type( @@ -127,6 +127,9 @@ impl TypeKind { /// Reverse of binop_type, where the given hint is the known required output /// type of the binop, and the output is the hint for the lhs/rhs type. pub fn simple_binop_hint(&self, op: &BinaryOperator) -> Option { + if !self.category().is_simple_maths() { + return None; + } match op { BinaryOperator::Add | BinaryOperator::Minus @@ -275,7 +278,7 @@ impl TypeKind { | TypeKind::F80 | TypeKind::F128PPC => TypeCategory::Real, TypeKind::Void => TypeCategory::Other, - TypeKind::Bool => TypeCategory::Other, + TypeKind::Bool => TypeCategory::Bool, TypeKind::Array(_, _) => TypeCategory::Other, TypeKind::CustomType(..) => TypeCategory::Other, TypeKind::Borrow(_, _) => TypeCategory::Other, @@ -329,10 +332,23 @@ impl BinaryOperator { pub enum TypeCategory { Integer, Real, + Bool, Other, TypeRef, } +impl TypeCategory { + pub fn is_simple_maths(&self) -> bool { + match self { + TypeCategory::Integer => true, + TypeCategory::Real => true, + TypeCategory::Other => false, + TypeCategory::TypeRef => false, + TypeCategory::Bool => true, + } + } +} + impl StructType { pub fn get_field_ty(&self, name: &String) -> Option<&TypeKind> { self.0 diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index fb82f27..0dedaf1 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -64,14 +64,16 @@ pub enum ErrorKind { ImpossibleMutableBorrow(String), #[error("Cannot declare variable {0} as mutable, when it's type is immutable")] ImpossibleMutLet(String), - #[error("Cannot produce a negative unsigned value of type {0}!")] + #[error("Cannot produce a negative unsigned value of type {0}")] NegativeUnsignedValue(TypeKind), - #[error("Cannot cast type {0} into type {1}!")] + #[error("Cannot cast type {0} into type {1}")] NotCastableTo(TypeKind, TypeKind), #[error("Cannot divide by zero")] DivideZero, - #[error("Binary operation between {0} and {1} is already defined!")] - BinaryOpAlreadyDefined(TypeKind, TypeKind), + #[error("Binary operation {0} between {1} and {2} is already defined")] + BinaryOpAlreadyDefined(BinaryOperator, TypeKind, TypeKind), + #[error("Binary operation {0} between {1} and {2} is not defined")] + InvalidBinop(BinaryOperator, TypeKind, TypeKind), } /// Struct used to implement a type-checking pass that can be performed on the @@ -580,7 +582,9 @@ impl Expression { rhs.typecheck(state, &typerefs, Some(&collapsed)).ok(); } - Ok(both_t.simple_binop_type(op)) + both_t + .simple_binop_type(op) + .ok_or(ErrorKind::InvalidBinop(*op, lhs_type, rhs_type)) } } ExprKind::FunctionCall(function_call) => { diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index c9b937f..f94f368 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -65,9 +65,12 @@ impl<'t> Pass for TypeInference<'t> { params: (binop.lhs.1.clone(), binop.rhs.1.clone()), operator: binop.op, }; - if seen_binops.contains(&binop_key) { + if seen_binops.contains(&binop_key) + || (binop.lhs == binop.rhs && binop.lhs.1.category().is_simple_maths()) + { state.note_errors( &vec![ErrorKind::BinaryOpAlreadyDefined( + binop.op, binop.lhs.1.clone(), binop.rhs.1.clone(), )], @@ -323,7 +326,17 @@ impl Expression { } else { let typeref = lhs_ref.narrow(&rhs_ref).unwrap(); Ok(type_refs - .from_type(&typeref.resolve_deep().unwrap().simple_binop_type(op)) + .from_type( + &typeref + .resolve_deep() + .unwrap() + .simple_binop_type(op) + .ok_or(ErrorKind::InvalidBinop( + *op, + lhs_ref.resolve_deep().unwrap(), + rhs_ref.resolve_deep().unwrap(), + ))?, + ) .unwrap()) } }