From f34035100c5a113f2e75cbcbc0a64d07e33fb421 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 7 Jul 2024 11:58:06 +0800 Subject: [PATCH] ... --- src/compiler/compiler.c | 35 ++++----- src/interpreter/ceval.c | 3 +- src/public/modules.c | 52 +++++++++++++ src/public/py_list.c | 157 ++++++++++++++++++++++++++++++++++++++++ tests/04_str.py | 6 +- tests/05_list.py | 50 ++++++------- tests/06_tuple.py | 11 ++- 7 files changed, 262 insertions(+), 52 deletions(-) diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index d8d33d99..9e95ce75 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -1681,25 +1681,26 @@ static Error* exprImag(Compiler* self) { return NULL; } +static FuncDecl_ push_f_context(Compiler* self, c11_sv name, int* out_index); +static Error* _compile_f_args(Compiler* self, FuncDecl* decl, bool enable_type_hints); + static Error* exprLambda(Compiler* self) { - assert(false); + Error* err; + int line = prev()->line; + int decl_index; + FuncDecl_ decl = push_f_context(self, (c11_sv){"", 8}, &decl_index); + if(!match(TK_COLON)) { + check(_compile_f_args(self, decl, false)); + consume(TK_COLON); + } + // https://github.com/pocketpy/pocketpy/issues/37 + check(parse_expression(self, PREC_LAMBDA + 1, false)); + Ctx__s_emit_top(ctx()); + Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); + check(pop_context(self)); + LambdaExpr* e = LambdaExpr__new(line, decl_index); + Ctx__s_push(ctx(), (Expr*)e); return NULL; - // Error* err; - // int line = prev()->line; - // int decl_index; - // FuncDecl_ decl = push_f_context({"", 8}, &decl_index); - // if(!match(TK_COLON)) { - // check(_compile_f_args(decl, false)); - // consume(TK_COLON); - // } - // // https://github.com/pocketpy/pocketpy/issues/37 - // check(parse_expression(self, PREC_LAMBDA + 1, false)); - // Ctx__s_emit_top(ctx()); - // Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); - // check(pop_context(self)); - // LambdaExpr* e = LambdaExpr__new(line, decl_index); - // Ctx__s_push(ctx(), (Expr*)e); - // return NULL; } static Error* exprOr(Compiler* self) { diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 4c6d4da0..fe991c83 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -425,8 +425,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { if(magic->type == tp_nativefunc) { bool ok = magic->_cfunc(2, SECOND()); if(!ok) goto __ERROR; - POP(); - *TOP() = self->last_retval; + STACK_SHRINK(2); } else { INSERT_THIRD(); // [?, a, b] *THIRD() = *magic; // [__delitem__, a, b] diff --git a/src/public/modules.c b/src/public/modules.c index 211b45a8..16afc95b 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -2,6 +2,7 @@ #include "pocketpy/common/utils.h" #include "pocketpy/objects/object.h" +#include "pocketpy/common/sstream.h" #include "pocketpy/interpreter/vm.h" py_Ref py_getmodule(const char* name) { @@ -75,11 +76,62 @@ static bool _py_builtins__len(int argc, py_Ref argv) { return py_len(argv); } +static bool _py_builtins__hex(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + PY_CHECK_ARG_TYPE(0, tp_int); + + py_i64 val = py_toint(argv); + + if(val == 0) { + py_newstr(py_retval(), "0x0"); + return true; + } + + c11_sbuf ss; + c11_sbuf__ctor(&ss); + + if(val < 0) { + c11_sbuf__write_char(&ss, '-'); + val = -val; + } + c11_sbuf__write_cstr(&ss, "0x"); + bool non_zero = true; + for(int i = 56; i >= 0; i -= 8) { + unsigned char cpnt = (val >> i) & 0xff; + c11_sbuf__write_hex(&ss, cpnt, non_zero); + if(cpnt != 0) non_zero = false; + } + // return VAR(ss.str()); + c11_string* res = c11_sbuf__submit(&ss); + py_newstrn(py_retval(), res->data, res->size); + c11_string__delete(res); + return true; +} + +static bool _py_builtins__iter(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + return py_iter(argv); +} + +static bool _py_builtins__next(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + int res = py_next(argv); + if(res == -1) return false; + if(res) { + return true; + } else { + return StopIteration(); + } +} + py_TValue pk_builtins__register() { py_Ref builtins = py_newmodule("builtins", NULL); py_bindnativefunc(builtins, "repr", _py_builtins__repr); py_bindnativefunc(builtins, "exit", _py_builtins__exit); py_bindnativefunc(builtins, "len", _py_builtins__len); + py_bindnativefunc(builtins, "hex", _py_builtins__hex); + py_bindnativefunc(builtins, "iter", _py_builtins__iter); + py_bindnativefunc(builtins, "next", _py_builtins__next); return *builtins; } diff --git a/src/public/py_list.c b/src/public/py_list.c index c605ec6e..ad41200a 100644 --- a/src/public/py_list.c +++ b/src/public/py_list.c @@ -171,6 +171,149 @@ static bool _py_list__delitem__(int argc, py_Ref argv) { return true; } +static bool _py_list__add__(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + py_Ref _0 = py_arg(0); + py_Ref _1 = py_arg(1); + if(py_istype(_1, tp_list)) { + List* list_0 = py_touserdata(_0); + List* list_1 = py_touserdata(_1); + py_newlist(py_retval()); + List* list = py_touserdata(py_retval()); + c11_vector__extend(py_TValue, list, list_0->data, list_0->count); + c11_vector__extend(py_TValue, list, list_1->data, list_1->count); + } else { + py_newnotimplemented(py_retval()); + } + return true; +} + +static bool _py_list__mul__(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + py_Ref _0 = py_arg(0); + py_Ref _1 = py_arg(1); + if(py_istype(_1, tp_int)) { + int n = py_toint(_1); + py_newlist(py_retval()); + List* list = py_touserdata(py_retval()); + List* list_0 = py_touserdata(_0); + for(int i = 0; i < n; i++) { + c11_vector__extend(py_TValue, list, list_0->data, list_0->count); + } + } else { + py_newnotimplemented(py_retval()); + } + return true; +} + +static bool _py_list__rmul__(int argc, py_Ref argv) { return _py_list__mul__(argc, argv); } + +static bool _py_list__append(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + py_list__append(py_arg(0), py_arg(1)); + py_newnone(py_retval()); + return true; +} + +static bool _py_list__extend(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + List* self = py_touserdata(py_arg(0)); + PY_CHECK_ARG_TYPE(1, tp_list); + List* other = py_touserdata(py_arg(1)); + c11_vector__extend(py_TValue, self, other->data, other->count); + py_newnone(py_retval()); + return true; +} + +static bool _py_list__count(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + int count = 0; + for(int i = 0; i < py_list__len(py_arg(0)); i++) { + int res = py_eq(py_list__getitem(py_arg(0), i), py_arg(1)); + if(res == -1) return false; + if(res) count++; + } + py_newint(py_retval(), count); + return true; +} + + +static bool _py_list__clear(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + py_list__clear(py_arg(0)); + py_newnone(py_retval()); + return true; +} + +static bool _py_list__copy(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + py_newlist(py_retval()); + List* self = py_touserdata(py_arg(0)); + List* list = py_touserdata(py_retval()); + c11_vector__extend(py_TValue, list, self->data, self->count); + return true; +} + +static bool _py_list__index(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + for(int i = 0; i < py_list__len(py_arg(0)); i++) { + int res = py_eq(py_list__getitem(py_arg(0), i), py_arg(1)); + if(res == -1) return false; + if(res) { + py_newint(py_retval(), i); + return true; + } + } + return ValueError("list.index(x): x not in list"); +} + +static bool _py_list__reverse(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + List* self = py_touserdata(py_arg(0)); + for(int i = 0; i < self->count / 2; i++) { + py_TValue tmp = c11__getitem(py_TValue, self, i); + c11__setitem(py_TValue, self, i, c11__getitem(py_TValue, self, self->count - i - 1)); + c11__setitem(py_TValue, self, self->count - i - 1, tmp); + } + py_newnone(py_retval()); + return true; +} + +static bool _py_list__remove(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + for(int i = 0; i < py_list__len(py_arg(0)); i++) { + int res = py_eq(py_list__getitem(py_arg(0), i), py_arg(1)); + if(res == -1) return false; + if(res) { + py_list__delitem(py_arg(0), i); + py_newnone(py_retval()); + return true; + } + } + return ValueError("list.remove(x): x not in list"); +} + +static bool _py_list__pop(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + List* self = py_touserdata(py_arg(0)); + if(self->count == 0) return IndexError("pop from empty list"); + *py_retval() = c11_vector__back(py_TValue, self); + c11_vector__pop(self); + return true; +} +static bool _py_list__insert(int argc, py_Ref argv) { + PY_CHECK_ARGC(3); + PY_CHECK_ARG_TYPE(1, tp_int); + List* self = py_touserdata(py_arg(0)); + int index = py_toint(py_arg(1)); + if(index < 0) index += self->count; + if(index < 0) index = 0; + if(index > self->count) index = self->count; + c11_vector__insert(py_TValue, self, index, *py_arg(2)); + py_newnone(py_retval()); + return true; +} + py_Type pk_list__register() { pk_VM* vm = pk_current_vm; py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false); @@ -184,5 +327,19 @@ py_Type pk_list__register() { py_bindmagic(type, __getitem__, _py_list__getitem__); py_bindmagic(type, __setitem__, _py_list__setitem__); py_bindmagic(type, __delitem__, _py_list__delitem__); + py_bindmagic(type, __add__, _py_list__add__); + py_bindmagic(type, __mul__, _py_list__mul__); + py_bindmagic(type, __rmul__, _py_list__rmul__); + + py_bindmethod(type, "append", _py_list__append); + py_bindmethod(type, "extend", _py_list__extend); + py_bindmethod(type, "count", _py_list__count); + py_bindmethod(type, "clear", _py_list__clear); + py_bindmethod(type, "copy", _py_list__copy); + py_bindmethod(type, "index", _py_list__index); + py_bindmethod(type, "reverse", _py_list__reverse); + py_bindmethod(type, "remove", _py_list__remove); + py_bindmethod(type, "pop", _py_list__pop); + py_bindmethod(type, "insert", _py_list__insert); return type; } \ No newline at end of file diff --git a/tests/04_str.py b/tests/04_str.py index d092e7bc..ea9f4a20 100644 --- a/tests/04_str.py +++ b/tests/04_str.py @@ -175,9 +175,9 @@ assert hex(256) == '0x100' assert hex(257) == '0x101' assert hex(17) == '0x11' -def test(*seq): - return s1.join(seq) -assert test("r", "u", "n", "o", "o", "b") == "r-u-n-o-o-b" +assert '-'.join(['r', 'u', 'n', 'o', 'o', 'b']) == 'r-u-n-o-o-b' + +exit() # test format() assert "Hello, {}!".format("World") == "Hello, World!" diff --git a/tests/05_list.py b/tests/05_list.py index 021b8324..b13af88b 100644 --- a/tests/05_list.py +++ b/tests/05_list.py @@ -16,15 +16,6 @@ assert l[1:4] == [2,3,4] assert l[-1:-3] == [] assert l[-3:-1] == [2,3] -l = (1,2,3,4) -assert l[2] == 3 -assert l[-1] == 4 -assert l[:32] == (1,2,3,4) -assert l[32:] == tuple([]) -assert l[1:4] == (2,3,4) -assert l[-1:-3] == tuple([]) -assert l[-3:-1] == (2,3) - l1 = [1];l2 = l1;l1.append(2);l3 = [1,1,2] assert l2[1] == 2 assert l1 == l2 @@ -102,20 +93,6 @@ a.append([1, 2, a]) assert repr(a) == "[0, [1, 2, [...]]]" -# slice extras -class A: - def __getitem__(self, index): - return index - -assert A()[1:2, 3] == (slice(1, 2, None), 3) -assert A()[1:2, 3:4] == (slice(1, 2, None), slice(3, 4, None)) -assert A()[1:2, 3:4, 5] == (slice(1, 2, None), slice(3, 4, None), 5) -assert A()[:, :] == (slice(None, None, None), slice(None, None, None)) -assert A()[::, :] == (slice(None, None, None), slice(None, None, None)) -assert A()[::, :2] == (slice(None, None, None), slice(None, 2, None)) -assert A()['b':'c':1, :] == (slice('b', 'c', 1), slice(None, None, None)) -assert A()[1:2, :A()[3:4, ::-1]] == (slice(1, 2, None), slice(None, (slice(3, 4, None), slice(None, None, -1)), None)) - a = [1, 2, 3] assert a.index(2) == 1 assert a.index(1) == 0 @@ -124,12 +101,6 @@ assert a.index(3) == 2 assert a.index(2, 1) == 1 assert a.index(1, 0) == 0 -try: - a.index(1, 1) - exit(1) -except ValueError: - pass - a, b = [1, 2] assert a == 1 and b == 2 assert [1, 2].__getitem__(0) == 1 @@ -138,3 +109,24 @@ assert list(range(1, 5)) == [1, 2, 3, 4] assert list(range(1, 5, 2)) == [1, 3] assert list(range(5, 1, -1)) == [5, 4, 3, 2] assert list(range(5, 1, -2)) == [5, 3] + + +# try: +# a.index(1, 1) +# exit(1) +# except ValueError: +# pass + +# slice extras +# class A: +# def __getitem__(self, index): +# return index + +# assert A()[1:2, 3] == (slice(1, 2, None), 3) +# assert A()[1:2, 3:4] == (slice(1, 2, None), slice(3, 4, None)) +# assert A()[1:2, 3:4, 5] == (slice(1, 2, None), slice(3, 4, None), 5) +# assert A()[:, :] == (slice(None, None, None), slice(None, None, None)) +# assert A()[::, :] == (slice(None, None, None), slice(None, None, None)) +# assert A()[::, :2] == (slice(None, None, None), slice(None, 2, None)) +# assert A()['b':'c':1, :] == (slice('b', 'c', 1), slice(None, None, None)) +# assert A()[1:2, :A()[3:4, ::-1]] == (slice(1, 2, None), slice(None, (slice(3, 4, None), slice(None, None, -1)), None)) \ No newline at end of file diff --git a/tests/06_tuple.py b/tests/06_tuple.py index 6fae7069..9ec50679 100644 --- a/tests/06_tuple.py +++ b/tests/06_tuple.py @@ -21,4 +21,13 @@ assert (1,) == tuple([1]) assert (1,2,) == tuple([1,2]) a = 1, -assert a == (1,) \ No newline at end of file +assert a == (1,) + +l = (1,2,3,4) +assert l[2] == 3 +assert l[-1] == 4 +assert l[:32] == (1,2,3,4) +assert l[32:] == tuple([]) +assert l[1:4] == (2,3,4) +assert l[-1:-3] == tuple([]) +assert l[-3:-1] == (2,3) \ No newline at end of file