1
0
forked from M-Labs/nac3

core: Change bitshift operators to accept int32/uint32 for RHS operand

This commit is contained in:
David Mak 2023-10-31 11:41:13 +08:00 committed by sb10q
parent 3231eb0d78
commit d322c91697
4 changed files with 49 additions and 12 deletions

View File

@ -96,11 +96,13 @@ pub fn impl_binop(
let (ty, var_id) = unifier.get_fresh_var_with_range(other_ty, Some("N".into()), None); let (ty, var_id) = unifier.get_fresh_var_with_range(other_ty, Some("N".into()), None);
(ty, Some(var_id)) (ty, Some(var_id))
}; };
let function_vars = if let Some(var_id) = other_var_id { let function_vars = if let Some(var_id) = other_var_id {
vec![(var_id, other_ty)].into_iter().collect::<HashMap<_, _>>() vec![(var_id, other_ty)].into_iter().collect::<HashMap<_, _>>()
} else { } else {
HashMap::new() HashMap::new()
}; };
for op in ops { for op in ops {
fields.insert(binop_name(op).into(), { fields.insert(binop_name(op).into(), {
( (
@ -224,7 +226,7 @@ pub fn impl_bitwise_arithmetic(unifier: &mut Unifier, store: &PrimitiveStore, ty
/// LShift, RShift /// LShift, RShift
pub fn impl_bitwise_shift(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type) { pub fn impl_bitwise_shift(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type) {
impl_binop(unifier, store, ty, &[ty], ty, &[ast::Operator::LShift, ast::Operator::RShift]) impl_binop(unifier, store, ty, &[store.int32, store.uint32], ty, &[ast::Operator::LShift, ast::Operator::RShift]);
} }
/// Div /// Div
@ -295,6 +297,7 @@ pub fn set_primitives_magic_methods(store: &PrimitiveStore, unifier: &mut Unifie
uint64: uint64_t, uint64: uint64_t,
.. ..
} = *store; } = *store;
/* int ======== */ /* int ======== */
for t in [int32_t, int64_t, uint32_t, uint64_t] { for t in [int32_t, int64_t, uint32_t, uint64_t] {
impl_basic_arithmetic(unifier, store, t, &[t], t); impl_basic_arithmetic(unifier, store, t, &[t], t);

View File

@ -116,6 +116,7 @@ impl RecordField {
} }
} }
/// Category of variable and value types.
#[derive(Clone)] #[derive(Clone)]
pub enum TypeEnum { pub enum TypeEnum {
TRigidVar { TRigidVar {
@ -123,6 +124,8 @@ pub enum TypeEnum {
name: Option<StrRef>, name: Option<StrRef>,
loc: Option<Location>, loc: Option<Location>,
}, },
/// A type variable.
TVar { TVar {
id: u32, id: u32,
// empty indicates this is not a struct/tuple/list // empty indicates this is not a struct/tuple/list
@ -132,21 +135,41 @@ pub enum TypeEnum {
name: Option<StrRef>, name: Option<StrRef>,
loc: Option<Location>, loc: Option<Location>,
}, },
/// A tuple type.
TTuple { TTuple {
/// The types of elements present in this tuple.
ty: Vec<Type>, ty: Vec<Type>,
}, },
/// A list type.
TList { TList {
/// The type of elements present in this list.
ty: Type, ty: Type,
}, },
/// An object type.
TObj { TObj {
/// The [DefintionId] of this object type.
obj_id: DefinitionId, obj_id: DefinitionId,
/// The fields present in this object type.
///
/// The key of the [Mapping] is the identifier of the field, while the value is a tuple
/// containing the [Type] of the field, and a `bool` indicating whether the field is a
/// variable (as opposed to a function).
fields: Mapping<StrRef, (Type, bool)>, fields: Mapping<StrRef, (Type, bool)>,
/// Mapping between the ID of type variables and the [Type] representing the type variables
/// of this object type.
params: VarMap, params: VarMap,
}, },
TVirtual { TVirtual {
ty: Type, ty: Type,
}, },
TCall(Vec<CallId>), TCall(Vec<CallId>),
/// A function type.
TFunc(FunSignature), TFunc(FunSignature),
} }
@ -294,11 +317,16 @@ impl Unifier {
self.get_fresh_var_with_range(&[], None, None) self.get_fresh_var_with_range(&[], None, None)
} }
/// Returns a fresh [type variable][TypeEnum::TVar] with no associated range.
///
/// This type variable can be instantiated by any type.
pub fn get_fresh_var(&mut self, name: Option<StrRef>, loc: Option<Location>) -> (Type, u32) { pub fn get_fresh_var(&mut self, name: Option<StrRef>, loc: Option<Location>) -> (Type, u32) {
self.get_fresh_var_with_range(&[], name, loc) self.get_fresh_var_with_range(&[], name, loc)
} }
/// Get a fresh type variable. /// Returns a fresh [type variable][TypeEnum::TVar] with the range specified by `range`.
///
/// This type variable can be instantiated by any type present in `range`.
pub fn get_fresh_var_with_range( pub fn get_fresh_var_with_range(
&mut self, &mut self,
range: &[Type], range: &[Type],

View File

@ -41,10 +41,10 @@ def u64_max() -> uint64:
return ~uint64(0) return ~uint64(0)
def i64_min() -> int64: def i64_min() -> int64:
return int64(1) << int64(63) return int64(1) << 63
def i64_max() -> int64: def i64_max() -> int64:
return ~(int64(1) << int64(63)) return ~(int64(1) << 63)
def test_u32_bnot(): def test_u32_bnot():
output_uint32(~uint32(0)) output_uint32(~uint32(0))

View File

@ -37,7 +37,9 @@ def test_int32():
output_int32(a ^ b) output_int32(a ^ b)
output_int32(a & b) output_int32(a & b)
output_int32(a << b) output_int32(a << b)
output_int32(a << uint32(b))
output_int32(a >> b) output_int32(a >> b)
output_int32(a >> uint32(b))
output_float64(a / b) output_float64(a / b)
a += b a += b
output_int32(a) output_int32(a)
@ -74,7 +76,9 @@ def test_uint32():
output_uint32(a ^ b) output_uint32(a ^ b)
output_uint32(a & b) output_uint32(a & b)
output_uint32(a << b) output_uint32(a << b)
output_uint32(a << int32(b))
output_uint32(a >> b) output_uint32(a >> b)
output_uint32(a >> int32(b))
output_float64(a / b) output_float64(a / b)
a += b a += b
output_uint32(a) output_uint32(a)
@ -108,8 +112,10 @@ def test_int64():
output_int64(a | b) output_int64(a | b)
output_int64(a ^ b) output_int64(a ^ b)
output_int64(a & b) output_int64(a & b)
output_int64(a << b) output_int64(a << int32(b))
output_int64(a >> b) output_int64(a << uint32(b))
output_int64(a >> int32(b))
output_int64(a >> uint32(b))
output_float64(a / b) output_float64(a / b)
a += b a += b
output_int64(a) output_int64(a)
@ -127,9 +133,9 @@ def test_int64():
output_int64(a) output_int64(a)
a &= b a &= b
output_int64(a) output_int64(a)
a <<= b a <<= int32(b)
output_int64(a) output_int64(a)
a >>= b a >>= int32(b)
output_int64(a) output_int64(a)
def test_uint64(): def test_uint64():
@ -143,8 +149,8 @@ def test_uint64():
output_uint64(a | b) output_uint64(a | b)
output_uint64(a ^ b) output_uint64(a ^ b)
output_uint64(a & b) output_uint64(a & b)
output_uint64(a << b) output_uint64(a << uint32(b))
output_uint64(a >> b) output_uint64(a >> uint32(b))
output_float64(a / b) output_float64(a / b)
a += b a += b
output_uint64(a) output_uint64(a)
@ -162,9 +168,9 @@ def test_uint64():
output_uint64(a) output_uint64(a)
a &= b a &= b
output_uint64(a) output_uint64(a)
a <<= b a <<= uint32(b)
output_uint64(a) output_uint64(a)
a >>= b a >>= uint32(b)
output_uint64(a) output_uint64(a)
class A: class A: