make system safe

remove **kwargs

Update obj.h
This commit is contained in:
blueloveTH 2022-11-10 14:59:29 +08:00
parent 5765c731a5
commit 47c6639627
5 changed files with 41 additions and 21 deletions

View File

@ -795,7 +795,7 @@ __LISTCOMP:
case 0: func.args.push_back(name); break; case 0: func.args.push_back(name); break;
case 1: func.starredArg = name; state+=1; break; case 1: func.starredArg = name; state+=1; break;
case 2: consume(TK("=")); func.kwArgs[name] = consumeLiteral(); 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(","))); } while (match(TK(",")));
} }

View File

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

View File

@ -20,7 +20,31 @@ class VM;
typedef std::shared_ptr<PyObject> PyVar; typedef std::shared_ptr<PyObject> PyVar;
typedef PyVar PyVarOrNull; 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::unordered_map<_Str, PyVar> PyVarDict;
typedef std::shared_ptr<const BasePointer> _Pointer; typedef std::shared_ptr<const BasePointer> _Pointer;
@ -32,15 +56,13 @@ struct _Func {
_Code code; _Code code;
std::vector<_Str> args; std::vector<_Str> args;
_Str starredArg; // empty if no *arg _Str starredArg; // empty if no *arg
PyVarDict kwArgs; // empty if no k=v PyVarDict kwArgs; // empty if no k=v
_Str doubleStarredArg; // empty if no **kwargs
bool hasName(const _Str& val) const { bool hasName(const _Str& val) const {
bool _0 = std::find(args.begin(), args.end(), val) != args.end(); bool _0 = std::find(args.begin(), args.end(), val) != args.end();
bool _1 = starredArg == val; bool _1 = starredArg == val;
bool _2 = kwArgs.find(val) != kwArgs.end(); bool _2 = kwArgs.find(val) != kwArgs.end();
bool _3 = doubleStarredArg == val; return _0 || _1 || _2;
return _0 || _1 || _2 || _3;
} }
}; };
@ -81,7 +103,7 @@ public:
typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,BoundedMethod,_Range,_Slice,_Pointer> _Value; 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 { struct PyObject {
PyVarDict attribs; PyVarDict attribs;

View File

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

View File

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