diff --git a/src/compiler.h b/src/compiler.h index 11f3abf7..55753ecf 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -95,7 +95,7 @@ public: rules[TK(",")] = { nullptr, METHOD(exprComma), PREC_COMMA }; rules[TK("<<")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; rules[TK(">>")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; - rules[TK("&")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_AND }; + rules[TK("&")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_BITWISE_AND }; rules[TK("|")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_OR }; rules[TK("^")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_XOR }; #undef METHOD @@ -449,6 +449,7 @@ public: switch (op) { case TK("-"): emitCode(OP_UNARY_NEGATIVE); break; case TK("not"): emitCode(OP_UNARY_NOT); break; + case TK("&"): emitCode(OP_UNARY_REF); break; default: UNREACHABLE(); } } diff --git a/src/opcodes.h b/src/opcodes.h index 30754267..281e6f47 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -59,5 +59,6 @@ OPCODE(BUILD_SMART_TUPLE) // if all elements are pointers, build a compound po OPCODE(BUILD_STRING) // arg is the expr count, build a string from the top of the stack OPCODE(GOTO) +OPCODE(UNARY_REF) // for & #endif \ No newline at end of file diff --git a/src/pocketpy.h b/src/pocketpy.h index 0e1a4483..bfa29e32 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -56,6 +56,19 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyStr(tvm->readStdin()); }); + _vm->bindMethod("pointer", "set", [](VM* vm, const pkpy::ArgList& args) { + vm->__checkArgSize(args, 2, true); + _Pointer& p = std::get<_Pointer>(args[0]->_native); + p->set(vm, vm->topFrame(), args[1]); + return vm->None; + }); + + _vm->bindMethod("pointer", "get", [](VM* vm, const pkpy::ArgList& args) { + vm->__checkArgSize(args, 1, true); + _Pointer& p = std::get<_Pointer>(args[0]->_native); + return p->get(vm, vm->topFrame()); + }); + _vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) { vm->__checkArgSize(args, 1); const _Str& expr = vm->PyStr_AS_C(args[0]); @@ -115,8 +128,13 @@ void __initializeBuiltinFunctions(VM* _vm) { _vm->bindBuiltinFunc("dir", [](VM* vm, const pkpy::ArgList& args) { vm->__checkArgSize(args, 1); + std::vector<_Str> names; + for (auto& [k, _] : args[0]->attribs) names.push_back(k); + for (auto& [k, _] : args[0]->_type->attribs) { + if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k); + } PyVarList ret; - for (auto& [k, _] : args[0]->attribs) ret.push_back(vm->PyStr(k)); + for (const auto& name : names) ret.push_back(vm->PyStr(name)); return vm->PyList(ret); }); diff --git a/src/vm.h b/src/vm.h index f570f6f0..e1010a84 100644 --- a/src/vm.h +++ b/src/vm.h @@ -207,6 +207,12 @@ private: const PyVar& obj_bool = asBool(obj); frame->push(PyBool(!PyBool_AS_C(obj_bool))); } break; + case OP_UNARY_REF: + { + PyVar obj = frame->__pop(); + _Pointer p = PyPointer_AS_C(obj); + frame->push(newObject(_tp_user_pointer, p)); + } break; case OP_POP_JUMP_IF_FALSE: if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg); break; @@ -659,12 +665,13 @@ public: PyVar _tp_list, _tp_tuple; PyVar _tp_function, _tp_native_function, _tp_native_iterator, _tp_bounded_method; PyVar _tp_slice, _tp_range, _tp_module, _tp_pointer; + PyVar _tp_user_pointer; __DEF_PY_POOL(Int, _Int, _tp_int, 256); __DEF_PY_AS_C(Int, _Int, _tp_int) __DEF_PY_POOL(Float, _Float, _tp_float, 256); __DEF_PY_AS_C(Float, _Float, _tp_float) - __DEF_PY_POOL(Pointer, _Pointer, _tp_pointer, 512) + __DEF_PY_POOL(Pointer, _Pointer, _tp_pointer, 256) __DEF_PY_AS_C(Pointer, _Pointer, _tp_pointer) DEF_NATIVE(Str, _Str, _tp_str) @@ -698,6 +705,7 @@ public: _tp_range = newClassType("range"); _tp_module = newClassType("module"); _tp_pointer = newClassType("_pointer"); + _tp_user_pointer = newClassType("pointer"); newClassType("NoneType"); newClassType("ellipsis");