mirror of
https://github.com/pocketpy/pocketpy
synced 2025-12-07 10:40:16 +00:00
add arg size check
This commit is contained in:
parent
c9b58e2270
commit
a61315d1f7
@ -118,6 +118,13 @@ class dict:
|
|||||||
def items(self):
|
def items(self):
|
||||||
return [kv for kv in self._a if kv is not None]
|
return [kv for kv in self._a if kv is not None]
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
d = dict()
|
||||||
|
for kv in self._a:
|
||||||
|
if kv is not None:
|
||||||
|
d[kv[0]] = kv[1]
|
||||||
|
return d
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
a = [repr(k)+': '+repr(v) for k,v in self.items()]
|
a = [repr(k)+': '+repr(v) for k,v in self.items()]
|
||||||
return '{'+ ', '.join(a) + '}'
|
return '{'+ ', '.join(a) + '}'
|
||||||
|
|||||||
@ -4,11 +4,7 @@
|
|||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
inline _Int _round(_Float f){
|
|
||||||
if(f > 0) return (_Int)(f + 0.5);
|
|
||||||
return (_Int)(f - 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BIND_NUM_ARITH_OPT(name, op) \
|
#define BIND_NUM_ARITH_OPT(name, op) \
|
||||||
_vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, PyVarList args){ \
|
_vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, PyVarList args){ \
|
||||||
@ -52,39 +48,44 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindBuiltinFunc("eval", [](VM* vm, PyVarList args) {
|
_vm->bindBuiltinFunc("eval", [](VM* vm, PyVarList args) {
|
||||||
if (args.size() != 1) vm->typeError("eval() takes exactly one argument");
|
vm->__checkArgSize(args, 1);
|
||||||
if (!args[0]->isType(vm->_tp_str)) vm->typeError("eval() argument must be a string");
|
|
||||||
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
||||||
_Code code = compile(vm, expr, "<eval>", EVAL_MODE);
|
_Code code = compile(vm, expr, "<eval>", EVAL_MODE);
|
||||||
if(code == nullptr) return vm->None;
|
if(code == nullptr) return vm->None;
|
||||||
return vm->_exec(code); // not working in function
|
return vm->_exec(code); // not working in function
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_vm->bindBuiltinFunc("isinstance", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 2);
|
||||||
|
return vm->PyBool(vm->isInstance(args[0], args[1]));
|
||||||
|
});
|
||||||
|
|
||||||
_vm->bindBuiltinFunc("repr", [](VM* vm, PyVarList args) {
|
_vm->bindBuiltinFunc("repr", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 1);
|
||||||
return vm->asRepr(args[0]);
|
return vm->asRepr(args[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindBuiltinFunc("hash", [](VM* vm, PyVarList args) {
|
_vm->bindBuiltinFunc("hash", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 1);
|
||||||
return vm->PyInt(vm->hash(args[0]));
|
return vm->PyInt(vm->hash(args[0]));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindBuiltinFunc("chr", [](VM* vm, PyVarList args) {
|
_vm->bindBuiltinFunc("chr", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 1);
|
||||||
_Int i = vm->PyInt_AS_C(args[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) {
|
|
||||||
return vm->PyInt(_round(vm->numToFloat(args[0])));
|
|
||||||
});
|
|
||||||
|
|
||||||
_vm->bindBuiltinFunc("ord", [](VM* vm, PyVarList args) {
|
_vm->bindBuiltinFunc("ord", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 1);
|
||||||
_Str s = vm->PyStr_AS_C(args[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) {
|
||||||
|
vm->__checkArgSize(args, 1);
|
||||||
PyVarList ret;
|
PyVarList ret;
|
||||||
for (auto& [k, _] : args[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 +98,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->__checkArgSize(args, 1);
|
||||||
return args[0]->attribs[__class__];
|
return args[0]->attribs[__class__];
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -107,7 +108,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
case 1: r.stop = vm->PyInt_AS_C(args[0]); break;
|
case 1: r.stop = vm->PyInt_AS_C(args[0]); break;
|
||||||
case 2: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); break;
|
case 2: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); break;
|
||||||
case 3: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); r.step = vm->PyInt_AS_C(args[2]); break;
|
case 3: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); r.step = vm->PyInt_AS_C(args[2]); break;
|
||||||
default: vm->typeError("range expected 1-3 arguments, got " + std::to_string(args.size()));
|
default: vm->typeError("expected 1-3 arguments, but got " + std::to_string(args.size()));
|
||||||
}
|
}
|
||||||
return vm->PyRange(r);
|
return vm->PyRange(r);
|
||||||
});
|
});
|
||||||
@ -134,7 +135,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
if(!vm->isIntOrFloat(args[0], args[1]))
|
if(!vm->isIntOrFloat(args[0], args[1]))
|
||||||
vm->typeError("unsupported operand type(s) for " "**" );
|
vm->typeError("unsupported operand type(s) for " "**" );
|
||||||
if(args[0]->isType(vm->_tp_int) && args[1]->isType(vm->_tp_int)){
|
if(args[0]->isType(vm->_tp_int) && args[1]->isType(vm->_tp_int)){
|
||||||
return vm->PyInt(_round(pow(vm->PyInt_AS_C(args[0]), vm->PyInt_AS_C(args[1]))));
|
return vm->PyInt((_Int)round(pow(vm->PyInt_AS_C(args[0]), vm->PyInt_AS_C(args[1]))));
|
||||||
}else{
|
}else{
|
||||||
return vm->PyFloat((_Float)pow(vm->numToFloat(args[0]), vm->numToFloat(args[1])));
|
return vm->PyFloat((_Float)pow(vm->numToFloat(args[0]), vm->numToFloat(args[1])));
|
||||||
}
|
}
|
||||||
@ -182,7 +183,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
|
|
||||||
/************ PyString ************/
|
/************ PyString ************/
|
||||||
_vm->bindMethod("str", "__new__", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("str", "__new__", [](VM* vm, PyVarList args) {
|
||||||
vm->_assert(args.size() == 1, "expected 1 argument");
|
vm->__checkArgSize(args, 1);
|
||||||
return vm->asStr(args[0]);
|
return vm->asStr(args[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -248,6 +249,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("str", "upper", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("str", "upper", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 1, true);
|
||||||
const _Str& _self (vm->PyStr_AS_C(args[0]));
|
const _Str& _self (vm->PyStr_AS_C(args[0]));
|
||||||
_StrStream ss;
|
_StrStream ss;
|
||||||
for(auto c : _self.str()) ss << (char)toupper(c);
|
for(auto c : _self.str()) ss << (char)toupper(c);
|
||||||
@ -255,6 +257,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("str", "lower", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("str", "lower", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 1, true);
|
||||||
const _Str& _self (vm->PyStr_AS_C(args[0]));
|
const _Str& _self (vm->PyStr_AS_C(args[0]));
|
||||||
_StrStream ss;
|
_StrStream ss;
|
||||||
for(auto c : _self.str()) ss << (char)tolower(c);
|
for(auto c : _self.str()) ss << (char)tolower(c);
|
||||||
@ -262,6 +265,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("str", "replace", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("str", "replace", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 3, true);
|
||||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||||
const _Str& _old = vm->PyStr_AS_C(args[1]);
|
const _Str& _old = vm->PyStr_AS_C(args[1]);
|
||||||
const _Str& _new = vm->PyStr_AS_C(args[2]);
|
const _Str& _new = vm->PyStr_AS_C(args[2]);
|
||||||
@ -276,18 +280,21 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("str", "startswith", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("str", "startswith", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 2, true);
|
||||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||||
const _Str& _prefix = vm->PyStr_AS_C(args[1]);
|
const _Str& _prefix = vm->PyStr_AS_C(args[1]);
|
||||||
return vm->PyBool(_self.str().find(_prefix.str()) == 0);
|
return vm->PyBool(_self.str().find(_prefix.str()) == 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("str", "endswith", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("str", "endswith", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 2, true);
|
||||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||||
const _Str& _suffix = vm->PyStr_AS_C(args[1]);
|
const _Str& _suffix = vm->PyStr_AS_C(args[1]);
|
||||||
return vm->PyBool(_self.str().rfind(_suffix.str()) == _self.str().length() - _suffix.str().length());
|
return vm->PyBool(_self.str().rfind(_suffix.str()) == _self.str().length() - _suffix.str().length());
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("str", "join", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("str", "join", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 2, true);
|
||||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||||
const PyVarList& _list = vm->PyList_AS_C(args[1]);
|
const PyVarList& _list = vm->PyList_AS_C(args[1]);
|
||||||
_StrStream ss;
|
_StrStream ss;
|
||||||
@ -306,12 +313,14 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("list", "append", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("list", "append", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 2, true);
|
||||||
PyVarList& _self = vm->PyList_AS_C(args[0]);
|
PyVarList& _self = vm->PyList_AS_C(args[0]);
|
||||||
_self.push_back(args[1]);
|
_self.push_back(args[1]);
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("list", "insert", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("list", "insert", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 3, true);
|
||||||
PyVarList& _self = vm->PyList_AS_C(args[0]);
|
PyVarList& _self = vm->PyList_AS_C(args[0]);
|
||||||
int _index = vm->PyInt_AS_C(args[1]);
|
int _index = vm->PyInt_AS_C(args[1]);
|
||||||
_index = vm->normalizedIndex(_index, _self.size());
|
_index = vm->normalizedIndex(_index, _self.size());
|
||||||
@ -320,15 +329,18 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("list", "clear", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("list", "clear", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 1, true);
|
||||||
vm->PyList_AS_C(args[0]).clear();
|
vm->PyList_AS_C(args[0]).clear();
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("list", "copy", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("list", "copy", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 1, true);
|
||||||
return vm->PyList(vm->PyList_AS_C(args[0]));
|
return vm->PyList(vm->PyList_AS_C(args[0]));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bindMethod("list", "pop", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("list", "pop", [](VM* vm, PyVarList args) {
|
||||||
|
vm->__checkArgSize(args, 1, true);
|
||||||
PyVarList& _self = vm->PyList_AS_C(args[0]);
|
PyVarList& _self = vm->PyList_AS_C(args[0]);
|
||||||
if(_self.empty()) vm->indexError("pop from empty list");
|
if(_self.empty()) vm->indexError("pop from empty list");
|
||||||
PyVar ret = _self.back();
|
PyVar ret = _self.back();
|
||||||
|
|||||||
10
src/vm.h
10
src/vm.h
@ -450,8 +450,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar newNumber(PyVar type, _Value _native) {
|
PyVar newNumber(PyVar type, _Value _native) {
|
||||||
if(type != _tp_int && type != _tp_float)
|
if(type != _tp_int && type != _tp_float) UNREACHABLE();
|
||||||
systemError("type is not a number type");
|
|
||||||
PyObject* _raw = nullptr;
|
PyObject* _raw = nullptr;
|
||||||
if(numPool.size() > 0) {
|
if(numPool.size() > 0) {
|
||||||
_raw = numPool.back();
|
_raw = numPool.back();
|
||||||
@ -522,6 +521,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isInstance(PyVar obj, PyVar type){
|
bool isInstance(PyVar obj, PyVar type){
|
||||||
|
__checkType(type, _tp_type);
|
||||||
PyVar t = obj->attribs[__class__];
|
PyVar t = obj->attribs[__class__];
|
||||||
while (t != None){
|
while (t != None){
|
||||||
if (t == type) return true;
|
if (t == type) return true;
|
||||||
@ -687,6 +687,12 @@ public:
|
|||||||
if(!obj->isType(type)) typeError("expected '" + type->getName() + "', but got '" + obj->getTypeName() + "'");
|
if(!obj->isType(type)) typeError("expected '" + type->getName() + "', but got '" + obj->getTypeName() + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void __checkArgSize(const PyVarList& args, int size, bool method=false){
|
||||||
|
if(args.size() == size) return;
|
||||||
|
if(method) typeError(args.size()>size ? "too many arguments" : "too few arguments");
|
||||||
|
else typeError("expected " + std::to_string(size) + " arguments, but got " + std::to_string(args.size()));
|
||||||
|
}
|
||||||
|
|
||||||
void _assert(bool val, const _Str& msg){
|
void _assert(bool val, const _Str& msg){
|
||||||
if (!val) _error("AssertionError", msg);
|
if (!val) _error("AssertionError", msg);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user