From 2fddde4f9c6ee915b5afecb451cbb4b9baaea159 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 25 Jun 2023 01:59:40 +0800 Subject: [PATCH] ... --- python/builtins.py | 19 +++++++++ src/common.h | 2 +- src/io.h | 2 +- src/pocketpy.h | 96 +++++++++++++++++++++++++++------------------- src/re.h | 4 +- tests/04_str.py | 9 +++++ 6 files changed, 88 insertions(+), 44 deletions(-) diff --git a/python/builtins.py b/python/builtins.py index 9bd33ecc..07d0bc5f 100644 --- a/python/builtins.py +++ b/python/builtins.py @@ -105,6 +105,7 @@ def sorted(iterable, reverse=False, key=None): ##### str ##### def __f(self, sep=None): + flag = sep is None sep = sep or ' ' if sep == "": return list(self) @@ -118,9 +119,27 @@ def __f(self, sep=None): else: ++i res.append(self) + if flag: + return [i for i in res if i != ''] return res str.split = __f +def __f(self, s: str): + if type(s) is not str: + raise TypeError('must be str, not ' + type(s).__name__) + if s == '': + return len(self) + 1 + res = 0 + i = 0 + while i < len(self): + if self[i:i+len(s)] == s: + ++res + i += len(s) + else: + ++i + return res +str.count = __f + def __f(self, *args): if '{}' in self: for i in range(len(args)): diff --git a/src/common.h b/src/common.h index 4cffbbb2..acbb9c50 100644 --- a/src/common.h +++ b/src/common.h @@ -108,7 +108,7 @@ struct Type { operator int() const noexcept { return this->index; } }; -#define CPP_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; }) +#define PK_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; }) #ifdef POCKETPY_H #define FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!"); diff --git a/src/io.h b/src/io.h index 44deb7fb..f83a5608 100644 --- a/src/io.h +++ b/src/io.h @@ -88,7 +88,7 @@ struct FileIO { return vm->None; }); - vm->bind_method<0>(type, "__enter__", CPP_LAMBDA(vm->None)); + vm->bind_method<0>(type, "__enter__", PK_LAMBDA(vm->None)); } }; diff --git a/src/pocketpy.h b/src/pocketpy.h index 6783ebd7..334b4150 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -96,21 +96,26 @@ inline void init_builtins(VM* _vm) { return VAR(MappingProxy(mod)); }); - static const auto _mul = [](i64 a, i64 b, i64 c){ - if(c < 16384) return (a%c) * (b%c) % c; - i64 res = 0; - while(b > 0){ - if(b & 1) res = (res + a) % c; - a = (a << 1) % c; - b >>= 1; - } - return res; - }; - _vm->bind_builtin_func<3>("pow", [](VM* vm, ArgsView args) { i64 lhs = CAST(i64, args[0]); // assume lhs>=0 i64 rhs = CAST(i64, args[1]); // assume rhs>=0 i64 mod = CAST(i64, args[2]); // assume mod>0, mod*mod should not overflow + + if(rhs <= 0){ + vm->ValueError("pow(): rhs should be positive"); + } + + static const auto _mul = [](i64 a, i64 b, i64 c){ + if(c < 16384) return (a%c) * (b%c) % c; + i64 res = 0; + while(b > 0){ + if(b & 1) res = (res + a) % c; + a = (a << 1) % c; + b >>= 1; + } + return res; + }; + i64 res = 1; lhs %= mod; while(rhs){ @@ -167,7 +172,7 @@ inline void init_builtins(VM* _vm) { return vm->None; }); - _vm->bind_builtin_func<1>("repr", CPP_LAMBDA(vm->py_repr(args[0]))); + _vm->bind_builtin_func<1>("repr", PK_LAMBDA(vm->py_repr(args[0]))); _vm->bind_builtin_func<1>("len", [](VM* vm, ArgsView args){ const PyTypeInfo* ti = vm->_inst_type_info(args[0]); @@ -268,7 +273,7 @@ inline void init_builtins(VM* _vm) { return vm->heap.gcnew(t, {}); }); - _vm->bind_constructor<2>("type", CPP_LAMBDA(vm->_t(args[1]))); + _vm->bind_constructor<2>("type", PK_LAMBDA(vm->_t(args[1]))); _vm->bind_constructor<-1>("range", [](VM* vm, ArgsView args) { args._begin += 1; // skip cls @@ -424,7 +429,7 @@ inline void init_builtins(VM* _vm) { }); /************ str ************/ - _vm->bind_constructor<2>("str", CPP_LAMBDA(vm->py_str(args[1]))); + _vm->bind_constructor<2>("str", PK_LAMBDA(vm->py_str(args[1]))); _vm->bind__hash__(_vm->tp_str, [](VM* vm, PyObject* obj) { return (i64)_CAST(Str&, obj).hash(); @@ -488,6 +493,7 @@ inline void init_builtins(VM* _vm) { if(args.size() != 1+2 && args.size() != 1+3) vm->TypeError("replace() takes 2 or 3 arguments"); const Str& self = _CAST(Str&, args[0]); const Str& old = CAST(Str&, args[1]); + if(old.empty()) vm->ValueError("empty substring"); const Str& new_ = CAST(Str&, args[2]); int count = args.size()==1+3 ? CAST(int, args[3]) : -1; return VAR(self.replace(old, new_, count)); @@ -652,7 +658,17 @@ inline void init_builtins(VM* _vm) { _vm->bind__mul__(_vm->tp_list, [](VM* vm, PyObject* lhs, PyObject* rhs) { const List& self = _CAST(List&, lhs); - int n = CAST(int, rhs); + if(!is_int(rhs)) return vm->NotImplemented; + int n = _CAST(int, rhs); + List result; + result.reserve(self.size() * n); + for(int i = 0; i < n; i++) result.extend(self); + return VAR(std::move(result)); + }); + _vm->bind_method<1>("list", "__rmul__", [](VM* vm, ArgsView args) { + const List& self = _CAST(List&, args[0]); + if(!is_int(args[1])) return vm->NotImplemented; + int n = _CAST(int, args[1]); List result; result.reserve(self.size() * n); for(int i = 0; i < n; i++) result.extend(self); @@ -674,7 +690,7 @@ inline void init_builtins(VM* _vm) { return vm->None; }); - _vm->bind_method<0>("list", "copy", CPP_LAMBDA(VAR(_CAST(List, args[0])))); + _vm->bind_method<0>("list", "copy", PK_LAMBDA(VAR(_CAST(List, args[0])))); _vm->bind__hash__(_vm->tp_list, [](VM* vm, PyObject* obj) { vm->TypeError("unhashable type: 'list'"); @@ -761,7 +777,7 @@ inline void init_builtins(VM* _vm) { }); /************ bool ************/ - _vm->bind_constructor<2>("bool", CPP_LAMBDA(VAR(vm->py_bool(args[1])))); + _vm->bind_constructor<2>("bool", PK_LAMBDA(VAR(vm->py_bool(args[1])))); _vm->bind__hash__(_vm->tp_bool, [](VM* vm, PyObject* obj) { return (i64)_CAST(bool, obj); }); @@ -1251,9 +1267,9 @@ inline void add_module_math(VM* vm){ mod->attr().set("inf", VAR(std::numeric_limits::infinity())); mod->attr().set("nan", VAR(std::numeric_limits::quiet_NaN())); - vm->bind_func<1>(mod, "ceil", CPP_LAMBDA(VAR((i64)std::ceil(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "fabs", CPP_LAMBDA(VAR(std::fabs(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "floor", CPP_LAMBDA(VAR((i64)std::floor(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "ceil", PK_LAMBDA(VAR((i64)std::ceil(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "fabs", PK_LAMBDA(VAR(std::fabs(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "floor", PK_LAMBDA(VAR((i64)std::floor(CAST_F(args[0]))))); vm->bind_func<1>(mod, "fsum", [](VM* vm, ArgsView args) { List& list = CAST(List&, args[0]); double sum = 0; @@ -1280,29 +1296,29 @@ inline void add_module_math(VM* vm){ return VAR(a); }); - vm->bind_func<1>(mod, "isfinite", CPP_LAMBDA(VAR(std::isfinite(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "isinf", CPP_LAMBDA(VAR(std::isinf(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "isnan", CPP_LAMBDA(VAR(std::isnan(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "isfinite", PK_LAMBDA(VAR(std::isfinite(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "isinf", PK_LAMBDA(VAR(std::isinf(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "isnan", PK_LAMBDA(VAR(std::isnan(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "exp", CPP_LAMBDA(VAR(std::exp(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "log", CPP_LAMBDA(VAR(std::log(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "log2", CPP_LAMBDA(VAR(std::log2(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "log10", CPP_LAMBDA(VAR(std::log10(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "exp", PK_LAMBDA(VAR(std::exp(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "log", PK_LAMBDA(VAR(std::log(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "log2", PK_LAMBDA(VAR(std::log2(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "log10", PK_LAMBDA(VAR(std::log10(CAST_F(args[0]))))); - vm->bind_func<2>(mod, "pow", CPP_LAMBDA(VAR(std::pow(CAST_F(args[0]), CAST_F(args[1]))))); - vm->bind_func<1>(mod, "sqrt", CPP_LAMBDA(VAR(std::sqrt(CAST_F(args[0]))))); + vm->bind_func<2>(mod, "pow", PK_LAMBDA(VAR(std::pow(CAST_F(args[0]), CAST_F(args[1]))))); + vm->bind_func<1>(mod, "sqrt", PK_LAMBDA(VAR(std::sqrt(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "acos", CPP_LAMBDA(VAR(std::acos(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "asin", CPP_LAMBDA(VAR(std::asin(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "atan", CPP_LAMBDA(VAR(std::atan(CAST_F(args[0]))))); - vm->bind_func<2>(mod, "atan2", CPP_LAMBDA(VAR(std::atan2(CAST_F(args[0]), CAST_F(args[1]))))); + vm->bind_func<1>(mod, "acos", PK_LAMBDA(VAR(std::acos(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "asin", PK_LAMBDA(VAR(std::asin(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "atan", PK_LAMBDA(VAR(std::atan(CAST_F(args[0]))))); + vm->bind_func<2>(mod, "atan2", PK_LAMBDA(VAR(std::atan2(CAST_F(args[0]), CAST_F(args[1]))))); - vm->bind_func<1>(mod, "cos", CPP_LAMBDA(VAR(std::cos(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "sin", CPP_LAMBDA(VAR(std::sin(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "tan", CPP_LAMBDA(VAR(std::tan(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "cos", PK_LAMBDA(VAR(std::cos(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "sin", PK_LAMBDA(VAR(std::sin(CAST_F(args[0]))))); + vm->bind_func<1>(mod, "tan", PK_LAMBDA(VAR(std::tan(CAST_F(args[0]))))); - vm->bind_func<1>(mod, "degrees", CPP_LAMBDA(VAR(CAST_F(args[0]) * 180 / 3.1415926535897932384))); - vm->bind_func<1>(mod, "radians", CPP_LAMBDA(VAR(CAST_F(args[0]) * 3.1415926535897932384 / 180))); + vm->bind_func<1>(mod, "degrees", PK_LAMBDA(VAR(CAST_F(args[0]) * 180 / 3.1415926535897932384))); + vm->bind_func<1>(mod, "radians", PK_LAMBDA(VAR(CAST_F(args[0]) * 3.1415926535897932384 / 180))); vm->bind_func<1>(mod, "modf", [](VM* vm, ArgsView args) { f64 i; @@ -1354,13 +1370,13 @@ inline void add_module_dis(VM* vm){ inline void add_module_gc(VM* vm){ PyObject* mod = vm->new_module("gc"); - vm->bind_func<0>(mod, "collect", CPP_LAMBDA(VAR(vm->heap.collect()))); + vm->bind_func<0>(mod, "collect", PK_LAMBDA(VAR(vm->heap.collect()))); } inline void VM::post_init(){ init_builtins(this); - _t(tp_object)->attr().set("__class__", property(CPP_LAMBDA(vm->_t(args[0])))); + _t(tp_object)->attr().set("__class__", property(PK_LAMBDA(vm->_t(args[0])))); _t(tp_type)->attr().set("__base__", property([](VM* vm, ArgsView args){ const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])]; return info.base.index == -1 ? vm->None : vm->_all_types[info.base].obj; diff --git a/src/re.h b/src/re.h index eebdeb3f..c0f4b882 100644 --- a/src/re.h +++ b/src/re.h @@ -18,8 +18,8 @@ struct ReMatch { static void _register(VM* vm, PyObject* mod, PyObject* type){ vm->bind_notimplemented_constructor(type); - vm->bind_method<0>(type, "start", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).start))); - vm->bind_method<0>(type, "end", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).end))); + vm->bind_method<0>(type, "start", PK_LAMBDA(VAR(_CAST(ReMatch&, args[0]).start))); + vm->bind_method<0>(type, "end", PK_LAMBDA(VAR(_CAST(ReMatch&, args[0]).end))); vm->bind_method<0>(type, "span", [](VM* vm, ArgsView args) { auto& self = _CAST(ReMatch&, args[0]); diff --git a/tests/04_str.py b/tests/04_str.py index a2983784..fea011fa 100644 --- a/tests/04_str.py +++ b/tests/04_str.py @@ -42,6 +42,15 @@ assert t.split('w') == ['this is string example....', 'o', '!!!'] assert "a,b,c".split(',') == ['a', 'b', 'c'] assert 'a,'.split(',') == ['a', ''] assert 'foo!!bar!!baz'.split('!!') == ['foo', 'bar', 'baz'] +assert ' 4 3 '.split() == ['4', '3'] +assert ' 4 3 '.split(' ') == ['', '', '4', '3', '', ''] + +assert '111'.count('1') == 3 +assert '111'.count('11') == 1 +assert '1111'.count('11') == 2 +assert '11'.count('') == 3 +assert ''.count('1') == 0 +assert ''.count('') == 1 t = "*****this is **string** example....wow!!!*****" s = "123abcrunoob321"