ref.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #pragma once
  2. #include "obj.h"
  3. #include "vm.h"
  4. namespace pkpy {
  5. struct BaseRef {
  6. virtual PyObject* get(VM*, Frame*) const = 0;
  7. virtual void set(VM*, Frame*, PyObject*) const = 0;
  8. virtual void del(VM*, Frame*) const = 0;
  9. virtual ~BaseRef() = default;
  10. };
  11. struct NameRef : BaseRef {
  12. const std::pair<StrName, NameScope> pair;
  13. StrName name() const { return pair.first; }
  14. NameScope scope() const { return pair.second; }
  15. NameRef(const std::pair<StrName, NameScope>& pair) : pair(pair) {}
  16. PyObject* get(VM* vm, Frame* frame) const{
  17. PyObject* val;
  18. val = frame->f_locals().try_get(name());
  19. if(val != nullptr) return val;
  20. val = frame->f_closure_try_get(name());
  21. if(val != nullptr) return val;
  22. val = frame->f_globals().try_get(name());
  23. if(val != nullptr) return val;
  24. val = vm->builtins->attr().try_get(name());
  25. if(val != nullptr) return val;
  26. vm->NameError(name());
  27. return nullptr;
  28. }
  29. void set(VM* vm, Frame* frame, PyObject* val) const{
  30. switch(scope()) {
  31. case NAME_LOCAL: frame->f_locals().set(name(), val); break;
  32. case NAME_GLOBAL:
  33. if(frame->f_locals().try_set(name(), val)) return;
  34. frame->f_globals().set(name(), val);
  35. break;
  36. default: UNREACHABLE();
  37. }
  38. }
  39. void del(VM* vm, Frame* frame) const{
  40. switch(scope()) {
  41. case NAME_LOCAL: {
  42. if(frame->f_locals().contains(name())){
  43. frame->f_locals().erase(name());
  44. }else{
  45. vm->NameError(name());
  46. }
  47. } break;
  48. case NAME_GLOBAL:
  49. {
  50. if(frame->f_locals().contains(name())){
  51. frame->f_locals().erase(name());
  52. }else{
  53. if(frame->f_globals().contains(name())){
  54. frame->f_globals().erase(name());
  55. }else{
  56. vm->NameError(name());
  57. }
  58. }
  59. } break;
  60. default: UNREACHABLE();
  61. }
  62. }
  63. };
  64. struct AttrRef : BaseRef {
  65. mutable PyObject* obj;
  66. NameRef attr;
  67. AttrRef(PyObject* obj, NameRef attr) : obj(obj), attr(attr) {}
  68. PyObject* get(VM* vm, Frame* frame) const{
  69. return vm->getattr(obj, attr.name());
  70. }
  71. void set(VM* vm, Frame* frame, PyObject* val) const{
  72. vm->setattr(obj, attr.name(), std::move(val));
  73. }
  74. void del(VM* vm, Frame* frame) const{
  75. if(!obj->is_attr_valid()) vm->TypeError("cannot delete attribute");
  76. if(!obj->attr().contains(attr.name())) vm->AttributeError(obj, attr.name());
  77. obj->attr().erase(attr.name());
  78. }
  79. };
  80. struct IndexRef : BaseRef {
  81. mutable PyObject* obj;
  82. PyObject* index;
  83. IndexRef(PyObject* obj, PyObject* index) : obj(obj), index(index) {}
  84. PyObject* get(VM* vm, Frame* frame) const{
  85. return vm->fast_call(__getitem__, Args{obj, index});
  86. }
  87. void set(VM* vm, Frame* frame, PyObject* val) const{
  88. vm->fast_call(__setitem__, Args{obj, index, val});
  89. }
  90. void del(VM* vm, Frame* frame) const{
  91. vm->fast_call(__delitem__, Args{obj, index});
  92. }
  93. };
  94. struct TupleRef : BaseRef {
  95. Tuple objs;
  96. TupleRef(Tuple&& objs) : objs(std::move(objs)) {}
  97. PyObject* get(VM* vm, Frame* frame) const{
  98. Tuple args(objs.size());
  99. for (int i = 0; i < objs.size(); i++) {
  100. args[i] = vm->PyRef_AS_C(objs[i])->get(vm, frame);
  101. }
  102. return VAR(std::move(args));
  103. }
  104. void set(VM* vm, Frame* frame, PyObject* val) const{
  105. val = vm->asIter(val);
  106. BaseIter* iter = vm->PyIter_AS_C(val);
  107. for(int i=0; i<objs.size(); i++){
  108. PyObject* x;
  109. if(is_type(objs[i], vm->tp_star_wrapper)){
  110. auto& star = _CAST(StarWrapper&, objs[i]);
  111. if(star.rvalue) vm->ValueError("can't use starred expression here");
  112. if(i != objs.size()-1) vm->ValueError("* can only be used at the end");
  113. auto ref = vm->PyRef_AS_C(star.obj);
  114. List list;
  115. while((x = iter->next()) != nullptr) list.push_back(x);
  116. ref->set(vm, frame, VAR(std::move(list)));
  117. return;
  118. }else{
  119. x = iter->next();
  120. if(x == nullptr) vm->ValueError("not enough values to unpack");
  121. vm->PyRef_AS_C(objs[i])->set(vm, frame, x);
  122. }
  123. }
  124. PyObject* x = iter->next();
  125. if(x != nullptr) vm->ValueError("too many values to unpack");
  126. }
  127. void del(VM* vm, Frame* frame) const{
  128. for(int i=0; i<objs.size(); i++) vm->PyRef_AS_C(objs[i])->del(vm, frame);
  129. }
  130. };
  131. template<typename P>
  132. PyObject* VM::PyRef(P&& value) {
  133. static_assert(std::is_base_of_v<BaseRef, std::decay_t<P>>);
  134. return gcnew<P>(tp_ref, std::forward<P>(value));
  135. }
  136. inline const BaseRef* VM::PyRef_AS_C(PyObject* obj)
  137. {
  138. if(!is_type(obj, tp_ref)) TypeError("expected an l-value");
  139. return static_cast<const BaseRef*>(obj->value());
  140. }
  141. /***** Frame's Impl *****/
  142. inline void Frame::try_deref(VM* vm, PyObject*& v){
  143. if(is_type(v, vm->tp_ref)) v = vm->PyRef_AS_C(v)->get(vm, this);
  144. }
  145. } // namespace pkpy