mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 21:01:10 +00:00
Merge pull request #203 from GreasySlug/fix/floordiv
[WIP] Implement floordiv operator
This commit is contained in:
commit
fe1fd686d8
8 changed files with 107 additions and 13 deletions
|
@ -33,6 +33,7 @@ pub enum Opcode {
|
|||
BINARY_ADD = 23,
|
||||
BINARY_SUBTRACT = 24,
|
||||
BINARY_SUBSCR = 25,
|
||||
BINARY_FLOOR_DIVIDE = 26,
|
||||
BINARY_TRUE_DIVIDE = 27,
|
||||
INPLACE_FLOOR_DIVIDE = 28,
|
||||
INPLACE_TRUE_DIVIDE = 29,
|
||||
|
@ -183,6 +184,7 @@ impl From<u8> for Opcode {
|
|||
23 => BINARY_ADD,
|
||||
24 => BINARY_SUBTRACT,
|
||||
25 => BINARY_SUBSCR,
|
||||
26 => BINARY_FLOOR_DIVIDE,
|
||||
27 => BINARY_TRUE_DIVIDE,
|
||||
28 => INPLACE_FLOOR_DIVIDE,
|
||||
29 => INPLACE_TRUE_DIVIDE,
|
||||
|
|
|
@ -1163,6 +1163,7 @@ impl CodeGenerator {
|
|||
TokenKind::Minus => BINARY_SUBTRACT,
|
||||
TokenKind::Star => BINARY_MULTIPLY,
|
||||
TokenKind::Slash => BINARY_TRUE_DIVIDE,
|
||||
TokenKind::FloorDiv => BINARY_FLOOR_DIVIDE,
|
||||
TokenKind::Pow => BINARY_POWER,
|
||||
TokenKind::Mod => BINARY_MODULO,
|
||||
TokenKind::AndOp => BINARY_AND,
|
||||
|
|
|
@ -52,6 +52,7 @@ fn try_get_op_kind_from_token(kind: TokenKind) -> EvalResult<OpKind> {
|
|||
TokenKind::Minus => Ok(OpKind::Sub),
|
||||
TokenKind::Star => Ok(OpKind::Mul),
|
||||
TokenKind::Slash => Ok(OpKind::Div),
|
||||
TokenKind::FloorDiv => Ok(OpKind::FloorDiv),
|
||||
TokenKind::Pow => Ok(OpKind::Pow),
|
||||
TokenKind::Mod => Ok(OpKind::Mod),
|
||||
TokenKind::DblEq => Ok(OpKind::Eq),
|
||||
|
@ -78,6 +79,7 @@ fn op_to_name(op: OpKind) -> &'static str {
|
|||
OpKind::Sub => "__sub__",
|
||||
OpKind::Mul => "__mul__",
|
||||
OpKind::Div => "__div__",
|
||||
OpKind::FloorDiv => "__floordiv__",
|
||||
OpKind::Mod => "__mod__",
|
||||
OpKind::Pow => "__pow__",
|
||||
OpKind::Pos => "__pos__",
|
||||
|
@ -664,6 +666,13 @@ impl Context {
|
|||
line!(),
|
||||
))
|
||||
}),
|
||||
FloorDiv => lhs.try_floordiv(rhs).ok_or_else(|| {
|
||||
EvalErrors::from(EvalError::unreachable(
|
||||
self.cfg.input.clone(),
|
||||
fn_name!(),
|
||||
line!(),
|
||||
))
|
||||
}),
|
||||
Gt => lhs.try_gt(rhs).ok_or_else(|| {
|
||||
EvalErrors::from(EvalError::unreachable(
|
||||
self.cfg.input.clone(),
|
||||
|
|
|
@ -394,13 +394,25 @@ impl Context {
|
|||
mul.register_builtin_decl("__mul__", op_t, Public);
|
||||
mul.register_builtin_decl("Output", Type, Public);
|
||||
/* Div */
|
||||
let mut div = Self::builtin_poly_trait("Div", params, 2);
|
||||
let mut div = Self::builtin_poly_trait("Div", params.clone(), 2);
|
||||
div.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output);
|
||||
let op_t = fn1_met(mono_q("Self"), r, mono_proj(mono_q("Self"), "Output"));
|
||||
let op_t = fn1_met(
|
||||
mono_q("Self"),
|
||||
r.clone(),
|
||||
mono_proj(mono_q("Self"), "Output"),
|
||||
);
|
||||
let self_bound = subtypeof(mono_q("Self"), builtin_poly("Div", ty_params.clone()));
|
||||
let op_t = quant(op_t, set! {r_bound, self_bound});
|
||||
let op_t = quant(op_t, set! {r_bound.clone(), self_bound});
|
||||
div.register_builtin_decl("__div__", op_t, Public);
|
||||
div.register_builtin_decl("Output", Type, Public);
|
||||
/* FloorDiv */
|
||||
let mut floor_div = Self::builtin_poly_trait("FloorDiv", params, 2);
|
||||
floor_div.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output);
|
||||
let op_t = fn1_met(mono_q("Self"), r, mono_proj(mono_q("Self"), "Output"));
|
||||
let self_bound = subtypeof(mono_q("Self"), builtin_poly("FloorDiv", ty_params.clone()));
|
||||
let op_t = quant(op_t, set! {r_bound, self_bound});
|
||||
floor_div.register_builtin_decl("__floordiv__", op_t, Public);
|
||||
floor_div.register_builtin_decl("Output", Type, Public);
|
||||
self.register_builtin_type(builtin_mono("Unpack"), unpack, Const);
|
||||
self.register_builtin_type(builtin_mono("InheritableType"), inheritable_type, Const);
|
||||
self.register_builtin_type(builtin_mono("Named"), named, Const);
|
||||
|
@ -433,7 +445,8 @@ impl Context {
|
|||
self.register_builtin_type(builtin_poly("Add", ty_params.clone()), add, Const);
|
||||
self.register_builtin_type(builtin_poly("Sub", ty_params.clone()), sub, Const);
|
||||
self.register_builtin_type(builtin_poly("Mul", ty_params.clone()), mul, Const);
|
||||
self.register_builtin_type(builtin_poly("Div", ty_params), div, Const);
|
||||
self.register_builtin_type(builtin_poly("Div", ty_params.clone()), div, Const);
|
||||
self.register_builtin_type(builtin_poly("FloorDiv", ty_params), floor_div, Const);
|
||||
self.register_const_param_defaults(
|
||||
"Eq",
|
||||
vec![ConstTemplate::Obj(ValueObj::builtin_t(mono_q("Self")))],
|
||||
|
@ -458,6 +471,10 @@ impl Context {
|
|||
"Div",
|
||||
vec![ConstTemplate::Obj(ValueObj::builtin_t(mono_q("Self")))],
|
||||
);
|
||||
self.register_const_param_defaults(
|
||||
"FloorDiv",
|
||||
vec![ConstTemplate::Obj(ValueObj::builtin_t(mono_q("Self")))],
|
||||
);
|
||||
}
|
||||
|
||||
fn init_builtin_classes(&mut self) {
|
||||
|
@ -522,10 +539,18 @@ impl Context {
|
|||
float_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Float));
|
||||
float.register_trait(Float, builtin_poly("Mul", vec![ty_tp(Float)]), float_mul);
|
||||
let mut float_div = Self::builtin_methods("Div", 2);
|
||||
float_div.register_builtin_impl("__div__", op_t, Const, Public);
|
||||
float_div.register_builtin_impl("__div__", op_t.clone(), Const, Public);
|
||||
float_div.register_builtin_const("Output", ValueObj::builtin_t(Float));
|
||||
float_div.register_builtin_const("ModOutput", ValueObj::builtin_t(Float));
|
||||
float.register_trait(Float, builtin_poly("Div", vec![ty_tp(Float)]), float_div);
|
||||
let mut float_floordiv = Self::builtin_methods("FloorDiv", 2);
|
||||
float_floordiv.register_builtin_impl("__floordiv__", op_t, Const, Public);
|
||||
float_floordiv.register_builtin_const("Output", ValueObj::builtin_t(Float));
|
||||
float.register_trait(
|
||||
Float,
|
||||
builtin_poly("FloorDiv", vec![ty_tp(Float)]),
|
||||
float_floordiv,
|
||||
);
|
||||
let mut float_mutizable = Self::builtin_methods("Mutizable", 2);
|
||||
float_mutizable
|
||||
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Float!")));
|
||||
|
@ -573,10 +598,18 @@ impl Context {
|
|||
ratio_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Ratio));
|
||||
ratio.register_trait(Ratio, builtin_poly("Mul", vec![ty_tp(Ratio)]), ratio_mul);
|
||||
let mut ratio_div = Self::builtin_methods("Div", 2);
|
||||
ratio_div.register_builtin_impl("__div__", op_t, Const, Public);
|
||||
ratio_div.register_builtin_impl("__div__", op_t.clone(), Const, Public);
|
||||
ratio_div.register_builtin_const("Output", ValueObj::builtin_t(Ratio));
|
||||
ratio_div.register_builtin_const("ModOutput", ValueObj::builtin_t(Ratio));
|
||||
ratio.register_trait(Ratio, builtin_poly("Div", vec![ty_tp(Ratio)]), ratio_div);
|
||||
let mut ratio_floordiv = Self::builtin_methods("FloorDiv", 2);
|
||||
ratio_floordiv.register_builtin_impl("__floordiv__", op_t, Const, Public);
|
||||
ratio_floordiv.register_builtin_const("Output", ValueObj::builtin_t(Ratio));
|
||||
ratio.register_trait(
|
||||
Ratio,
|
||||
builtin_poly("FloorDiv", vec![ty_tp(Ratio)]),
|
||||
ratio_floordiv,
|
||||
);
|
||||
let mut ratio_mutizable = Self::builtin_methods("Mutizable", 2);
|
||||
ratio_mutizable
|
||||
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Ratio!")));
|
||||
|
@ -621,10 +654,18 @@ impl Context {
|
|||
int_sub.register_builtin_const("Output", ValueObj::builtin_t(Int));
|
||||
int.register_trait(Int, builtin_poly("Sub", vec![ty_tp(Int)]), int_sub);
|
||||
let mut int_mul = Self::builtin_methods("Mul", 2);
|
||||
int_mul.register_builtin_impl("__mul__", op_t, Const, Public);
|
||||
int_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public);
|
||||
int_mul.register_builtin_const("Output", ValueObj::builtin_t(Int));
|
||||
int_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Nat));
|
||||
int.register_trait(Int, builtin_poly("Mul", vec![ty_tp(Int)]), int_mul);
|
||||
let mut int_floordiv = Self::builtin_methods("FloorDiv", 2);
|
||||
int_floordiv.register_builtin_impl("__floordiv__", op_t, Const, Public);
|
||||
int_floordiv.register_builtin_const("Output", ValueObj::builtin_t(Int));
|
||||
int.register_trait(
|
||||
Int,
|
||||
builtin_poly("FloorDiv", vec![ty_tp(Int)]),
|
||||
int_floordiv,
|
||||
);
|
||||
let mut int_mutizable = Self::builtin_methods("Mutizable", 2);
|
||||
int_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Int!")));
|
||||
int.register_trait(Int, builtin_mono("Mutizable"), int_mutizable);
|
||||
|
@ -676,9 +717,17 @@ impl Context {
|
|||
nat_add.register_builtin_const("Output", ValueObj::builtin_t(Nat));
|
||||
nat.register_trait(Nat, builtin_poly("Add", vec![ty_tp(Nat)]), nat_add);
|
||||
let mut nat_mul = Self::builtin_methods("Mul", 2);
|
||||
nat_mul.register_builtin_impl("__mul__", op_t, Const, Public);
|
||||
nat_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public);
|
||||
nat_mul.register_builtin_const("Output", ValueObj::builtin_t(Nat));
|
||||
nat.register_trait(Nat, builtin_poly("Mul", vec![ty_tp(Nat)]), nat_mul);
|
||||
let mut nat_floordiv = Self::builtin_methods("FloorDiv", 2);
|
||||
nat_floordiv.register_builtin_impl("__floordiv__", op_t, Const, Public);
|
||||
nat_floordiv.register_builtin_const("Output", ValueObj::builtin_t(Nat));
|
||||
nat.register_trait(
|
||||
Nat,
|
||||
builtin_poly("FloorDiv", vec![ty_tp(Nat)]),
|
||||
nat_floordiv,
|
||||
);
|
||||
let mut nat_mutizable = Self::builtin_methods("Mutizable", 2);
|
||||
nat_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Nat!")));
|
||||
nat.register_trait(Nat, builtin_mono("Mutizable"), nat_mutizable);
|
||||
|
@ -710,10 +759,6 @@ impl Context {
|
|||
let mut bool_eq = Self::builtin_methods("Eq", 2);
|
||||
bool_eq.register_builtin_impl("__eq__", fn1_met(Bool, Bool, Bool), Const, Public);
|
||||
bool_.register_trait(Bool, builtin_poly("Eq", vec![ty_tp(Bool)]), bool_eq);
|
||||
let mut bool_add = Self::builtin_methods("Add", 2);
|
||||
bool_add.register_builtin_impl("__add__", fn1_met(Bool, Bool, Int), Const, Public);
|
||||
bool_add.register_builtin_const("Output", ValueObj::builtin_t(Nat));
|
||||
bool_.register_trait(Bool, builtin_poly("Add", vec![ty_tp(Bool)]), bool_add);
|
||||
let mut bool_mutizable = Self::builtin_methods("Mutizable", 2);
|
||||
bool_mutizable
|
||||
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Bool!")));
|
||||
|
@ -1860,6 +1905,15 @@ impl Context {
|
|||
},
|
||||
);
|
||||
self.register_builtin_impl("__div__", op_t, Const, Private);
|
||||
let op_t = bin_op(l.clone(), r.clone(), mono_proj(mono_q("L"), "Output"));
|
||||
let op_t = quant(
|
||||
op_t,
|
||||
set! {
|
||||
static_instance("R", Type),
|
||||
subtypeof(l.clone(), builtin_poly("FloorDiv", params.clone()))
|
||||
},
|
||||
);
|
||||
self.register_builtin_impl("__floordiv__", op_t, Const, Private);
|
||||
let m = mono_q("M");
|
||||
let op_t = bin_op(m.clone(), m.clone(), mono_proj(m.clone(), "PowOutput"));
|
||||
let op_t = quant(op_t, set! {subtypeof(m, builtin_poly("Mul", vec![]))});
|
||||
|
|
|
@ -1381,7 +1381,7 @@ impl Context {
|
|||
.super_classes
|
||||
.iter()
|
||||
.chain(ctx.super_traits.iter())
|
||||
.map(|sup| self.get_nominal_type_ctx(sup).unwrap());
|
||||
.map(|sup| self.get_nominal_type_ctx(sup).expect("compiler bug: sup not found"));
|
||||
Some(vec![ctx].into_iter().chain(sups))
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ pub fn binop_to_dname(op: &str) -> &str {
|
|||
"-" => "__sub__",
|
||||
"*" => "__mul__",
|
||||
"/" => "__div__",
|
||||
"//" => "__floordiv__",
|
||||
"**" => "__pow__",
|
||||
"%" => "__mod__",
|
||||
".." => "__rng__",
|
||||
|
@ -66,6 +67,7 @@ pub fn readable_name(name: &str) -> &str {
|
|||
"__sub__" => "`-`",
|
||||
"__mul__" => "`*`",
|
||||
"__div__" => "`/`",
|
||||
"__floordiv__" => "`//`",
|
||||
"__pow__" => "`**`",
|
||||
"__mod__" => "`%`",
|
||||
"__rng__" => "`..`",
|
||||
|
|
|
@ -17,6 +17,7 @@ pub enum OpKind {
|
|||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
FloorDiv,
|
||||
Pow,
|
||||
Mod,
|
||||
Pos,
|
||||
|
@ -45,6 +46,7 @@ impl fmt::Display for OpKind {
|
|||
Self::Sub => write!(f, "-"),
|
||||
Self::Mul => write!(f, "*"),
|
||||
Self::Div => write!(f, "/"),
|
||||
Self::FloorDiv => write!(f, "//"),
|
||||
Self::Pow => write!(f, "**"),
|
||||
Self::Mod => write!(f, "%"),
|
||||
Self::Pos => write!(f, "+"),
|
||||
|
|
|
@ -686,6 +686,30 @@ impl ValueObj {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn try_floordiv(self, other: Self) -> Option<Self> {
|
||||
match (self, other) {
|
||||
(Self::Int(l), Self::Int(r)) => Some(Self::Int(l / r)),
|
||||
(Self::Nat(l), Self::Nat(r)) => Some(Self::Nat(l / r)),
|
||||
(Self::Float(l), Self::Float(r)) => Some(Self::Float((l / r).floor())),
|
||||
(Self::Int(l), Self::Nat(r)) => Some(Self::Int(l / r as i32)),
|
||||
(Self::Nat(l), Self::Int(r)) => Some(Self::Int(l as i32 / r)),
|
||||
(Self::Float(l), Self::Nat(r)) => Some(Self::Float((l / r as f64).floor())),
|
||||
(Self::Nat(l), Self::Float(r)) => Some(Self::Float((l as f64 / r).floor())),
|
||||
(Self::Float(l), Self::Int(r)) => Some(Self::Float((l / r as f64).floor())),
|
||||
(Self::Int(l), Self::Float(r)) => Some(Self::Float((l as f64 / r).floor())),
|
||||
(Self::Mut(m), other) => {
|
||||
{
|
||||
let ref_m = &mut *m.borrow_mut();
|
||||
*ref_m = mem::take(ref_m).try_div(other)?;
|
||||
}
|
||||
Some(Self::Mut(m))
|
||||
}
|
||||
(self_, Self::Mut(m)) => self_.try_floordiv(m.borrow().clone()),
|
||||
// TODO: x//±Inf = 0
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_gt(self, other: Self) -> Option<Self> {
|
||||
match (self, other) {
|
||||
(Self::Int(l), Self::Int(r)) => Some(Self::from(l > r)),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue