2021-08-02 17:36:37 +08:00
|
|
|
use std::borrow::Borrow;
|
2021-08-02 11:28:05 +08:00
|
|
|
use std::collections::HashMap;
|
2021-06-28 10:49:41 +08:00
|
|
|
use rustpython_parser::ast::{Cmpop, Operator, Unaryop};
|
2021-01-04 14:53:52 +08:00
|
|
|
|
|
|
|
pub fn binop_name(op: &Operator) -> &'static str {
|
|
|
|
match op {
|
|
|
|
Operator::Add => "__add__",
|
|
|
|
Operator::Sub => "__sub__",
|
|
|
|
Operator::Div => "__truediv__",
|
|
|
|
Operator::Mod => "__mod__",
|
|
|
|
Operator::Mult => "__mul__",
|
|
|
|
Operator::Pow => "__pow__",
|
|
|
|
Operator::BitOr => "__or__",
|
|
|
|
Operator::BitXor => "__xor__",
|
|
|
|
Operator::BitAnd => "__and__",
|
|
|
|
Operator::LShift => "__lshift__",
|
|
|
|
Operator::RShift => "__rshift__",
|
|
|
|
Operator::FloorDiv => "__floordiv__",
|
|
|
|
Operator::MatMult => "__matmul__",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn binop_assign_name(op: &Operator) -> &'static str {
|
|
|
|
match op {
|
|
|
|
Operator::Add => "__iadd__",
|
|
|
|
Operator::Sub => "__isub__",
|
|
|
|
Operator::Div => "__itruediv__",
|
|
|
|
Operator::Mod => "__imod__",
|
|
|
|
Operator::Mult => "__imul__",
|
|
|
|
Operator::Pow => "__ipow__",
|
|
|
|
Operator::BitOr => "__ior__",
|
|
|
|
Operator::BitXor => "__ixor__",
|
|
|
|
Operator::BitAnd => "__iand__",
|
|
|
|
Operator::LShift => "__ilshift__",
|
|
|
|
Operator::RShift => "__irshift__",
|
|
|
|
Operator::FloorDiv => "__ifloordiv__",
|
|
|
|
Operator::MatMult => "__imatmul__",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-28 10:49:41 +08:00
|
|
|
pub fn unaryop_name(op: &Unaryop) -> &'static str {
|
2021-01-04 14:53:52 +08:00
|
|
|
match op {
|
2021-06-28 10:49:41 +08:00
|
|
|
Unaryop::UAdd => "__pos__",
|
|
|
|
Unaryop::USub => "__neg__",
|
|
|
|
Unaryop::Not => "__not__",
|
|
|
|
Unaryop::Invert => "__inv__",
|
2021-01-04 14:53:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-28 10:49:41 +08:00
|
|
|
pub fn comparison_name(op: &Cmpop) -> Option<&'static str> {
|
2021-01-04 14:53:52 +08:00
|
|
|
match op {
|
2021-06-28 10:49:41 +08:00
|
|
|
Cmpop::Lt => Some("__lt__"),
|
|
|
|
Cmpop::LtE => Some("__le__"),
|
|
|
|
Cmpop::Gt => Some("__gt__"),
|
|
|
|
Cmpop::GtE => Some("__ge__"),
|
|
|
|
Cmpop::Eq => Some("__eq__"),
|
|
|
|
Cmpop::NotEq => Some("__ne__"),
|
2021-01-04 14:53:52 +08:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2021-07-30 15:40:14 +08:00
|
|
|
|
2021-08-02 11:28:05 +08:00
|
|
|
use crate::typecheck::{type_inferencer::*, typedef::{FunSignature, FuncArg, TypeEnum, Unifier, Type}};
|
2021-07-30 15:40:14 +08:00
|
|
|
use rustpython_parser::ast;
|
2021-08-02 11:28:05 +08:00
|
|
|
|
|
|
|
/// Add, Sub, Mult, Pow
|
|
|
|
pub fn impl_basic_arithmetic(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type, other_ty: Type, ret_ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
2021-07-30 15:40:14 +08:00
|
|
|
for op in &[
|
2021-08-02 11:28:05 +08:00
|
|
|
ast::Operator::Add,
|
|
|
|
ast::Operator::Sub,
|
|
|
|
ast::Operator::Mult,
|
|
|
|
ast::Operator::Pow,
|
2021-07-30 15:40:14 +08:00
|
|
|
] {
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_name(op).into(),
|
2021-07-30 15:40:14 +08:00
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
2021-08-02 11:28:05 +08:00
|
|
|
ret: ret_ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
2021-08-02 11:28:05 +08:00
|
|
|
ty: other_ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_assign_name(op).into(),
|
2021-07-30 15:40:14 +08:00
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
2021-08-02 11:28:05 +08:00
|
|
|
ret: store.none,
|
2021-07-30 15:40:14 +08:00
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
2021-08-02 11:28:05 +08:00
|
|
|
ty: other_ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
2021-08-02 11:28:05 +08:00
|
|
|
}]
|
2021-07-30 15:40:14 +08:00
|
|
|
}))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else { unreachable!() }
|
2021-08-02 11:28:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// LShift, RShift, BitOr, BitXor, BitAnd
|
|
|
|
pub fn impl_bitwise_arithmetic(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
2021-07-30 15:40:14 +08:00
|
|
|
for op in &[
|
2021-08-02 11:28:05 +08:00
|
|
|
ast::Operator::LShift,
|
|
|
|
ast::Operator::RShift,
|
|
|
|
ast::Operator::BitOr,
|
|
|
|
ast::Operator::BitXor,
|
|
|
|
ast::Operator::BitAnd,
|
2021-07-30 15:40:14 +08:00
|
|
|
] {
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_name(op).into(),
|
2021-07-30 15:40:14 +08:00
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
2021-08-02 11:28:05 +08:00
|
|
|
ret: ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
2021-08-02 11:28:05 +08:00
|
|
|
ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
is_optional: false,
|
2021-08-02 11:28:05 +08:00
|
|
|
name: "other".into()
|
|
|
|
}]
|
2021-07-30 15:40:14 +08:00
|
|
|
}))
|
|
|
|
);
|
|
|
|
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_assign_name(op).into(),
|
2021-07-30 15:40:14 +08:00
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
|
|
|
ret: store.none,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
2021-08-02 11:28:05 +08:00
|
|
|
ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
2021-08-02 11:28:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Div
|
|
|
|
pub fn impl_div(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type, other_ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_name(&ast::Operator::Div).into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature{
|
2021-07-30 15:40:14 +08:00
|
|
|
ret: store.float,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
2021-08-02 11:28:05 +08:00
|
|
|
ty: other_ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_assign_name(&ast::Operator::Div).into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature{
|
|
|
|
ret: store.none,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
|
|
|
ty: other_ty,
|
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
} else { unreachable!() }
|
|
|
|
}
|
2021-07-30 15:40:14 +08:00
|
|
|
|
2021-08-02 11:28:05 +08:00
|
|
|
/// FloorDiv
|
|
|
|
pub fn impl_floordiv(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type, other_ty: Type, ret_ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_name(&ast::Operator::FloorDiv).into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature{
|
|
|
|
ret: ret_ty,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
|
|
|
ty: other_ty,
|
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_assign_name(&ast::Operator::FloorDiv).into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature{
|
|
|
|
ret: store.none,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
|
|
|
ty: other_ty,
|
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
2021-07-30 15:40:14 +08:00
|
|
|
} else { unreachable!() }
|
2021-08-02 11:28:05 +08:00
|
|
|
}
|
2021-07-30 15:40:14 +08:00
|
|
|
|
2021-08-02 11:28:05 +08:00
|
|
|
/// Mod
|
|
|
|
pub fn impl_mod(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type, other_ty: Type, ret_ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_name(&ast::Operator::Mod).into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
|
|
|
ret: ret_ty,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
|
|
|
ty: other_ty,
|
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
2021-07-30 15:40:14 +08:00
|
|
|
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
binop_assign_name(&ast::Operator::Mod).into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
|
|
|
ret: store.none,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
|
|
|
ty: other_ty,
|
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
} else { unreachable!() }
|
|
|
|
}
|
2021-07-30 15:40:14 +08:00
|
|
|
|
2021-08-02 11:28:05 +08:00
|
|
|
/// UAdd, USub
|
|
|
|
pub fn impl_unary_op(unifier: &mut Unifier, _store: &PrimitiveStore, ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
2021-07-30 15:40:14 +08:00
|
|
|
for op in &[
|
|
|
|
ast::Unaryop::UAdd,
|
2021-08-02 11:28:05 +08:00
|
|
|
ast::Unaryop::USub
|
2021-07-30 15:40:14 +08:00
|
|
|
] {
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-07-30 15:40:14 +08:00
|
|
|
unaryop_name(op).into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
2021-08-02 11:28:05 +08:00
|
|
|
ret: ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![]
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else { unreachable!() }
|
2021-08-02 11:28:05 +08:00
|
|
|
}
|
2021-07-30 15:40:14 +08:00
|
|
|
|
2021-08-02 11:28:05 +08:00
|
|
|
/// Invert
|
|
|
|
pub fn impl_invert(unifier: &mut Unifier, _store: &PrimitiveStore, ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
unaryop_name(&ast::Unaryop::Invert).into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
|
|
|
ret: ty,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![]
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-07-30 15:40:14 +08:00
|
|
|
|
2021-08-02 11:28:05 +08:00
|
|
|
/// Not
|
|
|
|
pub fn impl_not(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
unaryop_name(&ast::Unaryop::Not).into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
|
|
|
ret: store.bool,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![]
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
} else { unreachable!() }
|
|
|
|
}
|
2021-07-30 15:40:14 +08:00
|
|
|
|
2021-08-02 11:28:05 +08:00
|
|
|
/// Lt, LtE, Gt, GtE
|
|
|
|
pub fn impl_comparison(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type, other_ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
2021-08-02 11:28:05 +08:00
|
|
|
for op in &[
|
|
|
|
ast::Cmpop::Lt,
|
|
|
|
ast::Cmpop::LtE,
|
|
|
|
ast::Cmpop::Gt,
|
|
|
|
ast::Cmpop::GtE,
|
2021-07-30 15:40:14 +08:00
|
|
|
] {
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-08-02 11:28:05 +08:00
|
|
|
comparison_name(op).unwrap().into(),
|
2021-07-30 15:40:14 +08:00
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
|
|
|
ret: store.bool,
|
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
2021-08-02 11:28:05 +08:00
|
|
|
ty: other_ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
2021-08-02 11:28:05 +08:00
|
|
|
}
|
|
|
|
} else { unreachable!() }
|
|
|
|
}
|
2021-07-30 15:40:14 +08:00
|
|
|
|
2021-08-02 11:28:05 +08:00
|
|
|
/// Eq, NotEq
|
|
|
|
pub fn impl_eq(unifier: &mut Unifier, store: &PrimitiveStore, ty: Type) {
|
2021-08-02 17:36:37 +08:00
|
|
|
if let TypeEnum::TObj {fields, .. } = unifier.get_ty(ty).borrow() {
|
2021-07-30 15:40:14 +08:00
|
|
|
for op in &[
|
|
|
|
ast::Cmpop::Eq,
|
|
|
|
ast::Cmpop::NotEq,
|
|
|
|
] {
|
2021-08-02 17:36:37 +08:00
|
|
|
fields.borrow_mut().insert(
|
2021-07-30 15:40:14 +08:00
|
|
|
comparison_name(op).unwrap().into(),
|
|
|
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
2021-08-02 11:28:05 +08:00
|
|
|
ret: store.bool,
|
2021-07-30 15:40:14 +08:00
|
|
|
vars: HashMap::new(),
|
|
|
|
args: vec![FuncArg {
|
2021-08-02 11:28:05 +08:00
|
|
|
ty,
|
2021-07-30 15:40:14 +08:00
|
|
|
is_optional: false,
|
|
|
|
name: "other".into()
|
|
|
|
}]
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
}
|
2021-08-02 11:28:05 +08:00
|
|
|
} else { unreachable!() }
|
|
|
|
}
|
|
|
|
|
2021-08-04 12:03:56 +08:00
|
|
|
pub fn set_primitives_magic_methods(store: &PrimitiveStore, unifier: &mut Unifier) {
|
2021-08-02 11:28:05 +08:00
|
|
|
let PrimitiveStore {
|
|
|
|
int32: int32_t,
|
|
|
|
int64: int64_t,
|
|
|
|
float: float_t,
|
|
|
|
bool: bool_t,
|
2021-08-03 10:41:52 +08:00
|
|
|
..
|
2021-08-02 11:28:05 +08:00
|
|
|
} = *store;
|
2021-08-02 17:36:37 +08:00
|
|
|
/* int32 ======== */
|
2021-08-02 11:28:05 +08:00
|
|
|
impl_basic_arithmetic(unifier, store, int32_t, int32_t, int32_t);
|
|
|
|
impl_bitwise_arithmetic(unifier, store, int32_t);
|
|
|
|
impl_div(unifier, store, int32_t, int32_t);
|
|
|
|
impl_floordiv(unifier, store, int32_t, int32_t, int32_t);
|
|
|
|
impl_mod(unifier, store, int32_t, int32_t, int32_t);
|
|
|
|
impl_unary_op(unifier, store, int32_t);
|
|
|
|
impl_invert(unifier, store, int32_t);
|
|
|
|
impl_not(unifier, store, int32_t);
|
|
|
|
impl_comparison(unifier, store, int32_t, int32_t);
|
|
|
|
impl_eq(unifier, store, int32_t);
|
2021-08-02 17:36:37 +08:00
|
|
|
|
|
|
|
/* int64 ======== */
|
2021-08-02 11:28:05 +08:00
|
|
|
impl_basic_arithmetic(unifier, store, int64_t, int64_t, int64_t);
|
|
|
|
impl_bitwise_arithmetic(unifier, store, int64_t);
|
|
|
|
impl_div(unifier, store, int64_t, int64_t);
|
|
|
|
impl_floordiv(unifier, store, int64_t, int64_t, int64_t);
|
|
|
|
impl_mod(unifier, store, int64_t, int64_t, int64_t);
|
|
|
|
impl_unary_op(unifier, store, int64_t);
|
|
|
|
impl_invert(unifier, store, int64_t);
|
|
|
|
impl_not(unifier, store, int64_t);
|
|
|
|
impl_comparison(unifier, store, int64_t, int64_t);
|
|
|
|
impl_eq(unifier, store, int64_t);
|
2021-08-02 17:36:37 +08:00
|
|
|
|
|
|
|
/* float ======== */
|
2021-08-02 11:28:05 +08:00
|
|
|
impl_basic_arithmetic(unifier, store, float_t, float_t, float_t);
|
|
|
|
impl_div(unifier, store, float_t, float_t);
|
|
|
|
impl_floordiv(unifier, store, float_t, float_t, float_t);
|
|
|
|
impl_mod(unifier, store, float_t, float_t, float_t);
|
|
|
|
impl_unary_op(unifier, store, float_t);
|
|
|
|
impl_not(unifier, store, float_t);
|
|
|
|
impl_comparison(unifier, store, float_t, float_t);
|
|
|
|
impl_eq(unifier, store, float_t);
|
2021-08-02 17:36:37 +08:00
|
|
|
|
|
|
|
/* bool ======== */
|
2021-08-02 11:28:05 +08:00
|
|
|
impl_not(unifier, store, bool_t);
|
|
|
|
impl_eq(unifier, store, bool_t);
|
2021-07-30 15:40:14 +08:00
|
|
|
}
|