forked from M-Labs/nac3
1
0
Fork 0

core/object: remove *Object::is_instance

This makes implementations awkward.
This commit is contained in:
lyken 2024-08-23 10:11:43 +08:00
parent 5c68ef00ac
commit c0cace843d
No known key found for this signature in database
GPG Key ID: 3BD5FC6AC8325DD8
5 changed files with 95 additions and 33 deletions

View File

@ -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 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)
} else if ListObject::is_instance(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)
} else {
unsupported_type(ctx, "len", &[arg_ty])
list.len(generator, ctx).truncate(generator, ctx, Int32)
}
_ => unsupported_type(ctx, "len", &[arg_ty]),
};
len.truncate(generator, ctx, Int32).value
len.value
})
}

View File

@ -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,

View File

@ -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) {
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)
} else {
ScalarOrNDArray::Scalar(object)
}
_ => ScalarOrNDArray::Scalar(object),
}
}

View File

@ -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)
}
}

View File

@ -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,