mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
test ++
/--
This commit is contained in:
parent
b6bb543c84
commit
f076bf4310
@ -1,6 +1,8 @@
|
|||||||
UPPER_BOUND = 5000000
|
UPPER_BOUND = 5000000
|
||||||
PREFIX = 32338
|
PREFIX = 32338
|
||||||
|
|
||||||
|
exit(0)
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.children = {}
|
self.children = {}
|
||||||
|
@ -1,4 +1,30 @@
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
a = [random.randint(-100000, 100000) for i in range(100000)]
|
a = [random.randint(-100000, 100000) for i in range(100000)]
|
||||||
a = sorted(a)
|
|
||||||
|
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--
|
||||||
|
if i<j:
|
||||||
|
a[i] = a[j]
|
||||||
|
i++
|
||||||
|
while i<j and a[i]<u:
|
||||||
|
i++
|
||||||
|
if i<j:
|
||||||
|
a[j] = a[i]
|
||||||
|
j--
|
||||||
|
a[i] = u;
|
||||||
|
__qsort(a, d1, i-1)
|
||||||
|
__qsort(a, i+1, d2)
|
||||||
|
|
||||||
|
from dis import dis
|
||||||
|
dis(__qsort)
|
||||||
|
|
||||||
|
__qsort(a, 0, len(a)-1)
|
@ -4,7 +4,14 @@ import time
|
|||||||
|
|
||||||
def test_file(filepath, cpython=False):
|
def test_file(filepath, cpython=False):
|
||||||
if cpython:
|
if cpython:
|
||||||
return os.system("python3 " + filepath) == 0
|
with open(filepath, 'rt') as f:
|
||||||
|
text = f.read().replace('++', '+=1').replace('--', '-=1')
|
||||||
|
with open("tmp.py", 'wt') as f:
|
||||||
|
f.write(text)
|
||||||
|
x = os.system("python3 tmp.py") == 0
|
||||||
|
os.remove("tmp.py")
|
||||||
|
return x
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
return os.system("pocketpy.exe " + filepath) == 0
|
return os.system("pocketpy.exe " + filepath) == 0
|
||||||
else:
|
else:
|
||||||
@ -16,7 +23,7 @@ def test_dir(path):
|
|||||||
if not filename.endswith('.py'):
|
if not filename.endswith('.py'):
|
||||||
continue
|
continue
|
||||||
filepath = os.path.join(path, filename)
|
filepath = os.path.join(path, filename)
|
||||||
print("> " + filepath)
|
print("> " + filepath, flush=True)
|
||||||
|
|
||||||
if path == 'benchmarks/':
|
if path == 'benchmarks/':
|
||||||
_0 = time.time()
|
_0 = time.time()
|
||||||
@ -30,7 +37,7 @@ def test_dir(path):
|
|||||||
if not test_file(filepath): exit(1)
|
if not test_file(filepath): exit(1)
|
||||||
|
|
||||||
if len(sys.argv) == 2:
|
if len(sys.argv) == 2:
|
||||||
assert sys.argv[1] == 'benchmark'
|
assert 'benchmark' in sys.argv[1]
|
||||||
d = 'benchmarks/'
|
d = 'benchmarks/'
|
||||||
else:
|
else:
|
||||||
d = 'tests/'
|
d = 'tests/'
|
||||||
|
@ -73,6 +73,8 @@ public:
|
|||||||
rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX };
|
rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX };
|
||||||
rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX };
|
rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX };
|
||||||
rules[TK("@fstr")] = { METHOD(exprFString), 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(exprTernary), PREC_TERNARY };
|
||||||
rules[TK("=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
rules[TK("=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
||||||
rules[TK("+=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
rules[TK("+=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
||||||
@ -225,7 +227,12 @@ private:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case '=': parser->set_next_token_2('=', TK("="), TK("==")); 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 '>': {
|
case '>': {
|
||||||
if(parser->matchchar('=')) parser->set_next_token(TK(">="));
|
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(">>"));
|
||||||
@ -241,6 +248,7 @@ private:
|
|||||||
case '-': {
|
case '-': {
|
||||||
if(parser->matchchar('=')) parser->set_next_token(TK("-="));
|
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 if(parser->matchchar('-')) parser->set_next_token(TK("--"));
|
||||||
else parser->set_next_token(TK("-"));
|
else parser->set_next_token(TK("-"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -456,6 +464,16 @@ private:
|
|||||||
patch_jump(patch2);
|
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() {
|
void exprBinaryOp() {
|
||||||
TokenIndex op = parser->prev.type;
|
TokenIndex op = parser->prev.type;
|
||||||
parse_expression((Precedence)(rules[op].precedence + 1));
|
parse_expression((Precedence)(rules[op].precedence + 1));
|
||||||
@ -626,7 +644,8 @@ __LISTCOMP:
|
|||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
const Str& name = parser->prev.str();
|
const Str& name = parser->prev.str();
|
||||||
int index = co()->add_name(name, NAME_ATTR);
|
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]
|
// [:], [:b]
|
||||||
@ -655,7 +674,8 @@ __LISTCOMP:
|
|||||||
consume(TK("]"));
|
consume(TK("]"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit(OP_BUILD_INDEX_REF);
|
|
||||||
|
emit(OP_BUILD_INDEX, (int)co()->_rvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void exprValue() {
|
void exprValue() {
|
||||||
@ -730,7 +750,7 @@ __LISTCOMP:
|
|||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
Token tkname = parser->prev;
|
Token tkname = parser->prev;
|
||||||
int index = co()->add_name(tkname.str(), NAME_ATTR);
|
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"))) {
|
if (match(TK("as"))) {
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
tkname = parser->prev;
|
tkname = parser->prev;
|
||||||
@ -923,7 +943,7 @@ __LISTCOMP:
|
|||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
// If last op is not an assignment, pop the result.
|
// If last op is not an assignment, pop the result.
|
||||||
uint8_t last_op = co()->codes.back().op;
|
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);
|
if(mode()==REPL_MODE && parser->indents.top()==0) emit(OP_PRINT_EXPR, -1, true);
|
||||||
emit(OP_POP_TOP, -1, true);
|
emit(OP_POP_TOP, -1, true);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ namespace pkpy {
|
|||||||
inline static void call(int* counter) {
|
inline static void call(int* counter) {
|
||||||
PyObject* obj = (PyObject*)(counter + 1);
|
PyObject* obj = (PyObject*)(counter + 1);
|
||||||
std::vector<int*>& pool = _obj_pool[obj->_tid];
|
std::vector<int*>& pool = _obj_pool[obj->_tid];
|
||||||
if(obj->_tid==tid<Dummy>() || pool.size() > 60){
|
if(obj->_tid==tid<Dummy>() || pool.size() > 32){
|
||||||
obj->~PyObject();
|
obj->~PyObject();
|
||||||
free(counter);
|
free(counter);
|
||||||
}else{
|
}else{
|
||||||
|
@ -58,8 +58,8 @@ OPCODE(EXCEPTION_MATCH)
|
|||||||
OPCODE(RAISE)
|
OPCODE(RAISE)
|
||||||
OPCODE(RE_RAISE)
|
OPCODE(RE_RAISE)
|
||||||
|
|
||||||
OPCODE(BUILD_INDEX_REF)
|
OPCODE(BUILD_INDEX)
|
||||||
OPCODE(BUILD_ATTR_REF)
|
OPCODE(BUILD_ATTR)
|
||||||
OPCODE(STORE_NAME)
|
OPCODE(STORE_NAME)
|
||||||
OPCODE(STORE_FUNCTION)
|
OPCODE(STORE_FUNCTION)
|
||||||
OPCODE(STORE_REF)
|
OPCODE(STORE_REF)
|
||||||
@ -68,4 +68,9 @@ OPCODE(DELETE_REF)
|
|||||||
OPCODE(TRY_BLOCK_ENTER)
|
OPCODE(TRY_BLOCK_ENTER)
|
||||||
OPCODE(TRY_BLOCK_EXIT)
|
OPCODE(TRY_BLOCK_EXIT)
|
||||||
|
|
||||||
|
OPCODE(STORE_INCREMENT)
|
||||||
|
|
||||||
|
//OPCODE(FAST_INDEX_0) // a[0]
|
||||||
|
//OPCODE(FAST_INDEX_1) // a[i]
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -10,7 +10,7 @@ constexpr const char* kTokens[] = {
|
|||||||
"+", "-", "*", "/", "//", "**", "=", ">", "<", "...", "->",
|
"+", "-", "*", "/", "//", "**", "=", ">", "<", "...", "->",
|
||||||
"<<", ">>", "&", "|", "^", "?",
|
"<<", ">>", "&", "|", "^", "?",
|
||||||
"==", "!=", ">=", "<=",
|
"==", "!=", ">=", "<=",
|
||||||
"+=", "-=", "*=", "/=", "//=", "%=", "&=", "|=", "^=",
|
"+=", "-=", "*=", "/=", "//=", "%=", "&=", "|=", "^=", "++", "--",
|
||||||
/** KW_BEGIN **/
|
/** KW_BEGIN **/
|
||||||
"class", "import", "as", "def", "lambda", "pass", "del", "from", "with",
|
"class", "import", "as", "def", "lambda", "pass", "del", "from", "with",
|
||||||
"None", "in", "is", "and", "or", "not", "True", "False", "global", "try", "except", "finally",
|
"None", "in", "is", "and", "or", "not", "True", "False", "global", "try", "except", "finally",
|
||||||
|
24
src/vm.h
24
src/vm.h
@ -27,6 +27,12 @@ class VM {
|
|||||||
{
|
{
|
||||||
case OP_NO_OP: break; // do nothing
|
case OP_NO_OP: break; // do nothing
|
||||||
case OP_LOAD_CONST: frame->push(frame->co->consts[byte.arg]); break;
|
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: {
|
case OP_LOAD_LAMBDA: {
|
||||||
PyVar obj = frame->co->consts[byte.arg];
|
PyVar obj = frame->co->consts[byte.arg];
|
||||||
setattr(obj, __module__, frame->_module);
|
setattr(obj, __module__, frame->_module);
|
||||||
@ -42,14 +48,20 @@ class VM {
|
|||||||
auto& p = frame->co->names[byte.arg];
|
auto& p = frame->co->names[byte.arg];
|
||||||
NameRef(p).set(this, frame, frame->pop_value(this));
|
NameRef(p).set(this, frame, frame->pop_value(this));
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_ATTR_REF: {
|
case OP_BUILD_ATTR: {
|
||||||
auto& attr = frame->co->names[byte.arg];
|
int name = byte.arg >> 1;
|
||||||
|
bool _rvalue = byte.arg % 2 == 1;
|
||||||
|
auto& attr = frame->co->names[name];
|
||||||
PyVar obj = frame->pop_value(this);
|
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;
|
} break;
|
||||||
case OP_BUILD_INDEX_REF: {
|
case OP_BUILD_INDEX: {
|
||||||
PyVar index = frame->pop_value(this);
|
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;
|
} break;
|
||||||
case OP_STORE_REF: {
|
case OP_STORE_REF: {
|
||||||
PyVar obj = frame->pop_value(this);
|
PyVar obj = frame->pop_value(this);
|
||||||
@ -794,7 +806,7 @@ public:
|
|||||||
|
|
||||||
template<typename P>
|
template<typename P>
|
||||||
inline PyVarRef PyRef(P&& value) {
|
inline PyVarRef PyRef(P&& value) {
|
||||||
static_assert(std::is_base_of<BaseRef, P>::value, "P should derive from BaseRef");
|
static_assert(std::is_base_of<BaseRef, std::remove_reference_t<P>>::value, "P should derive from BaseRef");
|
||||||
return new_object(tp_ref, std::forward<P>(value));
|
return new_object(tp_ref, std::forward<P>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user