From da8480148ae94432e3891194b4cba1982f4ae99a Mon Sep 17 00:00:00 2001 From: David Mak Date: Thu, 23 Jan 2025 14:45:45 +0800 Subject: [PATCH] [core] codegen: Refactor Proxy{Type,Value} for StructProxy{Type,Value} --- nac3artiq/src/codegen.rs | 6 +- nac3core/src/codegen/builtin_fns.rs | 6 +- nac3core/src/codegen/expr.rs | 4 +- .../src/codegen/irrt/ndarray/broadcast.rs | 7 +- nac3core/src/codegen/stmt.rs | 6 +- nac3core/src/codegen/test.rs | 4 +- nac3core/src/codegen/types/list.rs | 65 ++--- nac3core/src/codegen/types/mod.rs | 15 +- .../src/codegen/types/ndarray/broadcast.rs | 53 ++-- .../src/codegen/types/ndarray/contiguous.rs | 69 +++--- .../src/codegen/types/ndarray/indexing.rs | 47 ++-- nac3core/src/codegen/types/ndarray/mod.rs | 49 ++-- nac3core/src/codegen/types/ndarray/nditer.rs | 49 ++-- nac3core/src/codegen/types/range.rs | 233 +++++++++--------- nac3core/src/codegen/types/tuple.rs | 22 +- nac3core/src/codegen/types/utils/slice.rs | 97 ++++---- nac3core/src/codegen/values/list.rs | 11 +- nac3core/src/codegen/values/mod.rs | 20 +- .../src/codegen/values/ndarray/broadcast.rs | 11 +- .../src/codegen/values/ndarray/contiguous.rs | 11 +- .../src/codegen/values/ndarray/indexing.rs | 11 +- nac3core/src/codegen/values/ndarray/mod.rs | 11 +- nac3core/src/codegen/values/ndarray/nditer.rs | 11 +- nac3core/src/codegen/values/range.rs | 23 +- nac3core/src/codegen/values/tuple.rs | 11 +- nac3core/src/codegen/values/utils/slice.rs | 11 +- nac3core/src/toplevel/builtins.rs | 6 +- 27 files changed, 339 insertions(+), 530 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index e4727056..4c86028f 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -19,9 +19,9 @@ use nac3core::{ llvm_intrinsics::{call_int_smax, call_memcpy, call_stackrestore, call_stacksave}, stmt::{gen_block, gen_for_callback_incrementing, gen_if_callback, gen_with}, type_aligned_alloca, - types::ndarray::NDArrayType, + types::{ndarray::NDArrayType, RangeType}, values::{ - ArrayLikeIndexer, ArrayLikeValue, ArraySliceValue, ListValue, ProxyValue, RangeValue, + ArrayLikeIndexer, ArrayLikeValue, ArraySliceValue, ListValue, ProxyValue, UntypedArrayLikeAccessor, }, CodeGenContext, CodeGenerator, @@ -1431,7 +1431,7 @@ fn polymorphic_print<'ctx>( fmt.push_str("range("); flush(ctx, generator, &mut fmt, &mut args); - let val = RangeValue::from_pointer_value(value.into_pointer_value(), None); + let val = RangeType::new(ctx).map_value(value.into_pointer_value(), None); let (start, stop, step) = destructure_range(ctx, val); diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index 911e3dc1..6cacac45 100644 --- a/nac3core/src/codegen/builtin_fns.rs +++ b/nac3core/src/codegen/builtin_fns.rs @@ -11,10 +11,10 @@ use super::{ irrt::calculate_len_for_slice_range, llvm_intrinsics, macros::codegen_unreachable, - types::{ndarray::NDArrayType, ListType, TupleType}, + types::{ndarray::NDArrayType, ListType, RangeType, TupleType}, values::{ ndarray::{NDArrayOut, NDArrayValue, ScalarOrNDArray}, - ProxyValue, RangeValue, TypedArrayLikeAccessor, UntypedArrayLikeAccessor, + ProxyValue, TypedArrayLikeAccessor, UntypedArrayLikeAccessor, }, CodeGenContext, CodeGenerator, }; @@ -47,7 +47,7 @@ pub fn call_len<'ctx, G: CodeGenerator + ?Sized>( let range_ty = ctx.primitives.range; Ok(if ctx.unifier.unioned(arg_ty, range_ty) { - let arg = RangeValue::from_pointer_value(arg.into_pointer_value(), Some("range")); + let arg = RangeType::new(ctx).map_value(arg.into_pointer_value(), Some("range")); let (start, end, step) = destructure_range(ctx, arg); calculate_len_for_slice_range(generator, ctx, start, end, step) } else { diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index fd2cd286..4da0ef33 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -32,7 +32,7 @@ use super::{ gen_for_callback_incrementing, gen_if_callback, gen_if_else_expr_callback, gen_raise, gen_var, }, - types::{ndarray::NDArrayType, ListType}, + types::{ndarray::NDArrayType, ListType, RangeType}, values::{ ndarray::{NDArrayOut, RustNDIndex, ScalarOrNDArray}, ArrayLikeIndexer, ArrayLikeValue, ListValue, ProxyValue, RangeValue, @@ -1151,7 +1151,7 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>( if *obj_id == ctx.primitives.range.obj_id(&ctx.unifier).unwrap() => { let iter_val = - RangeValue::from_pointer_value(iter_val.into_pointer_value(), Some("range")); + RangeType::new(ctx).map_value(iter_val.into_pointer_value(), Some("range")); let (start, stop, step) = destructure_range(ctx, iter_val); let diff = ctx.builder.build_int_sub(stop, start, "diff").unwrap(); // add 1 to the length as the value is rounded to zero diff --git a/nac3core/src/codegen/irrt/ndarray/broadcast.rs b/nac3core/src/codegen/irrt/ndarray/broadcast.rs index fceba25f..a7d40a57 100644 --- a/nac3core/src/codegen/irrt/ndarray/broadcast.rs +++ b/nac3core/src/codegen/irrt/ndarray/broadcast.rs @@ -55,10 +55,9 @@ pub fn call_nac3_ndarray_broadcast_shapes<'ctx, G, Shape>( let llvm_usize = ctx.get_size_type(); assert_eq!(num_shape_entries.get_type(), llvm_usize); - assert!(ShapeEntryType::is_type( - generator, - ctx.ctx, - shape_entries.base_ptr(ctx, generator).get_type() + assert!(ShapeEntryType::is_representable( + shape_entries.base_ptr(ctx, generator).get_type(), + llvm_usize, ) .is_ok()); assert_eq!(dst_ndims.get_type(), llvm_usize); diff --git a/nac3core/src/codegen/stmt.rs b/nac3core/src/codegen/stmt.rs index 7b99bc26..e8f1d906 100644 --- a/nac3core/src/codegen/stmt.rs +++ b/nac3core/src/codegen/stmt.rs @@ -17,10 +17,10 @@ use super::{ gen_in_range_check, irrt::{handle_slice_indices, list_slice_assignment}, macros::codegen_unreachable, - types::ndarray::NDArrayType, + types::{ndarray::NDArrayType, RangeType}, values::{ ndarray::{RustNDIndex, ScalarOrNDArray}, - ArrayLikeIndexer, ArraySliceValue, ListValue, ProxyValue, RangeValue, + ArrayLikeIndexer, ArraySliceValue, ListValue, ProxyValue, }, CodeGenContext, CodeGenerator, }; @@ -511,7 +511,7 @@ pub fn gen_for( if *obj_id == ctx.primitives.range.obj_id(&ctx.unifier).unwrap() => { let iter_val = - RangeValue::from_pointer_value(iter_val.into_pointer_value(), Some("range")); + RangeType::new(ctx).map_value(iter_val.into_pointer_value(), Some("range")); // Internal variable for loop; Cannot be assigned let i = generator.gen_var_alloc(ctx, int32.into(), Some("for.i.addr"))?; // Variable declared in "target" expression of the loop; Can be reassigned *or* shadowed diff --git a/nac3core/src/codegen/test.rs b/nac3core/src/codegen/test.rs index 01672c55..ecc0ba96 100644 --- a/nac3core/src/codegen/test.rs +++ b/nac3core/src/codegen/test.rs @@ -455,8 +455,10 @@ fn test_classes_range_type_new() { let ctx = inkwell::context::Context::create(); let generator = DefaultCodeGenerator::new(String::new(), ctx.i64_type()); + let llvm_usize = generator.get_size_type(&ctx); + let llvm_range = RangeType::new_with_generator(&generator, &ctx); - assert!(RangeType::is_representable(llvm_range.as_base_type()).is_ok()); + assert!(RangeType::is_representable(llvm_range.as_base_type(), llvm_usize).is_ok()); } #[test] diff --git a/nac3core/src/codegen/types/list.rs b/nac3core/src/codegen/types/list.rs index 637cced3..60015b8c 100644 --- a/nac3core/src/codegen/types/list.rs +++ b/nac3core/src/codegen/types/list.rs @@ -56,34 +56,6 @@ impl<'ctx> ListStructFields<'ctx> { } impl<'ctx> ListType<'ctx> { - /// Checks whether `llvm_ty` represents a `list` type, returning [Err] if it does not. - pub fn is_representable( - llvm_ty: PointerType<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - let ctx = llvm_ty.get_context(); - - let llvm_ty = llvm_ty.get_element_type(); - let AnyTypeEnum::StructType(llvm_ty) = llvm_ty else { - return Err(format!("Expected struct type for `list` type, got {llvm_ty}")); - }; - - let fields = ListStructFields::new(ctx, llvm_usize); - - check_struct_type_matches_fields( - fields, - llvm_ty, - "list", - &[(fields.items.name(), &|ty| { - if ty.is_pointer_type() { - Ok(()) - } else { - Err(format!("Expected T* for `list.items`, got {ty}")) - } - })], - ) - } - /// Returns an instance of [`StructFields`] containing all field accessors for this type. #[must_use] fn fields(item: BasicTypeEnum<'ctx>, llvm_usize: IntType<'ctx>) -> ListStructFields<'ctx> { @@ -184,7 +156,7 @@ impl<'ctx> ListType<'ctx> { /// Creates an [`ListType`] from a [`PointerType`]. #[must_use] pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { - debug_assert!(Self::is_representable(ptr_ty, llvm_usize).is_ok()); + debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); let ctx = ptr_ty.get_context(); @@ -336,24 +308,39 @@ impl<'ctx> ProxyType<'ctx> for ListType<'ctx> { type Base = PointerType<'ctx>; type Value = ListValue<'ctx>; - fn is_type( - generator: &G, - ctx: &'ctx Context, + fn is_representable( llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, ) -> Result<(), String> { if let BasicTypeEnum::PointerType(ty) = llvm_ty.as_basic_type_enum() { - >::is_representable(generator, ctx, ty) + Self::has_same_repr(ty, llvm_usize) } else { Err(format!("Expected pointer type, got {llvm_ty:?}")) } } - fn is_representable( - generator: &G, - ctx: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String> { - Self::is_representable(llvm_ty, generator.get_size_type(ctx)) + fn has_same_repr(ty: Self::Base, llvm_usize: IntType<'ctx>) -> Result<(), String> { + let ctx = ty.get_context(); + + let llvm_ty = ty.get_element_type(); + let AnyTypeEnum::StructType(llvm_ty) = llvm_ty else { + return Err(format!("Expected struct type for `list` type, got {llvm_ty}")); + }; + + let fields = ListStructFields::new(ctx, llvm_usize); + + check_struct_type_matches_fields( + fields, + llvm_ty, + "list", + &[(fields.items.name(), &|ty| { + if ty.is_pointer_type() { + Ok(()) + } else { + Err(format!("Expected T* for `list.items`, got {ty}")) + } + })], + ) } fn alloca_type(&self) -> impl BasicType<'ctx> { diff --git a/nac3core/src/codegen/types/mod.rs b/nac3core/src/codegen/types/mod.rs index 0a31d6a5..1c66a7d1 100644 --- a/nac3core/src/codegen/types/mod.rs +++ b/nac3core/src/codegen/types/mod.rs @@ -17,8 +17,7 @@ //! on the stack. use inkwell::{ - context::Context, - types::BasicType, + types::{BasicType, IntType}, values::{IntValue, PointerValue}, }; @@ -46,18 +45,12 @@ pub trait ProxyType<'ctx>: Into { /// The type of values represented by this type. type Value: ProxyValue<'ctx, Type = Self>; - fn is_type( - generator: &G, - ctx: &'ctx Context, + fn is_representable( llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, ) -> Result<(), String>; - /// Checks whether `llvm_ty` can be represented by this [`ProxyType`]. - fn is_representable( - generator: &G, - ctx: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String>; + fn has_same_repr(ty: Self::Base, llvm_usize: IntType<'ctx>) -> Result<(), String>; /// Returns the type that should be used in `alloca` IR statements. fn alloca_type(&self) -> impl BasicType<'ctx>; diff --git a/nac3core/src/codegen/types/ndarray/broadcast.rs b/nac3core/src/codegen/types/ndarray/broadcast.rs index 3a1fd8da..af1a26fa 100644 --- a/nac3core/src/codegen/types/ndarray/broadcast.rs +++ b/nac3core/src/codegen/types/ndarray/broadcast.rs @@ -32,28 +32,6 @@ pub struct ShapeEntryStructFields<'ctx> { } impl<'ctx> ShapeEntryType<'ctx> { - /// Checks whether `llvm_ty` represents a [`ShapeEntryType`], returning [Err] if it does not. - pub fn is_representable( - llvm_ty: PointerType<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - let ctx = llvm_ty.get_context(); - - let llvm_ndarray_ty = llvm_ty.get_element_type(); - let AnyTypeEnum::StructType(llvm_ndarray_ty) = llvm_ndarray_ty else { - return Err(format!( - "Expected struct type for `ShapeEntry` type, got {llvm_ndarray_ty}" - )); - }; - - check_struct_type_matches_fields( - Self::fields(ctx, llvm_usize), - llvm_ndarray_ty, - "NDArray", - &[], - ) - } - /// Returns an instance of [`StructFields`] containing all field accessors for this type. #[must_use] fn fields( @@ -103,7 +81,7 @@ impl<'ctx> ShapeEntryType<'ctx> { /// Creates a [`ShapeEntryType`] from a [`PointerType`] representing an `ShapeEntry`. #[must_use] pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { - debug_assert!(Self::is_representable(ptr_ty, llvm_usize).is_ok()); + debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); Self { ty: ptr_ty, llvm_usize } } @@ -152,24 +130,33 @@ impl<'ctx> ProxyType<'ctx> for ShapeEntryType<'ctx> { type Base = PointerType<'ctx>; type Value = ShapeEntryValue<'ctx>; - fn is_type( - generator: &G, - ctx: &'ctx Context, + fn is_representable( llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, ) -> Result<(), String> { if let BasicTypeEnum::PointerType(ty) = llvm_ty.as_basic_type_enum() { - >::is_representable(generator, ctx, ty) + Self::has_same_repr(ty, llvm_usize) } else { Err(format!("Expected pointer type, got {llvm_ty:?}")) } } - fn is_representable( - generator: &G, - ctx: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String> { - Self::is_representable(llvm_ty, generator.get_size_type(ctx)) + fn has_same_repr(ty: Self::Base, llvm_usize: IntType<'ctx>) -> Result<(), String> { + let ctx = ty.get_context(); + + let llvm_ndarray_ty = ty.get_element_type(); + let AnyTypeEnum::StructType(llvm_ndarray_ty) = llvm_ndarray_ty else { + return Err(format!( + "Expected struct type for `ShapeEntry` type, got {llvm_ndarray_ty}" + )); + }; + + check_struct_type_matches_fields( + Self::fields(ctx, llvm_usize), + llvm_ndarray_ty, + "NDArray", + &[], + ) } fn alloca_type(&self) -> impl BasicType<'ctx> { diff --git a/nac3core/src/codegen/types/ndarray/contiguous.rs b/nac3core/src/codegen/types/ndarray/contiguous.rs index c751d573..1987ab6d 100644 --- a/nac3core/src/codegen/types/ndarray/contiguous.rs +++ b/nac3core/src/codegen/types/ndarray/contiguous.rs @@ -58,36 +58,6 @@ impl<'ctx> ContiguousNDArrayStructFields<'ctx> { } impl<'ctx> ContiguousNDArrayType<'ctx> { - /// Checks whether `llvm_ty` represents a `ndarray` type, returning [Err] if it does not. - pub fn is_representable( - llvm_ty: PointerType<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - let ctx = llvm_ty.get_context(); - - let llvm_ty = llvm_ty.get_element_type(); - let AnyTypeEnum::StructType(llvm_ty) = llvm_ty else { - return Err(format!( - "Expected struct type for `ContiguousNDArray` type, got {llvm_ty}" - )); - }; - - let fields = ContiguousNDArrayStructFields::new(ctx, llvm_usize); - - check_struct_type_matches_fields( - fields, - llvm_ty, - "ContiguousNDArray", - &[(fields.data.name(), &|ty| { - if ty.is_pointer_type() { - Ok(()) - } else { - Err(format!("Expected T* for `ContiguousNDArray.data`, got {ty}")) - } - })], - ) - } - /// Returns an instance of [`StructFields`] containing all field accessors for this type. #[must_use] fn fields( @@ -160,7 +130,7 @@ impl<'ctx> ContiguousNDArrayType<'ctx> { item: BasicTypeEnum<'ctx>, llvm_usize: IntType<'ctx>, ) -> Self { - debug_assert!(Self::is_representable(ptr_ty, llvm_usize).is_ok()); + debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); Self { ty: ptr_ty, item, llvm_usize } } @@ -222,24 +192,41 @@ impl<'ctx> ProxyType<'ctx> for ContiguousNDArrayType<'ctx> { type Base = PointerType<'ctx>; type Value = ContiguousNDArrayValue<'ctx>; - fn is_type( - generator: &G, - ctx: &'ctx Context, + fn is_representable( llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, ) -> Result<(), String> { if let BasicTypeEnum::PointerType(ty) = llvm_ty.as_basic_type_enum() { - >::is_representable(generator, ctx, ty) + Self::has_same_repr(ty, llvm_usize) } else { Err(format!("Expected pointer type, got {llvm_ty:?}")) } } - fn is_representable( - generator: &G, - ctx: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String> { - Self::is_representable(llvm_ty, generator.get_size_type(ctx)) + fn has_same_repr(ty: Self::Base, llvm_usize: IntType<'ctx>) -> Result<(), String> { + let ctx = ty.get_context(); + + let llvm_ty = ty.get_element_type(); + let AnyTypeEnum::StructType(llvm_ty) = llvm_ty else { + return Err(format!( + "Expected struct type for `ContiguousNDArray` type, got {llvm_ty}" + )); + }; + + let fields = ContiguousNDArrayStructFields::new(ctx, llvm_usize); + + check_struct_type_matches_fields( + fields, + llvm_ty, + "ContiguousNDArray", + &[(fields.data.name(), &|ty| { + if ty.is_pointer_type() { + Ok(()) + } else { + Err(format!("Expected T* for `ContiguousNDArray.data`, got {ty}")) + } + })], + ) } fn alloca_type(&self) -> impl BasicType<'ctx> { diff --git a/nac3core/src/codegen/types/ndarray/indexing.rs b/nac3core/src/codegen/types/ndarray/indexing.rs index 3e4e1362..8e15c903 100644 --- a/nac3core/src/codegen/types/ndarray/indexing.rs +++ b/nac3core/src/codegen/types/ndarray/indexing.rs @@ -35,25 +35,6 @@ pub struct NDIndexStructFields<'ctx> { } impl<'ctx> NDIndexType<'ctx> { - /// Checks whether `llvm_ty` represents a `ndindex` type, returning [Err] if it does not. - pub fn is_representable( - llvm_ty: PointerType<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - let ctx = llvm_ty.get_context(); - - let llvm_ty = llvm_ty.get_element_type(); - let AnyTypeEnum::StructType(llvm_ty) = llvm_ty else { - return Err(format!( - "Expected struct type for `ContiguousNDArray` type, got {llvm_ty}" - )); - }; - - let fields = NDIndexStructFields::new(ctx, llvm_usize); - - check_struct_type_matches_fields(fields, llvm_ty, "NDIndex", &[]) - } - #[must_use] fn fields( ctx: impl AsContextRef<'ctx>, @@ -96,7 +77,7 @@ impl<'ctx> NDIndexType<'ctx> { #[must_use] pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { - debug_assert!(Self::is_representable(ptr_ty, llvm_usize).is_ok()); + debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); Self { ty: ptr_ty, llvm_usize } } @@ -180,24 +161,30 @@ impl<'ctx> ProxyType<'ctx> for NDIndexType<'ctx> { type Base = PointerType<'ctx>; type Value = NDIndexValue<'ctx>; - fn is_type( - generator: &G, - ctx: &'ctx Context, + fn is_representable( llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, ) -> Result<(), String> { if let BasicTypeEnum::PointerType(ty) = llvm_ty.as_basic_type_enum() { - >::is_representable(generator, ctx, ty) + Self::has_same_repr(ty, llvm_usize) } else { Err(format!("Expected pointer type, got {llvm_ty:?}")) } } - fn is_representable( - generator: &G, - ctx: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String> { - Self::is_representable(llvm_ty, generator.get_size_type(ctx)) + fn has_same_repr(ty: Self::Base, llvm_usize: IntType<'ctx>) -> Result<(), String> { + let ctx = ty.get_context(); + + let llvm_ty = ty.get_element_type(); + let AnyTypeEnum::StructType(llvm_ty) = llvm_ty else { + return Err(format!( + "Expected struct type for `ContiguousNDArray` type, got {llvm_ty}" + )); + }; + + let fields = NDIndexStructFields::new(ctx, llvm_usize); + + check_struct_type_matches_fields(fields, llvm_ty, "NDIndex", &[]) } fn alloca_type(&self) -> impl BasicType<'ctx> { diff --git a/nac3core/src/codegen/types/ndarray/mod.rs b/nac3core/src/codegen/types/ndarray/mod.rs index fe73307d..1743fe2b 100644 --- a/nac3core/src/codegen/types/ndarray/mod.rs +++ b/nac3core/src/codegen/types/ndarray/mod.rs @@ -62,26 +62,6 @@ pub struct NDArrayStructFields<'ctx> { } impl<'ctx> NDArrayType<'ctx> { - /// Checks whether `llvm_ty` represents a `ndarray` type, returning [Err] if it does not. - pub fn is_representable( - llvm_ty: PointerType<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - let ctx = llvm_ty.get_context(); - - let llvm_ndarray_ty = llvm_ty.get_element_type(); - let AnyTypeEnum::StructType(llvm_ndarray_ty) = llvm_ndarray_ty else { - return Err(format!("Expected struct type for `NDArray` type, got {llvm_ndarray_ty}")); - }; - - check_struct_type_matches_fields( - Self::fields(ctx, llvm_usize), - llvm_ndarray_ty, - "NDArray", - &[], - ) - } - /// Returns an instance of [`StructFields`] containing all field accessors for this type. #[must_use] fn fields( @@ -211,7 +191,7 @@ impl<'ctx> NDArrayType<'ctx> { ndims: u64, llvm_usize: IntType<'ctx>, ) -> Self { - debug_assert!(Self::is_representable(ptr_ty, llvm_usize).is_ok()); + debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); NDArrayType { ty: ptr_ty, dtype, ndims, llvm_usize } } @@ -450,24 +430,31 @@ impl<'ctx> ProxyType<'ctx> for NDArrayType<'ctx> { type Base = PointerType<'ctx>; type Value = NDArrayValue<'ctx>; - fn is_type( - generator: &G, - ctx: &'ctx Context, + fn is_representable( llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, ) -> Result<(), String> { if let BasicTypeEnum::PointerType(ty) = llvm_ty.as_basic_type_enum() { - >::is_representable(generator, ctx, ty) + Self::has_same_repr(ty, llvm_usize) } else { Err(format!("Expected pointer type, got {llvm_ty:?}")) } } - fn is_representable( - generator: &G, - ctx: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String> { - Self::is_representable(llvm_ty, generator.get_size_type(ctx)) + fn has_same_repr(ty: Self::Base, llvm_usize: IntType<'ctx>) -> Result<(), String> { + let ctx = ty.get_context(); + + let llvm_ndarray_ty = ty.get_element_type(); + let AnyTypeEnum::StructType(llvm_ndarray_ty) = llvm_ndarray_ty else { + return Err(format!("Expected struct type for `NDArray` type, got {llvm_ndarray_ty}")); + }; + + check_struct_type_matches_fields( + Self::fields(ctx, llvm_usize), + llvm_ndarray_ty, + "NDArray", + &[], + ) } fn alloca_type(&self) -> impl BasicType<'ctx> { diff --git a/nac3core/src/codegen/types/ndarray/nditer.rs b/nac3core/src/codegen/types/ndarray/nditer.rs index 45b6bb0a..6246eef2 100644 --- a/nac3core/src/codegen/types/ndarray/nditer.rs +++ b/nac3core/src/codegen/types/ndarray/nditer.rs @@ -44,26 +44,6 @@ pub struct NDIterStructFields<'ctx> { } impl<'ctx> NDIterType<'ctx> { - /// Checks whether `llvm_ty` represents a `nditer` type, returning [Err] if it does not. - pub fn is_representable( - llvm_ty: PointerType<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - let ctx = llvm_ty.get_context(); - - let llvm_ty = llvm_ty.get_element_type(); - let AnyTypeEnum::StructType(llvm_ndarray_ty) = llvm_ty else { - return Err(format!("Expected struct type for `NDIter` type, got {llvm_ty}")); - }; - - check_struct_type_matches_fields( - Self::fields(ctx, llvm_usize), - llvm_ndarray_ty, - "NDIter", - &[], - ) - } - /// Returns an instance of [`StructFields`] containing all field accessors for this type. #[must_use] fn fields(ctx: impl AsContextRef<'ctx>, llvm_usize: IntType<'ctx>) -> NDIterStructFields<'ctx> { @@ -110,7 +90,7 @@ impl<'ctx> NDIterType<'ctx> { /// Creates an [`NDIterType`] from a [`PointerType`] representing an `NDIter`. #[must_use] pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { - debug_assert!(Self::is_representable(ptr_ty, llvm_usize).is_ok()); + debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); Self { ty: ptr_ty, llvm_usize } } @@ -208,24 +188,31 @@ impl<'ctx> ProxyType<'ctx> for NDIterType<'ctx> { type Base = PointerType<'ctx>; type Value = NDIterValue<'ctx>; - fn is_type( - generator: &G, - ctx: &'ctx Context, + fn is_representable( llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, ) -> Result<(), String> { if let BasicTypeEnum::PointerType(ty) = llvm_ty.as_basic_type_enum() { - >::is_representable(generator, ctx, ty) + Self::has_same_repr(ty, llvm_usize) } else { Err(format!("Expected pointer type, got {llvm_ty:?}")) } } - fn is_representable( - generator: &G, - ctx: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String> { - Self::is_representable(llvm_ty, generator.get_size_type(ctx)) + fn has_same_repr(ty: Self::Base, llvm_usize: IntType<'ctx>) -> Result<(), String> { + let ctx = ty.get_context(); + + let llvm_ty = ty.get_element_type(); + let AnyTypeEnum::StructType(llvm_ndarray_ty) = llvm_ty else { + return Err(format!("Expected struct type for `NDIter` type, got {llvm_ty}")); + }; + + check_struct_type_matches_fields( + Self::fields(ctx, llvm_usize), + llvm_ndarray_ty, + "NDIter", + &[], + ) } fn alloca_type(&self) -> impl BasicType<'ctx> { diff --git a/nac3core/src/codegen/types/range.rs b/nac3core/src/codegen/types/range.rs index b92d7658..158152bf 100644 --- a/nac3core/src/codegen/types/range.rs +++ b/nac3core/src/codegen/types/range.rs @@ -17,12 +17,125 @@ use crate::{ #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct RangeType<'ctx> { ty: PointerType<'ctx>, + llvm_usize: IntType<'ctx>, } impl<'ctx> RangeType<'ctx> { - /// Checks whether `llvm_ty` represents a `range` type, returning [Err] if it does not. - pub fn is_representable(llvm_ty: PointerType<'ctx>) -> Result<(), String> { - let llvm_range_ty = llvm_ty.get_element_type(); + /// Creates an LLVM type corresponding to the expected structure of a `Range`. + #[must_use] + fn llvm_type(ctx: &'ctx Context) -> PointerType<'ctx> { + // typedef int32_t Range[3]; + let llvm_i32 = ctx.i32_type(); + llvm_i32.array_type(3).ptr_type(AddressSpace::default()) + } + + fn new_impl(ctx: &'ctx Context, llvm_usize: IntType<'ctx>) -> Self { + let llvm_range = Self::llvm_type(ctx); + + RangeType { ty: llvm_range, llvm_usize } + } + + /// Creates an instance of [`RangeType`]. + #[must_use] + pub fn new(ctx: &CodeGenContext<'ctx, '_>) -> Self { + Self::new_impl(ctx.ctx, ctx.get_size_type()) + } + + /// Creates an instance of [`RangeType`]. + #[must_use] + pub fn new_with_generator( + generator: &G, + ctx: &'ctx Context, + ) -> Self { + Self::new_impl(ctx, generator.get_size_type(ctx)) + } + + /// Creates an [`RangeType`] from a [unifier type][Type]. + #[must_use] + pub fn from_unifier_type(ctx: &mut CodeGenContext<'ctx, '_>, ty: Type) -> Self { + // Check unifier type + assert!( + matches!(&*ctx.unifier.get_ty_immutable(ty), TypeEnum::TObj { obj_id, .. } if *obj_id == ctx.primitives.range.obj_id(&ctx.unifier).unwrap()) + ); + + Self::new(ctx) + } + + /// Creates an [`RangeType`] from a [`PointerType`]. + #[must_use] + pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); + + RangeType { ty: ptr_ty, llvm_usize } + } + + /// Returns the type of all fields of this `range` type. + #[must_use] + pub fn value_type(&self) -> IntType<'ctx> { + self.as_base_type().get_element_type().into_array_type().get_element_type().into_int_type() + } + + /// Allocates an instance of [`RangeValue`] as if by calling `alloca` on the base type. + /// + /// See [`ProxyType::raw_alloca`]. + #[must_use] + pub fn alloca( + &self, + ctx: &mut CodeGenContext<'ctx, '_>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value( + self.raw_alloca(ctx, name), + self.llvm_usize, + name, + ) + } + + /// Allocates an instance of [`RangeValue`] as if by calling `alloca` on the base type. + /// + /// See [`ProxyType::raw_alloca_var`]. + #[must_use] + pub fn alloca_var( + &self, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value( + self.raw_alloca_var(generator, ctx, name), + self.llvm_usize, + name, + ) + } + + /// Converts an existing value into a [`RangeValue`]. + #[must_use] + pub fn map_value( + &self, + value: <>::Value as ProxyValue<'ctx>>::Base, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value(value, self.llvm_usize, name) + } +} + +impl<'ctx> ProxyType<'ctx> for RangeType<'ctx> { + type Base = PointerType<'ctx>; + type Value = RangeValue<'ctx>; + + fn is_representable( + llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, + ) -> Result<(), String> { + if let BasicTypeEnum::PointerType(ty) = llvm_ty.as_basic_type_enum() { + Self::has_same_repr(ty, llvm_usize) + } else { + Err(format!("Expected pointer type, got {llvm_ty:?}")) + } + } + + fn has_same_repr(ty: Self::Base, _: IntType<'ctx>) -> Result<(), String> { + let llvm_range_ty = ty.get_element_type(); let AnyTypeEnum::ArrayType(llvm_range_ty) = llvm_range_ty else { return Err(format!("Expected array type for `range` type, got {llvm_range_ty}")); }; @@ -49,120 +162,6 @@ impl<'ctx> RangeType<'ctx> { Ok(()) } - /// Creates an LLVM type corresponding to the expected structure of a `Range`. - #[must_use] - fn llvm_type(ctx: &'ctx Context) -> PointerType<'ctx> { - // typedef int32_t Range[3]; - let llvm_i32 = ctx.i32_type(); - llvm_i32.array_type(3).ptr_type(AddressSpace::default()) - } - - fn new_impl(ctx: &'ctx Context) -> Self { - let llvm_range = Self::llvm_type(ctx); - - RangeType { ty: llvm_range } - } - - /// Creates an instance of [`RangeType`]. - #[must_use] - pub fn new(ctx: &CodeGenContext<'ctx, '_>) -> Self { - RangeType::new_impl(ctx.ctx) - } - - /// Creates an instance of [`RangeType`]. - #[must_use] - pub fn new_with_generator(_: &G, ctx: &'ctx Context) -> Self { - Self::new_impl(ctx) - } - - /// Creates an [`RangeType`] from a [unifier type][Type]. - #[must_use] - pub fn from_unifier_type(ctx: &mut CodeGenContext<'ctx, '_>, ty: Type) -> Self { - // Check unifier type - assert!( - matches!(&*ctx.unifier.get_ty_immutable(ty), TypeEnum::TObj { obj_id, .. } if *obj_id == ctx.primitives.range.obj_id(&ctx.unifier).unwrap()) - ); - - Self::new(ctx) - } - - /// Creates an [`RangeType`] from a [`PointerType`]. - #[must_use] - pub fn from_type(ptr_ty: PointerType<'ctx>) -> Self { - debug_assert!(Self::is_representable(ptr_ty).is_ok()); - - RangeType { ty: ptr_ty } - } - - /// Returns the type of all fields of this `range` type. - #[must_use] - pub fn value_type(&self) -> IntType<'ctx> { - self.as_base_type().get_element_type().into_array_type().get_element_type().into_int_type() - } - - /// Allocates an instance of [`RangeValue`] as if by calling `alloca` on the base type. - /// - /// See [`ProxyType::raw_alloca`]. - #[must_use] - pub fn alloca( - &self, - ctx: &mut CodeGenContext<'ctx, '_>, - name: Option<&'ctx str>, - ) -> >::Value { - >::Value::from_pointer_value(self.raw_alloca(ctx, name), name) - } - - /// Allocates an instance of [`RangeValue`] as if by calling `alloca` on the base type. - /// - /// See [`ProxyType::raw_alloca_var`]. - #[must_use] - pub fn alloca_var( - &self, - generator: &mut G, - ctx: &mut CodeGenContext<'ctx, '_>, - name: Option<&'ctx str>, - ) -> >::Value { - >::Value::from_pointer_value( - self.raw_alloca_var(generator, ctx, name), - name, - ) - } - - /// Converts an existing value into a [`RangeValue`]. - #[must_use] - pub fn map_value( - &self, - value: <>::Value as ProxyValue<'ctx>>::Base, - name: Option<&'ctx str>, - ) -> >::Value { - >::Value::from_pointer_value(value, name) - } -} - -impl<'ctx> ProxyType<'ctx> for RangeType<'ctx> { - type Base = PointerType<'ctx>; - type Value = RangeValue<'ctx>; - - fn is_type( - generator: &G, - ctx: &'ctx Context, - llvm_ty: impl BasicType<'ctx>, - ) -> Result<(), String> { - if let BasicTypeEnum::PointerType(ty) = llvm_ty.as_basic_type_enum() { - >::is_representable(generator, ctx, ty) - } else { - Err(format!("Expected pointer type, got {llvm_ty:?}")) - } - } - - fn is_representable( - _: &G, - _: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String> { - Self::is_representable(llvm_ty) - } - fn alloca_type(&self) -> impl BasicType<'ctx> { self.as_base_type().get_element_type().into_struct_type() } diff --git a/nac3core/src/codegen/types/tuple.rs b/nac3core/src/codegen/types/tuple.rs index 5c736528..d05b7f26 100644 --- a/nac3core/src/codegen/types/tuple.rs +++ b/nac3core/src/codegen/types/tuple.rs @@ -21,11 +21,6 @@ pub struct TupleType<'ctx> { } impl<'ctx> TupleType<'ctx> { - /// Checks whether `llvm_ty` represents any tuple type, returning [Err] if it does not. - pub fn is_representable(_value: StructType<'ctx>) -> Result<(), String> { - Ok(()) - } - /// Creates an LLVM type corresponding to the expected structure of a tuple. #[must_use] fn llvm_type(ctx: &'ctx Context, tys: &[BasicTypeEnum<'ctx>]) -> StructType<'ctx> { @@ -83,7 +78,7 @@ impl<'ctx> TupleType<'ctx> { /// Creates an [`TupleType`] from a [`StructType`]. #[must_use] pub fn from_type(struct_ty: StructType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { - debug_assert!(Self::is_representable(struct_ty).is_ok()); + debug_assert!(Self::has_same_repr(struct_ty, llvm_usize).is_ok()); TupleType { ty: struct_ty, llvm_usize } } @@ -165,24 +160,19 @@ impl<'ctx> ProxyType<'ctx> for TupleType<'ctx> { type Base = StructType<'ctx>; type Value = TupleValue<'ctx>; - fn is_type( - generator: &G, - ctx: &'ctx Context, + fn is_representable( llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, ) -> Result<(), String> { if let BasicTypeEnum::StructType(ty) = llvm_ty.as_basic_type_enum() { - >::is_representable(generator, ctx, ty) + Self::has_same_repr(ty, llvm_usize) } else { Err(format!("Expected struct type, got {llvm_ty:?}")) } } - fn is_representable( - _generator: &G, - _ctx: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String> { - Self::is_representable(llvm_ty) + fn has_same_repr(_: Self::Base, _: IntType<'ctx>) -> Result<(), String> { + Ok(()) } fn alloca_type(&self) -> impl BasicType<'ctx> { diff --git a/nac3core/src/codegen/types/utils/slice.rs b/nac3core/src/codegen/types/utils/slice.rs index 0ef4d1b0..b7fafefa 100644 --- a/nac3core/src/codegen/types/utils/slice.rs +++ b/nac3core/src/codegen/types/utils/slice.rs @@ -61,50 +61,6 @@ impl<'ctx> SliceFields<'ctx> { } impl<'ctx> SliceType<'ctx> { - /// Checks whether `llvm_ty` represents a `slice` type, returning [Err] if it does not. - pub fn is_representable( - llvm_ty: PointerType<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - let ctx = llvm_ty.get_context(); - - let fields = SliceFields::new(ctx, llvm_usize); - - let llvm_ty = llvm_ty.get_element_type(); - let AnyTypeEnum::StructType(llvm_ty) = llvm_ty else { - return Err(format!("Expected struct type for `Slice` type, got {llvm_ty}")); - }; - - check_struct_type_matches_fields( - fields, - llvm_ty, - "Slice", - &[ - (fields.start.name(), &|ty| { - if ty.is_int_type() { - Ok(()) - } else { - Err(format!("Expected int type for `Slice.start`, got {ty}")) - } - }), - (fields.stop.name(), &|ty| { - if ty.is_int_type() { - Ok(()) - } else { - Err(format!("Expected int type for `Slice.stop`, got {ty}")) - } - }), - (fields.step.name(), &|ty| { - if ty.is_int_type() { - Ok(()) - } else { - Err(format!("Expected int type for `Slice.step`, got {ty}")) - } - }), - ], - ) - } - // TODO: Move this into e.g. StructProxyType #[must_use] pub fn get_fields(&self) -> SliceFields<'ctx> { @@ -156,7 +112,7 @@ impl<'ctx> SliceType<'ctx> { int_ty: IntType<'ctx>, llvm_usize: IntType<'ctx>, ) -> Self { - debug_assert!(Self::is_representable(ptr_ty, int_ty).is_ok()); + debug_assert!(Self::has_same_repr(ptr_ty, int_ty).is_ok()); Self { ty: ptr_ty, int_ty, llvm_usize } } @@ -221,24 +177,55 @@ impl<'ctx> ProxyType<'ctx> for SliceType<'ctx> { type Base = PointerType<'ctx>; type Value = SliceValue<'ctx>; - fn is_type( - generator: &G, - ctx: &'ctx Context, + fn is_representable( llvm_ty: impl BasicType<'ctx>, + llvm_usize: IntType<'ctx>, ) -> Result<(), String> { if let BasicTypeEnum::PointerType(ty) = llvm_ty.as_basic_type_enum() { - >::is_representable(generator, ctx, ty) + Self::has_same_repr(ty, llvm_usize) } else { Err(format!("Expected pointer type, got {llvm_ty:?}")) } } - fn is_representable( - generator: &G, - ctx: &'ctx Context, - llvm_ty: Self::Base, - ) -> Result<(), String> { - Self::is_representable(llvm_ty, generator.get_size_type(ctx)) + fn has_same_repr(ty: Self::Base, llvm_usize: IntType<'ctx>) -> Result<(), String> { + let ctx = ty.get_context(); + + let fields = SliceFields::new(ctx, llvm_usize); + + let llvm_ty = ty.get_element_type(); + let AnyTypeEnum::StructType(llvm_ty) = llvm_ty else { + return Err(format!("Expected struct type for `Slice` type, got {llvm_ty}")); + }; + + check_struct_type_matches_fields( + fields, + llvm_ty, + "Slice", + &[ + (fields.start.name(), &|ty| { + if ty.is_int_type() { + Ok(()) + } else { + Err(format!("Expected int type for `Slice.start`, got {ty}")) + } + }), + (fields.stop.name(), &|ty| { + if ty.is_int_type() { + Ok(()) + } else { + Err(format!("Expected int type for `Slice.stop`, got {ty}")) + } + }), + (fields.step.name(), &|ty| { + if ty.is_int_type() { + Ok(()) + } else { + Err(format!("Expected int type for `Slice.step`, got {ty}")) + } + }), + ], + ) } fn alloca_type(&self) -> impl BasicType<'ctx> { diff --git a/nac3core/src/codegen/values/list.rs b/nac3core/src/codegen/values/list.rs index 4ba5b6af..075f7f64 100644 --- a/nac3core/src/codegen/values/list.rs +++ b/nac3core/src/codegen/values/list.rs @@ -21,15 +21,6 @@ pub struct ListValue<'ctx> { } impl<'ctx> ListValue<'ctx> { - /// Checks whether `value` is an instance of `list`, returning [Err] if `value` is not an - /// instance. - pub fn is_representable( - value: PointerValue<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - ListType::is_representable(value.get_type(), llvm_usize) - } - /// Creates an [`ListValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -37,7 +28,7 @@ impl<'ctx> ListValue<'ctx> { llvm_usize: IntType<'ctx>, name: Option<&'ctx str>, ) -> Self { - debug_assert!(Self::is_representable(ptr, llvm_usize).is_ok()); + debug_assert!(Self::is_instance(ptr, llvm_usize).is_ok()); ListValue { value: ptr, llvm_usize, name } } diff --git a/nac3core/src/codegen/values/mod.rs b/nac3core/src/codegen/values/mod.rs index c789fe0f..dae10f31 100644 --- a/nac3core/src/codegen/values/mod.rs +++ b/nac3core/src/codegen/values/mod.rs @@ -1,7 +1,6 @@ -use inkwell::{context::Context, values::BasicValue}; +use inkwell::{types::IntType, values::BasicValue}; use super::types::ProxyType; -use crate::codegen::CodeGenerator; pub use array::*; pub use list::*; pub use range::*; @@ -24,21 +23,8 @@ pub trait ProxyValue<'ctx>: Into { type Type: ProxyType<'ctx, Value = Self>; /// Checks whether `value` can be represented by this [`ProxyValue`]. - fn is_instance( - generator: &G, - ctx: &'ctx Context, - value: impl BasicValue<'ctx>, - ) -> Result<(), String> { - Self::Type::is_type(generator, ctx, value.as_basic_value_enum().get_type()) - } - - /// Checks whether `value` can be represented by this [`ProxyValue`]. - fn is_representable( - generator: &G, - ctx: &'ctx Context, - value: Self::Base, - ) -> Result<(), String> { - Self::is_instance(generator, ctx, value.as_basic_value_enum()) + fn is_instance(value: impl BasicValue<'ctx>, llvm_usize: IntType<'ctx>) -> Result<(), String> { + Self::Type::is_representable(value.as_basic_value_enum().get_type(), llvm_usize) } /// Returns the [type][ProxyType] of this value. diff --git a/nac3core/src/codegen/values/ndarray/broadcast.rs b/nac3core/src/codegen/values/ndarray/broadcast.rs index b5182a2b..acbd2997 100644 --- a/nac3core/src/codegen/values/ndarray/broadcast.rs +++ b/nac3core/src/codegen/values/ndarray/broadcast.rs @@ -26,15 +26,6 @@ pub struct ShapeEntryValue<'ctx> { } impl<'ctx> ShapeEntryValue<'ctx> { - /// Checks whether `value` is an instance of `ShapeEntry`, returning [Err] if `value` is - /// not an instance. - pub fn is_representable( - value: PointerValue<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - >::Type::is_representable(value.get_type(), llvm_usize) - } - /// Creates an [`ShapeEntryValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -42,7 +33,7 @@ impl<'ctx> ShapeEntryValue<'ctx> { llvm_usize: IntType<'ctx>, name: Option<&'ctx str>, ) -> Self { - debug_assert!(Self::is_representable(ptr, llvm_usize).is_ok()); + debug_assert!(Self::is_instance(ptr, llvm_usize).is_ok()); Self { value: ptr, llvm_usize, name } } diff --git a/nac3core/src/codegen/values/ndarray/contiguous.rs b/nac3core/src/codegen/values/ndarray/contiguous.rs index 0fbb85f0..65e80258 100644 --- a/nac3core/src/codegen/values/ndarray/contiguous.rs +++ b/nac3core/src/codegen/values/ndarray/contiguous.rs @@ -23,15 +23,6 @@ pub struct ContiguousNDArrayValue<'ctx> { } impl<'ctx> ContiguousNDArrayValue<'ctx> { - /// Checks whether `value` is an instance of `ContiguousNDArray`, returning [Err] if `value` is - /// not an instance. - pub fn is_representable( - value: PointerValue<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - >::Type::is_representable(value.get_type(), llvm_usize) - } - /// Creates an [`ContiguousNDArrayValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -40,7 +31,7 @@ impl<'ctx> ContiguousNDArrayValue<'ctx> { llvm_usize: IntType<'ctx>, name: Option<&'ctx str>, ) -> Self { - debug_assert!(Self::is_representable(ptr, llvm_usize).is_ok()); + debug_assert!(Self::is_instance(ptr, llvm_usize).is_ok()); Self { value: ptr, item: dtype, llvm_usize, name } } diff --git a/nac3core/src/codegen/values/ndarray/indexing.rs b/nac3core/src/codegen/values/ndarray/indexing.rs index 60c9c3b7..3b7b8f10 100644 --- a/nac3core/src/codegen/values/ndarray/indexing.rs +++ b/nac3core/src/codegen/values/ndarray/indexing.rs @@ -30,15 +30,6 @@ pub struct NDIndexValue<'ctx> { } impl<'ctx> NDIndexValue<'ctx> { - /// Checks whether `value` is an instance of `ndindex`, returning [Err] if `value` is not an - /// instance. - pub fn is_representable( - value: PointerValue<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - >::Type::is_representable(value.get_type(), llvm_usize) - } - /// Creates an [`NDIndexValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -46,7 +37,7 @@ impl<'ctx> NDIndexValue<'ctx> { llvm_usize: IntType<'ctx>, name: Option<&'ctx str>, ) -> Self { - debug_assert!(Self::is_representable(ptr, llvm_usize).is_ok()); + debug_assert!(Self::is_instance(ptr, llvm_usize).is_ok()); Self { value: ptr, llvm_usize, name } } diff --git a/nac3core/src/codegen/values/ndarray/mod.rs b/nac3core/src/codegen/values/ndarray/mod.rs index 1bf5db31..cba35ad2 100644 --- a/nac3core/src/codegen/values/ndarray/mod.rs +++ b/nac3core/src/codegen/values/ndarray/mod.rs @@ -49,15 +49,6 @@ pub struct NDArrayValue<'ctx> { } impl<'ctx> NDArrayValue<'ctx> { - /// Checks whether `value` is an instance of `NDArray`, returning [Err] if `value` is not an - /// instance. - pub fn is_representable( - value: PointerValue<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - NDArrayType::is_representable(value.get_type(), llvm_usize) - } - /// Creates an [`NDArrayValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -67,7 +58,7 @@ impl<'ctx> NDArrayValue<'ctx> { llvm_usize: IntType<'ctx>, name: Option<&'ctx str>, ) -> Self { - debug_assert!(Self::is_representable(ptr, llvm_usize).is_ok()); + debug_assert!(Self::is_instance(ptr, llvm_usize).is_ok()); NDArrayValue { value: ptr, dtype, ndims, llvm_usize, name } } diff --git a/nac3core/src/codegen/values/ndarray/nditer.rs b/nac3core/src/codegen/values/ndarray/nditer.rs index 86f370e5..5479b929 100644 --- a/nac3core/src/codegen/values/ndarray/nditer.rs +++ b/nac3core/src/codegen/values/ndarray/nditer.rs @@ -23,15 +23,6 @@ pub struct NDIterValue<'ctx> { } impl<'ctx> NDIterValue<'ctx> { - /// Checks whether `value` is an instance of `NDArray`, returning [Err] if `value` is not an - /// instance. - pub fn is_representable( - value: PointerValue<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - ::Type::is_representable(value.get_type(), llvm_usize) - } - /// Creates an [`NDArrayValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -41,7 +32,7 @@ impl<'ctx> NDIterValue<'ctx> { llvm_usize: IntType<'ctx>, name: Option<&'ctx str>, ) -> Self { - debug_assert!(Self::is_representable(ptr, llvm_usize).is_ok()); + debug_assert!(Self::is_instance(ptr, llvm_usize).is_ok()); Self { value: ptr, parent, indices, llvm_usize, name } } diff --git a/nac3core/src/codegen/values/range.rs b/nac3core/src/codegen/values/range.rs index 7e9976a6..b1a5806a 100644 --- a/nac3core/src/codegen/values/range.rs +++ b/nac3core/src/codegen/values/range.rs @@ -1,4 +1,7 @@ -use inkwell::values::{BasicValueEnum, IntValue, PointerValue}; +use inkwell::{ + types::IntType, + values::{BasicValueEnum, IntValue, PointerValue}, +}; use super::ProxyValue; use crate::codegen::{types::RangeType, CodeGenContext}; @@ -7,21 +10,21 @@ use crate::codegen::{types::RangeType, CodeGenContext}; #[derive(Copy, Clone)] pub struct RangeValue<'ctx> { value: PointerValue<'ctx>, + llvm_usize: IntType<'ctx>, name: Option<&'ctx str>, } impl<'ctx> RangeValue<'ctx> { - /// Checks whether `value` is an instance of `range`, returning [Err] if `value` is not an instance. - pub fn is_representable(value: PointerValue<'ctx>) -> Result<(), String> { - RangeType::is_representable(value.get_type()) - } - /// Creates an [`RangeValue`] from a [`PointerValue`]. #[must_use] - pub fn from_pointer_value(ptr: PointerValue<'ctx>, name: Option<&'ctx str>) -> Self { - debug_assert!(Self::is_representable(ptr).is_ok()); + pub fn from_pointer_value( + ptr: PointerValue<'ctx>, + llvm_usize: IntType<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + debug_assert!(Self::is_instance(ptr, llvm_usize).is_ok()); - RangeValue { value: ptr, name } + RangeValue { value: ptr, llvm_usize, name } } fn ptr_to_start(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> { @@ -138,7 +141,7 @@ impl<'ctx> ProxyValue<'ctx> for RangeValue<'ctx> { type Type = RangeType<'ctx>; fn get_type(&self) -> Self::Type { - RangeType::from_type(self.value.get_type()) + RangeType::from_type(self.value.get_type(), self.llvm_usize) } fn as_base_value(&self) -> Self::Base { diff --git a/nac3core/src/codegen/values/tuple.rs b/nac3core/src/codegen/values/tuple.rs index 5167e479..4558f18c 100644 --- a/nac3core/src/codegen/values/tuple.rs +++ b/nac3core/src/codegen/values/tuple.rs @@ -14,15 +14,6 @@ pub struct TupleValue<'ctx> { } impl<'ctx> TupleValue<'ctx> { - /// Checks whether `value` is an instance of `tuple`, returning [Err] if `value` is not an - /// instance. - pub fn is_representable( - value: StructValue<'ctx>, - _llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - TupleType::is_representable(value.get_type()) - } - /// Creates an [`TupleValue`] from a [`StructValue`]. #[must_use] pub fn from_struct_value( @@ -30,7 +21,7 @@ impl<'ctx> TupleValue<'ctx> { llvm_usize: IntType<'ctx>, name: Option<&'ctx str>, ) -> Self { - debug_assert!(Self::is_representable(value, llvm_usize).is_ok()); + debug_assert!(Self::is_instance(value, llvm_usize).is_ok()); Self { value, llvm_usize, name } } diff --git a/nac3core/src/codegen/values/utils/slice.rs b/nac3core/src/codegen/values/utils/slice.rs index dffe6cef..df9e4de5 100644 --- a/nac3core/src/codegen/values/utils/slice.rs +++ b/nac3core/src/codegen/values/utils/slice.rs @@ -24,15 +24,6 @@ pub struct SliceValue<'ctx> { } impl<'ctx> SliceValue<'ctx> { - /// Checks whether `value` is an instance of `ContiguousNDArray`, returning [Err] if `value` is - /// not an instance. - pub fn is_representable( - value: PointerValue<'ctx>, - llvm_usize: IntType<'ctx>, - ) -> Result<(), String> { - >::Type::is_representable(value.get_type(), llvm_usize) - } - /// Creates an [`SliceValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -41,7 +32,7 @@ impl<'ctx> SliceValue<'ctx> { llvm_usize: IntType<'ctx>, name: Option<&'ctx str>, ) -> Self { - debug_assert!(Self::is_representable(ptr, llvm_usize).is_ok()); + debug_assert!(Self::is_instance(ptr, llvm_usize).is_ok()); Self { value: ptr, int_ty, llvm_usize, name } } diff --git a/nac3core/src/toplevel/builtins.rs b/nac3core/src/toplevel/builtins.rs index e06366c5..1c3b0854 100644 --- a/nac3core/src/toplevel/builtins.rs +++ b/nac3core/src/toplevel/builtins.rs @@ -17,10 +17,10 @@ use crate::{ builtin_fns, numpy::*, stmt::{exn_constructor, gen_if_callback}, - types::ndarray::NDArrayType, + types::{ndarray::NDArrayType, RangeType}, values::{ ndarray::{shape::parse_numpy_int_sequence, ScalarOrNDArray}, - ProxyValue, RangeValue, + ProxyValue, }, }, symbol_resolver::SymbolValue, @@ -577,7 +577,7 @@ impl<'a> BuiltinBuilder<'a> { let (zelf_ty, zelf) = obj.unwrap(); let zelf = zelf.to_basic_value_enum(ctx, generator, zelf_ty)?.into_pointer_value(); - let zelf = RangeValue::from_pointer_value(zelf, Some("range")); + let zelf = RangeType::new(ctx).map_value(zelf, Some("range")); let mut start = None; let mut stop = None;