Compare commits

..

12 Commits

Author SHA1 Message Date
David Mak 1cb9a90825 core: Implement elementwise binary operators
Including immediate variants of these operators.
2024-03-26 19:18:50 +08:00
David Mak 42c482f897 core/magic_methods: Add typeof_*op
Used to determine the expected type of the binary operator with
primitive operands.
2024-03-26 19:18:20 +08:00
David Mak 1a09ea126d core/toplevel/numpy: Split ndarray type var utilities 2024-03-26 19:18:18 +08:00
David Mak f0c8f88ce3 core: Implement calculations for broadcasting ndarrays 2024-03-26 17:36:52 +08:00
David Mak 0c3e353a11 core/type_inferencer: Allow both int32 and isize when indexing ndarray 2024-03-26 17:36:52 +08:00
David Mak 2f73c96e98 core/magic_methods: Allow unknown return types
These types can be later inferred by the type inferencer.
2024-03-26 17:36:51 +08:00
David Mak 0636398f3c core: Extract codegen portion of gen_binop_expr
This allows binops to be generated internally using LLVM values as
input. Required in a future change.
2024-03-26 17:36:51 +08:00
David Mak 2734a38635 core: Remove ArrayValue variants of accessors 2024-03-26 17:36:51 +08:00
David Mak 8de76510ed core: Use more typed slices in APIs 2024-03-26 17:36:51 +08:00
David Mak c90724c738 core/builtins: Fix len() on ndarrays 2024-03-26 17:36:51 +08:00
David Mak c9d21abb96 core: Fix index-based operations not returning i32 2024-03-25 14:53:35 +08:00
Sebastien Bourdeauducq 623fcf85af msys2: update 2024-03-25 14:45:36 +08:00
9 changed files with 846 additions and 316 deletions

View File

@ -1130,44 +1130,76 @@ pub fn gen_binop_expr_with_values<'ctx, G: CodeGenerator>(
Some("f_pow_i")
);
Ok(Some(res.into()))
} else if matches!(&*ctx.unifier.get_ty(ty1), TypeEnum::TObj { obj_id, .. } if obj_id == &PRIMITIVE_DEF_IDS.ndarray) && matches!(&*ctx.unifier.get_ty(ty2), TypeEnum::TObj { obj_id, .. } if obj_id == &PRIMITIVE_DEF_IDS.ndarray) {
} else if ty1.get_obj_id(&ctx.unifier) == PRIMITIVE_DEF_IDS.ndarray || ty2.get_obj_id(&ctx.unifier) == PRIMITIVE_DEF_IDS.ndarray {
let llvm_usize = generator.get_size_type(ctx.ctx);
let (ndarray_dtype1, _) = unpack_ndarray_var_tys(&mut ctx.unifier, ty1);
let (ndarray_dtype2, _) = unpack_ndarray_var_tys(&mut ctx.unifier, ty1);
assert!(ctx.unifier.unioned(ndarray_dtype1, ndarray_dtype2));
let is_ndarray1 = ty1.get_obj_id(&ctx.unifier) == PRIMITIVE_DEF_IDS.ndarray;
let is_ndarray2 = ty2.get_obj_id(&ctx.unifier) == PRIMITIVE_DEF_IDS.ndarray;
let left_val = NDArrayValue::from_ptr_val(
left_val.into_pointer_value(),
llvm_usize,
None
);
let right_val = NDArrayValue::from_ptr_val(
right_val.into_pointer_value(),
llvm_usize,
None
);
let res = numpy::ndarray_elementwise_binop_impl(
generator,
ctx,
ndarray_dtype1,
if is_aug_assign { Some(left_val) } else { None },
left_val,
right_val,
|generator, ctx, elem_ty, (lhs, rhs)| {
gen_binop_expr_with_values(
generator,
ctx,
(&Some(elem_ty), lhs),
op,
(&Some(elem_ty), rhs),
ctx.current_loc,
is_aug_assign,
)?.unwrap().to_basic_value_enum(ctx, generator, elem_ty)
},
)?;
if is_ndarray1 && is_ndarray2 {
let (ndarray_dtype1, _) = unpack_ndarray_var_tys(&mut ctx.unifier, ty1);
let (ndarray_dtype2, _) = unpack_ndarray_var_tys(&mut ctx.unifier, ty1);
Ok(Some(res.as_ptr_value().into()))
assert!(ctx.unifier.unioned(ndarray_dtype1, ndarray_dtype2));
let left_val = NDArrayValue::from_ptr_val(
left_val.into_pointer_value(),
llvm_usize,
None
);
let res = numpy::ndarray_elementwise_binop_impl(
generator,
ctx,
ndarray_dtype1,
if is_aug_assign { Some(left_val) } else { None },
(left_val.as_ptr_value().into(), false),
(right_val.into(), false),
|generator, ctx, elem_ty, (lhs, rhs)| {
gen_binop_expr_with_values(
generator,
ctx,
(&Some(elem_ty), lhs),
op,
(&Some(elem_ty), rhs),
ctx.current_loc,
is_aug_assign,
)?.unwrap().to_basic_value_enum(ctx, generator, elem_ty)
},
)?;
Ok(Some(res.as_ptr_value().into()))
} else {
let (ndarray_dtype, _) = unpack_ndarray_var_tys(
&mut ctx.unifier,
if is_ndarray1 { ty1 } else { ty2 },
);
let ndarray_val = NDArrayValue::from_ptr_val(
if is_ndarray1 { left_val } else { right_val }.into_pointer_value(),
llvm_usize,
None,
);
let res = numpy::ndarray_elementwise_binop_impl(
generator,
ctx,
ndarray_dtype,
if is_aug_assign { Some(ndarray_val) } else { None },
(left_val, !is_ndarray1),
(right_val, !is_ndarray2),
|generator, ctx, elem_ty, (lhs, rhs)| {
gen_binop_expr_with_values(
generator,
ctx,
(&Some(elem_ty), lhs),
op,
(&Some(elem_ty), rhs),
ctx.current_loc,
is_aug_assign,
)?.unwrap().to_basic_value_enum(ctx, generator, elem_ty)
},
)?;
Ok(Some(res.as_ptr_value().into()))
}
} else {
let left_ty_enum = ctx.unifier.get_ty_immutable(left_ty.unwrap());
let TypeEnum::TObj { fields, obj_id, .. } = left_ty_enum.as_ref() else {

View File

@ -346,39 +346,61 @@ fn ndarray_fill_indexed<'ctx, G, ValueFn>(
)
}
/// Generates the LLVM IR for populating the entire `NDArray` using a lambda with the same-indexed
/// element from two other `NDArray` as its input.
/// Generates the LLVM IR for populating the entire `NDArray` from two `ndarray` or scalar value
/// with broadcast-compatible shapes.
fn ndarray_broadcast_fill<'ctx, G, ValueFn>(
generator: &mut G,
ctx: &mut CodeGenContext<'ctx, '_>,
elem_ty: Type,
res: NDArrayValue<'ctx>,
lhs: NDArrayValue<'ctx>,
rhs: NDArrayValue<'ctx>,
lhs: (BasicValueEnum<'ctx>, bool),
rhs: (BasicValueEnum<'ctx>, bool),
value_fn: ValueFn,
) -> Result<NDArrayValue<'ctx>, String>
where
G: CodeGenerator + ?Sized,
ValueFn: Fn(&mut G, &mut CodeGenContext<'ctx, '_>, Type, (BasicValueEnum<'ctx>, BasicValueEnum<'ctx>)) -> Result<BasicValueEnum<'ctx>, String>,
{
let llvm_usize = generator.get_size_type(ctx.ctx);
let (lhs_val, lhs_scalar) = lhs;
let (rhs_val, rhs_scalar) = rhs;
assert!(!(lhs_scalar && rhs_scalar),
"One of the operands must be a ndarray instance: `{}`, `{}`",
lhs_val.get_type(),
rhs_val.get_type());
ndarray_fill_indexed(
generator,
ctx,
res,
|generator, ctx, idx| {
let lhs_idx = call_ndarray_calc_broadcast_index(generator, ctx, lhs, &idx);
let rhs_idx = call_ndarray_calc_broadcast_index(generator, ctx, rhs, &idx);
let lhs_elem = if lhs_scalar {
lhs_val
} else {
let lhs = NDArrayValue::from_ptr_val(lhs_val.into_pointer_value(), llvm_usize, None);
let lhs_idx = call_ndarray_calc_broadcast_index(generator, ctx, lhs, &idx);
let elem = unsafe {
(
lhs.data().get_unchecked(ctx, generator, lhs_idx, None),
rhs.data().get_unchecked(ctx, generator, rhs_idx, None),
)
unsafe {
lhs.data().get_unchecked(ctx, generator, lhs_idx, None)
}
};
debug_assert_eq!(elem.0.get_type(), elem.1.get_type());
let rhs_elem = if rhs_scalar {
rhs_val
} else {
let rhs = NDArrayValue::from_ptr_val(rhs_val.into_pointer_value(), llvm_usize, None);
let rhs_idx = call_ndarray_calc_broadcast_index(generator, ctx, rhs, &idx);
unsafe {
rhs.data().get_unchecked(ctx, generator, rhs_idx, None)
}
};
value_fn(generator, ctx, elem_ty, elem)
debug_assert_eq!(lhs_elem.get_type(), rhs_elem.get_type());
value_fn(generator, ctx, elem_ty, (lhs_elem, rhs_elem))
},
)?;
@ -620,41 +642,91 @@ fn ndarray_copy_impl<'ctx, G: CodeGenerator + ?Sized>(
Ok(ndarray)
}
/// LLVM-typed implementation for computing elementwise binary operations.
/// LLVM-typed implementation for computing elementwise binary operations on two input operands.
///
/// If the operand is a `ndarray`, the broadcast index corresponding to each element in the output
/// is computed, the element accessed and used as an operand of the `value_fn` arguments tuple.
/// Otherwise, the operand is treated as a scalar value, and is used as an operand of the
/// `value_fn` arguments tuple for all output elements.
///
/// The second element of the tuple indicates whether to treat the operand value as a `ndarray`
/// (which would be accessed by its broadcast index) or as a scalar value (which would be
/// broadcast to all elements).
///
/// * `elem_ty` - The element type of the `NDArray`.
/// * `res` - The `ndarray` instance to write results into, or [`None`] if the result should be
/// written to a new `ndarray`.
/// * `value_fn` - Function mapping the two input elements into the result.
///
/// # Panic
///
/// This function will panic if neither input operands (`lhs` or `rhs`) is a `ndarray`.
pub fn ndarray_elementwise_binop_impl<'ctx, G, ValueFn>(
generator: &mut G,
ctx: &mut CodeGenContext<'ctx, '_>,
elem_ty: Type,
res: Option<NDArrayValue<'ctx>>,
this: NDArrayValue<'ctx>,
other: NDArrayValue<'ctx>,
lhs: (BasicValueEnum<'ctx>, bool),
rhs: (BasicValueEnum<'ctx>, bool),
value_fn: ValueFn,
) -> Result<NDArrayValue<'ctx>, String>
where
G: CodeGenerator,
ValueFn: Fn(&mut G, &mut CodeGenContext<'ctx, '_>, Type, (BasicValueEnum<'ctx>, BasicValueEnum<'ctx>)) -> Result<BasicValueEnum<'ctx>, String>,
{
let ndarray_dims = call_ndarray_calc_broadcast(generator, ctx, this, other);
let llvm_usize = generator.get_size_type(ctx.ctx);
let (lhs_val, lhs_scalar) = lhs;
let (rhs_val, rhs_scalar) = rhs;
assert!(!(lhs_scalar && rhs_scalar),
"One of the operands must be a ndarray instance: `{}`, `{}`",
lhs_val.get_type(),
rhs_val.get_type());
let ndarray = res.unwrap_or_else(|| {
create_ndarray_dyn_shape(
generator,
ctx,
elem_ty,
&ndarray_dims,
|generator, ctx, v| {
Ok(v.size(ctx, generator))
},
|generator, ctx, v, idx| {
unsafe {
Ok(v.get_typed_unchecked(ctx, generator, idx, None))
}
},
).unwrap()
if lhs_scalar && rhs_scalar {
let lhs_val = NDArrayValue::from_ptr_val(lhs_val.into_pointer_value(), llvm_usize, None);
let rhs_val = NDArrayValue::from_ptr_val(rhs_val.into_pointer_value(), llvm_usize, None);
let ndarray_dims = call_ndarray_calc_broadcast(generator, ctx, lhs_val, rhs_val);
create_ndarray_dyn_shape(
generator,
ctx,
elem_ty,
&ndarray_dims,
|generator, ctx, v| {
Ok(v.size(ctx, generator))
},
|generator, ctx, v, idx| {
unsafe {
Ok(v.get_typed_unchecked(ctx, generator, idx, None))
}
},
).unwrap()
} else {
let ndarray = NDArrayValue::from_ptr_val(
if lhs_scalar { rhs_val } else { lhs_val }.into_pointer_value(),
llvm_usize,
None,
);
create_ndarray_dyn_shape(
generator,
ctx,
elem_ty,
&ndarray,
|_, ctx, v| {
Ok(v.load_ndims(ctx))
},
|generator, ctx, v, idx| {
unsafe {
Ok(v.dim_sizes().get_typed_unchecked(ctx, generator, idx, None))
}
},
).unwrap()
}
});
ndarray_broadcast_fill(
@ -662,8 +734,8 @@ pub fn ndarray_elementwise_binop_impl<'ctx, G, ValueFn>(
ctx,
elem_ty,
ndarray,
this,
other,
lhs,
rhs,
|generator, ctx, elem_ty, elems| {
value_fn(generator, ctx, elem_ty, elems)
},

View File

@ -170,13 +170,13 @@ impl SymbolValue {
/// Returns the [`TypeAnnotation`] representing the data type of this value.
pub fn get_type_annotation(&self, primitives: &PrimitiveStore, unifier: &mut Unifier) -> TypeAnnotation {
match self {
SymbolValue::Bool(..) => TypeAnnotation::Primitive(primitives.bool),
SymbolValue::Double(..) => TypeAnnotation::Primitive(primitives.float),
SymbolValue::I32(..) => TypeAnnotation::Primitive(primitives.int32),
SymbolValue::I64(..) => TypeAnnotation::Primitive(primitives.int64),
SymbolValue::U32(..) => TypeAnnotation::Primitive(primitives.uint32),
SymbolValue::U64(..) => TypeAnnotation::Primitive(primitives.uint64),
SymbolValue::Str(..) => TypeAnnotation::Primitive(primitives.str),
SymbolValue::Bool(..)
| SymbolValue::Double(..)
| SymbolValue::I32(..)
| SymbolValue::I64(..)
| SymbolValue::U32(..)
| SymbolValue::U64(..)
| SymbolValue::Str(..) => TypeAnnotation::Primitive(self.get_type(primitives, unifier)),
SymbolValue::Tuple(vs) => {
let vs_tys = vs
.iter()
@ -230,6 +230,36 @@ impl Display for SymbolValue {
}
}
impl TryFrom<SymbolValue> for u64 {
type Error = ();
/// TODO
fn try_from(value: SymbolValue) -> Result<Self, Self::Error> {
match value {
SymbolValue::I32(v) => Ok(v as u64),
SymbolValue::I64(v) => u64::try_from(v).map_err(|_| ()),
SymbolValue::U32(v) => Ok(v as u64),
SymbolValue::U64(v) => Ok(v),
_ => Err(()),
}
}
}
impl TryFrom<SymbolValue> for i128 {
type Error = ();
/// TODO
fn try_from(value: SymbolValue) -> Result<Self, Self::Error> {
match value {
SymbolValue::I32(v) => Ok(v as i128),
SymbolValue::I64(v) => Ok(v as i128),
SymbolValue::U32(v) => Ok(v as i128),
SymbolValue::U64(v) => Ok(v as i128),
_ => Err(()),
}
}
}
pub trait StaticValue {
/// Returns a unique identifier for this value.
fn get_unique_identifier(&self) -> u64;

View File

@ -1,7 +1,7 @@
use super::*;
use crate::{
codegen::{
classes::RangeValue,
classes::{ArrayLikeValue, NDArrayValue, RangeValue, TypedArrayLikeAccessor},
expr::destructure_range,
irrt::*,
llvm_intrinsics::*,
@ -1703,13 +1703,33 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
}
TypeEnum::TObj { obj_id, .. } if *obj_id == PRIMITIVE_DEF_IDS.ndarray => {
let llvm_i32 = ctx.ctx.i32_type();
let i32_zero = llvm_i32.const_zero();
let llvm_usize = generator.get_size_type(ctx.ctx);
let len = ctx.build_gep_and_load(
let arg = NDArrayValue::from_ptr_val(
arg.into_pointer_value(),
&[i32_zero, i32_zero],
None,
).into_int_value();
llvm_usize,
None
);
let ndims = arg.dim_sizes().size(ctx, generator);
ctx.make_assert(
generator,
ctx.builder.build_int_compare(
IntPredicate::NE,
ndims,
llvm_usize.const_zero(),
"",
).unwrap(),
"0:TypeError",
"len() of unsized object",
[None, None, None],
ctx.current_loc,
);
let len = unsafe {
arg.dim_sizes()
.get_typed_unchecked(ctx, generator, llvm_usize.const_zero(), None)
};
if len.get_type().get_bit_width() == 32 {
Some(len.into())

View File

@ -1,4 +1,7 @@
use crate::toplevel::numpy::make_ndarray_ty;
use std::cmp::max;
use crate::symbol_resolver::SymbolValue;
use crate::toplevel::helper::PRIMITIVE_DEF_IDS;
use crate::toplevel::numpy::{make_ndarray_ty, unpack_ndarray_var_tys};
use crate::typecheck::{
type_inferencer::*,
typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier, VarMap},
@ -7,6 +10,7 @@ use nac3parser::ast::StrRef;
use nac3parser::ast::{Cmpop, Operator, Unaryop};
use std::collections::HashMap;
use std::rc::Rc;
use itertools::Itertools;
#[must_use]
pub fn binop_name(op: &Operator) -> &'static str {
@ -91,7 +95,7 @@ pub fn impl_binop(
_store: &PrimitiveStore,
ty: Type,
other_ty: &[Type],
ret_ty: Type,
ret_ty: Option<Type>,
ops: &[Operator],
) {
with_fields(unifier, ty, |unifier, fields| {
@ -108,6 +112,8 @@ pub fn impl_binop(
VarMap::new()
};
let ret_ty = ret_ty.unwrap_or_else(|| unifier.get_fresh_var(None, None).0);
for op in ops {
fields.insert(binop_name(op).into(), {
(
@ -194,7 +200,7 @@ pub fn impl_basic_arithmetic(
store: &PrimitiveStore,
ty: Type,
other_ty: &[Type],
ret_ty: Type,
ret_ty: Option<Type>,
) {
impl_binop(
unifier,
@ -212,7 +218,7 @@ pub fn impl_pow(
store: &PrimitiveStore,
ty: Type,
other_ty: &[Type],
ret_ty: Type,
ret_ty: Option<Type>,
) {
impl_binop(unifier, store, ty, other_ty, ret_ty, &[Operator::Pow]);
}
@ -224,14 +230,14 @@ pub fn impl_bitwise_arithmetic(unifier: &mut Unifier, store: &PrimitiveStore, ty
store,
ty,
&[ty],
ty,
Some(ty),
&[Operator::BitAnd, Operator::BitOr, Operator::BitXor],
);
}
/// `LShift`, `RShift`
pub fn impl_bitwise_shift(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type) {
impl_binop(unifier, store, ty, &[store.int32, store.uint32], ty, &[Operator::LShift, Operator::RShift]);
impl_binop(unifier, store, ty, &[store.int32, store.uint32], Some(ty), &[Operator::LShift, Operator::RShift]);
}
/// `Div`
@ -240,7 +246,7 @@ pub fn impl_div(
store: &PrimitiveStore,
ty: Type,
other_ty: &[Type],
ret_ty: Type,
ret_ty: Option<Type>,
) {
impl_binop(unifier, store, ty, other_ty, ret_ty, &[Operator::Div]);
}
@ -251,7 +257,7 @@ pub fn impl_floordiv(
store: &PrimitiveStore,
ty: Type,
other_ty: &[Type],
ret_ty: Type,
ret_ty: Option<Type>,
) {
impl_binop(unifier, store, ty, other_ty, ret_ty, &[Operator::FloorDiv]);
}
@ -262,7 +268,7 @@ pub fn impl_mod(
store: &PrimitiveStore,
ty: Type,
other_ty: &[Type],
ret_ty: Type,
ret_ty: Option<Type>,
) {
impl_binop(unifier, store, ty, other_ty, ret_ty, &[Operator::Mod]);
}
@ -298,6 +304,137 @@ pub fn impl_eq(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type) {
impl_cmpop(unifier, store, ty, ty, &[Cmpop::Eq, Cmpop::NotEq]);
}
/// Returns the expected return type of binary operations with at least one `ndarray` operand.
pub fn typeof_ndarray_broadcast(
unifier: &mut Unifier,
primitives: &PrimitiveStore,
left: Type,
right: Type,
) -> Result<Type, String> {
let is_left_ndarray = left.get_obj_id(unifier) == PRIMITIVE_DEF_IDS.ndarray;
let is_right_ndarray = right.get_obj_id(unifier) == PRIMITIVE_DEF_IDS.ndarray;
assert!(is_left_ndarray || is_right_ndarray);
if is_left_ndarray && is_right_ndarray {
// Perform broadcasting on two ndarray operands.
let (left_ty_dtype, left_ty_ndims) = unpack_ndarray_var_tys(unifier, left);
let (right_ty_dtype, right_ty_ndims) = unpack_ndarray_var_tys(unifier, right);
assert!(unifier.unioned(left_ty_dtype, right_ty_dtype));
let left_ty_ndims = match &*unifier.get_ty_immutable(left_ty_ndims) {
TypeEnum::TLiteral { values, .. } => values.clone(),
_ => unreachable!(),
};
let right_ty_ndims = match &*unifier.get_ty_immutable(right_ty_ndims) {
TypeEnum::TLiteral { values, .. } => values.clone(),
_ => unreachable!(),
};
let res_ndims = left_ty_ndims.into_iter()
.cartesian_product(right_ty_ndims.into_iter())
.map(|(left, right)| {
let left_val = u64::try_from(left).unwrap();
let right_val = u64::try_from(right).unwrap();
max(left_val, right_val)
})
.unique()
.map(|ndim| SymbolValue::U64(ndim))
.collect_vec();
let res_ndims = unifier.get_fresh_literal(res_ndims, None);
Ok(make_ndarray_ty(unifier, primitives, Some(left_ty_dtype), Some(res_ndims)))
} else {
let (ndarray_ty, scalar_ty) = if is_left_ndarray {
(left, right)
} else {
(right, left)
};
let (ndarray_ty_dtype, _) = unpack_ndarray_var_tys(unifier, ndarray_ty);
if !unifier.unioned(ndarray_ty_dtype, scalar_ty) {
let (expected_ty, actual_ty) = if is_left_ndarray {
(ndarray_ty_dtype, scalar_ty)
} else {
(scalar_ty, ndarray_ty_dtype)
};
Err(format!(
"Expected right-hand side operand to be {}, got {}",
unifier.stringify(expected_ty),
unifier.stringify(actual_ty),
))
} else {
Ok(ndarray_ty)
}
}
}
/// Returns the return type given a binary operator and its primitive operands.
pub fn typeof_binop(
unifier: &mut Unifier,
primitives: &PrimitiveStore,
op: &Operator,
lhs: Type,
rhs: Type,
) -> Result<Option<Type>, String> {
let is_left_ndarray = lhs.get_obj_id(unifier) == PRIMITIVE_DEF_IDS.ndarray;
let is_right_ndarray = rhs.get_obj_id(unifier) == PRIMITIVE_DEF_IDS.ndarray;
Ok(Some(match op {
Operator::Add
| Operator::Sub
| Operator::Mult
| Operator::Mod
| Operator::FloorDiv => {
if is_left_ndarray || is_right_ndarray {
typeof_ndarray_broadcast(unifier, primitives, lhs, rhs)?
} else if unifier.unioned(lhs, rhs) {
lhs
} else {
return Ok(None)
}
}
Operator::MatMult => typeof_ndarray_broadcast(unifier, primitives, lhs, rhs)?,
Operator::Div => {
if is_left_ndarray || is_right_ndarray {
typeof_ndarray_broadcast(unifier, primitives, lhs, rhs)?
} else if unifier.unioned(lhs, rhs) {
primitives.float
} else {
return Ok(None)
}
}
Operator::Pow => {
if is_left_ndarray || is_right_ndarray {
typeof_ndarray_broadcast(unifier, primitives, lhs, rhs)?
} else if [primitives.int32, primitives.int64, primitives.uint32, primitives.uint64, primitives.float].into_iter().any(|ty| unifier.unioned(lhs, ty)) {
lhs
} else {
return Ok(None)
}
}
Operator::LShift
| Operator::RShift
| Operator::BitOr
| Operator::BitXor
| Operator::BitAnd => {
if unifier.unioned(lhs, rhs) {
lhs
} else {
return Ok(None)
}
}
}))
}
pub fn set_primitives_magic_methods(store: &PrimitiveStore, unifier: &mut Unifier) {
let PrimitiveStore {
int32: int32_t,
@ -313,13 +450,14 @@ pub fn set_primitives_magic_methods(store: &PrimitiveStore, unifier: &mut Unifie
/* int ======== */
for t in [int32_t, int64_t, uint32_t, uint64_t] {
impl_basic_arithmetic(unifier, store, t, &[t], t);
impl_pow(unifier, store, t, &[t], t);
let ndarray_int_t = make_ndarray_ty(unifier, store, Some(t), None);
impl_basic_arithmetic(unifier, store, t, &[t, ndarray_int_t], None);
impl_pow(unifier, store, t, &[t, ndarray_int_t], None);
impl_bitwise_arithmetic(unifier, store, t);
impl_bitwise_shift(unifier, store, t);
impl_div(unifier, store, t, &[t], float_t);
impl_floordiv(unifier, store, t, &[t], t);
impl_mod(unifier, store, t, &[t], t);
impl_div(unifier, store, t, &[t, ndarray_int_t], None);
impl_floordiv(unifier, store, t, &[t, ndarray_int_t], None);
impl_mod(unifier, store, t, &[t, ndarray_int_t], None);
impl_invert(unifier, store, t);
impl_not(unifier, store, t);
impl_comparison(unifier, store, t, t);
@ -330,11 +468,13 @@ pub fn set_primitives_magic_methods(store: &PrimitiveStore, unifier: &mut Unifie
}
/* float ======== */
impl_basic_arithmetic(unifier, store, float_t, &[float_t], float_t);
impl_pow(unifier, store, float_t, &[int32_t, float_t], float_t);
impl_div(unifier, store, float_t, &[float_t], float_t);
impl_floordiv(unifier, store, float_t, &[float_t], float_t);
impl_mod(unifier, store, float_t, &[float_t], float_t);
let ndarray_float_t = make_ndarray_ty(unifier, store, Some(float_t), None);
let ndarray_int32_t = make_ndarray_ty(unifier, store, Some(int32_t), None);
impl_basic_arithmetic(unifier, store, float_t, &[float_t, ndarray_float_t], None);
impl_pow(unifier, store, float_t, &[int32_t, float_t, ndarray_int32_t, ndarray_float_t], None);
impl_div(unifier, store, float_t, &[float_t, ndarray_float_t], None);
impl_floordiv(unifier, store, float_t, &[float_t, ndarray_float_t], None);
impl_mod(unifier, store, float_t, &[float_t, ndarray_float_t], None);
impl_sign(unifier, store, float_t);
impl_not(unifier, store, float_t);
impl_comparison(unifier, store, float_t, float_t);
@ -345,12 +485,13 @@ pub fn set_primitives_magic_methods(store: &PrimitiveStore, unifier: &mut Unifie
impl_eq(unifier, store, bool_t);
/* ndarray ===== */
let ndarray_float_t = make_ndarray_ty(unifier, store, Some(float_t), None);
let ndarray_usized_ndims_tvar = unifier.get_fresh_const_generic_var(size_t, Some("ndarray_ndims".into()), None);
let ndarray_unsized_t = make_ndarray_ty(unifier, store, None, Some(ndarray_usized_ndims_tvar.0));
impl_basic_arithmetic(unifier, store, ndarray_t, &[ndarray_unsized_t], ndarray_t);
impl_pow(unifier, store, ndarray_t, &[ndarray_unsized_t], ndarray_t);
impl_div(unifier, store, ndarray_t, &[ndarray_t], ndarray_float_t);
impl_floordiv(unifier, store, ndarray_t, &[ndarray_unsized_t], ndarray_t);
impl_mod(unifier, store, ndarray_t, &[ndarray_unsized_t], ndarray_t);
let (ndarray_dtype_t, _) = unpack_ndarray_var_tys(unifier, ndarray_t);
let (ndarray_unsized_dtype_t, _) = unpack_ndarray_var_tys(unifier, ndarray_unsized_t);
impl_basic_arithmetic(unifier, store, ndarray_t, &[ndarray_unsized_t, ndarray_unsized_dtype_t], None);
impl_pow(unifier, store, ndarray_t, &[ndarray_unsized_t, ndarray_unsized_dtype_t], None);
impl_div(unifier, store, ndarray_t, &[ndarray_t, ndarray_dtype_t], None);
impl_floordiv(unifier, store, ndarray_t, &[ndarray_unsized_t, ndarray_unsized_dtype_t], None);
impl_mod(unifier, store, ndarray_t, &[ndarray_unsized_t, ndarray_unsized_dtype_t], None);
}

View File

@ -13,7 +13,7 @@ use crate::{
TopLevelContext,
},
};
use itertools::izip;
use itertools::{Itertools, izip};
use nac3parser::ast::{
self,
fold::{self, Fold},
@ -59,6 +59,16 @@ pub struct PrimitiveStore {
}
impl PrimitiveStore {
/// Returns a [`Type`] representing a signed representation of `size_t`.
#[must_use]
pub fn isize(&self) -> Type {
match self.size_t {
32 => self.int32,
64 => self.int64,
_ => unreachable!(),
}
}
/// Returns a [Type] representing `size_t`.
#[must_use]
pub fn usize(&self) -> Type {
@ -1193,8 +1203,11 @@ impl<'a> Inferencer<'a> {
right: &ast::Expr<Option<Type>>,
is_aug_assign: bool,
) -> InferenceResult {
let left_ty = left.custom.unwrap();
let right_ty = right.custom.unwrap();
let method = if let TypeEnum::TObj { fields, .. } =
self.unifier.get_ty_immutable(left.custom.unwrap()).as_ref()
self.unifier.get_ty_immutable(left_ty).as_ref()
{
let (binop_name, binop_assign_name) = (
binop_name(op).into(),
@ -1209,12 +1222,26 @@ impl<'a> Inferencer<'a> {
} else {
binop_name(op).into()
};
let ret = if is_aug_assign {
// The type of an augmented assignment operator should never change
Some(left_ty)
} else {
typeof_binop(
self.unifier,
self.primitives,
op,
left_ty,
right_ty,
).map_err(|e| HashSet::from([format!("{} (at {})", e, location)]))?
};
self.build_method_call(
location,
method,
left.custom.unwrap(),
vec![right.custom.unwrap()],
None,
left_ty,
vec![right_ty],
ret,
)
}
@ -1381,7 +1408,16 @@ impl<'a> Inferencer<'a> {
TypeEnum::TObj { obj_id, .. } if *obj_id == PRIMITIVE_DEF_IDS.ndarray => {
let (_, ndims) = unpack_ndarray_var_tys(self.unifier, value.custom.unwrap());
self.constrain(slice.custom.unwrap(), self.primitives.usize(), &slice.location)?;
let valid_index_tys = [
self.primitives.int32,
self.primitives.isize(),
].into_iter().unique().collect_vec();
let valid_index_ty = self.unifier.get_fresh_var_with_range(
valid_index_tys.as_slice(),
None,
None,
).0;
self.constrain(slice.custom.unwrap(), valid_index_ty, &slice.location)?;
self.infer_subscript_ndarray(value, ty, ndims)
}
_ => unreachable!(),

View File

@ -765,12 +765,8 @@ impl Unifier {
// If the types don't match, try to implicitly promote integers
if !self.unioned(ty, value_ty) {
let num_val = match *value {
SymbolValue::I32(v) => v as i128,
SymbolValue::I64(v) => v as i128,
SymbolValue::U32(v) => v as i128,
SymbolValue::U64(v) => v as i128,
_ => return Self::incompatible_types(a, b),
let Ok(num_val) = i128::try_from(value.clone()) else {
return Self::incompatible_types(a, b)
};
let can_convert = if self.unioned(ty, primitives.int32) {

View File

@ -6,6 +6,19 @@ def output_int32(x: int32):
def output_float64(x: float):
...
def output_ndarray_int32_1(n: ndarray[int32, Literal[1]]):
for i in range(len(n)):
output_int32(n[i])
def output_ndarray_float_1(n: ndarray[float, Literal[1]]):
for i in range(len(n)):
output_float64(n[i])
def output_ndarray_float_2(n: ndarray[float, Literal[2]]):
for r in range(len(n)):
for c in range(len(n[r])):
output_float64(n[r][c])
def consume_ndarray_1(n: ndarray[float, Literal[1]]):
pass
@ -19,228 +32,381 @@ def test_ndarray_empty():
def test_ndarray_zeros():
n: ndarray[float, 1] = np_zeros([1])
output_float64(n[0])
output_ndarray_float_1(n)
def test_ndarray_ones():
n: ndarray[float, 1] = np_ones([1])
output_float64(n[0])
output_ndarray_float_1(n)
def test_ndarray_full():
n_float: ndarray[float, 1] = np_full([1], 2.0)
output_float64(n_float[0])
output_ndarray_float_1(n_float)
n_i32: ndarray[int32, 1] = np_full([1], 2)
output_int32(n_i32[0])
output_ndarray_int32_1(n_i32)
def test_ndarray_eye():
n: ndarray[float, 2] = np_eye(2)
n0: ndarray[float, 1] = n[0]
v: float = n0[0]
output_float64(v)
output_ndarray_float_2(n)
def test_ndarray_identity():
n: ndarray[float, 2] = np_identity(2)
output_float64(n[0][0])
output_float64(n[0][1])
output_float64(n[1][0])
output_float64(n[1][1])
output_ndarray_float_2(n)
def test_ndarray_fill():
n: ndarray[float, 2] = np_empty([2, 2])
n.fill(1.0)
output_float64(n[0][0])
output_float64(n[0][1])
output_float64(n[1][0])
output_float64(n[1][1])
output_ndarray_float_2(n)
def test_ndarray_copy():
x: ndarray[float, 2] = np_identity(2)
y = x.copy()
x.fill(0.0)
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_float64(y[0][0])
output_float64(y[0][1])
output_float64(y[1][0])
output_float64(y[1][1])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_add():
x = np_identity(2)
y = x + np_ones([2, 2])
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
output_float64(y[0][0])
output_float64(y[0][1])
output_float64(y[1][0])
output_float64(y[1][1])
def test_ndarray_add_broadcast():
x = np_identity(2)
# y: ndarray[float, 2] = x + np_ones([2])
y = x + np_ones([2])
# def test_ndarray_add_broadcast():
# x = np_identity(2)
# y: ndarray[float, 2] = x + np_ones([2])
#
# output_float64(x[0][0])
# output_float64(x[0][1])
# output_float64(x[1][0])
# output_float64(x[1][1])
#
# output_float64(y[0][0])
# output_float64(y[0][1])
# output_float64(y[1][0])
# output_float64(y[1][1])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_add_broadcast_lhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = 1.0 + x
y = 1.0 + x
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_add_broadcast_rhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = x + 1.0
y = x + 1.0
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_iadd():
x = np_identity(2)
x += np_ones([2, 2])
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
def test_ndarray_iadd_broadcast():
x = np_identity(2)
x += np_ones([2])
output_ndarray_float_2(x)
def test_ndarray_iadd_broadcast_scalar():
x = np_identity(2)
x += 1.0
output_ndarray_float_2(x)
def test_ndarray_sub():
x = np_ones([2, 2])
y = x - np_identity(2)
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
output_float64(y[0][0])
output_float64(y[0][1])
output_float64(y[1][0])
output_float64(y[1][1])
def test_ndarray_sub_broadcast():
x = np_identity(2)
# y: ndarray[float, 2] = x - np_ones([2])
y = x - np_ones([2])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_sub_broadcast_lhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = 1.0 - x
y = 1.0 - x
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_sub_broadcast_rhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = x - 1
y = x - 1.0
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_isub():
x = np_ones([2, 2])
x -= np_identity(2)
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
def test_ndarray_isub_broadcast():
x = np_identity(2)
x -= np_ones([2])
output_ndarray_float_2(x)
def test_ndarray_isub_broadcast_scalar():
x = np_identity(2)
x -= 1.0
output_ndarray_float_2(x)
def test_ndarray_mul():
x = np_ones([2, 2])
y = x * np_identity(2)
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
output_float64(y[0][0])
output_float64(y[0][1])
output_float64(y[1][0])
output_float64(y[1][1])
def test_ndarray_mul_broadcast():
x = np_identity(2)
# y: ndarray[float, 2] = x * np_ones([2])
y = x * np_ones([2])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_mul_broadcast_lhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = 2.0 * x
y = 2.0 * x
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_mul_broadcast_rhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = x * 2.0
y = x * 2.0
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_imul():
x = np_ones([2, 2])
x *= np_identity(2)
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
def test_ndarray_imul_broadcast():
x = np_identity(2)
x *= np_ones([2])
output_ndarray_float_2(x)
def test_ndarray_imul_broadcast_scalar():
x = np_identity(2)
x *= 2.0
output_ndarray_float_2(x)
def test_ndarray_truediv():
x = np_identity(2)
y = x / np_ones([2, 2])
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
output_float64(y[0][0])
output_float64(y[0][1])
output_float64(y[1][0])
output_float64(y[1][1])
def test_ndarray_truediv_broadcast():
x = np_identity(2)
# y: ndarray[float, 2] = x / np_ones([2])
y = x / np_ones([2])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_truediv_broadcast_lhs_scalar():
x = np_ones([2, 2])
# y: ndarray[float, 2] = 2.0 / x
y = 2.0 / x
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_truediv_broadcast_rhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = x / 2.0
y = x / 2.0
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_itruediv():
x = np_identity(2)
x /= np_ones([2, 2])
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
def test_ndarray_itruediv_broadcast():
x = np_identity(2)
x /= np_ones([2])
output_ndarray_float_2(x)
def test_ndarray_itruediv_broadcast_scalar():
x = np_identity(2)
x /= 2.0
output_ndarray_float_2(x)
def test_ndarray_floordiv():
x = np_identity(2)
y = x // np_ones([2, 2])
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
output_float64(y[0][0])
output_float64(y[0][1])
output_float64(y[1][0])
output_float64(y[1][1])
def test_ndarray_floordiv_broadcast():
x = np_identity(2)
# y: ndarray[float, 2] = x // np_ones([2])
y = x // np_ones([2])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_floordiv_broadcast_lhs_scalar():
x = np_ones([2, 2])
# y: ndarray[float, 2] = 2.0 // x
y = 2.0 // x
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_floordiv_broadcast_rhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = x // 2.0
y = x // 2.0
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_ifloordiv():
x = np_identity(2)
x //= np_ones([2, 2])
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
def test_ndarray_ifloordiv_broadcast():
x = np_identity(2)
x //= np_ones([2])
output_ndarray_float_2(x)
def test_ndarray_ifloordiv_broadcast_scalar():
x = np_identity(2)
x //= 2.0
output_ndarray_float_2(x)
def test_ndarray_mod():
x = np_identity(2)
y = x % np_full([2, 2], 2.0)
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
output_float64(y[0][0])
output_float64(y[0][1])
output_float64(y[1][0])
output_float64(y[1][1])
def test_ndarray_mod_broadcast():
x = np_identity(2)
# y: ndarray[float, 2] = x % np_ones([2])
y = x % np_full([2], 2.0)
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_mod_broadcast_lhs_scalar():
x = np_ones([2, 2])
# y: ndarray[float, 2] = 2.0 % x
y = 2.0 % x
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_mod_broadcast_rhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = x % 2.0
y = x % 2.0
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_imod():
x = np_identity(2)
x %= np_full([2, 2], 2.0)
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
def test_ndarray_imod_broadcast():
x = np_identity(2)
x %= np_full([2], 2.0)
output_ndarray_float_2(x)
def test_ndarray_imod_broadcast_scalar():
x = np_identity(2)
x %= 2.0
output_ndarray_float_2(x)
def test_ndarray_pow():
x = np_identity(2)
y = x ** np_full([2, 2], 2.0)
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
output_ndarray_float_2(y)
output_float64(y[0][0])
output_float64(y[0][1])
output_float64(y[1][0])
output_float64(y[1][1])
def test_ndarray_pow_broadcast():
x = np_identity(2)
# y: ndarray[float, 2] = x ** np_full([2], 2.0)
y = x ** np_full([2], 2.0)
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_pow_broadcast_lhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = 2.0 ** x
y = 2.0 ** x
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_pow_broadcast_rhs_scalar():
x = np_identity(2)
# y: ndarray[float, 2] = x % 2.0
y = x ** 2.0
output_ndarray_float_2(x)
output_ndarray_float_2(y)
def test_ndarray_ipow():
x = np_identity(2)
x **= np_full([2, 2], 2.0)
output_float64(x[0][0])
output_float64(x[0][1])
output_float64(x[1][0])
output_float64(x[1][1])
output_ndarray_float_2(x)
def test_ndarray_ipow_broadcast():
x = np_identity(2)
x **= np_full([2], 2.0)
output_ndarray_float_2(x)
def test_ndarray_ipow_broadcast_scalar():
x = np_identity(2)
x **= 2.0
output_ndarray_float_2(x)
def run() -> int32:
test_ndarray_ctor()
@ -253,16 +419,53 @@ def run() -> int32:
test_ndarray_fill()
test_ndarray_copy()
test_ndarray_add()
test_ndarray_add_broadcast()
test_ndarray_add_broadcast_lhs_scalar()
test_ndarray_add_broadcast_rhs_scalar()
test_ndarray_iadd()
test_ndarray_iadd_broadcast()
test_ndarray_iadd_broadcast_scalar()
test_ndarray_sub()
test_ndarray_sub_broadcast()
test_ndarray_sub_broadcast_lhs_scalar()
test_ndarray_sub_broadcast_rhs_scalar()
test_ndarray_isub()
test_ndarray_isub_broadcast()
test_ndarray_isub_broadcast_scalar()
test_ndarray_mul()
test_ndarray_mul_broadcast()
test_ndarray_mul_broadcast_lhs_scalar()
test_ndarray_mul_broadcast_rhs_scalar()
test_ndarray_imul()
test_ndarray_imul_broadcast()
test_ndarray_imul_broadcast_scalar()
test_ndarray_truediv()
test_ndarray_truediv_broadcast()
test_ndarray_truediv_broadcast_lhs_scalar()
test_ndarray_truediv_broadcast_rhs_scalar()
test_ndarray_itruediv()
test_ndarray_itruediv_broadcast()
test_ndarray_itruediv_broadcast_scalar()
test_ndarray_floordiv()
test_ndarray_floordiv_broadcast()
test_ndarray_floordiv_broadcast_lhs_scalar()
test_ndarray_floordiv_broadcast_rhs_scalar()
test_ndarray_ifloordiv()
test_ndarray_ifloordiv_broadcast()
test_ndarray_ifloordiv_broadcast_scalar()
test_ndarray_mod()
test_ndarray_mod_broadcast()
test_ndarray_mod_broadcast_lhs_scalar()
test_ndarray_mod_broadcast_rhs_scalar()
test_ndarray_imod()
test_ndarray_imod_broadcast()
test_ndarray_imod_broadcast_scalar()
test_ndarray_pow()
test_ndarray_pow_broadcast()
test_ndarray_pow_broadcast_lhs_scalar()
test_ndarray_pow_broadcast_rhs_scalar()
test_ndarray_ipow()
test_ndarray_ipow_broadcast()
test_ndarray_ipow_broadcast_scalar()
return 0

View File

@ -1,27 +1,21 @@
{ pkgs } : [
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libffi-3.4.5-1-any.pkg.tar.zst";
sha256 = "13br3j605wn1vmwvfd32c99x247b01dvnkpdbxp0yx7w76f0w8n5";
name = "mingw-w64-clang-x86_64-libffi-3.4.5-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libunwind-18.1.2-1-any.pkg.tar.zst";
sha256 = "0ksz7xz1lbwsmdr9sa1444k0dlfkbd8k11pq7w08ir7r1wjy6fid";
name = "mingw-w64-clang-x86_64-libunwind-18.1.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libunwind-17.0.6-1-any.pkg.tar.zst";
sha256 = "14qpk7xixmygvli5yx66k1kgc4i31sgqv9zjwvg918bw4771cy1w";
name = "mingw-w64-clang-x86_64-libunwind-17.0.6-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libc++-18.1.2-1-any.pkg.tar.zst";
sha256 = "0r8skyjqv4cpkqif0niakx4hdpkscil1zf6mzj34pqna0j5gdnq2";
name = "mingw-w64-clang-x86_64-libc++-18.1.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libc++-17.0.6-1-any.pkg.tar.zst";
sha256 = "1m3i8znblmzd3yanwss35wfn4v3373dvgkly1zpzxr87cwprhgw9";
name = "mingw-w64-clang-x86_64-libc++-17.0.6-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-zlib-1.3.1-1-any.pkg.tar.zst";
sha256 = "06i9xjsskf4ddb2ph4h31md5c7imj9mzjhd4lc4q44j8dmpc1w5p";
name = "mingw-w64-clang-x86_64-zlib-1.3.1-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libffi-3.4.6-1-any.pkg.tar.zst";
sha256 = "1q6gms980985bp087rnnpvz2fwfakgm5266izfk3b1mbp620s1yv";
name = "mingw-w64-clang-x86_64-libffi-3.4.6-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
@ -31,21 +25,27 @@
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-gettext-runtime-0.22.4-6-any.pkg.tar.zst";
sha256 = "06hanbbcb3zk7b4jlw46kcfxk7xb1fdc0g5wfhm4f2i38wc0c3la";
name = "mingw-w64-clang-x86_64-gettext-runtime-0.22.4-6-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-gettext-runtime-0.22.5-2-any.pkg.tar.zst";
sha256 = "0ll6ci6d3mc7g04q0xixjc209bh8r874dqbczgns69jsad3wg6mi";
name = "mingw-w64-clang-x86_64-gettext-runtime-0.22.5-2-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-xz-5.4.6-2-any.pkg.tar.zst";
sha256 = "09fy9g84153ccfwcvb6wp8nz7zl0apbm5qwn1zqjn34287y0b71a";
name = "mingw-w64-clang-x86_64-xz-5.4.6-2-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-xz-5.6.1-1-any.pkg.tar.zst";
sha256 = "14p4xxaxjjy6j1ingji82xhai1mc1gls5ali6z40fbb2ylxkaggs";
name = "mingw-w64-clang-x86_64-xz-5.6.1-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libxml2-2.12.5-1-any.pkg.tar.zst";
sha256 = "0x3457cbbqadn6nl4pbji4mvc78nngc6r17js5qbzg8ir4rllj5i";
name = "mingw-w64-clang-x86_64-libxml2-2.12.5-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-zlib-1.3.1-1-any.pkg.tar.zst";
sha256 = "06i9xjsskf4ddb2ph4h31md5c7imj9mzjhd4lc4q44j8dmpc1w5p";
name = "mingw-w64-clang-x86_64-zlib-1.3.1-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libxml2-2.12.6-1-any.pkg.tar.zst";
sha256 = "177b3rmsknqq6hf0zqwva71s3avh20ca7vzznp2ls2z5qm8vhhlp";
name = "mingw-w64-clang-x86_64-libxml2-2.12.6-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
@ -55,69 +55,69 @@
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-llvm-libs-17.0.6-7-any.pkg.tar.zst";
sha256 = "073dh9s67c982f1k9jlssm0d95ikydnfl3kis70bdjyf874d41v9";
name = "mingw-w64-clang-x86_64-llvm-libs-17.0.6-7-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-llvm-libs-18.1.2-1-any.pkg.tar.zst";
sha256 = "0ibiy01v16naik9pj32ch7a9pkbw4yrn3gyq7p0y6kcc63fkjazy";
name = "mingw-w64-clang-x86_64-llvm-libs-18.1.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-llvm-17.0.6-7-any.pkg.tar.zst";
sha256 = "17w9dzvfm0w6cxd69vy9mipng9ahhsdwabsrjxgf7dc6fhf7cg01";
name = "mingw-w64-clang-x86_64-llvm-17.0.6-7-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-llvm-18.1.2-1-any.pkg.tar.zst";
sha256 = "1hcfz6nb6svmmcqzfrdi96az2x7mzj0cispdv2ssbgn7nkf19pi0";
name = "mingw-w64-clang-x86_64-llvm-18.1.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-clang-libs-17.0.6-7-any.pkg.tar.zst";
sha256 = "0fb1jvvvzwnb6f2kjqqy2nagk9wb1brh7q7sx1l1blgpwzb99rgr";
name = "mingw-w64-clang-x86_64-clang-libs-17.0.6-7-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-clang-libs-18.1.2-1-any.pkg.tar.zst";
sha256 = "1k17d18g7rmq2ph4kq1mf84vs8133jzf52nkv6syh39ypjga67wa";
name = "mingw-w64-clang-x86_64-clang-libs-18.1.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-compiler-rt-17.0.6-7-any.pkg.tar.zst";
sha256 = "0lcllzsb4wj761kxijd9n70m50dgq6rp9ks8cqgfdk1b2hyxjhmn";
name = "mingw-w64-clang-x86_64-compiler-rt-17.0.6-7-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-compiler-rt-18.1.2-1-any.pkg.tar.zst";
sha256 = "1w2j0vs888haz9shjr1l8dc4j957sk1p0377zzipkbqnzqwjf1z8";
name = "mingw-w64-clang-x86_64-compiler-rt-18.1.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-headers-git-11.0.0.r631.ga4c0c1d00-1-any.pkg.tar.zst";
sha256 = "1f3hlmrhmndqd5f6nb9kjs7z7a2dcnnjwdj6vhnq1zdnb9ng5lsz";
name = "mingw-w64-clang-x86_64-headers-git-11.0.0.r631.ga4c0c1d00-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-headers-git-11.0.0.r655.gdbfdf8025-1-any.pkg.tar.zst";
sha256 = "18csfwlk2h9pr4411crx1b41qjzn5jgbssm3h109nzwbdizkp62h";
name = "mingw-w64-clang-x86_64-headers-git-11.0.0.r655.gdbfdf8025-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-crt-git-11.0.0.r631.ga4c0c1d00-1-any.pkg.tar.zst";
sha256 = "1g13b9xr2mw88256m45gy9q6ymgbs9fxc6acz8mvai0bqns3h978";
name = "mingw-w64-clang-x86_64-crt-git-11.0.0.r631.ga4c0c1d00-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-crt-git-11.0.0.r655.gdbfdf8025-1-any.pkg.tar.zst";
sha256 = "03l1zkrxgxxssp430xcv2gch1d03rbnbk1c0vgiqxigcs8lljh2g";
name = "mingw-w64-clang-x86_64-crt-git-11.0.0.r655.gdbfdf8025-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-lld-17.0.6-7-any.pkg.tar.zst";
sha256 = "0v2q0770bavm5nsf57vxb5hf9iz8aip97yy34cd30g6xvx33vz95";
name = "mingw-w64-clang-x86_64-lld-17.0.6-7-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-lld-18.1.2-1-any.pkg.tar.zst";
sha256 = "1ai4gl7ybpk9n10jmbpf3zzfa893m1krj5qhf44ajln0jabdfnbn";
name = "mingw-w64-clang-x86_64-lld-18.1.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libwinpthread-git-11.0.0.r631.ga4c0c1d00-1-any.pkg.tar.zst";
sha256 = "0i3ba2rwpyzai51c66kka2w8hbz7gpcc35pcmki1sskh0m9g33i6";
name = "mingw-w64-clang-x86_64-libwinpthread-git-11.0.0.r631.ga4c0c1d00-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-libwinpthread-git-11.0.0.r655.gdbfdf8025-1-any.pkg.tar.zst";
sha256 = "1svhjzwhvl4ldl439jhgfy47g05y2af1cjqvydgijn1dd4g8y8vq";
name = "mingw-w64-clang-x86_64-libwinpthread-git-11.0.0.r655.gdbfdf8025-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-winpthreads-git-11.0.0.r631.ga4c0c1d00-1-any.pkg.tar.zst";
sha256 = "0m86d2k0axdhspd3j63y8v55q463zghw5b0zq6w4f48cwaj3wvlv";
name = "mingw-w64-clang-x86_64-winpthreads-git-11.0.0.r631.ga4c0c1d00-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-winpthreads-git-11.0.0.r655.gdbfdf8025-1-any.pkg.tar.zst";
sha256 = "0jxdhkl256vnr13xf1x3fyjrdf764zg70xcs3gki3rg109f0a6xk";
name = "mingw-w64-clang-x86_64-winpthreads-git-11.0.0.r655.gdbfdf8025-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-clang-17.0.6-7-any.pkg.tar.zst";
sha256 = "0z6w4iixsl9cswc3mz9saw61dvz1wy1ssfspma2zni6s79igwdbq";
name = "mingw-w64-clang-x86_64-clang-17.0.6-7-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-clang-18.1.2-1-any.pkg.tar.zst";
sha256 = "0ahfic7vdfv96k5v7fdkgk1agk28l833xjn2igrmbvqg96ak0w6n";
name = "mingw-w64-clang-x86_64-clang-18.1.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-c-ares-1.26.0-1-any.pkg.tar.zst";
sha256 = "18rzy1rsb25gs4rj258pa35fnlb6ri1bx54s3f52585anna75j19";
name = "mingw-w64-clang-x86_64-c-ares-1.26.0-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-c-ares-1.27.0-1-any.pkg.tar.zst";
sha256 = "06y3sgqv6a0gr3dsbzs36jrj8adklssgjqi2ms5clsyq6ay4f91r";
name = "mingw-w64-clang-x86_64-c-ares-1.27.0-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
@ -157,9 +157,9 @@
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-ca-certificates-20230311-1-any.pkg.tar.zst";
sha256 = "00hdl239695xi5bgld7a1ssp6kapkb9az02dpx80vmz7mqg6wwxx";
name = "mingw-w64-clang-x86_64-ca-certificates-20230311-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-ca-certificates-20240203-1-any.pkg.tar.zst";
sha256 = "1q5nxhsk04gidz66ai5wgd4dr04lfyakkfja9p0r5hrgg4ppqqjg";
name = "mingw-w64-clang-x86_64-ca-certificates-20240203-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
@ -175,9 +175,9 @@
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-nghttp2-1.59.0-1-any.pkg.tar.zst";
sha256 = "1id5nkz8n2d3qxvrvp0zrbycwg1z58qwv5p6msmajx4ra3gkma47";
name = "mingw-w64-clang-x86_64-nghttp2-1.59.0-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-nghttp2-1.60.0-1-any.pkg.tar.zst";
sha256 = "0wxw8266hf4qd2m4zpgb1wvlrnaksmcrs0kh5y9zpf2y5sy8f2bq";
name = "mingw-w64-clang-x86_64-nghttp2-1.60.0-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
@ -199,9 +199,9 @@
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-expat-2.6.0-1-any.pkg.tar.zst";
sha256 = "1zdrv2k04qpzqn90v5g77mcqr5fcfqm83da3i75whwkjydp5szfj";
name = "mingw-w64-clang-x86_64-expat-2.6.0-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-expat-2.6.2-1-any.pkg.tar.zst";
sha256 = "0kj1vzjh3qh7d2g47avlgk7a6j4nc62111hy1m63jwq0alc01k38";
name = "mingw-w64-clang-x86_64-expat-2.6.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
@ -265,9 +265,9 @@
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-cmake-3.28.3-2-any.pkg.tar.zst";
sha256 = "1brv240jiw0sas8pvapyk9s5c3dhynq1cxkr9dcjr5b2rigmq3i3";
name = "mingw-w64-clang-x86_64-cmake-3.28.3-2-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-cmake-3.29.0-1-any.pkg.tar.zst";
sha256 = "0l79lf6zihn0k8hz93qnjnq259y45yq19235g9c444jc2w093si1";
name = "mingw-w64-clang-x86_64-cmake-3.29.0-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
@ -301,9 +301,9 @@
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-sqlite3-3.45.1-1-any.pkg.tar.zst";
sha256 = "04mrbn2b1ylr0vfcsmdbr22xp13y8dvyxhzc6xwnrd9yld3ylfpd";
name = "mingw-w64-clang-x86_64-sqlite3-3.45.1-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-sqlite3-3.45.2-1-any.pkg.tar.zst";
sha256 = "1icvw3f08cgi94p0177i46v72wgpsxw95p6kd0sm2w3vj0qlqbcw";
name = "mingw-w64-clang-x86_64-sqlite3-3.45.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
@ -325,9 +325,9 @@
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-openmp-17.0.6-1-any.pkg.tar.zst";
sha256 = "0v6ha1c571glq8ghgv4dwwd6v02bk5livmh4pgyyy10awd8zsy20";
name = "mingw-w64-clang-x86_64-openmp-17.0.6-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-openmp-18.1.2-1-any.pkg.tar.zst";
sha256 = "1v9wm3ja3a7a7yna2bpqky481qf244wc98kfdl7l03k7rkvvydpl";
name = "mingw-w64-clang-x86_64-openmp-18.1.2-1-any.pkg.tar.zst";
})
(pkgs.fetchurl {
@ -343,8 +343,8 @@
})
(pkgs.fetchurl {
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-python-setuptools-69.1.0-1-any.pkg.tar.zst";
sha256 = "16s4v18yi0xm10dkk7k5g9nk3ssgq1lplgci2fgq447x1x1cz0sy";
name = "mingw-w64-clang-x86_64-python-setuptools-69.1.0-1-any.pkg.tar.zst";
url = "https://mirror.msys2.org/mingw/clang64/mingw-w64-clang-x86_64-python-setuptools-69.1.1-1-any.pkg.tar.zst";
sha256 = "1mc56anasj0v92nlg84m3pa7dbqgjakxw0b4ibqlrr9cq0xzsg4b";
name = "mingw-w64-clang-x86_64-python-setuptools-69.1.1-1-any.pkg.tar.zst";
})
]