Possibly fix typechecking for binops
This commit is contained in:
parent
8810d34d54
commit
27db67dd99
@ -21,5 +21,5 @@ fn main() -> u8 {
|
||||
|
||||
free_string(&test);
|
||||
|
||||
return addition(5, 3);
|
||||
return 8;
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ fn parse_binop_rhs(
|
||||
|
||||
lhs = Expression(
|
||||
ExpressionKind::Binop(op, Box::new(lhs), Box::new(rhs)),
|
||||
stream.get_range().unwrap(),
|
||||
stream.get_range_prev().unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,10 @@ impl<Key: std::hash::Hash + Eq, T: Clone + std::fmt::Debug> Storage<Key, T> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&Key, &T)> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
pub fn find(&self, key: &Key) -> Option<(&Key, &T)> {
|
||||
self.0.iter().find(|(k, _)| *k == key)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
@ -216,7 +220,6 @@ impl std::hash::Hash for ScopeBinopKey {
|
||||
pub struct ScopeBinopDef {
|
||||
pub hands: (TypeKind, TypeKind),
|
||||
pub operator: BinaryOperator,
|
||||
pub commutative: bool,
|
||||
pub return_ty: TypeKind,
|
||||
}
|
||||
|
||||
@ -370,7 +373,6 @@ impl Module {
|
||||
ScopeBinopDef {
|
||||
hands: (binop.lhs.1.clone(), binop.rhs.1.clone()),
|
||||
operator: binop.op,
|
||||
commutative: true,
|
||||
return_ty: binop.return_type.clone(),
|
||||
},
|
||||
)
|
||||
|
@ -514,14 +514,28 @@ impl Expression {
|
||||
let rhs_res = rhs.typecheck(state, &typerefs, None);
|
||||
let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
|
||||
|
||||
let operator = state
|
||||
.scope
|
||||
.binops
|
||||
.get(&pass::ScopeBinopKey {
|
||||
params: (lhs_type.clone(), rhs_type.clone()),
|
||||
operator: *op,
|
||||
})
|
||||
.cloned();
|
||||
let cloned = state.scope.binops.clone();
|
||||
let mut iter = cloned.iter();
|
||||
let operator = loop {
|
||||
let Some((_, binop)) = iter.next() else {
|
||||
break None;
|
||||
};
|
||||
if binop.operator != *op {
|
||||
continue;
|
||||
}
|
||||
if let Some(hint_t) = hint_t {
|
||||
if binop.return_ty == *hint_t {
|
||||
if let Some(_) = TypeKind::binop_type(&lhs_type, &rhs_type, binop) {
|
||||
break Some(binop);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if let Some(_) = TypeKind::binop_type(&lhs_type, &rhs_type, binop) {
|
||||
break Some(binop);
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(operator) = operator {
|
||||
// Re-typecheck with found operator hints
|
||||
@ -534,7 +548,7 @@ impl Expression {
|
||||
let rhs_res = rhs.typecheck(state, &typerefs, Some(&rhs_ty));
|
||||
state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1);
|
||||
state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
|
||||
Ok(operator.return_ty)
|
||||
Ok(operator.return_ty.clone())
|
||||
} else {
|
||||
// Re-typecheck with typical everyday binop
|
||||
let lhs_res = lhs.typecheck(
|
||||
|
@ -311,6 +311,7 @@ impl Expression {
|
||||
// Infer LHS and RHS, and return binop type
|
||||
let mut lhs_ref = lhs.infer_types(state, type_refs)?;
|
||||
let mut rhs_ref = rhs.infer_types(state, type_refs)?;
|
||||
|
||||
type_refs
|
||||
.binop(op, &mut lhs_ref, &mut rhs_ref, &state.scope.binops)
|
||||
.ok_or(ErrorKind::TypesIncompatible(
|
||||
|
@ -233,11 +233,16 @@ impl<'outer> ScopeTypeRefs<'outer> {
|
||||
rhs: &mut TypeRef<'outer>,
|
||||
binops: &Storage<ScopeBinopKey, ScopeBinopDef>,
|
||||
) -> Option<TypeRef<'outer>> {
|
||||
if lhs.resolve_deep().unwrap().known().is_err()
|
||||
&& rhs.resolve_deep().unwrap().known().is_err()
|
||||
{
|
||||
return self.from_type(&TypeKind::Vague(VagueType::Unknown));
|
||||
}
|
||||
for (_, binop) in binops.iter() {
|
||||
if let Some(ret) = try_binop(lhs, rhs, binop) {
|
||||
return Some(ret);
|
||||
}
|
||||
if binop.commutative {
|
||||
if binop.operator.is_commutative() {
|
||||
if let Some(ret) = try_binop(rhs, lhs, binop) {
|
||||
return Some(ret);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user