some update

This commit is contained in:
blueloveTH 2023-02-11 16:23:32 +08:00
parent 817f7c3583
commit d70d2c6995
12 changed files with 85 additions and 130 deletions

View File

@ -42,6 +42,7 @@ jobs:
build_dir: web build_dir: web
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: github.event_name == 'push'
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:
path: output path: output

View File

@ -1,3 +1,5 @@
# BUG!! There is a memory leak in this code
UPPER_BOUND = 5000000 UPPER_BOUND = 5000000
PREFIX = 32338 PREFIX = 32338
@ -29,7 +31,7 @@ class Sieve:
while i < self.limit: while i < self.limit:
self.prime[i] = False self.prime[i] = False
i = i + r * r i = i + r * r
r = r + 1 r += 1
return self return self
def step1(self, x, y): def step1(self, x, y):
@ -53,13 +55,13 @@ class Sieve:
self.step1(x, y) self.step1(x, y)
self.step2(x, y) self.step2(x, y)
self.step3(x, y) self.step3(x, y)
y = y + 1 y += 1
def loop_x(self): def loop_x(self):
x = 1 x = 1
while x * x < self.limit: while x * x < self.limit:
self.loop_y(x) self.loop_y(x)
x = x + 1 x += 1
def calc(self): def calc(self):
self.loop_x() self.loop_x()
@ -83,10 +85,8 @@ def find(upper_bound, prefix):
str_prefix = str(prefix) str_prefix = str(prefix)
head = generate_trie(primes.to_list()) head = generate_trie(primes.to_list())
for ch in str_prefix: for ch in str_prefix:
if ch not in head.children: head = head.children.get(ch)
return None if head is None: # either ch does not exist or the value is None
head = head.children[ch]
if head is None:
return None return None
queue, result = [(head, str_prefix)], [] queue, result = [(head, str_prefix)], []

View File

@ -11,15 +11,15 @@ def __qsort(a: list, i: int, j: int):
u = a[i]; u = a[i];
while i<j: while i<j:
while i<j and a[j]>u: while i<j and a[j]>u:
j-- j -= 1
if i<j: if i<j:
a[i] = a[j] a[i] = a[j]
i++ i += 1
while i<j and a[i]<u: while i<j and a[i]<u:
i++ i += 1
if i<j: if i<j:
a[j] = a[i] a[j] = a[i]
j-- j -= 1
a[i] = u; a[i] = u;
__qsort(a, d1, i-1) __qsort(a, d1, i-1)
__qsort(a, i+1, d2) __qsort(a, i+1, d2)

View File

@ -4,14 +4,7 @@ import time
def test_file(filepath, cpython=False): def test_file(filepath, cpython=False):
if cpython: if cpython:
with open(filepath, 'rt') as f: return os.system("python3 " + filepath) == 0
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:

View File

@ -121,7 +121,7 @@ def __qsort(a: list, i: int, j: int):
mid = (i+j) // 2 mid = (i+j) // 2
a[mid], a[i] = a[i], a[mid] a[mid], a[i] = a[i], a[mid]
u = a[i]; u = a[i];
while i < j: while i<j:
while i<j and a[j]>u: while i<j and a[j]>u:
j -= 1 j -= 1
if i<j: if i<j:
@ -279,6 +279,12 @@ class dict:
if kv is not None: if kv is not None:
self[kv[0]] = kv[1] self[kv[0]] = kv[1]
def get(self, key, default=None):
ok, i = self.__probe(key)
if ok:
return self._a[i][1]
return default
def keys(self): def keys(self):
return [kv[0] for kv in self._a if kv is not None] return [kv[0] for kv in self._a if kv is not None]
@ -416,77 +422,11 @@ class set:
)"; )";
const char* kRandomCode = R"( const char* kRandomCode = R"(
import time as _time def shuffle(L):
for i in range(len(L)):
__all__ = ['Random', 'seed', 'random', 'randint', 'uniform'] j = randint(i, len(L) - 1)
L[i], L[j] = L[j], L[i]
def _int32(x):
return int(0xffffffff & x)
class Random:
def __init__(self, seed=None):
if seed is None:
seed = int(_time.time() * 1000000)
seed = _int32(seed)
self.mt = [0] * 624
self.mt[0] = seed
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 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 choice(L):
return L[randint(0, len(L) - 1)]
)"; )";

View File

@ -11,6 +11,7 @@
#include <regex> #include <regex>
#include <stack> #include <stack>
#include <cmath> #include <cmath>
#include <cstdlib>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include <string> #include <string>

View File

@ -73,8 +73,6 @@ 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 };
@ -227,12 +225,7 @@ private:
return; return;
} }
case '=': parser->set_next_token_2('=', TK("="), TK("==")); return; case '=': parser->set_next_token_2('=', TK("="), TK("==")); return;
case '+': { case '+': parser->set_next_token_2('=', TK("+"), TK("+=")); return;
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(">>"));
@ -464,16 +457,6 @@ 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));
@ -943,7 +926,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 && 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); 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);
} }

View File

@ -68,8 +68,6 @@ 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_0) // a[0]
//OPCODE(FAST_INDEX_1) // a[i] //OPCODE(FAST_INDEX_1) // a[i]

View File

@ -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",
@ -144,7 +144,7 @@ struct Parser {
if(brackets_level > 0) return true; if(brackets_level > 0) return true;
int spaces = eat_spaces(); int spaces = eat_spaces();
if(peekchar() == '#') skip_line_comment(); 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 // https://docs.python.org/3/reference/lexical_analysis.html#indentation
if(spaces > indents.top()){ if(spaces > indents.top()){
indents.push(spaces); indents.push(spaces);

View File

@ -569,12 +569,12 @@ void add_module_math(VM* vm){
vm->setattr(mod, "pi", vm->PyFloat(3.1415926535897932384)); vm->setattr(mod, "pi", vm->PyFloat(3.1415926535897932384));
vm->setattr(mod, "e" , vm->PyFloat(2.7182818284590452354)); 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, "log", CPP_LAMBDA(vm->PyFloat(std::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, "log10", CPP_LAMBDA(vm->PyFloat(std::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, "log2", CPP_LAMBDA(vm->PyFloat(std::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, "sin", CPP_LAMBDA(vm->PyFloat(std::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, "cos", CPP_LAMBDA(vm->PyFloat(std::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, "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, "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, "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]))))); 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<pkpy::NameDict>());
}
class _PkExported{ class _PkExported{
public: public:
virtual ~_PkExported() = default; virtual ~_PkExported() = default;
@ -781,11 +809,10 @@ extern "C" {
add_module_math(vm); add_module_math(vm);
add_module_re(vm); add_module_re(vm);
add_module_dis(vm); add_module_dis(vm);
add_module_random(vm);
CodeObject_ code = vm->compile(kBuiltinsCode, "<builtins>", EXEC_MODE); CodeObject_ code = vm->compile(kBuiltinsCode, "<builtins>", EXEC_MODE);
vm->_exec(code, vm->builtins, pkpy::make_shared<pkpy::NameDict>()); vm->_exec(code, vm->builtins, pkpy::make_shared<pkpy::NameDict>());
pkpy_vm_add_module(vm, "random", kRandomCode);
return vm; return vm;
} }

View File

@ -16,6 +16,7 @@
class VM { class VM {
std::stack< std::unique_ptr<Frame> > callstack; std::stack< std::unique_ptr<Frame> > callstack;
PyVar _py_op_call; PyVar _py_op_call;
PyVar _ascii_str_pool[128];
PyVar run_frame(Frame* frame){ PyVar run_frame(Frame* frame){
while(frame->has_next_bytecode()){ while(frame->has_next_bytecode()){
@ -27,12 +28,6 @@ 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);
@ -367,6 +362,7 @@ public:
} }
init_builtin_types(); 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){ PyVar asStr(const PyVar& obj){
@ -816,9 +812,20 @@ public:
return (const BaseRef*)(obj->value()); 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(Int, i64, tp_int)
DEF_NATIVE(Float, f64, tp_float) DEF_NATIVE(Float, f64, tp_float)
DEF_NATIVE(Str, Str, tp_str)
DEF_NATIVE(List, pkpy::List, tp_list) DEF_NATIVE(List, pkpy::List, tp_list)
DEF_NATIVE(Tuple, pkpy::Tuple, tp_tuple) DEF_NATIVE(Tuple, pkpy::Tuple, tp_tuple)
DEF_NATIVE(Function, pkpy::Function_, tp_function) DEF_NATIVE(Function, pkpy::Function_, tp_function)

View File

@ -5,6 +5,11 @@ for _ in range(100):
assert i <= 10 assert i <= 10
assert i >= 1 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 from sys import version as v