forked from M-Labs/nac3
core/object: remove *Object::is_instance
This makes implementations awkward.
This commit is contained in:
parent
5c68ef00ac
commit
c0cace843d
|
@ -9,7 +9,7 @@ use crate::codegen::irrt::calculate_len_for_slice_range;
|
|||
use crate::codegen::object::ndarray::{NDArrayOut, ScalarOrNDArray};
|
||||
use crate::codegen::{extern_fns, irrt, llvm_intrinsics, CodeGenContext, CodeGenerator};
|
||||
use crate::toplevel::helper::PrimDef;
|
||||
use crate::typecheck::typedef::Type;
|
||||
use crate::typecheck::typedef::{Type, TypeEnum};
|
||||
|
||||
use super::model::*;
|
||||
use super::object::any::AnyObject;
|
||||
|
@ -40,19 +40,26 @@ pub fn call_len<'ctx, G: CodeGenerator + ?Sized>(
|
|||
calculate_len_for_slice_range(generator, ctx, start, end, step)
|
||||
} else {
|
||||
let arg = AnyObject { ty: arg_ty, value: arg };
|
||||
let len = if NDArrayObject::is_instance(ctx, arg) {
|
||||
let ndarray = NDArrayObject::from_object(generator, ctx, arg);
|
||||
ndarray.len(generator, ctx)
|
||||
} else if TupleObject::is_instance(ctx, arg) {
|
||||
let tuple = TupleObject::from_object(ctx, arg);
|
||||
tuple.len(generator, ctx)
|
||||
} else if ListObject::is_instance(ctx, arg) {
|
||||
let list = ListObject::from_object(generator, ctx, arg);
|
||||
list.len(generator, ctx)
|
||||
} else {
|
||||
unsupported_type(ctx, "len", &[arg_ty])
|
||||
let len: Instance<'ctx, Int<Int32>> = match &*ctx.unifier.get_ty(arg_ty) {
|
||||
TypeEnum::TTuple { .. } => {
|
||||
let tuple = TupleObject::from_object(ctx, arg);
|
||||
tuple.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||
}
|
||||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let ndarray = NDArrayObject::from_object(generator, ctx, arg);
|
||||
ndarray.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||
}
|
||||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.list.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let list = ListObject::from_object(generator, ctx, arg);
|
||||
list.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||
}
|
||||
_ => unsupported_type(ctx, "len", &[arg_ty]),
|
||||
};
|
||||
len.truncate(generator, ctx, Int32).value
|
||||
len.value
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,11 @@ impl<'ctx> ListObject<'ctx> {
|
|||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
object: AnyObject<'ctx>,
|
||||
) -> Self {
|
||||
assert!(matches!(
|
||||
&*ctx.unifier.get_ty(object.ty),
|
||||
TypeEnum::TObj { obj_id, .. } if *obj_id == ctx.primitives.list.obj_id(&ctx.unifier).unwrap()
|
||||
));
|
||||
|
||||
// Check typechecker type and extract `item_type`
|
||||
let item_type = match &*ctx.unifier.get_ty(object.ty) {
|
||||
TypeEnum::TObj { obj_id, params, .. }
|
||||
|
@ -65,11 +70,6 @@ impl<'ctx> ListObject<'ctx> {
|
|||
ListObject { item_type, instance: value }
|
||||
}
|
||||
|
||||
/// Check if an object can be converted into an ndarray.
|
||||
pub fn is_instance(ctx: &mut CodeGenContext<'ctx, '_>, object: AnyObject<'ctx>) -> bool {
|
||||
matches!(&*ctx.unifier.get_ty(object.ty), TypeEnum::TObj { obj_id, .. } if *obj_id == ctx.primitives.list.obj_id(&ctx.unifier).unwrap())
|
||||
}
|
||||
|
||||
/// Get the `len()` of this list.
|
||||
pub fn len<G: CodeGenerator + ?Sized>(
|
||||
&self,
|
||||
|
|
|
@ -99,11 +99,6 @@ impl<'ctx> NDArrayObject<'ctx> {
|
|||
NDArrayObject { dtype, ndims, instance: value }
|
||||
}
|
||||
|
||||
/// Check if an object can be converted into an ndarray.
|
||||
pub fn is_instance(ctx: &mut CodeGenContext<'ctx, '_>, object: AnyObject<'ctx>) -> bool {
|
||||
matches!(&*ctx.unifier.get_ty(object.ty), TypeEnum::TObj { obj_id, .. } if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap())
|
||||
}
|
||||
|
||||
/// Get this ndarray's `ndims` as an LLVM constant.
|
||||
pub fn ndims_llvm<G: CodeGenerator + ?Sized>(
|
||||
&self,
|
||||
|
@ -592,11 +587,14 @@ impl<'ctx> ScalarOrNDArray<'ctx> {
|
|||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
object: AnyObject<'ctx>,
|
||||
) -> ScalarOrNDArray<'ctx> {
|
||||
if NDArrayObject::is_instance(ctx, object) {
|
||||
let ndarray = NDArrayObject::from_object(generator, ctx, object);
|
||||
ScalarOrNDArray::NDArray(ndarray)
|
||||
} else {
|
||||
ScalarOrNDArray::Scalar(object)
|
||||
match &*ctx.unifier.get_ty(object.ty) {
|
||||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let ndarray = NDArrayObject::from_object(generator, ctx, object);
|
||||
ScalarOrNDArray::NDArray(ndarray)
|
||||
}
|
||||
_ => ScalarOrNDArray::Scalar(object),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
use crate::codegen::{irrt::call_nac3_range_len_i32, model::*, CodeGenContext, CodeGenerator};
|
||||
|
||||
use super::any::AnyObject;
|
||||
|
||||
/// A range in NAC3.
|
||||
pub type Range<N> = Array<Len<3>, Int<N>>;
|
||||
|
||||
impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Ptr<Range<N>>> {
|
||||
/// Get GEP to `range.start`.
|
||||
pub fn start(&self, ctx: &CodeGenContext<'ctx, '_>) -> Instance<'ctx, Ptr<Int<N>>> {
|
||||
self.gep_const(ctx, 0)
|
||||
}
|
||||
|
||||
/// Get GEP to `range.stop`.
|
||||
pub fn stop(&self, ctx: &CodeGenContext<'ctx, '_>) -> Instance<'ctx, Ptr<Int<N>>> {
|
||||
self.gep_const(ctx, 1)
|
||||
}
|
||||
|
||||
/// Get GEP to `range.step`.
|
||||
pub fn step(&self, ctx: &CodeGenContext<'ctx, '_>) -> Instance<'ctx, Ptr<Int<N>>> {
|
||||
self.gep_const(ctx, 2)
|
||||
}
|
||||
}
|
||||
|
||||
/// A NAC3 Python range object.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct RangeObject<'ctx> {
|
||||
pub instance: Instance<'ctx, Ptr<Range<Int32>>>, // TODO: Ptr<Range<AnyInt>> in the future when there is range32, range64
|
||||
}
|
||||
|
||||
impl<'ctx> RangeObject<'ctx> {
|
||||
/// Attempt to convert an [`AnyObject`] into a [`RangeObject`].
|
||||
pub fn from_object<G: CodeGenerator + ?Sized>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
object: AnyObject<'ctx>,
|
||||
) -> RangeObject<'ctx> {
|
||||
assert!(RangeObject::is_instance(ctx, object));
|
||||
|
||||
let instance = Ptr(Range::default()).check_value(generator, ctx.ctx, object.value).unwrap();
|
||||
RangeObject { instance }
|
||||
}
|
||||
|
||||
/// Check if an object can be converted into a range.
|
||||
pub fn is_instance(ctx: &mut CodeGenContext<'ctx, '_>, object: AnyObject<'ctx>) -> bool {
|
||||
ctx.unifier.unioned(object.ty, ctx.primitives.range)
|
||||
}
|
||||
|
||||
/// Get the `len()` of this range.
|
||||
pub fn len<G: CodeGenerator + ?Sized>(
|
||||
&self,
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
) -> Instance<'ctx, Int<Int32>> {
|
||||
let start = self.instance.start(ctx).load(generator, ctx);
|
||||
let stop = self.instance.stop(ctx).load(generator, ctx);
|
||||
let step = self.instance.step(ctx).load(generator, ctx);
|
||||
call_nac3_range_len_i32(generator, ctx, start, stop, step)
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@ impl<'ctx> TupleObject<'ctx> {
|
|||
pub fn from_object(ctx: &mut CodeGenContext<'ctx, '_>, object: AnyObject<'ctx>) -> Self {
|
||||
// TODO: Keep `is_vararg_ctx` from TTuple?
|
||||
|
||||
assert!(matches!(&*ctx.unifier.get_ty(object.ty), TypeEnum::TTuple { .. }));
|
||||
|
||||
// Sanity check on object type.
|
||||
let TypeEnum::TTuple { ty: tys, .. } = &*ctx.unifier.get_ty(object.ty) else {
|
||||
panic!(
|
||||
|
@ -44,11 +46,6 @@ impl<'ctx> TupleObject<'ctx> {
|
|||
TupleObject { tys: tys.clone(), value }
|
||||
}
|
||||
|
||||
/// Check if an object can be converted into a tuple.
|
||||
pub fn is_instance(ctx: &mut CodeGenContext<'ctx, '_>, object: AnyObject<'ctx>) -> bool {
|
||||
matches!(&*ctx.unifier.get_ty(object.ty), TypeEnum::TTuple { .. })
|
||||
}
|
||||
|
||||
/// Convenience function. Create a [`TupleObject`] from an iterator of objects.
|
||||
pub fn from_objects<I, G: CodeGenerator + ?Sized>(
|
||||
generator: &mut G,
|
||||
|
|
Loading…
Reference in New Issue