Преглед изворни кода

make system safe

remove **kwargs

Update obj.h
blueloveTH пре 3 година
родитељ
комит
47c6639627
5 измењених фајлова са 41 додато и 21 уклоњено
  1. 1 1
      src/compiler.h
  2. 1 1
      src/iter.h
  3. 28 6
      src/obj.h
  4. 11 11
      src/pocketpy.h
  5. 0 2
      src/vm.h

+ 1 - 1
src/compiler.h

@@ -795,7 +795,7 @@ __LISTCOMP:
                 case 0: func.args.push_back(name); break;
                 case 1: func.starredArg = name; state+=1; break;
                 case 2: consume(TK("=")); func.kwArgs[name] = consumeLiteral(); break;
-                case 3: func.doubleStarredArg = name; break;
+                case 3: syntaxError("**kwargs is not supported yet"); break;
             }
         } while (match(TK(",")));
     }

+ 1 - 1
src/iter.h

@@ -44,6 +44,6 @@ public:
     }
 
     PyVar next(){
-        return vec->at(index++);
+        return vec->operator[](index++);
     }
 };

+ 28 - 6
src/obj.h

@@ -20,7 +20,31 @@ class VM;
 
 typedef std::shared_ptr<PyObject> PyVar;
 typedef PyVar PyVarOrNull;
-typedef std::vector<PyVar> PyVarList;
+
+class PyVarList: public std::vector<PyVar> {
+    PyVar& at(size_t) = delete;
+
+    inline void __checkIndex(size_t i) const {
+        if (i >= size()){
+            auto msg = "std::vector index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
+            throw std::out_of_range(msg);
+        }
+    }
+public:
+    PyVar& operator[](size_t i) {
+        __checkIndex(i);
+        return std::vector<PyVar>::operator[](i);
+    }
+
+    const PyVar& operator[](size_t i) const {
+        __checkIndex(i);
+        return std::vector<PyVar>::operator[](i);
+    }
+
+    // define constructors the same as std::vector
+    using std::vector<PyVar>::vector;
+};
+
 typedef std::unordered_map<_Str, PyVar> PyVarDict;
 typedef std::shared_ptr<const BasePointer> _Pointer;
 
@@ -32,15 +56,13 @@ struct _Func {
     _Code code;
     std::vector<_Str> args;
     _Str starredArg;        // empty if no *arg
-    PyVarDict kwArgs;         // empty if no k=v
-    _Str doubleStarredArg;  // empty if no **kwargs
+    PyVarDict kwArgs;       // empty if no k=v
 
     bool hasName(const _Str& val) const {
         bool _0 = std::find(args.begin(), args.end(), val) != args.end();
         bool _1 = starredArg == val;
         bool _2 = kwArgs.find(val) != kwArgs.end();
-        bool _3 = doubleStarredArg == val;
-        return _0 || _1 || _2 || _3;
+        return _0 || _1 || _2;
     }
 };
 
@@ -81,7 +103,7 @@ public:
 
 typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,BoundedMethod,_Range,_Slice,_Pointer> _Value;
 
-#define UNREACHABLE() throw std::runtime_error("Unreachable code")
+#define UNREACHABLE() throw std::runtime_error("unreachable code! (this should be a bug, please report it)");
 
 struct PyObject {
     PyVarDict attribs;

+ 11 - 11
src/pocketpy.h

@@ -60,32 +60,32 @@ void __initializeBuiltinFunctions(VM* _vm) {
     });
 
     _vm->bindBuiltinFunc("repr", [](VM* vm, PyVarList args) {
-        return vm->asRepr(args.at(0));
+        return vm->asRepr(args[0]);
     });
 
     _vm->bindBuiltinFunc("hash", [](VM* vm, PyVarList args) {
-        return vm->PyInt(vm->hash(args.at(0)));
+        return vm->PyInt(vm->hash(args[0]));
     });
 
     _vm->bindBuiltinFunc("chr", [](VM* vm, PyVarList args) {
-        _Int i = vm->PyInt_AS_C(args.at(0));
+        _Int i = vm->PyInt_AS_C(args[0]);
         if (i < 0 || i > 128) vm->valueError("chr() arg not in range(128)");
         return vm->PyStr(_Str(1, (char)i));
     });
 
     _vm->bindBuiltinFunc("round", [](VM* vm, PyVarList args) {
-        return vm->PyInt(_round(vm->numToFloat(args.at(0))));
+        return vm->PyInt(_round(vm->numToFloat(args[0])));
     });
 
     _vm->bindBuiltinFunc("ord", [](VM* vm, PyVarList args) {
-        _Str s = vm->PyStr_AS_C(args.at(0));
+        _Str s = vm->PyStr_AS_C(args[0]);
         if (s.size() != 1) vm->typeError("ord() expected an ASCII character");
         return vm->PyInt((_Int)s[0]);
     });
 
     _vm->bindBuiltinFunc("dir", [](VM* vm, PyVarList args) {
         PyVarList ret;
-        for (auto& [k, _] : args.at(0)->attribs) ret.push_back(vm->PyStr(k));
+        for (auto& [k, _] : args[0]->attribs) ret.push_back(vm->PyStr(k));
         return vm->PyList(ret);
     });
 
@@ -97,7 +97,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
 
     _vm->bindMethod("type", "__new__", [](VM* vm, PyVarList args) {
         vm->_assert(args.size() == 1, "expected 1 argument");
-        return args.at(0)->attribs[__class__];
+        return args[0]->attribs[__class__];
     });
 
     _vm->bindMethod("range", "__new__", [](VM* vm, PyVarList args) {
@@ -112,7 +112,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
     });
 
     _vm->bindMethod("range", "__iter__", [](VM* vm, PyVarList args) {
-        vm->__checkType(args.at(0), vm->_tp_range);
+        vm->__checkType(args[0], vm->_tp_range);
         auto iter = std::make_shared<RangeIterator>(args[0], [=](_Int val){return vm->PyInt(val);});
         return vm->PyIter(iter);
     });
@@ -215,7 +215,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
     });
 
     _vm->bindMethod("str", "__eq__", [](VM* vm, PyVarList args) {
-        if(args.at(0)->isType(vm->_tp_str) && args.at(1)->isType(vm->_tp_str))
+        if(args[0]->isType(vm->_tp_str) && args[1]->isType(vm->_tp_str))
             return vm->PyBool(vm->PyStr_AS_C(args[0]) == vm->PyStr_AS_C(args[1]));
         return vm->PyBool(args[0] == args[1]);      // fallback
     });
@@ -299,7 +299,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
 
     /************ PyList ************/
     _vm->bindMethod("list", "__iter__", [](VM* vm, PyVarList args) {
-        vm->__checkType(args.at(0), vm->_tp_list);
+        vm->__checkType(args[0], vm->_tp_list);
         auto iter = std::make_shared<VectorIterator>(args[0]);
         return vm->PyIter(iter);
     });
@@ -383,7 +383,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
 
     /************ PyTuple ************/
     _vm->bindMethod("tuple", "__iter__", [](VM* vm, PyVarList args) {
-        vm->__checkType(args.at(0), vm->_tp_tuple);
+        vm->__checkType(args[0], vm->_tp_tuple);
         auto iter = std::make_shared<VectorIterator>(args[0]);
         return vm->PyIter(iter);
     });

+ 0 - 2
src/vm.h

@@ -390,8 +390,6 @@ public:
             }
 
             if(i < args.size()) typeError("too many arguments");
-
-            // TODO: handle **kwargs
             return exec(fn.code, locals);
         }
         typeError("'" + callable->getTypeName() + "' object is not callable");