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> { pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
let mut intrinsics = Vec::new(); 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 intrinsics
} }

View File

@ -95,11 +95,11 @@ impl TypeKind {
/// Return the type that is the result of a binary operator between two /// Return the type that is the result of a binary operator between two
/// values of this type /// values of this type
pub fn simple_binop_type(&self, op: &BinaryOperator) -> TypeKind { pub fn simple_binop_type(&self, op: &BinaryOperator) -> Option<TypeKind> {
// TODO make some type of mechanism that allows to binop two values of if !self.category().is_simple_maths() {
// differing types.. return None;
// TODO Return None for arrays later }
match op { Some(match op {
BinaryOperator::Add => self.clone(), BinaryOperator::Add => self.clone(),
BinaryOperator::Minus => self.clone(), BinaryOperator::Minus => self.clone(),
BinaryOperator::Mult => self.clone(), BinaryOperator::Mult => self.clone(),
@ -107,7 +107,7 @@ impl TypeKind {
BinaryOperator::Cmp(_) => TypeKind::Bool, BinaryOperator::Cmp(_) => TypeKind::Bool,
BinaryOperator::Div => self.clone(), BinaryOperator::Div => self.clone(),
BinaryOperator::Mod => self.clone(), BinaryOperator::Mod => self.clone(),
} })
} }
pub fn binop_type( pub fn binop_type(
@ -127,6 +127,9 @@ impl TypeKind {
/// Reverse of binop_type, where the given hint is the known required output /// 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. /// 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> { pub fn simple_binop_hint(&self, op: &BinaryOperator) -> Option<TypeKind> {
if !self.category().is_simple_maths() {
return None;
}
match op { match op {
BinaryOperator::Add BinaryOperator::Add
| BinaryOperator::Minus | BinaryOperator::Minus
@ -275,7 +278,7 @@ impl TypeKind {
| TypeKind::F80 | TypeKind::F80
| TypeKind::F128PPC => TypeCategory::Real, | TypeKind::F128PPC => TypeCategory::Real,
TypeKind::Void => TypeCategory::Other, TypeKind::Void => TypeCategory::Other,
TypeKind::Bool => TypeCategory::Other, TypeKind::Bool => TypeCategory::Bool,
TypeKind::Array(_, _) => TypeCategory::Other, TypeKind::Array(_, _) => TypeCategory::Other,
TypeKind::CustomType(..) => TypeCategory::Other, TypeKind::CustomType(..) => TypeCategory::Other,
TypeKind::Borrow(_, _) => TypeCategory::Other, TypeKind::Borrow(_, _) => TypeCategory::Other,
@ -329,10 +332,23 @@ impl BinaryOperator {
pub enum TypeCategory { pub enum TypeCategory {
Integer, Integer,
Real, Real,
Bool,
Other, Other,
TypeRef, 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 { impl StructType {
pub fn get_field_ty(&self, name: &String) -> Option<&TypeKind> { pub fn get_field_ty(&self, name: &String) -> Option<&TypeKind> {
self.0 self.0

View File

@ -64,14 +64,16 @@ pub enum ErrorKind {
ImpossibleMutableBorrow(String), ImpossibleMutableBorrow(String),
#[error("Cannot declare variable {0} as mutable, when it's type is immutable")] #[error("Cannot declare variable {0} as mutable, when it's type is immutable")]
ImpossibleMutLet(String), ImpossibleMutLet(String),
#[error("Cannot produce a negative unsigned value of type {0}!")] #[error("Cannot produce a negative unsigned value of type {0}")]
NegativeUnsignedValue(TypeKind), NegativeUnsignedValue(TypeKind),
#[error("Cannot cast type {0} into type {1}!")] #[error("Cannot cast type {0} into type {1}")]
NotCastableTo(TypeKind, TypeKind), NotCastableTo(TypeKind, TypeKind),
#[error("Cannot divide by zero")] #[error("Cannot divide by zero")]
DivideZero, DivideZero,
#[error("Binary operation between {0} and {1} is already defined!")] #[error("Binary operation {0} between {1} and {2} is already defined")]
BinaryOpAlreadyDefined(TypeKind, TypeKind), 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 /// 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(); 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) => { 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()), params: (binop.lhs.1.clone(), binop.rhs.1.clone()),
operator: binop.op, 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( state.note_errors(
&vec![ErrorKind::BinaryOpAlreadyDefined( &vec![ErrorKind::BinaryOpAlreadyDefined(
binop.op,
binop.lhs.1.clone(), binop.lhs.1.clone(),
binop.rhs.1.clone(), binop.rhs.1.clone(),
)], )],
@ -323,7 +326,17 @@ impl Expression {
} else { } else {
let typeref = lhs_ref.narrow(&rhs_ref).unwrap(); let typeref = lhs_ref.narrow(&rhs_ref).unwrap();
Ok(type_refs 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()) .unwrap())
} }
} }