| 735 | } |
| 736 | |
| 737 | bool Debugger::CreateEnv(lua_State *L, int stackLevel) { |
| 738 | if (!L) { |
| 739 | return false; |
| 740 | } |
| 741 | |
| 742 | |
| 743 | //assert(L); |
| 744 | //const auto L = L; |
| 745 | |
| 746 | lua_Debug ar{}; |
| 747 | if (!lua_getstack(L, stackLevel, &ar)) { |
| 748 | return false; |
| 749 | } |
| 750 | if (!lua_getinfo(L, "nSlu", &ar)) { |
| 751 | return false; |
| 752 | } |
| 753 | |
| 754 | lua_newtable(L); |
| 755 | const int env = lua_gettop(L); |
| 756 | lua_newtable(L); |
| 757 | const int envMetatable = lua_gettop(L); |
| 758 | lua_newtable(L); |
| 759 | const int locals = lua_gettop(L); |
| 760 | lua_newtable(L); |
| 761 | const int upvalues = lua_gettop(L); |
| 762 | |
| 763 | int idx = 1; |
| 764 | // local values |
| 765 | while (true) { |
| 766 | const char *name = lua_getlocal(L, &ar, idx++); |
| 767 | if (name == nullptr) |
| 768 | break; |
| 769 | if (name[0] == '(') { |
| 770 | lua_pop(L, 1); |
| 771 | continue; |
| 772 | } |
| 773 | lua_setfield(L, locals, name); |
| 774 | } |
| 775 | // up values |
| 776 | if (lua_getinfo(L, "f", &ar)) { |
| 777 | const int fIdx = lua_gettop(L); |
| 778 | idx = 1; |
| 779 | while (true) { |
| 780 | const char *name = lua_getupvalue(L, fIdx, idx++); |
| 781 | if (name == nullptr) |
| 782 | break; |
| 783 | lua_setfield(L, upvalues, name); |
| 784 | } |
| 785 | lua_pop(L, 1); |
| 786 | } |
| 787 | int top = lua_gettop(L); |
| 788 | assert(top == upvalues); |
| 789 | |
| 790 | // index function |
| 791 | // up value: locals, upvalues |
| 792 | lua_pushcclosure(L, EnvIndexFunction, 2); |
| 793 | |
| 794 | // envMetatable.__index = EnvIndexFunction |
nothing calls this directly
no test coverage detected