diff --git a/.gitignore b/.gitignore index 6714e503..ee394036 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ pocketpy.dSYM main pypi/ +libpocketpy.dylib diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e9c2b91..d2cee2ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,9 +18,9 @@ if(NOT ${PREBUILD_RESULT} EQUAL 0) endif() if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR- /EHsc /utf-8 /O2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /utf-8 /O2") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fexceptions -O2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions -O2") endif() include_directories(${CMAKE_CURRENT_LIST_DIR}/include) diff --git a/README.md b/README.md index 818a48ed..6a4a5f61 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,6 @@ To compile it with your project, these flags must be set: + `--std=c++17` flag must be set + Exception must be enabled -+ RTTI is not required ### Example diff --git a/build.sh b/build.sh index 630e9e92..5c81603d 100644 --- a/build.sh +++ b/build.sh @@ -1,14 +1,16 @@ python3 prebuild.py SRC=$(find src/ -name "*.cpp") -FLAGS="-std=c++17 -fno-rtti -O2 -stdlib=libc++ -Wfatal-errors -Iinclude" +FLAGS="-std=c++17 -O2 -stdlib=libc++ -Wfatal-errors -Iinclude" if [[ "$OSTYPE" == "darwin"* ]]; then LIB_EXTENSION=".dylib" FLAGS="$FLAGS -undefined dynamic_lookup" + LINK_FLAGS="" else LIB_EXTENSION=".so" + LINK_FLAGS="-Wl,-rpath=." fi clang++ $FLAGS -o libpocketpy$LIB_EXTENSION $SRC -fPIC -shared -ldl # compile main.cpp and link to libpocketpy.so -clang++ $FLAGS -o main src2/main.cpp -L. -lpocketpy -Wl,-rpath=. \ No newline at end of file +clang++ $FLAGS -o main src2/main.cpp -L. -lpocketpy $LINK_FLAGS \ No newline at end of file diff --git a/build_web.sh b/build_web.sh index bfc5738a..9ed30b58 100644 --- a/build_web.sh +++ b/build_web.sh @@ -4,4 +4,4 @@ rm -rf web/lib mkdir web/lib SRC=$(find src/ -name "*.cpp") -em++ $SRC -Iinclude/ -fno-rtti -fexceptions -O3 -sEXPORTED_FUNCTIONS=_pkpy_new_repl,_pkpy_repl_input,_pkpy_new_vm -sEXPORTED_RUNTIME_METHODS=ccall -o web/lib/pocketpy.js \ No newline at end of file +em++ $SRC -Iinclude/ -fexceptions -O3 -sEXPORTED_FUNCTIONS=_pkpy_new_repl,_pkpy_repl_input,_pkpy_new_vm -sEXPORTED_RUNTIME_METHODS=ccall -o web/lib/pocketpy.js \ No newline at end of file diff --git a/c_bindings/test.c b/c_bindings/test.c index c1c78905..7d65d147 100644 --- a/c_bindings/test.c +++ b/c_bindings/test.c @@ -413,11 +413,11 @@ int main(int argc, char** argv) { PRINT_TITLE("test py_repr"); check(pkpy_eval(vm, "['1', 2, (3, '4')]")); - check(pkpy_py_repr(vm, -1)); + check(pkpy_py_repr(vm)); check(pkpy_to_string(vm, -1, &r_string)); for(int i = 0; i < r_string.size; i++) putchar(r_string.data[i]); putchar('\n'); - check(pkpy_pop(vm, 2)); + check(pkpy_pop_top(vm)); check(pkpy_stack_size(vm) == 0); return 0; } diff --git a/docs/C-API/stack.md b/docs/C-API/stack.md index e8d80a6d..88a426a1 100644 --- a/docs/C-API/stack.md +++ b/docs/C-API/stack.md @@ -6,6 +6,10 @@ order: 8 ### Basic manipulation ++ `bool pkpy_dup(pkpy_vm*, int)` + + Duplicate the value at the given index. + + `bool pkpy_pop(pkpy_vm*, int)` Pop `n` values from the stack. @@ -70,7 +74,7 @@ PK_EXPORT bool pkpy_is_none(pkpy_vm*, int i); + `pkpy_push_null(pkpy_vm*)` - Push a `PY_NULL` onto the stack. + Push a `PY_NULL` onto the stack. It is used for `pkpy_vectorcall`. + `pkpy_push_function(pkpy_vm*, const char* sig, pkpy_CFunction f)` @@ -140,10 +144,10 @@ PK_EXPORT bool pkpy_is_none(pkpy_vm*, int i); ``` [obj] -> [obj. self] ``` -+ `bool pkpy_py_repr(pkpy_vm*, int i)` ++ `bool pkpy_py_repr(pkpy_vm*)` - Get the repr of the value at the given index and push it onto the stack. + Get the repr of the value at the top of the stack. ``` - [..., value, ...] -> [..., value, ..., repr(value)] + [value] -> [repr(value)] ``` \ No newline at end of file diff --git a/docs/quick-start/installation.md b/docs/quick-start/installation.md index 3de66c02..28c4fa27 100644 --- a/docs/quick-start/installation.md +++ b/docs/quick-start/installation.md @@ -22,7 +22,6 @@ To compile it with your project, these flags must be set: + `--std=c++17` flag must be set + Exception must be enabled -+ RTTI is not required ### Example diff --git a/include/pocketpy/expr.h b/include/pocketpy/expr.h index 1ec109dc..41baf2b5 100644 --- a/include/pocketpy/expr.h +++ b/include/pocketpy/expr.h @@ -16,8 +16,6 @@ struct Expr{ int line = 0; virtual ~Expr() = default; virtual void emit(CodeEmitContext* ctx) = 0; - virtual std::string str() const = 0; - virtual bool is_literal() const { return false; } virtual bool is_json_object() const { return false; } virtual bool is_attrib() const { return false; } @@ -26,6 +24,8 @@ struct Expr{ virtual bool is_tuple() const { return false; } bool is_starred() const { return star_level() > 0; } + std::string str() const { PK_ASSERT(false); } + // for OP_DELETE_XXX [[nodiscard]] virtual bool emit_del(CodeEmitContext* ctx) { PK_UNUSED(ctx); @@ -70,9 +70,6 @@ struct NameExpr: Expr{ StrName name; NameScope scope; NameExpr(StrName name, NameScope scope): name(name), scope(scope) {} - - std::string str() const override { return fmt("Name(", name.escape(), ")"); } - void emit(CodeEmitContext* ctx) override; bool emit_del(CodeEmitContext* ctx) override; bool emit_store(CodeEmitContext* ctx) override; @@ -81,7 +78,6 @@ struct NameExpr: Expr{ struct InvertExpr: Expr{ Expr_ child; InvertExpr(Expr_&& child): child(std::move(child)) {} - std::string str() const override { return "Invert()"; } void emit(CodeEmitContext* ctx) override; }; @@ -89,7 +85,6 @@ struct StarredExpr: Expr{ int level; Expr_ child; StarredExpr(int level, Expr_&& child): level(level), child(std::move(child)) {} - std::string str() const override { return fmt("Starred(level=", level, ")"); } int star_level() const override { return level; } void emit(CodeEmitContext* ctx) override; bool emit_store(CodeEmitContext* ctx) override; @@ -98,22 +93,18 @@ struct StarredExpr: Expr{ struct NotExpr: Expr{ Expr_ child; NotExpr(Expr_&& child): child(std::move(child)) {} - std::string str() const override { return "Not()"; } - void emit(CodeEmitContext* ctx) override; }; struct AndExpr: Expr{ Expr_ lhs; Expr_ rhs; - std::string str() const override { return "And()"; } void emit(CodeEmitContext* ctx) override; }; struct OrExpr: Expr{ Expr_ lhs; Expr_ rhs; - std::string str() const override { return "Or()"; } void emit(CodeEmitContext* ctx) override; }; @@ -121,7 +112,6 @@ struct OrExpr: Expr{ struct Literal0Expr: Expr{ TokenIndex token; Literal0Expr(TokenIndex token): token(token) {} - std::string str() const override { return TK_STR(token); } bool is_json_object() const override { return true; } void emit(CodeEmitContext* ctx) override; @@ -130,14 +120,12 @@ struct Literal0Expr: Expr{ struct LongExpr: Expr{ Str s; LongExpr(const Str& s): s(s) {} - std::string str() const override { return s.str(); } void emit(CodeEmitContext* ctx) override; }; struct BytesExpr: Expr{ Str s; BytesExpr(const Str& s): s(s) {} - std::string str() const override { return s.str(); } void emit(CodeEmitContext* ctx) override; }; @@ -145,7 +133,6 @@ struct BytesExpr: Expr{ struct LiteralExpr: Expr{ TokenValue value; LiteralExpr(TokenValue value): value(value) {} - std::string str() const override; void emit(CodeEmitContext* ctx) override; bool is_literal() const override { return true; } bool is_json_object() const override { return true; } @@ -154,8 +141,6 @@ struct LiteralExpr: Expr{ struct NegatedExpr: Expr{ Expr_ child; NegatedExpr(Expr_&& child): child(std::move(child)) {} - std::string str() const override { return "Negated()"; } - void emit(CodeEmitContext* ctx) override; bool is_json_object() const override { return child->is_literal(); } }; @@ -164,14 +149,12 @@ struct SliceExpr: Expr{ Expr_ start; Expr_ stop; Expr_ step; - std::string str() const override { return "Slice()"; } void emit(CodeEmitContext* ctx) override; }; struct DictItemExpr: Expr{ Expr_ key; // maybe nullptr if it is **kwargs Expr_ value; - std::string str() const override { return "DictItem()"; } int star_level() const override { return value->star_level(); } void emit(CodeEmitContext* ctx) override; }; @@ -189,8 +172,6 @@ struct SequenceExpr: Expr{ struct ListExpr: SequenceExpr{ using SequenceExpr::SequenceExpr; - std::string str() const override { return "List()"; } - Opcode opcode() const override { for(auto& e: items) if(e->is_starred()) return OP_BUILD_LIST_UNPACK; return OP_BUILD_LIST; @@ -201,7 +182,6 @@ struct ListExpr: SequenceExpr{ struct DictExpr: SequenceExpr{ using SequenceExpr::SequenceExpr; - std::string str() const override { return "Dict()"; } Opcode opcode() const override { for(auto& e: items) if(e->is_starred()) return OP_BUILD_DICT_UNPACK; return OP_BUILD_DICT; @@ -212,7 +192,6 @@ struct DictExpr: SequenceExpr{ struct SetExpr: SequenceExpr{ using SequenceExpr::SequenceExpr; - std::string str() const override { return "Set()"; } Opcode opcode() const override { for(auto& e: items) if(e->is_starred()) return OP_BUILD_SET_UNPACK; return OP_BUILD_SET; @@ -221,7 +200,6 @@ struct SetExpr: SequenceExpr{ struct TupleExpr: SequenceExpr{ using SequenceExpr::SequenceExpr; - std::string str() const override { return "Tuple()"; } bool is_tuple() const override { return true; } Opcode opcode() const override { for(auto& e: items) if(e->is_starred()) return OP_BUILD_TUPLE_UNPACK; @@ -247,24 +225,20 @@ struct CompExpr: Expr{ struct ListCompExpr: CompExpr{ Opcode op0() override { return OP_BUILD_LIST; } Opcode op1() override { return OP_LIST_APPEND; } - std::string str() const override { return "ListComp()"; } }; struct DictCompExpr: CompExpr{ Opcode op0() override { return OP_BUILD_DICT; } Opcode op1() override { return OP_DICT_ADD; } - std::string str() const override { return "DictComp()"; } }; struct SetCompExpr: CompExpr{ Opcode op0() override { return OP_BUILD_SET; } Opcode op1() override { return OP_SET_ADD; } - std::string str() const override { return "SetComp()"; } }; struct LambdaExpr: Expr{ FuncDecl_ decl; - std::string str() const override { return "Lambda()"; } LambdaExpr(FuncDecl_ decl): decl(decl) {} @@ -277,10 +251,6 @@ struct LambdaExpr: Expr{ struct FStringExpr: Expr{ Str src; FStringExpr(const Str& src): src(src) {} - std::string str() const override { - return fmt("f", src.escape()); - } - void _load_simple_expr(CodeEmitContext* ctx, Str expr); void emit(CodeEmitContext* ctx) override; }; @@ -288,8 +258,6 @@ struct FStringExpr: Expr{ struct SubscrExpr: Expr{ Expr_ a; Expr_ b; - std::string str() const override { return "Subscr()"; } - void emit(CodeEmitContext* ctx) override; bool emit_del(CodeEmitContext* ctx) override; bool emit_store(CodeEmitContext* ctx) override; @@ -300,7 +268,6 @@ struct AttribExpr: Expr{ Str b; AttribExpr(Expr_ a, const Str& b): a(std::move(a)), b(b) {} AttribExpr(Expr_ a, Str&& b): a(std::move(a)), b(std::move(b)) {} - std::string str() const override { return "Attrib()"; } void emit(CodeEmitContext* ctx) override; bool emit_del(CodeEmitContext* ctx) override; @@ -314,14 +281,11 @@ struct CallExpr: Expr{ std::vector args; // **a will be interpreted as a special keyword argument: {"**": a} std::vector> kwargs; - std::string str() const override { return "Call()"; } void emit(CodeEmitContext* ctx) override; }; struct GroupedExpr: Expr{ Expr_ a; - std::string str() const override { return "Grouped()"; } - GroupedExpr(Expr_&& a): a(std::move(a)) {} void emit(CodeEmitContext* ctx) override{ @@ -341,8 +305,6 @@ struct BinaryExpr: Expr{ TokenIndex op; Expr_ lhs; Expr_ rhs; - std::string str() const override { return TK_STR(op); } - bool is_compare() const override; void _emit_compare(CodeEmitContext* ctx, std::vector& jmps); void emit(CodeEmitContext* ctx) override; @@ -353,7 +315,6 @@ struct TernaryExpr: Expr{ Expr_ cond; Expr_ true_expr; Expr_ false_expr; - std::string str() const override { return "Ternary()"; } void emit(CodeEmitContext* ctx) override; }; diff --git a/include/pocketpy/obj.h b/include/pocketpy/obj.h index e4aa3e92..ac66d73b 100644 --- a/include/pocketpy/obj.h +++ b/include/pocketpy/obj.h @@ -61,11 +61,12 @@ struct Bytes{ return _data != rhs._data; } - std::string str() const noexcept { return std::string(_data.begin(), _data.end()); } + Str str() const noexcept { return Str(_data.data(), _data.size()); } Bytes() : _data(), _ok(false) {} Bytes(std::vector&& data) : _data(std::move(data)), _ok(true) {} - Bytes(const std::string& data) : _data(data.begin(), data.end()), _ok(true) {} + Bytes(const Str& data) : _data(data.begin(), data.end()), _ok(true) {} + Bytes(std::string_view sv): _data(sv.begin(), sv.end()), _ok(true) {} operator bool() const noexcept { return _ok; } }; diff --git a/include/pocketpy/pocketpy_c.h b/include/pocketpy/pocketpy_c.h index 7e7a31ee..677aacc9 100644 --- a/include/pocketpy/pocketpy_c.h +++ b/include/pocketpy/pocketpy_c.h @@ -27,6 +27,7 @@ PK_EXPORT bool pkpy_exec(pkpy_vm*, const char* source); PK_EXPORT bool pkpy_exec_2(pkpy_vm*, const char* source, const char* filename, int mode, const char* module); /* Stack Manipulation */ +PK_EXPORT bool pkpy_dup(pkpy_vm*, int); PK_EXPORT bool pkpy_pop(pkpy_vm*, int); PK_EXPORT bool pkpy_pop_top(pkpy_vm*); PK_EXPORT bool pkpy_dup_top(pkpy_vm*); @@ -75,7 +76,7 @@ PK_EXPORT bool pkpy_setglobal(pkpy_vm*, pkpy_CName); PK_EXPORT bool pkpy_eval(pkpy_vm*, const char* source); PK_EXPORT bool pkpy_unpack_sequence(pkpy_vm*, int size); PK_EXPORT bool pkpy_get_unbound_method(pkpy_vm*, pkpy_CName); -PK_EXPORT bool pkpy_py_repr(pkpy_vm*, int i); +PK_EXPORT bool pkpy_py_repr(pkpy_vm*); /* Error Handling */ PK_EXPORT bool pkpy_error(pkpy_vm*, const char* name, pkpy_CString); diff --git a/plugins/flutter/src/CMakeLists.txt b/plugins/flutter/src/CMakeLists.txt index 3f2faf3d..0007b96f 100644 --- a/plugins/flutter/src/CMakeLists.txt +++ b/plugins/flutter/src/CMakeLists.txt @@ -13,12 +13,6 @@ add_library(pocketpy SHARED "pocketpy.cpp" ) -if (NOT MSVC) - target_compile_options(pocketpy PRIVATE -fno-rtti) -else() - target_compile_options(pocketpy PRIVATE /GR- /EHsc) -endif() - set_target_properties(pocketpy PROPERTIES PUBLIC_HEADER pocketpy.h OUTPUT_NAME "pocketpy" diff --git a/run_profile.sh b/run_profile.sh index 18acc550..33b1cdcb 100644 --- a/run_profile.sh +++ b/run_profile.sh @@ -1,6 +1,6 @@ python3 prebuild.py SRC=$(find src/ -name "*.cpp") -clang++ -pg -O1 -std=c++17 -fno-rtti -stdlib=libc++ -Wfatal-errors -o main $SRC -Iinclude -ldl +clang++ -pg -O1 -std=c++17 -stdlib=libc++ -Wfatal-errors -o main $SRC -Iinclude -ldl time ./main benchmarks/fib.py mv benchmarks/gmon.out . gprof pocketpy gmon.out > gprof.txt diff --git a/run_tests.sh b/run_tests.sh index 60dcb8ad..50b01a68 100644 --- a/run_tests.sh +++ b/run_tests.sh @@ -1,6 +1,6 @@ python3 prebuild.py SRC=$(find src/ -name "*.cpp") -clang++ -std=c++17 -fno-rtti --coverage -O1 -stdlib=libc++ -Wfatal-errors -o main src2/main.cpp $SRC -Iinclude -ldl +clang++ -std=c++17 --coverage -O1 -stdlib=libc++ -Wfatal-errors -o main src2/main.cpp $SRC -Iinclude -ldl python3 scripts/run_tests.py rm -rf .coverage mkdir .coverage diff --git a/src/expr.cpp b/src/expr.cpp index 665c066b..029089fe 100644 --- a/src/expr.cpp +++ b/src/expr.cpp @@ -196,20 +196,6 @@ namespace pkpy{ ctx->emit(OP_BUILD_BYTES, BC_NOARG, line); } - std::string LiteralExpr::str() const{ - if(std::holds_alternative(value)){ - return std::to_string(std::get(value)); - } - if(std::holds_alternative(value)){ - return std::to_string(std::get(value)); - } - if(std::holds_alternative(value)){ - Str s = std::get(value).escape(); - return s.str(); - } - FATAL_ERROR(); - } - void LiteralExpr::emit(CodeEmitContext* ctx) { VM* vm = ctx->vm; PyObject* obj = nullptr; diff --git a/src/io.cpp b/src/io.cpp index 6f250613..c6a080d4 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -40,7 +40,7 @@ Bytes _default_import_handler(const Str& name){ size_t sz = fread(buffer.data(), 1, buffer.size(), io.fp); PK_UNUSED(sz); Bytes b(std::move(buffer)); - if(io.is_text()) return VAR(Str(b.str())); + if(io.is_text()) return VAR(b.str()); return VAR(std::move(b)); }); diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 35d26daa..4a180cf3 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -916,7 +916,8 @@ void init_builtins(VM* _vm) { _vm->bind__hash__(_vm->tp_bytes, [](VM* vm, PyObject* obj) { const Bytes& self = _CAST(Bytes&, obj); - return (i64)std::hash()(self.str()); + std::string_view view(self.data(), self.size()); + return (i64)std::hash()(view); }); _vm->bind__repr__(_vm->tp_bytes, [](VM* vm, PyObject* obj) { diff --git a/src/pocketpy_c.cpp b/src/pocketpy_c.cpp index ea2be28a..cb84836e 100644 --- a/src/pocketpy_c.cpp +++ b/src/pocketpy_c.cpp @@ -89,6 +89,16 @@ bool pkpy_exec_2(pkpy_vm* vm_handle, const char* source, const char* filename, i return res != nullptr; } +bool pkpy_dup(pkpy_vm* vm_handle, int n){ + VM* vm = (VM*) vm_handle; + PK_ASSERT_NO_ERROR() + PK_PROTECTED( + PyObject* item = stack_item(vm, n); + vm->s_data.push(item); + ) + return true; +} + bool pkpy_pop(pkpy_vm* vm_handle, int n){ VM* vm = (VM*) vm_handle; PK_ASSERT_NO_ERROR() @@ -461,15 +471,15 @@ bool pkpy_get_unbound_method(pkpy_vm* vm_handle, pkpy_CName name){ return true; } -bool pkpy_py_repr(pkpy_vm* vm_handle, int i) { +bool pkpy_py_repr(pkpy_vm* vm_handle) { VM* vm = (VM*) vm_handle; PK_ASSERT_NO_ERROR() PK_ASSERT_N_EXTRA_ELEMENTS(1) + PyObject* item = vm->s_data.top(); PK_PROTECTED( - PyObject* item = stack_item(vm, i); - PyObject* repr = vm->py_repr(item); - vm->s_data.push(repr); + item = vm->py_repr(item); ) + vm->s_data.top() = item; return true; } diff --git a/tests/10_bytes.py b/tests/10_bytes.py index f982fa1e..f1a0f0c9 100644 --- a/tests/10_bytes.py +++ b/tests/10_bytes.py @@ -3,3 +3,6 @@ assert a.encode() == b'12345' assert b'\xff\xee' != b'1234' assert b'\xff\xee' == b'\xff\xee' + +a = '测试123' +assert a == a.encode().decode() \ No newline at end of file