rename

rename

rename
This commit is contained in:
blueloveTH 2023-02-04 20:35:26 +08:00
parent 7796369fb7
commit 48e91c4f50
13 changed files with 674 additions and 662 deletions

View File

@ -1,8 +1,24 @@
# Welcome to PocketPy # Welcome to PocketPy
PocketPy is a lightweight Python interpreter for game engines. PocketPy is a lightweight(~5000 LOC) Python interpreter for game engines.
![](https://pocketpy.dev/static/logo_flat.png) It is extremely easy to embed. Including a compiler, optimizer and bytecode virtual machine. All of them are available in a single header file `pocketpy.h`, without external dependencies.
## What it looks like
```python
def is_prime(x):
if x < 2:
return False
for i in range(2, x):
if x % i == 0:
return False
return True
primes = [i for i in range(2, 20) if is_prime(i)]
print(primes)
# [2, 3, 5, 7, 11, 13, 17, 19]
```
# basic # basic
The following table shows the basic features of PocketPy with respect to [CPython](https://github.com/python/cpython). The following table shows the basic features of PocketPy with respect to [CPython](https://github.com/python/cpython).

View File

@ -30,8 +30,8 @@ class _Bindings {
ffi.Pointer Function(ffi.Pointer vm), ffi.Pointer Function(ffi.Pointer vm),
ffi.Pointer Function(ffi.Pointer vm)>("pkpy_new_repl"); ffi.Pointer Function(ffi.Pointer vm)>("pkpy_new_repl");
static final pkpy_repl_input = _lib.lookupFunction< static final pkpy_repl_input = _lib.lookupFunction<
ffi.Int32 Function(ffi.Pointer r, ffi.Pointer<Utf8> line), ffi.Bool Function(ffi.Pointer r, ffi.Pointer<Utf8> line),
int Function(ffi.Pointer r, ffi.Pointer<Utf8> line)>("pkpy_repl_input"); bool Function(ffi.Pointer r, ffi.Pointer<Utf8> line)>("pkpy_repl_input");
static final pkpy_new_vm = _lib.lookupFunction< static final pkpy_new_vm = _lib.lookupFunction<
ffi.Pointer Function(ffi.Bool use_stdio), ffi.Pointer Function(ffi.Bool use_stdio),
ffi.Pointer Function(bool use_stdio)>("pkpy_new_vm"); ffi.Pointer Function(bool use_stdio)>("pkpy_new_vm");
@ -124,8 +124,8 @@ class REPL {
_Bindings.pkpy_delete(pointer); _Bindings.pkpy_delete(pointer);
} }
/// Input a source line to an interactive console. /// Input a source line to an interactive console. Return true if need more lines.
int input(String line) { bool input(String line) {
var ret = _Bindings.pkpy_repl_input(pointer, _Str(line).p); var ret = _Bindings.pkpy_repl_input(pointer, _Str(line).p);
return ret; return ret;
} }

View File

@ -13,7 +13,7 @@ class _Bindings {
static final pkpy_new_repl = static final pkpy_new_repl =
(dynamic vm) => ccall("pkpy_new_repl", "number", ["number"], [vm]); (dynamic vm) => ccall("pkpy_new_repl", "number", ["number"], [vm]);
static final pkpy_repl_input = (dynamic r, String line) => static final pkpy_repl_input = (dynamic r, String line) =>
ccall("pkpy_repl_input", "number", ["number", "string"], [r, line]); ccall("pkpy_repl_input", "boolean", ["number", "string"], [r, line]);
static final pkpy_new_vm = (bool use_stdio) => static final pkpy_new_vm = (bool use_stdio) =>
ccall("pkpy_new_vm", "number", ["boolean"], [use_stdio]); ccall("pkpy_new_vm", "number", ["boolean"], [use_stdio]);
static final pkpy_vm_add_module = (dynamic vm, String name, String source) => static final pkpy_vm_add_module = (dynamic vm, String name, String source) =>
@ -78,8 +78,8 @@ class REPL {
_Bindings.pkpy_delete(pointer); _Bindings.pkpy_delete(pointer);
} }
/// Input a source line to an interactive console. /// Input a source line to an interactive console. Return true if need more lines.
int input(String line) { bool input(String line) {
var ret = _Bindings.pkpy_repl_input(pointer, line); var ret = _Bindings.pkpy_repl_input(pointer, line);
return ret; return ret;
} }

File diff suppressed because it is too large Load Diff

View File

@ -172,7 +172,7 @@ struct Frame {
_StrStream ss; _StrStream ss;
ss << "["; ss << "[";
for(int i=0; i<_data.size(); i++){ for(int i=0; i<_data.size(); i++){
ss << UNION_TP_NAME(_data[i]); ss << OBJ_TP_NAME(_data[i]);
if(i != _data.size()-1) ss << ", "; if(i != _data.size()-1) ss << ", ";
} }
ss << "]"; ss << "]";

View File

@ -35,7 +35,7 @@
#include <emscripten.h> #include <emscripten.h>
#endif #endif
#define PK_VERSION "0.8.0" #define PK_VERSION "0.8.1"
typedef int64_t i64; typedef int64_t i64;
typedef double f64; typedef double f64;

View File

@ -8,7 +8,7 @@ private:
_Range r; _Range r;
public: public:
RangeIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) { RangeIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) {
this->r = UNION_GET(_Range, _ref); this->r = OBJ_GET(_Range, _ref);
this->current = r.start; this->current = r.start;
} }
@ -29,7 +29,7 @@ private:
const PyVarList* vec; const PyVarList* vec;
public: public:
VectorIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) { VectorIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) {
vec = &UNION_GET(PyVarList, _ref); vec = &OBJ_GET(PyVarList, _ref);
} }
bool hasNext(){ bool hasNext(){
@ -47,7 +47,7 @@ private:
_Str str; _Str str;
public: public:
StringIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) { StringIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) {
str = UNION_GET(_Str, _ref); str = OBJ_GET(_Str, _ref);
} }
bool hasNext(){ bool hasNext(){

View File

@ -26,12 +26,12 @@ int main(int argc, char** argv){
}); });
if(argc == 1){ if(argc == 1){
REPL* repl = pkpy_new_repl(vm); REPL* repl = pkpy_new_repl(vm);
int result = -1; bool need_more_lines = false;
while(true){ while(true){
(*vm->_stdout) << (result==0 ? "... " : ">>> "); (*vm->_stdout) << (need_more_lines ? "... " : ">>> ");
std::string line; std::string line;
std::getline(std::cin, line); std::getline(std::cin, line);
result = pkpy_repl_input(repl, line.c_str()); need_more_lines = pkpy_repl_input(repl, line.c_str());
} }
pkpy_delete(vm); pkpy_delete(vm);
return 0; return 0;

View File

@ -87,13 +87,13 @@ struct PyObject {
template <typename T> template <typename T>
struct Py_ : PyObject { struct Py_ : PyObject {
T _valueT; T _value;
Py_(T val, const PyVar& type) : PyObject(type), _valueT(val) {} Py_(const PyVar& type, T val) : PyObject(type), _value(val) {}
virtual void* value() override { return &_valueT; } virtual void* value() override { return &_value; }
}; };
//#define UNION_GET(T, obj) (((Py_<T>*)((obj).get()))->_valueT) //#define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value)
#define UNION_GET(T, obj) (*static_cast<T*>((obj)->value())) #define OBJ_GET(T, obj) (*static_cast<T*>((obj)->value()))
#define UNION_NAME(obj) UNION_GET(_Str, (obj)->attribs[__name__]) #define OBJ_NAME(obj) OBJ_GET(_Str, (obj)->attribs[__name__])
#define UNION_TP_NAME(obj) UNION_GET(_Str, (obj)->type->attribs[__name__]) #define OBJ_TP_NAME(obj) OBJ_GET(_Str, (obj)->type->attribs[__name__])

View File

@ -128,7 +128,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
PyVar _self = args[0]; PyVar _self = args[0];
std::stringstream ss; std::stringstream ss;
ss << std::hex << (uintptr_t)_self.get(); ss << std::hex << (uintptr_t)_self.get();
_Str s = "<" + UNION_TP_NAME(_self) + " object at 0x" + ss.str() + ">"; _Str s = "<" + OBJ_TP_NAME(_self) + " object at 0x" + ss.str() + ">";
return vm->PyStr(s); return vm->PyStr(s);
}); });
@ -578,16 +578,16 @@ struct ReMatch {
static PyVar _bind(VM* vm){ static PyVar _bind(VM* vm){
PyVar _tp_match = vm->new_user_type_object(vm->_modules["re"], "Match", vm->_tp_object); PyVar _tp_match = vm->new_user_type_object(vm->_modules["re"], "Match", vm->_tp_object);
vm->bindMethod<0>(_tp_match, "start", CPP_LAMBDA(vm->PyInt(UNION_GET(ReMatch, args[0]).start))); vm->bindMethod<0>(_tp_match, "start", CPP_LAMBDA(vm->PyInt(OBJ_GET(ReMatch, args[0]).start)));
vm->bindMethod<0>(_tp_match, "end", CPP_LAMBDA(vm->PyInt(UNION_GET(ReMatch, args[0]).end))); vm->bindMethod<0>(_tp_match, "end", CPP_LAMBDA(vm->PyInt(OBJ_GET(ReMatch, args[0]).end)));
vm->bindMethod<0>(_tp_match, "span", [](VM* vm, const pkpy::Args& args) { vm->bindMethod<0>(_tp_match, "span", [](VM* vm, const pkpy::Args& args) {
auto& m = UNION_GET(ReMatch, args[0]); auto& m = OBJ_GET(ReMatch, args[0]);
return vm->PyTuple({ vm->PyInt(m.start), vm->PyInt(m.end) }); return vm->PyTuple({ vm->PyInt(m.start), vm->PyInt(m.end) });
}); });
vm->bindMethod<1>(_tp_match, "group", [](VM* vm, const pkpy::Args& args) { vm->bindMethod<1>(_tp_match, "group", [](VM* vm, const pkpy::Args& args) {
auto& m = UNION_GET(ReMatch, args[0]); auto& m = OBJ_GET(ReMatch, args[0]);
int index = (int)vm->PyInt_AS_C(args[1]); int index = (int)vm->PyInt_AS_C(args[1]);
index = vm->normalized_index(index, m.m.size()); index = vm->normalized_index(index, m.m.size());
return vm->PyStr(m.m[index].str()); return vm->PyStr(m.m[index].str());
@ -736,8 +736,8 @@ extern "C" {
} }
__EXPORT __EXPORT
/// Input a source line to an interactive console. /// Input a source line to an interactive console. Return true if need more lines.
int pkpy_repl_input(REPL* r, const char* line){ bool pkpy_repl_input(REPL* r, const char* line){
return r->input(line); return r->input(line);
} }

View File

@ -3,12 +3,6 @@
#include "compiler.h" #include "compiler.h"
#include "vm.h" #include "vm.h"
enum InputResult {
NEED_MORE_LINES = 0,
EXEC_STARTED = 1,
EXEC_SKIPPED = 2,
};
class REPL { class REPL {
protected: protected:
int need_more_lines = 0; int need_more_lines = 0;
@ -21,7 +15,7 @@ public:
(*vm->_stdout) << ("Type \"exit()\" to exit." "\n"); (*vm->_stdout) << ("Type \"exit()\" to exit." "\n");
} }
InputResult input(std::string line){ bool input(std::string line){
CompileMode mode = SINGLE_MODE; CompileMode mode = SINGLE_MODE;
if(need_more_lines){ if(need_more_lines){
buffer += line; buffer += line;
@ -37,10 +31,8 @@ public:
mode = EXEC_MODE; mode = EXEC_MODE;
}else{ }else{
__NOT_ENOUGH_LINES: __NOT_ENOUGH_LINES:
return NEED_MORE_LINES; return true;
} }
}else{
if(line.empty()) return EXEC_SKIPPED;
} }
try{ try{
@ -49,8 +41,8 @@ __NOT_ENOUGH_LINES:
buffer += line; buffer += line;
buffer += '\n'; buffer += '\n';
need_more_lines = ne.isClassDef ? 3 : 2; need_more_lines = ne.isClassDef ? 3 : 2;
if (need_more_lines) return NEED_MORE_LINES; if (need_more_lines) return true;
} }
return EXEC_STARTED; return false;
} }
}; };

View File

@ -7,7 +7,7 @@
#define __DEF_PY_AS_C(type, ctype, ptype) \ #define __DEF_PY_AS_C(type, ctype, ptype) \
inline ctype& Py##type##_AS_C(const PyVar& obj) { \ inline ctype& Py##type##_AS_C(const PyVar& obj) { \
check_type(obj, ptype); \ check_type(obj, ptype); \
return UNION_GET(ctype, obj); \ return OBJ_GET(ctype, obj); \
} }
#define __DEF_PY(type, ctype, ptype) \ #define __DEF_PY(type, ctype, ptype) \
@ -254,7 +254,7 @@ class VM {
PyIter_AS_C(tmp)->var = var; PyIter_AS_C(tmp)->var = var;
frame->push(std::move(tmp)); frame->push(std::move(tmp));
}else{ }else{
typeError("'" + UNION_TP_NAME(obj) + "' object is not iterable"); typeError("'" + OBJ_TP_NAME(obj) + "' object is not iterable");
} }
} break; } break;
case OP_FOR_ITER: case OP_FOR_ITER:
@ -383,7 +383,7 @@ public:
} }
PyVar asRepr(const PyVar& obj){ PyVar asRepr(const PyVar& obj){
if(obj->is_type(_tp_type)) return PyStr("<class '" + UNION_GET(_Str, obj->attribs[__name__]) + "'>"); if(obj->is_type(_tp_type)) return PyStr("<class '" + OBJ_GET(_Str, obj->attribs[__name__]) + "'>");
return call(obj, __repr__); return call(obj, __repr__);
} }
@ -453,7 +453,7 @@ public:
} }
if((*callable)->is_type(_tp_native_function)){ if((*callable)->is_type(_tp_native_function)){
const auto& f = UNION_GET(_CppFunc, *callable); const auto& f = OBJ_GET(_CppFunc, *callable);
// _CppFunc do not support kwargs // _CppFunc do not support kwargs
return f(this, args); return f(this, args);
} else if((*callable)->is_type(_tp_function)){ } else if((*callable)->is_type(_tp_function)){
@ -513,7 +513,7 @@ public:
} }
return _exec(fn->code, _module, _locals); return _exec(fn->code, _module, _locals);
} }
typeError("'" + UNION_TP_NAME(*callable) + "' object is not callable"); typeError("'" + OBJ_TP_NAME(*callable) + "' object is not callable");
return None; return None;
} }
@ -587,10 +587,10 @@ public:
} }
PyVar new_user_type_object(PyVar mod, _Str name, PyVar base){ PyVar new_user_type_object(PyVar mod, _Str name, PyVar base){
PyVar obj = pkpy::make_shared<PyObject, Py_<i64>>(DUMMY_VAL, _tp_type); PyVar obj = pkpy::make_shared<PyObject, Py_<i64>>(_tp_type, DUMMY_VAL);
setattr(obj, __base__, base); setattr(obj, __base__, base);
_Str fullName = name; _Str fullName = name;
if(mod != builtins) fullName = UNION_NAME(mod) + "." + name; if(mod != builtins) fullName = OBJ_NAME(mod) + "." + name;
setattr(obj, __name__, PyStr(fullName)); setattr(obj, __name__, PyStr(fullName));
setattr(mod, name, obj); setattr(mod, name, obj);
return obj; return obj;
@ -598,7 +598,7 @@ public:
PyVar new_type_object(_Str name, PyVar base=nullptr) { PyVar new_type_object(_Str name, PyVar base=nullptr) {
if(base == nullptr) base = _tp_object; if(base == nullptr) base = _tp_object;
PyVar obj = pkpy::make_shared<PyObject, Py_<i64>>(DUMMY_VAL, _tp_type); PyVar obj = pkpy::make_shared<PyObject, Py_<i64>>(_tp_type, DUMMY_VAL);
setattr(obj, __base__, base); setattr(obj, __base__, base);
_types[name] = obj; _types[name] = obj;
return obj; return obj;
@ -607,7 +607,7 @@ public:
template<typename T> template<typename T>
inline PyVar new_object(PyVar type, T _value) { inline PyVar new_object(PyVar type, T _value) {
if(!type->is_type(_tp_type)) UNREACHABLE(); if(!type->is_type(_tp_type)) UNREACHABLE();
return pkpy::make_shared<PyObject, Py_<T>>(_value, type); return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
} }
template<typename T, typename... Args> template<typename T, typename... Args>
@ -636,7 +636,7 @@ public:
const PyVar* root = &obj; const PyVar* root = &obj;
int depth = 1; int depth = 1;
while(true){ while(true){
root = &UNION_GET(PyVar, *root); root = &OBJ_GET(PyVar, *root);
if(!(*root)->is_type(_tp_super)) break; if(!(*root)->is_type(_tp_super)) break;
depth++; depth++;
} }
@ -670,7 +670,7 @@ public:
template<typename T> template<typename T>
inline void setattr(PyVar& obj, const _Str& name, T&& value) { inline void setattr(PyVar& obj, const _Str& name, T&& value) {
PyObject* p = obj.get(); PyObject* p = obj.get();
while(p->is_type(_tp_super)) p = ((Py_<PyVar>*)p)->_valueT.get(); while(p->is_type(_tp_super)) p = static_cast<PyVar*>(p->value())->get();
p->attribs[name] = std::forward<T>(value); p->attribs[name] = std::forward<T>(value);
} }
@ -711,7 +711,7 @@ public:
}else if(obj->is_type(_tp_float)){ }else if(obj->is_type(_tp_float)){
return PyFloat_AS_C(obj); return PyFloat_AS_C(obj);
} }
typeError("expected int or float, got " + UNION_TP_NAME(obj)); typeError("expected int or float, got " + OBJ_TP_NAME(obj));
return 0; return 0;
} }
@ -838,8 +838,8 @@ public:
inline const PyVar& PyBool(bool value){return value ? True : False;} inline const PyVar& PyBool(bool value){return value ? True : False;}
void initializeBuiltinClasses(){ void initializeBuiltinClasses(){
_tp_object = pkpy::make_shared<PyObject, Py_<i64>>(DUMMY_VAL, nullptr); _tp_object = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
_tp_type = pkpy::make_shared<PyObject, Py_<i64>>(DUMMY_VAL, nullptr); _tp_type = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
_types["object"] = _tp_object; _types["object"] = _tp_object;
_types["type"] = _tp_type; _types["type"] = _tp_type;
@ -901,7 +901,7 @@ public:
} }
return x; return x;
} }
typeError("unhashable type: " + UNION_TP_NAME(obj)); typeError("unhashable type: " + OBJ_TP_NAME(obj));
return 0; return 0;
} }
@ -934,11 +934,11 @@ public:
void nameError(const _Str& name){ _error("NameError", "name '" + name + "' is not defined"); } void nameError(const _Str& name){ _error("NameError", "name '" + name + "' is not defined"); }
void attributeError(PyVar obj, const _Str& name){ void attributeError(PyVar obj, const _Str& name){
_error("AttributeError", "type '" + UNION_TP_NAME(obj) + "' has no attribute '" + name + "'"); _error("AttributeError", "type '" + OBJ_TP_NAME(obj) + "' has no attribute '" + name + "'");
} }
inline void check_type(const PyVar& obj, const PyVar& type){ inline void check_type(const PyVar& obj, const PyVar& type){
if(!obj->is_type(type)) typeError("expected '" + UNION_NAME(type) + "', but got '" + UNION_TP_NAME(obj) + "'"); if(!obj->is_type(type)) typeError("expected '" + OBJ_NAME(type) + "', but got '" + OBJ_TP_NAME(obj) + "'");
} }
~VM() { ~VM() {
@ -1041,7 +1041,7 @@ void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{
if(!val->is_type(vm->_tp_tuple) && !val->is_type(vm->_tp_list)){ if(!val->is_type(vm->_tp_tuple) && !val->is_type(vm->_tp_list)){
vm->typeError("only tuple or list can be unpacked"); vm->typeError("only tuple or list can be unpacked");
} }
const PyVarList& args = UNION_GET(PyVarList, val); const PyVarList& args = OBJ_GET(PyVarList, val);
if(args.size() > varRefs.size()) vm->valueError("too many values to unpack"); if(args.size() > varRefs.size()) vm->valueError("too many values to unpack");
if(args.size() < varRefs.size()) vm->valueError("not enough values to unpack"); if(args.size() < varRefs.size()) vm->valueError("not enough values to unpack");
for (int i = 0; i < varRefs.size(); i++) { for (int i = 0; i < varRefs.size(); i++) {

View File

@ -34,7 +34,7 @@ function term_init() {
term.write("Bye!\r\n"); term.write("Bye!\r\n");
break; break;
} }
need_more_lines = Module.ccall('pkpy_repl_input', 'number', ['number', 'string'], [repl, command]) == 0; need_more_lines = Module.ccall('pkpy_repl_input', 'bool', ['number', 'string'], [repl, command]);
command = ''; command = '';
term.write(need_more_lines ? "... " : ">>> "); term.write(need_more_lines ? "... " : ">>> ");
break; break;