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 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(",")));
}

View File

@ -44,6 +44,6 @@ public:
}
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 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;

View File

@ -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);
});

View File

@ -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");