blueloveTH %!s(int64=2) %!d(string=hai) anos
pai
achega
88c80a2340
Modificáronse 8 ficheiros con 55 adicións e 50 borrados
  1. 1 1
      include/pocketpy/common.h
  2. 2 1
      include/pocketpy/str.h
  3. 8 40
      python/builtins.py
  4. 7 1
      src/pocketpy.cpp
  5. 16 3
      src/str.cpp
  6. 2 2
      src/vm.cpp
  7. 2 2
      tests/04_str.py
  8. 17 0
      tests/99_builtin_func.py

+ 1 - 1
include/pocketpy/common.h

@@ -21,7 +21,7 @@
 #include <type_traits>
 #include <random>
 
-#define PK_VERSION				"1.1.7"
+#define PK_VERSION				"1.1.8"
 
 #include "config.h"
 #include "export.h"

+ 2 - 1
include/pocketpy/str.h

@@ -74,7 +74,8 @@ struct Str{
     int index(const Str& sub, int start=0) const;
     Str replace(char old, char new_) const;
     Str replace(const Str& old, const Str& new_, int count=-1) const;
-    std::vector<std::string_view> split(const Str& sep, bool remove_empty) const;
+    std::vector<std::string_view> split(const Str& sep) const;
+    int count(const Str& sub) const;
 
     /*************unicode*************/
     int _unicode_index_to_byte(int i) const;

+ 8 - 40
python/builtins.py

@@ -7,7 +7,9 @@ def print(*args, sep=' ', end='\n'):
 def abs(x):
     return -x if x < 0 else x
 
-def max(*args):
+def max(*args, key=None):
+    if key is None:
+        key = lambda x: x
     if len(args) == 0:
         raise TypeError('max expected 1 arguments, got 0')
     if len(args) == 1:
@@ -20,11 +22,13 @@ def max(*args):
         i = next(args)
         if i is StopIteration:
             break
-        if i > res:
+        if key(i) > key(res):
             res = i
     return res
 
-def min(*args):
+def min(*args, key=None):
+    if key is None:
+        key = lambda x: x
     if len(args) == 0:
         raise TypeError('min expected 1 arguments, got 0')
     if len(args) == 1:
@@ -37,7 +41,7 @@ def min(*args):
         i = next(args)
         if i is StopIteration:
             break
-        if i < res:
+        if key(i) < key(res):
             res = i
     return res
 
@@ -95,42 +99,6 @@ def sorted(iterable, reverse=False, key=None):
     return a
 
 ##### str #####
-def __f(self, sep=None):
-    flag = sep is None
-    sep = sep or ' '
-    if sep == "":
-        return list(self)
-    res = []
-    i = 0
-    while i < len(self):
-        if self[i:i+len(sep)] == sep:
-            res.append(self[:i])
-            self = self[i+len(sep):]
-            i = 0
-        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)):

+ 7 - 1
src/pocketpy.cpp

@@ -560,12 +560,18 @@ void init_builtins(VM* _vm) {
 
     _vm->bind(_vm->_t(_vm->tp_str), "split(self, sep=' ')", [](VM* vm, ArgsView args) {
         const Str& self = _CAST(Str&, args[0]);
-        std::vector<std::string_view> parts = self.split(CAST(Str&, args[1]), false);
+        std::vector<std::string_view> parts = self.split(CAST(Str&, args[1]));
         List ret(parts.size());
         for(int i=0; i<parts.size(); i++) ret[i] = VAR(Str(parts[i]));
         return VAR(std::move(ret));
     });
 
+    _vm->bind(_vm->_t(_vm->tp_str), "count(self, s: str)", [](VM* vm, ArgsView args) {
+        const Str& self = _CAST(Str&, args[0]);
+        const Str& s = CAST(Str&, args[1]);
+        return VAR(self.count(s));
+    });
+
     _vm->bind_method<1>("str", "index", [](VM* vm, ArgsView args) {
         const Str& self = _CAST(Str&, args[0]);
         const Str& sub = CAST(Str&, args[1]);

+ 16 - 3
src/str.cpp

@@ -316,7 +316,7 @@ int utf8len(unsigned char c, bool suppress){
         return _byte_index_to_unicode(size);
     }
 
-    std::vector<std::string_view> Str::split(const Str& sep, bool remove_empty) const{
+    std::vector<std::string_view> Str::split(const Str& sep) const{
         std::vector<std::string_view> result;
         std::string_view tmp;
         int start = 0;
@@ -324,14 +324,27 @@ int utf8len(unsigned char c, bool suppress){
             int i = index(sep, start);
             if(i == -1) break;
             tmp = sv().substr(start, i - start);
-            if(!remove_empty || !tmp.empty()) result.push_back(tmp);
+            if(!tmp.empty()) result.push_back(tmp);
             start = i + sep.size;
         }
         tmp = sv().substr(start, size - start);
-        if(!remove_empty || !tmp.empty()) result.push_back(tmp);
+        if(!tmp.empty()) result.push_back(tmp);
         return result;
     }
 
+    int Str::count(const Str& sub) const{
+        if(sub.empty()) return size + 1;
+        int cnt = 0;
+        int start = 0;
+        while(true){
+            int i = index(sub, start);
+            if(i == -1) break;
+            cnt++;
+            start = i + sub.size;
+        }
+        return cnt;
+    }
+
     std::ostream& operator<<(std::ostream& os, const StrName& sn){
         return os << sn.sv();
     }

+ 2 - 2
src/vm.cpp

@@ -233,7 +233,7 @@ namespace pkpy{
             Str curr_path = _import_context.pending.back();
             bool curr_is_init = _import_context.pending_is_init.back();
             // convert relative path to absolute path
-            std::vector<std::string_view> cpnts = curr_path.split(".", true);
+            std::vector<std::string_view> cpnts = curr_path.split(".");
             int prefix = 0;     // how many dots in the prefix
             for(int i=0; i<path.length(); i++){
                 if(path[i] == '.') prefix++;
@@ -251,7 +251,7 @@ namespace pkpy{
         PK_ASSERT(path.begin()[0] != '.');
         PK_ASSERT(path.end()[-1] != '.');
 
-        auto path_cpnts = path.split(".", true);
+        auto path_cpnts = path.split(".");
 
         // check circular import
         if(_import_context.pending.size() > 128){

+ 2 - 2
tests/04_str.py

@@ -42,10 +42,10 @@ assert t.startswith('this') == True;
 
 assert t.split('w') == ['this is string example....', 'o', '!!!']
 assert "a,b,c".split(',') == ['a', 'b', 'c']
-assert 'a,'.split(',') == ['a', '']
+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 '  4 3  '.split(' ') == ['4', '3']
 
 assert '111'.count('1') == 3
 assert '111'.count('11') == 1

+ 17 - 0
tests/99_builtin_func.py

@@ -1120,3 +1120,20 @@ import dis
 def aaa():
     pass
 assert dis.dis(aaa) is None
+
+# test min/max
+assert min(1, 2) == 1
+assert min(1, 2, 3) == 1
+assert min([1, 2]) == 1
+assert min([1, 2], key=lambda x: -x) == 2
+
+assert max(1, 2) == 2
+assert max(1, 2, 3) == 3
+assert max([1, 2]) == 2
+assert max([1, 2], key=lambda x: -x) == 1
+
+assert min([
+    (1, 2),
+    (1, 3),
+    (1, 4),
+]) == (1, 2)