From d70d2c69958d0425bfd92fbecb8d14be7cd687cf Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 11 Feb 2023 16:23:32 +0800 Subject: [PATCH] some update --- .github/workflows/main.yml | 1 + benchmarks/primes.py | 14 +++---- benchmarks/sort.py | 8 ++-- scripts/run_tests.py | 9 +--- src/builtins.h | 86 ++++++-------------------------------- src/common.h | 1 + src/compiler.h | 21 +--------- src/opcodes.h | 2 - src/parser.h | 4 +- src/pocketpy.h | 43 +++++++++++++++---- src/vm.h | 21 ++++++---- tests/_random.py | 5 +++ 12 files changed, 85 insertions(+), 130 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0b77327a..673f0c52 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,6 +42,7 @@ jobs: build_dir: web env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: github.event_name == 'push' - uses: actions/upload-artifact@v3 with: path: output diff --git a/benchmarks/primes.py b/benchmarks/primes.py index ff14b5be..4ebf49a1 100644 --- a/benchmarks/primes.py +++ b/benchmarks/primes.py @@ -1,3 +1,5 @@ +# BUG!! There is a memory leak in this code + UPPER_BOUND = 5000000 PREFIX = 32338 @@ -29,7 +31,7 @@ class Sieve: while i < self.limit: self.prime[i] = False i = i + r * r - r = r + 1 + r += 1 return self def step1(self, x, y): @@ -53,13 +55,13 @@ class Sieve: self.step1(x, y) self.step2(x, y) self.step3(x, y) - y = y + 1 + y += 1 def loop_x(self): x = 1 while x * x < self.limit: self.loop_y(x) - x = x + 1 + x += 1 def calc(self): self.loop_x() @@ -83,10 +85,8 @@ def find(upper_bound, prefix): str_prefix = str(prefix) head = generate_trie(primes.to_list()) for ch in str_prefix: - if ch not in head.children: - return None - head = head.children[ch] - if head is None: + head = head.children.get(ch) + if head is None: # either ch does not exist or the value is None return None queue, result = [(head, str_prefix)], [] diff --git a/benchmarks/sort.py b/benchmarks/sort.py index 517bdb24..13fe354c 100644 --- a/benchmarks/sort.py +++ b/benchmarks/sort.py @@ -11,15 +11,15 @@ def __qsort(a: list, i: int, j: int): u = a[i]; while iu: - j-- + j -= 1 if iu: j -= 1 if i> 30) + i) - - def extract_number(self): - if self.mti == 0: - self.twist() - y = self.mt[self.mti] - y = y ^ y >> 11 - y = y ^ y << 7 & 2636928640 - y = y ^ y << 15 & 4022730752 - y = y ^ y >> 18 - self.mti = (self.mti + 1) % 624 - return _int32(y) - - def twist(self): - for i in range(0, 624): - y = _int32((self.mt[i] & 0x80000000) + (self.mt[(i + 1) % 624] & 0x7fffffff)) - self.mt[i] = (y >> 1) ^ self.mt[(i + 397) % 624] - - if y % 2 != 0: - self.mt[i] = self.mt[i] ^ 0x9908b0df - - def seed(self, x): - assert type(x) is int - self.mt = [0] * 624 - self.mt[0] = _int32(x) - self.mti = 0 - for i in range(1, 624): - self.mt[i] = _int32(1812433253 * (self.mt[i - 1] ^ self.mt[i - 1] >> 30) + i) - - def random(self): - return self.extract_number() / 2 ** 32 - - def randint(self, a, b): - assert a <= b - return int(self.random() * (b - a + 1)) + a - - def uniform(self, a, b): - if a > b: - a, b = b, a - return self.random() * (b - a) + a - - def shuffle(self, L): - for i in range(len(L)): - j = self.randint(i, len(L) - 1) - L[i], L[j] = L[j], L[i] - - def choice(self, L): - return L[self.randint(0, len(L) - 1)] - -_inst = Random() -seed = _inst.seed -random = _inst.random -randint = _inst.randint -uniform = _inst.uniform -shuffle = _inst.shuffle -choice = _inst.choice +def shuffle(L): + for i in range(len(L)): + j = randint(i, len(L) - 1) + L[i], L[j] = L[j], L[i] +def choice(L): + return L[randint(0, len(L) - 1)] )"; \ No newline at end of file diff --git a/src/common.h b/src/common.h index 5c0991e5..dbf88cff 100644 --- a/src/common.h +++ b/src/common.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/src/compiler.h b/src/compiler.h index a737e7ff..2e63ea88 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -73,8 +73,6 @@ public: rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX }; rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX }; rules[TK("@fstr")] = { METHOD(exprFString), NO_INFIX }; - rules[TK("++")] = { nullptr, METHOD(exprSelfInc), PREC_UNARY }; - rules[TK("--")] = { nullptr, METHOD(exprSelfDec), PREC_UNARY }; rules[TK("?")] = { nullptr, METHOD(exprTernary), PREC_TERNARY }; rules[TK("=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT }; rules[TK("+=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT }; @@ -227,12 +225,7 @@ private: return; } case '=': parser->set_next_token_2('=', TK("="), TK("==")); return; - case '+': { - if(parser->matchchar('+')) parser->set_next_token(TK("++")); - else if(parser->matchchar('=')) parser->set_next_token(TK("+=")); - else parser->set_next_token(TK("+")); - return; - } + case '+': parser->set_next_token_2('=', TK("+"), TK("+=")); return; case '>': { if(parser->matchchar('=')) parser->set_next_token(TK(">=")); else if(parser->matchchar('>')) parser->set_next_token(TK(">>")); @@ -464,16 +457,6 @@ private: patch_jump(patch2); } - void exprSelfInc() { - emit(OP_STORE_INCREMENT, 1); - consume_end_stmt(); - } - - void exprSelfDec() { - emit(OP_STORE_INCREMENT, -1); - consume_end_stmt(); - } - void exprBinaryOp() { TokenIndex op = parser->prev.type; parse_expression((Precedence)(rules[op].precedence + 1)); @@ -943,7 +926,7 @@ __LISTCOMP: consume_end_stmt(); // If last op is not an assignment, pop the result. uint8_t last_op = co()->codes.back().op; - if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF && last_op!=OP_STORE_INCREMENT){ + if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF){ if(mode()==REPL_MODE && parser->indents.top()==0) emit(OP_PRINT_EXPR, -1, true); emit(OP_POP_TOP, -1, true); } diff --git a/src/opcodes.h b/src/opcodes.h index 05d4b15d..73315332 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -68,8 +68,6 @@ OPCODE(DELETE_REF) OPCODE(TRY_BLOCK_ENTER) OPCODE(TRY_BLOCK_EXIT) -OPCODE(STORE_INCREMENT) - //OPCODE(FAST_INDEX_0) // a[0] //OPCODE(FAST_INDEX_1) // a[i] diff --git a/src/parser.h b/src/parser.h index b53913fe..e7740ed1 100644 --- a/src/parser.h +++ b/src/parser.h @@ -10,7 +10,7 @@ constexpr const char* kTokens[] = { "+", "-", "*", "/", "//", "**", "=", ">", "<", "...", "->", "<<", ">>", "&", "|", "^", "?", "==", "!=", ">=", "<=", - "+=", "-=", "*=", "/=", "//=", "%=", "&=", "|=", "^=", "++", "--", + "+=", "-=", "*=", "/=", "//=", "%=", "&=", "|=", "^=", /** KW_BEGIN **/ "class", "import", "as", "def", "lambda", "pass", "del", "from", "with", "None", "in", "is", "and", "or", "not", "True", "False", "global", "try", "except", "finally", @@ -144,7 +144,7 @@ struct Parser { if(brackets_level > 0) return true; int spaces = eat_spaces(); if(peekchar() == '#') skip_line_comment(); - if(peekchar() == '\0' || peekchar() == '\n') return true; + if(peekchar() == '\0' || peekchar() == '\n' || peekchar() == '\r') return true; // https://docs.python.org/3/reference/lexical_analysis.html#indentation if(spaces > indents.top()){ indents.push(spaces); diff --git a/src/pocketpy.h b/src/pocketpy.h index 2a532f03..dfbd4953 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -569,12 +569,12 @@ void add_module_math(VM* vm){ vm->setattr(mod, "pi", vm->PyFloat(3.1415926535897932384)); vm->setattr(mod, "e" , vm->PyFloat(2.7182818284590452354)); - vm->bind_func<1>(mod, "log", CPP_LAMBDA(vm->PyFloat(log(vm->num_to_float(args[0]))))); - vm->bind_func<1>(mod, "log10", CPP_LAMBDA(vm->PyFloat(log10(vm->num_to_float(args[0]))))); - vm->bind_func<1>(mod, "log2", CPP_LAMBDA(vm->PyFloat(log2(vm->num_to_float(args[0]))))); - vm->bind_func<1>(mod, "sin", CPP_LAMBDA(vm->PyFloat(sin(vm->num_to_float(args[0]))))); - vm->bind_func<1>(mod, "cos", CPP_LAMBDA(vm->PyFloat(cos(vm->num_to_float(args[0]))))); - vm->bind_func<1>(mod, "tan", CPP_LAMBDA(vm->PyFloat(tan(vm->num_to_float(args[0]))))); + vm->bind_func<1>(mod, "log", CPP_LAMBDA(vm->PyFloat(std::log(vm->num_to_float(args[0]))))); + vm->bind_func<1>(mod, "log10", CPP_LAMBDA(vm->PyFloat(std::log10(vm->num_to_float(args[0]))))); + vm->bind_func<1>(mod, "log2", CPP_LAMBDA(vm->PyFloat(std::log2(vm->num_to_float(args[0]))))); + vm->bind_func<1>(mod, "sin", CPP_LAMBDA(vm->PyFloat(std::sin(vm->num_to_float(args[0]))))); + vm->bind_func<1>(mod, "cos", CPP_LAMBDA(vm->PyFloat(std::cos(vm->num_to_float(args[0]))))); + vm->bind_func<1>(mod, "tan", CPP_LAMBDA(vm->PyFloat(std::tan(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "isnan", CPP_LAMBDA(vm->PyBool(std::isnan(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "isinf", CPP_LAMBDA(vm->PyBool(std::isinf(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "fabs", CPP_LAMBDA(vm->PyFloat(std::fabs(vm->num_to_float(args[0]))))); @@ -669,6 +669,34 @@ void add_module_re(VM* vm){ }); } +void add_module_random(VM* vm){ + PyVar mod = vm->new_module("random"); + std::srand(std::time(nullptr)); + vm->bind_func<1>(mod, "seed", [](VM* vm, const pkpy::Args& args) { + std::srand((unsigned int)vm->PyInt_AS_C(args[0])); + return vm->None; + }); + + vm->bind_func<0>(mod, "random", CPP_LAMBDA(vm->PyFloat((f64)std::rand() / RAND_MAX))); + vm->bind_func<2>(mod, "randint", [](VM* vm, const pkpy::Args& args) { + i64 a = vm->PyInt_AS_C(args[0]); + i64 b = vm->PyInt_AS_C(args[1]); + if(a > b) std::swap(a, b); + return vm->PyInt(a + std::rand() % (b - a + 1)); + }); + + vm->bind_func<2>(mod, "uniform", [](VM* vm, const pkpy::Args& args) { + f64 a = vm->PyFloat_AS_C(args[0]); + f64 b = vm->PyFloat_AS_C(args[1]); + if(a > b) std::swap(a, b); + return vm->PyFloat(a + (b - a) * std::rand() / RAND_MAX); + }); + + CodeObject_ code = vm->compile(kRandomCode, "random.py", EXEC_MODE); + vm->_exec(code, mod, pkpy::make_shared()); +} + + class _PkExported{ public: virtual ~_PkExported() = default; @@ -781,11 +809,10 @@ extern "C" { add_module_math(vm); add_module_re(vm); add_module_dis(vm); + add_module_random(vm); CodeObject_ code = vm->compile(kBuiltinsCode, "", EXEC_MODE); vm->_exec(code, vm->builtins, pkpy::make_shared()); - - pkpy_vm_add_module(vm, "random", kRandomCode); return vm; } diff --git a/src/vm.h b/src/vm.h index 966e9208..bc301a97 100644 --- a/src/vm.h +++ b/src/vm.h @@ -16,6 +16,7 @@ class VM { std::stack< std::unique_ptr > callstack; PyVar _py_op_call; + PyVar _ascii_str_pool[128]; PyVar run_frame(Frame* frame){ while(frame->has_next_bytecode()){ @@ -27,12 +28,6 @@ class VM { { case OP_NO_OP: break; // do nothing case OP_LOAD_CONST: frame->push(frame->co->consts[byte.arg]); break; - case OP_STORE_INCREMENT:{ - const BaseRef* r = PyRef_AS_C(frame->top()); - i64 val = PyInt_AS_C(r->get(this, frame)); - r->set(this, frame, PyInt(val+byte.arg)); - frame->_pop(); - } break; case OP_LOAD_LAMBDA: { PyVar obj = frame->co->consts[byte.arg]; setattr(obj, __module__, frame->_module); @@ -367,6 +362,7 @@ public: } init_builtin_types(); + for(int i=0; i<128; i++) _ascii_str_pool[i] = new_object(tp_str, std::string(1, (char)i)); } PyVar asStr(const PyVar& obj){ @@ -816,9 +812,20 @@ public: return (const BaseRef*)(obj->value()); } + inline const Str& PyStr_AS_C(const PyVar& obj) { + check_type(obj, tp_str); + return OBJ_GET(Str, obj); + } + inline PyVar PyStr(const Str& value) { + if(value.size() == 1){ + char c = value.c_str()[0]; + if(c > 0) return _ascii_str_pool[(int)c]; + } + return new_object(tp_str, value); + } + DEF_NATIVE(Int, i64, tp_int) DEF_NATIVE(Float, f64, tp_float) - DEF_NATIVE(Str, Str, tp_str) DEF_NATIVE(List, pkpy::List, tp_list) DEF_NATIVE(Tuple, pkpy::Tuple, tp_tuple) DEF_NATIVE(Function, pkpy::Function_, tp_function) diff --git a/tests/_random.py b/tests/_random.py index dcda3aa7..93d576ed 100644 --- a/tests/_random.py +++ b/tests/_random.py @@ -5,6 +5,11 @@ for _ in range(100): assert i <= 10 assert i >= 1 +a = [1, 2, 3, 4] +b = (1, 2, 3) +r.shuffle(a) +r.choice(a) +r.choice(b) from sys import version as v