diff --git a/src/builtins.h b/src/builtins.h index 05c79d86..46a14781 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -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): diff --git a/src/error.h b/src/error.h index 0141b32d..4afbbd2c 100644 --- a/src/error.h +++ b/src/error.h @@ -62,7 +62,7 @@ public: } const char* what() const noexcept override { - return _what; + return _what.c_str(); } }; diff --git a/src/iter.h b/src/iter.h index 7818119f..819809bc 100644 --- a/src/iter.h +++ b/src/iter.h @@ -2,25 +2,16 @@ #include "obj.h" -typedef std::function _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(_ref->_native); } @@ -46,4 +39,20 @@ public: PyVar next(){ return vec->operator[](index++); } -}; \ No newline at end of file +}; + +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(); +}; diff --git a/src/obj.h b/src/obj.h index 591cd8bf..4ad5c63d 100644 --- a/src/obj.h +++ b/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; diff --git a/src/pocketpy.h b/src/pocketpy.h index e157c4ad..e69a8acf 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -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_MODE); + _Code code = compile(vm, expr.c_str(), "", 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(args[0], [=](_Int val){return vm->PyInt(val);}); + auto iter = std::make_shared(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(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(args[0]); + auto iter = std::make_shared(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(args[0]); + auto iter = std::make_shared(vm, args[0]); return vm->PyIter(iter); }); diff --git a/src/str.h b/src/str.h index ab3cdfaa..7551bc0c 100644 --- a/src/str.h +++ b/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) { diff --git a/src/vm.h b/src/vm.h index bb85fa57..67aa6853 100644 --- a/src/vm.h +++ b/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++)); } \ No newline at end of file