mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 20:10:17 +00:00
add __iter__ and __new__ for some types
This commit is contained in:
parent
b52aa85f13
commit
aa0c415f1d
@ -60,6 +60,8 @@ list.__contains__ = __iterable4__contains__
|
||||
tuple.__contains__ = __iterable4__contains__
|
||||
del __iterable4__contains__
|
||||
|
||||
list.__new__ = lambda obj: [i for i in obj]
|
||||
|
||||
# https://github.com/python/cpython/blob/main/Objects/dictobject.c
|
||||
class dict:
|
||||
def __init__(self):
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
}
|
||||
|
||||
const char* what() const noexcept override {
|
||||
return _what;
|
||||
return _what.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
|
31
src/iter.h
31
src/iter.h
@ -2,25 +2,16 @@
|
||||
|
||||
#include "obj.h"
|
||||
|
||||
typedef std::function<PyVar (_Int)> _PyIntFn;
|
||||
|
||||
class RangeIterator : public _Iterator {
|
||||
private:
|
||||
_Int current;
|
||||
_Range r;
|
||||
_PyIntFn fn;
|
||||
public:
|
||||
RangeIterator(PyVar _ref, _PyIntFn fn) : _Iterator(_ref), fn(fn) {
|
||||
RangeIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
|
||||
this->r = std::get<_Range>(_ref->_native);
|
||||
this->current = r.start;
|
||||
}
|
||||
|
||||
PyVar next() override {
|
||||
PyVar val = fn(current);
|
||||
current += r.step;
|
||||
return val;
|
||||
}
|
||||
|
||||
bool hasNext() override {
|
||||
if(r.step > 0){
|
||||
return current < r.stop;
|
||||
@ -28,6 +19,8 @@ public:
|
||||
return current > r.stop;
|
||||
}
|
||||
}
|
||||
|
||||
PyVar next();
|
||||
};
|
||||
|
||||
class VectorIterator : public _Iterator {
|
||||
@ -35,7 +28,7 @@ private:
|
||||
size_t index = 0;
|
||||
const PyVarList* vec;
|
||||
public:
|
||||
VectorIterator(PyVar _ref) : _Iterator(_ref) {
|
||||
VectorIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
|
||||
vec = &std::get<PyVarList>(_ref->_native);
|
||||
}
|
||||
|
||||
@ -47,3 +40,19 @@ public:
|
||||
return vec->operator[](index++);
|
||||
}
|
||||
};
|
||||
|
||||
class StringIterator : public _Iterator {
|
||||
private:
|
||||
size_t index = 0;
|
||||
const _Str* str;
|
||||
public:
|
||||
StringIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
|
||||
str = &std::get<_Str>(_ref->_native);
|
||||
}
|
||||
|
||||
bool hasNext(){
|
||||
return index < str->u8_length();
|
||||
}
|
||||
|
||||
PyVar next();
|
||||
};
|
||||
|
12
src/obj.h
12
src/obj.h
@ -13,6 +13,11 @@
|
||||
typedef int64_t _Int;
|
||||
typedef double _Float;
|
||||
|
||||
#define _Int_MAX_POS 9223372036854775807
|
||||
#define _Int_MAX_NEG -9223372036854775808
|
||||
#define _FLOAT_INF_POS 1.0/0.0
|
||||
#define _FLOAT_INF_NEG -1.0/0.0
|
||||
|
||||
class PyObject;
|
||||
class CodeObject;
|
||||
class BasePointer;
|
||||
@ -90,15 +95,14 @@ struct _Slice {
|
||||
};
|
||||
|
||||
class _Iterator {
|
||||
private:
|
||||
protected:
|
||||
PyVar _ref; // keep a reference to the object so it will not be deleted while iterating
|
||||
VM* vm;
|
||||
public:
|
||||
virtual PyVar next() = 0;
|
||||
virtual bool hasNext() = 0;
|
||||
|
||||
_Pointer var;
|
||||
|
||||
_Iterator(PyVar _ref) : _ref(_ref) {}
|
||||
_Iterator(VM* vm, PyVar _ref) : vm(vm), _ref(_ref) {}
|
||||
};
|
||||
|
||||
typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,BoundedMethod,_Range,_Slice,_Pointer> _Value;
|
||||
|
@ -42,7 +42,10 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
#undef BIND_NUM_LOGICAL_OPT
|
||||
|
||||
_vm->bindBuiltinFunc("print", [](VM* vm, PyVarList args) {
|
||||
for (auto& arg : args) vm->_stdout(vm->PyStr_AS_C(vm->asStr(arg)) + " ");
|
||||
for (auto& arg : args){
|
||||
_Str s = vm->PyStr_AS_C(vm->asStr(arg)) + " ";
|
||||
vm->_stdout(s.c_str());
|
||||
}
|
||||
vm->_stdout("\n");
|
||||
return vm->None;
|
||||
});
|
||||
@ -50,7 +53,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
_vm->bindBuiltinFunc("eval", [](VM* vm, PyVarList args) {
|
||||
vm->__checkArgSize(args, 1);
|
||||
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
||||
_Code code = compile(vm, expr, "<eval>", EVAL_MODE);
|
||||
_Code code = compile(vm, expr.c_str(), "<eval>", EVAL_MODE);
|
||||
if(code == nullptr) return vm->None;
|
||||
return vm->_exec(code); // not working in function
|
||||
});
|
||||
@ -115,7 +118,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
|
||||
_vm->bindMethod("range", "__iter__", [](VM* vm, PyVarList args) {
|
||||
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>(vm, args[0]);
|
||||
return vm->PyIter(iter);
|
||||
});
|
||||
|
||||
@ -142,6 +145,25 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
});
|
||||
|
||||
/************ PyInt ************/
|
||||
_vm->bindMethod("int", "__new__", [](VM* vm, PyVarList args) {
|
||||
if(args.size() == 0) return vm->PyInt(0);
|
||||
vm->__checkArgSize(args, 1);
|
||||
if (args[0]->isType(vm->_tp_int)) return args[0];
|
||||
if (args[0]->isType(vm->_tp_float)) return vm->PyInt((_Int)vm->PyFloat_AS_C(args[0]));
|
||||
if (args[0]->isType(vm->_tp_bool)) return vm->PyInt(vm->PyBool_AS_C(args[0]) ? 1 : 0);
|
||||
if (args[0]->isType(vm->_tp_str)) {
|
||||
const _Str& s = vm->PyStr_AS_C(args[0]);
|
||||
try{
|
||||
_Int val = std::stoll(s.str());
|
||||
return vm->PyInt(val);
|
||||
}catch(std::invalid_argument&){
|
||||
vm->valueError("invalid literal for int(): '" + s + "'");
|
||||
}
|
||||
}
|
||||
vm->typeError("int() argument must be a int, float, bool or str");
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bindMethod("int", "__floordiv__", [](VM* vm, PyVarList args) {
|
||||
if(!args[0]->isType(vm->_tp_int) || !args[1]->isType(vm->_tp_int))
|
||||
vm->typeError("unsupported operand type(s) for " "//" );
|
||||
@ -167,6 +189,27 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
});
|
||||
|
||||
/************ PyFloat ************/
|
||||
_vm->bindMethod("float", "__new__", [](VM* vm, PyVarList args) {
|
||||
if(args.size() == 0) return vm->PyFloat(0.0);
|
||||
vm->__checkArgSize(args, 1);
|
||||
if (args[0]->isType(vm->_tp_int)) return vm->PyFloat((_Float)vm->PyInt_AS_C(args[0]));
|
||||
if (args[0]->isType(vm->_tp_float)) return args[0];
|
||||
if (args[0]->isType(vm->_tp_bool)) return vm->PyFloat(vm->PyBool_AS_C(args[0]) ? 1.0 : 0.0);
|
||||
if (args[0]->isType(vm->_tp_str)) {
|
||||
const _Str& s = vm->PyStr_AS_C(args[0]);
|
||||
if(s == "inf") return vm->PyFloat(_FLOAT_INF_POS);
|
||||
if(s == "-inf") return vm->PyFloat(_FLOAT_INF_NEG);
|
||||
try{
|
||||
_Float val = std::stod(s.str());
|
||||
return vm->PyFloat(val);
|
||||
}catch(std::invalid_argument&){
|
||||
vm->valueError("invalid literal for float(): '" + s + "'");
|
||||
}
|
||||
}
|
||||
vm->typeError("float() argument must be a int, float, bool or str");
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bindMethod("float", "__neg__", [](VM* vm, PyVarList args) {
|
||||
return vm->PyFloat(-1.0 * vm->PyFloat_AS_C(args[0]));
|
||||
});
|
||||
@ -177,7 +220,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
_StrStream ss;
|
||||
ss << std::setprecision(std::numeric_limits<_Float>::max_digits10-1) << val;
|
||||
std::string s = ss.str();
|
||||
if(std::all_of(s.begin(), s.end(), isdigit)) s += ".0";
|
||||
if(std::all_of(s.begin()+1, s.end(), isdigit)) s += ".0";
|
||||
return vm->PyStr(s);
|
||||
});
|
||||
|
||||
@ -210,6 +253,11 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
return args[0]; // str is immutable
|
||||
});
|
||||
|
||||
_vm->bindMethod("str", "__iter__", [](VM* vm, PyVarList args) {
|
||||
auto it = std::make_shared<StringIterator>(vm, args[0]);
|
||||
return vm->PyIter(it);
|
||||
});
|
||||
|
||||
_vm->bindMethod("str", "__repr__", [](VM* vm, PyVarList args) {
|
||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
// we just do a simple repr here, no escaping
|
||||
@ -308,7 +356,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
/************ PyList ************/
|
||||
_vm->bindMethod("list", "__iter__", [](VM* vm, PyVarList args) {
|
||||
vm->__checkType(args[0], vm->_tp_list);
|
||||
auto iter = std::make_shared<VectorIterator>(args[0]);
|
||||
auto iter = std::make_shared<VectorIterator>(vm, args[0]);
|
||||
return vm->PyIter(iter);
|
||||
});
|
||||
|
||||
@ -395,9 +443,15 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
});
|
||||
|
||||
/************ PyTuple ************/
|
||||
_vm->bindMethod("tuple", "__new__", [](VM* vm, PyVarList args) {
|
||||
vm->__checkArgSize(args, 1);
|
||||
PyVarList _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args));
|
||||
return vm->PyTuple(_list);
|
||||
});
|
||||
|
||||
_vm->bindMethod("tuple", "__iter__", [](VM* vm, PyVarList args) {
|
||||
vm->__checkType(args[0], vm->_tp_tuple);
|
||||
auto iter = std::make_shared<VectorIterator>(args[0]);
|
||||
auto iter = std::make_shared<VectorIterator>(vm, args[0]);
|
||||
return vm->PyIter(iter);
|
||||
});
|
||||
|
||||
|
14
src/str.h
14
src/str.h
@ -75,6 +75,14 @@ public:
|
||||
return _s != other._s;
|
||||
}
|
||||
|
||||
bool operator==(const char* other) const {
|
||||
return _s == other;
|
||||
}
|
||||
|
||||
bool operator!=(const char* other) const {
|
||||
return _s != other;
|
||||
}
|
||||
|
||||
bool operator<(const _Str& other) const {
|
||||
return _s < other._s;
|
||||
}
|
||||
@ -116,12 +124,12 @@ public:
|
||||
return _s;
|
||||
}
|
||||
|
||||
static const std::size_t npos = std::string::npos;
|
||||
|
||||
operator const char*() const {
|
||||
const char* c_str() const {
|
||||
return _s.c_str();
|
||||
}
|
||||
|
||||
static const std::size_t npos = std::string::npos;
|
||||
|
||||
_Str __lstrip() const {
|
||||
std::string copy(_s);
|
||||
copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) {
|
||||
|
15
src/vm.h
15
src/vm.h
@ -132,7 +132,7 @@ private:
|
||||
{
|
||||
const PyVar& expr = frame->topValue(this);
|
||||
if(expr == None) break;
|
||||
_stdout(PyStr_AS_C(asRepr(expr)));
|
||||
_stdout(PyStr_AS_C(asRepr(expr)).c_str());
|
||||
_stdout("\n");
|
||||
} break;
|
||||
case OP_POP_TOP: frame->popValue(this); break;
|
||||
@ -799,8 +799,19 @@ void CompoundPointer::del(VM* vm, Frame* frame) const{
|
||||
for (auto& ptr : pointers) ptr->del(vm, frame);
|
||||
}
|
||||
|
||||
/**************** Frame ****************/
|
||||
/***** Frame's Impl *****/
|
||||
inline PyVar Frame::__deref_pointer(VM* vm, PyVar v){
|
||||
if(v->isType(vm->_tp_pointer)) v = vm->PyPointer_AS_C(v)->get(vm, this);
|
||||
return v;
|
||||
}
|
||||
|
||||
/***** Iterators' Impl *****/
|
||||
PyVar RangeIterator::next(){
|
||||
PyVar val = vm->PyInt(current);
|
||||
current += r.step;
|
||||
return val;
|
||||
}
|
||||
|
||||
PyVar StringIterator::next(){
|
||||
return vm->PyStr(str->u8_getitem(index++));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user