blueloveTH 1 سال پیش
والد
کامیت
f34035100c
7فایلهای تغییر یافته به همراه262 افزوده شده و 52 حذف شده
  1. 18 17
      src/compiler/compiler.c
  2. 1 2
      src/interpreter/ceval.c
  3. 52 0
      src/public/modules.c
  4. 157 0
      src/public/py_list.c
  5. 3 3
      tests/04_str.py
  6. 21 29
      tests/05_list.py
  7. 10 1
      tests/06_tuple.py

+ 18 - 17
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){"<lambda>", 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({"<lambda>", 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) {

+ 1 - 2
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]

+ 52 - 0
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;
 }
 

+ 157 - 0
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;
 }

+ 3 - 3
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!"

+ 21 - 29
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))

+ 10 - 1
tests/06_tuple.py

@@ -21,4 +21,13 @@ assert (1,) == tuple([1])
 assert (1,2,) == tuple([1,2])
 
 a = 1,
-assert a == (1,)
+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)