Embrace having megaintrinsic binops

This commit is contained in:
Sofia 2025-07-24 20:15:13 +03:00
parent ccdefe7033
commit f6425fc37e
5 changed files with 47 additions and 50 deletions

0
.rustfmt.toml Normal file
View File

View File

@ -47,42 +47,6 @@ pub fn form_intrinsics() -> Vec<FunctionDefinition> {
pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
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
}

View File

@ -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<TypeKind> {
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<TypeKind> {
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

View File

@ -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) => {

View File

@ -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())
}
}