Просмотр исходного кода

add `list.sort` impl (quick sort)

blueloveTH 3 лет назад
Родитель
Сommit
cb93e0ec25
11 измененных файлов с 77 добавлено и 37 удалено
  1. 46 12
      src/builtins.h
  2. 1 1
      src/codeobject.h
  3. 1 2
      src/common.h
  4. 1 1
      src/compiler.h
  5. 2 2
      src/error.h
  6. 1 1
      src/parser.h
  7. 6 6
      src/pocketpy.h
  8. 2 2
      src/str.h
  9. 6 8
      src/vm.h
  10. 1 2
      tests/_builtin_ty.py
  11. 10 0
      tests/_listcomp.py

+ 46 - 12
src/builtins.h

@@ -46,18 +46,13 @@ def zip(a, b):
 
 def reversed(iterable):
     a = list(iterable)
-    return [a[i] for i in range(len(a)-1, -1, -1)]
-
-def sorted(iterable, key=None, reverse=False):
-    b = list(iterable)
-    a = (key is None) ? b : [key(i) for i in iterable]
-    for i in range(len(a)):
-        for j in range(i+1, len(a)):
-            if (a[i] > a[j]) ^ reverse:
-                if a is not b:
-                    a[i], a[j] = a[j], a[i]
-                b[i], b[j] = b[j], b[i]
-    return b
+    a.reverse()
+    return a
+
+def sorted(iterable, reverse=False):
+    a = list(iterable)
+    a.sort(reverse=reverse)
+    return a
 
 ##### str #####
 
@@ -107,6 +102,45 @@ tuple.__repr__ = lambda self: '(' + ', '.join([repr(i) for i in self]) + ')'
 list.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']'
 tuple.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']'
 
+def __qsort(a: list, i: int, j: int):
+    if i>=j:
+        return
+    d1, d2 = i, j
+    mid = (i+j) // 2
+    a[mid], a[i] = a[i], a[mid]
+    u = a[i];
+    while i < j:
+        while i<j and a[j]>u:
+            j -= 1
+        if i<j:
+            a[i] = a[j]
+            i += 1
+        while i<j and a[i]<u:
+            i += 1
+        if i<j:
+            a[j] = a[i]
+            j -= 1
+    a[i] = u;
+    __qsort(a, d1, i-1)
+    __qsort(a, i+1, d2)
+
+def __list4reverse(self):
+    i, j = 0, len(self)-1
+    while i < j:
+        self[i], self[j] = self[j], self[i]
+        i += 1
+        j -= 1
+list.reverse = __list4reverse
+del __list4reverse
+
+def __list4sort(self, reverse=False):
+    __qsort(self, 0, len(self)-1)
+    if reverse:
+        self.reverse()
+
+list.sort = __list4sort
+del __list4sort
+
 def __list4extend(self, other):
     for i in other:
         self.append(i)

+ 1 - 1
src/codeobject.h

@@ -139,7 +139,7 @@ struct Frame {
     }
 
     Str stack_info(){
-        _StrStream ss;
+        StrStream ss;
         ss << "[";
         for(int i=0; i<_data.size(); i++){
             ss << OBJ_TP_NAME(_data[i]);

+ 1 - 2
src/common.h

@@ -31,13 +31,12 @@
 #define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
 #endif
 
-#define PK_VERSION "0.8.4"
+#define PK_VERSION "0.8.5"
 
 typedef int64_t i64;
 typedef double f64;
 
 struct Dummy { char _; };
-
 #define DUMMY_VAL Dummy()
 
 template<typename T>

+ 1 - 1
src/compiler.h

@@ -319,7 +319,7 @@ private:
 
     void consume(TokenIndex expected) {
         if (!match(expected)){
-            _StrStream ss;
+            StrStream ss;
             ss << "expected '" << TK_STR(expected) << "', but got '" << TK_STR(peek()) << "'";
             SyntaxError(ss.str());
         }

+ 2 - 2
src/error.h

@@ -45,7 +45,7 @@ struct SourceData {
     }
 
     Str snapshot(int lineno, const char* cursor=nullptr){
-        _StrStream ss;
+        StrStream ss;
         ss << "  " << "File \"" << filename << "\", line " << lineno << '\n';
         std::pair<const char*,const char*> pair = get_line(lineno);
         Str line = "<?>";
@@ -83,7 +83,7 @@ public:
 
     Str summary() const {
         std::stack<Str> st(stacktrace);
-        _StrStream ss;
+        StrStream ss;
         if(is_re) ss << "Traceback (most recent call last):\n";
         while(!st.empty()) { ss << st.top() << '\n'; st.pop(); }
         ss << type << ": " << msg;

+ 1 - 1
src/parser.h

@@ -56,7 +56,7 @@ struct Token{
   const Str str() const { return Str(start, length);}
 
   const Str info() const {
-    _StrStream ss;
+    StrStream ss;
     Str raw = str();
     if (raw == Str("\n")) raw = "\\n";
     ss << line << ": " << TK_STR(type) << " '" << raw << "'";

+ 6 - 6
src/pocketpy.h

@@ -256,7 +256,7 @@ void init_builtins(VM* _vm) {
     _vm->bind_method<0>("float", "__repr__", [](VM* vm, const pkpy::Args& args) {
         f64 val = vm->PyFloat_AS_C(args[0]);
         if(std::isinf(val) || std::isnan(val)) return vm->PyStr(std::to_string(val));
-        _StrStream ss;
+        StrStream ss;
         ss << std::setprecision(std::numeric_limits<f64>::max_digits10-1) << val;
         std::string s = ss.str();
         if(std::all_of(s.begin()+1, s.end(), isdigit)) s += ".0";
@@ -371,7 +371,7 @@ void init_builtins(VM* _vm) {
 
     _vm->bind_method<1>("str", "join", [](VM* vm, const pkpy::Args& args) {
         const Str& self = vm->PyStr_AS_C(args[0]);
-        _StrStream ss;
+        StrStream ss;
         if(args[1]->is_type(vm->tp_list)){
             const pkpy::List& a = vm->PyList_AS_C(args[1]);
             for(int i = 0; i < a.size(); i++){
@@ -793,11 +793,11 @@ extern "C" {
     /// Return a json representing the result.
     char* pkpy_vm_read_output(VM* vm){
         if(vm->use_stdio) return nullptr;
-        _StrStream* s_out = (_StrStream*)(vm->_stdout);
-        _StrStream* s_err = (_StrStream*)(vm->_stderr);
+        StrStream* s_out = (StrStream*)(vm->_stdout);
+        StrStream* s_err = (StrStream*)(vm->_stderr);
         Str _stdout = s_out->str();
         Str _stderr = s_err->str();
-        _StrStream ss;
+        StrStream ss;
         ss << '{' << "\"stdout\": " << _stdout.escape(false);
         ss << ", " << "\"stderr\": " << _stderr.escape(false) << '}';
         s_out->str(""); s_err->str("");
@@ -836,7 +836,7 @@ extern "C" {
         std::string f_header = std::string(mod) + '.' + name + '#' + std::to_string(kGlobalBindId++);
         PyVar obj = vm->_modules.contains(mod) ? vm->_modules[mod] : vm->new_module(mod);
         vm->bind_func<-1>(obj, name, [ret_code, f_header](VM* vm, const pkpy::Args& args){
-            _StrStream ss;
+            StrStream ss;
             ss << f_header;
             for(int i=0; i<args.size(); i++){
                 ss << ' ';

+ 2 - 2
src/str.h

@@ -2,7 +2,7 @@
 
 #include "common.h"
 
-typedef std::stringstream _StrStream;
+typedef std::stringstream StrStream;
 
 class Str : public std::string {
     mutable std::vector<uint16_t>* _u8_index = nullptr;
@@ -85,7 +85,7 @@ public:
     }
 
     Str escape(bool single_quote) const {
-        _StrStream ss;
+        StrStream ss;
         ss << (single_quote ? '\'' : '"');
         for (int i=0; i<length(); i++) {
             char c = this->operator[](i);

+ 6 - 8
src/vm.h

@@ -78,7 +78,7 @@ class VM {
             case OP_BUILD_STRING:
             {
                 pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg);
-                _StrStream ss;
+                StrStream ss;
                 for(int i=0; i<items.size(); i++) ss << PyStr_AS_C(asStr(items[i]));
                 frame->push(PyStr(ss.str()));
             } break;
@@ -347,13 +347,11 @@ public:
     VM(bool use_stdio){
         this->use_stdio = use_stdio;
         if(use_stdio){
-            std::cout.setf(std::ios::unitbuf);
-            std::cerr.setf(std::ios::unitbuf);
             this->_stdout = &std::cout;
             this->_stderr = &std::cerr;
         }else{
-            this->_stdout = new _StrStream();
-            this->_stderr = new _StrStream();
+            this->_stdout = new StrStream();
+            this->_stderr = new StrStream();
         }
 
         init_builtin_types();
@@ -731,7 +729,7 @@ public:
                 jumpTargets.push_back(byte.arg);
             }
         }
-        _StrStream ss;
+        StrStream ss;
         ss << std::string(54, '-') << '\n';
         ss << co->name << ":\n";
         int prev_line = -1;
@@ -764,11 +762,11 @@ public:
             ss << co->blocks[byte.block].to_string();
             if(i != co->codes.size() - 1) ss << '\n';
         }
-        _StrStream consts;
+        StrStream consts;
         consts << "co_consts: ";
         consts << PyStr_AS_C(asRepr(PyList(co->consts)));
 
-        _StrStream names;
+        StrStream names;
         names << "co_names: ";
         pkpy::List list;
         for(int i=0; i<co->names.size(); i++){

+ 1 - 2
tests/_builtin_ty.py

@@ -180,8 +180,7 @@ assert result == [1, 'a', 2, 'b', 3, 'c']
 
 a = [1,2,3,-1]
 assert sorted(a) == [-1,1,2,3]
-assert sorted(a, lambda x:-x) == [3,2,1,-1]
-assert sorted(a, None, True) == [3,2,1,-1]
+assert sorted(a, reverse=True) == [3,2,1,-1]
 
 assert abs(0) == 0
 assert abs(1.0) == 1.0

+ 10 - 0
tests/_listcomp.py

@@ -15,6 +15,16 @@ assert a == [2, 3]
 assert a.pop(-2) == 2
 assert a == [3]
 
+a = []
+a.sort()
+assert len(a) == 0
+assert a == []
+
+a = [1]
+a.sort()
+assert len(a) == 1
+assert a == [1]
+
 a = [1, 2, 3, 4]
 assert reversed(a) == [4, 3, 2, 1]
 assert a == [1, 2, 3, 4]