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