Bladeren bron

up

rename

rename

rename
blueloveTH 3 jaren geleden
bovenliggende
commit
48e91c4f50
13 gewijzigde bestanden met toevoegingen van 303 en 309 verwijderingen
  1. 18 2
      plugins/flutter/README.md
  2. 4 4
      plugins/flutter/lib/no_web.dart
  3. 3 3
      plugins/flutter/lib/web.dart
  4. 232 246
      plugins/flutter/src/pocketpy.h
  5. 1 1
      src/codeobject.h
  6. 1 1
      src/common.h
  7. 3 3
      src/iter.h
  8. 3 3
      src/main.cpp
  9. 7 7
      src/obj.h
  10. 7 7
      src/pocketpy.h
  11. 5 13
      src/repl.h
  12. 18 18
      src/vm.h
  13. 1 1
      web/index.js

+ 18 - 2
plugins/flutter/README.md

@@ -1,8 +1,24 @@
 # 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
 
 The following table shows the basic features of PocketPy with respect to [CPython](https://github.com/python/cpython).

+ 4 - 4
plugins/flutter/lib/no_web.dart

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

+ 3 - 3
plugins/flutter/lib/web.dart

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

File diff suppressed because it is too large
+ 232 - 246
plugins/flutter/src/pocketpy.h


+ 1 - 1
src/codeobject.h

@@ -172,7 +172,7 @@ struct Frame {
         _StrStream ss;
         ss << "[";
         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 << ", ";
         }
         ss << "]";

+ 1 - 1
src/common.h

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

+ 3 - 3
src/iter.h

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

+ 3 - 3
src/main.cpp

@@ -26,12 +26,12 @@ int main(int argc, char** argv){
     });
     if(argc == 1){
         REPL* repl = pkpy_new_repl(vm);
-        int result = -1;
+        bool need_more_lines = false;
         while(true){
-            (*vm->_stdout) << (result==0 ? "... " : ">>> ");
+            (*vm->_stdout) << (need_more_lines ? "... " : ">>> ");
             std::string 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);
         return 0;

+ 7 - 7
src/obj.h

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

+ 7 - 7
src/pocketpy.h

@@ -128,7 +128,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
         PyVar _self = args[0];
         std::stringstream ss;
         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);
     });
 
@@ -578,16 +578,16 @@ struct ReMatch {
 
     static PyVar _bind(VM* vm){
         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, "end", CPP_LAMBDA(vm->PyInt(UNION_GET(ReMatch, args[0]).end)));
+        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(OBJ_GET(ReMatch, args[0]).end)));
 
         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) });
         });
 
         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]);
             index = vm->normalized_index(index, m.m.size());
             return vm->PyStr(m.m[index].str());
@@ -736,8 +736,8 @@ extern "C" {
     }
 
     __EXPORT
-    /// Input a source line to an interactive console.
-    int pkpy_repl_input(REPL* r, const char* line){
+    /// Input a source line to an interactive console. Return true if need more lines.
+    bool pkpy_repl_input(REPL* r, const char* line){
         return r->input(line);
     }
 

+ 5 - 13
src/repl.h

@@ -3,12 +3,6 @@
 #include "compiler.h"
 #include "vm.h"
 
-enum InputResult {
-    NEED_MORE_LINES = 0,
-    EXEC_STARTED = 1,
-    EXEC_SKIPPED = 2,
-};
-
 class REPL {
 protected:
     int need_more_lines = 0;
@@ -21,7 +15,7 @@ public:
         (*vm->_stdout) << ("Type \"exit()\" to exit." "\n");
     }
 
-    InputResult input(std::string line){
+    bool input(std::string line){
         CompileMode mode = SINGLE_MODE;
         if(need_more_lines){
             buffer += line;
@@ -37,20 +31,18 @@ public:
                 mode = EXEC_MODE;
             }else{
 __NOT_ENOUGH_LINES:
-                return NEED_MORE_LINES;
+                return true;
             }
-        }else{
-            if(line.empty()) return EXEC_SKIPPED;
         }
-
+        
         try{
             vm->exec(line, "<stdin>", mode);
         }catch(NeedMoreLines& ne){
             buffer += line;
             buffer += '\n';
             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;
     }
 };

+ 18 - 18
src/vm.h

@@ -7,7 +7,7 @@
 #define __DEF_PY_AS_C(type, ctype, ptype)                       \
     inline ctype& Py##type##_AS_C(const PyVar& obj) {           \
         check_type(obj, ptype);                                \
-        return UNION_GET(ctype, obj);                           \
+        return OBJ_GET(ctype, obj);                           \
     }
 
 #define __DEF_PY(type, ctype, ptype)                            \
@@ -254,7 +254,7 @@ class VM {
                         PyIter_AS_C(tmp)->var = var;
                         frame->push(std::move(tmp));
                     }else{
-                        typeError("'" + UNION_TP_NAME(obj) + "' object is not iterable");
+                        typeError("'" + OBJ_TP_NAME(obj) + "' object is not iterable");
                     }
                 } break;
             case OP_FOR_ITER:
@@ -383,7 +383,7 @@ public:
     }
 
     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__);
     }
 
@@ -453,7 +453,7 @@ public:
         }
         
         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
             return f(this, args);
         } else if((*callable)->is_type(_tp_function)){
@@ -513,7 +513,7 @@ public:
             }
             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;
     }
 
@@ -587,10 +587,10 @@ public:
     }
 
     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);
         _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(mod, name, obj);
         return obj;
@@ -598,7 +598,7 @@ public:
 
     PyVar new_type_object(_Str name, PyVar base=nullptr) {
         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);
         _types[name] = obj;
         return obj;
@@ -607,7 +607,7 @@ public:
     template<typename T>
     inline PyVar new_object(PyVar type, T _value) {
         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>
@@ -636,7 +636,7 @@ public:
             const PyVar* root = &obj;
             int depth = 1;
             while(true){
-                root = &UNION_GET(PyVar, *root);
+                root = &OBJ_GET(PyVar, *root);
                 if(!(*root)->is_type(_tp_super)) break;
                 depth++;
             }
@@ -670,7 +670,7 @@ public:
     template<typename T>
     inline void setattr(PyVar& obj, const _Str& name, T&& value) {
         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);
     }
 
@@ -711,7 +711,7 @@ public:
         }else if(obj->is_type(_tp_float)){
             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;
     }
 
@@ -838,8 +838,8 @@ public:
     inline const PyVar& PyBool(bool value){return value ? True : False;}
 
     void initializeBuiltinClasses(){
-        _tp_object = pkpy::make_shared<PyObject, Py_<i64>>(DUMMY_VAL, nullptr);
-        _tp_type = 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>>(nullptr, DUMMY_VAL);
         _types["object"] = _tp_object;
         _types["type"] = _tp_type;
 
@@ -901,7 +901,7 @@ public:
             }
             return x;
         }
-        typeError("unhashable type: " +  UNION_TP_NAME(obj));
+        typeError("unhashable type: " +  OBJ_TP_NAME(obj));
         return 0;
     }
 
@@ -934,11 +934,11 @@ public:
     void nameError(const _Str& name){ _error("NameError", "name '" + name + "' is not defined"); }
 
     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){
-        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() {
@@ -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)){
         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("not enough values to unpack");
     for (int i = 0; i < varRefs.size(); i++) {

+ 1 - 1
web/index.js

@@ -34,7 +34,7 @@ function term_init() {
             term.write("Bye!\r\n");
             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 = '';
           term.write(need_more_lines ? "... " : ">>> ");
           break;

Some files were not shown because too many files changed in this diff