diff --git a/README_zh.md b/README_zh.md index 43722093..b1a102c9 100644 --- a/README_zh.md +++ b/README_zh.md @@ -37,8 +37,7 @@ int main(){ pkpy_vm_exec(vm, "print(sum(a))"); // 释放资源 - pkpy_delete(result); - pkpy_delete(vm); + pkpy_delete_vm(vm); return 0; } ``` diff --git a/amalgamate.py b/amalgamate.py index c87bbe06..67c8d5a3 100644 --- a/amalgamate.py +++ b/amalgamate.py @@ -9,7 +9,7 @@ pipeline = [ ["common.h", "memory.h", "vector.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "lexer.h"], ["obj.h", "dict.h", "codeobject.h", "frame.h"], ["gc.h", "vm.h", "ceval.h", "expr.h", "compiler.h", "repl.h"], - ["_generated.h", "cffi.h", "iter.h", "base64.h", "linalg.h", "easing.h", "requests.h", "io.h"], + ["_generated.h", "cffi.h", "iter.h", "base64.h", "re.h", "linalg.h", "easing.h", "requests.h", "io.h"], ["export.h", "pocketpy.h"] ] diff --git a/docs/C-API/vm.md b/docs/C-API/vm.md index 200cd057..4164f294 100644 --- a/docs/C-API/vm.md +++ b/docs/C-API/vm.md @@ -20,11 +20,14 @@ Run a given source on a virtual machine. Advanced version of `pkpy_vm_exec`. -#### `void pkpy_delete(void* p)` +#### `void pkpy_free(void* p)` -Delete a pointer allocated by `pkpy_xxx_xxx`. -It can be `VM*`, `REPL*`, `char*`, etc. +Free a pointer via `free`. -!!! -If the pointer is not allocated by `pkpy_xxx_xxx`, the behavior is undefined. -!!! +#### `void pkpy_delete_vm(VM* vm)` + +Delete a virtual machine. + +#### `void pkpy_delete_repl(REPL* repl)` + +Delete a REPL. \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5596db15..de93aac4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,7 +22,7 @@ int main(int argc, char** argv){ if(eof) break; need_more_lines = pkpy_repl_input(repl, line.c_str()); } - pkpy_delete(vm); + pkpy_delete_vm(vm); return 0; } @@ -49,7 +49,7 @@ int main(int argc, char** argv){ pkpy::PyObject* ret = nullptr; ret = vm->exec(src.c_str(), filepath.filename().string(), pkpy::EXEC_MODE); - pkpy_delete(vm); + pkpy_delete_vm(vm); return ret != nullptr ? 0 : 1; } diff --git a/src/pocketpy.h b/src/pocketpy.h index 43a75a13..8a37e70f 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -14,6 +14,7 @@ #include "_generated.h" #include "export.h" #include "vm.h" +#include "re.h" namespace pkpy { @@ -1263,83 +1264,6 @@ inline void add_module_dis(VM* vm){ }); } -struct ReMatch { - PY_CLASS(ReMatch, re, Match) - - i64 start; - i64 end; - std::cmatch m; - ReMatch(i64 start, i64 end, std::cmatch m) : start(start), end(end), m(m) {} - - static void _register(VM* vm, PyObject* mod, PyObject* type){ - vm->bind_notimplemented_constructor(type); - vm->bind_method<0>(type, "start", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).start))); - vm->bind_method<0>(type, "end", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).end))); - - vm->bind_method<0>(type, "span", [](VM* vm, ArgsView args) { - auto& self = _CAST(ReMatch&, args[0]); - return VAR(Tuple({VAR(self.start), VAR(self.end)})); - }); - - vm->bind_method<1>(type, "group", [](VM* vm, ArgsView args) { - auto& self = _CAST(ReMatch&, args[0]); - int index = CAST(int, args[1]); - index = vm->normalized_index(index, self.m.size()); - return VAR(self.m[index].str()); - }); - } -}; - -inline PyObject* _regex_search(const Str& pattern, const Str& string, bool from_start, VM* vm){ - std::regex re(pattern.begin(), pattern.end()); - std::cmatch m; - if(std::regex_search(string.begin(), string.end(), m, re)){ - if(from_start && m.position() != 0) return vm->None; - i64 start = string._byte_index_to_unicode(m.position()); - i64 end = string._byte_index_to_unicode(m.position() + m.length()); - return VAR_T(ReMatch, start, end, m); - } - return vm->None; -}; - -inline void add_module_re(VM* vm){ - PyObject* mod = vm->new_module("re"); - ReMatch::register_class(vm, mod); - - vm->bind_func<2>(mod, "match", [](VM* vm, ArgsView args) { - const Str& pattern = CAST(Str&, args[0]); - const Str& string = CAST(Str&, args[1]); - return _regex_search(pattern, string, true, vm); - }); - - vm->bind_func<2>(mod, "search", [](VM* vm, ArgsView args) { - const Str& pattern = CAST(Str&, args[0]); - const Str& string = CAST(Str&, args[1]); - return _regex_search(pattern, string, false, vm); - }); - - vm->bind_func<3>(mod, "sub", [](VM* vm, ArgsView args) { - const Str& pattern = CAST(Str&, args[0]); - const Str& repl = CAST(Str&, args[1]); - const Str& string = CAST(Str&, args[2]); - std::regex re(pattern.begin(), pattern.end()); - return VAR(std::regex_replace(string.str(), re, repl.str())); - }); - - vm->bind_func<2>(mod, "split", [](VM* vm, ArgsView args) { - const Str& pattern = CAST(Str&, args[0]); - const Str& string = CAST(Str&, args[1]); - std::regex re(pattern.begin(), pattern.end()); - std::cregex_token_iterator it(string.begin(), string.end(), re, -1); - std::cregex_token_iterator end; - List vec; - for(; it != end; ++it){ - vec.push_back(VAR(it->str())); - } - return VAR(vec); - }); -} - struct Random{ PY_CLASS(Random, random, Random) std::mt19937 gen; @@ -1469,17 +1393,10 @@ inline void VM::post_init(){ } // namespace pkpy /*************************GLOBAL NAMESPACE*************************/ -static std::map _pk_deleter_map; - extern "C" { PK_LEGACY_EXPORT - void pkpy_delete(void* p){ - auto it = _pk_deleter_map.find(p); - if(it != _pk_deleter_map.end()){ - it->second(p); - }else{ - free(p); - } + void pkpy_free(void* p){ + free(p); } PK_LEGACY_EXPORT @@ -1501,7 +1418,6 @@ extern "C" { PK_LEGACY_EXPORT pkpy::REPL* pkpy_new_repl(pkpy::VM* vm){ pkpy::REPL* p = new pkpy::REPL(vm); - _pk_deleter_map[p] = [](void* p){ delete (pkpy::REPL*)p; }; return p; } @@ -1518,10 +1434,19 @@ extern "C" { PK_LEGACY_EXPORT pkpy::VM* pkpy_new_vm(bool enable_os=true){ pkpy::VM* p = new pkpy::VM(enable_os); - _pk_deleter_map[p] = [](void* p){ delete (pkpy::VM*)p; }; return p; } + PK_LEGACY_EXPORT + void pkpy_delete_vm(pkpy::VM* vm){ + delete vm; + } + + PK_LEGACY_EXPORT + void pkpy_delete_repl(pkpy::REPL* repl){ + delete repl; + } + PK_LEGACY_EXPORT void pkpy_vm_gc_on_delete(pkpy::VM* vm, void (*f)(pkpy::VM *, pkpy::PyObject *)){ vm->heap._gc_on_delete = f; diff --git a/src/re.h b/src/re.h new file mode 100644 index 00000000..045a7dac --- /dev/null +++ b/src/re.h @@ -0,0 +1,84 @@ +#pragma once + +#include "cffi.h" + +namespace pkpy{ + +struct ReMatch { + PY_CLASS(ReMatch, re, Match) + + i64 start; + i64 end; + std::cmatch m; + ReMatch(i64 start, i64 end, std::cmatch m) : start(start), end(end), m(m) {} + + static void _register(VM* vm, PyObject* mod, PyObject* type){ + vm->bind_notimplemented_constructor(type); + vm->bind_method<0>(type, "start", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).start))); + vm->bind_method<0>(type, "end", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).end))); + + vm->bind_method<0>(type, "span", [](VM* vm, ArgsView args) { + auto& self = _CAST(ReMatch&, args[0]); + return VAR(Tuple({VAR(self.start), VAR(self.end)})); + }); + + vm->bind_method<1>(type, "group", [](VM* vm, ArgsView args) { + auto& self = _CAST(ReMatch&, args[0]); + int index = CAST(int, args[1]); + index = vm->normalized_index(index, self.m.size()); + return VAR(self.m[index].str()); + }); + } +}; + +inline PyObject* _regex_search(const Str& pattern, const Str& string, bool from_start, VM* vm){ + std::regex re(pattern.begin(), pattern.end()); + std::cmatch m; + if(std::regex_search(string.begin(), string.end(), m, re)){ + if(from_start && m.position() != 0) return vm->None; + i64 start = string._byte_index_to_unicode(m.position()); + i64 end = string._byte_index_to_unicode(m.position() + m.length()); + return VAR_T(ReMatch, start, end, m); + } + return vm->None; +}; + +inline void add_module_re(VM* vm){ + PyObject* mod = vm->new_module("re"); + ReMatch::register_class(vm, mod); + + vm->bind_func<2>(mod, "match", [](VM* vm, ArgsView args) { + const Str& pattern = CAST(Str&, args[0]); + const Str& string = CAST(Str&, args[1]); + return _regex_search(pattern, string, true, vm); + }); + + vm->bind_func<2>(mod, "search", [](VM* vm, ArgsView args) { + const Str& pattern = CAST(Str&, args[0]); + const Str& string = CAST(Str&, args[1]); + return _regex_search(pattern, string, false, vm); + }); + + vm->bind_func<3>(mod, "sub", [](VM* vm, ArgsView args) { + const Str& pattern = CAST(Str&, args[0]); + const Str& repl = CAST(Str&, args[1]); + const Str& string = CAST(Str&, args[2]); + std::regex re(pattern.begin(), pattern.end()); + return VAR(std::regex_replace(string.str(), re, repl.str())); + }); + + vm->bind_func<2>(mod, "split", [](VM* vm, ArgsView args) { + const Str& pattern = CAST(Str&, args[0]); + const Str& string = CAST(Str&, args[1]); + std::regex re(pattern.begin(), pattern.end()); + std::cregex_token_iterator it(string.begin(), string.end(), re, -1); + std::cregex_token_iterator end; + List vec; + for(; it != end; ++it){ + vec.push_back(VAR(it->str())); + } + return VAR(vec); + }); +} + +} // namespace pkpy