ref.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #pragma once
  2. #include "obj.h"
  3. #include "vm.h"
  4. namespace pkpy {
  5. struct BaseRef {
  6. virtual PyVar get(VM*, Frame*) const = 0;
  7. virtual void set(VM*, Frame*, PyVar) 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. inline StrName name() const { return pair.first; }
  14. inline NameScope scope() const { return pair.second; }
  15. NameRef(const std::pair<StrName, NameScope>& pair) : pair(pair) {}
  16. PyVar get(VM* vm, Frame* frame) const{
  17. PyVar* 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, PyVar val) const{
  30. switch(scope()) {
  31. case NAME_LOCAL: frame->f_locals().set(name(), std::move(val)); break;
  32. case NAME_GLOBAL:
  33. if(frame->f_locals().try_set(name(), std::move(val))) return;
  34. frame->f_globals().set(name(), std::move(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 PyVar obj;
  66. NameRef attr;
  67. AttrRef(PyVar obj, NameRef attr) : obj(obj), attr(attr) {}
  68. PyVar get(VM* vm, Frame* frame) const{
  69. return vm->getattr(obj, attr.name());
  70. }
  71. void set(VM* vm, Frame* frame, PyVar 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 PyVar obj;
  82. PyVar index;
  83. IndexRef(PyVar obj, PyVar index) : obj(obj), index(index) {}
  84. PyVar get(VM* vm, Frame* frame) const{
  85. return vm->fast_call(__getitem__, two_args(obj, index));
  86. }
  87. void set(VM* vm, Frame* frame, PyVar val) const{
  88. Args args(3);
  89. args[0] = obj; args[1] = index; args[2] = std::move(val);
  90. vm->fast_call(__setitem__, std::move(args));
  91. }
  92. void del(VM* vm, Frame* frame) const{
  93. vm->fast_call(__delitem__, two_args(obj, index));
  94. }
  95. };
  96. struct TupleRef : BaseRef {
  97. Tuple objs;
  98. TupleRef(Tuple&& objs) : objs(std::move(objs)) {}
  99. PyVar get(VM* vm, Frame* frame) const{
  100. Tuple args(objs.size());
  101. for (int i = 0; i < objs.size(); i++) {
  102. args[i] = vm->PyRef_AS_C(objs[i])->get(vm, frame);
  103. }
  104. return VAR(std::move(args));
  105. }
  106. void set(VM* vm, Frame* frame, PyVar val) const{
  107. val = vm->asIter(val);
  108. BaseIter* iter = vm->PyIter_AS_C(val);
  109. for(int i=0; i<objs.size(); i++){
  110. PyVarOrNull x;
  111. if(is_type(objs[i], vm->tp_star_wrapper)){
  112. auto& star = _CAST(StarWrapper&, objs[i]);
  113. if(star.rvalue) vm->ValueError("can't use starred expression here");
  114. if(i != objs.size()-1) vm->ValueError("* can only be used at the end");
  115. auto ref = vm->PyRef_AS_C(star.obj);
  116. List list;
  117. while((x = iter->next()) != nullptr) list.push_back(x);
  118. ref->set(vm, frame, VAR(std::move(list)));
  119. return;
  120. }else{
  121. x = iter->next();
  122. if(x == nullptr) vm->ValueError("not enough values to unpack");
  123. vm->PyRef_AS_C(objs[i])->set(vm, frame, x);
  124. }
  125. }
  126. PyVarOrNull x = iter->next();
  127. if(x != nullptr) vm->ValueError("too many values to unpack");
  128. }
  129. void del(VM* vm, Frame* frame) const{
  130. for(int i=0; i<objs.size(); i++) vm->PyRef_AS_C(objs[i])->del(vm, frame);
  131. }
  132. };
  133. template<typename P>
  134. PyVarRef VM::PyRef(P&& value) {
  135. static_assert(std::is_base_of_v<BaseRef, std::decay_t<P>>);
  136. return new_object(tp_ref, std::forward<P>(value));
  137. }
  138. const BaseRef* VM::PyRef_AS_C(const PyVar& obj)
  139. {
  140. if(!is_type(obj, tp_ref)) TypeError("expected an l-value");
  141. return static_cast<const BaseRef*>(obj->value());
  142. }
  143. /***** Frame's Impl *****/
  144. inline void Frame::try_deref(VM* vm, PyVar& v){
  145. if(is_type(v, vm->tp_ref)) v = vm->PyRef_AS_C(v)->get(vm, this);
  146. }
  147. } // namespace pkpy