Fix intrinsic binops

This commit is contained in:
Sofia 2025-07-25 21:11:30 +03:00
parent 307137d0d9
commit 5149ef8727
4 changed files with 79 additions and 68 deletions

View File

@ -5,6 +5,7 @@ use std::collections::HashMap;
use std::convert::Infallible; use std::convert::Infallible;
use std::error::Error as STDError; use std::error::Error as STDError;
use crate::codegen::intrinsics::form_intrinsic_binops;
use crate::error_raporting::ReidError; use crate::error_raporting::ReidError;
use super::*; use super::*;
@ -53,12 +54,7 @@ impl<TErr: STDError> State<TErr> {
} }
} }
fn or_else<U, T: Into<Metadata> + Clone + Copy>( fn or_else<U, T: Into<Metadata> + Clone + Copy>(&mut self, result: Result<U, TErr>, default: U, meta: T) -> U {
&mut self,
result: Result<U, TErr>,
default: U,
meta: T,
) -> U {
match result { match result {
Ok(t) => t, Ok(t) => t,
Err(e) => { Err(e) => {
@ -71,11 +67,7 @@ impl<TErr: STDError> State<TErr> {
} }
} }
fn ok<T: Into<Metadata> + Clone + Copy, U>( fn ok<T: Into<Metadata> + Clone + Copy, U>(&mut self, result: Result<U, TErr>, meta: T) -> Option<U> {
&mut self,
result: Result<U, TErr>,
meta: T,
) -> Option<U> {
match result { match result {
Ok(v) => Some(v), Ok(v) => Some(v),
Err(e) => { Err(e) => {
@ -200,10 +192,10 @@ impl PartialEq for ScopeBinopKey {
return false; return false;
} }
let operators_eq = self.params.0.narrow_into(&other.params.0).is_ok() let operators_eq =
&& self.params.1.narrow_into(&other.params.1).is_ok(); self.params.0.narrow_into(&other.params.0).is_ok() && self.params.1.narrow_into(&other.params.1).is_ok();
let swapped_ops_eq = self.params.0.narrow_into(&other.params.1).is_ok() let swapped_ops_eq =
&& self.params.1.narrow_into(&other.params.0).is_ok(); self.params.0.narrow_into(&other.params.1).is_ok() && self.params.1.narrow_into(&other.params.0).is_ok();
if self.operator.is_commutative() { if self.operator.is_commutative() {
operators_eq || swapped_ops_eq operators_eq || swapped_ops_eq
@ -253,11 +245,7 @@ pub struct PassState<'st, 'sc, Data: Clone + Default, TError: STDError + Clone>
} }
impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, 'sc, Data, TError> { impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, 'sc, Data, TError> {
fn from( fn from(state: &'st mut State<TError>, scope: &'sc mut Scope<Data>, module_id: Option<SourceModuleId>) -> Self {
state: &'st mut State<TError>,
scope: &'sc mut Scope<Data>,
module_id: Option<SourceModuleId>,
) -> Self {
PassState { PassState {
state, state,
scope, scope,
@ -275,19 +263,11 @@ impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, '
self.state.or_else(result, default, meta) self.state.or_else(result, default, meta)
} }
pub fn ok<TMeta: Into<Metadata> + Clone + Copy, U>( pub fn ok<TMeta: Into<Metadata> + Clone + Copy, U>(&mut self, result: Result<U, TError>, meta: TMeta) -> Option<U> {
&mut self,
result: Result<U, TError>,
meta: TMeta,
) -> Option<U> {
self.state.ok(result, meta) self.state.ok(result, meta)
} }
pub fn note_errors<TMeta: Into<Metadata> + Clone>( pub fn note_errors<TMeta: Into<Metadata> + Clone>(&mut self, errors: &Vec<TError>, meta: TMeta) {
&mut self,
errors: &Vec<TError>,
meta: TMeta,
) {
for error in errors { for error in errors {
self.ok::<_, Infallible>(Err(error.clone()), meta.clone().into()); self.ok::<_, Infallible>(Err(error.clone()), meta.clone().into());
} }
@ -311,18 +291,10 @@ pub trait Pass {
type Data: Clone + Default; type Data: Clone + Default;
type TError: STDError + Clone; type TError: STDError + Clone;
fn context( fn context(&mut self, _context: &mut Context, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
&mut self,
_context: &mut Context,
mut _state: PassState<Self::Data, Self::TError>,
) -> PassResult {
Ok(()) Ok(())
} }
fn module( fn module(&mut self, _module: &mut Module, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
&mut self,
_module: &mut Module,
mut _state: PassState<Self::Data, Self::TError>,
) -> PassResult {
Ok(()) Ok(())
} }
fn function( fn function(
@ -332,25 +304,13 @@ pub trait Pass {
) -> PassResult { ) -> PassResult {
Ok(()) Ok(())
} }
fn block( fn block(&mut self, _block: &mut Block, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
&mut self,
_block: &mut Block,
mut _state: PassState<Self::Data, Self::TError>,
) -> PassResult {
Ok(()) Ok(())
} }
fn stmt( fn stmt(&mut self, _stmt: &mut Statement, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
&mut self,
_stmt: &mut Statement,
mut _state: PassState<Self::Data, Self::TError>,
) -> PassResult {
Ok(()) Ok(())
} }
fn expr( fn expr(&mut self, _expr: &mut Expression, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
&mut self,
_expr: &mut Expression,
mut _state: PassState<Self::Data, Self::TError>,
) -> PassResult {
Ok(()) Ok(())
} }
} }
@ -360,6 +320,24 @@ impl Context {
let mut state = State::new(); let mut state = State::new();
let mut scope = Scope::default(); let mut scope = Scope::default();
pass.context(self, PassState::from(&mut state, &mut scope, None))?; pass.context(self, PassState::from(&mut state, &mut scope, None))?;
for intrinsic in form_intrinsic_binops() {
scope
.binops
.set(
ScopeBinopKey {
params: (intrinsic.lhs.1.clone(), intrinsic.rhs.1.clone()),
operator: intrinsic.op,
},
ScopeBinopDef {
hands: (intrinsic.lhs.1.clone(), intrinsic.rhs.1.clone()),
operator: intrinsic.op,
return_ty: intrinsic.return_type.clone(),
},
)
.ok();
}
for (_, module) in &mut self.modules { for (_, module) in &mut self.modules {
module.pass(pass, &mut state, &mut scope.inner())?; module.pass(pass, &mut state, &mut scope.inner())?;
} }
@ -368,12 +346,7 @@ impl Context {
} }
impl Module { impl Module {
fn pass<T: Pass>( fn pass<T: Pass>(&mut self, pass: &mut T, state: &mut State<T::TError>, scope: &mut Scope<T::Data>) -> PassResult {
&mut self,
pass: &mut T,
state: &mut State<T::TError>,
scope: &mut Scope<T::Data>,
) -> PassResult {
for typedef in &self.typedefs { for typedef in &self.typedefs {
scope scope
.types .types

View File

@ -418,13 +418,13 @@ impl Expression {
let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1); let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
let expected_return_ty = ret_ty.resolve_ref(typerefs); let expected_return_ty = ret_ty.resolve_ref(typerefs);
let binops = typerefs.binop_types.filter(&pass::ScopeBinopKey { let binops = state.scope.binops.filter(&pass::ScopeBinopKey {
params: (lhs_type.clone(), rhs_type.clone()), params: (lhs_type.clone(), rhs_type.clone()),
operator: *op, operator: *op,
}); });
if let Some(binop) = binops if let Some(binop) = binops
.iter() .iter()
.filter(|f| f.1.return_ty == expected_return_ty) .filter(|f| f.1.return_ty.narrow_into(&expected_return_ty).is_ok())
.map(|v| (v.1.clone())) .map(|v| (v.1.clone()))
.next() .next()
{ {

View File

@ -119,6 +119,7 @@ impl BinopDefinition {
.fn_kind .fn_kind
.infer_types(state, &scope_hints, Some(self.return_type.clone()))?; .infer_types(state, &scope_hints, Some(self.return_type.clone()))?;
if let Some(mut ret_ty) = ret_ty { if let Some(mut ret_ty) = ret_ty {
dbg!(&ret_ty, &self.return_type);
ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap()); ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap());
} }
@ -296,7 +297,27 @@ impl Expression {
let mut lhs_ref = lhs.infer_types(state, type_refs)?; let mut lhs_ref = lhs.infer_types(state, type_refs)?;
let mut rhs_ref = rhs.infer_types(state, type_refs)?; let mut rhs_ref = rhs.infer_types(state, type_refs)?;
let binops = type_refs.available_binops(op, &mut lhs_ref, &mut rhs_ref); let binops = if let (Some(lhs_ty), Some(rhs_ty)) = (lhs_ref.resolve_deep(), rhs_ref.resolve_deep()) {
let mut applying_binops = Vec::new();
for (_, binop) in state.scope.binops.iter() {
if binop.operator != *op {
continue;
}
if let Some(_) = binop.narrow(&lhs_ty, &rhs_ty) {
applying_binops.push(binop.clone());
continue;
}
if binop.operator.is_commutative() {
if let Some(_) = binop.narrow(&lhs_ty, &rhs_ty) {
applying_binops.push(binop.clone());
continue;
}
}
}
applying_binops
} else {
Vec::new()
};
if binops.len() > 0 { if binops.len() > 0 {
let binop = unsafe { binops.get_unchecked(0) }; let binop = unsafe { binops.get_unchecked(0) };
@ -307,9 +328,15 @@ impl Expression {
widened_rhs = widened_rhs.widen_into(&binop.hands.1); widened_rhs = widened_rhs.widen_into(&binop.hands.1);
} }
let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref); let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref);
dbg!(&type_refs.types.type_refs);
dbg!(&type_refs.types.hints);
lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap()); lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap());
rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap()); rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap());
dbg!(&lhs_ref, &rhs_ref);
*return_ty = binop_res.as_type(); *return_ty = binop_res.as_type();
dbg!(&type_refs.types.hints, &type_refs.types.type_refs);
dbg!(&return_ty);
dbg!(&type_refs.from_type(&return_ty));
Ok(binop_res) Ok(binop_res)
} else { } else {
Err(ErrorKind::InvalidBinop( Err(ErrorKind::InvalidBinop(

View File

@ -283,14 +283,14 @@ impl<'outer> ScopeTypeRefs<'outer> {
match &lhs { match &lhs {
TypeKind::Vague(VagueType::TypeRef(idx)) => { TypeKind::Vague(VagueType::TypeRef(idx)) => {
let mut lhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self); let mut lhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self);
let narrowed = self.narrow_to_type(&mut lhs_ref, &lhs_narrow).unwrap_or(lhs_ref); self.narrow_to_type(&mut lhs_ref, &lhs_narrow).unwrap_or(lhs_ref);
} }
_ => {} _ => {}
}; };
match &rhs { match &rhs {
TypeKind::Vague(VagueType::TypeRef(idx)) => { TypeKind::Vague(VagueType::TypeRef(idx)) => {
let mut rhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self); let mut rhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self);
let narrowed = self.narrow_to_type(&mut rhs_ref, &rhs_narrow).unwrap_or(rhs_ref); self.narrow_to_type(&mut rhs_ref, &rhs_narrow).unwrap_or(rhs_ref);
} }
_ => {} _ => {}
} }
@ -312,9 +312,20 @@ impl<'outer> ScopeTypeRefs<'outer> {
.clone() .clone()
.widen(self.types); .widen(self.types);
self.narrow_to_type(&hint1, &ty)?; self.narrow_to_type(&hint1, &ty)?;
let hint1_typeref = self.types.retrieve_typeref(*hint1.0.borrow()).unwrap();
for idx in self.types.type_refs.borrow_mut().iter_mut() { for idx in self.types.type_refs.borrow_mut().iter_mut() {
if *idx == hint2.0 && idx != &hint1.0 { match hint1_typeref {
*idx.borrow_mut() = *hint1.0.borrow(); TypeRefKind::Direct(_) => {
if *idx == hint2.0 && idx != &hint1.0 {
*idx.borrow_mut() = *hint1.0.borrow();
}
}
TypeRefKind::BinOp(_, _, _) => {
// TODO may not be good ?
// if *idx == hint2.0 && idx != &hint1.0 {
// *idx.borrow_mut() = *hint1.0.borrow();
// }
}
} }
} }
Some(TypeRef(hint1.0.clone(), self)) Some(TypeRef(hint1.0.clone(), self))