blueloveTH vor 2 Jahren
Ursprung
Commit
b13581037d
11 geänderte Dateien mit 123 neuen und 60 gelöschten Zeilen
  1. 2 5
      python/builtins.py
  2. 12 0
      src/c.pyi
  3. 0 4
      src/ceval.h
  4. 44 13
      src/cffi.h
  5. 7 4
      src/compiler.h
  6. 16 2
      src/main.cpp
  7. 4 3
      src/obj.h
  8. 0 1
      src/opcodes.h
  9. 22 27
      src/pocketpy.h
  10. 11 0
      src/str.h
  11. 5 1
      src/vm.h

+ 2 - 5
python/builtins.py

@@ -270,11 +270,8 @@ type.__repr__ = lambda self: "<class '" + self.__name__ + "'>"
 def help(obj):
     if hasattr(obj, '__func__'):
         obj = obj.__func__
-    if hasattr(obj, '__doc__'):
-        print(obj.__doc__)
-    else:
-        print("No docstring found")
-
+    print(obj.__signature__)
+    print(obj.__doc__)
 
 del __f
 

+ 12 - 0
src/c.pyi

@@ -65,12 +65,24 @@ class void_p:
     def set_base_offset(self, offset: str) -> None: ...
     
 class struct:
+    @overload
+    def __init__(self, size: int): ...
+    @overload
+    def __init__(self, p: 'void_p', size: int): ...
+    @overload
+    def __init__(self, s: str): ...
+    @overload
+    def __init__(self, b: bytes): ...
+
     def addr(self) -> 'void_p': ...
     def copy(self) -> 'struct': ...
     def size(self) -> int: ...
     def __eq__(self, other: 'struct') -> bool: ...
     def __ne__(self, other: 'struct') -> bool: ...
 
+    def to_string(self) -> str: ...
+    def to_bytes(self) -> bytes: ...
+
     def read_char(self, offset=0) -> int: ...
     def read_uchar(self, offset=0) -> int: ...
     def read_short(self, offset=0) -> int: ...

+ 0 - 4
src/ceval.h

@@ -11,7 +11,6 @@ inline PyObject* VM::_run_top_frame(){
     DEF_SNAME(set);
     DEF_SNAME(__enter__);
     DEF_SNAME(__exit__);
-    DEF_SNAME(__doc__);
 
     FrameId frame = top_frame();
     const int base_id = frame.index;
@@ -674,9 +673,6 @@ __NEXT_STEP:;
     TARGET(RE_RAISE) _raise(); DISPATCH();
     TARGET(POP_EXCEPTION) _last_exception = POPX(); DISPATCH();
     /*****************************************/
-    TARGET(SETUP_DOCSTRING)
-        TOP()->attr().set(__doc__, co_consts[byte.arg]);
-        DISPATCH();
     TARGET(FORMAT_STRING) {
         _0 = POPX();
         const Str& spec = CAST(Str&, co_consts[byte.arg]);

+ 44 - 13
src/cffi.h

@@ -191,7 +191,7 @@ struct C99Struct{
     char* p;
     int size;
 
-    void _init(int new_size){
+    C99Struct(int new_size){
         this->size = new_size;
         if(size <= INLINE_SIZE){
             p = _inlined;
@@ -201,27 +201,46 @@ struct C99Struct{
     }
 
     template<typename T>
-    C99Struct(const T& data){
+    C99Struct(const T& data): C99Struct(sizeof(T)){
         static_assert(std::is_pod_v<T>);
         static_assert(!std::is_pointer_v<T>);
-        _init(sizeof(T));
         memcpy(p, &data, this->size);
     }
 
-    C99Struct() { p = _inlined; }
-    C99Struct(void* p, int size){
-        _init(size);
-        if(p!=nullptr) memcpy(this->p, p, size);
+    C99Struct(void* p, int size): C99Struct(size){
+        if(p != nullptr) memcpy(this->p, p, size);
     }
-    ~C99Struct(){ if(p!=_inlined) free(p); }
 
-    C99Struct(const C99Struct& other){
-        _init(other.size);
-        memcpy(p, other.p, size);
-    }
+    C99Struct(const C99Struct& other): C99Struct(other.p, other.size){}
+
+    ~C99Struct(){ if(p!=_inlined) free(p); }
 
     static void _register(VM* vm, PyObject* mod, PyObject* type){
-        vm->bind_default_constructor<C99Struct>(type);
+        vm->bind_constructor<-1>(type, [](VM* vm, ArgsView args){
+            if(args.size() == 1+1){
+                if(is_int(args[1])){
+                    int size = _CAST(int, args[1]);
+                    return VAR_T(C99Struct, size);
+                }
+                if(is_non_tagged_type(args[1], vm->tp_str)){
+                    const Str& s = _CAST(Str&, args[1]);
+                    return VAR_T(C99Struct, (void*)s.data, s.size);
+                }
+                if(is_non_tagged_type(args[1], vm->tp_bytes)){
+                    const Bytes& b = _CAST(Bytes&, args[1]);
+                    return VAR_T(C99Struct, (void*)b.data(), b.size());
+                }
+                vm->TypeError("expected int, str or bytes");
+                return vm->None;
+            }
+            if(args.size() == 1+2){
+                void* p = CAST(void*, args[1]);
+                int size = CAST(int, args[2]);
+                return VAR_T(C99Struct, p, size);
+            }
+            vm->TypeError("expected 1 or 2 arguments");
+            return vm->None;
+        });
 
         vm->bind_method<0>(type, "addr", [](VM* vm, ArgsView args){
             C99Struct& self = _CAST(C99Struct&, args[0]);
@@ -238,6 +257,18 @@ struct C99Struct{
             return VAR_T(C99Struct, self);
         });
 
+        vm->bind_method<0>(type, "to_string", [](VM* vm, ArgsView args){
+            C99Struct& self = _CAST(C99Struct&, args[0]);
+            return VAR(Str(self.p, self.size));
+        });
+
+        vm->bind_method<0>(type, "to_bytes", [](VM* vm, ArgsView args){
+            C99Struct& self = _CAST(C99Struct&, args[0]);
+            std::vector<char> buffer(self.size);
+            memcpy(buffer.data(), self.p, self.size);
+            return VAR(Bytes(std::move(buffer)));
+        });
+
         vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
             C99Struct& self = _CAST(C99Struct&, lhs);
             if(!is_non_tagged_type(rhs, C99Struct::_type(vm))) return vm->NotImplemented;

+ 7 - 4
src/compiler.h

@@ -972,9 +972,9 @@ __SUBSCR_END:
     }
 
     void compile_function(const std::vector<Expr_>& decorators={}){
-        Str decl_name;
+        const char* _start = curr().start;
         consume(TK("@id"));
-        decl_name = prev().str();
+        Str decl_name = prev().str();
         FuncDecl_ decl = push_f_context(decl_name);
         consume(TK("("));
         if (!match(TK(")"))) {
@@ -982,6 +982,8 @@ __SUBSCR_END:
             consume(TK(")"));
         }
         if(match(TK("->"))) consume_type_hints();
+        const char* _end = curr().start;
+        decl->signature = Str(_start, _end-_start);
         compile_block_body();
         pop_context();
 
@@ -994,10 +996,11 @@ __SUBSCR_END:
                 docstring = c;
             }
         }
-        ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line);
         if(docstring != nullptr){
-            ctx()->emit(OP_SETUP_DOCSTRING, ctx()->add_const(docstring), prev().line);
+            decl->docstring = PK_OBJ_GET(Str, docstring);
         }
+        ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line);
+
         // add decorators
         for(auto it=decorators.rbegin(); it!=decorators.rend(); ++it){
             (*it)->emit(ctx());

+ 16 - 2
src/main.cpp

@@ -7,11 +7,25 @@
 
 int main(int argc, char** argv){
     pkpy::VM* vm = pkpy_new_vm();
-    pkpy::PyObject* input_f = vm->bind_builtin_func<0>("input", [](pkpy::VM* vm, pkpy::ArgsView args){
+    vm->bind_builtin_func<0>("input", [](pkpy::VM* vm, pkpy::ArgsView args){
         // pkpy::getline() has bugs for PIPE input on Windows
         return VAR(pkpy::getline());
     });
-    vm->_modules["sys"]->attr("stdin")->attr().set("readline", input_f);
+
+    // vm->bind(vm->builtins, "test_sum(a: int, b: int, *args, x=5)",
+    //     "Test function for summing up numbers.",
+    //     [](pkpy::VM* vm, pkpy::ArgsView args){
+    //         PK_ASSERT(args.size() == 4);
+    //         int sum = 0;
+    //         sum += pkpy::CAST(int, args[0]);
+    //         sum += pkpy::CAST(int, args[1]);
+    //         pkpy::Tuple& t = pkpy::CAST(pkpy::Tuple&, args[2]);
+    //         for(pkpy::PyObject* ob: t){
+    //             sum += pkpy::CAST(int, ob);
+    //         }
+    //         sum *= pkpy::CAST(int, args[3]);
+    //         return VAR(sum);
+    //     });
     if(argc == 1){
         pkpy::REPL* repl = pkpy_new_repl(vm);
         bool need_more_lines = false;

+ 4 - 3
src/obj.h

@@ -30,6 +30,9 @@ struct FuncDecl {
     int starred_arg = -1;       // index in co->varnames, -1 if no *arg
     int starred_kwarg = -1;     // index in co->varnames, -1 if no **kwarg
     bool nested = false;        // whether this function is nested
+
+    Str signature;              // signature of this function
+    Str docstring;              // docstring of this function
     void _gc_mark() const;
 };
 
@@ -43,7 +46,6 @@ struct NativeFunc {
 
     // new style decl-based call
     FuncDecl_ decl;
-    const char* docstring;
 
     using UserData = char[32];
     UserData _userdata;
@@ -75,11 +77,10 @@ struct NativeFunc {
         _has_userdata = false;
     }
 
-    NativeFunc(NativeFuncC f, FuncDecl_ decl, const char* docstring){
+    NativeFunc(NativeFuncC f, FuncDecl_ decl){
         this->f = f;
         this->argc = -1;
         this->decl = decl;
-        this->docstring = docstring;
         _has_userdata = false;
     }
 

+ 0 - 1
src/opcodes.h

@@ -123,7 +123,6 @@ OPCODE(RAISE)
 OPCODE(RE_RAISE)
 OPCODE(POP_EXCEPTION)
 /**************************/
-OPCODE(SETUP_DOCSTRING)
 OPCODE(FORMAT_STRING)
 /**************************/
 OPCODE(INC_FAST)

+ 22 - 27
src/pocketpy.h

@@ -559,16 +559,6 @@ inline void init_builtins(VM* _vm) {
         return VAR(ss.str());
     });
 
-    _vm->bind_method<0>("str", "to_c_str", [](VM* vm, ArgsView args){
-        const Str& self = _CAST(Str&, args[0]);
-        return VAR(self.c_str_dup());
-    });
-
-    _vm->bind_func<1>("str", "from_c_str", [](VM* vm, ArgsView args){
-        char* p = CAST(char*, args[0]);
-        return VAR(Str(p));
-    });
-
     _vm->bind_method<0>("str", "lower", [](VM* vm, ArgsView args) {
         const Str& self = _CAST(Str&, args[0]);
         return VAR(self.lower());
@@ -907,21 +897,6 @@ inline void init_builtins(VM* _vm) {
         return VAR(Str(self.str()));
     });
 
-    _vm->bind_method<0>("bytes", "to_char_array", [](VM* vm, ArgsView args) {
-        const Bytes& self = _CAST(Bytes&, args[0]);
-        void* buffer = malloc(self.size());
-        memcpy(buffer, self.data(), self.size());
-        return VAR_T(VoidP, buffer);
-    });
-
-    _vm->bind_func<2>("bytes", "from_char_array", [](VM* vm, ArgsView args) {
-        const VoidP& data = _CAST(VoidP&, args[0]);
-        int size = CAST(int, args[1]);
-        std::vector<char> buffer(size);
-        memcpy(buffer.data(), data.ptr, size);
-        return VAR(Bytes(std::move(buffer)));
-    });
-
     _vm->bind__eq__(_vm->tp_bytes, [](VM* vm, PyObject* lhs, PyObject* rhs) {
         if(!is_non_tagged_type(rhs, vm->tp_bytes)) return vm->NotImplemented;
         return VAR(_CAST(Bytes&, lhs) == _CAST(Bytes&, rhs));
@@ -1175,6 +1150,28 @@ inline void init_builtins(VM* _vm) {
         vm->TypeError("property() takes at most 2 arguments");
         return vm->None;
     });
+    
+    _vm->_t(_vm->tp_function)->attr().set("__doc__", _vm->property([](VM* vm, ArgsView args) {
+        Function& func = _CAST(Function&, args[0]);
+        return VAR(func.decl->docstring);
+    }));
+
+    _vm->_t(_vm->tp_native_func)->attr().set("__doc__", _vm->property([](VM* vm, ArgsView args) {
+        NativeFunc& func = _CAST(NativeFunc&, args[0]);
+        if(func.decl != nullptr) return VAR(func.decl->docstring);
+        return VAR("");
+    }));
+
+    _vm->_t(_vm->tp_function)->attr().set("__signature__", _vm->property([](VM* vm, ArgsView args) {
+        Function& func = _CAST(Function&, args[0]);
+        return VAR(func.decl->signature);
+    }));
+
+    _vm->_t(_vm->tp_native_func)->attr().set("__signature__", _vm->property([](VM* vm, ArgsView args) {
+        NativeFunc& func = _CAST(NativeFunc&, args[0]);
+        if(func.decl != nullptr) return VAR(func.decl->signature);
+        return VAR("unknown(*args, **kwargs)");
+    }));
 
     RangeIter::register_class(_vm, _vm->builtins);
     ArrayIter::register_class(_vm, _vm->builtins);
@@ -1288,10 +1285,8 @@ inline void add_module_sys(VM* vm){
 
     PyObject* stdout_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
     PyObject* stderr_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
-    PyObject* stdin_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
     vm->setattr(mod, "stdout", stdout_);
     vm->setattr(mod, "stderr", stderr_);
-    vm->setattr(mod, "stdin", stdin_);
 
     vm->bind_func<1>(stdout_, "write", [](VM* vm, ArgsView args) {
         vm->_stdout(vm, CAST(Str&, args[0]));

+ 11 - 0
src/str.h

@@ -228,6 +228,17 @@ struct Str{
         return Str(copy);
     }
 
+    Str strip() const {
+        std::string copy(data, size);
+        copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) {
+            return c != ' ' && c != '\t' && c != '\r' && c != '\n';
+        }));
+        copy.erase(std::find_if(copy.rbegin(), copy.rend(), [](char c) {
+            return c != ' ' && c != '\t' && c != '\r' && c != '\n';
+        }).base(), copy.end());
+        return Str(copy);
+    }
+
     Str lower() const{
         std::string copy(data, size);
         std::transform(copy.begin(), copy.end(), copy.begin(), [](unsigned char c){ return std::tolower(c); });

+ 5 - 1
src/vm.h

@@ -1561,7 +1561,11 @@ inline PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring,
         throw std::runtime_error("expected 1 function declaration");
     }
     FuncDecl_ decl = co->func_decls[0];
-    PyObject* f_obj = VAR(NativeFunc(fn, decl, docstring));
+    decl->signature = Str(sig);
+    if(docstring != nullptr){
+        decl->docstring = Str(docstring).strip();
+    }
+    PyObject* f_obj = VAR(NativeFunc(fn, decl));
     obj->attr().set(decl->code->name, f_obj);
     return f_obj;
 }