From f076bf43104358591ebafc8c120d91a7e9ffd3b0 Mon Sep 17 00:00:00 2001 From: BLUELOVETH Date: Fri, 10 Feb 2023 20:43:22 +0000 Subject: [PATCH] test `++`/`--` --- benchmarks/primes.py | 2 ++ benchmarks/sort.py | 28 +++++++++++++++++++++++++++- scripts/run_tests.py | 13 ++++++++++--- src/compiler.h | 30 +++++++++++++++++++++++++----- src/obj.h | 2 +- src/opcodes.h | 9 +++++++-- src/parser.h | 2 +- src/vm.h | 24 ++++++++++++++++++------ 8 files changed, 91 insertions(+), 19 deletions(-) diff --git a/benchmarks/primes.py b/benchmarks/primes.py index aa3c74c8..b093be9d 100644 --- a/benchmarks/primes.py +++ b/benchmarks/primes.py @@ -1,6 +1,8 @@ UPPER_BOUND = 5000000 PREFIX = 32338 +exit(0) + class Node: def __init__(self): self.children = {} diff --git a/benchmarks/sort.py b/benchmarks/sort.py index fa12d733..2cc9e7e2 100644 --- a/benchmarks/sort.py +++ b/benchmarks/sort.py @@ -1,4 +1,30 @@ import random a = [random.randint(-100000, 100000) for i in range(100000)] -a = sorted(a) \ No newline at end of file + +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 iu: + j-- + if i " + filepath) + print("> " + filepath, flush=True) if path == 'benchmarks/': _0 = time.time() @@ -30,7 +37,7 @@ def test_dir(path): if not test_file(filepath): exit(1) if len(sys.argv) == 2: - assert sys.argv[1] == 'benchmark' + assert 'benchmark' in sys.argv[1] d = 'benchmarks/' else: d = 'tests/' diff --git a/src/compiler.h b/src/compiler.h index 71ffbe1f..a737e7ff 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -73,6 +73,8 @@ 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 }; @@ -225,7 +227,12 @@ private: return; } case '=': parser->set_next_token_2('=', TK("="), 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("+=")); + else parser->set_next_token(TK("+")); + return; + } case '>': { if(parser->matchchar('=')) parser->set_next_token(TK(">=")); else if(parser->matchchar('>')) parser->set_next_token(TK(">>")); @@ -241,6 +248,7 @@ private: case '-': { if(parser->matchchar('=')) parser->set_next_token(TK("-=")); else if(parser->matchchar('>')) parser->set_next_token(TK("->")); + else if(parser->matchchar('-')) parser->set_next_token(TK("--")); else parser->set_next_token(TK("-")); return; } @@ -456,6 +464,16 @@ 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)); @@ -626,7 +644,8 @@ __LISTCOMP: consume(TK("@id")); const Str& name = parser->prev.str(); int index = co()->add_name(name, NAME_ATTR); - emit(OP_BUILD_ATTR_REF, index); + index = (index<<1) + (int)co()->_rvalue; + emit(OP_BUILD_ATTR, index); } // [:], [:b] @@ -655,7 +674,8 @@ __LISTCOMP: consume(TK("]")); } } - emit(OP_BUILD_INDEX_REF); + + emit(OP_BUILD_INDEX, (int)co()->_rvalue); } void exprValue() { @@ -730,7 +750,7 @@ __LISTCOMP: consume(TK("@id")); Token tkname = parser->prev; int index = co()->add_name(tkname.str(), NAME_ATTR); - emit(OP_BUILD_ATTR_REF, index); + emit(OP_BUILD_ATTR, (index<<1)+1); if (match(TK("as"))) { consume(TK("@id")); tkname = parser->prev; @@ -923,7 +943,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){ + if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF && last_op!=OP_STORE_INCREMENT){ if(mode()==REPL_MODE && parser->indents.top()==0) emit(OP_PRINT_EXPR, -1, true); emit(OP_POP_TOP, -1, true); } diff --git a/src/obj.h b/src/obj.h index 98357df0..9227d44a 100644 --- a/src/obj.h +++ b/src/obj.h @@ -113,7 +113,7 @@ namespace pkpy { inline static void call(int* counter) { PyObject* obj = (PyObject*)(counter + 1); std::vector& pool = _obj_pool[obj->_tid]; - if(obj->_tid==tid() || pool.size() > 60){ + if(obj->_tid==tid() || pool.size() > 32){ obj->~PyObject(); free(counter); }else{ diff --git a/src/opcodes.h b/src/opcodes.h index f995ec74..05d4b15d 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -58,8 +58,8 @@ OPCODE(EXCEPTION_MATCH) OPCODE(RAISE) OPCODE(RE_RAISE) -OPCODE(BUILD_INDEX_REF) -OPCODE(BUILD_ATTR_REF) +OPCODE(BUILD_INDEX) +OPCODE(BUILD_ATTR) OPCODE(STORE_NAME) OPCODE(STORE_FUNCTION) OPCODE(STORE_REF) @@ -68,4 +68,9 @@ 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] + #endif \ No newline at end of file diff --git a/src/parser.h b/src/parser.h index c52a73ac..b53913fe 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", diff --git a/src/vm.h b/src/vm.h index bf9fa76d..966e9208 100644 --- a/src/vm.h +++ b/src/vm.h @@ -27,6 +27,12 @@ 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); @@ -42,14 +48,20 @@ class VM { auto& p = frame->co->names[byte.arg]; NameRef(p).set(this, frame, frame->pop_value(this)); } break; - case OP_BUILD_ATTR_REF: { - auto& attr = frame->co->names[byte.arg]; + case OP_BUILD_ATTR: { + int name = byte.arg >> 1; + bool _rvalue = byte.arg % 2 == 1; + auto& attr = frame->co->names[name]; PyVar obj = frame->pop_value(this); - frame->push(PyRef(AttrRef(obj, NameRef(attr)))); + AttrRef ref = AttrRef(obj, NameRef(attr)); + if(_rvalue) frame->push(ref.get(this, frame)); + else frame->push(PyRef(ref)); } break; - case OP_BUILD_INDEX_REF: { + case OP_BUILD_INDEX: { PyVar index = frame->pop_value(this); - frame->push(PyRef(IndexRef(frame->pop_value(this), index))); + auto ref = IndexRef(frame->pop_value(this), index); + if(byte.arg == 0) frame->push(PyRef(ref)); + else frame->push(ref.get(this, frame)); } break; case OP_STORE_REF: { PyVar obj = frame->pop_value(this); @@ -794,7 +806,7 @@ public: template inline PyVarRef PyRef(P&& value) { - static_assert(std::is_base_of::value, "P should derive from BaseRef"); + static_assert(std::is_base_of>::value, "P should derive from BaseRef"); return new_object(tp_ref, std::forward

(value)); }