From cb93e0ec2570e87c81a9c70de14b8016038d914c Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Fri, 10 Feb 2023 21:32:13 +0800 Subject: [PATCH] add `list.sort` impl (quick sort) --- src/builtins.h | 56 +++++++++++++++++++++++++++++++++++--------- src/codeobject.h | 2 +- src/common.h | 3 +-- src/compiler.h | 2 +- src/error.h | 4 ++-- src/parser.h | 2 +- src/pocketpy.h | 12 +++++----- src/str.h | 4 ++-- src/vm.h | 14 +++++------ tests/_builtin_ty.py | 3 +-- tests/_listcomp.py | 10 ++++++++ 11 files changed, 76 insertions(+), 36 deletions(-) diff --git a/src/builtins.h b/src/builtins.h index 014c9dd0..519e80c2 100644 --- a/src/builtins.h +++ b/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)] + a.reverse() + return a -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 +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 iu: + j -= 1 + if i diff --git a/src/compiler.h b/src/compiler.h index c1efd10f..71ffbe1f 100644 --- a/src/compiler.h +++ b/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()); } diff --git a/src/error.h b/src/error.h index 6a190e6d..2e55d385 100644 --- a/src/error.h +++ b/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 pair = get_line(lineno); Str line = ""; @@ -83,7 +83,7 @@ public: Str summary() const { std::stack 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; diff --git a/src/parser.h b/src/parser.h index 0c9f96b1..c52a73ac 100644 --- a/src/parser.h +++ b/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 << "'"; diff --git a/src/pocketpy.h b/src/pocketpy.h index 87a89dea..9c775b33 100644 --- a/src/pocketpy.h +++ b/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::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* _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; ioperator[](i); diff --git a/src/vm.h b/src/vm.h index 365974ad..bf9fa76d 100644 --- a/src/vm.h +++ b/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; ipush(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; inames.size(); i++){ diff --git a/tests/_builtin_ty.py b/tests/_builtin_ty.py index fecd5f44..d3365eee 100644 --- a/tests/_builtin_ty.py +++ b/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 diff --git a/tests/_listcomp.py b/tests/_listcomp.py index a6f23cdb..b5c6ffe6 100644 --- a/tests/_listcomp.py +++ b/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]