Skip to content

Commit

Permalink
fix: symop codegen bug
Browse files Browse the repository at this point in the history
  • Loading branch information
mtshiba committed Sep 9, 2023
1 parent 21cb0bb commit abb025a
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 22 deletions.
15 changes: 15 additions & 0 deletions crates/erg_compiler/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ pub struct PyCodeGenerator {
module_type_loaded: bool,
control_loaded: bool,
convertors_loaded: bool,
operators_loaded: bool,
abc_loaded: bool,
unit_size: usize,
units: PyCodeGenStack,
Expand All @@ -202,6 +203,7 @@ impl PyCodeGenerator {
module_type_loaded: false,
control_loaded: false,
convertors_loaded: false,
operators_loaded: false,
abc_loaded: false,
unit_size: 0,
units: PyCodeGenStack::empty(),
Expand All @@ -221,6 +223,7 @@ impl PyCodeGenerator {
module_type_loaded: false,
control_loaded: false,
convertors_loaded: false,
operators_loaded: false,
abc_loaded: false,
unit_size: 0,
units: PyCodeGenStack::empty(),
Expand All @@ -240,6 +243,7 @@ impl PyCodeGenerator {
self.module_type_loaded = false;
self.control_loaded = false;
self.convertors_loaded = false;
self.operators_loaded = false;
self.abc_loaded = false;
}

Expand Down Expand Up @@ -729,6 +733,11 @@ impl PyCodeGenerator {
"int__" | "nat__" | "str__" | "float__" => {
self.load_convertors();
}
"add" | "sub" | "mul" | "truediv" | "floordiv" | "mod" | "pow" | "eq" | "ne" | "lt"
| "le" | "gt" | "ge" | "and_" | "or_" | "xor" | "lshift" | "rshift" | "pos" | "neg"
| "invert" | "is_" | "is_not" | "call" => {
self.load_operators();
}
// NoneType is not defined in the global scope, use `type(None)` instead
"NoneType" => {
self.emit_push_null();
Expand Down Expand Up @@ -3450,6 +3459,12 @@ impl PyCodeGenerator {
self.convertors_loaded = true;
}

fn load_operators(&mut self) {
let mod_name = Identifier::public("operator");
self.emit_import_all_instr(mod_name);
self.operators_loaded = true;
}

fn load_prelude_py(&mut self) {
self.emit_global_import_items(
Identifier::public("sys"),
Expand Down
201 changes: 180 additions & 21 deletions crates/erg_compiler/context/initialize/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,41 +664,119 @@ impl Context {
proj(L, OUTPUT),
)
.quantify();
self.register_builtin_erg_impl(OP_ADD, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_ADD,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("add"),
);
let L = mono_q(TY_L, subtypeof(poly(SUB, params.clone())));
let op_t = bin_op(L.clone(), R.clone(), proj(L, OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_SUB, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_SUB,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("sub"),
);
let L = mono_q(TY_L, subtypeof(poly(MUL, params.clone())));
let op_t = bin_op(L.clone(), R.clone(), proj(L, OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_MUL, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_MUL,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("mul"),
);
let L = mono_q(TY_L, subtypeof(poly(DIV, params.clone())));
let op_t = bin_op(L.clone(), R.clone(), proj(L, OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_DIV, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_DIV,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("truediv"),
);
let L = mono_q(TY_L, subtypeof(poly(FLOOR_DIV, params)));
let op_t = bin_op(L.clone(), R, proj(L, OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_FLOOR_DIV, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_FLOOR_DIV,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("floordiv"),
);
let P = mono_q(TY_P, Constraint::Uninited);
let P = mono_q(TY_P, subtypeof(poly(MUL, vec![ty_tp(P)])));
let op_t = bin_op(P.clone(), P.clone(), proj(P, POW_OUTPUT)).quantify();
// TODO: add bound: M == M.Output
self.register_builtin_erg_impl(OP_POW, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_POW,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("pow"),
);
let M = mono_q(TY_M, Constraint::Uninited);
let M = mono_q(TY_M, subtypeof(poly(DIV, vec![ty_tp(M)])));
let op_t = bin_op(M.clone(), M.clone(), proj(M, MOD_OUTPUT)).quantify();
self.register_builtin_erg_impl(OP_MOD, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_MOD,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("mod"),
);
let op_t = nd_proc(vec![kw(KW_LHS, Obj), kw(KW_RHS, Obj)], None, Bool);
self.register_builtin_erg_impl(OP_IS, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_IS_NOT, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_IS,
op_t.clone(),
Const,
Visibility::BUILTIN_PRIVATE,
Some("is_"),
);
self.register_builtin_py_impl(
OP_IS_NOT,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("is_not"),
);
let E = mono_q(TY_E, subtypeof(mono(EQ)));
let op_t = bin_op(E.clone(), E, Bool).quantify();
self.register_builtin_erg_impl(OP_EQ, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_NE, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_EQ,
op_t.clone(),
Const,
Visibility::BUILTIN_PRIVATE,
Some("eq"),
);
self.register_builtin_py_impl(OP_NE, op_t, Const, Visibility::BUILTIN_PRIVATE, Some("ne"));
let O = mono_q(TY_O, subtypeof(mono(PARTIAL_ORD)));
let op_t = bin_op(O.clone(), O.clone(), Bool).quantify();
self.register_builtin_erg_impl(OP_LT, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_LE, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_GT, op_t.clone(), Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_impl(OP_GE, op_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_LT,
op_t.clone(),
Const,
Visibility::BUILTIN_PRIVATE,
Some("lt"),
);
self.register_builtin_py_impl(
OP_LE,
op_t.clone(),
Const,
Visibility::BUILTIN_PRIVATE,
Some("le"),
);
self.register_builtin_py_impl(
OP_GT,
op_t.clone(),
Const,
Visibility::BUILTIN_PRIVATE,
Some("gt"),
);
self.register_builtin_py_impl(OP_GE, op_t, Const, Visibility::BUILTIN_PRIVATE, Some("ge"));
let T = type_q(TY_T);
let U = type_q(TY_U);
let or_t = bin_op(Bool, Bool, Bool)
Expand All @@ -708,15 +786,44 @@ impl Context {
tp_enum(Type, set! { ty_tp(T.clone() | U.clone()) }),
)
.quantify();
self.register_builtin_erg_impl(OP_OR, or_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(OP_OR, or_t, Const, Visibility::BUILTIN_PRIVATE, Some("or_"));
let and_t = bin_op(Bool, Bool, Bool)
& bin_op(
tp_enum(Type, set! { ty_tp(T.clone()) }),
tp_enum(Type, set! { ty_tp(U.clone()) }),
tp_enum(Type, set! { ty_tp(T & U) }),
)
.quantify();
self.register_builtin_erg_impl(OP_AND, and_t, Const, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_AND,
and_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("and_"),
);
let xor_t = bin_op(Bool, Bool, Bool);
self.register_builtin_py_impl(
OP_XOR,
xor_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("xor"),
);
let shift_t = bin_op(Int, Nat, Int);
self.register_builtin_py_impl(
OP_LSHIFT,
shift_t.clone(),
Const,
Visibility::BUILTIN_PRIVATE,
Some("lshift"),
);
self.register_builtin_py_impl(
OP_RSHIFT,
shift_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("rshift"),
);
let op_t = bin_op(O.clone(), O.clone(), range(O)).quantify();
self.register_builtin_erg_decl(OP_RNG, op_t.clone(), Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_decl(OP_LORNG, op_t.clone(), Visibility::BUILTIN_PRIVATE);
Expand All @@ -740,10 +847,30 @@ impl Context {
self.register_builtin_erg_impl(OP_MUTATE, op_t, Const, Visibility::BUILTIN_PRIVATE);
let P = mono_q(TY_N, subtypeof(mono(POS)));
let op_t = func1(P.clone(), proj(P, OUTPUT)).quantify();
self.register_builtin_erg_decl(OP_POS, op_t, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_POS,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("__pos__"),
);
let N = mono_q(TY_N, subtypeof(mono(NEG)));
let op_t = func1(N.clone(), proj(N, OUTPUT)).quantify();
self.register_builtin_erg_decl(OP_NEG, op_t, Visibility::BUILTIN_PRIVATE);
self.register_builtin_py_impl(
OP_NEG,
op_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("__neg__"),
);
let invert_t = func1(Int, Int);
self.register_builtin_py_impl(
OP_INVERT,
invert_t,
Const,
Visibility::BUILTIN_PRIVATE,
Some("__invert__"),
);
}

pub(super) fn init_py_compat_builtin_operators(&mut self) {
Expand Down Expand Up @@ -860,9 +987,33 @@ impl Context {
dict! { Field::public("__or__".into()) => fn1_met(Never, R.clone(), O.clone()) },
)
.structuralize();
bin_op(S, R.clone(), O).quantify()
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_OR, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__xor__".into()) => fn1_met(Never, R.clone(), O.clone()) },
)
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_XOR, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__lshift__".into()) => fn1_met(Never, R.clone(), O.clone()) },
)
.structuralize();
bin_op(S, R.clone(), O.clone()).quantify()
};
self.register_builtin_erg_impl(OP_LSHIFT, op_t, Const, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__rshift__".into()) => fn1_met(Never, R.clone(), O.clone()) },
)
.structuralize();
bin_op(S, R.clone(), O).quantify()
};
self.register_builtin_erg_impl(OP_RSHIFT, op_t, Const, Visibility::BUILTIN_PRIVATE);
let T = mono_q(TY_T, instanceof(Type));
let C = mono_q(TY_C, subtypeof(poly(CONTAINER, vec![ty_tp(T.clone())])));
let op_t = bin_op(C, T, Bool).quantify();
Expand All @@ -887,8 +1038,16 @@ impl Context {
let S =
Type::from(dict! { Field::public("__neg__".into()) => fn0_met(Never, R.clone()) })
.structuralize();
func1(S, R).quantify()
func1(S, R.clone()).quantify()
};
self.register_builtin_erg_decl(OP_NEG, op_t, Visibility::BUILTIN_PRIVATE);
let op_t = {
let S = Type::from(
dict! { Field::public("__invert__".into()) => fn0_met(Never, R.clone()) },
)
.structuralize();
func1(S, R).quantify()
};
self.register_builtin_erg_decl(OP_INVERT, op_t, Visibility::BUILTIN_PRIVATE);
}
}
4 changes: 4 additions & 0 deletions crates/erg_compiler/context/initialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,9 @@ const OP_ABS: &str = "__abs__";
const OP_PARTIAL_CMP: &str = "__partial_cmp__";
const OP_AND: &str = "__and__";
const OP_OR: &str = "__or__";
const OP_XOR: &str = "__xor__";
const OP_LSHIFT: &str = "__lshift__";
const OP_RSHIFT: &str = "__rshift__";
const OP_POW: &str = "__pow__";
const OP_MOD: &str = "__mod__";
const OP_IS: &str = "__is__!";
Expand All @@ -423,6 +426,7 @@ const OP_ORNG: &str = "__orng__";
const OP_MUTATE: &str = "__mutate__";
const OP_POS: &str = "__pos__";
const OP_NEG: &str = "__neg__";
const OP_INVERT: &str = "__invert__";

const FUNDAMENTAL_ARGS: &str = "__args__";
const FUNDAMENTAL_LEN: &str = "__len__";
Expand Down
2 changes: 1 addition & 1 deletion crates/erg_parser/lex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ impl Lexer /*<'a>*/ {
s,
"+_" | "_+_"
| "-_"
| "-"
| "_-_"
| "*"
| "/"
| "//"
Expand Down
5 changes: 5 additions & 0 deletions tests/should_ok/sym_op.er
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
perform f, x, y = f x, y
assert 3 == perform `_+_`, 1, 2
assert -1 == perform `_-_`, 1, 2
assert 2 == perform `*`, 1, 2
assert 0.5 - perform(`/`, 1, 2) < Float.EPSILON
5 changes: 5 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ fn exec_subtyping() -> Result<(), ()> {
expect_success("tests/should_ok/subtyping.er", 0)
}

#[test]
fn exec_sym_op() -> Result<(), ()> {
expect_success("tests/should_ok/sym_op.er", 0)
}

#[test]
fn exec_trait() -> Result<(), ()> {
expect_success("examples/trait.er", 0)
Expand Down

0 comments on commit abb025a

Please sign in to comment.