forked from M-Labs/nac3
WIP: core/typecheck: after np.newaxis and ...
This commit is contained in:
parent
2546053013
commit
c28166efb8
|
@ -335,6 +335,8 @@ pub mod util {
|
||||||
|
|
||||||
RustNDIndex::Slice(RustUserSlice { start, stop, step })
|
RustNDIndex::Slice(RustUserSlice { start, stop, step })
|
||||||
} else {
|
} else {
|
||||||
|
todo!("implement me");
|
||||||
|
|
||||||
// Anything else that is not a slice (might be illegal values),
|
// Anything else that is not a slice (might be illegal values),
|
||||||
// For nac3core, this should be e.g., an int32 constant, an int32 variable, otherwise its an error
|
// For nac3core, this should be e.g., an int32 constant, an int32 variable, otherwise its an error
|
||||||
let index = generator.gen_expr(ctx, index_expr)?.unwrap().to_basic_value_enum(
|
let index = generator.gen_expr(ctx, index_expr)?.unwrap().to_basic_value_enum(
|
||||||
|
|
|
@ -31,6 +31,7 @@ pub mod builtins;
|
||||||
pub mod composer;
|
pub mod composer;
|
||||||
pub mod helper;
|
pub mod helper;
|
||||||
pub mod numpy;
|
pub mod numpy;
|
||||||
|
pub mod option;
|
||||||
pub mod type_annotation;
|
pub mod type_annotation;
|
||||||
use composer::*;
|
use composer::*;
|
||||||
use type_annotation::*;
|
use type_annotation::*;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
symbol_resolver::SymbolValue,
|
symbol_resolver::SymbolValue,
|
||||||
toplevel::helper::PrimDef,
|
toplevel::helper::PrimDef,
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
toplevel::helper::PrimDef,
|
||||||
|
typecheck::{
|
||||||
|
type_inferencer::PrimitiveStore,
|
||||||
|
typedef::{Type, TypeEnum, Unifier, VarMap},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: This entire module is duplicated code (numpy.rs also has these kinds of things)
|
||||||
|
|
||||||
|
/// Creates a `option` [`Type`] with the given type arguments.
|
||||||
|
///
|
||||||
|
/// * `dtype` - The element type of the `option`, or [`None`] if the type variable is not
|
||||||
|
/// specialized.
|
||||||
|
/// * `ndims` - The number of dimensions of the `option`, or [`None`] if the type variable is not
|
||||||
|
/// specialized.
|
||||||
|
pub fn make_option_ty(
|
||||||
|
unifier: &mut Unifier,
|
||||||
|
primitives: &PrimitiveStore,
|
||||||
|
dtype: Option<Type>,
|
||||||
|
) -> Type {
|
||||||
|
subst_option_tvars(unifier, primitives.option, dtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Substitutes type variables in `option`.
|
||||||
|
///
|
||||||
|
/// * `dtype` - The element type of the `option`, or [`None`] if the type variable is not
|
||||||
|
/// specialized.
|
||||||
|
pub fn subst_option_tvars(unifier: &mut Unifier, option: Type, dtype: Option<Type>) -> Type {
|
||||||
|
let TypeEnum::TObj { obj_id, params, .. } = &*unifier.get_ty_immutable(option) else {
|
||||||
|
panic!("Expected `option` to be TObj, but got {}", unifier.stringify(option))
|
||||||
|
};
|
||||||
|
debug_assert_eq!(*obj_id, PrimDef::Option.id());
|
||||||
|
|
||||||
|
let tvar_ids = params.iter().map(|(obj_id, _)| *obj_id).collect_vec();
|
||||||
|
debug_assert_eq!(tvar_ids.len(), 1);
|
||||||
|
|
||||||
|
let mut tvar_subst = VarMap::new();
|
||||||
|
if let Some(dtype) = dtype {
|
||||||
|
tvar_subst.insert(tvar_ids[0], dtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
unifier.subst(option, &tvar_subst).unwrap_or(option)
|
||||||
|
}
|
|
@ -80,7 +80,7 @@ impl<'a> Inferencer<'a> {
|
||||||
return Err(HashSet::from([format!(
|
return Err(HashSet::from([format!(
|
||||||
"expected concrete type at {} but got {}",
|
"expected concrete type at {} but got {}",
|
||||||
expr.location,
|
expr.location,
|
||||||
self.unifier.get_ty(*ty).get_type_name()
|
self.unifier.stringify(*ty)
|
||||||
)]));
|
)]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ use super::{
|
||||||
RecordField, RecordKey, Type, TypeEnum, TypeVar, Unifier, VarMap,
|
RecordField, RecordKey, Type, TypeEnum, TypeVar, Unifier, VarMap,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use crate::toplevel::option::make_option_ty;
|
||||||
use crate::{
|
use crate::{
|
||||||
symbol_resolver::{SymbolResolver, SymbolValue},
|
symbol_resolver::{SymbolResolver, SymbolValue},
|
||||||
toplevel::{
|
toplevel::{
|
||||||
|
@ -2264,16 +2265,30 @@ impl<'a> Inferencer<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Constant { value: Constant::Ellipsis, .. } => {
|
ExprKind::Constant { value: Constant::Ellipsis, .. } => {
|
||||||
// Handle `...`. Do nothing.
|
// Handle `...`.
|
||||||
|
|
||||||
|
// See https://git.m-labs.hk/M-Labs/nac3/issues/486
|
||||||
|
// Force `...` to have `()` (completely bogus) to make it concrete.
|
||||||
|
let empty_tuple = TypeEnum::TTuple { ty: vec![], is_vararg_ctx: false };
|
||||||
|
let empty_tuple = self.unifier.add_ty(empty_tuple);
|
||||||
|
self.unify(index.custom.unwrap(), empty_tuple, &index.location)?;
|
||||||
}
|
}
|
||||||
ExprKind::Name { id, .. } if id == &"none".into() => {
|
ExprKind::Name { id, .. } if id == &"none".into() => {
|
||||||
// Handle `np.newaxis` / `None`.
|
// Handle `np.newaxis` / `None`.
|
||||||
dims_to_subtract -= 1;
|
dims_to_subtract -= 1;
|
||||||
|
|
||||||
|
// "none" itself has type `Option[T]`, and since we have a stray `T` (non-concrete type).
|
||||||
|
// We will force the type to be `Option[()]` to make it concrete. (TODO: is there a void type?)
|
||||||
|
let empty_tuple = TypeEnum::TTuple { ty: vec![], is_vararg_ctx: false };
|
||||||
|
let empty_tuple = self.unifier.add_ty(empty_tuple);
|
||||||
|
let expected_type =
|
||||||
|
make_option_ty(self.unifier, self.primitives, Some(empty_tuple));
|
||||||
|
self.unify(index.custom.unwrap(), expected_type, &index.location)?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Treat anything else as an integer index, and force unify their type to int32.
|
// Treat anything else as an integer index, and force unify their type to int32.
|
||||||
self.unify(index.custom.unwrap(), self.primitives.int32, &index.location)?;
|
|
||||||
dims_to_subtract += 1;
|
dims_to_subtract += 1;
|
||||||
|
self.unify(index.custom.unwrap(), self.primitives.int32, &index.location)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -621,8 +621,7 @@ impl Unifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unify_call(
|
pub fn unify_call(
|
||||||
&mut self,
|
&mut self, call: &Call,
|
||||||
call: &Call,
|
|
||||||
b: Type,
|
b: Type,
|
||||||
signature: &FunSignature,
|
signature: &FunSignature,
|
||||||
) -> Result<(), TypeError> {
|
) -> Result<(), TypeError> {
|
||||||
|
|
Loading…
Reference in New Issue