forked from M-Labs/nac3
core/typecheck: Inferencer allow heterogenerous assignemnt
This commit is contained in:
parent
e4f6adb1ec
commit
3d8240259c
|
@ -389,7 +389,7 @@ impl<'a> Fold<()> for Inferencer<'a> {
|
||||||
}
|
}
|
||||||
ast::StmtKind::Assign { targets, value, .. } => {
|
ast::StmtKind::Assign { targets, value, .. } => {
|
||||||
for target in targets {
|
for target in targets {
|
||||||
self.unify(target.custom.unwrap(), value.custom.unwrap(), &target.location)?;
|
self.fold_assign(target, value)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::StmtKind::Raise { exc, cause, .. } => {
|
ast::StmtKind::Raise { exc, cause, .. } => {
|
||||||
|
@ -2159,4 +2159,58 @@ impl<'a> Inferencer<'a> {
|
||||||
self.constrain(body.custom.unwrap(), orelse.custom.unwrap(), &body.location)?;
|
self.constrain(body.custom.unwrap(), orelse.custom.unwrap(), &body.location)?;
|
||||||
Ok(body.custom.unwrap())
|
Ok(body.custom.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_assign(
|
||||||
|
&mut self,
|
||||||
|
target: &ast::Expr<Option<Type>>,
|
||||||
|
value: &ast::Expr<Option<Type>>,
|
||||||
|
) -> Result<(), HashSet<String>> {
|
||||||
|
let target_ty = target.custom.unwrap();
|
||||||
|
let value_ty = value.custom.unwrap();
|
||||||
|
|
||||||
|
match (&target.node, &*self.unifier.get_ty(target_ty)) {
|
||||||
|
(ExprKind::Subscript { .. }, TypeEnum::TObj { obj_id: target_obj_id, .. })
|
||||||
|
if *target_obj_id == self.primitives.ndarray.obj_id(self.unifier).unwrap() =>
|
||||||
|
{
|
||||||
|
// Pattern match expressions like `my_ndarray[slices] = value`.
|
||||||
|
// TODO: `(my_ndarray[slices1], my_ndarray[slices2]) = (value1, value2)` are not supported for now.
|
||||||
|
|
||||||
|
// Suppose `my_ndarray` has type `ndarray[target_dtype, ndims]`
|
||||||
|
// value's type could be one of the following:
|
||||||
|
// Case 1. `target_dtype`
|
||||||
|
// Case 2. `ndarray[target_dtype, ?]`
|
||||||
|
// Case 3. list, tuple, iterables (TODO: NOT IMPLEMENTED)
|
||||||
|
|
||||||
|
let (target_dtype, _) = unpack_ndarray_var_tys(self.unifier, target_ty);
|
||||||
|
|
||||||
|
// Typecheck `value_ty`
|
||||||
|
match &*self.unifier.get_ty(value_ty) {
|
||||||
|
TypeEnum::TObj { obj_id: value_obj_id, .. }
|
||||||
|
if *value_obj_id
|
||||||
|
== self.primitives.ndarray.obj_id(self.unifier).unwrap() =>
|
||||||
|
{
|
||||||
|
// Case 2
|
||||||
|
// - `dtype` of `target_ty` and `value_ty` must unify.
|
||||||
|
// - `ndims` of `value_ty` is ignored.
|
||||||
|
let (value_dtype, _) = unpack_ndarray_var_tys(self.unifier, value_ty);
|
||||||
|
|
||||||
|
self.unify(target_dtype, value_dtype, &target.location)?;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// If `value_ty` is not an ndarray, simply typecheck as through it has to be Case 1.
|
||||||
|
self.unify(target_dtype, value_ty, &target.location)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// To handle
|
||||||
|
// - variable assignments `target = value`
|
||||||
|
// - and attribute assignments `target.my_attr = value`
|
||||||
|
//
|
||||||
|
// For these cases in nac3core, types of LHS and RHS must unify
|
||||||
|
self.unify(target_ty, value_ty, &target.location)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue