From aacdca31b8cc9077432c7ad5a0961e0d20bcd60f Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 13 Sep 2023 11:09:30 +0900 Subject: [PATCH] fix: Python 3.7~3.8 bugs --- .github/workflows/rust.yml | 2 +- crates/erg_compiler/codegen.rs | 18 +++++++++++++++++- .../erg_compiler/context/initialize/funcs.rs | 4 ++-- crates/erg_compiler/hir.rs | 7 +++++++ crates/erg_compiler/lib/std/_erg_builtins.py | 6 ++++++ .../lib/std/_erg_contains_operator.py | 2 ++ 6 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 crates/erg_compiler/lib/std/_erg_builtins.py diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9d5f1a6b6..79af65785 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -35,7 +35,7 @@ jobs: fail-fast: false matrix: os: [windows-latest, ubuntu-latest, macos-latest] - python-version: ['3.9', '3.10', '3.11.3'] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11.3'] runs-on: ${{ matrix.os }} env: RUST_BACKTRACE: full diff --git a/crates/erg_compiler/codegen.rs b/crates/erg_compiler/codegen.rs index 85f6ea7a8..b460c398a 100644 --- a/crates/erg_compiler/codegen.rs +++ b/crates/erg_compiler/codegen.rs @@ -187,6 +187,7 @@ pub struct PyCodeGenerator { union_loaded: bool, fake_generic_loaded: bool, abc_loaded: bool, + builtins_loaded: bool, unit_size: usize, units: PyCodeGenStack, fresh_gen: SharedFreshNameGenerator, @@ -209,6 +210,7 @@ impl PyCodeGenerator { union_loaded: false, fake_generic_loaded: false, abc_loaded: false, + builtins_loaded: false, unit_size: 0, units: PyCodeGenStack::empty(), fresh_gen: SharedFreshNameGenerator::new("codegen"), @@ -231,6 +233,7 @@ impl PyCodeGenerator { union_loaded: false, fake_generic_loaded: false, abc_loaded: false, + builtins_loaded: false, unit_size: 0, units: PyCodeGenStack::empty(), fresh_gen: self.fresh_gen.clone(), @@ -253,6 +256,7 @@ impl PyCodeGenerator { self.union_loaded = false; self.fake_generic_loaded = false; self.abc_loaded = false; + self.builtins_loaded = false; } #[inline] @@ -2456,13 +2460,18 @@ impl PyCodeGenerator { Some(7) => self.emit_with_instr_307(args), _ => todo!("not supported Python version"), }, + "sum" if self.py_version.minor <= Some(7) && args.get_kw("start").is_some() => { + self.load_builtins(); + self.emit_load_name_instr(Identifier::private("#sum")); + self.emit_args_311(args, Name, true); + } other if local.ref_t().is_poly_type_meta() && other != "classof" => { if self.py_version.minor <= Some(9) { self.load_fake_generic(); self.emit_load_name_instr(Identifier::private("#FakeGenericAlias")); let mut args = args; args.insert_pos(0, PosArg::new(Expr::Accessor(Accessor::Ident(local)))); - self.emit_args_311(args, Name, false); + self.emit_args_311(args, Name, true); } else { self.emit_load_name_instr(local); self.emit_index_args(args); @@ -3573,6 +3582,13 @@ impl PyCodeGenerator { ); } + fn load_builtins(&mut self) { + self.emit_global_import_items( + Identifier::public("_erg_builtins"), + vec![(Identifier::public("sum"), Some(Identifier::private("#sum")))], + ); + } + pub fn emit(&mut self, hir: HIR) -> CodeObj { log!(info "the code-generating process has started.{RESET}"); self.unit_size += 1; diff --git a/crates/erg_compiler/context/initialize/funcs.rs b/crates/erg_compiler/context/initialize/funcs.rs index 0354146f9..a9402949a 100644 --- a/crates/erg_compiler/context/initialize/funcs.rs +++ b/crates/erg_compiler/context/initialize/funcs.rs @@ -139,7 +139,7 @@ impl Context { let t_isinstance = nd_func( vec![ kw(KW_OBJECT, Obj), - kw(KW_CLASSINFO, ClassType), // TODO: => ClassInfo + kw(KW_CLASSINFO, ClassType | unknown_len_array_t(ClassType)), // TODO: => ClassInfo ], None, Bool, @@ -147,7 +147,7 @@ impl Context { let t_issubclass = nd_func( vec![ kw(KW_SUBCLASS, ClassType), - kw(KW_CLASSINFO, ClassType), // TODO: => ClassInfo + kw(KW_CLASSINFO, ClassType | unknown_len_array_t(ClassType)), // TODO: => ClassInfo ], None, Bool, diff --git a/crates/erg_compiler/hir.rs b/crates/erg_compiler/hir.rs index 916105b9f..7328a73c9 100644 --- a/crates/erg_compiler/hir.rs +++ b/crates/erg_compiler/hir.rs @@ -385,6 +385,13 @@ impl Args { pub fn insert_pos(&mut self, idx: usize, pos: PosArg) { self.pos_args.insert(idx, pos); } + + pub fn get_kw(&self, keyword: &str) -> Option<&Expr> { + self.kw_args + .iter() + .find(|kw| kw.keyword.inspect() == keyword) + .map(|kw| &kw.expr) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/crates/erg_compiler/lib/std/_erg_builtins.py b/crates/erg_compiler/lib/std/_erg_builtins.py new file mode 100644 index 000000000..a44d206b1 --- /dev/null +++ b/crates/erg_compiler/lib/std/_erg_builtins.py @@ -0,0 +1,6 @@ +# in Python 3.7, `sum` takes no keyword arguments +def sum(iterable, start=0): + s = start + for i in iterable: + s += i + return s diff --git a/crates/erg_compiler/lib/std/_erg_contains_operator.py b/crates/erg_compiler/lib/std/_erg_contains_operator.py index a10009ee6..54a4951bb 100644 --- a/crates/erg_compiler/lib/std/_erg_contains_operator.py +++ b/crates/erg_compiler/lib/std/_erg_contains_operator.py @@ -14,6 +14,8 @@ def contains_operator(y, elem) -> bool: return True elif hasattr(y, "try_new") and is_ok(y.try_new(elem)): return True + elif hasattr(y, "__origin__") and hasattr(y.__origin__, "type_check"): + return y.__origin__.type_check(elem, y) # TODO: trait check return False # [1] in [Int]