Prechádzať zdrojové kódy

add __iter__ and __new__ for some types

blueloveTH 3 rokov pred
rodič
commit
aa0c415f1d
7 zmenil súbory, kde vykonal 116 pridanie a 28 odobranie
  1. 2 0
      src/builtins.h
  2. 1 1
      src/error.h
  3. 21 12
      src/iter.h
  4. 8 4
      src/obj.h
  5. 60 6
      src/pocketpy.h
  6. 11 3
      src/str.h
  7. 13 2
      src/vm.h

+ 2 - 0
src/builtins.h

@@ -60,6 +60,8 @@ list.__contains__ = __iterable4__contains__
 tuple.__contains__ = __iterable4__contains__
 del __iterable4__contains__
 
+list.__new__ = lambda obj: [i for i in obj]
+
 # https://github.com/python/cpython/blob/main/Objects/dictobject.c
 class dict:
     def __init__(self):

+ 1 - 1
src/error.h

@@ -62,7 +62,7 @@ public:
     }
 
     const char* what() const noexcept override {
-        return _what;
+        return _what.c_str();
     }
 };
 

+ 21 - 12
src/iter.h

@@ -2,25 +2,16 @@
 
 #include "obj.h"
 
-typedef std::function<PyVar (_Int)> _PyIntFn;
-
 class RangeIterator : public _Iterator {
 private:
     _Int current;
     _Range r;
-    _PyIntFn fn;
 public:
-    RangeIterator(PyVar _ref, _PyIntFn fn) : _Iterator(_ref), fn(fn) {
+    RangeIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
         this->r = std::get<_Range>(_ref->_native);
         this->current = r.start;
     }
 
-    PyVar next() override {
-        PyVar val = fn(current);
-        current += r.step;
-        return val;
-    }
-
     bool hasNext() override {
         if(r.step > 0){
             return current < r.stop;
@@ -28,6 +19,8 @@ public:
             return current > r.stop;
         }
     }
+
+    PyVar next();
 };
 
 class VectorIterator : public _Iterator {
@@ -35,7 +28,7 @@ private:
     size_t index = 0;
     const PyVarList* vec;
 public:
-    VectorIterator(PyVar _ref) : _Iterator(_ref) {
+    VectorIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
         vec = &std::get<PyVarList>(_ref->_native);
     }
 
@@ -46,4 +39,20 @@ public:
     PyVar next(){
         return vec->operator[](index++);
     }
-};
+};
+
+class StringIterator : public _Iterator {
+private:
+    size_t index = 0;
+    const _Str* str;
+public:
+    StringIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
+        str = &std::get<_Str>(_ref->_native);
+    }
+
+    bool hasNext(){
+        return index < str->u8_length();
+    }
+
+    PyVar next();
+};

+ 8 - 4
src/obj.h

@@ -13,6 +13,11 @@
 typedef int64_t _Int;
 typedef double _Float;
 
+#define _Int_MAX_POS 9223372036854775807
+#define _Int_MAX_NEG -9223372036854775808
+#define _FLOAT_INF_POS 1.0/0.0
+#define _FLOAT_INF_NEG -1.0/0.0
+
 class PyObject;
 class CodeObject;
 class BasePointer;
@@ -90,15 +95,14 @@ struct _Slice {
 };
 
 class _Iterator {
-private:
+protected:
     PyVar _ref;     // keep a reference to the object so it will not be deleted while iterating
+    VM* vm;
 public:
     virtual PyVar next() = 0;
     virtual bool hasNext() = 0;
-
     _Pointer var;
-
-    _Iterator(PyVar _ref) : _ref(_ref) {}
+    _Iterator(VM* vm, PyVar _ref) : vm(vm), _ref(_ref) {}
 };
 
 typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,BoundedMethod,_Range,_Slice,_Pointer> _Value;

+ 60 - 6
src/pocketpy.h

@@ -42,7 +42,10 @@ void __initializeBuiltinFunctions(VM* _vm) {
 #undef BIND_NUM_LOGICAL_OPT
 
     _vm->bindBuiltinFunc("print", [](VM* vm, PyVarList args) {
-        for (auto& arg : args) vm->_stdout(vm->PyStr_AS_C(vm->asStr(arg)) + " ");
+        for (auto& arg : args){
+            _Str s = vm->PyStr_AS_C(vm->asStr(arg)) + " ";
+            vm->_stdout(s.c_str());
+        }
         vm->_stdout("\n");
         return vm->None;
     });
@@ -50,7 +53,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
     _vm->bindBuiltinFunc("eval", [](VM* vm, PyVarList args) {
         vm->__checkArgSize(args, 1);
         const _Str& expr = vm->PyStr_AS_C(args[0]);
-        _Code code = compile(vm, expr, "<eval>", EVAL_MODE);
+        _Code code = compile(vm, expr.c_str(), "<eval>", EVAL_MODE);
         if(code == nullptr) return vm->None;
         return vm->_exec(code);      // not working in function
     });
@@ -115,7 +118,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
 
     _vm->bindMethod("range", "__iter__", [](VM* vm, PyVarList args) {
         vm->__checkType(args[0], vm->_tp_range);
-        auto iter = std::make_shared<RangeIterator>(args[0], [=](_Int val){return vm->PyInt(val);});
+        auto iter = std::make_shared<RangeIterator>(vm, args[0]);
         return vm->PyIter(iter);
     });
 
@@ -142,6 +145,25 @@ void __initializeBuiltinFunctions(VM* _vm) {
     });
 
     /************ PyInt ************/
+    _vm->bindMethod("int", "__new__", [](VM* vm, PyVarList args) {
+        if(args.size() == 0) return vm->PyInt(0);
+        vm->__checkArgSize(args, 1);
+        if (args[0]->isType(vm->_tp_int)) return args[0];
+        if (args[0]->isType(vm->_tp_float)) return vm->PyInt((_Int)vm->PyFloat_AS_C(args[0]));
+        if (args[0]->isType(vm->_tp_bool)) return vm->PyInt(vm->PyBool_AS_C(args[0]) ? 1 : 0);
+        if (args[0]->isType(vm->_tp_str)) {
+            const _Str& s = vm->PyStr_AS_C(args[0]);
+            try{
+                _Int val = std::stoll(s.str());
+                return vm->PyInt(val);
+            }catch(std::invalid_argument&){
+                vm->valueError("invalid literal for int(): '" + s + "'");
+            }
+        }
+        vm->typeError("int() argument must be a int, float, bool or str");
+        return vm->None;
+    });
+
     _vm->bindMethod("int", "__floordiv__", [](VM* vm, PyVarList args) {
         if(!args[0]->isType(vm->_tp_int) || !args[1]->isType(vm->_tp_int))
             vm->typeError("unsupported operand type(s) for " "//" );
@@ -167,6 +189,27 @@ void __initializeBuiltinFunctions(VM* _vm) {
     });
 
     /************ PyFloat ************/
+    _vm->bindMethod("float", "__new__", [](VM* vm, PyVarList args) {
+        if(args.size() == 0) return vm->PyFloat(0.0);
+        vm->__checkArgSize(args, 1);
+        if (args[0]->isType(vm->_tp_int)) return vm->PyFloat((_Float)vm->PyInt_AS_C(args[0]));
+        if (args[0]->isType(vm->_tp_float)) return args[0];
+        if (args[0]->isType(vm->_tp_bool)) return vm->PyFloat(vm->PyBool_AS_C(args[0]) ? 1.0 : 0.0);
+        if (args[0]->isType(vm->_tp_str)) {
+            const _Str& s = vm->PyStr_AS_C(args[0]);
+            if(s == "inf") return vm->PyFloat(_FLOAT_INF_POS);
+            if(s == "-inf") return vm->PyFloat(_FLOAT_INF_NEG);
+            try{
+                _Float val = std::stod(s.str());
+                return vm->PyFloat(val);
+            }catch(std::invalid_argument&){
+                vm->valueError("invalid literal for float(): '" + s + "'");
+            }
+        }
+        vm->typeError("float() argument must be a int, float, bool or str");
+        return vm->None;
+    });
+
     _vm->bindMethod("float", "__neg__", [](VM* vm, PyVarList args) {
         return vm->PyFloat(-1.0 * vm->PyFloat_AS_C(args[0]));
     });
@@ -177,7 +220,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
         _StrStream ss;
         ss << std::setprecision(std::numeric_limits<_Float>::max_digits10-1) << val;
         std::string s = ss.str();
-        if(std::all_of(s.begin(), s.end(), isdigit)) s += ".0";
+        if(std::all_of(s.begin()+1, s.end(), isdigit)) s += ".0";
         return vm->PyStr(s);
     });
 
@@ -210,6 +253,11 @@ void __initializeBuiltinFunctions(VM* _vm) {
         return args[0]; // str is immutable
     });
 
+    _vm->bindMethod("str", "__iter__", [](VM* vm, PyVarList args) {
+        auto it = std::make_shared<StringIterator>(vm, args[0]);
+        return vm->PyIter(it);
+    });
+
     _vm->bindMethod("str", "__repr__", [](VM* vm, PyVarList args) {
         const _Str& _self = vm->PyStr_AS_C(args[0]);
         // we just do a simple repr here, no escaping
@@ -308,7 +356,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
     /************ PyList ************/
     _vm->bindMethod("list", "__iter__", [](VM* vm, PyVarList args) {
         vm->__checkType(args[0], vm->_tp_list);
-        auto iter = std::make_shared<VectorIterator>(args[0]);
+        auto iter = std::make_shared<VectorIterator>(vm, args[0]);
         return vm->PyIter(iter);
     });
 
@@ -395,9 +443,15 @@ void __initializeBuiltinFunctions(VM* _vm) {
     });
 
     /************ PyTuple ************/
+    _vm->bindMethod("tuple", "__new__", [](VM* vm, PyVarList args) {
+        vm->__checkArgSize(args, 1);
+        PyVarList _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args));
+        return vm->PyTuple(_list);
+    });
+
     _vm->bindMethod("tuple", "__iter__", [](VM* vm, PyVarList args) {
         vm->__checkType(args[0], vm->_tp_tuple);
-        auto iter = std::make_shared<VectorIterator>(args[0]);
+        auto iter = std::make_shared<VectorIterator>(vm, args[0]);
         return vm->PyIter(iter);
     });
 

+ 11 - 3
src/str.h

@@ -75,6 +75,14 @@ public:
         return _s != other._s;
     }
 
+    bool operator==(const char* other) const {
+        return _s == other;
+    }
+
+    bool operator!=(const char* other) const {
+        return _s != other;
+    }
+
     bool operator<(const _Str& other) const {
         return _s < other._s;
     }
@@ -116,12 +124,12 @@ public:
         return _s;
     }
 
-    static const std::size_t npos = std::string::npos;
-
-    operator const char*() const {
+    const char* c_str() const {
         return _s.c_str();
     }
 
+    static const std::size_t npos = std::string::npos;
+
     _Str __lstrip() const {
         std::string copy(_s);
         copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) {

+ 13 - 2
src/vm.h

@@ -132,7 +132,7 @@ private:
                 {
                     const PyVar& expr = frame->topValue(this);
                     if(expr == None) break;
-                    _stdout(PyStr_AS_C(asRepr(expr)));
+                    _stdout(PyStr_AS_C(asRepr(expr)).c_str());
                     _stdout("\n");
                 } break;
             case OP_POP_TOP: frame->popValue(this); break;
@@ -799,8 +799,19 @@ void CompoundPointer::del(VM* vm, Frame* frame) const{
     for (auto& ptr : pointers) ptr->del(vm, frame);
 }
 
-/**************** Frame ****************/
+/***** Frame's Impl *****/
 inline PyVar Frame::__deref_pointer(VM* vm, PyVar v){
     if(v->isType(vm->_tp_pointer)) v = vm->PyPointer_AS_C(v)->get(vm, this);
     return v;
+}
+
+/***** Iterators' Impl *****/
+PyVar RangeIterator::next(){
+    PyVar val = vm->PyInt(current);
+    current += r.step;
+    return val;
+}
+
+PyVar StringIterator::next(){
+    return vm->PyStr(str->u8_getitem(index++));
 }