blueloveTH 2 лет назад
Родитель
Сommit
2fddde4f9c
6 измененных файлов с 88 добавлено и 44 удалено
  1. 19 0
      python/builtins.py
  2. 1 1
      src/common.h
  3. 1 1
      src/io.h
  4. 56 40
      src/pocketpy.h
  5. 2 2
      src/re.h
  6. 9 0
      tests/04_str.py

+ 19 - 0
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)):

+ 1 - 1
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()!");

+ 1 - 1
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));
     }
 };
 

+ 56 - 40
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<DummyInstance>(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<double>::infinity()));
     mod->attr().set("nan", VAR(std::numeric_limits<double>::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;

+ 2 - 2
src/re.h

@@ -18,8 +18,8 @@ struct ReMatch {
 
     static void _register(VM* vm, PyObject* mod, PyObject* type){
         vm->bind_notimplemented_constructor<ReMatch>(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]);

+ 9 - 0
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"