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::object::ndarray::{NDArrayOut, ScalarOrNDArray};
|
||||||
use crate::codegen::{extern_fns, irrt, llvm_intrinsics, CodeGenContext, CodeGenerator};
|
use crate::codegen::{extern_fns, irrt, llvm_intrinsics, CodeGenContext, CodeGenerator};
|
||||||
use crate::toplevel::helper::PrimDef;
|
use crate::toplevel::helper::PrimDef;
|
||||||
use crate::typecheck::typedef::Type;
|
use crate::typecheck::typedef::{Type, TypeEnum};
|
||||||
|
|
||||||
use super::model::*;
|
use super::model::*;
|
||||||
use super::object::any::AnyObject;
|
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)
|
calculate_len_for_slice_range(generator, ctx, start, end, step)
|
||||||
} else {
|
} else {
|
||||||
let arg = AnyObject { ty: arg_ty, value: arg };
|
let arg = AnyObject { ty: arg_ty, value: arg };
|
||||||
let len = if NDArrayObject::is_instance(ctx, arg) {
|
let len: Instance<'ctx, Int<Int32>> = match &*ctx.unifier.get_ty(arg_ty) {
|
||||||
let ndarray = NDArrayObject::from_object(generator, ctx, arg);
|
TypeEnum::TTuple { .. } => {
|
||||||
ndarray.len(generator, ctx)
|
let tuple = TupleObject::from_object(ctx, arg);
|
||||||
} else if TupleObject::is_instance(ctx, arg) {
|
tuple.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||||
let tuple = TupleObject::from_object(ctx, arg);
|
}
|
||||||
tuple.len(generator, ctx)
|
TypeEnum::TObj { obj_id, .. }
|
||||||
} else if ListObject::is_instance(ctx, arg) {
|
if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap() =>
|
||||||
let list = ListObject::from_object(generator, ctx, arg);
|
{
|
||||||
list.len(generator, ctx)
|
let ndarray = NDArrayObject::from_object(generator, ctx, arg);
|
||||||
} else {
|
ndarray.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||||
unsupported_type(ctx, "len", &[arg_ty])
|
}
|
||||||
|
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, '_>,
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
object: AnyObject<'ctx>,
|
object: AnyObject<'ctx>,
|
||||||
) -> Self {
|
) -> 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`
|
// Check typechecker type and extract `item_type`
|
||||||
let item_type = match &*ctx.unifier.get_ty(object.ty) {
|
let item_type = match &*ctx.unifier.get_ty(object.ty) {
|
||||||
TypeEnum::TObj { obj_id, params, .. }
|
TypeEnum::TObj { obj_id, params, .. }
|
||||||
|
@ -65,11 +70,6 @@ impl<'ctx> ListObject<'ctx> {
|
||||||
ListObject { item_type, instance: value }
|
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.
|
/// Get the `len()` of this list.
|
||||||
pub fn len<G: CodeGenerator + ?Sized>(
|
pub fn len<G: CodeGenerator + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -99,11 +99,6 @@ impl<'ctx> NDArrayObject<'ctx> {
|
||||||
NDArrayObject { dtype, ndims, instance: value }
|
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.
|
/// Get this ndarray's `ndims` as an LLVM constant.
|
||||||
pub fn ndims_llvm<G: CodeGenerator + ?Sized>(
|
pub fn ndims_llvm<G: CodeGenerator + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -592,11 +587,14 @@ impl<'ctx> ScalarOrNDArray<'ctx> {
|
||||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
object: AnyObject<'ctx>,
|
object: AnyObject<'ctx>,
|
||||||
) -> ScalarOrNDArray<'ctx> {
|
) -> ScalarOrNDArray<'ctx> {
|
||||||
if NDArrayObject::is_instance(ctx, object) {
|
match &*ctx.unifier.get_ty(object.ty) {
|
||||||
let ndarray = NDArrayObject::from_object(generator, ctx, object);
|
TypeEnum::TObj { obj_id, .. }
|
||||||
ScalarOrNDArray::NDArray(ndarray)
|
if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap() =>
|
||||||
} else {
|
{
|
||||||
ScalarOrNDArray::Scalar(object)
|
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 {
|
pub fn from_object(ctx: &mut CodeGenContext<'ctx, '_>, object: AnyObject<'ctx>) -> Self {
|
||||||
// TODO: Keep `is_vararg_ctx` from TTuple?
|
// TODO: Keep `is_vararg_ctx` from TTuple?
|
||||||
|
|
||||||
|
assert!(matches!(&*ctx.unifier.get_ty(object.ty), TypeEnum::TTuple { .. }));
|
||||||
|
|
||||||
// Sanity check on object type.
|
// Sanity check on object type.
|
||||||
let TypeEnum::TTuple { ty: tys, .. } = &*ctx.unifier.get_ty(object.ty) else {
|
let TypeEnum::TTuple { ty: tys, .. } = &*ctx.unifier.get_ty(object.ty) else {
|
||||||
panic!(
|
panic!(
|
||||||
|
@ -44,11 +46,6 @@ impl<'ctx> TupleObject<'ctx> {
|
||||||
TupleObject { tys: tys.clone(), value }
|
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.
|
/// Convenience function. Create a [`TupleObject`] from an iterator of objects.
|
||||||
pub fn from_objects<I, G: CodeGenerator + ?Sized>(
|
pub fn from_objects<I, G: CodeGenerator + ?Sized>(
|
||||||
generator: &mut G,
|
generator: &mut G,
|
||||||
|
|
Loading…
Reference in New Issue