nac3_sca/nac3core/src/typecheck/magic_methods.rs

422 lines
13 KiB
Rust

use std::{collections::HashMap, rc::Rc};
use rustpython_parser::ast::{Cmpop, Operator, Unaryop};
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__",
}
}
pub fn unaryop_name(op: &Unaryop) -> &'static str {
match op {
Unaryop::UAdd => "__pos__",
Unaryop::USub => "__neg__",
Unaryop::Not => "__not__",
Unaryop::Invert => "__inv__",
}
}
pub fn comparison_name(op: &Cmpop) -> Option<&'static str> {
match op {
Cmpop::Lt => Some("__lt__"),
Cmpop::LtE => Some("__le__"),
Cmpop::Gt => Some("__gt__"),
Cmpop::GtE => Some("__ge__"),
Cmpop::Eq => Some("__eq__"),
Cmpop::NotEq => Some("__ne__"),
_ => None,
}
}
use crate::typecheck::{type_inferencer::*, typedef::{FunSignature, FuncArg, TypeEnum, Unifier}};
use rustpython_parser::ast;
pub fn set_primirives_magic_methods(store: &PrimitiveStore, unifier: &mut Unifier) {
// int32 --------
if let Some(TypeEnum::TObj {fields, .. }) = Rc::get_mut(&mut unifier.get_ty(store.int32)) {
for op in &[
ast::Operator::Add,
ast::Operator::Sub,
ast::Operator::Mult,
ast::Operator::Mod,
ast::Operator::Pow,
ast::Operator::LShift,
ast::Operator::RShift,
ast::Operator::BitOr,
ast::Operator::BitXor,
ast::Operator::BitAnd,
ast::Operator::FloorDiv
] {
fields.insert(
binop_name(op).to_string(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.int32,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int32,
is_optional: false,
name: "other".into() // the name does not matter here
}],
}))
);
fields.insert(
binop_assign_name(op).to_string(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.none,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int32,
is_optional: false,
name: "other".into()
}]
}))
);
};
// int div int gets float
fields.insert(
binop_assign_name(&ast::Operator::Div).into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.float,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int32,
is_optional: false,
name: "other".into()
}]
}))
);
for op in &[
ast::Cmpop::Eq,
ast::Cmpop::NotEq,
ast::Cmpop::Lt,
ast::Cmpop::LtE,
ast::Cmpop::Gt,
ast::Cmpop::GtE,
] {
fields.insert(
comparison_name(op).unwrap().to_string(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.bool,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int32,
is_optional: false,
name: "other".into()
}],
}))
);
}
for op in &[
ast::Unaryop::UAdd,
ast::Unaryop::USub,
ast::Unaryop::Not,
ast::Unaryop::Invert,
] {
fields.insert(
unaryop_name(op).into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.int32,
vars: HashMap::new(),
args: vec![]
}))
);
}
} else { unreachable!() }
// int32 --------
// int64 --------
if let Some(TypeEnum::TObj {fields, .. }) = Rc::get_mut(&mut unifier.get_ty(store.int64)) {
for op in &[
ast::Operator::Add,
ast::Operator::Sub,
ast::Operator::Mult,
ast::Operator::Mod,
ast::Operator::Pow,
ast::Operator::LShift,
ast::Operator::RShift,
ast::Operator::BitOr,
ast::Operator::BitXor,
ast::Operator::BitAnd,
ast::Operator::FloorDiv
] {
fields.insert(
binop_name(op).to_string(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.int64,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int64,
is_optional: false,
name: "other".into() // the name does not matter here
}],
}))
);
fields.insert(
binop_assign_name(op).to_string(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.none,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int64,
is_optional: false,
name: "other".into()
}]
}))
);
};
fields.insert(
binop_assign_name(&ast::Operator::Div).into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.float,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int64,
is_optional: false,
name: "other".into()
}]
}))
);
for op in &[
ast::Cmpop::Eq,
ast::Cmpop::NotEq,
ast::Cmpop::Lt,
ast::Cmpop::LtE,
ast::Cmpop::Gt,
ast::Cmpop::GtE,
] {
fields.insert(
comparison_name(op).unwrap().to_string(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.bool,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int64,
is_optional: false,
name: "other".into()
}],
}))
);
}
for op in &[
ast::Unaryop::UAdd,
ast::Unaryop::USub,
ast::Unaryop::Not,
ast::Unaryop::Invert,
] {
fields.insert(
unaryop_name(op).into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.int64,
vars: HashMap::new(),
args: vec![]
}))
);
}
} else { unreachable!() }
// int64 --------
// float --------
if let Some(TypeEnum::TObj {fields, .. }) = Rc::get_mut(&mut unifier.get_ty(store.float)) {
for op in &[
ast::Operator::Add,
ast::Operator::Sub,
ast::Operator::Mult,
ast::Operator::Div,
ast::Operator::Mod,
ast::Operator::Pow,
ast::Operator::FloorDiv,
] {
fields.insert(
binop_name(op).to_string(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.float,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.float,
is_optional: false,
name: "other".into() // the name does not matter here
}],
}))
);
fields.insert(
binop_assign_name(op).to_string(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.none,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.float,
is_optional: false,
name: "other".into()
}]
}))
);
};
for op in &[
ast::Cmpop::Eq,
ast::Cmpop::NotEq,
ast::Cmpop::Lt,
ast::Cmpop::LtE,
ast::Cmpop::Gt,
ast::Cmpop::GtE,
] {
fields.insert(
comparison_name(op).unwrap().to_string(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.bool,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.float,
is_optional: false,
name: "other".into()
}],
}))
);
}
for op in &[
ast::Unaryop::UAdd,
ast::Unaryop::USub,
ast::Unaryop::Not,
] {
fields.insert(
unaryop_name(op).into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.int64,
vars: HashMap::new(),
args: vec![]
}))
);
}
} else { unreachable!() }
// float --------
// bool ---------
if let Some(TypeEnum::TObj {fields, .. }) = Rc::get_mut(&mut unifier.get_ty(store.bool)) {
for op in &[
ast::Operator::Add,
ast::Operator::Sub,
ast::Operator::Mult,
ast::Operator::Mod,
ast::Operator::Pow,
ast::Operator::LShift,
ast::Operator::RShift,
ast::Operator::FloorDiv
] {
fields.insert(
binop_name(op).into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.int32,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.bool,
is_optional: false,
name: "other".into()
}]
}))
);
fields.insert(
binop_name(op).into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.int32,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int32,
is_optional: false,
name: "other".into()
}]
}))
);
// binop_assignment will change type?
/* fields.insert(
binop_assignment_name(op).into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.none,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.bool,
is_optional: false,
name: "other".into()
}]
}))
); */
};
for op in &[
ast::Operator::BitOr,
ast::Operator::BitXor,
ast::Operator::BitAnd
] {
fields.insert(
binop_name(op).into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.bool,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.int32,
is_optional: false,
name: "other".into()
}]
}))
);
};
for op in &[
ast::Cmpop::Eq,
ast::Cmpop::NotEq,
ast::Cmpop::Lt,
ast::Cmpop::LtE,
ast::Cmpop::Gt,
ast::Cmpop::GtE,
] {
fields.insert(
comparison_name(op).unwrap().into(),
unifier.add_ty(TypeEnum::TFunc(FunSignature {
ret: store.int32,
vars: HashMap::new(),
args: vec![FuncArg {
ty: store.bool,
is_optional: false,
name: "other".into()
}]
}))
);
}
}
// bool --------
}