diff --git a/src/compiler.h b/src/compiler.h index 37e61559..893bda60 100644 --- a/src/compiler.h +++ b/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(","))); } diff --git a/src/iter.h b/src/iter.h index bc259901..7818119f 100644 --- a/src/iter.h +++ b/src/iter.h @@ -44,6 +44,6 @@ public: } PyVar next(){ - return vec->at(index++); + return vec->operator[](index++); } }; \ No newline at end of file diff --git a/src/obj.h b/src/obj.h index 3603413c..591cd8bf 100644 --- a/src/obj.h +++ b/src/obj.h @@ -20,7 +20,31 @@ class VM; typedef std::shared_ptr PyVar; typedef PyVar PyVarOrNull; -typedef std::vector PyVarList; + +class PyVarList: public std::vector { + 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::operator[](i); + } + + const PyVar& operator[](size_t i) const { + __checkIndex(i); + return std::vector::operator[](i); + } + + // define constructors the same as std::vector + using std::vector::vector; +}; + typedef std::unordered_map<_Str, PyVar> PyVarDict; typedef std::shared_ptr _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; diff --git a/src/pocketpy.h b/src/pocketpy.h index 7cca31c6..6777d844 100644 --- a/src/pocketpy.h +++ b/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(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(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(args[0]); return vm->PyIter(iter); }); diff --git a/src/vm.h b/src/vm.h index a30da508..539a0afb 100644 --- a/src/vm.h +++ b/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");