this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #2200 from blueloveTH/main

Convert `vendor/pocketpy` into a git submodule

authored by

Vadim Grigoruk and committed by
GitHub
7ca2f44c a7e5bbb3

+19 -9180
+3
.gitmodules
··· 82 82 [submodule "vendor/janet"] 83 83 path = vendor/janet 84 84 url = https://github.com/janet-lang/janet.git 85 + [submodule "vendor/pocketpy"] 86 + path = vendor/pocketpy 87 + url = https://github.com/blueloveTH/pocketpy
+16 -4
CMakeLists.txt
··· 401 401 ################################ 402 402 403 403 set(POCKETPY_DIR ${THIRDPARTY_DIR}/pocketpy) 404 - set(POCKETPY_SRC 405 - ${POCKETPY_DIR}/pocketpy_c.cpp 404 + execute_process( 405 + COMMAND python3 preprocess.py 406 + WORKING_DIRECTORY ${POCKETPY_DIR} 407 + RESULT_VARIABLE EXIT_CODE 406 408 ) 407 409 408 - add_library(python STATIC ${POCKETPY_SRC}) 410 + if(NOT ${EXIT_CODE} EQUAL 0) 411 + message(FATAL_ERROR "python3 prebuild failed!!") 412 + endif() 413 + 414 + add_library( 415 + python 416 + STATIC 417 + ${POCKETPY_DIR}/c_bindings/pocketpy_c.cpp 418 + ) 409 419 set_target_properties(python PROPERTIES LINKER_LANGUAGE CXX) 410 - target_include_directories(python PUBLIC ${POCKETPY_DIR}) 420 + target_compile_definitions(python PRIVATE PK_ENABLE_OS=0) 421 + target_include_directories(python PRIVATE ${POCKETPY_DIR}/src) 422 + target_include_directories(python PUBLIC ${POCKETPY_DIR}/c_bindings) 411 423 if (${CMAKE_VERSION} VERSION_LESS "3.8.0") 412 424 set_target_properties(python PROPERTIES COMPILE_FLAGS "--std=c++17") 413 425 else()
-8483
vendor/pocketpy/pocketpy.h
··· 1 - /* 2 - * Copyright (c) 2023 blueloveTH 3 - * Distributed Under The MIT License 4 - * https://github.com/blueloveTH/pocketpy 5 - */ 6 - 7 - #ifndef POCKETPY_H 8 - #define POCKETPY_H 9 - 10 - 11 - #ifdef _MSC_VER 12 - #pragma warning (disable:4267) 13 - #pragma warning (disable:4101) 14 - #pragma warning (disable:4244) 15 - #define _CRT_NONSTDC_NO_DEPRECATE 16 - #define strdup _strdup 17 - #endif 18 - 19 - #include <cmath> 20 - #include <cstring> 21 - 22 - #include <sstream> 23 - #include <regex> 24 - #include <stdexcept> 25 - #include <vector> 26 - #include <string> 27 - #include <chrono> 28 - #include <string_view> 29 - #include <iomanip> 30 - #include <memory> 31 - #include <iostream> 32 - #include <map> 33 - #include <set> 34 - #include <algorithm> 35 - #include <random> 36 - #include <initializer_list> 37 - #include <variant> 38 - #include <type_traits> 39 - 40 - #define PK_VERSION "0.9.9" 41 - 42 - // debug macros 43 - #define DEBUG_NO_BUILTIN_MODULES 0 44 - #define DEBUG_EXTRA_CHECK 0 45 - #define DEBUG_DIS_EXEC 0 46 - #define DEBUG_CEVAL_STEP 0 47 - #define DEBUG_CEVAL_STEP_MIN 0 48 - #define DEBUG_FULL_EXCEPTION 0 49 - #define DEBUG_MEMORY_POOL 0 50 - #define DEBUG_NO_MEMORY_POOL 0 51 - #define DEBUG_NO_AUTO_GC 0 52 - #define DEBUG_GC_STATS 0 53 - 54 - #ifdef __ANDROID__ 55 - #include <android/ndk-version.h> 56 - 57 - #if __NDK_MAJOR__ <= 22 58 - #define PK_ENABLE_OS 0 59 - #else 60 - #define PK_ENABLE_OS 0 61 - #endif 62 - 63 - #else 64 - #define PK_ENABLE_OS 0 65 - #endif 66 - 67 - // This is the maximum number of arguments in a function declaration 68 - // including positional arguments, keyword-only arguments, and varargs 69 - #define PK_MAX_CO_VARNAMES 255 70 - 71 - #if _MSC_VER 72 - #define PK_ENABLE_COMPUTED_GOTO 0 73 - #define UNREACHABLE() __assume(0) 74 - #else 75 - #define PK_ENABLE_COMPUTED_GOTO 1 76 - #define UNREACHABLE() __builtin_unreachable() 77 - 78 - #if DEBUG_CEVAL_STEP || DEBUG_CEVAL_STEP_MIN 79 - #undef PK_ENABLE_COMPUTED_GOTO 80 - #endif 81 - 82 - #endif 83 - 84 - namespace pkpy{ 85 - 86 - namespace std = ::std; 87 - 88 - template <size_t T> 89 - struct NumberTraits; 90 - 91 - template <> 92 - struct NumberTraits<4> { 93 - using int_t = int32_t; 94 - using float_t = float; 95 - 96 - template<typename... Args> 97 - static int_t stoi(Args&&... args) { return std::stoi(std::forward<Args>(args)...); } 98 - template<typename... Args> 99 - static float_t stof(Args&&... args) { return std::stof(std::forward<Args>(args)...); } 100 - }; 101 - 102 - template <> 103 - struct NumberTraits<8> { 104 - using int_t = int64_t; 105 - using float_t = double; 106 - 107 - template<typename... Args> 108 - static int_t stoi(Args&&... args) { return std::stoll(std::forward<Args>(args)...); } 109 - template<typename... Args> 110 - static float_t stof(Args&&... args) { return std::stod(std::forward<Args>(args)...); } 111 - }; 112 - 113 - using Number = NumberTraits<sizeof(void*)>; 114 - using i64 = Number::int_t; 115 - using f64 = Number::float_t; 116 - 117 - static_assert(sizeof(i64) == sizeof(void*)); 118 - static_assert(sizeof(f64) == sizeof(void*)); 119 - static_assert(std::numeric_limits<f64>::is_iec559); 120 - 121 - struct Dummy { }; 122 - struct DummyInstance { }; 123 - struct DummyModule { }; 124 - struct Discarded { }; 125 - 126 - struct Type { 127 - int index; 128 - Type(): index(-1) {} 129 - Type(int index): index(index) {} 130 - bool operator==(Type other) const noexcept { return this->index == other.index; } 131 - bool operator!=(Type other) const noexcept { return this->index != other.index; } 132 - operator int() const noexcept { return this->index; } 133 - }; 134 - 135 - #define THREAD_LOCAL // thread_local 136 - #define CPP_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; }) 137 - #define CPP_NOT_IMPLEMENTED() ([](VM* vm, ArgsView args) { vm->NotImplementedError(); return vm->None; }) 138 - 139 - #ifdef POCKETPY_H 140 - #define FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!"); 141 - #else 142 - #define FATAL_ERROR() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " FATAL_ERROR()!"); 143 - #endif 144 - 145 - inline const float kInstAttrLoadFactor = 0.67f; 146 - inline const float kTypeAttrLoadFactor = 0.5f; 147 - 148 - struct PyObject; 149 - #define BITS(p) (reinterpret_cast<i64>(p)) 150 - inline bool is_tagged(PyObject* p) noexcept { return (BITS(p) & 0b11) != 0b00; } 151 - inline bool is_int(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b01; } 152 - inline bool is_float(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b10; } 153 - inline bool is_special(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b11; } 154 - 155 - inline bool is_both_int_or_float(PyObject* a, PyObject* b) noexcept { 156 - return is_tagged(a) && is_tagged(b); 157 - } 158 - 159 - inline bool is_both_int(PyObject* a, PyObject* b) noexcept { 160 - return is_int(a) && is_int(b); 161 - } 162 - 163 - // special singals, is_tagged() for them is true 164 - inline PyObject* const PY_NULL = (PyObject*)0b000011; 165 - inline PyObject* const PY_BEGIN_CALL = (PyObject*)0b010011; 166 - inline PyObject* const PY_OP_CALL = (PyObject*)0b100011; 167 - inline PyObject* const PY_OP_YIELD = (PyObject*)0b110011; 168 - 169 - struct Expr; 170 - typedef std::unique_ptr<Expr> Expr_; 171 - 172 - } // namespace pkpy 173 - 174 - 175 - namespace pkpy{ 176 - 177 - struct LinkedListNode{ 178 - LinkedListNode* prev; 179 - LinkedListNode* next; 180 - }; 181 - 182 - template<typename T> 183 - struct DoubleLinkedList{ 184 - static_assert(std::is_base_of_v<LinkedListNode, T>); 185 - int _size; 186 - LinkedListNode head; 187 - LinkedListNode tail; 188 - 189 - DoubleLinkedList(): _size(0){ 190 - head.prev = nullptr; 191 - head.next = &tail; 192 - tail.prev = &head; 193 - tail.next = nullptr; 194 - } 195 - 196 - void push_back(T* node){ 197 - node->prev = tail.prev; 198 - node->next = &tail; 199 - tail.prev->next = node; 200 - tail.prev = node; 201 - _size++; 202 - } 203 - 204 - void push_front(T* node){ 205 - node->prev = &head; 206 - node->next = head.next; 207 - head.next->prev = node; 208 - head.next = node; 209 - _size++; 210 - } 211 - 212 - void pop_back(){ 213 - #if DEBUG_MEMORY_POOL 214 - if(empty()) throw std::runtime_error("DoubleLinkedList::pop_back() called on empty list"); 215 - #endif 216 - tail.prev->prev->next = &tail; 217 - tail.prev = tail.prev->prev; 218 - _size--; 219 - } 220 - 221 - void pop_front(){ 222 - #if DEBUG_MEMORY_POOL 223 - if(empty()) throw std::runtime_error("DoubleLinkedList::pop_front() called on empty list"); 224 - #endif 225 - head.next->next->prev = &head; 226 - head.next = head.next->next; 227 - _size--; 228 - } 229 - 230 - T* back() const { 231 - #if DEBUG_MEMORY_POOL 232 - if(empty()) throw std::runtime_error("DoubleLinkedList::back() called on empty list"); 233 - #endif 234 - return static_cast<T*>(tail.prev); 235 - } 236 - 237 - T* front() const { 238 - #if DEBUG_MEMORY_POOL 239 - if(empty()) throw std::runtime_error("DoubleLinkedList::front() called on empty list"); 240 - #endif 241 - return static_cast<T*>(head.next); 242 - } 243 - 244 - void erase(T* node){ 245 - #if DEBUG_MEMORY_POOL 246 - if(empty()) throw std::runtime_error("DoubleLinkedList::erase() called on empty list"); 247 - LinkedListNode* n = head.next; 248 - while(n != &tail){ 249 - if(n == node) break; 250 - n = n->next; 251 - } 252 - if(n != node) throw std::runtime_error("DoubleLinkedList::erase() called on node not in the list"); 253 - #endif 254 - node->prev->next = node->next; 255 - node->next->prev = node->prev; 256 - _size--; 257 - } 258 - 259 - void move_all_back(DoubleLinkedList<T>& other){ 260 - if(other.empty()) return; 261 - other.tail.prev->next = &tail; 262 - tail.prev->next = other.head.next; 263 - other.head.next->prev = tail.prev; 264 - tail.prev = other.tail.prev; 265 - _size += other._size; 266 - other.head.next = &other.tail; 267 - other.tail.prev = &other.head; 268 - other._size = 0; 269 - } 270 - 271 - bool empty() const { 272 - #if DEBUG_MEMORY_POOL 273 - if(size() == 0){ 274 - if(head.next != &tail || tail.prev != &head){ 275 - throw std::runtime_error("DoubleLinkedList::size() returned 0 but the list is not empty"); 276 - } 277 - return true; 278 - } 279 - #endif 280 - return _size == 0; 281 - } 282 - 283 - int size() const { return _size; } 284 - 285 - template<typename Func> 286 - void apply(Func func){ 287 - LinkedListNode* p = head.next; 288 - while(p != &tail){ 289 - LinkedListNode* next = p->next; 290 - func(static_cast<T*>(p)); 291 - p = next; 292 - } 293 - } 294 - }; 295 - 296 - template<int __BlockSize=128> 297 - struct MemoryPool{ 298 - static const size_t __MaxBlocks = 256*1024 / __BlockSize; 299 - struct Block{ 300 - void* arena; 301 - char data[__BlockSize]; 302 - }; 303 - 304 - struct Arena: LinkedListNode{ 305 - Block _blocks[__MaxBlocks]; 306 - Block* _free_list[__MaxBlocks]; 307 - int _free_list_size; 308 - bool dirty; 309 - 310 - Arena(): _free_list_size(__MaxBlocks), dirty(false){ 311 - for(int i=0; i<__MaxBlocks; i++){ 312 - _blocks[i].arena = this; 313 - _free_list[i] = &_blocks[i]; 314 - } 315 - } 316 - 317 - bool empty() const { return _free_list_size == 0; } 318 - bool full() const { return _free_list_size == __MaxBlocks; } 319 - 320 - size_t allocated_size() const{ 321 - return __BlockSize * (__MaxBlocks - _free_list_size); 322 - } 323 - 324 - Block* alloc(){ 325 - #if DEBUG_MEMORY_POOL 326 - if(empty()) throw std::runtime_error("Arena::alloc() called on empty arena"); 327 - #endif 328 - _free_list_size--; 329 - return _free_list[_free_list_size]; 330 - } 331 - 332 - void dealloc(Block* block){ 333 - #if DEBUG_MEMORY_POOL 334 - if(full()) throw std::runtime_error("Arena::dealloc() called on full arena"); 335 - #endif 336 - _free_list[_free_list_size] = block; 337 - _free_list_size++; 338 - } 339 - }; 340 - 341 - DoubleLinkedList<Arena> _arenas; 342 - DoubleLinkedList<Arena> _empty_arenas; 343 - 344 - template<typename __T> 345 - void* alloc() { return alloc(sizeof(__T)); } 346 - 347 - void* alloc(size_t size){ 348 - #if DEBUG_NO_MEMORY_POOL 349 - return malloc(size); 350 - #endif 351 - if(size > __BlockSize){ 352 - void* p = malloc(sizeof(void*) + size); 353 - memset(p, 0, sizeof(void*)); 354 - return (char*)p + sizeof(void*); 355 - } 356 - 357 - if(_arenas.empty()){ 358 - // std::cout << _arenas.size() << ',' << _empty_arenas.size() << ',' << _full_arenas.size() << std::endl; 359 - _arenas.push_back(new Arena()); 360 - } 361 - Arena* arena = _arenas.back(); 362 - void* p = arena->alloc()->data; 363 - if(arena->empty()){ 364 - _arenas.pop_back(); 365 - arena->dirty = true; 366 - _empty_arenas.push_back(arena); 367 - } 368 - return p; 369 - } 370 - 371 - void dealloc(void* p){ 372 - #if DEBUG_NO_MEMORY_POOL 373 - free(p); 374 - return; 375 - #endif 376 - #if DEBUG_MEMORY_POOL 377 - if(p == nullptr) throw std::runtime_error("MemoryPool::dealloc() called on nullptr"); 378 - #endif 379 - Block* block = (Block*)((char*)p - sizeof(void*)); 380 - if(block->arena == nullptr){ 381 - free(block); 382 - }else{ 383 - Arena* arena = (Arena*)block->arena; 384 - if(arena->empty()){ 385 - _empty_arenas.erase(arena); 386 - _arenas.push_front(arena); 387 - arena->dealloc(block); 388 - }else{ 389 - arena->dealloc(block); 390 - if(arena->full() && arena->dirty){ 391 - _arenas.erase(arena); 392 - delete arena; 393 - } 394 - } 395 - } 396 - } 397 - 398 - size_t allocated_size() { 399 - size_t n = 0; 400 - _arenas.apply([&n](Arena* arena){ n += arena->allocated_size(); }); 401 - _empty_arenas.apply([&n](Arena* arena){ n += arena->allocated_size(); }); 402 - return n; 403 - } 404 - 405 - ~MemoryPool(){ 406 - _arenas.apply([](Arena* arena){ delete arena; }); 407 - _empty_arenas.apply([](Arena* arena){ delete arena; }); 408 - } 409 - }; 410 - 411 - inline MemoryPool<64> pool64; 412 - inline MemoryPool<128> pool128; 413 - 414 - // get the total memory usage of pkpy (across all VMs) 415 - inline size_t memory_usage(){ 416 - return pool64.allocated_size() + pool128.allocated_size(); 417 - } 418 - 419 - #define SP_MALLOC(size) pool128.alloc(size) 420 - #define SP_FREE(p) pool128.dealloc(p) 421 - 422 - template <typename T> 423 - struct shared_ptr { 424 - int* counter; 425 - 426 - T* _t() const noexcept { return (T*)(counter + 1); } 427 - void _inc_counter() { if(counter) ++(*counter); } 428 - void _dec_counter() { if(counter && --(*counter) == 0) {((T*)(counter + 1))->~T(); SP_FREE(counter);} } 429 - 430 - public: 431 - shared_ptr() : counter(nullptr) {} 432 - shared_ptr(int* counter) : counter(counter) {} 433 - shared_ptr(const shared_ptr& other) : counter(other.counter) { 434 - _inc_counter(); 435 - } 436 - shared_ptr(shared_ptr&& other) noexcept : counter(other.counter) { 437 - other.counter = nullptr; 438 - } 439 - ~shared_ptr() { _dec_counter(); } 440 - 441 - bool operator==(const shared_ptr& other) const { return counter == other.counter; } 442 - bool operator!=(const shared_ptr& other) const { return counter != other.counter; } 443 - bool operator<(const shared_ptr& other) const { return counter < other.counter; } 444 - bool operator>(const shared_ptr& other) const { return counter > other.counter; } 445 - bool operator<=(const shared_ptr& other) const { return counter <= other.counter; } 446 - bool operator>=(const shared_ptr& other) const { return counter >= other.counter; } 447 - bool operator==(std::nullptr_t) const { return counter == nullptr; } 448 - bool operator!=(std::nullptr_t) const { return counter != nullptr; } 449 - 450 - shared_ptr& operator=(const shared_ptr& other) { 451 - _dec_counter(); 452 - counter = other.counter; 453 - _inc_counter(); 454 - return *this; 455 - } 456 - 457 - shared_ptr& operator=(shared_ptr&& other) noexcept { 458 - _dec_counter(); 459 - counter = other.counter; 460 - other.counter = nullptr; 461 - return *this; 462 - } 463 - 464 - T& operator*() const { return *_t(); } 465 - T* operator->() const { return _t(); } 466 - T* get() const { return _t(); } 467 - 468 - int use_count() const { 469 - return counter ? *counter : 0; 470 - } 471 - 472 - void reset(){ 473 - _dec_counter(); 474 - counter = nullptr; 475 - } 476 - }; 477 - 478 - template <typename T, typename... Args> 479 - shared_ptr<T> make_sp(Args&&... args) { 480 - int* p = (int*)SP_MALLOC(sizeof(int) + sizeof(T)); 481 - *p = 1; 482 - new(p+1) T(std::forward<Args>(args)...); 483 - return shared_ptr<T>(p); 484 - } 485 - 486 - }; // namespace pkpy 487 - 488 - 489 - 490 - namespace pkpy{ 491 - 492 - template<typename T> 493 - struct pod_vector{ 494 - static_assert(128 % sizeof(T) == 0); 495 - static_assert(std::is_pod_v<T>); 496 - static constexpr int N = 128 / sizeof(T); 497 - static_assert(N > 4); 498 - int _size; 499 - int _capacity; 500 - T* _data; 501 - 502 - pod_vector(): _size(0), _capacity(N) { 503 - _data = (T*)pool128.alloc(_capacity * sizeof(T)); 504 - } 505 - 506 - pod_vector(int size): _size(size), _capacity(std::max(N, size)) { 507 - _data = (T*)pool128.alloc(_capacity * sizeof(T)); 508 - } 509 - 510 - pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) { 511 - _data = (T*)pool128.alloc(_capacity * sizeof(T)); 512 - memcpy(_data, other._data, sizeof(T) * _size); 513 - } 514 - 515 - pod_vector(pod_vector&& other) noexcept { 516 - _size = other._size; 517 - _capacity = other._capacity; 518 - _data = other._data; 519 - other._data = nullptr; 520 - } 521 - 522 - pod_vector& operator=(pod_vector&& other) noexcept { 523 - if(_data!=nullptr) pool128.dealloc(_data); 524 - _size = other._size; 525 - _capacity = other._capacity; 526 - _data = other._data; 527 - other._data = nullptr; 528 - return *this; 529 - } 530 - 531 - // remove copy assignment 532 - pod_vector& operator=(const pod_vector& other) = delete; 533 - 534 - template<typename __ValueT> 535 - void push_back(__ValueT&& t) { 536 - if (_size == _capacity) reserve(_capacity*2); 537 - _data[_size++] = std::forward<__ValueT>(t); 538 - } 539 - 540 - template<typename... Args> 541 - void emplace_back(Args&&... args) { 542 - if (_size == _capacity) reserve(_capacity*2); 543 - new (&_data[_size++]) T(std::forward<Args>(args)...); 544 - } 545 - 546 - void reserve(int cap){ 547 - if(cap <= _capacity) return; 548 - _capacity = cap; 549 - T* old_data = _data; 550 - _data = (T*)pool128.alloc(_capacity * sizeof(T)); 551 - if(old_data!=nullptr){ 552 - memcpy(_data, old_data, sizeof(T) * _size); 553 - pool128.dealloc(old_data); 554 - } 555 - } 556 - 557 - void pop_back() { _size--; } 558 - T popx_back() { T t = std::move(_data[_size-1]); _size--; return t; } 559 - void extend(const pod_vector& other){ 560 - for(int i=0; i<other.size(); i++) push_back(other[i]); 561 - } 562 - 563 - T& operator[](int index) { return _data[index]; } 564 - const T& operator[](int index) const { return _data[index]; } 565 - 566 - T* begin() { return _data; } 567 - T* end() { return _data + _size; } 568 - const T* begin() const { return _data; } 569 - const T* end() const { return _data + _size; } 570 - T& back() { return _data[_size - 1]; } 571 - const T& back() const { return _data[_size - 1]; } 572 - 573 - bool empty() const { return _size == 0; } 574 - int size() const { return _size; } 575 - T* data() { return _data; } 576 - const T* data() const { return _data; } 577 - void clear() { _size=0; } 578 - 579 - template<typename __ValueT> 580 - void insert(int i, __ValueT&& val){ 581 - if (_size == _capacity) reserve(_capacity*2); 582 - for(int j=_size; j>i; j--) _data[j] = _data[j-1]; 583 - _data[i] = std::forward<__ValueT>(val); 584 - _size++; 585 - } 586 - 587 - void erase(int i){ 588 - for(int j=i; j<_size-1; j++) _data[j] = _data[j+1]; 589 - _size--; 590 - } 591 - 592 - void resize(int size){ 593 - if(size > _capacity) reserve(size); 594 - _size = size; 595 - } 596 - 597 - ~pod_vector() { 598 - if(_data!=nullptr) pool128.dealloc(_data); 599 - } 600 - }; 601 - 602 - 603 - template <typename T, typename Container=std::vector<T>> 604 - class stack{ 605 - Container vec; 606 - public: 607 - void push(const T& t){ vec.push_back(t); } 608 - void push(T&& t){ vec.push_back(std::move(t)); } 609 - template<typename... Args> 610 - void emplace(Args&&... args){ 611 - vec.emplace_back(std::forward<Args>(args)...); 612 - } 613 - void pop(){ vec.pop_back(); } 614 - void clear(){ vec.clear(); } 615 - bool empty() const { return vec.empty(); } 616 - size_t size() const { return vec.size(); } 617 - T& top(){ return vec.back(); } 618 - const T& top() const { return vec.back(); } 619 - T popx(){ T t = std::move(vec.back()); vec.pop_back(); return t; } 620 - void reserve(int n){ vec.reserve(n); } 621 - Container& data() { return vec; } 622 - }; 623 - 624 - template <typename T> 625 - using pod_stack = stack<T, pod_vector<T>>; 626 - } // namespace pkpy 627 - 628 - 629 - namespace pkpy { 630 - 631 - inline int utf8len(unsigned char c, bool suppress=false){ 632 - if((c & 0b10000000) == 0) return 1; 633 - if((c & 0b11100000) == 0b11000000) return 2; 634 - if((c & 0b11110000) == 0b11100000) return 3; 635 - if((c & 0b11111000) == 0b11110000) return 4; 636 - if((c & 0b11111100) == 0b11111000) return 5; 637 - if((c & 0b11111110) == 0b11111100) return 6; 638 - if(!suppress) throw std::runtime_error("invalid utf8 char: " + std::to_string(c)); 639 - return 0; 640 - } 641 - 642 - struct Str{ 643 - int size; 644 - bool is_ascii; 645 - char* data; 646 - 647 - Str(): size(0), is_ascii(true), data(nullptr) {} 648 - 649 - Str(int size, bool is_ascii): size(size), is_ascii(is_ascii) { 650 - data = (char*)pool64.alloc(size); 651 - } 652 - 653 - #define STR_INIT() \ 654 - data = (char*)pool64.alloc(size); \ 655 - for(int i=0; i<size; i++){ \ 656 - data[i] = s[i]; \ 657 - if(!isascii(s[i])) is_ascii = false; \ 658 - } 659 - 660 - Str(const std::string& s): size(s.size()), is_ascii(true) { 661 - STR_INIT() 662 - } 663 - 664 - Str(std::string_view s): size(s.size()), is_ascii(true) { 665 - STR_INIT() 666 - } 667 - 668 - Str(const char* s): size(strlen(s)), is_ascii(true) { 669 - STR_INIT() 670 - } 671 - 672 - Str(const char* s, int len): size(len), is_ascii(true) { 673 - STR_INIT() 674 - } 675 - 676 - #undef STR_INIT 677 - 678 - Str(const Str& other): size(other.size), is_ascii(other.is_ascii) { 679 - data = (char*)pool64.alloc(size); 680 - memcpy(data, other.data, size); 681 - } 682 - 683 - Str(Str&& other): size(other.size), is_ascii(other.is_ascii), data(other.data) { 684 - other.data = nullptr; 685 - other.size = 0; 686 - } 687 - 688 - const char* begin() const { return data; } 689 - const char* end() const { return data + size; } 690 - char operator[](int idx) const { return data[idx]; } 691 - int length() const { return size; } 692 - bool empty() const { return size == 0; } 693 - size_t hash() const{ return std::hash<std::string_view>()(sv()); } 694 - 695 - Str& operator=(const Str& other){ 696 - if(data!=nullptr) pool64.dealloc(data); 697 - size = other.size; 698 - is_ascii = other.is_ascii; 699 - data = (char*)pool64.alloc(size); 700 - memcpy(data, other.data, size); 701 - return *this; 702 - } 703 - 704 - Str& operator=(Str&& other) noexcept{ 705 - if(data!=nullptr) pool64.dealloc(data); 706 - size = other.size; 707 - is_ascii = other.is_ascii; 708 - data = other.data; 709 - other.data = nullptr; 710 - return *this; 711 - } 712 - 713 - ~Str(){ 714 - if(data!=nullptr) pool64.dealloc(data); 715 - } 716 - 717 - Str operator+(const Str& other) const { 718 - Str ret(size + other.size, is_ascii && other.is_ascii); 719 - memcpy(ret.data, data, size); 720 - memcpy(ret.data + size, other.data, other.size); 721 - return ret; 722 - } 723 - 724 - Str operator+(const char* p) const { 725 - Str other(p); 726 - return *this + other; 727 - } 728 - 729 - friend Str operator+(const char* p, const Str& str){ 730 - Str other(p); 731 - return other + str; 732 - } 733 - 734 - friend std::ostream& operator<<(std::ostream& os, const Str& str){ 735 - if(str.data!=nullptr) os.write(str.data, str.size); 736 - return os; 737 - } 738 - 739 - bool operator==(const Str& other) const { 740 - if(size != other.size) return false; 741 - return memcmp(data, other.data, size) == 0; 742 - } 743 - 744 - bool operator!=(const Str& other) const { 745 - if(size != other.size) return true; 746 - return memcmp(data, other.data, size) != 0; 747 - } 748 - 749 - bool operator<(const Str& other) const { 750 - int ret = strncmp(data, other.data, std::min(size, other.size)); 751 - if(ret != 0) return ret < 0; 752 - return size < other.size; 753 - } 754 - 755 - bool operator<(const std::string_view& other) const { 756 - int ret = strncmp(data, other.data(), std::min(size, (int)other.size())); 757 - if(ret != 0) return ret < 0; 758 - return size < (int)other.size(); 759 - } 760 - 761 - friend bool operator<(const std::string_view& other, const Str& str){ 762 - return str > other; 763 - } 764 - 765 - bool operator>(const Str& other) const { 766 - int ret = strncmp(data, other.data, std::min(size, other.size)); 767 - if(ret != 0) return ret > 0; 768 - return size > other.size; 769 - } 770 - 771 - bool operator<=(const Str& other) const { 772 - int ret = strncmp(data, other.data, std::min(size, other.size)); 773 - if(ret != 0) return ret < 0; 774 - return size <= other.size; 775 - } 776 - 777 - bool operator>=(const Str& other) const { 778 - int ret = strncmp(data, other.data, std::min(size, other.size)); 779 - if(ret != 0) return ret > 0; 780 - return size >= other.size; 781 - } 782 - 783 - Str substr(int start, int len) const { 784 - Str ret(len, is_ascii); 785 - memcpy(ret.data, data + start, len); 786 - return ret; 787 - } 788 - 789 - Str substr(int start) const { 790 - return substr(start, size - start); 791 - } 792 - 793 - char* c_str_dup() const { 794 - char* p = (char*)malloc(size + 1); 795 - memcpy(p, data, size); 796 - p[size] = 0; 797 - return p; 798 - } 799 - 800 - std::string_view sv() const { 801 - return std::string_view(data, size); 802 - } 803 - 804 - std::string str() const { 805 - return std::string(data, size); 806 - } 807 - 808 - Str lstrip() const { 809 - std::string copy(data, size); 810 - copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) { 811 - // std::isspace(c) does not working on windows (Debug) 812 - return c != ' ' && c != '\t' && c != '\r' && c != '\n'; 813 - })); 814 - return Str(copy); 815 - } 816 - 817 - Str escape(bool single_quote=true) const { 818 - std::stringstream ss; 819 - ss << (single_quote ? '\'' : '"'); 820 - for (int i=0; i<length(); i++) { 821 - char c = this->operator[](i); 822 - switch (c) { 823 - case '"': 824 - if(!single_quote) ss << '\\'; 825 - ss << '"'; 826 - break; 827 - case '\'': 828 - if(single_quote) ss << '\\'; 829 - ss << '\''; 830 - break; 831 - case '\\': ss << '\\' << '\\'; break; 832 - case '\n': ss << "\\n"; break; 833 - case '\r': ss << "\\r"; break; 834 - case '\t': ss << "\\t"; break; 835 - default: 836 - if ('\x00' <= c && c <= '\x1f') { 837 - ss << "\\x" << std::hex << std::setw(2) << std::setfill('0') << (int)c; 838 - } else { 839 - ss << c; 840 - } 841 - } 842 - } 843 - ss << (single_quote ? '\'' : '"'); 844 - return ss.str(); 845 - } 846 - 847 - int index(const Str& sub, int start=0) const { 848 - auto p = std::search(data + start, data + size, sub.data, sub.data + sub.size); 849 - if(p == data + size) return -1; 850 - return p - data; 851 - } 852 - 853 - Str replace(const Str& old, const Str& new_, int count=-1) const { 854 - std::stringstream ss; 855 - int start = 0; 856 - while(true){ 857 - int i = index(old, start); 858 - if(i == -1) break; 859 - ss << substr(start, i - start); 860 - ss << new_; 861 - start = i + old.size; 862 - if(count != -1 && --count == 0) break; 863 - } 864 - ss << substr(start, size - start); 865 - return ss.str(); 866 - } 867 - 868 - /*************unicode*************/ 869 - 870 - int _unicode_index_to_byte(int i) const{ 871 - if(is_ascii) return i; 872 - int j = 0; 873 - while(i > 0){ 874 - j += utf8len(data[j]); 875 - i--; 876 - } 877 - return j; 878 - } 879 - 880 - int _byte_index_to_unicode(int n) const{ 881 - if(is_ascii) return n; 882 - int cnt = 0; 883 - for(int i=0; i<n; i++){ 884 - if((data[i] & 0xC0) != 0x80) cnt++; 885 - } 886 - return cnt; 887 - } 888 - 889 - Str u8_getitem(int i) const{ 890 - i = _unicode_index_to_byte(i); 891 - return substr(i, utf8len(data[i])); 892 - } 893 - 894 - Str u8_slice(int start, int stop, int step) const{ 895 - std::stringstream ss; 896 - if(is_ascii){ 897 - for(int i=start; step>0?i<stop:i>stop; i+=step) ss << data[i]; 898 - }else{ 899 - for(int i=start; step>0?i<stop:i>stop; i+=step) ss << u8_getitem(i); 900 - } 901 - return ss.str(); 902 - } 903 - 904 - int u8_length() const { 905 - return _byte_index_to_unicode(size); 906 - } 907 - }; 908 - 909 - template<typename... Args> 910 - inline std::string fmt(Args&&... args) { 911 - std::stringstream ss; 912 - (ss << ... << args); 913 - return ss.str(); 914 - } 915 - 916 - const uint32_t kLoRangeA[] = {170,186,443,448,660,1488,1519,1568,1601,1646,1649,1749,1774,1786,1791,1808,1810,1869,1969,1994,2048,2112,2144,2208,2230,2308,2365,2384,2392,2418,2437,2447,2451,2474,2482,2486,2493,2510,2524,2527,2544,2556,2565,2575,2579,2602,2610,2613,2616,2649,2654,2674,2693,2703,2707,2730,2738,2741,2749,2768,2784,2809,2821,2831,2835,2858,2866,2869,2877,2908,2911,2929,2947,2949,2958,2962,2969,2972,2974,2979,2984,2990,3024,3077,3086,3090,3114,3133,3160,3168,3200,3205,3214,3218,3242,3253,3261,3294,3296,3313,3333,3342,3346,3389,3406,3412,3423,3450,3461,3482,3507,3517,3520,3585,3634,3648,3713,3716,3718,3724,3749,3751,3762,3773,3776,3804,3840,3904,3913,3976,4096,4159,4176,4186,4193,4197,4206,4213,4238,4352,4682,4688,4696,4698,4704,4746,4752,4786,4792,4800,4802,4808,4824,4882,4888,4992,5121,5743,5761,5792,5873,5888,5902,5920,5952,5984,5998,6016,6108,6176,6212,6272,6279,6314,6320,6400,6480,6512,6528,6576,6656,6688,6917,6981,7043,7086,7098,7168,7245,7258,7401,7406,7413,7418,8501,11568,11648,11680,11688,11696,11704,11712,11720,11728,11736,12294,12348,12353,12447,12449,12543,12549,12593,12704,12784,13312,19968,40960,40982,42192,42240,42512,42538,42606,42656,42895,42999,43003,43011,43015,43020,43072,43138,43250,43259,43261,43274,43312,43360,43396,43488,43495,43514,43520,43584,43588,43616,43633,43642,43646,43697,43701,43705,43712,43714,43739,43744,43762,43777,43785,43793,43808,43816,43968,44032,55216,55243,63744,64112,64285,64287,64298,64312,64318,64320,64323,64326,64467,64848,64914,65008,65136,65142,65382,65393,65440,65474,65482,65490,65498,65536,65549,65576,65596,65599,65616,65664,66176,66208,66304,66349,66370,66384,66432,66464,66504,66640,66816,66864,67072,67392,67424,67584,67592,67594,67639,67644,67647,67680,67712,67808,67828,67840,67872,67968,68030,68096,68112,68117,68121,68192,68224,68288,68297,68352,68416,68448,68480,68608,68864,69376,69415,69424,69600,69635,69763,69840,69891,69956,69968,70006,70019,70081,70106,70108,70144,70163,70272,70280,70282,70287,70303,70320,70405,70415,70419,70442,70450,70453,70461,70480,70493,70656,70727,70751,70784,70852,70855,71040,71128,71168,71236,71296,71352,71424,71680,71935,72096,72106,72161,72163,72192,72203,72250,72272,72284,72349,72384,72704,72714,72768,72818,72960,72968,72971,73030,73056,73063,73066,73112,73440,73728,74880,77824,82944,92160,92736,92880,92928,93027,93053,93952,94032,94208,100352,110592,110928,110948,110960,113664,113776,113792,113808,123136,123214,123584,124928,126464,126469,126497,126500,126503,126505,126516,126521,126523,126530,126535,126537,126539,126541,126545,126548,126551,126553,126555,126557,126559,126561,126564,126567,126572,126580,126585,126590,126592,126603,126625,126629,126635,131072,173824,177984,178208,183984,194560}; 917 - const uint32_t kLoRangeB[] = {170,186,443,451,660,1514,1522,1599,1610,1647,1747,1749,1775,1788,1791,1808,1839,1957,1969,2026,2069,2136,2154,2228,2237,2361,2365,2384,2401,2432,2444,2448,2472,2480,2482,2489,2493,2510,2525,2529,2545,2556,2570,2576,2600,2608,2611,2614,2617,2652,2654,2676,2701,2705,2728,2736,2739,2745,2749,2768,2785,2809,2828,2832,2856,2864,2867,2873,2877,2909,2913,2929,2947,2954,2960,2965,2970,2972,2975,2980,2986,3001,3024,3084,3088,3112,3129,3133,3162,3169,3200,3212,3216,3240,3251,3257,3261,3294,3297,3314,3340,3344,3386,3389,3406,3414,3425,3455,3478,3505,3515,3517,3526,3632,3635,3653,3714,3716,3722,3747,3749,3760,3763,3773,3780,3807,3840,3911,3948,3980,4138,4159,4181,4189,4193,4198,4208,4225,4238,4680,4685,4694,4696,4701,4744,4749,4784,4789,4798,4800,4805,4822,4880,4885,4954,5007,5740,5759,5786,5866,5880,5900,5905,5937,5969,5996,6000,6067,6108,6210,6264,6276,6312,6314,6389,6430,6509,6516,6571,6601,6678,6740,6963,6987,7072,7087,7141,7203,7247,7287,7404,7411,7414,7418,8504,11623,11670,11686,11694,11702,11710,11718,11726,11734,11742,12294,12348,12438,12447,12538,12543,12591,12686,12730,12799,19893,40943,40980,42124,42231,42507,42527,42539,42606,42725,42895,42999,43009,43013,43018,43042,43123,43187,43255,43259,43262,43301,43334,43388,43442,43492,43503,43518,43560,43586,43595,43631,43638,43642,43695,43697,43702,43709,43712,43714,43740,43754,43762,43782,43790,43798,43814,43822,44002,55203,55238,55291,64109,64217,64285,64296,64310,64316,64318,64321,64324,64433,64829,64911,64967,65019,65140,65276,65391,65437,65470,65479,65487,65495,65500,65547,65574,65594,65597,65613,65629,65786,66204,66256,66335,66368,66377,66421,66461,66499,66511,66717,66855,66915,67382,67413,67431,67589,67592,67637,67640,67644,67669,67702,67742,67826,67829,67861,67897,68023,68031,68096,68115,68119,68149,68220,68252,68295,68324,68405,68437,68466,68497,68680,68899,69404,69415,69445,69622,69687,69807,69864,69926,69956,70002,70006,70066,70084,70106,70108,70161,70187,70278,70280,70285,70301,70312,70366,70412,70416,70440,70448,70451,70457,70461,70480,70497,70708,70730,70751,70831,70853,70855,71086,71131,71215,71236,71338,71352,71450,71723,71935,72103,72144,72161,72163,72192,72242,72250,72272,72329,72349,72440,72712,72750,72768,72847,72966,72969,73008,73030,73061,73064,73097,73112,73458,74649,75075,78894,83526,92728,92766,92909,92975,93047,93071,94026,94032,100343,101106,110878,110930,110951,111355,113770,113788,113800,113817,123180,123214,123627,125124,126467,126495,126498,126500,126503,126514,126519,126521,126523,126530,126535,126537,126539,126543,126546,126548,126551,126553,126555,126557,126559,126562,126564,126570,126578,126583,126588,126590,126601,126619,126627,126633,126651,173782,177972,178205,183969,191456,195101}; 918 - 919 - inline bool is_unicode_Lo_char(uint32_t c) { 920 - auto index = std::lower_bound(kLoRangeA, kLoRangeA + 476, c) - kLoRangeA; 921 - if(c == kLoRangeA[index]) return true; 922 - index -= 1; 923 - if(index < 0) return false; 924 - return c >= kLoRangeA[index] && c <= kLoRangeB[index]; 925 - } 926 - 927 - 928 - struct StrName { 929 - uint16_t index; 930 - StrName(): index(0) {} 931 - StrName(uint16_t index): index(index) {} 932 - StrName(const char* s): index(get(s).index) {} 933 - StrName(const Str& s){ 934 - index = get(s.sv()).index; 935 - } 936 - std::string_view sv() const { return _r_interned[index-1].sv(); } 937 - bool empty() const { return index == 0; } 938 - 939 - friend std::ostream& operator<<(std::ostream& os, const StrName& sn){ 940 - return os << sn.sv(); 941 - } 942 - 943 - Str escape() const { 944 - return _r_interned[index-1].escape(); 945 - } 946 - 947 - bool operator==(const StrName& other) const noexcept { 948 - return this->index == other.index; 949 - } 950 - 951 - bool operator!=(const StrName& other) const noexcept { 952 - return this->index != other.index; 953 - } 954 - 955 - bool operator<(const StrName& other) const noexcept { 956 - return this->index < other.index; 957 - } 958 - 959 - bool operator>(const StrName& other) const noexcept { 960 - return this->index > other.index; 961 - } 962 - 963 - static std::map<Str, uint16_t, std::less<>> _interned; 964 - static std::vector<Str> _r_interned; 965 - 966 - static StrName get(std::string_view s){ 967 - auto it = _interned.find(s); 968 - if(it != _interned.end()) return StrName(it->second); 969 - uint16_t index = (uint16_t)(_r_interned.size() + 1); 970 - _interned[s] = index; 971 - _r_interned.push_back(s); 972 - return StrName(index); 973 - } 974 - }; 975 - 976 - struct FastStrStream{ 977 - pod_vector<const Str*> parts; 978 - 979 - FastStrStream& operator<<(const Str& s){ 980 - parts.push_back(&s); 981 - return *this; 982 - } 983 - 984 - Str str() const{ 985 - int len = 0; 986 - bool is_ascii = true; 987 - for(auto& s: parts){ 988 - len += s->length(); 989 - is_ascii &= s->is_ascii; 990 - } 991 - Str result(len, is_ascii); 992 - char* p = result.data; 993 - for(auto& s: parts){ 994 - memcpy(p, s->data, s->length()); 995 - p += s->length(); 996 - } 997 - return result; 998 - } 999 - }; 1000 - 1001 - inline std::map<Str, uint16_t, std::less<>> StrName::_interned; 1002 - inline std::vector<Str> StrName::_r_interned; 1003 - 1004 - const StrName __class__ = StrName::get("__class__"); 1005 - const StrName __base__ = StrName::get("__base__"); 1006 - const StrName __new__ = StrName::get("__new__"); 1007 - const StrName __iter__ = StrName::get("__iter__"); 1008 - const StrName __next__ = StrName::get("__next__"); 1009 - const StrName __str__ = StrName::get("__str__"); 1010 - const StrName __repr__ = StrName::get("__repr__"); 1011 - const StrName __getitem__ = StrName::get("__getitem__"); 1012 - const StrName __setitem__ = StrName::get("__setitem__"); 1013 - const StrName __delitem__ = StrName::get("__delitem__"); 1014 - const StrName __contains__ = StrName::get("__contains__"); 1015 - const StrName __init__ = StrName::get("__init__"); 1016 - const StrName __json__ = StrName::get("__json__"); 1017 - const StrName __name__ = StrName::get("__name__"); 1018 - const StrName __len__ = StrName::get("__len__"); 1019 - const StrName __get__ = StrName::get("__get__"); 1020 - const StrName __set__ = StrName::get("__set__"); 1021 - const StrName __getattr__ = StrName::get("__getattr__"); 1022 - const StrName __setattr__ = StrName::get("__setattr__"); 1023 - const StrName __call__ = StrName::get("__call__"); 1024 - const StrName __doc__ = StrName::get("__doc__"); 1025 - 1026 - const StrName m_self = StrName::get("self"); 1027 - const StrName m_dict = StrName::get("dict"); 1028 - const StrName m_set = StrName::get("set"); 1029 - const StrName m_add = StrName::get("add"); 1030 - const StrName __enter__ = StrName::get("__enter__"); 1031 - const StrName __exit__ = StrName::get("__exit__"); 1032 - 1033 - const StrName __add__ = StrName::get("__add__"); 1034 - const StrName __sub__ = StrName::get("__sub__"); 1035 - const StrName __mul__ = StrName::get("__mul__"); 1036 - // const StrName __truediv__ = StrName::get("__truediv__"); 1037 - const StrName __floordiv__ = StrName::get("__floordiv__"); 1038 - const StrName __mod__ = StrName::get("__mod__"); 1039 - // const StrName __pow__ = StrName::get("__pow__"); 1040 - 1041 - const StrName BINARY_SPECIAL_METHODS[] = { 1042 - StrName::get("__add__"), StrName::get("__sub__"), StrName::get("__mul__"), 1043 - StrName::get("__truediv__"), StrName::get("__floordiv__"), 1044 - StrName::get("__mod__"), StrName::get("__pow__") 1045 - }; 1046 - 1047 - const StrName __lt__ = StrName::get("__lt__"); 1048 - const StrName __le__ = StrName::get("__le__"); 1049 - const StrName __eq__ = StrName::get("__eq__"); 1050 - const StrName __ne__ = StrName::get("__ne__"); 1051 - const StrName __gt__ = StrName::get("__gt__"); 1052 - const StrName __ge__ = StrName::get("__ge__"); 1053 - 1054 - const StrName __lshift__ = StrName::get("__lshift__"); 1055 - const StrName __rshift__ = StrName::get("__rshift__"); 1056 - const StrName __and__ = StrName::get("__and__"); 1057 - const StrName __or__ = StrName::get("__or__"); 1058 - const StrName __xor__ = StrName::get("__xor__"); 1059 - 1060 - } // namespace pkpy 1061 - 1062 - 1063 - namespace pkpy { 1064 - 1065 - using List = pod_vector<PyObject*>; 1066 - 1067 - class Tuple { 1068 - PyObject** _args; 1069 - int _size; 1070 - 1071 - void _alloc(int n){ 1072 - this->_args = (n==0) ? nullptr : (PyObject**)pool64.alloc(n * sizeof(void*)); 1073 - this->_size = n; 1074 - } 1075 - 1076 - public: 1077 - Tuple(int n){ _alloc(n); } 1078 - 1079 - Tuple(const Tuple& other){ 1080 - _alloc(other._size); 1081 - for(int i=0; i<_size; i++) _args[i] = other._args[i]; 1082 - } 1083 - 1084 - Tuple(Tuple&& other) noexcept { 1085 - this->_args = other._args; 1086 - this->_size = other._size; 1087 - other._args = nullptr; 1088 - other._size = 0; 1089 - } 1090 - 1091 - Tuple(std::initializer_list<PyObject*> list) : Tuple(list.size()){ 1092 - int i = 0; 1093 - for(PyObject* p : list) _args[i++] = p; 1094 - } 1095 - 1096 - // TODO: poor performance 1097 - // List is allocated by pool128 while tuple is by pool64 1098 - // ... 1099 - Tuple(List&& other) noexcept : Tuple(other.size()){ 1100 - for(int i=0; i<_size; i++) _args[i] = other[i]; 1101 - other.clear(); 1102 - } 1103 - 1104 - PyObject*& operator[](int i){ return _args[i]; } 1105 - PyObject* operator[](int i) const { return _args[i]; } 1106 - 1107 - Tuple& operator=(Tuple&& other) noexcept { 1108 - if(_args!=nullptr) pool64.dealloc(_args); 1109 - this->_args = other._args; 1110 - this->_size = other._size; 1111 - other._args = nullptr; 1112 - other._size = 0; 1113 - return *this; 1114 - } 1115 - 1116 - int size() const { return _size; } 1117 - 1118 - PyObject** begin() const { return _args; } 1119 - PyObject** end() const { return _args + _size; } 1120 - 1121 - ~Tuple(){ if(_args!=nullptr) pool64.dealloc(_args); } 1122 - }; 1123 - 1124 - // a lightweight view for function args, it does not own the memory 1125 - struct ArgsView{ 1126 - PyObject** _begin; 1127 - PyObject** _end; 1128 - 1129 - ArgsView(PyObject** begin, PyObject** end) : _begin(begin), _end(end) {} 1130 - ArgsView(const Tuple& t) : _begin(t.begin()), _end(t.end()) {} 1131 - ArgsView(): _begin(nullptr), _end(nullptr) {} 1132 - 1133 - PyObject** begin() const { return _begin; } 1134 - PyObject** end() const { return _end; } 1135 - int size() const { return _end - _begin; } 1136 - bool empty() const { return _begin == _end; } 1137 - PyObject* operator[](int i) const { return _begin[i]; } 1138 - 1139 - List to_list() const{ 1140 - List ret(size()); 1141 - for(int i=0; i<size(); i++) ret[i] = _begin[i]; 1142 - return ret; 1143 - } 1144 - 1145 - Tuple to_tuple() const{ 1146 - Tuple ret(size()); 1147 - for(int i=0; i<size(); i++) ret[i] = _begin[i]; 1148 - return ret; 1149 - } 1150 - }; 1151 - } // namespace pkpy 1152 - 1153 - 1154 - namespace pkpy{ 1155 - 1156 - const std::vector<uint16_t> kHashSeeds = {9629, 43049, 13267, 59509, 39251, 1249, 35803, 54469, 27689, 9719, 34897, 18973, 30661, 19913, 27919, 32143}; 1157 - 1158 - inline uint16_t find_next_power_of_2(uint16_t n){ 1159 - uint16_t x = 2; 1160 - while(x < n) x <<= 1; 1161 - return x; 1162 - } 1163 - 1164 - #define _hash(key, mask, hash_seed) ( ( (key).index * (hash_seed) >> 8 ) & (mask) ) 1165 - 1166 - inline uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vector<StrName>& keys){ 1167 - if(keys.empty()) return kHashSeeds[0]; 1168 - static std::set<uint16_t> indices; 1169 - indices.clear(); 1170 - std::pair<uint16_t, float> best_score = {kHashSeeds[0], 0.0f}; 1171 - for(int i=0; i<kHashSeeds.size(); i++){ 1172 - indices.clear(); 1173 - for(auto key: keys){ 1174 - uint16_t index = _hash(key, capacity-1, kHashSeeds[i]); 1175 - indices.insert(index); 1176 - } 1177 - float score = indices.size() / (float)keys.size(); 1178 - if(score > best_score.second) best_score = {kHashSeeds[i], score}; 1179 - } 1180 - return best_score.first; 1181 - } 1182 - 1183 - template<typename T> 1184 - struct NameDictImpl { 1185 - using Item = std::pair<StrName, T>; 1186 - static constexpr uint16_t __Capacity = 8; 1187 - // ensure the initial capacity is ok for memory pool 1188 - static_assert(std::is_pod_v<T>); 1189 - static_assert(sizeof(Item) * __Capacity <= 128); 1190 - 1191 - float _load_factor; 1192 - uint16_t _capacity; 1193 - uint16_t _size; 1194 - uint16_t _hash_seed; 1195 - uint16_t _mask; 1196 - Item* _items; 1197 - 1198 - void _alloc(int cap){ 1199 - _items = (Item*)pool128.alloc(cap * sizeof(Item)); 1200 - memset(_items, 0, cap * sizeof(Item)); 1201 - } 1202 - 1203 - NameDictImpl(float load_factor=0.67, uint16_t capacity=__Capacity, uint16_t hash_seed=kHashSeeds[0]): 1204 - _load_factor(load_factor), _capacity(capacity), _size(0), 1205 - _hash_seed(hash_seed), _mask(capacity-1) { 1206 - _alloc(capacity); 1207 - } 1208 - 1209 - NameDictImpl(const NameDictImpl& other) { 1210 - memcpy(this, &other, sizeof(NameDictImpl)); 1211 - _alloc(_capacity); 1212 - for(int i=0; i<_capacity; i++){ 1213 - _items[i] = other._items[i]; 1214 - } 1215 - } 1216 - 1217 - NameDictImpl& operator=(const NameDictImpl& other) { 1218 - pool128.dealloc(_items); 1219 - memcpy(this, &other, sizeof(NameDictImpl)); 1220 - _alloc(_capacity); 1221 - for(int i=0; i<_capacity; i++){ 1222 - _items[i] = other._items[i]; 1223 - } 1224 - return *this; 1225 - } 1226 - 1227 - ~NameDictImpl(){ pool128.dealloc(_items); } 1228 - 1229 - NameDictImpl(NameDictImpl&&) = delete; 1230 - NameDictImpl& operator=(NameDictImpl&&) = delete; 1231 - uint16_t size() const { return _size; } 1232 - 1233 - #define HASH_PROBE(key, ok, i) \ 1234 - ok = false; \ 1235 - i = _hash(key, _mask, _hash_seed); \ 1236 - while(!_items[i].first.empty()) { \ 1237 - if(_items[i].first == (key)) { ok = true; break; } \ 1238 - i = (i + 1) & _mask; \ 1239 - } 1240 - 1241 - T operator[](StrName key) const { 1242 - bool ok; uint16_t i; 1243 - HASH_PROBE(key, ok, i); 1244 - if(!ok) throw std::out_of_range(fmt("NameDict key not found: ", key)); 1245 - return _items[i].second; 1246 - } 1247 - 1248 - void set(StrName key, T val){ 1249 - bool ok; uint16_t i; 1250 - HASH_PROBE(key, ok, i); 1251 - if(!ok) { 1252 - _size++; 1253 - if(_size > _capacity*_load_factor){ 1254 - _rehash(true); 1255 - HASH_PROBE(key, ok, i); 1256 - } 1257 - _items[i].first = key; 1258 - } 1259 - _items[i].second = val; 1260 - } 1261 - 1262 - void _rehash(bool resize){ 1263 - Item* old_items = _items; 1264 - uint16_t old_capacity = _capacity; 1265 - if(resize){ 1266 - _capacity = find_next_power_of_2(_capacity * 2); 1267 - _mask = _capacity - 1; 1268 - } 1269 - _alloc(_capacity); 1270 - for(uint16_t i=0; i<old_capacity; i++){ 1271 - if(old_items[i].first.empty()) continue; 1272 - bool ok; uint16_t j; 1273 - HASH_PROBE(old_items[i].first, ok, j); 1274 - if(ok) FATAL_ERROR(); 1275 - _items[j] = old_items[i]; 1276 - } 1277 - pool128.dealloc(old_items); 1278 - } 1279 - 1280 - void _try_perfect_rehash(){ 1281 - _hash_seed = find_perfect_hash_seed(_capacity, keys()); 1282 - _rehash(false); // do not resize 1283 - } 1284 - 1285 - T try_get(StrName key) const{ 1286 - bool ok; uint16_t i; 1287 - HASH_PROBE(key, ok, i); 1288 - if(!ok){ 1289 - if constexpr(std::is_pointer_v<T>) return nullptr; 1290 - else if constexpr(std::is_same_v<int, T>) return -1; 1291 - else return Discarded(); 1292 - } 1293 - return _items[i].second; 1294 - } 1295 - 1296 - bool try_set(StrName key, T val){ 1297 - bool ok; uint16_t i; 1298 - HASH_PROBE(key, ok, i); 1299 - if(!ok) return false; 1300 - _items[i].second = val; 1301 - return true; 1302 - } 1303 - 1304 - bool contains(StrName key) const { 1305 - bool ok; uint16_t i; 1306 - HASH_PROBE(key, ok, i); 1307 - return ok; 1308 - } 1309 - 1310 - void update(const NameDictImpl& other){ 1311 - for(uint16_t i=0; i<other._capacity; i++){ 1312 - auto& item = other._items[i]; 1313 - if(!item.first.empty()) set(item.first, item.second); 1314 - } 1315 - } 1316 - 1317 - void erase(StrName key){ 1318 - bool ok; uint16_t i; 1319 - HASH_PROBE(key, ok, i); 1320 - if(!ok) throw std::out_of_range(fmt("NameDict key not found: ", key)); 1321 - _items[i].first = StrName(); 1322 - _items[i].second = nullptr; 1323 - _size--; 1324 - } 1325 - 1326 - std::vector<Item> items() const { 1327 - std::vector<Item> v; 1328 - for(uint16_t i=0; i<_capacity; i++){ 1329 - if(_items[i].first.empty()) continue; 1330 - v.push_back(_items[i]); 1331 - } 1332 - return v; 1333 - } 1334 - 1335 - std::vector<StrName> keys() const { 1336 - std::vector<StrName> v; 1337 - for(uint16_t i=0; i<_capacity; i++){ 1338 - if(_items[i].first.empty()) continue; 1339 - v.push_back(_items[i].first); 1340 - } 1341 - return v; 1342 - } 1343 - 1344 - void clear(){ 1345 - for(uint16_t i=0; i<_capacity; i++){ 1346 - _items[i].first = StrName(); 1347 - _items[i].second = nullptr; 1348 - } 1349 - _size = 0; 1350 - } 1351 - #undef HASH_PROBE 1352 - #undef _hash 1353 - }; 1354 - 1355 - using NameDict = NameDictImpl<PyObject*>; 1356 - using NameDict_ = shared_ptr<NameDict>; 1357 - using NameDictInt = NameDictImpl<int>; 1358 - 1359 - } // namespace pkpy 1360 - 1361 - 1362 - namespace pkpy{ 1363 - 1364 - struct NeedMoreLines { 1365 - NeedMoreLines(bool is_compiling_class) : is_compiling_class(is_compiling_class) {} 1366 - bool is_compiling_class; 1367 - }; 1368 - 1369 - struct HandledException {}; 1370 - struct UnhandledException {}; 1371 - struct ToBeRaisedException {}; 1372 - 1373 - enum CompileMode { 1374 - EXEC_MODE, 1375 - EVAL_MODE, 1376 - REPL_MODE, 1377 - JSON_MODE, 1378 - }; 1379 - 1380 - struct SourceData { 1381 - std::string source; 1382 - Str filename; 1383 - std::vector<const char*> line_starts; 1384 - CompileMode mode; 1385 - 1386 - std::pair<const char*,const char*> get_line(int lineno) const { 1387 - if(lineno == -1) return {nullptr, nullptr}; 1388 - lineno -= 1; 1389 - if(lineno < 0) lineno = 0; 1390 - const char* _start = line_starts.at(lineno); 1391 - const char* i = _start; 1392 - while(*i != '\n' && *i != '\0') i++; 1393 - return {_start, i}; 1394 - } 1395 - 1396 - SourceData(const Str& source, const Str& filename, CompileMode mode) { 1397 - int index = 0; 1398 - // Skip utf8 BOM if there is any. 1399 - if (strncmp(source.begin(), "\xEF\xBB\xBF", 3) == 0) index += 3; 1400 - // Remove all '\r' 1401 - std::stringstream ss; 1402 - while(index < source.length()){ 1403 - if(source[index] != '\r') ss << source[index]; 1404 - index++; 1405 - } 1406 - 1407 - this->filename = filename; 1408 - this->source = ss.str(); 1409 - line_starts.push_back(this->source.c_str()); 1410 - this->mode = mode; 1411 - } 1412 - 1413 - Str snapshot(int lineno, const char* cursor=nullptr){ 1414 - std::stringstream ss; 1415 - ss << " " << "File \"" << filename << "\", line " << lineno << '\n'; 1416 - std::pair<const char*,const char*> pair = get_line(lineno); 1417 - Str line = "<?>"; 1418 - int removed_spaces = 0; 1419 - if(pair.first && pair.second){ 1420 - line = Str(pair.first, pair.second-pair.first).lstrip(); 1421 - removed_spaces = pair.second - pair.first - line.length(); 1422 - if(line.empty()) line = "<?>"; 1423 - } 1424 - ss << " " << line; 1425 - if(cursor && line != "<?>" && cursor >= pair.first && cursor <= pair.second){ 1426 - auto column = cursor - pair.first - removed_spaces; 1427 - if(column >= 0) ss << "\n " << std::string(column, ' ') << "^"; 1428 - } 1429 - return ss.str(); 1430 - } 1431 - }; 1432 - 1433 - class Exception { 1434 - using StackTrace = stack<Str>; 1435 - StrName type; 1436 - Str msg; 1437 - StackTrace stacktrace; 1438 - public: 1439 - Exception(StrName type, Str msg): type(type), msg(msg) {} 1440 - bool match_type(StrName type) const { return this->type == type;} 1441 - bool is_re = true; 1442 - 1443 - void st_push(Str snapshot){ 1444 - if(stacktrace.size() >= 8) return; 1445 - stacktrace.push(snapshot); 1446 - } 1447 - 1448 - Str summary() const { 1449 - StackTrace st(stacktrace); 1450 - std::stringstream ss; 1451 - if(is_re) ss << "Traceback (most recent call last):\n"; 1452 - while(!st.empty()) { ss << st.top() << '\n'; st.pop(); } 1453 - if (!msg.empty()) ss << type.sv() << ": " << msg; 1454 - else ss << type.sv(); 1455 - return ss.str(); 1456 - } 1457 - }; 1458 - 1459 - } // namespace pkpy 1460 - 1461 - 1462 - namespace pkpy{ 1463 - 1464 - typedef uint8_t TokenIndex; 1465 - 1466 - constexpr const char* kTokens[] = { 1467 - "is not", "not in", "yield from", 1468 - "@eof", "@eol", "@sof", 1469 - "@id", "@num", "@str", "@fstr", 1470 - "@indent", "@dedent", 1471 - /*****************************************/ 1472 - "+", "+=", "-", "-=", // (INPLACE_OP - 1) can get '=' removed 1473 - "*", "*=", "/", "/=", "//", "//=", "%", "%=", 1474 - "&", "&=", "|", "|=", "^", "^=", 1475 - "<<", "<<=", ">>", ">>=", 1476 - /*****************************************/ 1477 - ".", ",", ":", ";", "#", "(", ")", "[", "]", "{", "}", 1478 - "**", "=", ">", "<", "...", "->", "?", "@", "==", "!=", ">=", "<=", 1479 - /** SPEC_BEGIN **/ 1480 - "$goto", "$label", 1481 - /** KW_BEGIN **/ 1482 - "class", "import", "as", "def", "lambda", "pass", "del", "from", "with", "yield", 1483 - "None", "in", "is", "and", "or", "not", "True", "False", "global", "try", "except", "finally", 1484 - "while", "for", "if", "elif", "else", "break", "continue", "return", "assert", "raise" 1485 - }; 1486 - 1487 - using TokenValue = std::variant<std::monostate, i64, f64, Str>; 1488 - const TokenIndex kTokenCount = sizeof(kTokens) / sizeof(kTokens[0]); 1489 - 1490 - constexpr TokenIndex TK(const char token[]) { 1491 - for(int k=0; k<kTokenCount; k++){ 1492 - const char* i = kTokens[k]; 1493 - const char* j = token; 1494 - while(*i && *j && *i == *j) { i++; j++;} 1495 - if(*i == *j) return k; 1496 - } 1497 - return 255; 1498 - } 1499 - 1500 - #define TK_STR(t) kTokens[t] 1501 - const std::map<std::string_view, TokenIndex> kTokenKwMap = [](){ 1502 - std::map<std::string_view, TokenIndex> map; 1503 - for(int k=TK("class"); k<kTokenCount; k++) map[kTokens[k]] = k; 1504 - return map; 1505 - }(); 1506 - 1507 - 1508 - struct Token{ 1509 - TokenIndex type; 1510 - const char* start; 1511 - int length; 1512 - int line; 1513 - TokenValue value; 1514 - 1515 - Str str() const { return Str(start, length);} 1516 - std::string_view sv() const { return std::string_view(start, length);} 1517 - 1518 - std::string info() const { 1519 - std::stringstream ss; 1520 - ss << line << ": " << TK_STR(type) << " '" << ( 1521 - sv()=="\n" ? "\\n" : sv() 1522 - ) << "'"; 1523 - return ss.str(); 1524 - } 1525 - }; 1526 - 1527 - // https://docs.python.org/3/reference/expressions.html#operator-precedence 1528 - enum Precedence { 1529 - PREC_NONE, 1530 - PREC_TUPLE, // , 1531 - PREC_LAMBDA, // lambda 1532 - PREC_TERNARY, // ?: 1533 - PREC_LOGICAL_OR, // or 1534 - PREC_LOGICAL_AND, // and 1535 - PREC_LOGICAL_NOT, // not 1536 - PREC_EQUALITY, // == != 1537 - PREC_TEST, // in / is / is not / not in 1538 - PREC_COMPARISION, // < > <= >= 1539 - PREC_BITWISE_OR, // | 1540 - PREC_BITWISE_XOR, // ^ 1541 - PREC_BITWISE_AND, // & 1542 - PREC_BITWISE_SHIFT, // << >> 1543 - PREC_TERM, // + - 1544 - PREC_FACTOR, // * / % // 1545 - PREC_UNARY, // - not 1546 - PREC_EXPONENT, // ** 1547 - PREC_CALL, // () 1548 - PREC_SUBSCRIPT, // [] 1549 - PREC_ATTRIB, // .index 1550 - PREC_PRIMARY, 1551 - }; 1552 - 1553 - enum StringType { NORMAL_STRING, RAW_STRING, F_STRING }; 1554 - 1555 - struct Lexer { 1556 - shared_ptr<SourceData> src; 1557 - const char* token_start; 1558 - const char* curr_char; 1559 - int current_line = 1; 1560 - std::vector<Token> nexts; 1561 - stack<int> indents; 1562 - int brackets_level = 0; 1563 - bool used = false; 1564 - 1565 - char peekchar() const{ return *curr_char; } 1566 - 1567 - bool match_n_chars(int n, char c0){ 1568 - const char* c = curr_char; 1569 - for(int i=0; i<n; i++){ 1570 - if(*c == '\0') return false; 1571 - if(*c != c0) return false; 1572 - c++; 1573 - } 1574 - for(int i=0; i<n; i++) eatchar_include_newline(); 1575 - return true; 1576 - } 1577 - 1578 - bool match_string(const char* s){ 1579 - int s_len = strlen(s); 1580 - bool ok = strncmp(curr_char, s, s_len) == 0; 1581 - if(ok) for(int i=0; i<s_len; i++) eatchar_include_newline(); 1582 - return ok; 1583 - } 1584 - 1585 - int eat_spaces(){ 1586 - int count = 0; 1587 - while (true) { 1588 - switch (peekchar()) { 1589 - case ' ' : count+=1; break; 1590 - case '\t': count+=4; break; 1591 - default: return count; 1592 - } 1593 - eatchar(); 1594 - } 1595 - } 1596 - 1597 - bool eat_indentation(){ 1598 - if(brackets_level > 0) return true; 1599 - int spaces = eat_spaces(); 1600 - if(peekchar() == '#') skip_line_comment(); 1601 - if(peekchar() == '\0' || peekchar() == '\n') return true; 1602 - // https://docs.python.org/3/reference/lexical_analysis.html#indentation 1603 - if(spaces > indents.top()){ 1604 - indents.push(spaces); 1605 - nexts.push_back(Token{TK("@indent"), token_start, 0, current_line}); 1606 - } else if(spaces < indents.top()){ 1607 - while(spaces < indents.top()){ 1608 - indents.pop(); 1609 - nexts.push_back(Token{TK("@dedent"), token_start, 0, current_line}); 1610 - } 1611 - if(spaces != indents.top()){ 1612 - return false; 1613 - } 1614 - } 1615 - return true; 1616 - } 1617 - 1618 - char eatchar() { 1619 - char c = peekchar(); 1620 - if(c == '\n') throw std::runtime_error("eatchar() cannot consume a newline"); 1621 - curr_char++; 1622 - return c; 1623 - } 1624 - 1625 - char eatchar_include_newline() { 1626 - char c = peekchar(); 1627 - curr_char++; 1628 - if (c == '\n'){ 1629 - current_line++; 1630 - src->line_starts.push_back(curr_char); 1631 - } 1632 - return c; 1633 - } 1634 - 1635 - int eat_name() { 1636 - curr_char--; 1637 - while(true){ 1638 - unsigned char c = peekchar(); 1639 - int u8bytes = utf8len(c, true); 1640 - if(u8bytes == 0) return 1; 1641 - if(u8bytes == 1){ 1642 - if(isalpha(c) || c=='_' || isdigit(c)) { 1643 - curr_char++; 1644 - continue; 1645 - }else{ 1646 - break; 1647 - } 1648 - } 1649 - // handle multibyte char 1650 - std::string u8str(curr_char, u8bytes); 1651 - if(u8str.size() != u8bytes) return 2; 1652 - uint32_t value = 0; 1653 - for(int k=0; k < u8bytes; k++){ 1654 - uint8_t b = u8str[k]; 1655 - if(k==0){ 1656 - if(u8bytes == 2) value = (b & 0b00011111) << 6; 1657 - else if(u8bytes == 3) value = (b & 0b00001111) << 12; 1658 - else if(u8bytes == 4) value = (b & 0b00000111) << 18; 1659 - }else{ 1660 - value |= (b & 0b00111111) << (6*(u8bytes-k-1)); 1661 - } 1662 - } 1663 - if(is_unicode_Lo_char(value)) curr_char += u8bytes; 1664 - else break; 1665 - } 1666 - 1667 - int length = (int)(curr_char - token_start); 1668 - if(length == 0) return 3; 1669 - std::string_view name(token_start, length); 1670 - 1671 - if(src->mode == JSON_MODE){ 1672 - if(name == "true"){ 1673 - add_token(TK("True")); 1674 - } else if(name == "false"){ 1675 - add_token(TK("False")); 1676 - } else if(name == "null"){ 1677 - add_token(TK("None")); 1678 - } else { 1679 - return 4; 1680 - } 1681 - return 0; 1682 - } 1683 - 1684 - if(kTokenKwMap.count(name)){ 1685 - if(name == "not"){ 1686 - if(strncmp(curr_char, " in", 3) == 0){ 1687 - curr_char += 3; 1688 - add_token(TK("not in")); 1689 - return 0; 1690 - } 1691 - }else if(name == "is"){ 1692 - if(strncmp(curr_char, " not", 4) == 0){ 1693 - curr_char += 4; 1694 - add_token(TK("is not")); 1695 - return 0; 1696 - } 1697 - }else if(name == "yield"){ 1698 - if(strncmp(curr_char, " from", 5) == 0){ 1699 - curr_char += 5; 1700 - add_token(TK("yield from")); 1701 - return 0; 1702 - } 1703 - } 1704 - add_token(kTokenKwMap.at(name)); 1705 - } else { 1706 - add_token(TK("@id")); 1707 - } 1708 - return 0; 1709 - } 1710 - 1711 - void skip_line_comment() { 1712 - char c; 1713 - while ((c = peekchar()) != '\0') { 1714 - if (c == '\n') return; 1715 - eatchar(); 1716 - } 1717 - } 1718 - 1719 - bool matchchar(char c) { 1720 - if (peekchar() != c) return false; 1721 - eatchar_include_newline(); 1722 - return true; 1723 - } 1724 - 1725 - void add_token(TokenIndex type, TokenValue value={}) { 1726 - switch(type){ 1727 - case TK("{"): case TK("["): case TK("("): brackets_level++; break; 1728 - case TK(")"): case TK("]"): case TK("}"): brackets_level--; break; 1729 - } 1730 - nexts.push_back( Token{ 1731 - type, 1732 - token_start, 1733 - (int)(curr_char - token_start), 1734 - current_line - ((type == TK("@eol")) ? 1 : 0), 1735 - value 1736 - }); 1737 - } 1738 - 1739 - void add_token_2(char c, TokenIndex one, TokenIndex two) { 1740 - if (matchchar(c)) add_token(two); 1741 - else add_token(one); 1742 - } 1743 - 1744 - Str eat_string_until(char quote, bool raw) { 1745 - bool quote3 = match_n_chars(2, quote); 1746 - std::vector<char> buff; 1747 - while (true) { 1748 - char c = eatchar_include_newline(); 1749 - if (c == quote){ 1750 - if(quote3 && !match_n_chars(2, quote)){ 1751 - buff.push_back(c); 1752 - continue; 1753 - } 1754 - break; 1755 - } 1756 - if (c == '\0'){ 1757 - if(quote3 && src->mode == REPL_MODE){ 1758 - throw NeedMoreLines(false); 1759 - } 1760 - SyntaxError("EOL while scanning string literal"); 1761 - } 1762 - if (c == '\n'){ 1763 - if(!quote3) SyntaxError("EOL while scanning string literal"); 1764 - else{ 1765 - buff.push_back(c); 1766 - continue; 1767 - } 1768 - } 1769 - if (!raw && c == '\\') { 1770 - switch (eatchar_include_newline()) { 1771 - case '"': buff.push_back('"'); break; 1772 - case '\'': buff.push_back('\''); break; 1773 - case '\\': buff.push_back('\\'); break; 1774 - case 'n': buff.push_back('\n'); break; 1775 - case 'r': buff.push_back('\r'); break; 1776 - case 't': buff.push_back('\t'); break; 1777 - default: SyntaxError("invalid escape char"); 1778 - } 1779 - } else { 1780 - buff.push_back(c); 1781 - } 1782 - } 1783 - return Str(buff.data(), buff.size()); 1784 - } 1785 - 1786 - void eat_string(char quote, StringType type) { 1787 - Str s = eat_string_until(quote, type == RAW_STRING); 1788 - if(type == F_STRING){ 1789 - add_token(TK("@fstr"), s); 1790 - }else{ 1791 - add_token(TK("@str"), s); 1792 - } 1793 - } 1794 - 1795 - void eat_number() { 1796 - static const std::regex pattern("^(0x)?[0-9a-fA-F]+(\\.[0-9]+)?"); 1797 - std::smatch m; 1798 - 1799 - const char* i = token_start; 1800 - while(*i != '\n' && *i != '\0') i++; 1801 - std::string s = std::string(token_start, i); 1802 - 1803 - try{ 1804 - if (std::regex_search(s, m, pattern)) { 1805 - // here is m.length()-1, since the first char was eaten by lex_token() 1806 - for(int j=0; j<m.length()-1; j++) eatchar(); 1807 - 1808 - int base = 10; 1809 - size_t size; 1810 - if (m[1].matched) base = 16; 1811 - if (m[2].matched) { 1812 - if(base == 16) SyntaxError("hex literal should not contain a dot"); 1813 - add_token(TK("@num"), Number::stof(m[0], &size)); 1814 - } else { 1815 - add_token(TK("@num"), Number::stoi(m[0], &size, base)); 1816 - } 1817 - if (size != m.length()) FATAL_ERROR(); 1818 - } 1819 - }catch(std::exception& _){ 1820 - SyntaxError("invalid number literal"); 1821 - } 1822 - } 1823 - 1824 - bool lex_one_token() { 1825 - while (peekchar() != '\0') { 1826 - token_start = curr_char; 1827 - char c = eatchar_include_newline(); 1828 - switch (c) { 1829 - case '\'': case '"': eat_string(c, NORMAL_STRING); return true; 1830 - case '#': skip_line_comment(); break; 1831 - case '{': add_token(TK("{")); return true; 1832 - case '}': add_token(TK("}")); return true; 1833 - case ',': add_token(TK(",")); return true; 1834 - case ':': add_token(TK(":")); return true; 1835 - case ';': add_token(TK(";")); return true; 1836 - case '(': add_token(TK("(")); return true; 1837 - case ')': add_token(TK(")")); return true; 1838 - case '[': add_token(TK("[")); return true; 1839 - case ']': add_token(TK("]")); return true; 1840 - case '@': add_token(TK("@")); return true; 1841 - case '$': { 1842 - for(int i=TK("$goto"); i<=TK("$label"); i++){ 1843 - // +1 to skip the '$' 1844 - if(match_string(TK_STR(i) + 1)){ 1845 - add_token((TokenIndex)i); 1846 - return true; 1847 - } 1848 - } 1849 - SyntaxError("invalid special token"); 1850 - } 1851 - case '%': add_token_2('=', TK("%"), TK("%=")); return true; 1852 - case '&': add_token_2('=', TK("&"), TK("&=")); return true; 1853 - case '|': add_token_2('=', TK("|"), TK("|=")); return true; 1854 - case '^': add_token_2('=', TK("^"), TK("^=")); return true; 1855 - case '?': add_token(TK("?")); return true; 1856 - case '.': { 1857 - if(matchchar('.')) { 1858 - if(matchchar('.')) { 1859 - add_token(TK("...")); 1860 - } else { 1861 - SyntaxError("invalid token '..'"); 1862 - } 1863 - } else { 1864 - add_token(TK(".")); 1865 - } 1866 - return true; 1867 - } 1868 - case '=': add_token_2('=', TK("="), TK("==")); return true; 1869 - case '+': add_token_2('=', TK("+"), TK("+=")); return true; 1870 - case '>': { 1871 - if(matchchar('=')) add_token(TK(">=")); 1872 - else if(matchchar('>')) add_token_2('=', TK(">>"), TK(">>=")); 1873 - else add_token(TK(">")); 1874 - return true; 1875 - } 1876 - case '<': { 1877 - if(matchchar('=')) add_token(TK("<=")); 1878 - else if(matchchar('<')) add_token_2('=', TK("<<"), TK("<<=")); 1879 - else add_token(TK("<")); 1880 - return true; 1881 - } 1882 - case '-': { 1883 - if(matchchar('=')) add_token(TK("-=")); 1884 - else if(matchchar('>')) add_token(TK("->")); 1885 - else add_token(TK("-")); 1886 - return true; 1887 - } 1888 - case '!': 1889 - if(matchchar('=')) add_token(TK("!=")); 1890 - else SyntaxError("expected '=' after '!'"); 1891 - break; 1892 - case '*': 1893 - if (matchchar('*')) { 1894 - add_token(TK("**")); // '**' 1895 - } else { 1896 - add_token_2('=', TK("*"), TK("*=")); 1897 - } 1898 - return true; 1899 - case '/': 1900 - if(matchchar('/')) { 1901 - add_token_2('=', TK("//"), TK("//=")); 1902 - } else { 1903 - add_token_2('=', TK("/"), TK("/=")); 1904 - } 1905 - return true; 1906 - case ' ': case '\t': eat_spaces(); break; 1907 - case '\n': { 1908 - add_token(TK("@eol")); 1909 - if(!eat_indentation()) IndentationError("unindent does not match any outer indentation level"); 1910 - return true; 1911 - } 1912 - default: { 1913 - if(c == 'f'){ 1914 - if(matchchar('\'')) {eat_string('\'', F_STRING); return true;} 1915 - if(matchchar('"')) {eat_string('"', F_STRING); return true;} 1916 - }else if(c == 'r'){ 1917 - if(matchchar('\'')) {eat_string('\'', RAW_STRING); return true;} 1918 - if(matchchar('"')) {eat_string('"', RAW_STRING); return true;} 1919 - } 1920 - if (c >= '0' && c <= '9') { 1921 - eat_number(); 1922 - return true; 1923 - } 1924 - switch (eat_name()) 1925 - { 1926 - case 0: break; 1927 - case 1: SyntaxError("invalid char: " + std::string(1, c)); 1928 - case 2: SyntaxError("invalid utf8 sequence: " + std::string(1, c)); 1929 - case 3: SyntaxError("@id contains invalid char"); break; 1930 - case 4: SyntaxError("invalid JSON token"); break; 1931 - default: FATAL_ERROR(); 1932 - } 1933 - return true; 1934 - } 1935 - } 1936 - } 1937 - 1938 - token_start = curr_char; 1939 - while(indents.size() > 1){ 1940 - indents.pop(); 1941 - add_token(TK("@dedent")); 1942 - return true; 1943 - } 1944 - add_token(TK("@eof")); 1945 - return false; 1946 - } 1947 - 1948 - /***** Error Reporter *****/ 1949 - void throw_err(Str type, Str msg){ 1950 - int lineno = current_line; 1951 - const char* cursor = curr_char; 1952 - if(peekchar() == '\n'){ 1953 - lineno--; 1954 - cursor--; 1955 - } 1956 - throw_err(type, msg, lineno, cursor); 1957 - } 1958 - 1959 - void throw_err(Str type, Str msg, int lineno, const char* cursor){ 1960 - auto e = Exception("SyntaxError", msg); 1961 - e.st_push(src->snapshot(lineno, cursor)); 1962 - throw e; 1963 - } 1964 - void SyntaxError(Str msg){ throw_err("SyntaxError", msg); } 1965 - void SyntaxError(){ throw_err("SyntaxError", "invalid syntax"); } 1966 - void IndentationError(Str msg){ throw_err("IndentationError", msg); } 1967 - 1968 - Lexer(shared_ptr<SourceData> src) { 1969 - this->src = src; 1970 - this->token_start = src->source.c_str(); 1971 - this->curr_char = src->source.c_str(); 1972 - this->nexts.push_back(Token{TK("@sof"), token_start, 0, current_line}); 1973 - this->indents.push(0); 1974 - } 1975 - 1976 - std::vector<Token> run() { 1977 - if(used) FATAL_ERROR(); 1978 - used = true; 1979 - while (lex_one_token()); 1980 - return std::move(nexts); 1981 - } 1982 - }; 1983 - 1984 - } // namespace pkpy 1985 - 1986 - 1987 - 1988 - namespace pkpy { 1989 - 1990 - struct CodeObject; 1991 - struct Frame; 1992 - struct Function; 1993 - class VM; 1994 - 1995 - typedef PyObject* (*NativeFuncC)(VM*, ArgsView); 1996 - typedef int (*LuaStyleFuncC)(VM*); 1997 - 1998 - struct NativeFunc { 1999 - NativeFuncC f; 2000 - int argc; // DONOT include self 2001 - bool method; 2002 - 2003 - // this is designed for lua style C bindings 2004 - // access it via `CAST(NativeFunc&, args[-2])._lua_f` 2005 - LuaStyleFuncC _lua_f; 2006 - 2007 - NativeFunc(NativeFuncC f, int argc, bool method) : f(f), argc(argc), method(method), _lua_f(nullptr) {} 2008 - PyObject* operator()(VM* vm, ArgsView args) const; 2009 - }; 2010 - 2011 - typedef shared_ptr<CodeObject> CodeObject_; 2012 - 2013 - struct FuncDecl { 2014 - struct KwArg { 2015 - int key; // index in co->varnames 2016 - PyObject* value; // default value 2017 - }; 2018 - CodeObject_ code; // code object of this function 2019 - pod_vector<int> args; // indices in co->varnames 2020 - int starred_arg = -1; // index in co->varnames, -1 if no *arg 2021 - pod_vector<KwArg> kwargs; // indices in co->varnames 2022 - bool nested = false; // whether this function is nested 2023 - void _gc_mark() const; 2024 - }; 2025 - 2026 - using FuncDecl_ = shared_ptr<FuncDecl>; 2027 - 2028 - struct Function{ 2029 - FuncDecl_ decl; 2030 - bool is_simple; 2031 - int argc; // cached argc 2032 - PyObject* _module; 2033 - NameDict_ _closure; 2034 - }; 2035 - 2036 - struct BoundMethod { 2037 - PyObject* self; 2038 - PyObject* func; 2039 - BoundMethod(PyObject* self, PyObject* func) : self(self), func(func) {} 2040 - 2041 - bool operator==(const BoundMethod& rhs) const noexcept { 2042 - return self == rhs.self && func == rhs.func; 2043 - } 2044 - bool operator!=(const BoundMethod& rhs) const noexcept { 2045 - return self != rhs.self || func != rhs.func; 2046 - } 2047 - }; 2048 - 2049 - struct Range { 2050 - i64 start = 0; 2051 - i64 stop = -1; 2052 - i64 step = 1; 2053 - }; 2054 - 2055 - struct Bytes{ 2056 - std::vector<char> _data; 2057 - bool _ok; 2058 - 2059 - int size() const noexcept { return _data.size(); } 2060 - int operator[](int i) const noexcept { return (int)(uint8_t)_data[i]; } 2061 - const char* data() const noexcept { return _data.data(); } 2062 - 2063 - bool operator==(const Bytes& rhs) const noexcept { 2064 - return _data == rhs._data; 2065 - } 2066 - bool operator!=(const Bytes& rhs) const noexcept { 2067 - return _data != rhs._data; 2068 - } 2069 - 2070 - std::string str() const noexcept { return std::string(_data.begin(), _data.end()); } 2071 - 2072 - Bytes() : _data(), _ok(false) {} 2073 - Bytes(std::vector<char>&& data) : _data(std::move(data)), _ok(true) {} 2074 - Bytes(const std::string& data) : _data(data.begin(), data.end()), _ok(true) {} 2075 - operator bool() const noexcept { return _ok; } 2076 - }; 2077 - 2078 - using Super = std::pair<PyObject*, Type>; 2079 - 2080 - struct Slice { 2081 - PyObject* start; 2082 - PyObject* stop; 2083 - PyObject* step; 2084 - Slice(PyObject* start, PyObject* stop, PyObject* step) : start(start), stop(stop), step(step) {} 2085 - }; 2086 - 2087 - class BaseIter { 2088 - protected: 2089 - VM* vm; 2090 - public: 2091 - BaseIter(VM* vm) : vm(vm) {} 2092 - virtual PyObject* next() = 0; 2093 - virtual ~BaseIter() = default; 2094 - }; 2095 - 2096 - struct GCHeader { 2097 - bool enabled; // whether this object is managed by GC 2098 - bool marked; // whether this object is marked 2099 - GCHeader() : enabled(true), marked(false) {} 2100 - }; 2101 - 2102 - struct PyObject{ 2103 - GCHeader gc; 2104 - Type type; 2105 - NameDict* _attr; 2106 - 2107 - bool is_attr_valid() const noexcept { return _attr != nullptr; } 2108 - NameDict& attr() noexcept { return *_attr; } 2109 - PyObject* attr(StrName name) const noexcept { return (*_attr)[name]; } 2110 - virtual void* value() = 0; 2111 - virtual void _obj_gc_mark() = 0; 2112 - 2113 - PyObject(Type type) : type(type), _attr(nullptr) {} 2114 - 2115 - virtual ~PyObject() { 2116 - if(_attr == nullptr) return; 2117 - _attr->~NameDict(); 2118 - pool64.dealloc(_attr); 2119 - } 2120 - 2121 - void enable_instance_dict(float lf=kInstAttrLoadFactor) noexcept { 2122 - _attr = new(pool64.alloc<NameDict>()) NameDict(lf); 2123 - } 2124 - }; 2125 - 2126 - template <typename, typename=void> struct has_gc_marker : std::false_type {}; 2127 - template <typename T> struct has_gc_marker<T, std::void_t<decltype(&T::_gc_mark)>> : std::true_type {}; 2128 - 2129 - template <typename T> 2130 - struct Py_ final: PyObject { 2131 - T _value; 2132 - void* value() override { return &_value; } 2133 - void _obj_gc_mark() override { 2134 - if constexpr (has_gc_marker<T>::value) { 2135 - _value._gc_mark(); 2136 - } 2137 - } 2138 - Py_(Type type, const T& value) : PyObject(type), _value(value) {} 2139 - Py_(Type type, T&& value) : PyObject(type), _value(std::move(value)) {} 2140 - }; 2141 - 2142 - struct MappingProxy{ 2143 - PyObject* obj; 2144 - MappingProxy(PyObject* obj) : obj(obj) {} 2145 - NameDict& attr() noexcept { return obj->attr(); } 2146 - }; 2147 - 2148 - #define OBJ_GET(T, obj) (((Py_<T>*)(obj))->_value) 2149 - // #define OBJ_GET(T, obj) (*reinterpret_cast<T*>((obj)->value())) 2150 - 2151 - #define OBJ_MARK(obj) \ 2152 - if(!is_tagged(obj) && !(obj)->gc.marked) { \ 2153 - (obj)->gc.marked = true; \ 2154 - (obj)->_obj_gc_mark(); \ 2155 - if((obj)->is_attr_valid()) gc_mark_namedict((obj)->attr()); \ 2156 - } 2157 - 2158 - inline void gc_mark_namedict(NameDict& t){ 2159 - if(t.size() == 0) return; 2160 - for(uint16_t i=0; i<t._capacity; i++){ 2161 - if(t._items[i].first.empty()) continue; 2162 - OBJ_MARK(t._items[i].second); 2163 - } 2164 - } 2165 - 2166 - Str obj_type_name(VM* vm, Type type); 2167 - 2168 - #if DEBUG_NO_BUILTIN_MODULES 2169 - #define OBJ_NAME(obj) Str("<?>") 2170 - #else 2171 - #define OBJ_NAME(obj) OBJ_GET(Str, vm->getattr(obj, __name__)) 2172 - #endif 2173 - 2174 - const int kTpIntIndex = 2; 2175 - const int kTpFloatIndex = 3; 2176 - 2177 - inline bool is_type(PyObject* obj, Type type) { 2178 - #if DEBUG_EXTRA_CHECK 2179 - if(obj == nullptr) throw std::runtime_error("is_type() called with nullptr"); 2180 - if(is_special(obj)) throw std::runtime_error("is_type() called with special object"); 2181 - #endif 2182 - switch(type.index){ 2183 - case kTpIntIndex: return is_int(obj); 2184 - case kTpFloatIndex: return is_float(obj); 2185 - default: return !is_tagged(obj) && obj->type == type; 2186 - } 2187 - } 2188 - 2189 - inline bool is_non_tagged_type(PyObject* obj, Type type) { 2190 - #if DEBUG_EXTRA_CHECK 2191 - if(obj == nullptr) throw std::runtime_error("is_non_tagged_type() called with nullptr"); 2192 - if(is_special(obj)) throw std::runtime_error("is_non_tagged_type() called with special object"); 2193 - #endif 2194 - return !is_tagged(obj) && obj->type == type; 2195 - } 2196 - 2197 - union BitsCvt { 2198 - i64 _int; 2199 - f64 _float; 2200 - BitsCvt(i64 val) : _int(val) {} 2201 - BitsCvt(f64 val) : _float(val) {} 2202 - }; 2203 - 2204 - template <typename, typename=void> struct is_py_class : std::false_type {}; 2205 - template <typename T> struct is_py_class<T, std::void_t<decltype(T::_type)>> : std::true_type {}; 2206 - 2207 - template<typename T> void _check_py_class(VM*, PyObject*); 2208 - template<typename T> T py_pointer_cast(VM*, PyObject*); 2209 - 2210 - template<typename __T> 2211 - __T py_cast(VM* vm, PyObject* obj) { 2212 - using T = std::decay_t<__T>; 2213 - if constexpr(std::is_pointer_v<T>){ 2214 - return py_pointer_cast<T>(vm, obj); 2215 - }else if constexpr(is_py_class<T>::value){ 2216 - _check_py_class<T>(vm, obj); 2217 - return OBJ_GET(T, obj); 2218 - }else { 2219 - return Discarded(); 2220 - } 2221 - } 2222 - 2223 - template<typename __T> 2224 - __T _py_cast(VM* vm, PyObject* obj) { 2225 - using T = std::decay_t<__T>; 2226 - if constexpr(std::is_pointer_v<__T>){ 2227 - return py_pointer_cast<__T>(vm, obj); 2228 - }else if constexpr(is_py_class<T>::value){ 2229 - return OBJ_GET(T, obj); 2230 - }else{ 2231 - return Discarded(); 2232 - } 2233 - } 2234 - 2235 - #define VAR(x) py_var(vm, x) 2236 - #define CAST(T, x) py_cast<T>(vm, x) 2237 - #define _CAST(T, x) _py_cast<T>(vm, x) 2238 - 2239 - /*****************************************************************/ 2240 - template<> 2241 - struct Py_<List> final: PyObject { 2242 - List _value; 2243 - void* value() override { return &_value; } 2244 - 2245 - Py_(Type type, List&& val): PyObject(type), _value(std::move(val)) {} 2246 - Py_(Type type, const List& val): PyObject(type), _value(val) {} 2247 - 2248 - void _obj_gc_mark() override { 2249 - for(PyObject* obj: _value) OBJ_MARK(obj); 2250 - } 2251 - }; 2252 - 2253 - template<> 2254 - struct Py_<Tuple> final: PyObject { 2255 - Tuple _value; 2256 - void* value() override { return &_value; } 2257 - 2258 - Py_(Type type, Tuple&& val): PyObject(type), _value(std::move(val)) {} 2259 - Py_(Type type, const Tuple& val): PyObject(type), _value(val) {} 2260 - 2261 - void _obj_gc_mark() override { 2262 - for(PyObject* obj: _value) OBJ_MARK(obj); 2263 - } 2264 - }; 2265 - 2266 - template<> 2267 - struct Py_<MappingProxy> final: PyObject { 2268 - MappingProxy _value; 2269 - void* value() override { return &_value; } 2270 - Py_(Type type, MappingProxy val): PyObject(type), _value(val) {} 2271 - void _obj_gc_mark() override { 2272 - OBJ_MARK(_value.obj); 2273 - } 2274 - }; 2275 - 2276 - template<> 2277 - struct Py_<BoundMethod> final: PyObject { 2278 - BoundMethod _value; 2279 - void* value() override { return &_value; } 2280 - Py_(Type type, BoundMethod val): PyObject(type), _value(val) {} 2281 - void _obj_gc_mark() override { 2282 - OBJ_MARK(_value.self); 2283 - OBJ_MARK(_value.func); 2284 - } 2285 - }; 2286 - 2287 - template<> 2288 - struct Py_<Slice> final: PyObject { 2289 - Slice _value; 2290 - void* value() override { return &_value; } 2291 - Py_(Type type, Slice val): PyObject(type), _value(val) {} 2292 - void _obj_gc_mark() override { 2293 - OBJ_MARK(_value.start); 2294 - OBJ_MARK(_value.stop); 2295 - OBJ_MARK(_value.step); 2296 - } 2297 - }; 2298 - 2299 - template<> 2300 - struct Py_<Function> final: PyObject { 2301 - Function _value; 2302 - void* value() override { return &_value; } 2303 - Py_(Type type, Function val): PyObject(type), _value(val) { 2304 - enable_instance_dict(); 2305 - } 2306 - void _obj_gc_mark() override { 2307 - _value.decl->_gc_mark(); 2308 - if(_value._module != nullptr) OBJ_MARK(_value._module); 2309 - if(_value._closure != nullptr) gc_mark_namedict(*_value._closure); 2310 - } 2311 - }; 2312 - 2313 - template<> 2314 - struct Py_<NativeFunc> final: PyObject { 2315 - NativeFunc _value; 2316 - void* value() override { return &_value; } 2317 - Py_(Type type, NativeFunc val): PyObject(type), _value(val) { 2318 - enable_instance_dict(); 2319 - } 2320 - void _obj_gc_mark() override {} 2321 - }; 2322 - 2323 - template<> 2324 - struct Py_<Super> final: PyObject { 2325 - Super _value; 2326 - void* value() override { return &_value; } 2327 - Py_(Type type, Super val): PyObject(type), _value(val) {} 2328 - void _obj_gc_mark() override { 2329 - OBJ_MARK(_value.first); 2330 - } 2331 - }; 2332 - 2333 - template<> 2334 - struct Py_<DummyInstance> final: PyObject { 2335 - void* value() override { return nullptr; } 2336 - Py_(Type type, DummyInstance val): PyObject(type) { 2337 - enable_instance_dict(); 2338 - } 2339 - void _obj_gc_mark() override {} 2340 - }; 2341 - 2342 - template<> 2343 - struct Py_<Type> final: PyObject { 2344 - Type _value; 2345 - void* value() override { return &_value; } 2346 - Py_(Type type, Type val): PyObject(type), _value(val) { 2347 - enable_instance_dict(kTypeAttrLoadFactor); 2348 - } 2349 - void _obj_gc_mark() override {} 2350 - }; 2351 - 2352 - template<> 2353 - struct Py_<DummyModule> final: PyObject { 2354 - void* value() override { return nullptr; } 2355 - Py_(Type type, DummyModule val): PyObject(type) { 2356 - enable_instance_dict(kTypeAttrLoadFactor); 2357 - } 2358 - void _obj_gc_mark() override {} 2359 - }; 2360 - 2361 - 2362 - } // namespace pkpy 2363 - 2364 - 2365 - namespace pkpy{ 2366 - 2367 - enum NameScope { NAME_LOCAL, NAME_GLOBAL, NAME_GLOBAL_UNKNOWN }; 2368 - 2369 - enum Opcode { 2370 - #define OPCODE(name) OP_##name, 2371 - #ifdef OPCODE 2372 - 2373 - /**************************/ 2374 - OPCODE(NO_OP) 2375 - /**************************/ 2376 - OPCODE(POP_TOP) 2377 - OPCODE(DUP_TOP) 2378 - OPCODE(ROT_TWO) 2379 - OPCODE(PRINT_EXPR) 2380 - /**************************/ 2381 - OPCODE(LOAD_CONST) 2382 - OPCODE(LOAD_NONE) 2383 - OPCODE(LOAD_TRUE) 2384 - OPCODE(LOAD_FALSE) 2385 - OPCODE(LOAD_INTEGER) 2386 - OPCODE(LOAD_ELLIPSIS) 2387 - OPCODE(LOAD_FUNCTION) 2388 - OPCODE(LOAD_NULL) 2389 - /**************************/ 2390 - OPCODE(LOAD_FAST) 2391 - OPCODE(LOAD_NAME) 2392 - OPCODE(LOAD_NONLOCAL) 2393 - OPCODE(LOAD_GLOBAL) 2394 - OPCODE(LOAD_ATTR) 2395 - OPCODE(LOAD_METHOD) 2396 - OPCODE(LOAD_SUBSCR) 2397 - 2398 - OPCODE(STORE_FAST) 2399 - OPCODE(STORE_NAME) 2400 - OPCODE(STORE_GLOBAL) 2401 - OPCODE(STORE_ATTR) 2402 - OPCODE(STORE_SUBSCR) 2403 - 2404 - OPCODE(DELETE_FAST) 2405 - OPCODE(DELETE_NAME) 2406 - OPCODE(DELETE_GLOBAL) 2407 - OPCODE(DELETE_ATTR) 2408 - OPCODE(DELETE_SUBSCR) 2409 - /**************************/ 2410 - OPCODE(BUILD_LIST) 2411 - OPCODE(BUILD_DICT) 2412 - OPCODE(BUILD_SET) 2413 - OPCODE(BUILD_SLICE) 2414 - OPCODE(BUILD_TUPLE) 2415 - OPCODE(BUILD_STRING) 2416 - /**************************/ 2417 - OPCODE(BINARY_OP) 2418 - OPCODE(BINARY_ADD) 2419 - OPCODE(BINARY_SUB) 2420 - OPCODE(BINARY_MUL) 2421 - OPCODE(BINARY_FLOORDIV) 2422 - OPCODE(BINARY_MOD) 2423 - 2424 - OPCODE(COMPARE_LT) 2425 - OPCODE(COMPARE_LE) 2426 - OPCODE(COMPARE_EQ) 2427 - OPCODE(COMPARE_NE) 2428 - OPCODE(COMPARE_GT) 2429 - OPCODE(COMPARE_GE) 2430 - 2431 - OPCODE(BITWISE_LSHIFT) 2432 - OPCODE(BITWISE_RSHIFT) 2433 - OPCODE(BITWISE_AND) 2434 - OPCODE(BITWISE_OR) 2435 - OPCODE(BITWISE_XOR) 2436 - 2437 - OPCODE(IS_OP) 2438 - OPCODE(CONTAINS_OP) 2439 - /**************************/ 2440 - OPCODE(JUMP_ABSOLUTE) 2441 - OPCODE(POP_JUMP_IF_FALSE) 2442 - OPCODE(JUMP_IF_TRUE_OR_POP) 2443 - OPCODE(JUMP_IF_FALSE_OR_POP) 2444 - OPCODE(LOOP_CONTINUE) 2445 - OPCODE(LOOP_BREAK) 2446 - OPCODE(GOTO) 2447 - /**************************/ 2448 - OPCODE(BEGIN_CALL) 2449 - OPCODE(CALL) 2450 - OPCODE(RETURN_VALUE) 2451 - OPCODE(YIELD_VALUE) 2452 - /**************************/ 2453 - OPCODE(LIST_APPEND) 2454 - OPCODE(DICT_ADD) 2455 - OPCODE(SET_ADD) 2456 - /**************************/ 2457 - OPCODE(UNARY_NEGATIVE) 2458 - OPCODE(UNARY_NOT) 2459 - /**************************/ 2460 - OPCODE(GET_ITER) 2461 - OPCODE(FOR_ITER) 2462 - /**************************/ 2463 - OPCODE(IMPORT_NAME) 2464 - OPCODE(IMPORT_STAR) 2465 - /**************************/ 2466 - OPCODE(UNPACK_SEQUENCE) 2467 - OPCODE(UNPACK_EX) 2468 - OPCODE(UNPACK_UNLIMITED) 2469 - /**************************/ 2470 - OPCODE(BEGIN_CLASS) 2471 - OPCODE(END_CLASS) 2472 - OPCODE(STORE_CLASS_ATTR) 2473 - /**************************/ 2474 - OPCODE(WITH_ENTER) 2475 - OPCODE(WITH_EXIT) 2476 - /**************************/ 2477 - OPCODE(ASSERT) 2478 - OPCODE(EXCEPTION_MATCH) 2479 - OPCODE(RAISE) 2480 - OPCODE(RE_RAISE) 2481 - /**************************/ 2482 - OPCODE(SETUP_DOCSTRING) 2483 - OPCODE(FORMAT_STRING) 2484 - #endif 2485 - #undef OPCODE 2486 - }; 2487 - 2488 - inline const char* OP_NAMES[] = { 2489 - #define OPCODE(name) #name, 2490 - #ifdef OPCODE 2491 - 2492 - /**************************/ 2493 - OPCODE(NO_OP) 2494 - /**************************/ 2495 - OPCODE(POP_TOP) 2496 - OPCODE(DUP_TOP) 2497 - OPCODE(ROT_TWO) 2498 - OPCODE(PRINT_EXPR) 2499 - /**************************/ 2500 - OPCODE(LOAD_CONST) 2501 - OPCODE(LOAD_NONE) 2502 - OPCODE(LOAD_TRUE) 2503 - OPCODE(LOAD_FALSE) 2504 - OPCODE(LOAD_INTEGER) 2505 - OPCODE(LOAD_ELLIPSIS) 2506 - OPCODE(LOAD_FUNCTION) 2507 - OPCODE(LOAD_NULL) 2508 - /**************************/ 2509 - OPCODE(LOAD_FAST) 2510 - OPCODE(LOAD_NAME) 2511 - OPCODE(LOAD_NONLOCAL) 2512 - OPCODE(LOAD_GLOBAL) 2513 - OPCODE(LOAD_ATTR) 2514 - OPCODE(LOAD_METHOD) 2515 - OPCODE(LOAD_SUBSCR) 2516 - 2517 - OPCODE(STORE_FAST) 2518 - OPCODE(STORE_NAME) 2519 - OPCODE(STORE_GLOBAL) 2520 - OPCODE(STORE_ATTR) 2521 - OPCODE(STORE_SUBSCR) 2522 - 2523 - OPCODE(DELETE_FAST) 2524 - OPCODE(DELETE_NAME) 2525 - OPCODE(DELETE_GLOBAL) 2526 - OPCODE(DELETE_ATTR) 2527 - OPCODE(DELETE_SUBSCR) 2528 - /**************************/ 2529 - OPCODE(BUILD_LIST) 2530 - OPCODE(BUILD_DICT) 2531 - OPCODE(BUILD_SET) 2532 - OPCODE(BUILD_SLICE) 2533 - OPCODE(BUILD_TUPLE) 2534 - OPCODE(BUILD_STRING) 2535 - /**************************/ 2536 - OPCODE(BINARY_OP) 2537 - OPCODE(BINARY_ADD) 2538 - OPCODE(BINARY_SUB) 2539 - OPCODE(BINARY_MUL) 2540 - OPCODE(BINARY_FLOORDIV) 2541 - OPCODE(BINARY_MOD) 2542 - 2543 - OPCODE(COMPARE_LT) 2544 - OPCODE(COMPARE_LE) 2545 - OPCODE(COMPARE_EQ) 2546 - OPCODE(COMPARE_NE) 2547 - OPCODE(COMPARE_GT) 2548 - OPCODE(COMPARE_GE) 2549 - 2550 - OPCODE(BITWISE_LSHIFT) 2551 - OPCODE(BITWISE_RSHIFT) 2552 - OPCODE(BITWISE_AND) 2553 - OPCODE(BITWISE_OR) 2554 - OPCODE(BITWISE_XOR) 2555 - 2556 - OPCODE(IS_OP) 2557 - OPCODE(CONTAINS_OP) 2558 - /**************************/ 2559 - OPCODE(JUMP_ABSOLUTE) 2560 - OPCODE(POP_JUMP_IF_FALSE) 2561 - OPCODE(JUMP_IF_TRUE_OR_POP) 2562 - OPCODE(JUMP_IF_FALSE_OR_POP) 2563 - OPCODE(LOOP_CONTINUE) 2564 - OPCODE(LOOP_BREAK) 2565 - OPCODE(GOTO) 2566 - /**************************/ 2567 - OPCODE(BEGIN_CALL) 2568 - OPCODE(CALL) 2569 - OPCODE(RETURN_VALUE) 2570 - OPCODE(YIELD_VALUE) 2571 - /**************************/ 2572 - OPCODE(LIST_APPEND) 2573 - OPCODE(DICT_ADD) 2574 - OPCODE(SET_ADD) 2575 - /**************************/ 2576 - OPCODE(UNARY_NEGATIVE) 2577 - OPCODE(UNARY_NOT) 2578 - /**************************/ 2579 - OPCODE(GET_ITER) 2580 - OPCODE(FOR_ITER) 2581 - /**************************/ 2582 - OPCODE(IMPORT_NAME) 2583 - OPCODE(IMPORT_STAR) 2584 - /**************************/ 2585 - OPCODE(UNPACK_SEQUENCE) 2586 - OPCODE(UNPACK_EX) 2587 - OPCODE(UNPACK_UNLIMITED) 2588 - /**************************/ 2589 - OPCODE(BEGIN_CLASS) 2590 - OPCODE(END_CLASS) 2591 - OPCODE(STORE_CLASS_ATTR) 2592 - /**************************/ 2593 - OPCODE(WITH_ENTER) 2594 - OPCODE(WITH_EXIT) 2595 - /**************************/ 2596 - OPCODE(ASSERT) 2597 - OPCODE(EXCEPTION_MATCH) 2598 - OPCODE(RAISE) 2599 - OPCODE(RE_RAISE) 2600 - /**************************/ 2601 - OPCODE(SETUP_DOCSTRING) 2602 - OPCODE(FORMAT_STRING) 2603 - #endif 2604 - #undef OPCODE 2605 - }; 2606 - 2607 - struct Bytecode{ 2608 - uint16_t op; 2609 - uint16_t block; 2610 - int arg; 2611 - }; 2612 - 2613 - enum CodeBlockType { 2614 - NO_BLOCK, 2615 - FOR_LOOP, 2616 - WHILE_LOOP, 2617 - CONTEXT_MANAGER, 2618 - TRY_EXCEPT, 2619 - }; 2620 - 2621 - #define BC_NOARG -1 2622 - #define BC_KEEPLINE -1 2623 - 2624 - struct CodeBlock { 2625 - CodeBlockType type; 2626 - int parent; // parent index in blocks 2627 - int for_loop_depth; // this is used for exception handling 2628 - int start; // start index of this block in codes, inclusive 2629 - int end; // end index of this block in codes, exclusive 2630 - 2631 - CodeBlock(CodeBlockType type, int parent, int for_loop_depth, int start): 2632 - type(type), parent(parent), for_loop_depth(for_loop_depth), start(start), end(-1) {} 2633 - }; 2634 - 2635 - struct CodeObject { 2636 - shared_ptr<SourceData> src; 2637 - Str name; 2638 - bool is_generator = false; 2639 - 2640 - CodeObject(shared_ptr<SourceData> src, const Str& name): 2641 - src(src), name(name) {} 2642 - 2643 - std::vector<Bytecode> codes; 2644 - std::vector<int> lines; // line number for each bytecode 2645 - List consts; 2646 - std::vector<StrName> varnames; // local variables 2647 - NameDictInt varnames_inv; 2648 - std::set<Str> global_names; 2649 - std::vector<CodeBlock> blocks = { CodeBlock(NO_BLOCK, -1, 0, 0) }; 2650 - NameDictInt labels; 2651 - std::vector<FuncDecl_> func_decls; 2652 - 2653 - void optimize(VM* vm); 2654 - 2655 - void _gc_mark() const { 2656 - for(PyObject* v : consts) OBJ_MARK(v); 2657 - for(auto& decl: func_decls) decl->_gc_mark(); 2658 - } 2659 - }; 2660 - 2661 - } // namespace pkpy 2662 - 2663 - 2664 - namespace pkpy{ 2665 - 2666 - // weak reference fast locals 2667 - struct FastLocals{ 2668 - // this is a weak reference 2669 - const NameDictInt* varnames_inv; 2670 - PyObject** a; 2671 - 2672 - int size() const{ 2673 - return varnames_inv->size(); 2674 - } 2675 - 2676 - PyObject*& operator[](int i){ return a[i]; } 2677 - PyObject* operator[](int i) const { return a[i]; } 2678 - 2679 - FastLocals(const CodeObject* co, PyObject** a): varnames_inv(&co->varnames_inv), a(a) {} 2680 - FastLocals(const FastLocals& other): varnames_inv(other.varnames_inv), a(other.a) {} 2681 - 2682 - PyObject* try_get(StrName name){ 2683 - int index = varnames_inv->try_get(name); 2684 - if(index == -1) return nullptr; 2685 - return a[index]; 2686 - } 2687 - 2688 - bool contains(StrName name){ 2689 - return varnames_inv->contains(name); 2690 - } 2691 - 2692 - void erase(StrName name){ 2693 - int index = varnames_inv->try_get(name); 2694 - if(index == -1) FATAL_ERROR(); 2695 - a[index] = nullptr; 2696 - } 2697 - 2698 - bool try_set(StrName name, PyObject* value){ 2699 - int index = varnames_inv->try_get(name); 2700 - if(index == -1) return false; 2701 - a[index] = value; 2702 - return true; 2703 - } 2704 - 2705 - NameDict_ to_namedict(){ 2706 - NameDict_ dict = make_sp<NameDict>(); 2707 - // TODO: optimize this 2708 - // NameDict.items() is expensive 2709 - for(auto& kv: varnames_inv->items()){ 2710 - dict->set(kv.first, a[kv.second]); 2711 - } 2712 - return dict; 2713 - } 2714 - }; 2715 - 2716 - template<size_t MAX_SIZE> 2717 - struct ValueStackImpl { 2718 - // We allocate extra MAX_SIZE/128 places to keep `_sp` valid when `is_overflow() == true`. 2719 - PyObject* _begin[MAX_SIZE + MAX_SIZE/128]; 2720 - PyObject** _sp; 2721 - PyObject** _max_end; 2722 - 2723 - ValueStackImpl(): _sp(_begin), _max_end(_begin + MAX_SIZE) {} 2724 - 2725 - PyObject*& top(){ return _sp[-1]; } 2726 - PyObject* top() const { return _sp[-1]; } 2727 - PyObject*& second(){ return _sp[-2]; } 2728 - PyObject* second() const { return _sp[-2]; } 2729 - PyObject*& third(){ return _sp[-3]; } 2730 - PyObject* third() const { return _sp[-3]; } 2731 - PyObject*& peek(int n){ return _sp[-n]; } 2732 - PyObject* peek(int n) const { return _sp[-n]; } 2733 - void push(PyObject* v){ *_sp++ = v; } 2734 - void pop(){ --_sp; } 2735 - PyObject* popx(){ return *--_sp; } 2736 - ArgsView view(int n){ return ArgsView(_sp-n, _sp); } 2737 - void shrink(int n){ _sp -= n; } 2738 - int size() const { return _sp - _begin; } 2739 - bool empty() const { return _sp == _begin; } 2740 - PyObject** begin() { return _begin; } 2741 - PyObject** end() { return _sp; } 2742 - void reset(PyObject** sp) { 2743 - #if DEBUG_EXTRA_CHECK 2744 - if(sp < _begin || sp > _begin + MAX_SIZE) FATAL_ERROR(); 2745 - #endif 2746 - _sp = sp; 2747 - } 2748 - void clear() { _sp = _begin; } 2749 - bool is_overflow() const { return _sp >= _max_end; } 2750 - 2751 - ValueStackImpl(const ValueStackImpl&) = delete; 2752 - ValueStackImpl(ValueStackImpl&&) = delete; 2753 - ValueStackImpl& operator=(const ValueStackImpl&) = delete; 2754 - ValueStackImpl& operator=(ValueStackImpl&&) = delete; 2755 - }; 2756 - 2757 - using ValueStack = ValueStackImpl<32768>; 2758 - 2759 - struct Frame { 2760 - int _ip = -1; 2761 - int _next_ip = 0; 2762 - ValueStack* _s; 2763 - // This is for unwinding only, use `actual_sp_base()` for value stack access 2764 - PyObject** _sp_base; 2765 - 2766 - const CodeObject* co; 2767 - PyObject* _module; 2768 - PyObject* _callable; 2769 - FastLocals _locals; 2770 - 2771 - NameDict& f_globals() noexcept { return _module->attr(); } 2772 - 2773 - PyObject* f_closure_try_get(StrName name){ 2774 - if(_callable == nullptr) return nullptr; 2775 - Function& fn = OBJ_GET(Function, _callable); 2776 - if(fn._closure == nullptr) return nullptr; 2777 - return fn._closure->try_get(name); 2778 - } 2779 - 2780 - Frame(ValueStack* _s, PyObject** p0, const CodeObject* co, PyObject* _module, PyObject* _callable) 2781 - : _s(_s), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(co, p0) { } 2782 - 2783 - Frame(ValueStack* _s, PyObject** p0, const CodeObject* co, PyObject* _module, PyObject* _callable, FastLocals _locals) 2784 - : _s(_s), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals) { } 2785 - 2786 - Frame(ValueStack* _s, PyObject** p0, const CodeObject_& co, PyObject* _module) 2787 - : _s(_s), _sp_base(p0), co(co.get()), _module(_module), _callable(nullptr), _locals(co.get(), p0) {} 2788 - 2789 - Bytecode next_bytecode() { 2790 - _ip = _next_ip++; 2791 - #if DEBUG_EXTRA_CHECK 2792 - if(_ip >= co->codes.size()) FATAL_ERROR(); 2793 - #endif 2794 - return co->codes[_ip]; 2795 - } 2796 - 2797 - Str snapshot(){ 2798 - int line = co->lines[_ip]; 2799 - return co->src->snapshot(line); 2800 - } 2801 - 2802 - PyObject** actual_sp_base() const { return _locals.a; } 2803 - int stack_size() const { return _s->_sp - actual_sp_base(); } 2804 - ArgsView stack_view() const { return ArgsView(actual_sp_base(), _s->_sp); } 2805 - 2806 - void jump_abs(int i){ _next_ip = i; } 2807 - // void jump_rel(int i){ _next_ip += i; } 2808 - 2809 - bool jump_to_exception_handler(){ 2810 - // try to find a parent try block 2811 - int block = co->codes[_ip].block; 2812 - while(block >= 0){ 2813 - if(co->blocks[block].type == TRY_EXCEPT) break; 2814 - block = co->blocks[block].parent; 2815 - } 2816 - if(block < 0) return false; 2817 - PyObject* obj = _s->popx(); // pop exception object 2818 - // get the stack size of the try block (depth of for loops) 2819 - int _stack_size = co->blocks[block].for_loop_depth; 2820 - if(stack_size() < _stack_size) throw std::runtime_error("invalid stack size"); 2821 - _s->reset(actual_sp_base() + _stack_size); // rollback the stack 2822 - _s->push(obj); // push exception object 2823 - _next_ip = co->blocks[block].end; 2824 - return true; 2825 - } 2826 - 2827 - int _exit_block(int i){ 2828 - if(co->blocks[i].type == FOR_LOOP) _s->pop(); 2829 - return co->blocks[i].parent; 2830 - } 2831 - 2832 - void jump_abs_break(int target){ 2833 - const Bytecode& prev = co->codes[_ip]; 2834 - int i = prev.block; 2835 - _next_ip = target; 2836 - if(_next_ip >= co->codes.size()){ 2837 - while(i>=0) i = _exit_block(i); 2838 - }else{ 2839 - const Bytecode& next = co->codes[target]; 2840 - while(i>=0 && i!=next.block) i = _exit_block(i); 2841 - if(i!=next.block) throw std::runtime_error("invalid jump"); 2842 - } 2843 - } 2844 - 2845 - void _gc_mark() const { 2846 - OBJ_MARK(_module); 2847 - if(_callable != nullptr) OBJ_MARK(_callable); 2848 - co->_gc_mark(); 2849 - } 2850 - }; 2851 - 2852 - }; // namespace pkpy 2853 - 2854 - 2855 - namespace pkpy { 2856 - struct ManagedHeap{ 2857 - std::vector<PyObject*> _no_gc; 2858 - std::vector<PyObject*> gen; 2859 - VM* vm; 2860 - ManagedHeap(VM* vm): vm(vm) {} 2861 - 2862 - static const int kMinGCThreshold = 3072; 2863 - int gc_threshold = kMinGCThreshold; 2864 - int gc_counter = 0; 2865 - 2866 - /********************/ 2867 - int _gc_lock_counter = 0; 2868 - struct ScopeLock{ 2869 - ManagedHeap* heap; 2870 - ScopeLock(ManagedHeap* heap): heap(heap){ 2871 - heap->_gc_lock_counter++; 2872 - } 2873 - ~ScopeLock(){ 2874 - heap->_gc_lock_counter--; 2875 - } 2876 - }; 2877 - 2878 - ScopeLock gc_scope_lock(){ 2879 - return ScopeLock(this); 2880 - } 2881 - /********************/ 2882 - 2883 - template<typename T> 2884 - PyObject* gcnew(Type type, T&& val){ 2885 - using __T = Py_<std::decay_t<T>>; 2886 - PyObject* obj = new(pool64.alloc<__T>()) __T(type, std::forward<T>(val)); 2887 - gen.push_back(obj); 2888 - gc_counter++; 2889 - return obj; 2890 - } 2891 - 2892 - template<typename T> 2893 - PyObject* _new(Type type, T&& val){ 2894 - using __T = Py_<std::decay_t<T>>; 2895 - PyObject* obj = new(pool64.alloc<__T>()) __T(type, std::forward<T>(val)); 2896 - obj->gc.enabled = false; 2897 - _no_gc.push_back(obj); 2898 - return obj; 2899 - } 2900 - 2901 - #if DEBUG_GC_STATS 2902 - inline static std::map<Type, int> deleted; 2903 - #endif 2904 - 2905 - int sweep(){ 2906 - std::vector<PyObject*> alive; 2907 - for(PyObject* obj: gen){ 2908 - if(obj->gc.marked){ 2909 - obj->gc.marked = false; 2910 - alive.push_back(obj); 2911 - }else{ 2912 - #if DEBUG_GC_STATS 2913 - deleted[obj->type] += 1; 2914 - #endif 2915 - obj->~PyObject(), pool64.dealloc(obj); 2916 - } 2917 - } 2918 - 2919 - // clear _no_gc marked flag 2920 - for(PyObject* obj: _no_gc) obj->gc.marked = false; 2921 - 2922 - int freed = gen.size() - alive.size(); 2923 - // std::cout << "GC: " << alive.size() << "/" << gen.size() << " (" << freed << " freed)" << std::endl; 2924 - gen.clear(); 2925 - gen.swap(alive); 2926 - return freed; 2927 - } 2928 - 2929 - void _auto_collect(){ 2930 - #if !DEBUG_NO_AUTO_GC 2931 - if(_gc_lock_counter > 0) return; 2932 - if(gc_counter < gc_threshold) return; 2933 - gc_counter = 0; 2934 - collect(); 2935 - gc_threshold = gen.size() * 2; 2936 - if(gc_threshold < kMinGCThreshold) gc_threshold = kMinGCThreshold; 2937 - #endif 2938 - } 2939 - 2940 - int collect(){ 2941 - if(_gc_lock_counter > 0) FATAL_ERROR(); 2942 - mark(); 2943 - int freed = sweep(); 2944 - return freed; 2945 - } 2946 - 2947 - void mark(); 2948 - 2949 - ~ManagedHeap(){ 2950 - for(PyObject* obj: _no_gc) obj->~PyObject(), pool64.dealloc(obj); 2951 - for(PyObject* obj: gen) obj->~PyObject(), pool64.dealloc(obj); 2952 - #if DEBUG_GC_STATS 2953 - for(auto& [type, count]: deleted){ 2954 - std::cout << "GC: " << obj_type_name(vm, type) << "=" << count << std::endl; 2955 - } 2956 - #endif 2957 - } 2958 - }; 2959 - 2960 - inline void FuncDecl::_gc_mark() const{ 2961 - code->_gc_mark(); 2962 - for(int i=0; i<kwargs.size(); i++) OBJ_MARK(kwargs[i].value); 2963 - } 2964 - 2965 - } // namespace pkpy 2966 - 2967 - 2968 - namespace pkpy{ 2969 - 2970 - /* Stack manipulation macros */ 2971 - // https://github.com/python/cpython/blob/3.9/Python/ceval.c#L1123 2972 - #define TOP() (s_data.top()) 2973 - #define SECOND() (s_data.second()) 2974 - #define THIRD() (s_data.third()) 2975 - #define PEEK(n) (s_data.peek(n)) 2976 - #define STACK_SHRINK(n) (s_data.shrink(n)) 2977 - #define PUSH(v) (s_data.push(v)) 2978 - #define POP() (s_data.pop()) 2979 - #define POPX() (s_data.popx()) 2980 - #define STACK_VIEW(n) (s_data.view(n)) 2981 - 2982 - typedef Bytes (*ReadFileCwdFunc)(const Str& name); 2983 - inline ReadFileCwdFunc _read_file_cwd = [](const Str& name) { return Bytes(); }; 2984 - inline int set_read_file_cwd(ReadFileCwdFunc func) { _read_file_cwd = func; return 0; } 2985 - 2986 - #define DEF_NATIVE_2(ctype, ptype) \ 2987 - template<> inline ctype py_cast<ctype>(VM* vm, PyObject* obj) { \ 2988 - vm->check_non_tagged_type(obj, vm->ptype); \ 2989 - return OBJ_GET(ctype, obj); \ 2990 - } \ 2991 - template<> inline ctype _py_cast<ctype>(VM* vm, PyObject* obj) { \ 2992 - return OBJ_GET(ctype, obj); \ 2993 - } \ 2994 - template<> inline ctype& py_cast<ctype&>(VM* vm, PyObject* obj) { \ 2995 - vm->check_non_tagged_type(obj, vm->ptype); \ 2996 - return OBJ_GET(ctype, obj); \ 2997 - } \ 2998 - template<> inline ctype& _py_cast<ctype&>(VM* vm, PyObject* obj) { \ 2999 - return OBJ_GET(ctype, obj); \ 3000 - } \ 3001 - inline PyObject* py_var(VM* vm, const ctype& value) { return vm->heap.gcnew(vm->ptype, value);} \ 3002 - inline PyObject* py_var(VM* vm, ctype&& value) { return vm->heap.gcnew(vm->ptype, std::move(value));} 3003 - 3004 - 3005 - class Generator final: public BaseIter { 3006 - Frame frame; 3007 - int state; // 0,1,2 3008 - List s_backup; 3009 - public: 3010 - Generator(VM* vm, Frame&& frame, ArgsView buffer): BaseIter(vm), frame(std::move(frame)), state(0) { 3011 - for(PyObject* obj: buffer) s_backup.push_back(obj); 3012 - } 3013 - 3014 - PyObject* next() override; 3015 - void _gc_mark() const; 3016 - }; 3017 - 3018 - struct PyTypeInfo{ 3019 - PyObject* obj; 3020 - Type base; 3021 - Str name; 3022 - }; 3023 - 3024 - struct FrameId{ 3025 - std::vector<pkpy::Frame>* data; 3026 - int index; 3027 - FrameId(std::vector<pkpy::Frame>* data, int index) : data(data), index(index) {} 3028 - Frame* operator->() const { return &data->operator[](index); } 3029 - }; 3030 - 3031 - typedef void(*PrintFunc)(VM*, const Str&); 3032 - 3033 - class VM { 3034 - VM* vm; // self reference for simplify code 3035 - public: 3036 - ManagedHeap heap; 3037 - ValueStack s_data; 3038 - stack< Frame > callstack; 3039 - std::vector<PyTypeInfo> _all_types; 3040 - void (*_gc_marker_ex)(VM*) = nullptr; 3041 - 3042 - NameDict _modules; // loaded modules 3043 - std::map<StrName, Str> _lazy_modules; // lazy loaded modules 3044 - 3045 - PyObject* None; 3046 - PyObject* True; 3047 - PyObject* False; 3048 - PyObject* Ellipsis; 3049 - PyObject* builtins; // builtins module 3050 - PyObject* StopIteration; 3051 - PyObject* _main; // __main__ module 3052 - 3053 - PrintFunc _stdout; 3054 - PrintFunc _stderr; 3055 - 3056 - bool _initialized; 3057 - 3058 - // for quick access 3059 - Type tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str; 3060 - Type tp_list, tp_tuple; 3061 - Type tp_function, tp_native_func, tp_iterator, tp_bound_method; 3062 - Type tp_slice, tp_range, tp_module; 3063 - Type tp_super, tp_exception, tp_bytes, tp_mappingproxy; 3064 - 3065 - const bool enable_os; 3066 - 3067 - VM(bool enable_os=true) : heap(this), enable_os(enable_os) { 3068 - this->vm = this; 3069 - _stdout = [](VM* vm, const Str& s) { std::cout << s; }; 3070 - _stderr = [](VM* vm, const Str& s) { std::cerr << s; }; 3071 - callstack.reserve(8); 3072 - _initialized = false; 3073 - init_builtin_types(); 3074 - _initialized = true; 3075 - } 3076 - 3077 - FrameId top_frame() { 3078 - #if DEBUG_EXTRA_CHECK 3079 - if(callstack.empty()) FATAL_ERROR(); 3080 - #endif 3081 - return FrameId(&callstack.data(), callstack.size()-1); 3082 - } 3083 - 3084 - PyObject* asStr(PyObject* obj){ 3085 - PyObject* self; 3086 - PyObject* f = get_unbound_method(obj, __str__, &self, false); 3087 - if(self != PY_NULL) return call_method(self, f); 3088 - return asRepr(obj); 3089 - } 3090 - 3091 - PyObject* asIter(PyObject* obj){ 3092 - if(is_type(obj, tp_iterator)) return obj; 3093 - PyObject* self; 3094 - PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false); 3095 - if(self != PY_NULL) return call_method(self, iter_f); 3096 - TypeError(OBJ_NAME(_t(obj)).escape() + " object is not iterable"); 3097 - return nullptr; 3098 - } 3099 - 3100 - PyObject* asList(PyObject* it){ 3101 - if(is_non_tagged_type(it, tp_list)) return it; 3102 - return call(_t(tp_list), it); 3103 - } 3104 - 3105 - PyObject* find_name_in_mro(PyObject* cls, StrName name){ 3106 - PyObject* val; 3107 - do{ 3108 - val = cls->attr().try_get(name); 3109 - if(val != nullptr) return val; 3110 - Type cls_t = OBJ_GET(Type, cls); 3111 - Type base = _all_types[cls_t].base; 3112 - if(base.index == -1) break; 3113 - cls = _all_types[base].obj; 3114 - }while(true); 3115 - return nullptr; 3116 - } 3117 - 3118 - bool isinstance(PyObject* obj, Type cls_t){ 3119 - Type obj_t = OBJ_GET(Type, _t(obj)); 3120 - do{ 3121 - if(obj_t == cls_t) return true; 3122 - Type base = _all_types[obj_t].base; 3123 - if(base.index == -1) break; 3124 - obj_t = base; 3125 - }while(true); 3126 - return false; 3127 - } 3128 - 3129 - PyObject* exec(Str source, Str filename, CompileMode mode, PyObject* _module=nullptr){ 3130 - if(_module == nullptr) _module = _main; 3131 - try { 3132 - CodeObject_ code = compile(source, filename, mode); 3133 - #if DEBUG_DIS_EXEC 3134 - if(_module == _main) std::cout << disassemble(code) << '\n'; 3135 - #endif 3136 - return _exec(code, _module); 3137 - }catch (const Exception& e){ 3138 - _stderr(this, e.summary() + "\n"); 3139 - } 3140 - #if !DEBUG_FULL_EXCEPTION 3141 - catch (const std::exception& e) { 3142 - _stderr(this, "An std::exception occurred! It could be a bug.\n"); 3143 - _stderr(this, e.what()); 3144 - _stderr(this, "\n"); 3145 - } 3146 - #endif 3147 - callstack.clear(); 3148 - s_data.clear(); 3149 - return nullptr; 3150 - } 3151 - 3152 - template<typename ...Args> 3153 - PyObject* _exec(Args&&... args){ 3154 - callstack.emplace(&s_data, s_data._sp, std::forward<Args>(args)...); 3155 - return _run_top_frame(); 3156 - } 3157 - 3158 - void _pop_frame(){ 3159 - Frame* frame = &callstack.top(); 3160 - s_data.reset(frame->_sp_base); 3161 - callstack.pop(); 3162 - } 3163 - 3164 - void _push_varargs(){ } 3165 - void _push_varargs(PyObject* _0){ PUSH(_0); } 3166 - void _push_varargs(PyObject* _0, PyObject* _1){ PUSH(_0); PUSH(_1); } 3167 - void _push_varargs(PyObject* _0, PyObject* _1, PyObject* _2){ PUSH(_0); PUSH(_1); PUSH(_2); } 3168 - void _push_varargs(PyObject* _0, PyObject* _1, PyObject* _2, PyObject* _3){ PUSH(_0); PUSH(_1); PUSH(_2); PUSH(_3); } 3169 - 3170 - template<typename... Args> 3171 - PyObject* call(PyObject* callable, Args&&... args){ 3172 - PUSH(callable); 3173 - PUSH(PY_NULL); 3174 - _push_varargs(args...); 3175 - return vectorcall(sizeof...(args)); 3176 - } 3177 - 3178 - template<typename... Args> 3179 - PyObject* call_method(PyObject* self, PyObject* callable, Args&&... args){ 3180 - PUSH(callable); 3181 - PUSH(self); 3182 - _push_varargs(args...); 3183 - return vectorcall(sizeof...(args)); 3184 - } 3185 - 3186 - template<typename... Args> 3187 - PyObject* call_method(PyObject* self, StrName name, Args&&... args){ 3188 - PyObject* callable = get_unbound_method(self, name, &self); 3189 - return call_method(self, callable, args...); 3190 - } 3191 - 3192 - PyObject* property(NativeFuncC fget, NativeFuncC fset=nullptr){ 3193 - PyObject* p = builtins->attr("property"); 3194 - PyObject* _0 = heap.gcnew(tp_native_func, NativeFunc(fget, 1, false)); 3195 - PyObject* _1 = vm->None; 3196 - if(fset != nullptr) _1 = heap.gcnew(tp_native_func, NativeFunc(fset, 2, false)); 3197 - return call(p, _0, _1); 3198 - } 3199 - 3200 - PyObject* new_type_object(PyObject* mod, StrName name, Type base){ 3201 - PyObject* obj = heap._new<Type>(tp_type, _all_types.size()); 3202 - PyTypeInfo info{ 3203 - obj, 3204 - base, 3205 - (mod!=nullptr && mod!=builtins) ? Str(OBJ_NAME(mod)+"."+name.sv()): name.sv() 3206 - }; 3207 - if(mod != nullptr) mod->attr().set(name, obj); 3208 - _all_types.push_back(info); 3209 - return obj; 3210 - } 3211 - 3212 - Type _new_type_object(StrName name, Type base=0) { 3213 - PyObject* obj = new_type_object(nullptr, name, base); 3214 - return OBJ_GET(Type, obj); 3215 - } 3216 - 3217 - PyObject* _find_type(const Str& type){ 3218 - PyObject* obj = builtins->attr().try_get(type); 3219 - if(obj == nullptr){ 3220 - for(auto& t: _all_types) if(t.name == type) return t.obj; 3221 - throw std::runtime_error(fmt("type not found: ", type)); 3222 - } 3223 - return obj; 3224 - } 3225 - 3226 - template<int ARGC> 3227 - void bind_func(Str type, Str name, NativeFuncC fn) { 3228 - bind_func<ARGC>(_find_type(type), name, fn); 3229 - } 3230 - 3231 - template<int ARGC> 3232 - void bind_method(Str type, Str name, NativeFuncC fn) { 3233 - bind_method<ARGC>(_find_type(type), name, fn); 3234 - } 3235 - 3236 - template<int ARGC, typename... Args> 3237 - void bind_static_method(Args&&... args) { 3238 - bind_func<ARGC>(std::forward<Args>(args)...); 3239 - } 3240 - 3241 - template<int ARGC> 3242 - void bind_builtin_func(Str name, NativeFuncC fn) { 3243 - bind_func<ARGC>(builtins, name, fn); 3244 - } 3245 - 3246 - int normalized_index(int index, int size){ 3247 - if(index < 0) index += size; 3248 - if(index < 0 || index >= size){ 3249 - IndexError(std::to_string(index) + " not in [0, " + std::to_string(size) + ")"); 3250 - } 3251 - return index; 3252 - } 3253 - 3254 - template<typename P> 3255 - PyObject* PyIter(P&& value) { 3256 - static_assert(std::is_base_of_v<BaseIter, std::decay_t<P>>); 3257 - return heap.gcnew<P>(tp_iterator, std::forward<P>(value)); 3258 - } 3259 - 3260 - PyObject* PyIterNext(PyObject* obj){ 3261 - if(is_non_tagged_type(obj, tp_iterator)){ 3262 - BaseIter* iter = static_cast<BaseIter*>(obj->value()); 3263 - return iter->next(); 3264 - } 3265 - return call_method(obj, __next__); 3266 - } 3267 - 3268 - /***** Error Reporter *****/ 3269 - void _error(StrName name, const Str& msg){ 3270 - _error(Exception(name, msg)); 3271 - } 3272 - 3273 - void _raise(){ 3274 - bool ok = top_frame()->jump_to_exception_handler(); 3275 - if(ok) throw HandledException(); 3276 - else throw UnhandledException(); 3277 - } 3278 - 3279 - void StackOverflowError() { _error("StackOverflowError", ""); } 3280 - void IOError(const Str& msg) { _error("IOError", msg); } 3281 - void NotImplementedError(){ _error("NotImplementedError", ""); } 3282 - void TypeError(const Str& msg){ _error("TypeError", msg); } 3283 - void ZeroDivisionError(){ _error("ZeroDivisionError", "division by zero"); } 3284 - void IndexError(const Str& msg){ _error("IndexError", msg); } 3285 - void ValueError(const Str& msg){ _error("ValueError", msg); } 3286 - void NameError(StrName name){ _error("NameError", fmt("name ", name.escape() + " is not defined")); } 3287 - 3288 - void AttributeError(PyObject* obj, StrName name){ 3289 - // OBJ_NAME calls getattr, which may lead to a infinite recursion 3290 - _error("AttributeError", fmt("type ", OBJ_NAME(_t(obj)).escape(), " has no attribute ", name.escape())); 3291 - } 3292 - 3293 - void AttributeError(Str msg){ _error("AttributeError", msg); } 3294 - 3295 - void check_type(PyObject* obj, Type type){ 3296 - if(is_type(obj, type)) return; 3297 - TypeError("expected " + OBJ_NAME(_t(type)).escape() + ", but got " + OBJ_NAME(_t(obj)).escape()); 3298 - } 3299 - 3300 - void check_non_tagged_type(PyObject* obj, Type type){ 3301 - if(is_non_tagged_type(obj, type)) return; 3302 - TypeError("expected " + OBJ_NAME(_t(type)).escape() + ", but got " + OBJ_NAME(_t(obj)).escape()); 3303 - } 3304 - 3305 - void check_int(PyObject* obj){ 3306 - if(is_int(obj)) return; 3307 - check_type(obj, tp_int); 3308 - } 3309 - 3310 - void check_float(PyObject* obj){ 3311 - if(is_float(obj)) return; 3312 - check_type(obj, tp_float); 3313 - } 3314 - 3315 - PyObject* _t(Type t){ 3316 - return _all_types[t.index].obj; 3317 - } 3318 - 3319 - PyObject* _t(PyObject* obj){ 3320 - if(is_int(obj)) return _t(tp_int); 3321 - if(is_float(obj)) return _t(tp_float); 3322 - return _all_types[OBJ_GET(Type, _t(obj->type)).index].obj; 3323 - } 3324 - 3325 - ~VM() { 3326 - callstack.clear(); 3327 - s_data.clear(); 3328 - _all_types.clear(); 3329 - _modules.clear(); 3330 - _lazy_modules.clear(); 3331 - } 3332 - 3333 - void _log_s_data(const char* title = nullptr); 3334 - PyObject* vectorcall(int ARGC, int KWARGC=0, bool op_call=false); 3335 - CodeObject_ compile(Str source, Str filename, CompileMode mode, bool unknown_global_scope=false); 3336 - PyObject* num_negated(PyObject* obj); 3337 - f64 num_to_float(PyObject* obj); 3338 - bool asBool(PyObject* obj); 3339 - i64 hash(PyObject* obj); 3340 - PyObject* asRepr(PyObject* obj); 3341 - PyObject* new_module(StrName name); 3342 - Str disassemble(CodeObject_ co); 3343 - void init_builtin_types(); 3344 - PyObject* _py_call(PyObject** sp_base, PyObject* callable, ArgsView args, ArgsView kwargs); 3345 - PyObject* getattr(PyObject* obj, StrName name, bool throw_err=true); 3346 - PyObject* get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err=true, bool fallback=false); 3347 - void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step); 3348 - PyObject* format(Str, PyObject*); 3349 - void setattr(PyObject* obj, StrName name, PyObject* value); 3350 - template<int ARGC> 3351 - void bind_method(PyObject*, Str, NativeFuncC); 3352 - template<int ARGC> 3353 - void bind_func(PyObject*, Str, NativeFuncC); 3354 - void _error(Exception); 3355 - PyObject* _run_top_frame(); 3356 - void post_init(); 3357 - }; 3358 - 3359 - inline PyObject* NativeFunc::operator()(VM* vm, ArgsView args) const{ 3360 - int args_size = args.size() - (int)method; // remove self 3361 - if(argc != -1 && args_size != argc) { 3362 - vm->TypeError(fmt("expected ", argc, " arguments, but got ", args_size)); 3363 - } 3364 - return f(vm, args); 3365 - } 3366 - 3367 - inline void CodeObject::optimize(VM* vm){ 3368 - // uint32_t base_n = (uint32_t)(names.size() / kLocalsLoadFactor + 0.5); 3369 - // perfect_locals_capacity = std::max(find_next_capacity(base_n), NameDict::__Capacity); 3370 - // perfect_hash_seed = find_perfect_hash_seed(perfect_locals_capacity, names); 3371 - } 3372 - 3373 - DEF_NATIVE_2(Str, tp_str) 3374 - DEF_NATIVE_2(List, tp_list) 3375 - DEF_NATIVE_2(Tuple, tp_tuple) 3376 - DEF_NATIVE_2(Function, tp_function) 3377 - DEF_NATIVE_2(NativeFunc, tp_native_func) 3378 - DEF_NATIVE_2(BoundMethod, tp_bound_method) 3379 - DEF_NATIVE_2(Range, tp_range) 3380 - DEF_NATIVE_2(Slice, tp_slice) 3381 - DEF_NATIVE_2(Exception, tp_exception) 3382 - DEF_NATIVE_2(Bytes, tp_bytes) 3383 - DEF_NATIVE_2(MappingProxy, tp_mappingproxy) 3384 - 3385 - #define PY_CAST_INT(T) \ 3386 - template<> inline T py_cast<T>(VM* vm, PyObject* obj){ \ 3387 - vm->check_int(obj); \ 3388 - return (T)(BITS(obj) >> 2); \ 3389 - } \ 3390 - template<> inline T _py_cast<T>(VM* vm, PyObject* obj){ \ 3391 - return (T)(BITS(obj) >> 2); \ 3392 - } 3393 - 3394 - PY_CAST_INT(char) 3395 - PY_CAST_INT(short) 3396 - PY_CAST_INT(int) 3397 - PY_CAST_INT(long) 3398 - PY_CAST_INT(long long) 3399 - PY_CAST_INT(unsigned char) 3400 - PY_CAST_INT(unsigned short) 3401 - PY_CAST_INT(unsigned int) 3402 - PY_CAST_INT(unsigned long) 3403 - PY_CAST_INT(unsigned long long) 3404 - 3405 - 3406 - template<> inline float py_cast<float>(VM* vm, PyObject* obj){ 3407 - vm->check_float(obj); 3408 - i64 bits = BITS(obj); 3409 - bits = (bits >> 2) << 2; 3410 - return BitsCvt(bits)._float; 3411 - } 3412 - template<> inline float _py_cast<float>(VM* vm, PyObject* obj){ 3413 - i64 bits = BITS(obj); 3414 - bits = (bits >> 2) << 2; 3415 - return BitsCvt(bits)._float; 3416 - } 3417 - template<> inline double py_cast<double>(VM* vm, PyObject* obj){ 3418 - vm->check_float(obj); 3419 - i64 bits = BITS(obj); 3420 - bits = (bits >> 2) << 2; 3421 - return BitsCvt(bits)._float; 3422 - } 3423 - template<> inline double _py_cast<double>(VM* vm, PyObject* obj){ 3424 - i64 bits = BITS(obj); 3425 - bits = (bits >> 2) << 2; 3426 - return BitsCvt(bits)._float; 3427 - } 3428 - 3429 - 3430 - #define PY_VAR_INT(T) \ 3431 - inline PyObject* py_var(VM* vm, T _val){ \ 3432 - i64 val = static_cast<i64>(_val); \ 3433 - if(((val << 2) >> 2) != val){ \ 3434 - vm->_error("OverflowError", std::to_string(val) + " is out of range"); \ 3435 - } \ 3436 - val = (val << 2) | 0b01; \ 3437 - return reinterpret_cast<PyObject*>(val); \ 3438 - } 3439 - 3440 - PY_VAR_INT(char) 3441 - PY_VAR_INT(short) 3442 - PY_VAR_INT(int) 3443 - PY_VAR_INT(long) 3444 - PY_VAR_INT(long long) 3445 - PY_VAR_INT(unsigned char) 3446 - PY_VAR_INT(unsigned short) 3447 - PY_VAR_INT(unsigned int) 3448 - PY_VAR_INT(unsigned long) 3449 - PY_VAR_INT(unsigned long long) 3450 - 3451 - #define PY_VAR_FLOAT(T) \ 3452 - inline PyObject* py_var(VM* vm, T _val){ \ 3453 - f64 val = static_cast<f64>(_val); \ 3454 - i64 bits = BitsCvt(val)._int; \ 3455 - bits = (bits >> 2) << 2; \ 3456 - bits |= 0b10; \ 3457 - return reinterpret_cast<PyObject*>(bits); \ 3458 - } 3459 - 3460 - PY_VAR_FLOAT(float) 3461 - PY_VAR_FLOAT(double) 3462 - 3463 - inline PyObject* py_var(VM* vm, bool val){ 3464 - return val ? vm->True : vm->False; 3465 - } 3466 - 3467 - template<> inline bool py_cast<bool>(VM* vm, PyObject* obj){ 3468 - vm->check_non_tagged_type(obj, vm->tp_bool); 3469 - return obj == vm->True; 3470 - } 3471 - template<> inline bool _py_cast<bool>(VM* vm, PyObject* obj){ 3472 - return obj == vm->True; 3473 - } 3474 - 3475 - inline PyObject* py_var(VM* vm, const char val[]){ 3476 - return VAR(Str(val)); 3477 - } 3478 - 3479 - inline PyObject* py_var(VM* vm, std::string val){ 3480 - return VAR(Str(std::move(val))); 3481 - } 3482 - 3483 - inline PyObject* py_var(VM* vm, std::string_view val){ 3484 - return VAR(Str(val)); 3485 - } 3486 - 3487 - template<typename T> 3488 - void _check_py_class(VM* vm, PyObject* obj){ 3489 - vm->check_non_tagged_type(obj, T::_type(vm)); 3490 - } 3491 - 3492 - inline PyObject* VM::num_negated(PyObject* obj){ 3493 - if (is_int(obj)){ 3494 - return VAR(-CAST(i64, obj)); 3495 - }else if(is_float(obj)){ 3496 - return VAR(-CAST(f64, obj)); 3497 - } 3498 - TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape()); 3499 - return nullptr; 3500 - } 3501 - 3502 - inline f64 VM::num_to_float(PyObject* obj){ 3503 - if(is_float(obj)){ 3504 - return CAST(f64, obj); 3505 - } else if (is_int(obj)){ 3506 - return (f64)CAST(i64, obj); 3507 - } 3508 - TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape()); 3509 - return 0; 3510 - } 3511 - 3512 - inline bool VM::asBool(PyObject* obj){ 3513 - if(is_non_tagged_type(obj, tp_bool)) return obj == True; 3514 - if(obj == None) return false; 3515 - if(is_int(obj)) return CAST(i64, obj) != 0; 3516 - if(is_float(obj)) return CAST(f64, obj) != 0.0; 3517 - PyObject* self; 3518 - PyObject* len_f = get_unbound_method(obj, __len__, &self, false); 3519 - if(self != PY_NULL){ 3520 - PyObject* ret = call_method(self, len_f); 3521 - return CAST(i64, ret) > 0; 3522 - } 3523 - return true; 3524 - } 3525 - 3526 - inline void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step){ 3527 - auto clip = [](int value, int min, int max){ 3528 - if(value < min) return min; 3529 - if(value > max) return max; 3530 - return value; 3531 - }; 3532 - if(s.step == None) step = 1; 3533 - else step = CAST(int, s.step); 3534 - if(step == 0) ValueError("slice step cannot be zero"); 3535 - if(step > 0){ 3536 - if(s.start == None){ 3537 - start = 0; 3538 - }else{ 3539 - start = CAST(int, s.start); 3540 - if(start < 0) start += length; 3541 - start = clip(start, 0, length); 3542 - } 3543 - if(s.stop == None){ 3544 - stop = length; 3545 - }else{ 3546 - stop = CAST(int, s.stop); 3547 - if(stop < 0) stop += length; 3548 - stop = clip(stop, 0, length); 3549 - } 3550 - }else{ 3551 - if(s.start == None){ 3552 - start = length - 1; 3553 - }else{ 3554 - start = CAST(int, s.start); 3555 - if(start < 0) start += length; 3556 - start = clip(start, -1, length - 1); 3557 - } 3558 - if(s.stop == None){ 3559 - stop = -1; 3560 - }else{ 3561 - stop = CAST(int, s.stop); 3562 - if(stop < 0) stop += length; 3563 - stop = clip(stop, -1, length - 1); 3564 - } 3565 - } 3566 - } 3567 - 3568 - inline i64 VM::hash(PyObject* obj){ 3569 - if (is_non_tagged_type(obj, tp_str)) return CAST(Str&, obj).hash(); 3570 - if (is_int(obj)) return CAST(i64, obj); 3571 - if (is_non_tagged_type(obj, tp_tuple)) { 3572 - i64 x = 1000003; 3573 - const Tuple& items = CAST(Tuple&, obj); 3574 - for (int i=0; i<items.size(); i++) { 3575 - i64 y = hash(items[i]); 3576 - // recommended by Github Copilot 3577 - x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); 3578 - } 3579 - return x; 3580 - } 3581 - if (is_non_tagged_type(obj, tp_type)) return BITS(obj); 3582 - if (is_non_tagged_type(obj, tp_iterator)) return BITS(obj); 3583 - if (is_non_tagged_type(obj, tp_bool)) return _CAST(bool, obj) ? 1 : 0; 3584 - if (is_float(obj)){ 3585 - f64 val = CAST(f64, obj); 3586 - return (i64)std::hash<f64>()(val); 3587 - } 3588 - TypeError("unhashable type: " + OBJ_NAME(_t(obj)).escape()); 3589 - return 0; 3590 - } 3591 - 3592 - inline PyObject* VM::asRepr(PyObject* obj){ 3593 - return call_method(obj, __repr__); 3594 - } 3595 - 3596 - inline PyObject* VM::format(Str spec, PyObject* obj){ 3597 - if(spec.empty()) return asStr(obj); 3598 - char type; 3599 - switch(spec.end()[-1]){ 3600 - case 'f': case 'd': case 's': 3601 - type = spec.end()[-1]; 3602 - spec = spec.substr(0, spec.length() - 1); 3603 - break; 3604 - default: type = ' '; break; 3605 - } 3606 - 3607 - char pad_c = ' '; 3608 - if(spec[0] == '0'){ 3609 - pad_c = '0'; 3610 - spec = spec.substr(1); 3611 - } 3612 - char align; 3613 - if(spec[0] == '>'){ 3614 - align = '>'; 3615 - spec = spec.substr(1); 3616 - }else if(spec[0] == '<'){ 3617 - align = '<'; 3618 - spec = spec.substr(1); 3619 - }else{ 3620 - if(is_int(obj) || is_float(obj)) align = '>'; 3621 - else align = '<'; 3622 - } 3623 - 3624 - int dot = spec.index("."); 3625 - int width, precision; 3626 - try{ 3627 - if(dot >= 0){ 3628 - width = Number::stoi(spec.substr(0, dot).str()); 3629 - precision = Number::stoi(spec.substr(dot+1).str()); 3630 - }else{ 3631 - width = Number::stoi(spec.str()); 3632 - precision = -1; 3633 - } 3634 - }catch(...){ 3635 - ValueError("invalid format specifer"); 3636 - } 3637 - 3638 - if(type != 'f' && dot >= 0) ValueError("precision not allowed in the format specifier"); 3639 - Str ret; 3640 - if(type == 'f'){ 3641 - f64 val = num_to_float(obj); 3642 - if(precision < 0) precision = 6; 3643 - std::stringstream ss; 3644 - ss << std::fixed << std::setprecision(precision) << val; 3645 - ret = ss.str(); 3646 - }else if(type == 'd'){ 3647 - ret = std::to_string(CAST(i64, obj)); 3648 - }else if(type == 's'){ 3649 - ret = CAST(Str&, obj); 3650 - }else{ 3651 - ret = CAST(Str&, asStr(obj)); 3652 - } 3653 - if(width > ret.length()){ 3654 - int pad = width - ret.length(); 3655 - std::string padding(pad, pad_c); 3656 - if(align == '>') ret = padding.c_str() + ret; 3657 - else ret = ret + padding.c_str(); 3658 - } 3659 - return VAR(ret); 3660 - } 3661 - 3662 - inline PyObject* VM::new_module(StrName name) { 3663 - PyObject* obj = heap._new<DummyModule>(tp_module, DummyModule()); 3664 - obj->attr().set(__name__, VAR(name.sv())); 3665 - // we do not allow override in order to avoid memory leak 3666 - // it is because Module objects are not garbage collected 3667 - if(_modules.contains(name)) FATAL_ERROR(); 3668 - _modules.set(name, obj); 3669 - return obj; 3670 - } 3671 - 3672 - inline std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){ 3673 - std::string argStr = byte.arg == -1 ? "" : std::to_string(byte.arg); 3674 - switch(byte.op){ 3675 - case OP_LOAD_CONST: 3676 - if(vm != nullptr){ 3677 - argStr += fmt(" (", CAST(Str, vm->asRepr(co->consts[byte.arg])), ")"); 3678 - } 3679 - break; 3680 - case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL: 3681 - case OP_LOAD_ATTR: case OP_LOAD_METHOD: case OP_STORE_ATTR: case OP_DELETE_ATTR: 3682 - case OP_IMPORT_NAME: case OP_BEGIN_CLASS: 3683 - case OP_DELETE_GLOBAL: 3684 - argStr += fmt(" (", StrName(byte.arg).sv(), ")"); 3685 - break; 3686 - case OP_LOAD_FAST: case OP_STORE_FAST: case OP_DELETE_FAST: 3687 - argStr += fmt(" (", co->varnames[byte.arg].sv(), ")"); 3688 - break; 3689 - case OP_BINARY_OP: 3690 - argStr += fmt(" (", BINARY_SPECIAL_METHODS[byte.arg], ")"); 3691 - break; 3692 - case OP_LOAD_FUNCTION: 3693 - argStr += fmt(" (", co->func_decls[byte.arg]->code->name, ")"); 3694 - break; 3695 - } 3696 - return argStr; 3697 - } 3698 - 3699 - inline Str VM::disassemble(CodeObject_ co){ 3700 - auto pad = [](const Str& s, const int n){ 3701 - if(s.length() >= n) return s.substr(0, n); 3702 - return s + std::string(n - s.length(), ' '); 3703 - }; 3704 - 3705 - std::vector<int> jumpTargets; 3706 - for(auto byte : co->codes){ 3707 - if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE){ 3708 - jumpTargets.push_back(byte.arg); 3709 - } 3710 - } 3711 - std::stringstream ss; 3712 - int prev_line = -1; 3713 - for(int i=0; i<co->codes.size(); i++){ 3714 - const Bytecode& byte = co->codes[i]; 3715 - Str line = std::to_string(co->lines[i]); 3716 - if(co->lines[i] == prev_line) line = ""; 3717 - else{ 3718 - if(prev_line != -1) ss << "\n"; 3719 - prev_line = co->lines[i]; 3720 - } 3721 - 3722 - std::string pointer; 3723 - if(std::find(jumpTargets.begin(), jumpTargets.end(), i) != jumpTargets.end()){ 3724 - pointer = "-> "; 3725 - }else{ 3726 - pointer = " "; 3727 - } 3728 - ss << pad(line, 8) << pointer << pad(std::to_string(i), 3); 3729 - ss << " " << pad(OP_NAMES[byte.op], 20) << " "; 3730 - // ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5); 3731 - std::string argStr = _opcode_argstr(this, byte, co.get()); 3732 - ss << pad(argStr, 40); // may overflow 3733 - ss << co->blocks[byte.block].type; 3734 - if(i != co->codes.size() - 1) ss << '\n'; 3735 - } 3736 - 3737 - for(auto& decl: co->func_decls){ 3738 - ss << "\n\n" << "Disassembly of " << decl->code->name << ":\n"; 3739 - ss << disassemble(decl->code); 3740 - } 3741 - ss << "\n"; 3742 - return Str(ss.str()); 3743 - } 3744 - 3745 - inline void VM::_log_s_data(const char* title) { 3746 - if(!_initialized) return; 3747 - if(callstack.empty()) return; 3748 - std::stringstream ss; 3749 - if(title) ss << title << " | "; 3750 - std::map<PyObject**, int> sp_bases; 3751 - for(Frame& f: callstack.data()){ 3752 - if(f._sp_base == nullptr) FATAL_ERROR(); 3753 - sp_bases[f._sp_base] += 1; 3754 - } 3755 - FrameId frame = top_frame(); 3756 - int line = frame->co->lines[frame->_ip]; 3757 - ss << frame->co->name << ":" << line << " ["; 3758 - for(PyObject** p=s_data.begin(); p!=s_data.end(); p++){ 3759 - ss << std::string(sp_bases[p], '|'); 3760 - if(sp_bases[p] > 0) ss << " "; 3761 - PyObject* obj = *p; 3762 - if(obj == nullptr) ss << "(nil)"; 3763 - else if(obj == PY_BEGIN_CALL) ss << "BEGIN_CALL"; 3764 - else if(obj == PY_NULL) ss << "NULL"; 3765 - else if(is_int(obj)) ss << CAST(i64, obj); 3766 - else if(is_float(obj)) ss << CAST(f64, obj); 3767 - else if(is_type(obj, tp_str)) ss << CAST(Str, obj).escape(); 3768 - else if(obj == None) ss << "None"; 3769 - else if(obj == True) ss << "True"; 3770 - else if(obj == False) ss << "False"; 3771 - else if(is_type(obj, tp_function)){ 3772 - auto& f = CAST(Function&, obj); 3773 - ss << f.decl->code->name << "(...)"; 3774 - } else if(is_type(obj, tp_type)){ 3775 - Type t = OBJ_GET(Type, obj); 3776 - ss << "<class " + _all_types[t].name.escape() + ">"; 3777 - } else if(is_type(obj, tp_list)){ 3778 - auto& t = CAST(List&, obj); 3779 - ss << "list(size=" << t.size() << ")"; 3780 - } else if(is_type(obj, tp_tuple)){ 3781 - auto& t = CAST(Tuple&, obj); 3782 - ss << "tuple(size=" << t.size() << ")"; 3783 - } else ss << "(" << obj_type_name(this, obj->type) << ")"; 3784 - ss << ", "; 3785 - } 3786 - std::string output = ss.str(); 3787 - if(!s_data.empty()) { 3788 - output.pop_back(); output.pop_back(); 3789 - } 3790 - output.push_back(']'); 3791 - Bytecode byte = frame->co->codes[frame->_ip]; 3792 - std::cout << output << " " << OP_NAMES[byte.op] << " " << _opcode_argstr(nullptr, byte, frame->co) << std::endl; 3793 - } 3794 - 3795 - inline void VM::init_builtin_types(){ 3796 - _all_types.push_back({heap._new<Type>(Type(1), Type(0)), -1, "object"}); 3797 - _all_types.push_back({heap._new<Type>(Type(1), Type(1)), 0, "type"}); 3798 - tp_object = 0; tp_type = 1; 3799 - 3800 - tp_int = _new_type_object("int"); 3801 - tp_float = _new_type_object("float"); 3802 - if(tp_int.index != kTpIntIndex || tp_float.index != kTpFloatIndex) FATAL_ERROR(); 3803 - 3804 - tp_bool = _new_type_object("bool"); 3805 - tp_str = _new_type_object("str"); 3806 - tp_list = _new_type_object("list"); 3807 - tp_tuple = _new_type_object("tuple"); 3808 - tp_slice = _new_type_object("slice"); 3809 - tp_range = _new_type_object("range"); 3810 - tp_module = _new_type_object("module"); 3811 - tp_function = _new_type_object("function"); 3812 - tp_native_func = _new_type_object("native_func"); 3813 - tp_iterator = _new_type_object("iterator"); 3814 - tp_bound_method = _new_type_object("bound_method"); 3815 - tp_super = _new_type_object("super"); 3816 - tp_exception = _new_type_object("Exception"); 3817 - tp_bytes = _new_type_object("bytes"); 3818 - tp_mappingproxy = _new_type_object("mappingproxy"); 3819 - 3820 - this->None = heap._new<Dummy>(_new_type_object("NoneType"), {}); 3821 - this->Ellipsis = heap._new<Dummy>(_new_type_object("ellipsis"), {}); 3822 - this->True = heap._new<Dummy>(tp_bool, {}); 3823 - this->False = heap._new<Dummy>(tp_bool, {}); 3824 - this->StopIteration = heap._new<Dummy>(_new_type_object("StopIterationType"), {}); 3825 - 3826 - this->builtins = new_module("builtins"); 3827 - this->_main = new_module("__main__"); 3828 - 3829 - // setup public types 3830 - builtins->attr().set("type", _t(tp_type)); 3831 - builtins->attr().set("object", _t(tp_object)); 3832 - builtins->attr().set("bool", _t(tp_bool)); 3833 - builtins->attr().set("int", _t(tp_int)); 3834 - builtins->attr().set("float", _t(tp_float)); 3835 - builtins->attr().set("str", _t(tp_str)); 3836 - builtins->attr().set("list", _t(tp_list)); 3837 - builtins->attr().set("tuple", _t(tp_tuple)); 3838 - builtins->attr().set("range", _t(tp_range)); 3839 - builtins->attr().set("bytes", _t(tp_bytes)); 3840 - builtins->attr().set("StopIteration", StopIteration); 3841 - builtins->attr().set("slice", _t(tp_slice)); 3842 - 3843 - post_init(); 3844 - for(int i=0; i<_all_types.size(); i++){ 3845 - _all_types[i].obj->attr()._try_perfect_rehash(); 3846 - } 3847 - for(auto [k, v]: _modules.items()) v->attr()._try_perfect_rehash(); 3848 - } 3849 - 3850 - inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ 3851 - bool is_varargs = ARGC == 0xFFFF; 3852 - PyObject** p0; 3853 - PyObject** p1 = s_data._sp - KWARGC*2; 3854 - if(is_varargs){ 3855 - p0 = p1 - 1; 3856 - while(*p0 != PY_BEGIN_CALL) p0--; 3857 - // [BEGIN_CALL, callable, <self>, args..., kwargs...] 3858 - // ^p0 ^p1 ^_sp 3859 - ARGC = p1 - (p0 + 3); 3860 - }else{ 3861 - p0 = p1 - ARGC - 2 - (int)is_varargs; 3862 - // [callable, <self>, args..., kwargs...] 3863 - // ^p0 ^p1 ^_sp 3864 - } 3865 - PyObject* callable = p1[-(ARGC + 2)]; 3866 - bool method_call = p1[-(ARGC + 1)] != PY_NULL; 3867 - 3868 - 3869 - // handle boundmethod, do a patch 3870 - if(is_non_tagged_type(callable, tp_bound_method)){ 3871 - if(method_call) FATAL_ERROR(); 3872 - auto& bm = CAST(BoundMethod&, callable); 3873 - callable = bm.func; // get unbound method 3874 - p1[-(ARGC + 2)] = bm.func; 3875 - p1[-(ARGC + 1)] = bm.self; 3876 - method_call = true; 3877 - // [unbound, self, args..., kwargs...] 3878 - } 3879 - 3880 - ArgsView args(p1 - ARGC - int(method_call), p1); 3881 - 3882 - if(is_non_tagged_type(callable, tp_native_func)){ 3883 - const auto& f = OBJ_GET(NativeFunc, callable); 3884 - if(KWARGC != 0) TypeError("native_func does not accept keyword arguments"); 3885 - PyObject* ret = f(this, args); 3886 - s_data.reset(p0); 3887 - return ret; 3888 - } 3889 - 3890 - ArgsView kwargs(p1, s_data._sp); 3891 - 3892 - if(is_non_tagged_type(callable, tp_function)){ 3893 - // ret is nullptr or a generator 3894 - PyObject* ret = _py_call(p0, callable, args, kwargs); 3895 - // stack resetting is handled by _py_call 3896 - if(ret != nullptr) return ret; 3897 - if(op_call) return PY_OP_CALL; 3898 - return _run_top_frame(); 3899 - } 3900 - 3901 - if(is_non_tagged_type(callable, tp_type)){ 3902 - if(method_call) FATAL_ERROR(); 3903 - // [type, NULL, args..., kwargs...] 3904 - 3905 - // TODO: derived __new__ ? 3906 - PyObject* new_f = callable->attr().try_get(__new__); 3907 - PyObject* obj; 3908 - if(new_f != nullptr){ 3909 - PUSH(new_f); 3910 - PUSH(PY_NULL); 3911 - for(PyObject* obj: args) PUSH(obj); 3912 - for(PyObject* obj: kwargs) PUSH(obj); 3913 - obj = vectorcall(ARGC, KWARGC); 3914 - if(!isinstance(obj, OBJ_GET(Type, callable))) return obj; 3915 - }else{ 3916 - obj = heap.gcnew<DummyInstance>(OBJ_GET(Type, callable), {}); 3917 - } 3918 - PyObject* self; 3919 - callable = get_unbound_method(obj, __init__, &self, false); 3920 - if (self != PY_NULL) { 3921 - // replace `NULL` with `self` 3922 - p1[-(ARGC + 2)] = callable; 3923 - p1[-(ARGC + 1)] = self; 3924 - // [init_f, self, args..., kwargs...] 3925 - vectorcall(ARGC, KWARGC); 3926 - // We just discard the return value of `__init__` 3927 - // in cpython it raises a TypeError if the return value is not None 3928 - }else{ 3929 - // manually reset the stack 3930 - s_data.reset(p0); 3931 - } 3932 - return obj; 3933 - } 3934 - 3935 - // handle `__call__` overload 3936 - PyObject* self; 3937 - PyObject* call_f = get_unbound_method(callable, __call__, &self, false); 3938 - if(self != PY_NULL){ 3939 - p1[-(ARGC + 2)] = call_f; 3940 - p1[-(ARGC + 1)] = self; 3941 - // [call_f, self, args..., kwargs...] 3942 - return vectorcall(ARGC, KWARGC, false); 3943 - } 3944 - TypeError(OBJ_NAME(_t(callable)).escape() + " object is not callable"); 3945 - return nullptr; 3946 - } 3947 - 3948 - inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args, ArgsView kwargs){ 3949 - // callable must be a `function` object 3950 - if(s_data.is_overflow()) StackOverflowError(); 3951 - 3952 - const Function& fn = CAST(Function&, callable); 3953 - const CodeObject* co = fn.decl->code.get(); 3954 - 3955 - if(args.size() < fn.argc){ 3956 - vm->TypeError(fmt( 3957 - "expected ", 3958 - fn.argc, 3959 - " positional arguments, but got ", 3960 - args.size(), 3961 - " (", fn.decl->code->name, ')' 3962 - )); 3963 - } 3964 - 3965 - // if this function is simple, a.k.a, no kwargs and no *args and not a generator 3966 - // we can use a fast path to avoid using buffer copy 3967 - if(fn.is_simple){ 3968 - if(args.size() > fn.argc) TypeError("too many positional arguments"); 3969 - int spaces = co->varnames.size() - fn.argc; 3970 - for(int j=0; j<spaces; j++) PUSH(nullptr); 3971 - callstack.emplace(&s_data, p0, co, fn._module, callable, FastLocals(co, args.begin())); 3972 - return nullptr; 3973 - } 3974 - 3975 - int i = 0; 3976 - static THREAD_LOCAL PyObject* buffer[PK_MAX_CO_VARNAMES]; 3977 - 3978 - // prepare args 3979 - for(int index: fn.decl->args) buffer[index] = args[i++]; 3980 - // set extra varnames to nullptr 3981 - for(int j=i; j<co->varnames.size(); j++) buffer[j] = nullptr; 3982 - 3983 - // prepare kwdefaults 3984 - for(auto& kv: fn.decl->kwargs) buffer[kv.key] = kv.value; 3985 - 3986 - // handle *args 3987 - if(fn.decl->starred_arg != -1){ 3988 - List vargs; // handle *args 3989 - while(i < args.size()) vargs.push_back(args[i++]); 3990 - buffer[fn.decl->starred_arg] = VAR(Tuple(std::move(vargs))); 3991 - }else{ 3992 - // kwdefaults override 3993 - for(auto& kv: fn.decl->kwargs){ 3994 - if(i < args.size()){ 3995 - buffer[kv.key] = args[i++]; 3996 - }else{ 3997 - break; 3998 - } 3999 - } 4000 - if(i < args.size()) TypeError(fmt("too many arguments", " (", fn.decl->code->name, ')')); 4001 - } 4002 - 4003 - for(int i=0; i<kwargs.size(); i+=2){ 4004 - StrName key = CAST(int, kwargs[i]); 4005 - int index = co->varnames_inv.try_get(key); 4006 - if(index<0) TypeError(fmt(key.escape(), " is an invalid keyword argument for ", co->name, "()")); 4007 - buffer[index] = kwargs[i+1]; 4008 - } 4009 - 4010 - s_data.reset(p0); 4011 - if(co->is_generator){ 4012 - PyObject* ret = PyIter(Generator( 4013 - this, 4014 - Frame(&s_data, nullptr, co, fn._module, callable), 4015 - ArgsView(buffer, buffer + co->varnames.size()) 4016 - )); 4017 - return ret; 4018 - } 4019 - 4020 - // copy buffer to stack 4021 - for(int i=0; i<co->varnames.size(); i++) PUSH(buffer[i]); 4022 - callstack.emplace(&s_data, p0, co, fn._module, callable); 4023 - return nullptr; 4024 - } 4025 - 4026 - // https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance 4027 - inline PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){ 4028 - PyObject* objtype = _t(obj); 4029 - // handle super() proxy 4030 - if(is_non_tagged_type(obj, tp_super)){ 4031 - const Super& super = OBJ_GET(Super, obj); 4032 - obj = super.first; 4033 - objtype = _t(super.second); 4034 - } 4035 - PyObject* cls_var = find_name_in_mro(objtype, name); 4036 - if(cls_var != nullptr){ 4037 - // handle descriptor 4038 - PyObject* descr_get = _t(cls_var)->attr().try_get(__get__); 4039 - if(descr_get != nullptr) return call_method(cls_var, descr_get, obj); 4040 - } 4041 - // handle instance __dict__ 4042 - if(!is_tagged(obj) && obj->is_attr_valid()){ 4043 - PyObject* val = obj->attr().try_get(name); 4044 - if(val != nullptr) return val; 4045 - } 4046 - if(cls_var != nullptr){ 4047 - // bound method is non-data descriptor 4048 - if(is_non_tagged_type(cls_var, tp_function) || is_non_tagged_type(cls_var, tp_native_func)){ 4049 - return VAR(BoundMethod(obj, cls_var)); 4050 - } 4051 - return cls_var; 4052 - } 4053 - if(throw_err) AttributeError(obj, name); 4054 - return nullptr; 4055 - } 4056 - 4057 - // used by OP_LOAD_METHOD 4058 - // try to load a unbound method (fallback to `getattr` if not found) 4059 - inline PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err, bool fallback){ 4060 - *self = PY_NULL; 4061 - PyObject* objtype = _t(obj); 4062 - // handle super() proxy 4063 - if(is_non_tagged_type(obj, tp_super)){ 4064 - const Super& super = OBJ_GET(Super, obj); 4065 - obj = super.first; 4066 - objtype = _t(super.second); 4067 - } 4068 - PyObject* cls_var = find_name_in_mro(objtype, name); 4069 - 4070 - if(fallback){ 4071 - if(cls_var != nullptr){ 4072 - // handle descriptor 4073 - PyObject* descr_get = _t(cls_var)->attr().try_get(__get__); 4074 - if(descr_get != nullptr) return call_method(cls_var, descr_get, obj); 4075 - } 4076 - // handle instance __dict__ 4077 - if(!is_tagged(obj) && obj->is_attr_valid()){ 4078 - PyObject* val = obj->attr().try_get(name); 4079 - if(val != nullptr) return val; 4080 - } 4081 - } 4082 - 4083 - if(cls_var != nullptr){ 4084 - if(is_non_tagged_type(cls_var, tp_function) || is_non_tagged_type(cls_var, tp_native_func)){ 4085 - *self = obj; 4086 - } 4087 - return cls_var; 4088 - } 4089 - if(throw_err) AttributeError(obj, name); 4090 - return nullptr; 4091 - } 4092 - 4093 - inline void VM::setattr(PyObject* obj, StrName name, PyObject* value){ 4094 - PyObject* objtype = _t(obj); 4095 - // handle super() proxy 4096 - if(is_non_tagged_type(obj, tp_super)){ 4097 - Super& super = OBJ_GET(Super, obj); 4098 - obj = super.first; 4099 - objtype = _t(super.second); 4100 - } 4101 - PyObject* cls_var = find_name_in_mro(objtype, name); 4102 - if(cls_var != nullptr){ 4103 - // handle descriptor 4104 - PyObject* cls_var_t = _t(cls_var); 4105 - if(cls_var_t->attr().contains(__get__)){ 4106 - PyObject* descr_set = cls_var_t->attr().try_get(__set__); 4107 - if(descr_set != nullptr){ 4108 - call_method(cls_var, descr_set, obj, value); 4109 - }else{ 4110 - TypeError(fmt("readonly attribute: ", name.escape())); 4111 - } 4112 - return; 4113 - } 4114 - } 4115 - // handle instance __dict__ 4116 - if(is_tagged(obj) || !obj->is_attr_valid()) TypeError("cannot set attribute"); 4117 - obj->attr().set(name, value); 4118 - } 4119 - 4120 - template<int ARGC> 4121 - void VM::bind_method(PyObject* obj, Str name, NativeFuncC fn) { 4122 - check_non_tagged_type(obj, tp_type); 4123 - obj->attr().set(name, VAR(NativeFunc(fn, ARGC, true))); 4124 - } 4125 - 4126 - template<int ARGC> 4127 - void VM::bind_func(PyObject* obj, Str name, NativeFuncC fn) { 4128 - obj->attr().set(name, VAR(NativeFunc(fn, ARGC, false))); 4129 - } 4130 - 4131 - inline void VM::_error(Exception e){ 4132 - if(callstack.empty()){ 4133 - e.is_re = false; 4134 - throw e; 4135 - } 4136 - PUSH(VAR(e)); 4137 - _raise(); 4138 - } 4139 - 4140 - inline void ManagedHeap::mark() { 4141 - for(PyObject* obj: _no_gc) OBJ_MARK(obj); 4142 - for(auto& frame : vm->callstack.data()) frame._gc_mark(); 4143 - for(PyObject* obj: vm->s_data) if(obj!=nullptr) OBJ_MARK(obj); 4144 - if(vm->_gc_marker_ex != nullptr) vm->_gc_marker_ex(vm); 4145 - } 4146 - 4147 - inline Str obj_type_name(VM *vm, Type type){ 4148 - return vm->_all_types[type].name; 4149 - } 4150 - 4151 - #undef PY_VAR_INT 4152 - #undef PY_VAR_FLOAT 4153 - 4154 - } // namespace pkpy 4155 - 4156 - 4157 - namespace pkpy{ 4158 - 4159 - inline PyObject* VM::_run_top_frame(){ 4160 - FrameId frame = top_frame(); 4161 - const int base_id = frame.index; 4162 - bool need_raise = false; 4163 - 4164 - // shared registers 4165 - PyObject *_0, *_1, *_2; 4166 - StrName _name; 4167 - 4168 - while(true){ 4169 - #if DEBUG_EXTRA_CHECK 4170 - if(frame.index < base_id) FATAL_ERROR(); 4171 - #endif 4172 - try{ 4173 - if(need_raise){ need_raise = false; _raise(); } 4174 - // if(s_data.is_overflow()) StackOverflowError(); 4175 - /**********************************************************************/ 4176 - /* NOTE: 4177 - * Be aware of accidental gc! 4178 - * DO NOT leave any strong reference of PyObject* in the C stack 4179 - */ 4180 - { 4181 - #define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; } 4182 - __NEXT_FRAME: 4183 - Bytecode byte = frame->next_bytecode(); 4184 - // cache 4185 - const CodeObject* co = frame->co; 4186 - const auto& co_consts = co->consts; 4187 - const auto& co_blocks = co->blocks; 4188 - 4189 - #if PK_ENABLE_COMPUTED_GOTO 4190 - static void* OP_LABELS[] = { 4191 - #define OPCODE(name) &&CASE_OP_##name, 4192 - #ifdef OPCODE 4193 - 4194 - /**************************/ 4195 - OPCODE(NO_OP) 4196 - /**************************/ 4197 - OPCODE(POP_TOP) 4198 - OPCODE(DUP_TOP) 4199 - OPCODE(ROT_TWO) 4200 - OPCODE(PRINT_EXPR) 4201 - /**************************/ 4202 - OPCODE(LOAD_CONST) 4203 - OPCODE(LOAD_NONE) 4204 - OPCODE(LOAD_TRUE) 4205 - OPCODE(LOAD_FALSE) 4206 - OPCODE(LOAD_INTEGER) 4207 - OPCODE(LOAD_ELLIPSIS) 4208 - OPCODE(LOAD_FUNCTION) 4209 - OPCODE(LOAD_NULL) 4210 - /**************************/ 4211 - OPCODE(LOAD_FAST) 4212 - OPCODE(LOAD_NAME) 4213 - OPCODE(LOAD_NONLOCAL) 4214 - OPCODE(LOAD_GLOBAL) 4215 - OPCODE(LOAD_ATTR) 4216 - OPCODE(LOAD_METHOD) 4217 - OPCODE(LOAD_SUBSCR) 4218 - 4219 - OPCODE(STORE_FAST) 4220 - OPCODE(STORE_NAME) 4221 - OPCODE(STORE_GLOBAL) 4222 - OPCODE(STORE_ATTR) 4223 - OPCODE(STORE_SUBSCR) 4224 - 4225 - OPCODE(DELETE_FAST) 4226 - OPCODE(DELETE_NAME) 4227 - OPCODE(DELETE_GLOBAL) 4228 - OPCODE(DELETE_ATTR) 4229 - OPCODE(DELETE_SUBSCR) 4230 - /**************************/ 4231 - OPCODE(BUILD_LIST) 4232 - OPCODE(BUILD_DICT) 4233 - OPCODE(BUILD_SET) 4234 - OPCODE(BUILD_SLICE) 4235 - OPCODE(BUILD_TUPLE) 4236 - OPCODE(BUILD_STRING) 4237 - /**************************/ 4238 - OPCODE(BINARY_OP) 4239 - OPCODE(BINARY_ADD) 4240 - OPCODE(BINARY_SUB) 4241 - OPCODE(BINARY_MUL) 4242 - OPCODE(BINARY_FLOORDIV) 4243 - OPCODE(BINARY_MOD) 4244 - 4245 - OPCODE(COMPARE_LT) 4246 - OPCODE(COMPARE_LE) 4247 - OPCODE(COMPARE_EQ) 4248 - OPCODE(COMPARE_NE) 4249 - OPCODE(COMPARE_GT) 4250 - OPCODE(COMPARE_GE) 4251 - 4252 - OPCODE(BITWISE_LSHIFT) 4253 - OPCODE(BITWISE_RSHIFT) 4254 - OPCODE(BITWISE_AND) 4255 - OPCODE(BITWISE_OR) 4256 - OPCODE(BITWISE_XOR) 4257 - 4258 - OPCODE(IS_OP) 4259 - OPCODE(CONTAINS_OP) 4260 - /**************************/ 4261 - OPCODE(JUMP_ABSOLUTE) 4262 - OPCODE(POP_JUMP_IF_FALSE) 4263 - OPCODE(JUMP_IF_TRUE_OR_POP) 4264 - OPCODE(JUMP_IF_FALSE_OR_POP) 4265 - OPCODE(LOOP_CONTINUE) 4266 - OPCODE(LOOP_BREAK) 4267 - OPCODE(GOTO) 4268 - /**************************/ 4269 - OPCODE(BEGIN_CALL) 4270 - OPCODE(CALL) 4271 - OPCODE(RETURN_VALUE) 4272 - OPCODE(YIELD_VALUE) 4273 - /**************************/ 4274 - OPCODE(LIST_APPEND) 4275 - OPCODE(DICT_ADD) 4276 - OPCODE(SET_ADD) 4277 - /**************************/ 4278 - OPCODE(UNARY_NEGATIVE) 4279 - OPCODE(UNARY_NOT) 4280 - /**************************/ 4281 - OPCODE(GET_ITER) 4282 - OPCODE(FOR_ITER) 4283 - /**************************/ 4284 - OPCODE(IMPORT_NAME) 4285 - OPCODE(IMPORT_STAR) 4286 - /**************************/ 4287 - OPCODE(UNPACK_SEQUENCE) 4288 - OPCODE(UNPACK_EX) 4289 - OPCODE(UNPACK_UNLIMITED) 4290 - /**************************/ 4291 - OPCODE(BEGIN_CLASS) 4292 - OPCODE(END_CLASS) 4293 - OPCODE(STORE_CLASS_ATTR) 4294 - /**************************/ 4295 - OPCODE(WITH_ENTER) 4296 - OPCODE(WITH_EXIT) 4297 - /**************************/ 4298 - OPCODE(ASSERT) 4299 - OPCODE(EXCEPTION_MATCH) 4300 - OPCODE(RAISE) 4301 - OPCODE(RE_RAISE) 4302 - /**************************/ 4303 - OPCODE(SETUP_DOCSTRING) 4304 - OPCODE(FORMAT_STRING) 4305 - #endif 4306 - #undef OPCODE 4307 - }; 4308 - 4309 - #define DISPATCH() { byte = frame->next_bytecode(); goto *OP_LABELS[byte.op];} 4310 - #define TARGET(op) CASE_OP_##op: 4311 - goto *OP_LABELS[byte.op]; 4312 - 4313 - #else 4314 - #define TARGET(op) case OP_##op: 4315 - #define DISPATCH() { byte = frame->next_bytecode(); goto __NEXT_STEP;} 4316 - 4317 - __NEXT_STEP:; 4318 - #if DEBUG_CEVAL_STEP 4319 - _log_s_data(); 4320 - #endif 4321 - #if DEBUG_CEVAL_STEP_MIN 4322 - std::cout << OP_NAMES[byte.op] << std::endl; 4323 - #endif 4324 - switch (byte.op) 4325 - { 4326 - #endif 4327 - TARGET(NO_OP) DISPATCH(); 4328 - /*****************************************/ 4329 - TARGET(POP_TOP) POP(); DISPATCH(); 4330 - TARGET(DUP_TOP) PUSH(TOP()); DISPATCH(); 4331 - TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH(); 4332 - TARGET(PRINT_EXPR) 4333 - if(TOP() != None){ 4334 - _stdout(this, CAST(Str&, asRepr(TOP()))); 4335 - _stdout(this, "\n"); 4336 - } 4337 - POP(); 4338 - DISPATCH(); 4339 - /*****************************************/ 4340 - TARGET(LOAD_CONST) 4341 - heap._auto_collect(); 4342 - PUSH(co_consts[byte.arg]); 4343 - DISPATCH(); 4344 - TARGET(LOAD_NONE) PUSH(None); DISPATCH(); 4345 - TARGET(LOAD_TRUE) PUSH(True); DISPATCH(); 4346 - TARGET(LOAD_FALSE) PUSH(False); DISPATCH(); 4347 - TARGET(LOAD_INTEGER) PUSH(VAR(byte.arg)); DISPATCH(); 4348 - TARGET(LOAD_ELLIPSIS) PUSH(Ellipsis); DISPATCH(); 4349 - TARGET(LOAD_FUNCTION) { 4350 - FuncDecl_ decl = co->func_decls[byte.arg]; 4351 - bool is_simple = decl->starred_arg==-1 && decl->kwargs.size()==0 && !decl->code->is_generator; 4352 - int argc = decl->args.size(); 4353 - PyObject* obj; 4354 - if(decl->nested){ 4355 - obj = VAR(Function({decl, is_simple, argc, frame->_module, frame->_locals.to_namedict()})); 4356 - }else{ 4357 - obj = VAR(Function({decl, is_simple, argc, frame->_module})); 4358 - } 4359 - PUSH(obj); 4360 - } DISPATCH(); 4361 - TARGET(LOAD_NULL) PUSH(PY_NULL); DISPATCH(); 4362 - /*****************************************/ 4363 - TARGET(LOAD_FAST) { 4364 - heap._auto_collect(); 4365 - _0 = frame->_locals[byte.arg]; 4366 - if(_0 == nullptr) vm->NameError(co->varnames[byte.arg]); 4367 - PUSH(_0); 4368 - } DISPATCH(); 4369 - TARGET(LOAD_NAME) 4370 - heap._auto_collect(); 4371 - _name = StrName(byte.arg); 4372 - _0 = frame->_locals.try_get(_name); 4373 - if(_0 != nullptr) { PUSH(_0); DISPATCH(); } 4374 - _0 = frame->f_closure_try_get(_name); 4375 - if(_0 != nullptr) { PUSH(_0); DISPATCH(); } 4376 - _0 = frame->f_globals().try_get(_name); 4377 - if(_0 != nullptr) { PUSH(_0); DISPATCH(); } 4378 - _0 = vm->builtins->attr().try_get(_name); 4379 - if(_0 != nullptr) { PUSH(_0); DISPATCH(); } 4380 - vm->NameError(_name); 4381 - DISPATCH(); 4382 - TARGET(LOAD_NONLOCAL) { 4383 - heap._auto_collect(); 4384 - _name = StrName(byte.arg); 4385 - _0 = frame->f_closure_try_get(_name); 4386 - if(_0 != nullptr) { PUSH(_0); DISPATCH(); } 4387 - _0 = frame->f_globals().try_get(_name); 4388 - if(_0 != nullptr) { PUSH(_0); DISPATCH(); } 4389 - _0 = vm->builtins->attr().try_get(_name); 4390 - if(_0 != nullptr) { PUSH(_0); DISPATCH(); } 4391 - vm->NameError(_name); 4392 - DISPATCH(); 4393 - } DISPATCH(); 4394 - TARGET(LOAD_GLOBAL) 4395 - heap._auto_collect(); 4396 - _name = StrName(byte.arg); 4397 - _0 = frame->f_globals().try_get(_name); 4398 - if(_0 != nullptr) { PUSH(_0); DISPATCH(); } 4399 - _0 = vm->builtins->attr().try_get(_name); 4400 - if(_0 != nullptr) { PUSH(_0); DISPATCH(); } 4401 - vm->NameError(_name); 4402 - DISPATCH(); 4403 - TARGET(LOAD_ATTR) 4404 - TOP() = getattr(TOP(), StrName(byte.arg)); 4405 - DISPATCH(); 4406 - TARGET(LOAD_METHOD) 4407 - TOP() = get_unbound_method(TOP(), StrName(byte.arg), &_0, true, true); 4408 - PUSH(_0); 4409 - DISPATCH(); 4410 - TARGET(LOAD_SUBSCR) 4411 - _1 = POPX(); 4412 - _0 = TOP(); 4413 - TOP() = call_method(_0, __getitem__, _1); 4414 - DISPATCH(); 4415 - TARGET(STORE_FAST) 4416 - frame->_locals[byte.arg] = POPX(); 4417 - DISPATCH(); 4418 - TARGET(STORE_NAME) 4419 - _name = StrName(byte.arg); 4420 - _0 = POPX(); 4421 - if(frame->_callable != nullptr){ 4422 - bool ok = frame->_locals.try_set(_name, _0); 4423 - if(!ok) vm->NameError(_name); 4424 - }else{ 4425 - frame->f_globals().set(_name, _0); 4426 - } 4427 - DISPATCH(); 4428 - TARGET(STORE_GLOBAL) 4429 - frame->f_globals().set(StrName(byte.arg), POPX()); 4430 - DISPATCH(); 4431 - TARGET(STORE_ATTR) { 4432 - _0 = TOP(); // a 4433 - _1 = SECOND(); // val 4434 - setattr(_0, StrName(byte.arg), _1); 4435 - STACK_SHRINK(2); 4436 - } DISPATCH(); 4437 - TARGET(STORE_SUBSCR) 4438 - _2 = POPX(); // b 4439 - _1 = POPX(); // a 4440 - _0 = POPX(); // val 4441 - call_method(_1, __setitem__, _2, _0); 4442 - DISPATCH(); 4443 - TARGET(DELETE_FAST) 4444 - _0 = frame->_locals[byte.arg]; 4445 - if(_0 == nullptr) vm->NameError(co->varnames[byte.arg]); 4446 - frame->_locals[byte.arg] = nullptr; 4447 - DISPATCH(); 4448 - TARGET(DELETE_NAME) 4449 - _name = StrName(byte.arg); 4450 - if(frame->_callable != nullptr){ 4451 - if(!frame->_locals.contains(_name)) vm->NameError(_name); 4452 - frame->_locals.erase(_name); 4453 - }else{ 4454 - if(!frame->f_globals().contains(_name)) vm->NameError(_name); 4455 - frame->f_globals().erase(_name); 4456 - } 4457 - DISPATCH(); 4458 - TARGET(DELETE_GLOBAL) 4459 - _name = StrName(byte.arg); 4460 - if(frame->f_globals().contains(_name)){ 4461 - frame->f_globals().erase(_name); 4462 - }else{ 4463 - NameError(_name); 4464 - } 4465 - DISPATCH(); 4466 - TARGET(DELETE_ATTR) 4467 - _0 = POPX(); 4468 - _name = StrName(byte.arg); 4469 - if(!_0->is_attr_valid()) TypeError("cannot delete attribute"); 4470 - if(!_0->attr().contains(_name)) AttributeError(_0, _name); 4471 - _0->attr().erase(_name); 4472 - DISPATCH(); 4473 - TARGET(DELETE_SUBSCR) 4474 - _1 = POPX(); 4475 - _0 = POPX(); 4476 - call_method(_0, __delitem__, _1); 4477 - DISPATCH(); 4478 - /*****************************************/ 4479 - TARGET(BUILD_LIST) 4480 - _0 = VAR(STACK_VIEW(byte.arg).to_list()); 4481 - STACK_SHRINK(byte.arg); 4482 - PUSH(_0); 4483 - DISPATCH(); 4484 - TARGET(BUILD_DICT) { 4485 - PyObject* t = VAR(STACK_VIEW(byte.arg).to_tuple()); 4486 - PyObject* obj = call(builtins->attr(m_dict), t); 4487 - STACK_SHRINK(byte.arg); 4488 - PUSH(obj); 4489 - } DISPATCH(); 4490 - TARGET(BUILD_SET) { 4491 - PyObject* t = VAR(STACK_VIEW(byte.arg).to_tuple()); 4492 - PyObject* obj = call(builtins->attr(m_set), t); 4493 - STACK_SHRINK(byte.arg); 4494 - PUSH(obj); 4495 - } DISPATCH(); 4496 - TARGET(BUILD_SLICE) 4497 - _2 = POPX(); // step 4498 - _1 = POPX(); // stop 4499 - _0 = POPX(); // start 4500 - PUSH(VAR(Slice(_0, _1, _2))); 4501 - DISPATCH(); 4502 - TARGET(BUILD_TUPLE) 4503 - _0 = VAR(STACK_VIEW(byte.arg).to_tuple()); 4504 - STACK_SHRINK(byte.arg); 4505 - PUSH(_0); 4506 - DISPATCH(); 4507 - TARGET(BUILD_STRING) { 4508 - std::stringstream ss; 4509 - auto view = STACK_VIEW(byte.arg); 4510 - for(PyObject* obj : view) ss << CAST(Str&, asStr(obj)); 4511 - STACK_SHRINK(byte.arg); 4512 - PUSH(VAR(ss.str())); 4513 - } DISPATCH(); 4514 - /*****************************************/ 4515 - TARGET(BINARY_OP) 4516 - _1 = POPX(); // b 4517 - _0 = TOP(); // a 4518 - TOP() = call_method(_0, BINARY_SPECIAL_METHODS[byte.arg], _1); 4519 - DISPATCH(); 4520 - 4521 - #define INT_BINARY_OP(op, func) \ 4522 - if(is_both_int(TOP(), SECOND())){ \ 4523 - i64 b = _CAST(i64, TOP()); \ 4524 - i64 a = _CAST(i64, SECOND()); \ 4525 - POP(); \ 4526 - TOP() = VAR(a op b); \ 4527 - }else{ \ 4528 - _1 = POPX(); \ 4529 - _0 = TOP(); \ 4530 - TOP() = call_method(_0, func, _1); \ 4531 - } 4532 - 4533 - TARGET(BINARY_ADD) 4534 - INT_BINARY_OP(+, __add__) 4535 - DISPATCH() 4536 - TARGET(BINARY_SUB) 4537 - INT_BINARY_OP(-, __sub__) 4538 - DISPATCH() 4539 - TARGET(BINARY_MUL) 4540 - INT_BINARY_OP(*, __mul__) 4541 - DISPATCH() 4542 - TARGET(BINARY_FLOORDIV) 4543 - INT_BINARY_OP(/, __floordiv__) 4544 - DISPATCH() 4545 - TARGET(BINARY_MOD) 4546 - INT_BINARY_OP(%, __mod__) 4547 - DISPATCH() 4548 - TARGET(COMPARE_LT) 4549 - INT_BINARY_OP(<, __lt__) 4550 - DISPATCH() 4551 - TARGET(COMPARE_LE) 4552 - INT_BINARY_OP(<=, __le__) 4553 - DISPATCH() 4554 - TARGET(COMPARE_EQ) 4555 - INT_BINARY_OP(==, __eq__) 4556 - DISPATCH() 4557 - TARGET(COMPARE_NE) 4558 - INT_BINARY_OP(!=, __ne__) 4559 - DISPATCH() 4560 - TARGET(COMPARE_GT) 4561 - INT_BINARY_OP(>, __gt__) 4562 - DISPATCH() 4563 - TARGET(COMPARE_GE) 4564 - INT_BINARY_OP(>=, __ge__) 4565 - DISPATCH() 4566 - TARGET(BITWISE_LSHIFT) 4567 - INT_BINARY_OP(<<, __lshift__) 4568 - DISPATCH() 4569 - TARGET(BITWISE_RSHIFT) 4570 - INT_BINARY_OP(>>, __rshift__) 4571 - DISPATCH() 4572 - TARGET(BITWISE_AND) 4573 - INT_BINARY_OP(&, __and__) 4574 - DISPATCH() 4575 - TARGET(BITWISE_OR) 4576 - INT_BINARY_OP(|, __or__) 4577 - DISPATCH() 4578 - TARGET(BITWISE_XOR) 4579 - INT_BINARY_OP(^, __xor__) 4580 - DISPATCH() 4581 - #undef INT_BINARY_OP 4582 - 4583 - TARGET(IS_OP) 4584 - _1 = POPX(); // rhs 4585 - _0 = TOP(); // lhs 4586 - if(byte.arg == 1){ 4587 - TOP() = VAR(_0 != _1); 4588 - }else{ 4589 - TOP() = VAR(_0 == _1); 4590 - } 4591 - DISPATCH(); 4592 - TARGET(CONTAINS_OP) 4593 - // a in b -> b __contains__ a 4594 - _0 = call_method(TOP(), __contains__, SECOND()); 4595 - POP(); 4596 - if(byte.arg == 1){ 4597 - TOP() = VAR(!CAST(bool, _0)); 4598 - }else{ 4599 - TOP() = VAR(CAST(bool, _0)); 4600 - } 4601 - DISPATCH(); 4602 - /*****************************************/ 4603 - TARGET(JUMP_ABSOLUTE) 4604 - frame->jump_abs(byte.arg); 4605 - DISPATCH(); 4606 - TARGET(POP_JUMP_IF_FALSE) 4607 - if(!asBool(POPX())) frame->jump_abs(byte.arg); 4608 - DISPATCH(); 4609 - TARGET(JUMP_IF_TRUE_OR_POP) 4610 - if(asBool(TOP()) == true) frame->jump_abs(byte.arg); 4611 - else POP(); 4612 - DISPATCH(); 4613 - TARGET(JUMP_IF_FALSE_OR_POP) 4614 - if(asBool(TOP()) == false) frame->jump_abs(byte.arg); 4615 - else POP(); 4616 - DISPATCH(); 4617 - TARGET(LOOP_CONTINUE) 4618 - frame->jump_abs(co_blocks[byte.block].start); 4619 - DISPATCH(); 4620 - TARGET(LOOP_BREAK) 4621 - frame->jump_abs_break(co_blocks[byte.block].end); 4622 - DISPATCH(); 4623 - TARGET(GOTO) { 4624 - StrName name(byte.arg); 4625 - int index = co->labels.try_get(name); 4626 - if(index < 0) _error("KeyError", fmt("label ", name.escape(), " not found")); 4627 - frame->jump_abs_break(index); 4628 - } DISPATCH(); 4629 - /*****************************************/ 4630 - TARGET(BEGIN_CALL) 4631 - PUSH(PY_BEGIN_CALL); 4632 - DISPATCH(); 4633 - TARGET(CALL) 4634 - _0 = vectorcall( 4635 - byte.arg & 0xFFFF, // ARGC 4636 - (byte.arg>>16) & 0xFFFF, // KWARGC 4637 - true 4638 - ); 4639 - if(_0 == PY_OP_CALL) DISPATCH_OP_CALL(); 4640 - PUSH(_0); 4641 - DISPATCH(); 4642 - TARGET(RETURN_VALUE) 4643 - _0 = POPX(); 4644 - _pop_frame(); 4645 - if(frame.index == base_id){ // [ frameBase<- ] 4646 - return _0; 4647 - }else{ 4648 - frame = top_frame(); 4649 - PUSH(_0); 4650 - goto __NEXT_FRAME; 4651 - } 4652 - TARGET(YIELD_VALUE) 4653 - return PY_OP_YIELD; 4654 - /*****************************************/ 4655 - TARGET(LIST_APPEND) 4656 - _0 = POPX(); 4657 - CAST(List&, SECOND()).push_back(_0); 4658 - DISPATCH(); 4659 - TARGET(DICT_ADD) { 4660 - _0 = POPX(); 4661 - Tuple& t = CAST(Tuple&, _0); 4662 - call_method(SECOND(), __setitem__, t[0], t[1]); 4663 - } DISPATCH(); 4664 - TARGET(SET_ADD) 4665 - _0 = POPX(); 4666 - call_method(SECOND(), m_add, _0); 4667 - DISPATCH(); 4668 - /*****************************************/ 4669 - TARGET(UNARY_NEGATIVE) 4670 - TOP() = num_negated(TOP()); 4671 - DISPATCH(); 4672 - TARGET(UNARY_NOT) 4673 - TOP() = VAR(!asBool(TOP())); 4674 - DISPATCH(); 4675 - /*****************************************/ 4676 - TARGET(GET_ITER) 4677 - TOP() = asIter(TOP()); 4678 - DISPATCH(); 4679 - TARGET(FOR_ITER) 4680 - _0 = PyIterNext(TOP()); 4681 - if(_0 != StopIteration){ 4682 - PUSH(_0); 4683 - }else{ 4684 - frame->jump_abs_break(co_blocks[byte.block].end); 4685 - } 4686 - DISPATCH(); 4687 - /*****************************************/ 4688 - TARGET(IMPORT_NAME) { 4689 - StrName name(byte.arg); 4690 - PyObject* ext_mod = _modules.try_get(name); 4691 - if(ext_mod == nullptr){ 4692 - Str source; 4693 - auto it = _lazy_modules.find(name); 4694 - if(it == _lazy_modules.end()){ 4695 - Bytes b = _read_file_cwd(fmt(name, ".py")); 4696 - if(!b) _error("ImportError", fmt("module ", name.escape(), " not found")); 4697 - source = Str(b.str()); 4698 - }else{ 4699 - source = it->second; 4700 - _lazy_modules.erase(it); 4701 - } 4702 - CodeObject_ code = compile(source, Str(name.sv())+".py", EXEC_MODE); 4703 - PyObject* new_mod = new_module(name); 4704 - _exec(code, new_mod); 4705 - new_mod->attr()._try_perfect_rehash(); 4706 - PUSH(new_mod); 4707 - }else{ 4708 - PUSH(ext_mod); 4709 - } 4710 - } DISPATCH(); 4711 - TARGET(IMPORT_STAR) { 4712 - PyObject* obj = POPX(); 4713 - for(auto& [name, value]: obj->attr().items()){ 4714 - std::string_view s = name.sv(); 4715 - if(s.empty() || s[0] == '_') continue; 4716 - frame->f_globals().set(name, value); 4717 - } 4718 - }; DISPATCH(); 4719 - /*****************************************/ 4720 - TARGET(UNPACK_SEQUENCE) 4721 - TARGET(UNPACK_EX) { 4722 - auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!! 4723 - PyObject* iter = asIter(POPX()); 4724 - for(int i=0; i<byte.arg; i++){ 4725 - PyObject* item = PyIterNext(iter); 4726 - if(item == StopIteration) ValueError("not enough values to unpack"); 4727 - PUSH(item); 4728 - } 4729 - // handle extra items 4730 - if(byte.op == OP_UNPACK_EX){ 4731 - List extras; 4732 - while(true){ 4733 - PyObject* item = PyIterNext(iter); 4734 - if(item == StopIteration) break; 4735 - extras.push_back(item); 4736 - } 4737 - PUSH(VAR(extras)); 4738 - }else{ 4739 - if(PyIterNext(iter) != StopIteration) ValueError("too many values to unpack"); 4740 - } 4741 - } DISPATCH(); 4742 - TARGET(UNPACK_UNLIMITED) { 4743 - auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!! 4744 - PyObject* iter = asIter(POPX()); 4745 - _0 = PyIterNext(iter); 4746 - while(_0 != StopIteration){ 4747 - PUSH(_0); 4748 - _0 = PyIterNext(iter); 4749 - } 4750 - } DISPATCH(); 4751 - /*****************************************/ 4752 - TARGET(BEGIN_CLASS) { 4753 - StrName name(byte.arg); 4754 - PyObject* super_cls = POPX(); 4755 - if(super_cls == None) super_cls = _t(tp_object); 4756 - check_non_tagged_type(super_cls, tp_type); 4757 - PyObject* cls = new_type_object(frame->_module, name, OBJ_GET(Type, super_cls)); 4758 - PUSH(cls); 4759 - } DISPATCH(); 4760 - TARGET(END_CLASS) 4761 - _0 = POPX(); 4762 - _0->attr()._try_perfect_rehash(); 4763 - DISPATCH(); 4764 - TARGET(STORE_CLASS_ATTR) 4765 - _name = StrName(byte.arg); 4766 - _0 = POPX(); 4767 - TOP()->attr().set(_name, _0); 4768 - DISPATCH(); 4769 - /*****************************************/ 4770 - // TODO: using "goto" inside with block may cause __exit__ not called 4771 - TARGET(WITH_ENTER) 4772 - call_method(POPX(), __enter__); 4773 - DISPATCH(); 4774 - TARGET(WITH_EXIT) 4775 - call_method(POPX(), __exit__); 4776 - DISPATCH(); 4777 - /*****************************************/ 4778 - TARGET(ASSERT) { 4779 - PyObject* obj = TOP(); 4780 - Str msg; 4781 - if(is_type(obj, tp_tuple)){ 4782 - auto& t = CAST(Tuple&, obj); 4783 - if(t.size() != 2) ValueError("assert tuple must have 2 elements"); 4784 - obj = t[0]; 4785 - msg = CAST(Str&, asStr(t[1])); 4786 - } 4787 - bool ok = asBool(obj); 4788 - POP(); 4789 - if(!ok) _error("AssertionError", msg); 4790 - } DISPATCH(); 4791 - TARGET(EXCEPTION_MATCH) { 4792 - const auto& e = CAST(Exception&, TOP()); 4793 - _name = StrName(byte.arg); 4794 - PUSH(VAR(e.match_type(_name))); 4795 - } DISPATCH(); 4796 - TARGET(RAISE) { 4797 - PyObject* obj = POPX(); 4798 - Str msg = obj == None ? "" : CAST(Str, asStr(obj)); 4799 - _error(StrName(byte.arg), msg); 4800 - } DISPATCH(); 4801 - TARGET(RE_RAISE) _raise(); DISPATCH(); 4802 - /*****************************************/ 4803 - TARGET(SETUP_DOCSTRING) 4804 - TOP()->attr().set(__doc__, co_consts[byte.arg]); 4805 - DISPATCH(); 4806 - TARGET(FORMAT_STRING) { 4807 - _0 = POPX(); 4808 - const Str& spec = CAST(Str&, co_consts[byte.arg]); 4809 - PUSH(format(spec, _0)); 4810 - } DISPATCH(); 4811 - #if !PK_ENABLE_COMPUTED_GOTO 4812 - #if DEBUG_EXTRA_CHECK 4813 - default: throw std::runtime_error(fmt(OP_NAMES[byte.op], " is not implemented")); 4814 - #else 4815 - default: UNREACHABLE(); 4816 - #endif 4817 - } 4818 - #endif 4819 - } 4820 - 4821 - #undef DISPATCH 4822 - #undef TARGET 4823 - #undef DISPATCH_OP_CALL 4824 - /**********************************************************************/ 4825 - UNREACHABLE(); 4826 - }catch(HandledException& e){ 4827 - continue; 4828 - }catch(UnhandledException& e){ 4829 - PyObject* obj = POPX(); 4830 - Exception& _e = CAST(Exception&, obj); 4831 - _e.st_push(frame->snapshot()); 4832 - _pop_frame(); 4833 - if(callstack.empty()){ 4834 - #if DEBUG_FULL_EXCEPTION 4835 - std::cerr << _e.summary() << std::endl; 4836 - #endif 4837 - throw _e; 4838 - } 4839 - frame = top_frame(); 4840 - PUSH(obj); 4841 - if(frame.index < base_id) throw ToBeRaisedException(); 4842 - need_raise = true; 4843 - }catch(ToBeRaisedException& e){ 4844 - need_raise = true; 4845 - } 4846 - } 4847 - } 4848 - 4849 - #undef TOP 4850 - #undef SECOND 4851 - #undef THIRD 4852 - #undef PEEK 4853 - #undef STACK_SHRINK 4854 - #undef PUSH 4855 - #undef POP 4856 - #undef POPX 4857 - #undef STACK_VIEW 4858 - 4859 - } // namespace pkpy 4860 - 4861 - 4862 - #include <algorithm> 4863 - 4864 - namespace pkpy{ 4865 - 4866 - struct CodeEmitContext; 4867 - 4868 - struct Expr{ 4869 - int line = 0; 4870 - virtual ~Expr() = default; 4871 - virtual void emit(CodeEmitContext* ctx) = 0; 4872 - virtual std::string str() const = 0; 4873 - 4874 - virtual bool is_starred() const { return false; } 4875 - virtual bool is_literal() const { return false; } 4876 - virtual bool is_json_object() const { return false; } 4877 - virtual bool is_attrib() const { return false; } 4878 - 4879 - // for OP_DELETE_XXX 4880 - [[nodiscard]] virtual bool emit_del(CodeEmitContext* ctx) { return false; } 4881 - 4882 - // for OP_STORE_XXX 4883 - [[nodiscard]] virtual bool emit_store(CodeEmitContext* ctx) { return false; } 4884 - }; 4885 - 4886 - struct CodeEmitContext{ 4887 - VM* vm; 4888 - CodeObject_ co; 4889 - stack<Expr_> s_expr; 4890 - int level; 4891 - CodeEmitContext(VM* vm, CodeObject_ co, int level): vm(vm), co(co), level(level) {} 4892 - 4893 - int curr_block_i = 0; 4894 - bool is_compiling_class = false; 4895 - int for_loop_depth = 0; 4896 - 4897 - bool is_curr_block_loop() const { 4898 - return co->blocks[curr_block_i].type == FOR_LOOP || co->blocks[curr_block_i].type == WHILE_LOOP; 4899 - } 4900 - 4901 - void enter_block(CodeBlockType type){ 4902 - if(type == FOR_LOOP) for_loop_depth++; 4903 - co->blocks.push_back(CodeBlock( 4904 - type, curr_block_i, for_loop_depth, (int)co->codes.size() 4905 - )); 4906 - curr_block_i = co->blocks.size()-1; 4907 - } 4908 - 4909 - void exit_block(){ 4910 - if(co->blocks[curr_block_i].type == FOR_LOOP) for_loop_depth--; 4911 - co->blocks[curr_block_i].end = co->codes.size(); 4912 - curr_block_i = co->blocks[curr_block_i].parent; 4913 - if(curr_block_i < 0) FATAL_ERROR(); 4914 - } 4915 - 4916 - // clear the expression stack and generate bytecode 4917 - void emit_expr(){ 4918 - if(s_expr.size() != 1){ 4919 - throw std::runtime_error("s_expr.size() != 1\n" + _log_s_expr()); 4920 - } 4921 - Expr_ expr = s_expr.popx(); 4922 - expr->emit(this); 4923 - } 4924 - 4925 - std::string _log_s_expr(){ 4926 - std::stringstream ss; 4927 - for(auto& e: s_expr.data()) ss << e->str() << " "; 4928 - return ss.str(); 4929 - } 4930 - 4931 - int emit(Opcode opcode, int arg, int line) { 4932 - co->codes.push_back( 4933 - Bytecode{(uint16_t)opcode, (uint16_t)curr_block_i, arg} 4934 - ); 4935 - co->lines.push_back(line); 4936 - int i = co->codes.size() - 1; 4937 - if(line==BC_KEEPLINE){ 4938 - if(i>=1) co->lines[i] = co->lines[i-1]; 4939 - else co->lines[i] = 1; 4940 - } 4941 - return i; 4942 - } 4943 - 4944 - void patch_jump(int index) { 4945 - int target = co->codes.size(); 4946 - co->codes[index].arg = target; 4947 - } 4948 - 4949 - bool add_label(StrName name){ 4950 - if(co->labels.contains(name)) return false; 4951 - co->labels.set(name, co->codes.size()); 4952 - return true; 4953 - } 4954 - 4955 - int add_varname(StrName name){ 4956 - int index = co->varnames_inv.try_get(name); 4957 - if(index >= 0) return index; 4958 - co->varnames.push_back(name); 4959 - index = co->varnames.size() - 1; 4960 - co->varnames_inv.set(name, index); 4961 - return index; 4962 - } 4963 - 4964 - int add_const(PyObject* v){ 4965 - // simple deduplication, only works for int/float 4966 - for(int i=0; i<co->consts.size(); i++){ 4967 - if(co->consts[i] == v) return i; 4968 - } 4969 - co->consts.push_back(v); 4970 - return co->consts.size() - 1; 4971 - } 4972 - 4973 - int add_func_decl(FuncDecl_ decl){ 4974 - co->func_decls.push_back(decl); 4975 - return co->func_decls.size() - 1; 4976 - } 4977 - }; 4978 - 4979 - struct NameExpr: Expr{ 4980 - StrName name; 4981 - NameScope scope; 4982 - NameExpr(StrName name, NameScope scope): name(name), scope(scope) {} 4983 - 4984 - std::string str() const override { return fmt("Name(", name.escape(), ")"); } 4985 - 4986 - void emit(CodeEmitContext* ctx) override { 4987 - int index = ctx->co->varnames_inv.try_get(name); 4988 - if(scope == NAME_LOCAL && index >= 0){ 4989 - ctx->emit(OP_LOAD_FAST, index, line); 4990 - }else{ 4991 - Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL; 4992 - // we cannot determine the scope when calling exec()/eval() 4993 - if(scope == NAME_GLOBAL_UNKNOWN) op = OP_LOAD_NAME; 4994 - ctx->emit(op, StrName(name).index, line); 4995 - } 4996 - } 4997 - 4998 - bool emit_del(CodeEmitContext* ctx) override { 4999 - switch(scope){ 5000 - case NAME_LOCAL: 5001 - ctx->emit(OP_DELETE_FAST, ctx->add_varname(name), line); 5002 - break; 5003 - case NAME_GLOBAL: 5004 - ctx->emit(OP_DELETE_GLOBAL, StrName(name).index, line); 5005 - break; 5006 - case NAME_GLOBAL_UNKNOWN: 5007 - ctx->emit(OP_DELETE_NAME, StrName(name).index, line); 5008 - break; 5009 - default: FATAL_ERROR(); break; 5010 - } 5011 - return true; 5012 - } 5013 - 5014 - bool emit_store(CodeEmitContext* ctx) override { 5015 - if(ctx->is_compiling_class){ 5016 - int index = StrName(name).index; 5017 - ctx->emit(OP_STORE_CLASS_ATTR, index, line); 5018 - return true; 5019 - } 5020 - switch(scope){ 5021 - case NAME_LOCAL: 5022 - ctx->emit(OP_STORE_FAST, ctx->add_varname(name), line); 5023 - break; 5024 - case NAME_GLOBAL: 5025 - ctx->emit(OP_STORE_GLOBAL, StrName(name).index, line); 5026 - break; 5027 - case NAME_GLOBAL_UNKNOWN: 5028 - ctx->emit(OP_STORE_NAME, StrName(name).index, line); 5029 - break; 5030 - default: FATAL_ERROR(); break; 5031 - } 5032 - return true; 5033 - } 5034 - }; 5035 - 5036 - struct StarredExpr: Expr{ 5037 - Expr_ child; 5038 - StarredExpr(Expr_&& child): child(std::move(child)) {} 5039 - std::string str() const override { return "Starred()"; } 5040 - 5041 - bool is_starred() const override { return true; } 5042 - 5043 - void emit(CodeEmitContext* ctx) override { 5044 - child->emit(ctx); 5045 - ctx->emit(OP_UNPACK_UNLIMITED, BC_NOARG, line); 5046 - } 5047 - 5048 - bool emit_store(CodeEmitContext* ctx) override { 5049 - // simply proxy to child 5050 - return child->emit_store(ctx); 5051 - } 5052 - }; 5053 - 5054 - 5055 - struct NotExpr: Expr{ 5056 - Expr_ child; 5057 - NotExpr(Expr_&& child): child(std::move(child)) {} 5058 - std::string str() const override { return "Not()"; } 5059 - 5060 - void emit(CodeEmitContext* ctx) override { 5061 - child->emit(ctx); 5062 - ctx->emit(OP_UNARY_NOT, BC_NOARG, line); 5063 - } 5064 - }; 5065 - 5066 - struct AndExpr: Expr{ 5067 - Expr_ lhs; 5068 - Expr_ rhs; 5069 - std::string str() const override { return "And()"; } 5070 - 5071 - void emit(CodeEmitContext* ctx) override { 5072 - lhs->emit(ctx); 5073 - int patch = ctx->emit(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line); 5074 - rhs->emit(ctx); 5075 - ctx->patch_jump(patch); 5076 - } 5077 - }; 5078 - 5079 - struct OrExpr: Expr{ 5080 - Expr_ lhs; 5081 - Expr_ rhs; 5082 - std::string str() const override { return "Or()"; } 5083 - 5084 - void emit(CodeEmitContext* ctx) override { 5085 - lhs->emit(ctx); 5086 - int patch = ctx->emit(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line); 5087 - rhs->emit(ctx); 5088 - ctx->patch_jump(patch); 5089 - } 5090 - }; 5091 - 5092 - // [None, True, False, ...] 5093 - struct Literal0Expr: Expr{ 5094 - TokenIndex token; 5095 - Literal0Expr(TokenIndex token): token(token) {} 5096 - std::string str() const override { return TK_STR(token); } 5097 - 5098 - void emit(CodeEmitContext* ctx) override { 5099 - switch (token) { 5100 - case TK("None"): ctx->emit(OP_LOAD_NONE, BC_NOARG, line); break; 5101 - case TK("True"): ctx->emit(OP_LOAD_TRUE, BC_NOARG, line); break; 5102 - case TK("False"): ctx->emit(OP_LOAD_FALSE, BC_NOARG, line); break; 5103 - case TK("..."): ctx->emit(OP_LOAD_ELLIPSIS, BC_NOARG, line); break; 5104 - default: FATAL_ERROR(); 5105 - } 5106 - } 5107 - 5108 - bool is_json_object() const override { return true; } 5109 - }; 5110 - 5111 - // @num, @str which needs to invoke OP_LOAD_CONST 5112 - struct LiteralExpr: Expr{ 5113 - TokenValue value; 5114 - LiteralExpr(TokenValue value): value(value) {} 5115 - std::string str() const override { 5116 - if(std::holds_alternative<i64>(value)){ 5117 - return std::to_string(std::get<i64>(value)); 5118 - } 5119 - 5120 - if(std::holds_alternative<f64>(value)){ 5121 - return std::to_string(std::get<f64>(value)); 5122 - } 5123 - 5124 - if(std::holds_alternative<Str>(value)){ 5125 - Str s = std::get<Str>(value).escape(); 5126 - return s.str(); 5127 - } 5128 - 5129 - FATAL_ERROR(); 5130 - } 5131 - 5132 - void emit(CodeEmitContext* ctx) override { 5133 - VM* vm = ctx->vm; 5134 - PyObject* obj = nullptr; 5135 - if(std::holds_alternative<i64>(value)){ 5136 - i64 _val = std::get<i64>(value); 5137 - if(_val >= INT16_MIN && _val <= INT16_MAX){ 5138 - ctx->emit(OP_LOAD_INTEGER, (int)_val, line); 5139 - return; 5140 - } 5141 - obj = VAR(_val); 5142 - } 5143 - if(std::holds_alternative<f64>(value)){ 5144 - obj = VAR(std::get<f64>(value)); 5145 - } 5146 - if(std::holds_alternative<Str>(value)){ 5147 - obj = VAR(std::get<Str>(value)); 5148 - } 5149 - if(obj == nullptr) FATAL_ERROR(); 5150 - ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line); 5151 - } 5152 - 5153 - bool is_literal() const override { return true; } 5154 - bool is_json_object() const override { return true; } 5155 - }; 5156 - 5157 - struct NegatedExpr: Expr{ 5158 - Expr_ child; 5159 - NegatedExpr(Expr_&& child): child(std::move(child)) {} 5160 - std::string str() const override { return "Negated()"; } 5161 - 5162 - void emit(CodeEmitContext* ctx) override { 5163 - VM* vm = ctx->vm; 5164 - // if child is a int of float, do constant folding 5165 - if(child->is_literal()){ 5166 - LiteralExpr* lit = static_cast<LiteralExpr*>(child.get()); 5167 - if(std::holds_alternative<i64>(lit->value)){ 5168 - i64 _val = -std::get<i64>(lit->value); 5169 - if(_val >= INT16_MIN && _val <= INT16_MAX){ 5170 - ctx->emit(OP_LOAD_INTEGER, (int)_val, line); 5171 - }else{ 5172 - ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line); 5173 - } 5174 - return; 5175 - } 5176 - if(std::holds_alternative<f64>(lit->value)){ 5177 - PyObject* obj = VAR(-std::get<f64>(lit->value)); 5178 - ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line); 5179 - return; 5180 - } 5181 - } 5182 - child->emit(ctx); 5183 - ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line); 5184 - } 5185 - 5186 - bool is_json_object() const override { 5187 - return child->is_literal(); 5188 - } 5189 - }; 5190 - 5191 - struct SliceExpr: Expr{ 5192 - Expr_ start; 5193 - Expr_ stop; 5194 - Expr_ step; 5195 - std::string str() const override { return "Slice()"; } 5196 - 5197 - void emit(CodeEmitContext* ctx) override { 5198 - if(start){ 5199 - start->emit(ctx); 5200 - }else{ 5201 - ctx->emit(OP_LOAD_NONE, BC_NOARG, line); 5202 - } 5203 - 5204 - if(stop){ 5205 - stop->emit(ctx); 5206 - }else{ 5207 - ctx->emit(OP_LOAD_NONE, BC_NOARG, line); 5208 - } 5209 - 5210 - if(step){ 5211 - step->emit(ctx); 5212 - }else{ 5213 - ctx->emit(OP_LOAD_NONE, BC_NOARG, line); 5214 - } 5215 - 5216 - ctx->emit(OP_BUILD_SLICE, BC_NOARG, line); 5217 - } 5218 - }; 5219 - 5220 - struct DictItemExpr: Expr{ 5221 - Expr_ key; 5222 - Expr_ value; 5223 - std::string str() const override { return "DictItem()"; } 5224 - 5225 - void emit(CodeEmitContext* ctx) override { 5226 - value->emit(ctx); 5227 - key->emit(ctx); // reverse order 5228 - ctx->emit(OP_BUILD_TUPLE, 2, line); 5229 - } 5230 - }; 5231 - 5232 - struct SequenceExpr: Expr{ 5233 - std::vector<Expr_> items; 5234 - SequenceExpr(std::vector<Expr_>&& items): items(std::move(items)) {} 5235 - virtual Opcode opcode() const = 0; 5236 - 5237 - void emit(CodeEmitContext* ctx) override { 5238 - for(auto& item: items) item->emit(ctx); 5239 - ctx->emit(opcode(), items.size(), line); 5240 - } 5241 - }; 5242 - 5243 - struct ListExpr: SequenceExpr{ 5244 - using SequenceExpr::SequenceExpr; 5245 - std::string str() const override { return "List()"; } 5246 - Opcode opcode() const override { return OP_BUILD_LIST; } 5247 - 5248 - bool is_json_object() const override { return true; } 5249 - }; 5250 - 5251 - struct DictExpr: SequenceExpr{ 5252 - using SequenceExpr::SequenceExpr; 5253 - std::string str() const override { return "Dict()"; } 5254 - Opcode opcode() const override { return OP_BUILD_DICT; } 5255 - 5256 - bool is_json_object() const override { return true; } 5257 - }; 5258 - 5259 - struct SetExpr: SequenceExpr{ 5260 - using SequenceExpr::SequenceExpr; 5261 - std::string str() const override { return "Set()"; } 5262 - Opcode opcode() const override { return OP_BUILD_SET; } 5263 - }; 5264 - 5265 - struct TupleExpr: SequenceExpr{ 5266 - using SequenceExpr::SequenceExpr; 5267 - std::string str() const override { return "Tuple()"; } 5268 - Opcode opcode() const override { return OP_BUILD_TUPLE; } 5269 - 5270 - bool emit_store(CodeEmitContext* ctx) override { 5271 - // TOS is an iterable 5272 - // items may contain StarredExpr, we should check it 5273 - int starred_i = -1; 5274 - for(int i=0; i<items.size(); i++){ 5275 - if(!items[i]->is_starred()) continue; 5276 - if(starred_i == -1) starred_i = i; 5277 - else return false; // multiple StarredExpr not allowed 5278 - } 5279 - 5280 - if(starred_i == -1){ 5281 - ctx->emit(OP_UNPACK_SEQUENCE, items.size(), line); 5282 - }else{ 5283 - // starred assignment target must be in a tuple 5284 - if(items.size() == 1) return false; 5285 - // starred assignment target must be the last one (differ from cpython) 5286 - if(starred_i != items.size()-1) return false; 5287 - // a,*b = [1,2,3] 5288 - // stack is [1,2,3] -> [1,[2,3]] 5289 - ctx->emit(OP_UNPACK_EX, items.size()-1, line); 5290 - } 5291 - // do reverse emit 5292 - for(int i=items.size()-1; i>=0; i--){ 5293 - bool ok = items[i]->emit_store(ctx); 5294 - if(!ok) return false; 5295 - } 5296 - return true; 5297 - } 5298 - 5299 - bool emit_del(CodeEmitContext* ctx) override{ 5300 - for(auto& e: items){ 5301 - bool ok = e->emit_del(ctx); 5302 - if(!ok) return false; 5303 - } 5304 - return true; 5305 - } 5306 - }; 5307 - 5308 - struct CompExpr: Expr{ 5309 - Expr_ expr; // loop expr 5310 - Expr_ vars; // loop vars 5311 - Expr_ iter; // loop iter 5312 - Expr_ cond; // optional if condition 5313 - 5314 - virtual Opcode op0() = 0; 5315 - virtual Opcode op1() = 0; 5316 - 5317 - void emit(CodeEmitContext* ctx){ 5318 - ctx->emit(op0(), 0, line); 5319 - iter->emit(ctx); 5320 - ctx->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE); 5321 - ctx->enter_block(FOR_LOOP); 5322 - ctx->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE); 5323 - bool ok = vars->emit_store(ctx); 5324 - // this error occurs in `vars` instead of this line, but...nevermind 5325 - if(!ok) FATAL_ERROR(); // TODO: raise a SyntaxError instead 5326 - if(cond){ 5327 - cond->emit(ctx); 5328 - int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE); 5329 - expr->emit(ctx); 5330 - ctx->emit(op1(), BC_NOARG, BC_KEEPLINE); 5331 - ctx->patch_jump(patch); 5332 - }else{ 5333 - expr->emit(ctx); 5334 - ctx->emit(op1(), BC_NOARG, BC_KEEPLINE); 5335 - } 5336 - ctx->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE); 5337 - ctx->exit_block(); 5338 - } 5339 - }; 5340 - 5341 - struct ListCompExpr: CompExpr{ 5342 - Opcode op0() override { return OP_BUILD_LIST; } 5343 - Opcode op1() override { return OP_LIST_APPEND; } 5344 - std::string str() const override { return "ListComp()"; } 5345 - }; 5346 - 5347 - struct DictCompExpr: CompExpr{ 5348 - Opcode op0() override { return OP_BUILD_DICT; } 5349 - Opcode op1() override { return OP_DICT_ADD; } 5350 - std::string str() const override { return "DictComp()"; } 5351 - }; 5352 - 5353 - struct SetCompExpr: CompExpr{ 5354 - Opcode op0() override { return OP_BUILD_SET; } 5355 - Opcode op1() override { return OP_SET_ADD; } 5356 - std::string str() const override { return "SetComp()"; } 5357 - }; 5358 - 5359 - struct LambdaExpr: Expr{ 5360 - FuncDecl_ decl; 5361 - std::string str() const override { return "Lambda()"; } 5362 - 5363 - LambdaExpr(FuncDecl_ decl): decl(decl) {} 5364 - 5365 - void emit(CodeEmitContext* ctx) override { 5366 - int index = ctx->add_func_decl(decl); 5367 - ctx->emit(OP_LOAD_FUNCTION, index, line); 5368 - } 5369 - }; 5370 - 5371 - struct FStringExpr: Expr{ 5372 - Str src; 5373 - FStringExpr(const Str& src): src(src) {} 5374 - std::string str() const override { 5375 - return fmt("f", src.escape()); 5376 - } 5377 - 5378 - void emit(CodeEmitContext* ctx) override { 5379 - VM* vm = ctx->vm; 5380 - static const std::regex pattern(R"(\{(.*?)\})"); 5381 - std::cregex_iterator begin(src.begin(), src.end(), pattern); 5382 - std::cregex_iterator end; 5383 - int size = 0; 5384 - int i = 0; 5385 - for(auto it = begin; it != end; it++) { 5386 - std::cmatch m = *it; 5387 - if (i < m.position()) { 5388 - Str literal = src.substr(i, m.position() - i); 5389 - ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line); 5390 - size++; 5391 - } 5392 - Str expr = m[1].str(); 5393 - int conon = expr.index(":"); 5394 - if(conon >= 0){ 5395 - ctx->emit( 5396 - OP_LOAD_NAME, 5397 - StrName(expr.substr(0, conon)).index, 5398 - line 5399 - ); 5400 - Str spec = expr.substr(conon+1); 5401 - ctx->emit(OP_FORMAT_STRING, ctx->add_const(VAR(spec)), line); 5402 - }else{ 5403 - ctx->emit(OP_LOAD_NAME, StrName(expr).index, line); 5404 - } 5405 - size++; 5406 - i = (int)(m.position() + m.length()); 5407 - } 5408 - if (i < src.length()) { 5409 - Str literal = src.substr(i, src.length() - i); 5410 - ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line); 5411 - size++; 5412 - } 5413 - ctx->emit(OP_BUILD_STRING, size, line); 5414 - } 5415 - }; 5416 - 5417 - struct SubscrExpr: Expr{ 5418 - Expr_ a; 5419 - Expr_ b; 5420 - std::string str() const override { return "Subscr()"; } 5421 - 5422 - void emit(CodeEmitContext* ctx) override{ 5423 - a->emit(ctx); 5424 - b->emit(ctx); 5425 - ctx->emit(OP_LOAD_SUBSCR, BC_NOARG, line); 5426 - } 5427 - 5428 - bool emit_del(CodeEmitContext* ctx) override { 5429 - a->emit(ctx); 5430 - b->emit(ctx); 5431 - ctx->emit(OP_DELETE_SUBSCR, BC_NOARG, line); 5432 - return true; 5433 - } 5434 - 5435 - bool emit_store(CodeEmitContext* ctx) override { 5436 - a->emit(ctx); 5437 - b->emit(ctx); 5438 - ctx->emit(OP_STORE_SUBSCR, BC_NOARG, line); 5439 - return true; 5440 - } 5441 - }; 5442 - 5443 - struct AttribExpr: Expr{ 5444 - Expr_ a; 5445 - Str b; 5446 - AttribExpr(Expr_ a, const Str& b): a(std::move(a)), b(b) {} 5447 - AttribExpr(Expr_ a, Str&& b): a(std::move(a)), b(std::move(b)) {} 5448 - std::string str() const override { return "Attrib()"; } 5449 - 5450 - void emit(CodeEmitContext* ctx) override{ 5451 - a->emit(ctx); 5452 - int index = StrName(b).index; 5453 - ctx->emit(OP_LOAD_ATTR, index, line); 5454 - } 5455 - 5456 - bool emit_del(CodeEmitContext* ctx) override { 5457 - a->emit(ctx); 5458 - int index = StrName(b).index; 5459 - ctx->emit(OP_DELETE_ATTR, index, line); 5460 - return true; 5461 - } 5462 - 5463 - bool emit_store(CodeEmitContext* ctx) override { 5464 - a->emit(ctx); 5465 - int index = StrName(b).index; 5466 - ctx->emit(OP_STORE_ATTR, index, line); 5467 - return true; 5468 - } 5469 - 5470 - void emit_method(CodeEmitContext* ctx) { 5471 - a->emit(ctx); 5472 - int index = StrName(b).index; 5473 - ctx->emit(OP_LOAD_METHOD, index, line); 5474 - } 5475 - 5476 - bool is_attrib() const override { return true; } 5477 - }; 5478 - 5479 - struct CallExpr: Expr{ 5480 - Expr_ callable; 5481 - std::vector<Expr_> args; 5482 - std::vector<std::pair<Str, Expr_>> kwargs; 5483 - std::string str() const override { return "Call()"; } 5484 - 5485 - bool need_unpack() const { 5486 - for(auto& item: args) if(item->is_starred()) return true; 5487 - return false; 5488 - } 5489 - 5490 - void emit(CodeEmitContext* ctx) override { 5491 - VM* vm = ctx->vm; 5492 - if(need_unpack()) ctx->emit(OP_BEGIN_CALL, BC_NOARG, line); 5493 - // if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` proxy 5494 - if(callable->is_attrib()){ 5495 - auto p = static_cast<AttribExpr*>(callable.get()); 5496 - p->emit_method(ctx); 5497 - }else{ 5498 - callable->emit(ctx); 5499 - ctx->emit(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE); 5500 - } 5501 - // emit args 5502 - for(auto& item: args) item->emit(ctx); 5503 - // emit kwargs 5504 - for(auto& item: kwargs){ 5505 - int index = StrName::get(item.first.sv()).index; 5506 - ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(index)), line); 5507 - item.second->emit(ctx); 5508 - } 5509 - int KWARGC = (int)kwargs.size(); 5510 - int ARGC = (int)args.size(); 5511 - if(need_unpack()) ARGC = 0xFFFF; 5512 - ctx->emit(OP_CALL, (KWARGC<<16)|ARGC, line); 5513 - } 5514 - }; 5515 - 5516 - struct BinaryExpr: Expr{ 5517 - TokenIndex op; 5518 - Expr_ lhs; 5519 - Expr_ rhs; 5520 - std::string str() const override { return TK_STR(op); } 5521 - 5522 - void emit(CodeEmitContext* ctx) override { 5523 - lhs->emit(ctx); 5524 - rhs->emit(ctx); 5525 - switch (op) { 5526 - case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break; 5527 - case TK("-"): ctx->emit(OP_BINARY_SUB, BC_NOARG, line); break; 5528 - case TK("*"): ctx->emit(OP_BINARY_MUL, BC_NOARG, line); break; 5529 - case TK("/"): ctx->emit(OP_BINARY_OP, 3, line); break; 5530 - case TK("//"): ctx->emit(OP_BINARY_FLOORDIV, BC_NOARG, line); break; 5531 - case TK("%"): ctx->emit(OP_BINARY_MOD, BC_NOARG, line); break; 5532 - case TK("**"): ctx->emit(OP_BINARY_OP, 6, line); break; 5533 - 5534 - case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break; 5535 - case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break; 5536 - case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break; 5537 - case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break; 5538 - case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break; 5539 - case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break; 5540 - case TK("in"): ctx->emit(OP_CONTAINS_OP, 0, line); break; 5541 - case TK("not in"): ctx->emit(OP_CONTAINS_OP, 1, line); break; 5542 - case TK("is"): ctx->emit(OP_IS_OP, 0, line); break; 5543 - case TK("is not"): ctx->emit(OP_IS_OP, 1, line); break; 5544 - 5545 - case TK("<<"): ctx->emit(OP_BITWISE_LSHIFT, BC_NOARG, line); break; 5546 - case TK(">>"): ctx->emit(OP_BITWISE_RSHIFT, BC_NOARG, line); break; 5547 - case TK("&"): ctx->emit(OP_BITWISE_AND, BC_NOARG, line); break; 5548 - case TK("|"): ctx->emit(OP_BITWISE_OR, BC_NOARG, line); break; 5549 - case TK("^"): ctx->emit(OP_BITWISE_XOR, BC_NOARG, line); break; 5550 - default: FATAL_ERROR(); 5551 - } 5552 - } 5553 - }; 5554 - 5555 - 5556 - struct TernaryExpr: Expr{ 5557 - Expr_ cond; 5558 - Expr_ true_expr; 5559 - Expr_ false_expr; 5560 - std::string str() const override { return "Ternary()"; } 5561 - 5562 - void emit(CodeEmitContext* ctx) override { 5563 - cond->emit(ctx); 5564 - int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, cond->line); 5565 - true_expr->emit(ctx); 5566 - int patch_2 = ctx->emit(OP_JUMP_ABSOLUTE, BC_NOARG, true_expr->line); 5567 - ctx->patch_jump(patch); 5568 - false_expr->emit(ctx); 5569 - ctx->patch_jump(patch_2); 5570 - } 5571 - }; 5572 - 5573 - 5574 - } // namespace pkpy 5575 - 5576 - 5577 - namespace pkpy{ 5578 - 5579 - class Compiler; 5580 - typedef void (Compiler::*PrattCallback)(); 5581 - 5582 - struct PrattRule{ 5583 - PrattCallback prefix; 5584 - PrattCallback infix; 5585 - Precedence precedence; 5586 - }; 5587 - 5588 - class Compiler { 5589 - inline static PrattRule rules[kTokenCount]; 5590 - std::unique_ptr<Lexer> lexer; 5591 - stack<CodeEmitContext> contexts; 5592 - VM* vm; 5593 - bool unknown_global_scope; // for eval/exec() call 5594 - bool used; 5595 - // for parsing token stream 5596 - int i = 0; 5597 - std::vector<Token> tokens; 5598 - 5599 - const Token& prev() const{ return tokens.at(i-1); } 5600 - const Token& curr() const{ return tokens.at(i); } 5601 - const Token& next() const{ return tokens.at(i+1); } 5602 - const Token& err() const{ 5603 - if(i >= tokens.size()) return prev(); 5604 - return curr(); 5605 - } 5606 - void advance(int delta=1) { i += delta; } 5607 - 5608 - CodeEmitContext* ctx() { return &contexts.top(); } 5609 - CompileMode mode() const{ return lexer->src->mode; } 5610 - NameScope name_scope() const { 5611 - auto s = contexts.size()>1 ? NAME_LOCAL : NAME_GLOBAL; 5612 - if(unknown_global_scope && s == NAME_GLOBAL) s = NAME_GLOBAL_UNKNOWN; 5613 - return s; 5614 - } 5615 - 5616 - CodeObject_ push_global_context(){ 5617 - CodeObject_ co = make_sp<CodeObject>(lexer->src, lexer->src->filename); 5618 - contexts.push(CodeEmitContext(vm, co, contexts.size())); 5619 - return co; 5620 - } 5621 - 5622 - FuncDecl_ push_f_context(Str name){ 5623 - FuncDecl_ decl = make_sp<FuncDecl>(); 5624 - decl->code = make_sp<CodeObject>(lexer->src, name); 5625 - decl->nested = name_scope() == NAME_LOCAL; 5626 - contexts.push(CodeEmitContext(vm, decl->code, contexts.size())); 5627 - return decl; 5628 - } 5629 - 5630 - void pop_context(){ 5631 - if(!ctx()->s_expr.empty()){ 5632 - throw std::runtime_error("!ctx()->s_expr.empty()\n" + ctx()->_log_s_expr()); 5633 - } 5634 - // add a `return None` in the end as a guard 5635 - // previously, we only do this if the last opcode is not a return 5636 - // however, this is buggy...since there may be a jump to the end (out of bound) even if the last opcode is a return 5637 - ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE); 5638 - ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); 5639 - ctx()->co->optimize(vm); 5640 - if(ctx()->co->varnames.size() > PK_MAX_CO_VARNAMES){ 5641 - SyntaxError("maximum number of local variables exceeded"); 5642 - } 5643 - contexts.pop(); 5644 - } 5645 - 5646 - static void init_pratt_rules(){ 5647 - if(rules[TK(".")].precedence != PREC_NONE) return; 5648 - // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ 5649 - #define METHOD(name) &Compiler::name 5650 - #define NO_INFIX nullptr, PREC_NONE 5651 - for(TokenIndex i=0; i<kTokenCount; i++) rules[i] = { nullptr, NO_INFIX }; 5652 - rules[TK(".")] = { nullptr, METHOD(exprAttrib), PREC_ATTRIB }; 5653 - rules[TK("(")] = { METHOD(exprGroup), METHOD(exprCall), PREC_CALL }; 5654 - rules[TK("[")] = { METHOD(exprList), METHOD(exprSubscr), PREC_SUBSCRIPT }; 5655 - rules[TK("{")] = { METHOD(exprMap), NO_INFIX }; 5656 - rules[TK("%")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR }; 5657 - rules[TK("+")] = { nullptr, METHOD(exprBinaryOp), PREC_TERM }; 5658 - rules[TK("-")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_TERM }; 5659 - rules[TK("*")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_FACTOR }; 5660 - rules[TK("/")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR }; 5661 - rules[TK("//")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR }; 5662 - rules[TK("**")] = { nullptr, METHOD(exprBinaryOp), PREC_EXPONENT }; 5663 - rules[TK(">")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; 5664 - rules[TK("<")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; 5665 - rules[TK("==")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY }; 5666 - rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY }; 5667 - rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; 5668 - rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; 5669 - rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; 5670 - rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; 5671 - rules[TK("<<")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; 5672 - rules[TK(">>")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; 5673 - rules[TK("&")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_AND }; 5674 - rules[TK("|")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_OR }; 5675 - rules[TK("^")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_XOR }; 5676 - rules[TK("if")] = { nullptr, METHOD(exprTernary), PREC_TERNARY }; 5677 - rules[TK(",")] = { nullptr, METHOD(exprTuple), PREC_TUPLE }; 5678 - rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; 5679 - rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; 5680 - rules[TK("and") ] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND }; 5681 - rules[TK("or")] = { nullptr, METHOD(exprOr), PREC_LOGICAL_OR }; 5682 - rules[TK("not")] = { METHOD(exprNot), nullptr, PREC_LOGICAL_NOT }; 5683 - rules[TK("True")] = { METHOD(exprLiteral0), NO_INFIX }; 5684 - rules[TK("False")] = { METHOD(exprLiteral0), NO_INFIX }; 5685 - rules[TK("None")] = { METHOD(exprLiteral0), NO_INFIX }; 5686 - rules[TK("...")] = { METHOD(exprLiteral0), NO_INFIX }; 5687 - rules[TK("lambda")] = { METHOD(exprLambda), NO_INFIX }; 5688 - rules[TK("@id")] = { METHOD(exprName), NO_INFIX }; 5689 - rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX }; 5690 - rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX }; 5691 - rules[TK("@fstr")] = { METHOD(exprFString), NO_INFIX }; 5692 - #undef METHOD 5693 - #undef NO_INFIX 5694 - } 5695 - 5696 - bool match(TokenIndex expected) { 5697 - if (curr().type != expected) return false; 5698 - advance(); 5699 - return true; 5700 - } 5701 - 5702 - void consume(TokenIndex expected) { 5703 - if (!match(expected)){ 5704 - SyntaxError( 5705 - fmt("expected '", TK_STR(expected), "', but got '", TK_STR(curr().type), "'") 5706 - ); 5707 - } 5708 - } 5709 - 5710 - bool match_newlines_repl(){ 5711 - return match_newlines(mode()==REPL_MODE); 5712 - } 5713 - 5714 - bool match_newlines(bool repl_throw=false) { 5715 - bool consumed = false; 5716 - if (curr().type == TK("@eol")) { 5717 - while (curr().type == TK("@eol")) advance(); 5718 - consumed = true; 5719 - } 5720 - if (repl_throw && curr().type == TK("@eof")){ 5721 - throw NeedMoreLines(ctx()->is_compiling_class); 5722 - } 5723 - return consumed; 5724 - } 5725 - 5726 - bool match_end_stmt() { 5727 - if (match(TK(";"))) { match_newlines(); return true; } 5728 - if (match_newlines() || curr().type == TK("@eof")) return true; 5729 - if (curr().type == TK("@dedent")) return true; 5730 - return false; 5731 - } 5732 - 5733 - void consume_end_stmt() { 5734 - if (!match_end_stmt()) SyntaxError("expected statement end"); 5735 - } 5736 - 5737 - /*************************************************/ 5738 - 5739 - void EXPR(bool push_stack=true) { 5740 - parse_expression(PREC_TUPLE+1, push_stack); 5741 - } 5742 - 5743 - void EXPR_TUPLE(bool push_stack=true) { 5744 - parse_expression(PREC_TUPLE, push_stack); 5745 - } 5746 - 5747 - // special case for `for loop` and `comp` 5748 - Expr_ EXPR_VARS(){ 5749 - std::vector<Expr_> items; 5750 - do { 5751 - consume(TK("@id")); 5752 - items.push_back(make_expr<NameExpr>(prev().str(), name_scope())); 5753 - } while(match(TK(","))); 5754 - if(items.size()==1) return std::move(items[0]); 5755 - return make_expr<TupleExpr>(std::move(items)); 5756 - } 5757 - 5758 - template <typename T, typename... Args> 5759 - std::unique_ptr<T> make_expr(Args&&... args) { 5760 - std::unique_ptr<T> expr = std::make_unique<T>(std::forward<Args>(args)...); 5761 - expr->line = prev().line; 5762 - return expr; 5763 - } 5764 - 5765 - 5766 - void exprLiteral(){ 5767 - ctx()->s_expr.push(make_expr<LiteralExpr>(prev().value)); 5768 - } 5769 - 5770 - 5771 - void exprFString(){ 5772 - ctx()->s_expr.push(make_expr<FStringExpr>(std::get<Str>(prev().value))); 5773 - } 5774 - 5775 - 5776 - void exprLambda(){ 5777 - FuncDecl_ decl = push_f_context("<lambda>"); 5778 - auto e = make_expr<LambdaExpr>(decl); 5779 - if(!match(TK(":"))){ 5780 - _compile_f_args(e->decl, false); 5781 - consume(TK(":")); 5782 - } 5783 - // https://github.com/blueloveTH/pocketpy/issues/37 5784 - parse_expression(PREC_LAMBDA + 1, false); 5785 - ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); 5786 - pop_context(); 5787 - ctx()->s_expr.push(std::move(e)); 5788 - } 5789 - 5790 - 5791 - void exprTuple(){ 5792 - std::vector<Expr_> items; 5793 - items.push_back(ctx()->s_expr.popx()); 5794 - do { 5795 - EXPR(); // NOTE: "1," will fail, "1,2" will be ok 5796 - items.push_back(ctx()->s_expr.popx()); 5797 - } while(match(TK(","))); 5798 - ctx()->s_expr.push(make_expr<TupleExpr>( 5799 - std::move(items) 5800 - )); 5801 - } 5802 - 5803 - 5804 - void exprOr(){ 5805 - auto e = make_expr<OrExpr>(); 5806 - e->lhs = ctx()->s_expr.popx(); 5807 - parse_expression(PREC_LOGICAL_OR + 1); 5808 - e->rhs = ctx()->s_expr.popx(); 5809 - ctx()->s_expr.push(std::move(e)); 5810 - } 5811 - 5812 - 5813 - void exprAnd(){ 5814 - auto e = make_expr<AndExpr>(); 5815 - e->lhs = ctx()->s_expr.popx(); 5816 - parse_expression(PREC_LOGICAL_AND + 1); 5817 - e->rhs = ctx()->s_expr.popx(); 5818 - ctx()->s_expr.push(std::move(e)); 5819 - } 5820 - 5821 - 5822 - void exprTernary(){ 5823 - auto e = make_expr<TernaryExpr>(); 5824 - e->true_expr = ctx()->s_expr.popx(); 5825 - // cond 5826 - parse_expression(PREC_TERNARY + 1); 5827 - e->cond = ctx()->s_expr.popx(); 5828 - consume(TK("else")); 5829 - // if false 5830 - parse_expression(PREC_TERNARY + 1); 5831 - e->false_expr = ctx()->s_expr.popx(); 5832 - ctx()->s_expr.push(std::move(e)); 5833 - } 5834 - 5835 - 5836 - void exprBinaryOp(){ 5837 - auto e = make_expr<BinaryExpr>(); 5838 - e->op = prev().type; 5839 - e->lhs = ctx()->s_expr.popx(); 5840 - parse_expression(rules[e->op].precedence + 1); 5841 - e->rhs = ctx()->s_expr.popx(); 5842 - ctx()->s_expr.push(std::move(e)); 5843 - } 5844 - 5845 - 5846 - void exprNot() { 5847 - parse_expression(PREC_LOGICAL_NOT + 1); 5848 - ctx()->s_expr.push(make_expr<NotExpr>(ctx()->s_expr.popx())); 5849 - } 5850 - 5851 - 5852 - void exprUnaryOp(){ 5853 - TokenIndex op = prev().type; 5854 - parse_expression(PREC_UNARY + 1); 5855 - switch(op){ 5856 - case TK("-"): 5857 - ctx()->s_expr.push(make_expr<NegatedExpr>(ctx()->s_expr.popx())); 5858 - break; 5859 - case TK("*"): 5860 - ctx()->s_expr.push(make_expr<StarredExpr>(ctx()->s_expr.popx())); 5861 - break; 5862 - default: FATAL_ERROR(); 5863 - } 5864 - } 5865 - 5866 - 5867 - void exprGroup(){ 5868 - match_newlines_repl(); 5869 - EXPR_TUPLE(); // () is just for change precedence 5870 - match_newlines_repl(); 5871 - consume(TK(")")); 5872 - } 5873 - 5874 - 5875 - template<typename T> 5876 - void _consume_comp(Expr_ expr){ 5877 - static_assert(std::is_base_of<CompExpr, T>::value); 5878 - std::unique_ptr<CompExpr> ce = make_expr<T>(); 5879 - ce->expr = std::move(expr); 5880 - ce->vars = EXPR_VARS(); 5881 - consume(TK("in")); 5882 - parse_expression(PREC_TERNARY + 1); 5883 - ce->iter = ctx()->s_expr.popx(); 5884 - match_newlines_repl(); 5885 - if(match(TK("if"))){ 5886 - parse_expression(PREC_TERNARY + 1); 5887 - ce->cond = ctx()->s_expr.popx(); 5888 - } 5889 - ctx()->s_expr.push(std::move(ce)); 5890 - match_newlines_repl(); 5891 - } 5892 - 5893 - 5894 - void exprList() { 5895 - int line = prev().line; 5896 - std::vector<Expr_> items; 5897 - do { 5898 - match_newlines_repl(); 5899 - if (curr().type == TK("]")) break; 5900 - EXPR(); 5901 - items.push_back(ctx()->s_expr.popx()); 5902 - match_newlines_repl(); 5903 - if(items.size()==1 && match(TK("for"))){ 5904 - _consume_comp<ListCompExpr>(std::move(items[0])); 5905 - consume(TK("]")); 5906 - return; 5907 - } 5908 - match_newlines_repl(); 5909 - } while (match(TK(","))); 5910 - consume(TK("]")); 5911 - auto e = make_expr<ListExpr>(std::move(items)); 5912 - e->line = line; // override line 5913 - ctx()->s_expr.push(std::move(e)); 5914 - } 5915 - 5916 - 5917 - void exprMap() { 5918 - bool parsing_dict = false; // {...} may be dict or set 5919 - std::vector<Expr_> items; 5920 - do { 5921 - match_newlines_repl(); 5922 - if (curr().type == TK("}")) break; 5923 - EXPR(); 5924 - if(curr().type == TK(":")) parsing_dict = true; 5925 - if(parsing_dict){ 5926 - consume(TK(":")); 5927 - EXPR(); 5928 - auto dict_item = make_expr<DictItemExpr>(); 5929 - dict_item->key = ctx()->s_expr.popx(); 5930 - dict_item->value = ctx()->s_expr.popx(); 5931 - items.push_back(std::move(dict_item)); 5932 - }else{ 5933 - items.push_back(ctx()->s_expr.popx()); 5934 - } 5935 - match_newlines_repl(); 5936 - if(items.size()==1 && match(TK("for"))){ 5937 - if(parsing_dict) _consume_comp<DictCompExpr>(std::move(items[0])); 5938 - else _consume_comp<SetCompExpr>(std::move(items[0])); 5939 - consume(TK("}")); 5940 - return; 5941 - } 5942 - match_newlines_repl(); 5943 - } while (match(TK(","))); 5944 - consume(TK("}")); 5945 - if(items.size()==0 || parsing_dict){ 5946 - auto e = make_expr<DictExpr>(std::move(items)); 5947 - ctx()->s_expr.push(std::move(e)); 5948 - }else{ 5949 - auto e = make_expr<SetExpr>(std::move(items)); 5950 - ctx()->s_expr.push(std::move(e)); 5951 - } 5952 - } 5953 - 5954 - 5955 - void exprCall() { 5956 - auto e = make_expr<CallExpr>(); 5957 - e->callable = ctx()->s_expr.popx(); 5958 - do { 5959 - match_newlines_repl(); 5960 - if (curr().type==TK(")")) break; 5961 - if(curr().type==TK("@id") && next().type==TK("=")) { 5962 - consume(TK("@id")); 5963 - Str key = prev().str(); 5964 - consume(TK("=")); 5965 - EXPR(); 5966 - e->kwargs.push_back({key, ctx()->s_expr.popx()}); 5967 - } else{ 5968 - if(!e->kwargs.empty()) SyntaxError("positional argument follows keyword argument"); 5969 - EXPR(); 5970 - e->args.push_back(ctx()->s_expr.popx()); 5971 - } 5972 - match_newlines_repl(); 5973 - } while (match(TK(","))); 5974 - consume(TK(")")); 5975 - if(e->args.size() > 32767) SyntaxError("too many positional arguments"); 5976 - if(e->kwargs.size() > 32767) SyntaxError("too many keyword arguments"); 5977 - ctx()->s_expr.push(std::move(e)); 5978 - } 5979 - 5980 - 5981 - void exprName(){ 5982 - Str name = prev().str(); 5983 - NameScope scope = name_scope(); 5984 - if(ctx()->co->global_names.count(name)){ 5985 - scope = NAME_GLOBAL; 5986 - } 5987 - ctx()->s_expr.push(make_expr<NameExpr>(name, scope)); 5988 - } 5989 - 5990 - 5991 - void exprAttrib() { 5992 - consume(TK("@id")); 5993 - ctx()->s_expr.push( 5994 - make_expr<AttribExpr>(ctx()->s_expr.popx(), prev().str()) 5995 - ); 5996 - } 5997 - 5998 - 5999 - void exprSubscr() { 6000 - auto e = make_expr<SubscrExpr>(); 6001 - e->a = ctx()->s_expr.popx(); 6002 - auto slice = make_expr<SliceExpr>(); 6003 - bool is_slice = false; 6004 - // a[<0> <state:1> : state<3> : state<5>] 6005 - int state = 0; 6006 - do{ 6007 - switch(state){ 6008 - case 0: 6009 - if(match(TK(":"))){ 6010 - is_slice=true; 6011 - state=2; 6012 - break; 6013 - } 6014 - if(match(TK("]"))) SyntaxError(); 6015 - EXPR_TUPLE(); 6016 - slice->start = ctx()->s_expr.popx(); 6017 - state=1; 6018 - break; 6019 - case 1: 6020 - if(match(TK(":"))){ 6021 - is_slice=true; 6022 - state=2; 6023 - break; 6024 - } 6025 - if(match(TK("]"))) goto __SUBSCR_END; 6026 - SyntaxError("expected ':' or ']'"); 6027 - break; 6028 - case 2: 6029 - if(match(TK(":"))){ 6030 - state=4; 6031 - break; 6032 - } 6033 - if(match(TK("]"))) goto __SUBSCR_END; 6034 - EXPR_TUPLE(); 6035 - slice->stop = ctx()->s_expr.popx(); 6036 - state=3; 6037 - break; 6038 - case 3: 6039 - if(match(TK(":"))){ 6040 - state=4; 6041 - break; 6042 - } 6043 - if(match(TK("]"))) goto __SUBSCR_END; 6044 - SyntaxError("expected ':' or ']'"); 6045 - break; 6046 - case 4: 6047 - if(match(TK("]"))) goto __SUBSCR_END; 6048 - EXPR_TUPLE(); 6049 - slice->step = ctx()->s_expr.popx(); 6050 - state=5; 6051 - break; 6052 - case 5: consume(TK("]")); goto __SUBSCR_END; 6053 - } 6054 - }while(true); 6055 - __SUBSCR_END: 6056 - if(is_slice){ 6057 - e->b = std::move(slice); 6058 - }else{ 6059 - if(state != 1) FATAL_ERROR(); 6060 - e->b = std::move(slice->start); 6061 - } 6062 - ctx()->s_expr.push(std::move(e)); 6063 - } 6064 - 6065 - 6066 - void exprLiteral0() { 6067 - ctx()->s_expr.push(make_expr<Literal0Expr>(prev().type)); 6068 - } 6069 - 6070 - void compile_block_body() { 6071 - consume(TK(":")); 6072 - if(curr().type!=TK("@eol") && curr().type!=TK("@eof")){ 6073 - compile_stmt(); // inline block 6074 - return; 6075 - } 6076 - if(!match_newlines(mode()==REPL_MODE)){ 6077 - SyntaxError("expected a new line after ':'"); 6078 - } 6079 - consume(TK("@indent")); 6080 - while (curr().type != TK("@dedent")) { 6081 - match_newlines(); 6082 - compile_stmt(); 6083 - match_newlines(); 6084 - } 6085 - consume(TK("@dedent")); 6086 - } 6087 - 6088 - Str _compile_import() { 6089 - if(name_scope() != NAME_GLOBAL) SyntaxError("import statement should be used in global scope"); 6090 - consume(TK("@id")); 6091 - Str name = prev().str(); 6092 - ctx()->emit(OP_IMPORT_NAME, StrName(name).index, prev().line); 6093 - return name; 6094 - } 6095 - 6096 - // import a as b 6097 - void compile_normal_import() { 6098 - do { 6099 - Str name = _compile_import(); 6100 - if (match(TK("as"))) { 6101 - consume(TK("@id")); 6102 - name = prev().str(); 6103 - } 6104 - ctx()->emit(OP_STORE_GLOBAL, StrName(name).index, prev().line); 6105 - } while (match(TK(","))); 6106 - consume_end_stmt(); 6107 - } 6108 - 6109 - // from a import b as c, d as e 6110 - void compile_from_import() { 6111 - _compile_import(); 6112 - consume(TK("import")); 6113 - if (match(TK("*"))) { 6114 - ctx()->emit(OP_IMPORT_STAR, BC_NOARG, prev().line); 6115 - consume_end_stmt(); 6116 - return; 6117 - } 6118 - do { 6119 - ctx()->emit(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE); 6120 - consume(TK("@id")); 6121 - Str name = prev().str(); 6122 - ctx()->emit(OP_LOAD_ATTR, StrName(name).index, prev().line); 6123 - if (match(TK("as"))) { 6124 - consume(TK("@id")); 6125 - name = prev().str(); 6126 - } 6127 - ctx()->emit(OP_STORE_GLOBAL, StrName(name).index, prev().line); 6128 - } while (match(TK(","))); 6129 - ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE); 6130 - consume_end_stmt(); 6131 - } 6132 - 6133 - void parse_expression(int precedence, bool push_stack=true) { 6134 - advance(); 6135 - PrattCallback prefix = rules[prev().type].prefix; 6136 - if (prefix == nullptr) SyntaxError(Str("expected an expression, but got ") + TK_STR(prev().type)); 6137 - (this->*prefix)(); 6138 - while (rules[curr().type].precedence >= precedence) { 6139 - TokenIndex op = curr().type; 6140 - advance(); 6141 - PrattCallback infix = rules[op].infix; 6142 - if(infix == nullptr) throw std::runtime_error("(infix == nullptr) is true"); 6143 - (this->*infix)(); 6144 - } 6145 - if(!push_stack) ctx()->emit_expr(); 6146 - } 6147 - 6148 - 6149 - void compile_if_stmt() { 6150 - EXPR(false); // condition 6151 - int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line); 6152 - compile_block_body(); 6153 - if (match(TK("elif"))) { 6154 - int exit_patch = ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line); 6155 - ctx()->patch_jump(patch); 6156 - compile_if_stmt(); 6157 - ctx()->patch_jump(exit_patch); 6158 - } else if (match(TK("else"))) { 6159 - int exit_patch = ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, prev().line); 6160 - ctx()->patch_jump(patch); 6161 - compile_block_body(); 6162 - ctx()->patch_jump(exit_patch); 6163 - } else { 6164 - ctx()->patch_jump(patch); 6165 - } 6166 - } 6167 - 6168 - 6169 - void compile_while_loop() { 6170 - ctx()->enter_block(WHILE_LOOP); 6171 - EXPR(false); // condition 6172 - int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line); 6173 - compile_block_body(); 6174 - ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE); 6175 - ctx()->patch_jump(patch); 6176 - ctx()->exit_block(); 6177 - } 6178 - 6179 - 6180 - void compile_for_loop() { 6181 - Expr_ vars = EXPR_VARS(); 6182 - consume(TK("in")); 6183 - EXPR_TUPLE(false); 6184 - ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE); 6185 - ctx()->enter_block(FOR_LOOP); 6186 - ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE); 6187 - bool ok = vars->emit_store(ctx()); 6188 - if(!ok) SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind 6189 - compile_block_body(); 6190 - ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE); 6191 - ctx()->exit_block(); 6192 - } 6193 - 6194 - void compile_try_except() { 6195 - ctx()->enter_block(TRY_EXCEPT); 6196 - compile_block_body(); 6197 - std::vector<int> patches = { 6198 - ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE) 6199 - }; 6200 - ctx()->exit_block(); 6201 - do { 6202 - consume(TK("except")); 6203 - if(match(TK("@id"))){ 6204 - ctx()->emit(OP_EXCEPTION_MATCH, StrName(prev().str()).index, prev().line); 6205 - }else{ 6206 - ctx()->emit(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE); 6207 - } 6208 - int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE); 6209 - // pop the exception on match 6210 - ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE); 6211 - compile_block_body(); 6212 - patches.push_back(ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)); 6213 - ctx()->patch_jump(patch); 6214 - }while(curr().type == TK("except")); 6215 - // no match, re-raise 6216 - ctx()->emit(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE); 6217 - for (int patch : patches) ctx()->patch_jump(patch); 6218 - } 6219 - 6220 - void compile_decorated(){ 6221 - std::vector<Expr_> decorators; 6222 - do{ 6223 - EXPR(); 6224 - decorators.push_back(ctx()->s_expr.popx()); 6225 - if(!match_newlines_repl()) SyntaxError(); 6226 - }while(match(TK("@"))); 6227 - consume(TK("def")); 6228 - compile_function(decorators); 6229 - } 6230 - 6231 - bool try_compile_assignment(){ 6232 - Expr* lhs_p = ctx()->s_expr.top().get(); 6233 - bool inplace; 6234 - switch (curr().type) { 6235 - case TK("+="): case TK("-="): case TK("*="): case TK("/="): case TK("//="): case TK("%="): 6236 - case TK("<<="): case TK(">>="): case TK("&="): case TK("|="): case TK("^="): { 6237 - if(ctx()->is_compiling_class) SyntaxError(); 6238 - inplace = true; 6239 - advance(); 6240 - auto e = make_expr<BinaryExpr>(); 6241 - e->op = prev().type - 1; // -1 to remove = 6242 - e->lhs = ctx()->s_expr.popx(); 6243 - EXPR_TUPLE(); 6244 - e->rhs = ctx()->s_expr.popx(); 6245 - ctx()->s_expr.push(std::move(e)); 6246 - } break; 6247 - case TK("="): 6248 - inplace = false; 6249 - advance(); 6250 - EXPR_TUPLE(); 6251 - break; 6252 - default: return false; 6253 - } 6254 - // std::cout << ctx()->_log_s_expr() << std::endl; 6255 - Expr_ rhs = ctx()->s_expr.popx(); 6256 - 6257 - if(lhs_p->is_starred() || rhs->is_starred()){ 6258 - SyntaxError("can't use starred expression here"); 6259 - } 6260 - 6261 - rhs->emit(ctx()); 6262 - bool ok = lhs_p->emit_store(ctx()); 6263 - if(!ok) SyntaxError(); 6264 - if(!inplace) ctx()->s_expr.pop(); 6265 - return true; 6266 - } 6267 - 6268 - void compile_stmt() { 6269 - advance(); 6270 - int kw_line = prev().line; // backup line number 6271 - switch(prev().type){ 6272 - case TK("break"): 6273 - if (!ctx()->is_curr_block_loop()) SyntaxError("'break' outside loop"); 6274 - ctx()->emit(OP_LOOP_BREAK, BC_NOARG, kw_line); 6275 - consume_end_stmt(); 6276 - break; 6277 - case TK("continue"): 6278 - if (!ctx()->is_curr_block_loop()) SyntaxError("'continue' not properly in loop"); 6279 - ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, kw_line); 6280 - consume_end_stmt(); 6281 - break; 6282 - case TK("yield"): 6283 - if (contexts.size() <= 1) SyntaxError("'yield' outside function"); 6284 - EXPR_TUPLE(false); 6285 - // if yield present, mark the function as generator 6286 - ctx()->co->is_generator = true; 6287 - ctx()->emit(OP_YIELD_VALUE, BC_NOARG, kw_line); 6288 - consume_end_stmt(); 6289 - break; 6290 - case TK("yield from"): 6291 - if (contexts.size() <= 1) SyntaxError("'yield from' outside function"); 6292 - EXPR_TUPLE(false); 6293 - // if yield from present, mark the function as generator 6294 - ctx()->co->is_generator = true; 6295 - ctx()->emit(OP_GET_ITER, BC_NOARG, kw_line); 6296 - ctx()->enter_block(FOR_LOOP); 6297 - ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE); 6298 - ctx()->emit(OP_YIELD_VALUE, BC_NOARG, BC_KEEPLINE); 6299 - ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE); 6300 - ctx()->exit_block(); 6301 - consume_end_stmt(); 6302 - break; 6303 - case TK("return"): 6304 - if (contexts.size() <= 1) SyntaxError("'return' outside function"); 6305 - if(match_end_stmt()){ 6306 - ctx()->emit(OP_LOAD_NONE, BC_NOARG, kw_line); 6307 - }else{ 6308 - EXPR_TUPLE(false); 6309 - consume_end_stmt(); 6310 - } 6311 - ctx()->emit(OP_RETURN_VALUE, BC_NOARG, kw_line); 6312 - break; 6313 - /*************************************************/ 6314 - case TK("if"): compile_if_stmt(); break; 6315 - case TK("while"): compile_while_loop(); break; 6316 - case TK("for"): compile_for_loop(); break; 6317 - case TK("import"): compile_normal_import(); break; 6318 - case TK("from"): compile_from_import(); break; 6319 - case TK("def"): compile_function(); break; 6320 - case TK("@"): compile_decorated(); break; 6321 - case TK("try"): compile_try_except(); break; 6322 - case TK("pass"): consume_end_stmt(); break; 6323 - /*************************************************/ 6324 - case TK("assert"): 6325 - EXPR_TUPLE(false); 6326 - ctx()->emit(OP_ASSERT, BC_NOARG, kw_line); 6327 - consume_end_stmt(); 6328 - break; 6329 - case TK("global"): 6330 - do { 6331 - consume(TK("@id")); 6332 - ctx()->co->global_names.insert(prev().str()); 6333 - } while (match(TK(","))); 6334 - consume_end_stmt(); 6335 - break; 6336 - case TK("raise"): { 6337 - consume(TK("@id")); 6338 - int dummy_t = StrName(prev().str()).index; 6339 - if(match(TK("(")) && !match(TK(")"))){ 6340 - EXPR(false); consume(TK(")")); 6341 - }else{ 6342 - ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE); 6343 - } 6344 - ctx()->emit(OP_RAISE, dummy_t, kw_line); 6345 - consume_end_stmt(); 6346 - } break; 6347 - case TK("del"): { 6348 - EXPR_TUPLE(); 6349 - Expr_ e = ctx()->s_expr.popx(); 6350 - bool ok = e->emit_del(ctx()); 6351 - if(!ok) SyntaxError(); 6352 - consume_end_stmt(); 6353 - } break; 6354 - case TK("with"): { 6355 - EXPR(false); 6356 - consume(TK("as")); 6357 - consume(TK("@id")); 6358 - StrName name(prev().str()); 6359 - ctx()->emit(OP_STORE_NAME, name.index, prev().line); 6360 - ctx()->emit(OP_LOAD_NAME, name.index, prev().line); 6361 - ctx()->emit(OP_WITH_ENTER, BC_NOARG, prev().line); 6362 - compile_block_body(); 6363 - ctx()->emit(OP_LOAD_NAME, name.index, prev().line); 6364 - ctx()->emit(OP_WITH_EXIT, BC_NOARG, prev().line); 6365 - } break; 6366 - /*************************************************/ 6367 - case TK("$label"): { 6368 - if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE"); 6369 - consume(TK("@id")); 6370 - bool ok = ctx()->add_label(prev().str()); 6371 - if(!ok) SyntaxError("label " + prev().str().escape() + " already exists"); 6372 - consume_end_stmt(); 6373 - } break; 6374 - case TK("$goto"): 6375 - if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE"); 6376 - consume(TK("@id")); 6377 - ctx()->emit(OP_GOTO, StrName(prev().str()).index, prev().line); 6378 - consume_end_stmt(); 6379 - break; 6380 - /*************************************************/ 6381 - // handle dangling expression or assignment 6382 - default: { 6383 - advance(-1); // do revert since we have pre-called advance() at the beginning 6384 - EXPR_TUPLE(); 6385 - if(!try_compile_assignment()){ 6386 - ctx()->emit_expr(); 6387 - if(mode()==REPL_MODE && name_scope()==NAME_GLOBAL){ 6388 - ctx()->emit(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE); 6389 - }else{ 6390 - ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE); 6391 - } 6392 - } 6393 - consume_end_stmt(); 6394 - } 6395 - } 6396 - } 6397 - 6398 - 6399 - void compile_class(){ 6400 - consume(TK("@id")); 6401 - int namei = StrName(prev().str()).index; 6402 - int super_namei = -1; 6403 - if(match(TK("(")) && match(TK("@id"))){ 6404 - super_namei = StrName(prev().str()).index; 6405 - consume(TK(")")); 6406 - } 6407 - if(super_namei == -1) ctx()->emit(OP_LOAD_NONE, BC_NOARG, prev().line); 6408 - else ctx()->emit(OP_LOAD_GLOBAL, super_namei, prev().line); 6409 - ctx()->emit(OP_BEGIN_CLASS, namei, BC_KEEPLINE); 6410 - ctx()->is_compiling_class = true; 6411 - compile_block_body(); 6412 - ctx()->is_compiling_class = false; 6413 - ctx()->emit(OP_END_CLASS, BC_NOARG, BC_KEEPLINE); 6414 - } 6415 - 6416 - void _compile_f_args(FuncDecl_ decl, bool enable_type_hints){ 6417 - int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs 6418 - do { 6419 - if(state == 3) SyntaxError("**kwargs should be the last argument"); 6420 - match_newlines(); 6421 - if(match(TK("*"))){ 6422 - if(state < 1) state = 1; 6423 - else SyntaxError("*args should be placed before **kwargs"); 6424 - } 6425 - else if(match(TK("**"))){ 6426 - state = 3; 6427 - } 6428 - consume(TK("@id")); 6429 - StrName name = prev().str(); 6430 - 6431 - // check duplicate argument name 6432 - for(int i: decl->args){ 6433 - if(decl->code->varnames[i] == name) { 6434 - SyntaxError("duplicate argument name"); 6435 - } 6436 - } 6437 - if(decl->starred_arg!=-1 && decl->code->varnames[decl->starred_arg] == name){ 6438 - SyntaxError("duplicate argument name"); 6439 - } 6440 - for(auto& kv: decl->kwargs){ 6441 - if(decl->code->varnames[kv.key] == name){ 6442 - SyntaxError("duplicate argument name"); 6443 - } 6444 - } 6445 - 6446 - // eat type hints 6447 - if(enable_type_hints && match(TK(":"))) consume(TK("@id")); 6448 - if(state == 0 && curr().type == TK("=")) state = 2; 6449 - int index = ctx()->add_varname(name); 6450 - switch (state) 6451 - { 6452 - case 0: 6453 - decl->args.push_back(index); 6454 - break; 6455 - case 1: 6456 - decl->starred_arg = index; 6457 - state+=1; 6458 - break; 6459 - case 2: { 6460 - consume(TK("=")); 6461 - PyObject* value = read_literal(); 6462 - if(value == nullptr){ 6463 - SyntaxError(Str("expect a literal, not ") + TK_STR(curr().type)); 6464 - } 6465 - decl->kwargs.push_back(FuncDecl::KwArg{index, value}); 6466 - } break; 6467 - case 3: SyntaxError("**kwargs is not supported yet"); break; 6468 - } 6469 - } while (match(TK(","))); 6470 - } 6471 - 6472 - void compile_function(const std::vector<Expr_>& decorators={}){ 6473 - Str obj_name; 6474 - Str decl_name; 6475 - consume(TK("@id")); 6476 - decl_name = prev().str(); 6477 - if(!ctx()->is_compiling_class && match(TK("@"))){ 6478 - consume(TK("@id")); 6479 - obj_name = decl_name; 6480 - decl_name = prev().str(); 6481 - } 6482 - FuncDecl_ decl = push_f_context(decl_name); 6483 - consume(TK("(")); 6484 - if (!match(TK(")"))) { 6485 - _compile_f_args(decl, true); 6486 - consume(TK(")")); 6487 - } 6488 - if(match(TK("->"))){ 6489 - if(!match(TK("None"))) consume(TK("@id")); 6490 - } 6491 - compile_block_body(); 6492 - pop_context(); 6493 - 6494 - PyObject* docstring = nullptr; 6495 - if(decl->code->codes.size()>=2 && decl->code->codes[0].op == OP_LOAD_CONST && decl->code->codes[1].op == OP_POP_TOP){ 6496 - PyObject* c = decl->code->consts[decl->code->codes[0].arg]; 6497 - if(is_type(c, vm->tp_str)){ 6498 - decl->code->codes[0].op = OP_NO_OP; 6499 - decl->code->codes[1].op = OP_NO_OP; 6500 - docstring = c; 6501 - } 6502 - } 6503 - ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line); 6504 - if(docstring != nullptr){ 6505 - ctx()->emit(OP_SETUP_DOCSTRING, ctx()->add_const(docstring), prev().line); 6506 - } 6507 - // add decorators 6508 - for(auto it=decorators.rbegin(); it!=decorators.rend(); ++it){ 6509 - (*it)->emit(ctx()); 6510 - ctx()->emit(OP_ROT_TWO, BC_NOARG, (*it)->line); 6511 - ctx()->emit(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE); 6512 - ctx()->emit(OP_ROT_TWO, BC_NOARG, BC_KEEPLINE); 6513 - ctx()->emit(OP_CALL, 1, (*it)->line); 6514 - } 6515 - if(!ctx()->is_compiling_class){ 6516 - if(obj_name.empty()){ 6517 - auto e = make_expr<NameExpr>(decl_name, name_scope()); 6518 - e->emit_store(ctx()); 6519 - } else { 6520 - ctx()->emit(OP_LOAD_GLOBAL, StrName(obj_name).index, prev().line); 6521 - int index = StrName(decl_name).index; 6522 - ctx()->emit(OP_STORE_ATTR, index, prev().line); 6523 - } 6524 - }else{ 6525 - int index = StrName(decl_name).index; 6526 - ctx()->emit(OP_STORE_CLASS_ATTR, index, prev().line); 6527 - } 6528 - } 6529 - 6530 - PyObject* to_object(const TokenValue& value){ 6531 - PyObject* obj = nullptr; 6532 - if(std::holds_alternative<i64>(value)){ 6533 - obj = VAR(std::get<i64>(value)); 6534 - } 6535 - if(std::holds_alternative<f64>(value)){ 6536 - obj = VAR(std::get<f64>(value)); 6537 - } 6538 - if(std::holds_alternative<Str>(value)){ 6539 - obj = VAR(std::get<Str>(value)); 6540 - } 6541 - if(obj == nullptr) FATAL_ERROR(); 6542 - return obj; 6543 - } 6544 - 6545 - PyObject* read_literal(){ 6546 - advance(); 6547 - switch(prev().type){ 6548 - case TK("-"): { 6549 - consume(TK("@num")); 6550 - PyObject* val = to_object(prev().value); 6551 - return vm->num_negated(val); 6552 - } 6553 - case TK("@num"): return to_object(prev().value); 6554 - case TK("@str"): return to_object(prev().value); 6555 - case TK("True"): return VAR(true); 6556 - case TK("False"): return VAR(false); 6557 - case TK("None"): return vm->None; 6558 - case TK("..."): return vm->Ellipsis; 6559 - default: break; 6560 - } 6561 - return nullptr; 6562 - } 6563 - 6564 - void SyntaxError(Str msg){ lexer->throw_err("SyntaxError", msg, err().line, err().start); } 6565 - void SyntaxError(){ lexer->throw_err("SyntaxError", "invalid syntax", err().line, err().start); } 6566 - void IndentationError(Str msg){ lexer->throw_err("IndentationError", msg, err().line, err().start); } 6567 - 6568 - public: 6569 - Compiler(VM* vm, const Str& source, const Str& filename, CompileMode mode, bool unknown_global_scope=false){ 6570 - this->vm = vm; 6571 - this->used = false; 6572 - this->unknown_global_scope = unknown_global_scope; 6573 - this->lexer = std::make_unique<Lexer>( 6574 - make_sp<SourceData>(source, filename, mode) 6575 - ); 6576 - init_pratt_rules(); 6577 - } 6578 - 6579 - CodeObject_ compile(){ 6580 - if(used) FATAL_ERROR(); 6581 - used = true; 6582 - 6583 - tokens = lexer->run(); 6584 - // if(lexer->src->filename == "<stdin>"){ 6585 - // for(auto& t: tokens) std::cout << t.info() << std::endl; 6586 - // } 6587 - 6588 - CodeObject_ code = push_global_context(); 6589 - 6590 - advance(); // skip @sof, so prev() is always valid 6591 - match_newlines(); // skip possible leading '\n' 6592 - 6593 - if(mode()==EVAL_MODE) { 6594 - EXPR_TUPLE(false); 6595 - consume(TK("@eof")); 6596 - ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); 6597 - pop_context(); 6598 - return code; 6599 - }else if(mode()==JSON_MODE){ 6600 - EXPR(); 6601 - Expr_ e = ctx()->s_expr.popx(); 6602 - if(!e->is_json_object()) SyntaxError("expect a JSON object, literal or array"); 6603 - consume(TK("@eof")); 6604 - e->emit(ctx()); 6605 - ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); 6606 - pop_context(); 6607 - return code; 6608 - } 6609 - 6610 - while (!match(TK("@eof"))) { 6611 - if (match(TK("class"))) { 6612 - compile_class(); 6613 - } else { 6614 - compile_stmt(); 6615 - } 6616 - match_newlines(); 6617 - } 6618 - pop_context(); 6619 - return code; 6620 - } 6621 - }; 6622 - 6623 - } // namespace pkpy 6624 - 6625 - 6626 - #ifdef _WIN32 6627 - #define WIN32_LEAN_AND_MEAN 6628 - #include <Windows.h> 6629 - #endif 6630 - 6631 - namespace pkpy{ 6632 - 6633 - #ifdef _WIN32 6634 - 6635 - inline std::string getline(bool* eof=nullptr) { 6636 - HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); 6637 - std::wstringstream wss; 6638 - WCHAR buf; 6639 - DWORD read; 6640 - while (ReadConsoleW(hStdin, &buf, 1, &read, NULL) && buf != L'\n') { 6641 - if(eof && buf == L'\x1A') *eof = true; // Ctrl+Z 6642 - wss << buf; 6643 - } 6644 - std::wstring wideInput = wss.str(); 6645 - int length = WideCharToMultiByte(CP_UTF8, 0, wideInput.c_str(), (int)wideInput.length(), NULL, 0, NULL, NULL); 6646 - std::string output; 6647 - output.resize(length); 6648 - WideCharToMultiByte(CP_UTF8, 0, wideInput.c_str(), (int)wideInput.length(), &output[0], length, NULL, NULL); 6649 - if(!output.empty() && output.back() == '\r') output.pop_back(); 6650 - return output; 6651 - } 6652 - 6653 - #else 6654 - 6655 - inline std::string getline(bool* eof=nullptr){ 6656 - std::string line; 6657 - if(!std::getline(std::cin, line)){ 6658 - if(eof) *eof = true; 6659 - } 6660 - return line; 6661 - } 6662 - 6663 - #endif 6664 - 6665 - class REPL { 6666 - protected: 6667 - int need_more_lines = 0; 6668 - std::string buffer; 6669 - VM* vm; 6670 - public: 6671 - REPL(VM* vm) : vm(vm){ 6672 - vm->_stdout(vm, "pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") "); 6673 - vm->_stdout(vm, fmt("[", sizeof(void*)*8, " bit]" "\n")); 6674 - vm->_stdout(vm, "https://github.com/blueloveTH/pocketpy" "\n"); 6675 - vm->_stdout(vm, "Type \"exit()\" to exit." "\n"); 6676 - } 6677 - 6678 - bool input(std::string line){ 6679 - CompileMode mode = REPL_MODE; 6680 - if(need_more_lines){ 6681 - buffer += line; 6682 - buffer += '\n'; 6683 - int n = buffer.size(); 6684 - if(n>=need_more_lines){ 6685 - for(int i=buffer.size()-need_more_lines; i<buffer.size(); i++){ 6686 - // no enough lines 6687 - if(buffer[i] != '\n') return true; 6688 - } 6689 - need_more_lines = 0; 6690 - line = buffer; 6691 - buffer.clear(); 6692 - mode = EXEC_MODE; 6693 - }else{ 6694 - return true; 6695 - } 6696 - } 6697 - 6698 - try{ 6699 - vm->exec(line, "<stdin>", mode); 6700 - }catch(NeedMoreLines& ne){ 6701 - buffer += line; 6702 - buffer += '\n'; 6703 - need_more_lines = ne.is_compiling_class ? 3 : 2; 6704 - if (need_more_lines) return true; 6705 - } 6706 - return false; 6707 - } 6708 - }; 6709 - 6710 - } // namespace pkpy 6711 - 6712 - // generated on 2023-05-08 20:47:05 6713 - #include <map> 6714 - #include <string> 6715 - 6716 - namespace pkpy{ 6717 - inline static std::map<std::string, const char*> kPythonLibs = { 6718 - {"collections", "\x63\x6c\x61\x73\x73\x20\x5f\x4c\x69\x6e\x6b\x65\x64\x4c\x69\x73\x74\x4e\x6f\x64\x65\x3a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x69\x6e\x69\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x70\x72\x65\x76\x2c\x20\x6e\x65\x78\x74\x2c\x20\x76\x61\x6c\x75\x65\x29\x20\x2d\x3e\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x70\x72\x65\x76\x20\x3d\x20\x70\x72\x65\x76\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x6e\x65\x78\x74\x20\x3d\x20\x6e\x65\x78\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x76\x61\x6c\x75\x65\x20\x3d\x20\x76\x61\x6c\x75\x65\x0a\x0a\x63\x6c\x61\x73\x73\x20\x64\x65\x71\x75\x65\x3a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x69\x6e\x69\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3d\x4e\x6f\x6e\x65\x29\x20\x2d\x3e\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x20\x3d\x20\x5f\x4c\x69\x6e\x6b\x65\x64\x4c\x69\x73\x74\x4e\x6f\x64\x65\x28\x4e\x6f\x6e\x65\x2c\x20\x4e\x6f\x6e\x65\x2c\x20\x4e\x6f\x6e\x65\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x20\x3d\x20\x5f\x4c\x69\x6e\x6b\x65\x64\x4c\x69\x73\x74\x4e\x6f\x64\x65\x28\x4e\x6f\x6e\x65\x2c\x20\x4e\x6f\x6e\x65\x2c\x20\x4e\x6f\x6e\x65\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x2e\x6e\x65\x78\x74\x20\x3d\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x2e\x70\x72\x65\x76\x20\x3d\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x73\x69\x7a\x65\x20\x3d\x20\x30\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x20\x69\x73\x20\x6e\x6f\x74\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x76\x61\x6c\x75\x65\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x61\x70\x70\x65\x6e\x64\x28\x76\x61\x6c\x75\x65\x29\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x61\x70\x70\x65\x6e\x64\x28\x73\x65\x6c\x66\x2c\x20\x76\x61\x6c\x75\x65\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x6f\x64\x65\x20\x3d\x20\x5f\x4c\x69\x6e\x6b\x65\x64\x4c\x69\x73\x74\x4e\x6f\x64\x65\x28\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x2e\x70\x72\x65\x76\x2c\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x2c\x20\x76\x61\x6c\x75\x65\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x2e\x70\x72\x65\x76\x2e\x6e\x65\x78\x74\x20\x3d\x20\x6e\x6f\x64\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x2e\x70\x72\x65\x76\x20\x3d\x20\x6e\x6f\x64\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x73\x69\x7a\x65\x20\x2b\x3d\x20\x31\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x61\x70\x70\x65\x6e\x64\x6c\x65\x66\x74\x28\x73\x65\x6c\x66\x2c\x20\x76\x61\x6c\x75\x65\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x6f\x64\x65\x20\x3d\x20\x5f\x4c\x69\x6e\x6b\x65\x64\x4c\x69\x73\x74\x4e\x6f\x64\x65\x28\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x2c\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x2e\x6e\x65\x78\x74\x2c\x20\x76\x61\x6c\x75\x65\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x2e\x6e\x65\x78\x74\x2e\x70\x72\x65\x76\x20\x3d\x20\x6e\x6f\x64\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x2e\x6e\x65\x78\x74\x20\x3d\x20\x6e\x6f\x64\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x73\x69\x7a\x65\x20\x2b\x3d\x20\x31\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x70\x6f\x70\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x73\x73\x65\x72\x74\x20\x73\x65\x6c\x66\x2e\x73\x69\x7a\x65\x20\x3e\x20\x30\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x6f\x64\x65\x20\x3d\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x2e\x70\x72\x65\x76\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x6f\x64\x65\x2e\x70\x72\x65\x76\x2e\x6e\x65\x78\x74\x20\x3d\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x2e\x70\x72\x65\x76\x20\x3d\x20\x6e\x6f\x64\x65\x2e\x70\x72\x65\x76\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x73\x69\x7a\x65\x20\x2d\x3d\x20\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6e\x6f\x64\x65\x2e\x76\x61\x6c\x75\x65\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x70\x6f\x70\x6c\x65\x66\x74\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x73\x73\x65\x72\x74\x20\x73\x65\x6c\x66\x2e\x73\x69\x7a\x65\x20\x3e\x20\x30\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x6f\x64\x65\x20\x3d\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x2e\x6e\x65\x78\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x6f\x64\x65\x2e\x6e\x65\x78\x74\x2e\x70\x72\x65\x76\x20\x3d\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x2e\x6e\x65\x78\x74\x20\x3d\x20\x6e\x6f\x64\x65\x2e\x6e\x65\x78\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x73\x69\x7a\x65\x20\x2d\x3d\x20\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6e\x6f\x64\x65\x2e\x76\x61\x6c\x75\x65\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x63\x6f\x70\x79\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x65\x77\x5f\x6c\x69\x73\x74\x20\x3d\x20\x64\x65\x71\x75\x65\x28\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x76\x61\x6c\x75\x65\x20\x69\x6e\x20\x73\x65\x6c\x66\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x65\x77\x5f\x6c\x69\x73\x74\x2e\x61\x70\x70\x65\x6e\x64\x28\x76\x61\x6c\x75\x65\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6e\x65\x77\x5f\x6c\x69\x73\x74\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x6c\x65\x6e\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x73\x69\x7a\x65\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x69\x74\x65\x72\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x6f\x64\x65\x20\x3d\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x2e\x6e\x65\x78\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x6e\x6f\x64\x65\x20\x69\x73\x20\x6e\x6f\x74\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x69\x65\x6c\x64\x20\x6e\x6f\x64\x65\x2e\x76\x61\x6c\x75\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x6f\x64\x65\x20\x3d\x20\x6e\x6f\x64\x65\x2e\x6e\x65\x78\x74\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x72\x65\x70\x72\x5f\x5f\x28\x73\x65\x6c\x66\x29\x20\x2d\x3e\x20\x73\x74\x72\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x66\x22\x64\x65\x71\x75\x65\x28\x7b\x6c\x69\x73\x74\x28\x73\x65\x6c\x66\x29\x7d\x29\x22\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x65\x71\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x5f\x5f\x6f\x3a\x20\x6f\x62\x6a\x65\x63\x74\x29\x20\x2d\x3e\x20\x62\x6f\x6f\x6c\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6e\x6f\x74\x20\x69\x73\x69\x6e\x73\x74\x61\x6e\x63\x65\x28\x5f\x5f\x6f\x2c\x20\x64\x65\x71\x75\x65\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x20\x21\x3d\x20\x6c\x65\x6e\x28\x5f\x5f\x6f\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\x31\x2c\x20\x74\x32\x20\x3d\x20\x73\x65\x6c\x66\x2e\x68\x65\x61\x64\x2e\x6e\x65\x78\x74\x2c\x20\x5f\x5f\x6f\x2e\x68\x65\x61\x64\x2e\x6e\x65\x78\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x74\x31\x20\x69\x73\x20\x6e\x6f\x74\x20\x73\x65\x6c\x66\x2e\x74\x61\x69\x6c\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x74\x31\x2e\x76\x61\x6c\x75\x65\x20\x21\x3d\x20\x74\x32\x2e\x76\x61\x6c\x75\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\x31\x2c\x20\x74\x32\x20\x3d\x20\x74\x31\x2e\x6e\x65\x78\x74\x2c\x20\x74\x32\x2e\x6e\x65\x78\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x54\x72\x75\x65\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x6e\x65\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x5f\x5f\x6f\x3a\x20\x6f\x62\x6a\x65\x63\x74\x29\x20\x2d\x3e\x20\x62\x6f\x6f\x6c\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6e\x6f\x74\x20\x73\x65\x6c\x66\x20\x3d\x3d\x20\x5f\x5f\x6f\x0a\x0a\x0a\x64\x65\x66\x20\x43\x6f\x75\x6e\x74\x65\x72\x28\x69\x74\x65\x72\x61\x62\x6c\x65\x29\x3a\x0a\x20\x20\x20\x20\x61\x20\x3d\x20\x7b\x7d\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x78\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x78\x20\x69\x6e\x20\x61\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x61\x5b\x78\x5d\x20\x2b\x3d\x20\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x65\x6c\x73\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x61\x5b\x78\x5d\x20\x3d\x20\x31\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x61"}, 6719 - {"requests", "\x63\x6c\x61\x73\x73\x20\x52\x65\x73\x70\x6f\x6e\x73\x65\x3a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x69\x6e\x69\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x73\x74\x61\x74\x75\x73\x5f\x63\x6f\x64\x65\x2c\x20\x72\x65\x61\x73\x6f\x6e\x2c\x20\x63\x6f\x6e\x74\x65\x6e\x74\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x73\x74\x61\x74\x75\x73\x5f\x63\x6f\x64\x65\x20\x3d\x20\x73\x74\x61\x74\x75\x73\x5f\x63\x6f\x64\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x72\x65\x61\x73\x6f\x6e\x20\x3d\x20\x72\x65\x61\x73\x6f\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x63\x6f\x6e\x74\x65\x6e\x74\x20\x3d\x20\x63\x6f\x6e\x74\x65\x6e\x74\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x73\x73\x65\x72\x74\x20\x74\x79\x70\x65\x28\x73\x65\x6c\x66\x2e\x73\x74\x61\x74\x75\x73\x5f\x63\x6f\x64\x65\x29\x20\x69\x73\x20\x69\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x73\x73\x65\x72\x74\x20\x74\x79\x70\x65\x28\x73\x65\x6c\x66\x2e\x72\x65\x61\x73\x6f\x6e\x29\x20\x69\x73\x20\x73\x74\x72\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x73\x73\x65\x72\x74\x20\x74\x79\x70\x65\x28\x73\x65\x6c\x66\x2e\x63\x6f\x6e\x74\x65\x6e\x74\x29\x20\x69\x73\x20\x62\x79\x74\x65\x73\x0a\x0a\x20\x20\x20\x20\x40\x70\x72\x6f\x70\x65\x72\x74\x79\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x74\x65\x78\x74\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x63\x6f\x6e\x74\x65\x6e\x74\x2e\x64\x65\x63\x6f\x64\x65\x28\x29\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x72\x65\x70\x72\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x63\x6f\x64\x65\x20\x3d\x20\x73\x65\x6c\x66\x2e\x73\x74\x61\x74\x75\x73\x5f\x63\x6f\x64\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x66\x27\x3c\x52\x65\x73\x70\x6f\x6e\x73\x65\x20\x5b\x7b\x63\x6f\x64\x65\x7d\x5d\x3e\x27\x0a\x0a\x64\x65\x66\x20\x5f\x70\x61\x72\x73\x65\x5f\x68\x28\x68\x65\x61\x64\x65\x72\x73\x29\x3a\x0a\x20\x20\x20\x20\x69\x66\x20\x68\x65\x61\x64\x65\x72\x73\x20\x69\x73\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x5b\x5d\x0a\x20\x20\x20\x20\x69\x66\x20\x74\x79\x70\x65\x28\x68\x65\x61\x64\x65\x72\x73\x29\x20\x69\x73\x20\x64\x69\x63\x74\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6c\x69\x73\x74\x28\x68\x65\x61\x64\x65\x72\x73\x2e\x69\x74\x65\x6d\x73\x28\x29\x29\x0a\x20\x20\x20\x20\x72\x61\x69\x73\x65\x20\x56\x61\x6c\x75\x65\x45\x72\x72\x6f\x72\x28\x27\x68\x65\x61\x64\x65\x72\x73\x20\x6d\x75\x73\x74\x20\x62\x65\x20\x64\x69\x63\x74\x20\x6f\x72\x20\x4e\x6f\x6e\x65\x27\x29\x0a\x0a\x64\x65\x66\x20\x67\x65\x74\x28\x75\x72\x6c\x2c\x20\x68\x65\x61\x64\x65\x72\x73\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x68\x65\x61\x64\x65\x72\x73\x20\x3d\x20\x5f\x70\x61\x72\x73\x65\x5f\x68\x28\x68\x65\x61\x64\x65\x72\x73\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x5f\x72\x65\x71\x75\x65\x73\x74\x28\x27\x47\x45\x54\x27\x2c\x20\x75\x72\x6c\x2c\x20\x68\x65\x61\x64\x65\x72\x73\x2c\x20\x4e\x6f\x6e\x65\x29\x0a\x0a\x64\x65\x66\x20\x70\x6f\x73\x74\x28\x75\x72\x6c\x2c\x20\x64\x61\x74\x61\x3a\x20\x62\x79\x74\x65\x73\x2c\x20\x68\x65\x61\x64\x65\x72\x73\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x68\x65\x61\x64\x65\x72\x73\x20\x3d\x20\x5f\x70\x61\x72\x73\x65\x5f\x68\x28\x68\x65\x61\x64\x65\x72\x73\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x5f\x72\x65\x71\x75\x65\x73\x74\x28\x27\x50\x4f\x53\x54\x27\x2c\x20\x75\x72\x6c\x2c\x20\x68\x65\x61\x64\x65\x72\x73\x2c\x20\x64\x61\x74\x61\x29\x0a\x0a\x64\x65\x66\x20\x70\x75\x74\x28\x75\x72\x6c\x2c\x20\x64\x61\x74\x61\x3a\x20\x62\x79\x74\x65\x73\x2c\x20\x68\x65\x61\x64\x65\x72\x73\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x68\x65\x61\x64\x65\x72\x73\x20\x3d\x20\x5f\x70\x61\x72\x73\x65\x5f\x68\x28\x68\x65\x61\x64\x65\x72\x73\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x5f\x72\x65\x71\x75\x65\x73\x74\x28\x27\x50\x55\x54\x27\x2c\x20\x75\x72\x6c\x2c\x20\x68\x65\x61\x64\x65\x72\x73\x2c\x20\x64\x61\x74\x61\x29\x0a\x0a\x64\x65\x66\x20\x64\x65\x6c\x65\x74\x65\x28\x75\x72\x6c\x2c\x20\x68\x65\x61\x64\x65\x72\x73\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x68\x65\x61\x64\x65\x72\x73\x20\x3d\x20\x5f\x70\x61\x72\x73\x65\x5f\x68\x28\x68\x65\x61\x64\x65\x72\x73\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x5f\x72\x65\x71\x75\x65\x73\x74\x28\x27\x44\x45\x4c\x45\x54\x45\x27\x2c\x20\x75\x72\x6c\x2c\x20\x68\x65\x61\x64\x65\x72\x73\x2c\x20\x4e\x6f\x6e\x65\x29"}, 6720 - {"this", "\x70\x72\x69\x6e\x74\x28\x22\x22\x22\x54\x68\x65\x20\x5a\x65\x6e\x20\x6f\x66\x20\x50\x79\x74\x68\x6f\x6e\x2c\x20\x62\x79\x20\x54\x69\x6d\x20\x50\x65\x74\x65\x72\x73\x0a\x0a\x42\x65\x61\x75\x74\x69\x66\x75\x6c\x20\x69\x73\x20\x62\x65\x74\x74\x65\x72\x20\x74\x68\x61\x6e\x20\x75\x67\x6c\x79\x2e\x0a\x45\x78\x70\x6c\x69\x63\x69\x74\x20\x69\x73\x20\x62\x65\x74\x74\x65\x72\x20\x74\x68\x61\x6e\x20\x69\x6d\x70\x6c\x69\x63\x69\x74\x2e\x0a\x53\x69\x6d\x70\x6c\x65\x20\x69\x73\x20\x62\x65\x74\x74\x65\x72\x20\x74\x68\x61\x6e\x20\x63\x6f\x6d\x70\x6c\x65\x78\x2e\x0a\x43\x6f\x6d\x70\x6c\x65\x78\x20\x69\x73\x20\x62\x65\x74\x74\x65\x72\x20\x74\x68\x61\x6e\x20\x63\x6f\x6d\x70\x6c\x69\x63\x61\x74\x65\x64\x2e\x0a\x46\x6c\x61\x74\x20\x69\x73\x20\x62\x65\x74\x74\x65\x72\x20\x74\x68\x61\x6e\x20\x6e\x65\x73\x74\x65\x64\x2e\x0a\x53\x70\x61\x72\x73\x65\x20\x69\x73\x20\x62\x65\x74\x74\x65\x72\x20\x74\x68\x61\x6e\x20\x64\x65\x6e\x73\x65\x2e\x0a\x52\x65\x61\x64\x61\x62\x69\x6c\x69\x74\x79\x20\x63\x6f\x75\x6e\x74\x73\x2e\x0a\x53\x70\x65\x63\x69\x61\x6c\x20\x63\x61\x73\x65\x73\x20\x61\x72\x65\x6e\x27\x74\x20\x73\x70\x65\x63\x69\x61\x6c\x20\x65\x6e\x6f\x75\x67\x68\x20\x74\x6f\x20\x62\x72\x65\x61\x6b\x20\x74\x68\x65\x20\x72\x75\x6c\x65\x73\x2e\x0a\x41\x6c\x74\x68\x6f\x75\x67\x68\x20\x70\x72\x61\x63\x74\x69\x63\x61\x6c\x69\x74\x79\x20\x62\x65\x61\x74\x73\x20\x70\x75\x72\x69\x74\x79\x2e\x0a\x45\x72\x72\x6f\x72\x73\x20\x73\x68\x6f\x75\x6c\x64\x20\x6e\x65\x76\x65\x72\x20\x70\x61\x73\x73\x20\x73\x69\x6c\x65\x6e\x74\x6c\x79\x2e\x0a\x55\x6e\x6c\x65\x73\x73\x20\x65\x78\x70\x6c\x69\x63\x69\x74\x6c\x79\x20\x73\x69\x6c\x65\x6e\x63\x65\x64\x2e\x0a\x49\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f\x66\x20\x61\x6d\x62\x69\x67\x75\x69\x74\x79\x2c\x20\x72\x65\x66\x75\x73\x65\x20\x74\x68\x65\x20\x74\x65\x6d\x70\x74\x61\x74\x69\x6f\x6e\x20\x74\x6f\x20\x67\x75\x65\x73\x73\x2e\x0a\x54\x68\x65\x72\x65\x20\x73\x68\x6f\x75\x6c\x64\x20\x62\x65\x20\x6f\x6e\x65\x2d\x2d\x20\x61\x6e\x64\x20\x70\x72\x65\x66\x65\x72\x61\x62\x6c\x79\x20\x6f\x6e\x6c\x79\x20\x6f\x6e\x65\x20\x2d\x2d\x6f\x62\x76\x69\x6f\x75\x73\x20\x77\x61\x79\x20\x74\x6f\x20\x64\x6f\x20\x69\x74\x2e\x0a\x41\x6c\x74\x68\x6f\x75\x67\x68\x20\x74\x68\x61\x74\x20\x77\x61\x79\x20\x6d\x61\x79\x20\x6e\x6f\x74\x20\x62\x65\x20\x6f\x62\x76\x69\x6f\x75\x73\x20\x61\x74\x20\x66\x69\x72\x73\x74\x20\x75\x6e\x6c\x65\x73\x73\x20\x79\x6f\x75\x27\x72\x65\x20\x44\x75\x74\x63\x68\x2e\x0a\x4e\x6f\x77\x20\x69\x73\x20\x62\x65\x74\x74\x65\x72\x20\x74\x68\x61\x6e\x20\x6e\x65\x76\x65\x72\x2e\x0a\x41\x6c\x74\x68\x6f\x75\x67\x68\x20\x6e\x65\x76\x65\x72\x20\x69\x73\x20\x6f\x66\x74\x65\x6e\x20\x62\x65\x74\x74\x65\x72\x20\x74\x68\x61\x6e\x20\x2a\x72\x69\x67\x68\x74\x2a\x20\x6e\x6f\x77\x2e\x0a\x49\x66\x20\x74\x68\x65\x20\x69\x6d\x70\x6c\x65\x6d\x65\x6e\x74\x61\x74\x69\x6f\x6e\x20\x69\x73\x20\x68\x61\x72\x64\x20\x74\x6f\x20\x65\x78\x70\x6c\x61\x69\x6e\x2c\x20\x69\x74\x27\x73\x20\x61\x20\x62\x61\x64\x20\x69\x64\x65\x61\x2e\x0a\x49\x66\x20\x74\x68\x65\x20\x69\x6d\x70\x6c\x65\x6d\x65\x6e\x74\x61\x74\x69\x6f\x6e\x20\x69\x73\x20\x65\x61\x73\x79\x20\x74\x6f\x20\x65\x78\x70\x6c\x61\x69\x6e\x2c\x20\x69\x74\x20\x6d\x61\x79\x20\x62\x65\x20\x61\x20\x67\x6f\x6f\x64\x20\x69\x64\x65\x61\x2e\x0a\x4e\x61\x6d\x65\x73\x70\x61\x63\x65\x73\x20\x61\x72\x65\x20\x6f\x6e\x65\x20\x68\x6f\x6e\x6b\x69\x6e\x67\x20\x67\x72\x65\x61\x74\x20\x69\x64\x65\x61\x20\x2d\x2d\x20\x6c\x65\x74\x27\x73\x20\x64\x6f\x20\x6d\x6f\x72\x65\x20\x6f\x66\x20\x74\x68\x6f\x73\x65\x21\x22\x22\x22\x29"}, 6721 - {"heapq", "\x23\x20\x48\x65\x61\x70\x20\x71\x75\x65\x75\x65\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x20\x28\x61\x2e\x6b\x2e\x61\x2e\x20\x70\x72\x69\x6f\x72\x69\x74\x79\x20\x71\x75\x65\x75\x65\x29\x0a\x64\x65\x66\x20\x68\x65\x61\x70\x70\x75\x73\x68\x28\x68\x65\x61\x70\x2c\x20\x69\x74\x65\x6d\x29\x3a\x0a\x20\x20\x20\x20\x22\x22\x22\x50\x75\x73\x68\x20\x69\x74\x65\x6d\x20\x6f\x6e\x74\x6f\x20\x68\x65\x61\x70\x2c\x20\x6d\x61\x69\x6e\x74\x61\x69\x6e\x69\x6e\x67\x20\x74\x68\x65\x20\x68\x65\x61\x70\x20\x69\x6e\x76\x61\x72\x69\x61\x6e\x74\x2e\x22\x22\x22\x0a\x20\x20\x20\x20\x68\x65\x61\x70\x2e\x61\x70\x70\x65\x6e\x64\x28\x69\x74\x65\x6d\x29\x0a\x20\x20\x20\x20\x5f\x73\x69\x66\x74\x64\x6f\x77\x6e\x28\x68\x65\x61\x70\x2c\x20\x30\x2c\x20\x6c\x65\x6e\x28\x68\x65\x61\x70\x29\x2d\x31\x29\x0a\x0a\x64\x65\x66\x20\x68\x65\x61\x70\x70\x6f\x70\x28\x68\x65\x61\x70\x29\x3a\x0a\x20\x20\x20\x20\x22\x22\x22\x50\x6f\x70\x20\x74\x68\x65\x20\x73\x6d\x61\x6c\x6c\x65\x73\x74\x20\x69\x74\x65\x6d\x20\x6f\x66\x66\x20\x74\x68\x65\x20\x68\x65\x61\x70\x2c\x20\x6d\x61\x69\x6e\x74\x61\x69\x6e\x69\x6e\x67\x20\x74\x68\x65\x20\x68\x65\x61\x70\x20\x69\x6e\x76\x61\x72\x69\x61\x6e\x74\x2e\x22\x22\x22\x0a\x20\x20\x20\x20\x6c\x61\x73\x74\x65\x6c\x74\x20\x3d\x20\x68\x65\x61\x70\x2e\x70\x6f\x70\x28\x29\x20\x20\x20\x20\x23\x20\x72\x61\x69\x73\x65\x73\x20\x61\x70\x70\x72\x6f\x70\x72\x69\x61\x74\x65\x20\x49\x6e\x64\x65\x78\x45\x72\x72\x6f\x72\x20\x69\x66\x20\x68\x65\x61\x70\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x0a\x20\x20\x20\x20\x69\x66\x20\x68\x65\x61\x70\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x69\x74\x65\x6d\x20\x3d\x20\x68\x65\x61\x70\x5b\x30\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x68\x65\x61\x70\x5b\x30\x5d\x20\x3d\x20\x6c\x61\x73\x74\x65\x6c\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x73\x69\x66\x74\x75\x70\x28\x68\x65\x61\x70\x2c\x20\x30\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x74\x75\x72\x6e\x69\x74\x65\x6d\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6c\x61\x73\x74\x65\x6c\x74\x0a\x0a\x64\x65\x66\x20\x68\x65\x61\x70\x72\x65\x70\x6c\x61\x63\x65\x28\x68\x65\x61\x70\x2c\x20\x69\x74\x65\x6d\x29\x3a\x0a\x20\x20\x20\x20\x22\x22\x22\x50\x6f\x70\x20\x61\x6e\x64\x20\x72\x65\x74\x75\x72\x6e\x20\x74\x68\x65\x20\x63\x75\x72\x72\x65\x6e\x74\x20\x73\x6d\x61\x6c\x6c\x65\x73\x74\x20\x76\x61\x6c\x75\x65\x2c\x20\x61\x6e\x64\x20\x61\x64\x64\x20\x74\x68\x65\x20\x6e\x65\x77\x20\x69\x74\x65\x6d\x2e\x0a\x0a\x20\x20\x20\x20\x54\x68\x69\x73\x20\x69\x73\x20\x6d\x6f\x72\x65\x20\x65\x66\x66\x69\x63\x69\x65\x6e\x74\x20\x74\x68\x61\x6e\x20\x68\x65\x61\x70\x70\x6f\x70\x28\x29\x20\x66\x6f\x6c\x6c\x6f\x77\x65\x64\x20\x62\x79\x20\x68\x65\x61\x70\x70\x75\x73\x68\x28\x29\x2c\x20\x61\x6e\x64\x20\x63\x61\x6e\x20\x62\x65\x0a\x20\x20\x20\x20\x6d\x6f\x72\x65\x20\x61\x70\x70\x72\x6f\x70\x72\x69\x61\x74\x65\x20\x77\x68\x65\x6e\x20\x75\x73\x69\x6e\x67\x20\x61\x20\x66\x69\x78\x65\x64\x2d\x73\x69\x7a\x65\x20\x68\x65\x61\x70\x2e\x20\x20\x4e\x6f\x74\x65\x20\x74\x68\x61\x74\x20\x74\x68\x65\x20\x76\x61\x6c\x75\x65\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x65\x64\x20\x6d\x61\x79\x20\x62\x65\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x69\x74\x65\x6d\x21\x20\x20\x54\x68\x61\x74\x20\x63\x6f\x6e\x73\x74\x72\x61\x69\x6e\x73\x20\x72\x65\x61\x73\x6f\x6e\x61\x62\x6c\x65\x20\x75\x73\x65\x73\x20\x6f\x66\x0a\x20\x20\x20\x20\x74\x68\x69\x73\x20\x72\x6f\x75\x74\x69\x6e\x65\x20\x75\x6e\x6c\x65\x73\x73\x20\x77\x72\x69\x74\x74\x65\x6e\x20\x61\x73\x20\x70\x61\x72\x74\x20\x6f\x66\x20\x61\x20\x63\x6f\x6e\x64\x69\x74\x69\x6f\x6e\x61\x6c\x20\x72\x65\x70\x6c\x61\x63\x65\x6d\x65\x6e\x74\x3a\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x69\x74\x65\x6d\x20\x3e\x20\x68\x65\x61\x70\x5b\x30\x5d\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x74\x65\x6d\x20\x3d\x20\x68\x65\x61\x70\x72\x65\x70\x6c\x61\x63\x65\x28\x68\x65\x61\x70\x2c\x20\x69\x74\x65\x6d\x29\x0a\x20\x20\x20\x20\x22\x22\x22\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x69\x74\x65\x6d\x20\x3d\x20\x68\x65\x61\x70\x5b\x30\x5d\x20\x20\x20\x20\x23\x20\x72\x61\x69\x73\x65\x73\x20\x61\x70\x70\x72\x6f\x70\x72\x69\x61\x74\x65\x20\x49\x6e\x64\x65\x78\x45\x72\x72\x6f\x72\x20\x69\x66\x20\x68\x65\x61\x70\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x0a\x20\x20\x20\x20\x68\x65\x61\x70\x5b\x30\x5d\x20\x3d\x20\x69\x74\x65\x6d\x0a\x20\x20\x20\x20\x5f\x73\x69\x66\x74\x75\x70\x28\x68\x65\x61\x70\x2c\x20\x30\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x74\x75\x72\x6e\x69\x74\x65\x6d\x0a\x0a\x64\x65\x66\x20\x68\x65\x61\x70\x70\x75\x73\x68\x70\x6f\x70\x28\x68\x65\x61\x70\x2c\x20\x69\x74\x65\x6d\x29\x3a\x0a\x20\x20\x20\x20\x22\x22\x22\x46\x61\x73\x74\x20\x76\x65\x72\x73\x69\x6f\x6e\x20\x6f\x66\x20\x61\x20\x68\x65\x61\x70\x70\x75\x73\x68\x20\x66\x6f\x6c\x6c\x6f\x77\x65\x64\x20\x62\x79\x20\x61\x20\x68\x65\x61\x70\x70\x6f\x70\x2e\x22\x22\x22\x0a\x20\x20\x20\x20\x69\x66\x20\x68\x65\x61\x70\x20\x61\x6e\x64\x20\x68\x65\x61\x70\x5b\x30\x5d\x20\x3c\x20\x69\x74\x65\x6d\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x74\x65\x6d\x2c\x20\x68\x65\x61\x70\x5b\x30\x5d\x20\x3d\x20\x68\x65\x61\x70\x5b\x30\x5d\x2c\x20\x69\x74\x65\x6d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x73\x69\x66\x74\x75\x70\x28\x68\x65\x61\x70\x2c\x20\x30\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x69\x74\x65\x6d\x0a\x0a\x64\x65\x66\x20\x68\x65\x61\x70\x69\x66\x79\x28\x78\x29\x3a\x0a\x20\x20\x20\x20\x22\x22\x22\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x20\x6c\x69\x73\x74\x20\x69\x6e\x74\x6f\x20\x61\x20\x68\x65\x61\x70\x2c\x20\x69\x6e\x2d\x70\x6c\x61\x63\x65\x2c\x20\x69\x6e\x20\x4f\x28\x6c\x65\x6e\x28\x78\x29\x29\x20\x74\x69\x6d\x65\x2e\x22\x22\x22\x0a\x20\x20\x20\x20\x6e\x20\x3d\x20\x6c\x65\x6e\x28\x78\x29\x0a\x20\x20\x20\x20\x23\x20\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x20\x62\x6f\x74\x74\x6f\x6d\x2d\x75\x70\x2e\x20\x20\x54\x68\x65\x20\x6c\x61\x72\x67\x65\x73\x74\x20\x69\x6e\x64\x65\x78\x20\x74\x68\x65\x72\x65\x27\x73\x20\x61\x6e\x79\x20\x70\x6f\x69\x6e\x74\x20\x74\x6f\x20\x6c\x6f\x6f\x6b\x69\x6e\x67\x20\x61\x74\x0a\x20\x20\x20\x20\x23\x20\x69\x73\x20\x74\x68\x65\x20\x6c\x61\x72\x67\x65\x73\x74\x20\x77\x69\x74\x68\x20\x61\x20\x63\x68\x69\x6c\x64\x20\x69\x6e\x64\x65\x78\x20\x69\x6e\x2d\x72\x61\x6e\x67\x65\x2c\x20\x73\x6f\x20\x6d\x75\x73\x74\x20\x68\x61\x76\x65\x20\x32\x2a\x69\x20\x2b\x20\x31\x20\x3c\x20\x6e\x2c\x0a\x20\x20\x20\x20\x23\x20\x6f\x72\x20\x69\x20\x3c\x20\x28\x6e\x2d\x31\x29\x2f\x32\x2e\x20\x20\x49\x66\x20\x6e\x20\x69\x73\x20\x65\x76\x65\x6e\x20\x3d\x20\x32\x2a\x6a\x2c\x20\x74\x68\x69\x73\x20\x69\x73\x20\x28\x32\x2a\x6a\x2d\x31\x29\x2f\x32\x20\x3d\x20\x6a\x2d\x31\x2f\x32\x20\x73\x6f\x0a\x20\x20\x20\x20\x23\x20\x6a\x2d\x31\x20\x69\x73\x20\x74\x68\x65\x20\x6c\x61\x72\x67\x65\x73\x74\x2c\x20\x77\x68\x69\x63\x68\x20\x69\x73\x20\x6e\x2f\x2f\x32\x20\x2d\x20\x31\x2e\x20\x20\x49\x66\x20\x6e\x20\x69\x73\x20\x6f\x64\x64\x20\x3d\x20\x32\x2a\x6a\x2b\x31\x2c\x20\x74\x68\x69\x73\x20\x69\x73\x0a\x20\x20\x20\x20\x23\x20\x28\x32\x2a\x6a\x2b\x31\x2d\x31\x29\x2f\x32\x20\x3d\x20\x6a\x20\x73\x6f\x20\x6a\x2d\x31\x20\x69\x73\x20\x74\x68\x65\x20\x6c\x61\x72\x67\x65\x73\x74\x2c\x20\x61\x6e\x64\x20\x74\x68\x61\x74\x27\x73\x20\x61\x67\x61\x69\x6e\x20\x6e\x2f\x2f\x32\x2d\x31\x2e\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x72\x65\x76\x65\x72\x73\x65\x64\x28\x72\x61\x6e\x67\x65\x28\x6e\x2f\x2f\x32\x29\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x73\x69\x66\x74\x75\x70\x28\x78\x2c\x20\x69\x29\x0a\x0a\x23\x20\x27\x68\x65\x61\x70\x27\x20\x69\x73\x20\x61\x20\x68\x65\x61\x70\x20\x61\x74\x20\x61\x6c\x6c\x20\x69\x6e\x64\x69\x63\x65\x73\x20\x3e\x3d\x20\x73\x74\x61\x72\x74\x70\x6f\x73\x2c\x20\x65\x78\x63\x65\x70\x74\x20\x70\x6f\x73\x73\x69\x62\x6c\x79\x20\x66\x6f\x72\x20\x70\x6f\x73\x2e\x20\x20\x70\x6f\x73\x0a\x23\x20\x69\x73\x20\x74\x68\x65\x20\x69\x6e\x64\x65\x78\x20\x6f\x66\x20\x61\x20\x6c\x65\x61\x66\x20\x77\x69\x74\x68\x20\x61\x20\x70\x6f\x73\x73\x69\x62\x6c\x79\x20\x6f\x75\x74\x2d\x6f\x66\x2d\x6f\x72\x64\x65\x72\x20\x76\x61\x6c\x75\x65\x2e\x20\x20\x52\x65\x73\x74\x6f\x72\x65\x20\x74\x68\x65\x0a\x23\x20\x68\x65\x61\x70\x20\x69\x6e\x76\x61\x72\x69\x61\x6e\x74\x2e\x0a\x64\x65\x66\x20\x5f\x73\x69\x66\x74\x64\x6f\x77\x6e\x28\x68\x65\x61\x70\x2c\x20\x73\x74\x61\x72\x74\x70\x6f\x73\x2c\x20\x70\x6f\x73\x29\x3a\x0a\x20\x20\x20\x20\x6e\x65\x77\x69\x74\x65\x6d\x20\x3d\x20\x68\x65\x61\x70\x5b\x70\x6f\x73\x5d\x0a\x20\x20\x20\x20\x23\x20\x46\x6f\x6c\x6c\x6f\x77\x20\x74\x68\x65\x20\x70\x61\x74\x68\x20\x74\x6f\x20\x74\x68\x65\x20\x72\x6f\x6f\x74\x2c\x20\x6d\x6f\x76\x69\x6e\x67\x20\x70\x61\x72\x65\x6e\x74\x73\x20\x64\x6f\x77\x6e\x20\x75\x6e\x74\x69\x6c\x20\x66\x69\x6e\x64\x69\x6e\x67\x20\x61\x20\x70\x6c\x61\x63\x65\x0a\x20\x20\x20\x20\x23\x20\x6e\x65\x77\x69\x74\x65\x6d\x20\x66\x69\x74\x73\x2e\x0a\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x70\x6f\x73\x20\x3e\x20\x73\x74\x61\x72\x74\x70\x6f\x73\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x70\x61\x72\x65\x6e\x74\x70\x6f\x73\x20\x3d\x20\x28\x70\x6f\x73\x20\x2d\x20\x31\x29\x20\x3e\x3e\x20\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x70\x61\x72\x65\x6e\x74\x20\x3d\x20\x68\x65\x61\x70\x5b\x70\x61\x72\x65\x6e\x74\x70\x6f\x73\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6e\x65\x77\x69\x74\x65\x6d\x20\x3c\x20\x70\x61\x72\x65\x6e\x74\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x68\x65\x61\x70\x5b\x70\x6f\x73\x5d\x20\x3d\x20\x70\x61\x72\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x70\x6f\x73\x20\x3d\x20\x70\x61\x72\x65\x6e\x74\x70\x6f\x73\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x63\x6f\x6e\x74\x69\x6e\x75\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x62\x72\x65\x61\x6b\x0a\x20\x20\x20\x20\x68\x65\x61\x70\x5b\x70\x6f\x73\x5d\x20\x3d\x20\x6e\x65\x77\x69\x74\x65\x6d\x0a\x0a\x64\x65\x66\x20\x5f\x73\x69\x66\x74\x75\x70\x28\x68\x65\x61\x70\x2c\x20\x70\x6f\x73\x29\x3a\x0a\x20\x20\x20\x20\x65\x6e\x64\x70\x6f\x73\x20\x3d\x20\x6c\x65\x6e\x28\x68\x65\x61\x70\x29\x0a\x20\x20\x20\x20\x73\x74\x61\x72\x74\x70\x6f\x73\x20\x3d\x20\x70\x6f\x73\x0a\x20\x20\x20\x20\x6e\x65\x77\x69\x74\x65\x6d\x20\x3d\x20\x68\x65\x61\x70\x5b\x70\x6f\x73\x5d\x0a\x20\x20\x20\x20\x23\x20\x42\x75\x62\x62\x6c\x65\x20\x75\x70\x20\x74\x68\x65\x20\x73\x6d\x61\x6c\x6c\x65\x72\x20\x63\x68\x69\x6c\x64\x20\x75\x6e\x74\x69\x6c\x20\x68\x69\x74\x74\x69\x6e\x67\x20\x61\x20\x6c\x65\x61\x66\x2e\x0a\x20\x20\x20\x20\x63\x68\x69\x6c\x64\x70\x6f\x73\x20\x3d\x20\x32\x2a\x70\x6f\x73\x20\x2b\x20\x31\x20\x20\x20\x20\x23\x20\x6c\x65\x66\x74\x6d\x6f\x73\x74\x20\x63\x68\x69\x6c\x64\x20\x70\x6f\x73\x69\x74\x69\x6f\x6e\x0a\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x63\x68\x69\x6c\x64\x70\x6f\x73\x20\x3c\x20\x65\x6e\x64\x70\x6f\x73\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x23\x20\x53\x65\x74\x20\x63\x68\x69\x6c\x64\x70\x6f\x73\x20\x74\x6f\x20\x69\x6e\x64\x65\x78\x20\x6f\x66\x20\x73\x6d\x61\x6c\x6c\x65\x72\x20\x63\x68\x69\x6c\x64\x2e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x69\x67\x68\x74\x70\x6f\x73\x20\x3d\x20\x63\x68\x69\x6c\x64\x70\x6f\x73\x20\x2b\x20\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x72\x69\x67\x68\x74\x70\x6f\x73\x20\x3c\x20\x65\x6e\x64\x70\x6f\x73\x20\x61\x6e\x64\x20\x6e\x6f\x74\x20\x68\x65\x61\x70\x5b\x63\x68\x69\x6c\x64\x70\x6f\x73\x5d\x20\x3c\x20\x68\x65\x61\x70\x5b\x72\x69\x67\x68\x74\x70\x6f\x73\x5d\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x63\x68\x69\x6c\x64\x70\x6f\x73\x20\x3d\x20\x72\x69\x67\x68\x74\x70\x6f\x73\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x23\x20\x4d\x6f\x76\x65\x20\x74\x68\x65\x20\x73\x6d\x61\x6c\x6c\x65\x72\x20\x63\x68\x69\x6c\x64\x20\x75\x70\x2e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x68\x65\x61\x70\x5b\x70\x6f\x73\x5d\x20\x3d\x20\x68\x65\x61\x70\x5b\x63\x68\x69\x6c\x64\x70\x6f\x73\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x70\x6f\x73\x20\x3d\x20\x63\x68\x69\x6c\x64\x70\x6f\x73\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x63\x68\x69\x6c\x64\x70\x6f\x73\x20\x3d\x20\x32\x2a\x70\x6f\x73\x20\x2b\x20\x31\x0a\x20\x20\x20\x20\x23\x20\x54\x68\x65\x20\x6c\x65\x61\x66\x20\x61\x74\x20\x70\x6f\x73\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x20\x6e\x6f\x77\x2e\x20\x20\x50\x75\x74\x20\x6e\x65\x77\x69\x74\x65\x6d\x20\x74\x68\x65\x72\x65\x2c\x20\x61\x6e\x64\x20\x62\x75\x62\x62\x6c\x65\x20\x69\x74\x20\x75\x70\x0a\x20\x20\x20\x20\x23\x20\x74\x6f\x20\x69\x74\x73\x20\x66\x69\x6e\x61\x6c\x20\x72\x65\x73\x74\x69\x6e\x67\x20\x70\x6c\x61\x63\x65\x20\x28\x62\x79\x20\x73\x69\x66\x74\x69\x6e\x67\x20\x69\x74\x73\x20\x70\x61\x72\x65\x6e\x74\x73\x20\x64\x6f\x77\x6e\x29\x2e\x0a\x20\x20\x20\x20\x68\x65\x61\x70\x5b\x70\x6f\x73\x5d\x20\x3d\x20\x6e\x65\x77\x69\x74\x65\x6d\x0a\x20\x20\x20\x20\x5f\x73\x69\x66\x74\x64\x6f\x77\x6e\x28\x68\x65\x61\x70\x2c\x20\x73\x74\x61\x72\x74\x70\x6f\x73\x2c\x20\x70\x6f\x73\x29"}, 6722 - {"bisect", "\x22\x22\x22\x42\x69\x73\x65\x63\x74\x69\x6f\x6e\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x73\x2e\x22\x22\x22\x0a\x0a\x64\x65\x66\x20\x69\x6e\x73\x6f\x72\x74\x5f\x72\x69\x67\x68\x74\x28\x61\x2c\x20\x78\x2c\x20\x6c\x6f\x3d\x30\x2c\x20\x68\x69\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x22\x22\x22\x49\x6e\x73\x65\x72\x74\x20\x69\x74\x65\x6d\x20\x78\x20\x69\x6e\x20\x6c\x69\x73\x74\x20\x61\x2c\x20\x61\x6e\x64\x20\x6b\x65\x65\x70\x20\x69\x74\x20\x73\x6f\x72\x74\x65\x64\x20\x61\x73\x73\x75\x6d\x69\x6e\x67\x20\x61\x20\x69\x73\x20\x73\x6f\x72\x74\x65\x64\x2e\x0a\x0a\x20\x20\x20\x20\x49\x66\x20\x78\x20\x69\x73\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x69\x6e\x20\x61\x2c\x20\x69\x6e\x73\x65\x72\x74\x20\x69\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x72\x69\x67\x68\x74\x20\x6f\x66\x20\x74\x68\x65\x20\x72\x69\x67\x68\x74\x6d\x6f\x73\x74\x20\x78\x2e\x0a\x0a\x20\x20\x20\x20\x4f\x70\x74\x69\x6f\x6e\x61\x6c\x20\x61\x72\x67\x73\x20\x6c\x6f\x20\x28\x64\x65\x66\x61\x75\x6c\x74\x20\x30\x29\x20\x61\x6e\x64\x20\x68\x69\x20\x28\x64\x65\x66\x61\x75\x6c\x74\x20\x6c\x65\x6e\x28\x61\x29\x29\x20\x62\x6f\x75\x6e\x64\x20\x74\x68\x65\x0a\x20\x20\x20\x20\x73\x6c\x69\x63\x65\x20\x6f\x66\x20\x61\x20\x74\x6f\x20\x62\x65\x20\x73\x65\x61\x72\x63\x68\x65\x64\x2e\x0a\x20\x20\x20\x20\x22\x22\x22\x0a\x0a\x20\x20\x20\x20\x6c\x6f\x20\x3d\x20\x62\x69\x73\x65\x63\x74\x5f\x72\x69\x67\x68\x74\x28\x61\x2c\x20\x78\x2c\x20\x6c\x6f\x2c\x20\x68\x69\x29\x0a\x20\x20\x20\x20\x61\x2e\x69\x6e\x73\x65\x72\x74\x28\x6c\x6f\x2c\x20\x78\x29\x0a\x0a\x64\x65\x66\x20\x62\x69\x73\x65\x63\x74\x5f\x72\x69\x67\x68\x74\x28\x61\x2c\x20\x78\x2c\x20\x6c\x6f\x3d\x30\x2c\x20\x68\x69\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x22\x22\x22\x52\x65\x74\x75\x72\x6e\x20\x74\x68\x65\x20\x69\x6e\x64\x65\x78\x20\x77\x68\x65\x72\x65\x20\x74\x6f\x20\x69\x6e\x73\x65\x72\x74\x20\x69\x74\x65\x6d\x20\x78\x20\x69\x6e\x20\x6c\x69\x73\x74\x20\x61\x2c\x20\x61\x73\x73\x75\x6d\x69\x6e\x67\x20\x61\x20\x69\x73\x20\x73\x6f\x72\x74\x65\x64\x2e\x0a\x0a\x20\x20\x20\x20\x54\x68\x65\x20\x72\x65\x74\x75\x72\x6e\x20\x76\x61\x6c\x75\x65\x20\x69\x20\x69\x73\x20\x73\x75\x63\x68\x20\x74\x68\x61\x74\x20\x61\x6c\x6c\x20\x65\x20\x69\x6e\x20\x61\x5b\x3a\x69\x5d\x20\x68\x61\x76\x65\x20\x65\x20\x3c\x3d\x20\x78\x2c\x20\x61\x6e\x64\x20\x61\x6c\x6c\x20\x65\x20\x69\x6e\x0a\x20\x20\x20\x20\x61\x5b\x69\x3a\x5d\x20\x68\x61\x76\x65\x20\x65\x20\x3e\x20\x78\x2e\x20\x20\x53\x6f\x20\x69\x66\x20\x78\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x61\x70\x70\x65\x61\x72\x73\x20\x69\x6e\x20\x74\x68\x65\x20\x6c\x69\x73\x74\x2c\x20\x61\x2e\x69\x6e\x73\x65\x72\x74\x28\x78\x29\x20\x77\x69\x6c\x6c\x0a\x20\x20\x20\x20\x69\x6e\x73\x65\x72\x74\x20\x6a\x75\x73\x74\x20\x61\x66\x74\x65\x72\x20\x74\x68\x65\x20\x72\x69\x67\x68\x74\x6d\x6f\x73\x74\x20\x78\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x74\x68\x65\x72\x65\x2e\x0a\x0a\x20\x20\x20\x20\x4f\x70\x74\x69\x6f\x6e\x61\x6c\x20\x61\x72\x67\x73\x20\x6c\x6f\x20\x28\x64\x65\x66\x61\x75\x6c\x74\x20\x30\x29\x20\x61\x6e\x64\x20\x68\x69\x20\x28\x64\x65\x66\x61\x75\x6c\x74\x20\x6c\x65\x6e\x28\x61\x29\x29\x20\x62\x6f\x75\x6e\x64\x20\x74\x68\x65\x0a\x20\x20\x20\x20\x73\x6c\x69\x63\x65\x20\x6f\x66\x20\x61\x20\x74\x6f\x20\x62\x65\x20\x73\x65\x61\x72\x63\x68\x65\x64\x2e\x0a\x20\x20\x20\x20\x22\x22\x22\x0a\x0a\x20\x20\x20\x20\x69\x66\x20\x6c\x6f\x20\x3c\x20\x30\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x61\x69\x73\x65\x20\x56\x61\x6c\x75\x65\x45\x72\x72\x6f\x72\x28\x27\x6c\x6f\x20\x6d\x75\x73\x74\x20\x62\x65\x20\x6e\x6f\x6e\x2d\x6e\x65\x67\x61\x74\x69\x76\x65\x27\x29\x0a\x20\x20\x20\x20\x69\x66\x20\x68\x69\x20\x69\x73\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x68\x69\x20\x3d\x20\x6c\x65\x6e\x28\x61\x29\x0a\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x6c\x6f\x20\x3c\x20\x68\x69\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6d\x69\x64\x20\x3d\x20\x28\x6c\x6f\x2b\x68\x69\x29\x2f\x2f\x32\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x78\x20\x3c\x20\x61\x5b\x6d\x69\x64\x5d\x3a\x20\x68\x69\x20\x3d\x20\x6d\x69\x64\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x65\x6c\x73\x65\x3a\x20\x6c\x6f\x20\x3d\x20\x6d\x69\x64\x2b\x31\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6c\x6f\x0a\x0a\x64\x65\x66\x20\x69\x6e\x73\x6f\x72\x74\x5f\x6c\x65\x66\x74\x28\x61\x2c\x20\x78\x2c\x20\x6c\x6f\x3d\x30\x2c\x20\x68\x69\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x22\x22\x22\x49\x6e\x73\x65\x72\x74\x20\x69\x74\x65\x6d\x20\x78\x20\x69\x6e\x20\x6c\x69\x73\x74\x20\x61\x2c\x20\x61\x6e\x64\x20\x6b\x65\x65\x70\x20\x69\x74\x20\x73\x6f\x72\x74\x65\x64\x20\x61\x73\x73\x75\x6d\x69\x6e\x67\x20\x61\x20\x69\x73\x20\x73\x6f\x72\x74\x65\x64\x2e\x0a\x0a\x20\x20\x20\x20\x49\x66\x20\x78\x20\x69\x73\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x69\x6e\x20\x61\x2c\x20\x69\x6e\x73\x65\x72\x74\x20\x69\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x6c\x65\x66\x74\x20\x6f\x66\x20\x74\x68\x65\x20\x6c\x65\x66\x74\x6d\x6f\x73\x74\x20\x78\x2e\x0a\x0a\x20\x20\x20\x20\x4f\x70\x74\x69\x6f\x6e\x61\x6c\x20\x61\x72\x67\x73\x20\x6c\x6f\x20\x28\x64\x65\x66\x61\x75\x6c\x74\x20\x30\x29\x20\x61\x6e\x64\x20\x68\x69\x20\x28\x64\x65\x66\x61\x75\x6c\x74\x20\x6c\x65\x6e\x28\x61\x29\x29\x20\x62\x6f\x75\x6e\x64\x20\x74\x68\x65\x0a\x20\x20\x20\x20\x73\x6c\x69\x63\x65\x20\x6f\x66\x20\x61\x20\x74\x6f\x20\x62\x65\x20\x73\x65\x61\x72\x63\x68\x65\x64\x2e\x0a\x20\x20\x20\x20\x22\x22\x22\x0a\x0a\x20\x20\x20\x20\x6c\x6f\x20\x3d\x20\x62\x69\x73\x65\x63\x74\x5f\x6c\x65\x66\x74\x28\x61\x2c\x20\x78\x2c\x20\x6c\x6f\x2c\x20\x68\x69\x29\x0a\x20\x20\x20\x20\x61\x2e\x69\x6e\x73\x65\x72\x74\x28\x6c\x6f\x2c\x20\x78\x29\x0a\x0a\x0a\x64\x65\x66\x20\x62\x69\x73\x65\x63\x74\x5f\x6c\x65\x66\x74\x28\x61\x2c\x20\x78\x2c\x20\x6c\x6f\x3d\x30\x2c\x20\x68\x69\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x22\x22\x22\x52\x65\x74\x75\x72\x6e\x20\x74\x68\x65\x20\x69\x6e\x64\x65\x78\x20\x77\x68\x65\x72\x65\x20\x74\x6f\x20\x69\x6e\x73\x65\x72\x74\x20\x69\x74\x65\x6d\x20\x78\x20\x69\x6e\x20\x6c\x69\x73\x74\x20\x61\x2c\x20\x61\x73\x73\x75\x6d\x69\x6e\x67\x20\x61\x20\x69\x73\x20\x73\x6f\x72\x74\x65\x64\x2e\x0a\x0a\x20\x20\x20\x20\x54\x68\x65\x20\x72\x65\x74\x75\x72\x6e\x20\x76\x61\x6c\x75\x65\x20\x69\x20\x69\x73\x20\x73\x75\x63\x68\x20\x74\x68\x61\x74\x20\x61\x6c\x6c\x20\x65\x20\x69\x6e\x20\x61\x5b\x3a\x69\x5d\x20\x68\x61\x76\x65\x20\x65\x20\x3c\x20\x78\x2c\x20\x61\x6e\x64\x20\x61\x6c\x6c\x20\x65\x20\x69\x6e\x0a\x20\x20\x20\x20\x61\x5b\x69\x3a\x5d\x20\x68\x61\x76\x65\x20\x65\x20\x3e\x3d\x20\x78\x2e\x20\x20\x53\x6f\x20\x69\x66\x20\x78\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x61\x70\x70\x65\x61\x72\x73\x20\x69\x6e\x20\x74\x68\x65\x20\x6c\x69\x73\x74\x2c\x20\x61\x2e\x69\x6e\x73\x65\x72\x74\x28\x78\x29\x20\x77\x69\x6c\x6c\x0a\x20\x20\x20\x20\x69\x6e\x73\x65\x72\x74\x20\x6a\x75\x73\x74\x20\x62\x65\x66\x6f\x72\x65\x20\x74\x68\x65\x20\x6c\x65\x66\x74\x6d\x6f\x73\x74\x20\x78\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x74\x68\x65\x72\x65\x2e\x0a\x0a\x20\x20\x20\x20\x4f\x70\x74\x69\x6f\x6e\x61\x6c\x20\x61\x72\x67\x73\x20\x6c\x6f\x20\x28\x64\x65\x66\x61\x75\x6c\x74\x20\x30\x29\x20\x61\x6e\x64\x20\x68\x69\x20\x28\x64\x65\x66\x61\x75\x6c\x74\x20\x6c\x65\x6e\x28\x61\x29\x29\x20\x62\x6f\x75\x6e\x64\x20\x74\x68\x65\x0a\x20\x20\x20\x20\x73\x6c\x69\x63\x65\x20\x6f\x66\x20\x61\x20\x74\x6f\x20\x62\x65\x20\x73\x65\x61\x72\x63\x68\x65\x64\x2e\x0a\x20\x20\x20\x20\x22\x22\x22\x0a\x0a\x20\x20\x20\x20\x69\x66\x20\x6c\x6f\x20\x3c\x20\x30\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x61\x69\x73\x65\x20\x56\x61\x6c\x75\x65\x45\x72\x72\x6f\x72\x28\x27\x6c\x6f\x20\x6d\x75\x73\x74\x20\x62\x65\x20\x6e\x6f\x6e\x2d\x6e\x65\x67\x61\x74\x69\x76\x65\x27\x29\x0a\x20\x20\x20\x20\x69\x66\x20\x68\x69\x20\x69\x73\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x68\x69\x20\x3d\x20\x6c\x65\x6e\x28\x61\x29\x0a\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x6c\x6f\x20\x3c\x20\x68\x69\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6d\x69\x64\x20\x3d\x20\x28\x6c\x6f\x2b\x68\x69\x29\x2f\x2f\x32\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x61\x5b\x6d\x69\x64\x5d\x20\x3c\x20\x78\x3a\x20\x6c\x6f\x20\x3d\x20\x6d\x69\x64\x2b\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x65\x6c\x73\x65\x3a\x20\x68\x69\x20\x3d\x20\x6d\x69\x64\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6c\x6f\x0a\x0a\x23\x20\x43\x72\x65\x61\x74\x65\x20\x61\x6c\x69\x61\x73\x65\x73\x0a\x62\x69\x73\x65\x63\x74\x20\x3d\x20\x62\x69\x73\x65\x63\x74\x5f\x72\x69\x67\x68\x74\x0a\x69\x6e\x73\x6f\x72\x74\x20\x3d\x20\x69\x6e\x73\x6f\x72\x74\x5f\x72\x69\x67\x68\x74\x0a"}, 6723 - {"random", "\x5f\x69\x6e\x73\x74\x20\x3d\x20\x52\x61\x6e\x64\x6f\x6d\x28\x29\x0a\x0a\x73\x65\x65\x64\x20\x3d\x20\x5f\x69\x6e\x73\x74\x2e\x73\x65\x65\x64\x0a\x72\x61\x6e\x64\x6f\x6d\x20\x3d\x20\x5f\x69\x6e\x73\x74\x2e\x72\x61\x6e\x64\x6f\x6d\x0a\x75\x6e\x69\x66\x6f\x72\x6d\x20\x3d\x20\x5f\x69\x6e\x73\x74\x2e\x75\x6e\x69\x66\x6f\x72\x6d\x0a\x72\x61\x6e\x64\x69\x6e\x74\x20\x3d\x20\x5f\x69\x6e\x73\x74\x2e\x72\x61\x6e\x64\x69\x6e\x74\x0a\x0a\x64\x65\x66\x20\x73\x68\x75\x66\x66\x6c\x65\x28\x4c\x29\x3a\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x72\x61\x6e\x67\x65\x28\x6c\x65\x6e\x28\x4c\x29\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6a\x20\x3d\x20\x72\x61\x6e\x64\x69\x6e\x74\x28\x69\x2c\x20\x6c\x65\x6e\x28\x4c\x29\x20\x2d\x20\x31\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x4c\x5b\x69\x5d\x2c\x20\x4c\x5b\x6a\x5d\x20\x3d\x20\x4c\x5b\x6a\x5d\x2c\x20\x4c\x5b\x69\x5d\x0a\x0a\x64\x65\x66\x20\x63\x68\x6f\x69\x63\x65\x28\x4c\x29\x3a\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x4c\x5b\x72\x61\x6e\x64\x69\x6e\x74\x28\x30\x2c\x20\x6c\x65\x6e\x28\x4c\x29\x20\x2d\x20\x31\x29\x5d"}, 6724 - {"functools", "\x64\x65\x66\x20\x63\x61\x63\x68\x65\x28\x66\x29\x3a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x77\x72\x61\x70\x70\x65\x72\x28\x2a\x61\x72\x67\x73\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6e\x6f\x74\x20\x68\x61\x73\x61\x74\x74\x72\x28\x66\x2c\x20\x27\x63\x61\x63\x68\x65\x27\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x2e\x63\x61\x63\x68\x65\x20\x3d\x20\x7b\x7d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6b\x65\x79\x20\x3d\x20\x61\x72\x67\x73\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6b\x65\x79\x20\x6e\x6f\x74\x20\x69\x6e\x20\x66\x2e\x63\x61\x63\x68\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x2e\x63\x61\x63\x68\x65\x5b\x6b\x65\x79\x5d\x20\x3d\x20\x66\x28\x2a\x61\x72\x67\x73\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x66\x2e\x63\x61\x63\x68\x65\x5b\x6b\x65\x79\x5d\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x77\x72\x61\x70\x70\x65\x72"}, 6725 - {"_dict", "\x63\x6c\x61\x73\x73\x20\x64\x69\x63\x74\x3a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x69\x6e\x69\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6d\x61\x70\x70\x69\x6e\x67\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x63\x61\x70\x61\x63\x69\x74\x79\x20\x3d\x20\x31\x36\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x61\x20\x3d\x20\x5b\x4e\x6f\x6e\x65\x5d\x20\x2a\x20\x73\x65\x6c\x66\x2e\x5f\x63\x61\x70\x61\x63\x69\x74\x79\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x6c\x65\x6e\x20\x3d\x20\x30\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6d\x61\x70\x70\x69\x6e\x67\x20\x69\x73\x20\x6e\x6f\x74\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x6b\x2c\x76\x20\x69\x6e\x20\x6d\x61\x70\x70\x69\x6e\x67\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x5b\x6b\x5d\x20\x3d\x20\x76\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x6c\x65\x6e\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x6c\x65\x6e\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x70\x72\x6f\x62\x65\x28\x73\x65\x6c\x66\x2c\x20\x6b\x65\x79\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x20\x3d\x20\x68\x61\x73\x68\x28\x6b\x65\x79\x29\x20\x25\x20\x73\x65\x6c\x66\x2e\x5f\x63\x61\x70\x61\x63\x69\x74\x79\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x69\x5d\x20\x69\x73\x20\x6e\x6f\x74\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x69\x5d\x5b\x30\x5d\x20\x3d\x3d\x20\x6b\x65\x79\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x54\x72\x75\x65\x2c\x20\x69\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x20\x3d\x20\x28\x69\x20\x2b\x20\x31\x29\x20\x25\x20\x73\x65\x6c\x66\x2e\x5f\x63\x61\x70\x61\x63\x69\x74\x79\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x2c\x20\x69\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x67\x65\x74\x69\x74\x65\x6d\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6b\x65\x79\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x6b\x2c\x20\x69\x20\x3d\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x70\x72\x6f\x62\x65\x28\x6b\x65\x79\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6e\x6f\x74\x20\x6f\x6b\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x61\x69\x73\x65\x20\x4b\x65\x79\x45\x72\x72\x6f\x72\x28\x72\x65\x70\x72\x28\x6b\x65\x79\x29\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x69\x5d\x5b\x31\x5d\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x63\x6f\x6e\x74\x61\x69\x6e\x73\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6b\x65\x79\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x6b\x2c\x20\x69\x20\x3d\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x70\x72\x6f\x62\x65\x28\x6b\x65\x79\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6f\x6b\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x73\x65\x74\x69\x74\x65\x6d\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6b\x65\x79\x2c\x20\x76\x61\x6c\x75\x65\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x6b\x2c\x20\x69\x20\x3d\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x70\x72\x6f\x62\x65\x28\x6b\x65\x79\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6f\x6b\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x69\x5d\x5b\x31\x5d\x20\x3d\x20\x76\x61\x6c\x75\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x65\x6c\x73\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x69\x5d\x20\x3d\x20\x5b\x6b\x65\x79\x2c\x20\x76\x61\x6c\x75\x65\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x6c\x65\x6e\x20\x2b\x3d\x20\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x73\x65\x6c\x66\x2e\x5f\x6c\x65\x6e\x20\x3e\x20\x73\x65\x6c\x66\x2e\x5f\x63\x61\x70\x61\x63\x69\x74\x79\x20\x2a\x20\x30\x2e\x36\x37\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x63\x61\x70\x61\x63\x69\x74\x79\x20\x2a\x3d\x20\x32\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x72\x65\x68\x61\x73\x68\x28\x29\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x64\x65\x6c\x69\x74\x65\x6d\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6b\x65\x79\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x6b\x2c\x20\x69\x20\x3d\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x70\x72\x6f\x62\x65\x28\x6b\x65\x79\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6e\x6f\x74\x20\x6f\x6b\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x61\x69\x73\x65\x20\x4b\x65\x79\x45\x72\x72\x6f\x72\x28\x72\x65\x70\x72\x28\x6b\x65\x79\x29\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x69\x5d\x20\x3d\x20\x4e\x6f\x6e\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x6c\x65\x6e\x20\x2d\x3d\x20\x31\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x72\x65\x68\x61\x73\x68\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x6c\x64\x5f\x61\x20\x3d\x20\x73\x65\x6c\x66\x2e\x5f\x61\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x61\x20\x3d\x20\x5b\x4e\x6f\x6e\x65\x5d\x20\x2a\x20\x73\x65\x6c\x66\x2e\x5f\x63\x61\x70\x61\x63\x69\x74\x79\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x6c\x65\x6e\x20\x3d\x20\x30\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x6b\x76\x20\x69\x6e\x20\x6f\x6c\x64\x5f\x61\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6b\x76\x20\x69\x73\x20\x6e\x6f\x74\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x5b\x6b\x76\x5b\x30\x5d\x5d\x20\x3d\x20\x6b\x76\x5b\x31\x5d\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x67\x65\x74\x28\x73\x65\x6c\x66\x2c\x20\x6b\x65\x79\x2c\x20\x64\x65\x66\x61\x75\x6c\x74\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x6b\x2c\x20\x69\x20\x3d\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x70\x72\x6f\x62\x65\x28\x6b\x65\x79\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6f\x6b\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x69\x5d\x5b\x31\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x64\x65\x66\x61\x75\x6c\x74\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x6b\x65\x79\x73\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x6b\x76\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6b\x76\x20\x69\x73\x20\x6e\x6f\x74\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x69\x65\x6c\x64\x20\x6b\x76\x5b\x30\x5d\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x76\x61\x6c\x75\x65\x73\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x6b\x76\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6b\x76\x20\x69\x73\x20\x6e\x6f\x74\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x69\x65\x6c\x64\x20\x6b\x76\x5b\x31\x5d\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x69\x74\x65\x6d\x73\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x6b\x76\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6b\x76\x20\x69\x73\x20\x6e\x6f\x74\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x69\x65\x6c\x64\x20\x6b\x76\x5b\x30\x5d\x2c\x20\x6b\x76\x5b\x31\x5d\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x63\x6c\x65\x61\x72\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x61\x20\x3d\x20\x5b\x4e\x6f\x6e\x65\x5d\x20\x2a\x20\x73\x65\x6c\x66\x2e\x5f\x63\x61\x70\x61\x63\x69\x74\x79\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x6c\x65\x6e\x20\x3d\x20\x30\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x75\x70\x64\x61\x74\x65\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x6b\x2c\x20\x76\x20\x69\x6e\x20\x6f\x74\x68\x65\x72\x2e\x69\x74\x65\x6d\x73\x28\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x5b\x6b\x5d\x20\x3d\x20\x76\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x63\x6f\x70\x79\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x64\x20\x3d\x20\x64\x69\x63\x74\x28\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x6b\x76\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6b\x76\x20\x69\x73\x20\x6e\x6f\x74\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x5b\x6b\x76\x5b\x30\x5d\x5d\x20\x3d\x20\x6b\x76\x5b\x31\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x64\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x72\x65\x70\x72\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x20\x3d\x20\x5b\x72\x65\x70\x72\x28\x6b\x29\x2b\x27\x3a\x20\x27\x2b\x72\x65\x70\x72\x28\x76\x29\x20\x66\x6f\x72\x20\x6b\x2c\x76\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x69\x74\x65\x6d\x73\x28\x29\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x27\x7b\x27\x2b\x20\x27\x2c\x20\x27\x2e\x6a\x6f\x69\x6e\x28\x61\x29\x20\x2b\x20\x27\x7d\x27\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x6a\x73\x6f\x6e\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x20\x3d\x20\x5b\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x6b\x2c\x76\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x69\x74\x65\x6d\x73\x28\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x74\x79\x70\x65\x28\x6b\x29\x20\x69\x73\x20\x6e\x6f\x74\x20\x73\x74\x72\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x61\x69\x73\x65\x20\x54\x79\x70\x65\x45\x72\x72\x6f\x72\x28\x27\x6a\x73\x6f\x6e\x20\x6b\x65\x79\x73\x20\x6d\x75\x73\x74\x20\x62\x65\x20\x73\x74\x72\x69\x6e\x67\x73\x2c\x20\x67\x6f\x74\x20\x27\x20\x2b\x20\x72\x65\x70\x72\x28\x6b\x29\x20\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x61\x2e\x61\x70\x70\x65\x6e\x64\x28\x6b\x2e\x5f\x5f\x6a\x73\x6f\x6e\x5f\x5f\x28\x29\x2b\x27\x3a\x20\x27\x2b\x76\x2e\x5f\x5f\x6a\x73\x6f\x6e\x5f\x5f\x28\x29\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x27\x7b\x27\x2b\x20\x27\x2c\x20\x27\x2e\x6a\x6f\x69\x6e\x28\x61\x29\x20\x2b\x20\x27\x7d\x27\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x65\x71\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x5f\x5f\x6f\x3a\x20\x6f\x62\x6a\x65\x63\x74\x29\x20\x2d\x3e\x20\x62\x6f\x6f\x6c\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x74\x79\x70\x65\x28\x5f\x5f\x6f\x29\x20\x69\x73\x20\x6e\x6f\x74\x20\x64\x69\x63\x74\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x20\x21\x3d\x20\x6c\x65\x6e\x28\x5f\x5f\x6f\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x6b\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x6b\x65\x79\x73\x28\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6b\x20\x6e\x6f\x74\x20\x69\x6e\x20\x5f\x5f\x6f\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x73\x65\x6c\x66\x5b\x6b\x5d\x20\x21\x3d\x20\x5f\x5f\x6f\x5b\x6b\x5d\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x54\x72\x75\x65\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x6e\x65\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x5f\x5f\x6f\x3a\x20\x6f\x62\x6a\x65\x63\x74\x29\x20\x2d\x3e\x20\x62\x6f\x6f\x6c\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6e\x6f\x74\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x65\x71\x5f\x5f\x28\x5f\x5f\x6f\x29"}, 6726 - {"builtins", "\x69\x6d\x70\x6f\x72\x74\x20\x73\x79\x73\x20\x61\x73\x20\x5f\x73\x79\x73\x0a\x0a\x64\x65\x66\x20\x70\x72\x69\x6e\x74\x28\x2a\x61\x72\x67\x73\x2c\x20\x73\x65\x70\x3d\x27\x20\x27\x2c\x20\x65\x6e\x64\x3d\x27\x5c\x6e\x27\x29\x3a\x0a\x20\x20\x20\x20\x73\x20\x3d\x20\x73\x65\x70\x2e\x6a\x6f\x69\x6e\x28\x5b\x73\x74\x72\x28\x69\x29\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x61\x72\x67\x73\x5d\x29\x0a\x20\x20\x20\x20\x5f\x73\x79\x73\x2e\x73\x74\x64\x6f\x75\x74\x2e\x77\x72\x69\x74\x65\x28\x73\x20\x2b\x20\x65\x6e\x64\x29\x0a\x0a\x64\x65\x66\x20\x72\x6f\x75\x6e\x64\x28\x78\x2c\x20\x6e\x64\x69\x67\x69\x74\x73\x3d\x30\x29\x3a\x0a\x20\x20\x20\x20\x61\x73\x73\x65\x72\x74\x20\x6e\x64\x69\x67\x69\x74\x73\x20\x3e\x3d\x20\x30\x0a\x20\x20\x20\x20\x69\x66\x20\x6e\x64\x69\x67\x69\x74\x73\x20\x3d\x3d\x20\x30\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x69\x6e\x74\x28\x78\x20\x2b\x20\x30\x2e\x35\x29\x20\x69\x66\x20\x78\x20\x3e\x3d\x20\x30\x20\x65\x6c\x73\x65\x20\x69\x6e\x74\x28\x78\x20\x2d\x20\x30\x2e\x35\x29\x0a\x20\x20\x20\x20\x69\x66\x20\x78\x20\x3e\x3d\x20\x30\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x69\x6e\x74\x28\x78\x20\x2a\x20\x31\x30\x2a\x2a\x6e\x64\x69\x67\x69\x74\x73\x20\x2b\x20\x30\x2e\x35\x29\x20\x2f\x20\x31\x30\x2a\x2a\x6e\x64\x69\x67\x69\x74\x73\x0a\x20\x20\x20\x20\x65\x6c\x73\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x69\x6e\x74\x28\x78\x20\x2a\x20\x31\x30\x2a\x2a\x6e\x64\x69\x67\x69\x74\x73\x20\x2d\x20\x30\x2e\x35\x29\x20\x2f\x20\x31\x30\x2a\x2a\x6e\x64\x69\x67\x69\x74\x73\x0a\x0a\x64\x65\x66\x20\x61\x62\x73\x28\x78\x29\x3a\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x2d\x78\x20\x69\x66\x20\x78\x20\x3c\x20\x30\x20\x65\x6c\x73\x65\x20\x78\x0a\x0a\x64\x65\x66\x20\x6d\x61\x78\x28\x61\x2c\x20\x62\x29\x3a\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x61\x20\x69\x66\x20\x61\x20\x3e\x20\x62\x20\x65\x6c\x73\x65\x20\x62\x0a\x0a\x64\x65\x66\x20\x6d\x69\x6e\x28\x61\x2c\x20\x62\x29\x3a\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x61\x20\x69\x66\x20\x61\x20\x3c\x20\x62\x20\x65\x6c\x73\x65\x20\x62\x0a\x0a\x64\x65\x66\x20\x61\x6c\x6c\x28\x69\x74\x65\x72\x61\x62\x6c\x65\x29\x3a\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6e\x6f\x74\x20\x69\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x54\x72\x75\x65\x0a\x0a\x64\x65\x66\x20\x61\x6e\x79\x28\x69\x74\x65\x72\x61\x62\x6c\x65\x29\x3a\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x69\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x54\x72\x75\x65\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x0a\x64\x65\x66\x20\x65\x6e\x75\x6d\x65\x72\x61\x74\x65\x28\x69\x74\x65\x72\x61\x62\x6c\x65\x2c\x20\x73\x74\x61\x72\x74\x3d\x30\x29\x3a\x0a\x20\x20\x20\x20\x6e\x20\x3d\x20\x73\x74\x61\x72\x74\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x79\x69\x65\x6c\x64\x20\x6e\x2c\x20\x65\x6c\x65\x6d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x20\x2b\x3d\x20\x31\x0a\x0a\x64\x65\x66\x20\x73\x75\x6d\x28\x69\x74\x65\x72\x61\x62\x6c\x65\x29\x3a\x0a\x20\x20\x20\x20\x72\x65\x73\x20\x3d\x20\x30\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x73\x20\x2b\x3d\x20\x69\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x73\x0a\x0a\x64\x65\x66\x20\x6d\x61\x70\x28\x66\x2c\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x29\x3a\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x79\x69\x65\x6c\x64\x20\x66\x28\x69\x29\x0a\x0a\x64\x65\x66\x20\x66\x69\x6c\x74\x65\x72\x28\x66\x2c\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x29\x3a\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x66\x28\x69\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x69\x65\x6c\x64\x20\x69\x0a\x0a\x64\x65\x66\x20\x7a\x69\x70\x28\x61\x2c\x20\x62\x29\x3a\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x72\x61\x6e\x67\x65\x28\x6d\x69\x6e\x28\x6c\x65\x6e\x28\x61\x29\x2c\x20\x6c\x65\x6e\x28\x62\x29\x29\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x79\x69\x65\x6c\x64\x20\x28\x61\x5b\x69\x5d\x2c\x20\x62\x5b\x69\x5d\x29\x0a\x0a\x64\x65\x66\x20\x72\x65\x76\x65\x72\x73\x65\x64\x28\x69\x74\x65\x72\x61\x62\x6c\x65\x29\x3a\x0a\x20\x20\x20\x20\x61\x20\x3d\x20\x6c\x69\x73\x74\x28\x69\x74\x65\x72\x61\x62\x6c\x65\x29\x0a\x20\x20\x20\x20\x61\x2e\x72\x65\x76\x65\x72\x73\x65\x28\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x61\x0a\x0a\x64\x65\x66\x20\x73\x6f\x72\x74\x65\x64\x28\x69\x74\x65\x72\x61\x62\x6c\x65\x2c\x20\x72\x65\x76\x65\x72\x73\x65\x3d\x46\x61\x6c\x73\x65\x29\x3a\x0a\x20\x20\x20\x20\x61\x20\x3d\x20\x6c\x69\x73\x74\x28\x69\x74\x65\x72\x61\x62\x6c\x65\x29\x0a\x20\x20\x20\x20\x61\x2e\x73\x6f\x72\x74\x28\x72\x65\x76\x65\x72\x73\x65\x3d\x72\x65\x76\x65\x72\x73\x65\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x61\x0a\x0a\x23\x23\x23\x23\x23\x20\x73\x74\x72\x20\x23\x23\x23\x23\x23\x0a\x0a\x73\x74\x72\x2e\x5f\x5f\x6d\x75\x6c\x5f\x5f\x20\x3d\x20\x6c\x61\x6d\x62\x64\x61\x20\x73\x65\x6c\x66\x2c\x20\x6e\x3a\x20\x27\x27\x2e\x6a\x6f\x69\x6e\x28\x5b\x73\x65\x6c\x66\x20\x66\x6f\x72\x20\x5f\x20\x69\x6e\x20\x72\x61\x6e\x67\x65\x28\x6e\x29\x5d\x29\x0a\x0a\x64\x65\x66\x20\x73\x74\x72\x40\x73\x70\x6c\x69\x74\x28\x73\x65\x6c\x66\x2c\x20\x73\x65\x70\x29\x3a\x0a\x20\x20\x20\x20\x69\x66\x20\x73\x65\x70\x20\x3d\x3d\x20\x22\x22\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6c\x69\x73\x74\x28\x73\x65\x6c\x66\x29\x0a\x20\x20\x20\x20\x72\x65\x73\x20\x3d\x20\x5b\x5d\x0a\x20\x20\x20\x20\x69\x20\x3d\x20\x30\x0a\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x69\x20\x3c\x20\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x73\x65\x6c\x66\x5b\x69\x3a\x69\x2b\x6c\x65\x6e\x28\x73\x65\x70\x29\x5d\x20\x3d\x3d\x20\x73\x65\x70\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x73\x2e\x61\x70\x70\x65\x6e\x64\x28\x73\x65\x6c\x66\x5b\x3a\x69\x5d\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x20\x3d\x20\x73\x65\x6c\x66\x5b\x69\x2b\x6c\x65\x6e\x28\x73\x65\x70\x29\x3a\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x20\x3d\x20\x30\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x65\x6c\x73\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x20\x2b\x3d\x20\x31\x0a\x20\x20\x20\x20\x72\x65\x73\x2e\x61\x70\x70\x65\x6e\x64\x28\x73\x65\x6c\x66\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x73\x0a\x0a\x64\x65\x66\x20\x73\x74\x72\x40\x66\x6f\x72\x6d\x61\x74\x28\x73\x65\x6c\x66\x2c\x20\x2a\x61\x72\x67\x73\x29\x3a\x0a\x20\x20\x20\x20\x69\x66\x20\x27\x7b\x7d\x27\x20\x69\x6e\x20\x73\x65\x6c\x66\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x72\x61\x6e\x67\x65\x28\x6c\x65\x6e\x28\x61\x72\x67\x73\x29\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x20\x3d\x20\x73\x65\x6c\x66\x2e\x72\x65\x70\x6c\x61\x63\x65\x28\x27\x7b\x7d\x27\x2c\x20\x73\x74\x72\x28\x61\x72\x67\x73\x5b\x69\x5d\x29\x2c\x20\x31\x29\x0a\x20\x20\x20\x20\x65\x6c\x73\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x72\x61\x6e\x67\x65\x28\x6c\x65\x6e\x28\x61\x72\x67\x73\x29\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x20\x3d\x20\x73\x65\x6c\x66\x2e\x72\x65\x70\x6c\x61\x63\x65\x28\x27\x7b\x27\x2b\x73\x74\x72\x28\x69\x29\x2b\x27\x7d\x27\x2c\x20\x73\x74\x72\x28\x61\x72\x67\x73\x5b\x69\x5d\x29\x29\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x0a\x0a\x64\x65\x66\x20\x73\x74\x72\x40\x73\x74\x72\x69\x70\x28\x73\x65\x6c\x66\x2c\x20\x63\x68\x61\x72\x73\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x63\x68\x61\x72\x73\x20\x3d\x20\x63\x68\x61\x72\x73\x20\x6f\x72\x20\x27\x20\x5c\x74\x5c\x6e\x5c\x72\x27\x0a\x20\x20\x20\x20\x69\x20\x3d\x20\x30\x0a\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x69\x20\x3c\x20\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x20\x61\x6e\x64\x20\x73\x65\x6c\x66\x5b\x69\x5d\x20\x69\x6e\x20\x63\x68\x61\x72\x73\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x20\x2b\x3d\x20\x31\x0a\x20\x20\x20\x20\x6a\x20\x3d\x20\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x20\x2d\x20\x31\x0a\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x6a\x20\x3e\x3d\x20\x30\x20\x61\x6e\x64\x20\x73\x65\x6c\x66\x5b\x6a\x5d\x20\x69\x6e\x20\x63\x68\x61\x72\x73\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6a\x20\x2d\x3d\x20\x31\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x5b\x69\x3a\x6a\x2b\x31\x5d\x0a\x0a\x23\x23\x23\x23\x23\x20\x6c\x69\x73\x74\x20\x23\x23\x23\x23\x23\x0a\x0a\x6c\x69\x73\x74\x2e\x5f\x5f\x6e\x65\x77\x5f\x5f\x20\x3d\x20\x6c\x61\x6d\x62\x64\x61\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x20\x5b\x78\x20\x66\x6f\x72\x20\x78\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x5d\x0a\x6c\x69\x73\x74\x2e\x5f\x5f\x72\x65\x70\x72\x5f\x5f\x20\x3d\x20\x6c\x61\x6d\x62\x64\x61\x20\x73\x65\x6c\x66\x3a\x20\x27\x5b\x27\x20\x2b\x20\x27\x2c\x20\x27\x2e\x6a\x6f\x69\x6e\x28\x5b\x72\x65\x70\x72\x28\x69\x29\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x73\x65\x6c\x66\x5d\x29\x20\x2b\x20\x27\x5d\x27\x0a\x74\x75\x70\x6c\x65\x2e\x5f\x5f\x72\x65\x70\x72\x5f\x5f\x20\x3d\x20\x6c\x61\x6d\x62\x64\x61\x20\x73\x65\x6c\x66\x3a\x20\x27\x28\x27\x20\x2b\x20\x27\x2c\x20\x27\x2e\x6a\x6f\x69\x6e\x28\x5b\x72\x65\x70\x72\x28\x69\x29\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x73\x65\x6c\x66\x5d\x29\x20\x2b\x20\x27\x29\x27\x0a\x6c\x69\x73\x74\x2e\x5f\x5f\x6a\x73\x6f\x6e\x5f\x5f\x20\x3d\x20\x6c\x61\x6d\x62\x64\x61\x20\x73\x65\x6c\x66\x3a\x20\x27\x5b\x27\x20\x2b\x20\x27\x2c\x20\x27\x2e\x6a\x6f\x69\x6e\x28\x5b\x69\x2e\x5f\x5f\x6a\x73\x6f\x6e\x5f\x5f\x28\x29\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x73\x65\x6c\x66\x5d\x29\x20\x2b\x20\x27\x5d\x27\x0a\x74\x75\x70\x6c\x65\x2e\x5f\x5f\x6a\x73\x6f\x6e\x5f\x5f\x20\x3d\x20\x6c\x61\x6d\x62\x64\x61\x20\x73\x65\x6c\x66\x3a\x20\x27\x5b\x27\x20\x2b\x20\x27\x2c\x20\x27\x2e\x6a\x6f\x69\x6e\x28\x5b\x69\x2e\x5f\x5f\x6a\x73\x6f\x6e\x5f\x5f\x28\x29\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x73\x65\x6c\x66\x5d\x29\x20\x2b\x20\x27\x5d\x27\x0a\x0a\x64\x65\x66\x20\x5f\x5f\x71\x73\x6f\x72\x74\x28\x61\x3a\x20\x6c\x69\x73\x74\x2c\x20\x4c\x3a\x20\x69\x6e\x74\x2c\x20\x52\x3a\x20\x69\x6e\x74\x29\x3a\x0a\x20\x20\x20\x20\x69\x66\x20\x4c\x20\x3e\x3d\x20\x52\x3a\x20\x72\x65\x74\x75\x72\x6e\x3b\x0a\x20\x20\x20\x20\x6d\x69\x64\x20\x3d\x20\x61\x5b\x28\x52\x2b\x4c\x29\x2f\x2f\x32\x5d\x3b\x0a\x20\x20\x20\x20\x69\x2c\x20\x6a\x20\x3d\x20\x4c\x2c\x20\x52\x0a\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x69\x3c\x3d\x6a\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x61\x5b\x69\x5d\x3c\x6d\x69\x64\x3a\x20\x69\x2b\x3d\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x77\x68\x69\x6c\x65\x20\x61\x5b\x6a\x5d\x3e\x6d\x69\x64\x3a\x20\x6a\x2d\x3d\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x69\x3c\x3d\x6a\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x61\x5b\x69\x5d\x2c\x20\x61\x5b\x6a\x5d\x20\x3d\x20\x61\x5b\x6a\x5d\x2c\x20\x61\x5b\x69\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x2b\x3d\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6a\x2d\x3d\x31\x0a\x20\x20\x20\x20\x5f\x5f\x71\x73\x6f\x72\x74\x28\x61\x2c\x20\x4c\x2c\x20\x6a\x29\x0a\x20\x20\x20\x20\x5f\x5f\x71\x73\x6f\x72\x74\x28\x61\x2c\x20\x69\x2c\x20\x52\x29\x0a\x0a\x64\x65\x66\x20\x6c\x69\x73\x74\x40\x73\x6f\x72\x74\x28\x73\x65\x6c\x66\x2c\x20\x72\x65\x76\x65\x72\x73\x65\x3d\x46\x61\x6c\x73\x65\x29\x3a\x0a\x20\x20\x20\x20\x5f\x5f\x71\x73\x6f\x72\x74\x28\x73\x65\x6c\x66\x2c\x20\x30\x2c\x20\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x2d\x31\x29\x0a\x20\x20\x20\x20\x69\x66\x20\x72\x65\x76\x65\x72\x73\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x72\x65\x76\x65\x72\x73\x65\x28\x29\x0a\x0a\x64\x65\x66\x20\x6c\x69\x73\x74\x40\x72\x65\x6d\x6f\x76\x65\x28\x73\x65\x6c\x66\x2c\x20\x76\x61\x6c\x75\x65\x29\x3a\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x72\x61\x6e\x67\x65\x28\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x73\x65\x6c\x66\x5b\x69\x5d\x20\x3d\x3d\x20\x76\x61\x6c\x75\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x65\x6c\x20\x73\x65\x6c\x66\x5b\x69\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x0a\x20\x20\x20\x20\x76\x61\x6c\x75\x65\x20\x3d\x20\x72\x65\x70\x72\x28\x76\x61\x6c\x75\x65\x29\x0a\x20\x20\x20\x20\x72\x61\x69\x73\x65\x20\x56\x61\x6c\x75\x65\x45\x72\x72\x6f\x72\x28\x66\x27\x7b\x76\x61\x6c\x75\x65\x7d\x20\x69\x73\x20\x6e\x6f\x74\x20\x69\x6e\x20\x6c\x69\x73\x74\x27\x29\x0a\x0a\x64\x65\x66\x20\x6c\x69\x73\x74\x40\x69\x6e\x64\x65\x78\x28\x73\x65\x6c\x66\x2c\x20\x76\x61\x6c\x75\x65\x29\x3a\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x72\x61\x6e\x67\x65\x28\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x73\x65\x6c\x66\x5b\x69\x5d\x20\x3d\x3d\x20\x76\x61\x6c\x75\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x69\x0a\x20\x20\x20\x20\x76\x61\x6c\x75\x65\x20\x3d\x20\x72\x65\x70\x72\x28\x76\x61\x6c\x75\x65\x29\x0a\x20\x20\x20\x20\x72\x61\x69\x73\x65\x20\x56\x61\x6c\x75\x65\x45\x72\x72\x6f\x72\x28\x66\x27\x7b\x76\x61\x6c\x75\x65\x7d\x20\x69\x73\x20\x6e\x6f\x74\x20\x69\x6e\x20\x6c\x69\x73\x74\x27\x29\x0a\x0a\x64\x65\x66\x20\x6c\x69\x73\x74\x40\x70\x6f\x70\x28\x73\x65\x6c\x66\x2c\x20\x69\x3d\x2d\x31\x29\x3a\x0a\x20\x20\x20\x20\x72\x65\x73\x20\x3d\x20\x73\x65\x6c\x66\x5b\x69\x5d\x0a\x20\x20\x20\x20\x64\x65\x6c\x20\x73\x65\x6c\x66\x5b\x69\x5d\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x73\x0a\x0a\x64\x65\x66\x20\x6c\x69\x73\x74\x40\x5f\x5f\x65\x71\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x69\x66\x20\x74\x79\x70\x65\x28\x73\x65\x6c\x66\x29\x20\x69\x73\x20\x6e\x6f\x74\x20\x74\x79\x70\x65\x28\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x69\x66\x20\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x20\x21\x3d\x20\x6c\x65\x6e\x28\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x72\x61\x6e\x67\x65\x28\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x73\x65\x6c\x66\x5b\x69\x5d\x20\x21\x3d\x20\x6f\x74\x68\x65\x72\x5b\x69\x5d\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x54\x72\x75\x65\x0a\x74\x75\x70\x6c\x65\x2e\x5f\x5f\x65\x71\x5f\x5f\x20\x3d\x20\x6c\x69\x73\x74\x2e\x5f\x5f\x65\x71\x5f\x5f\x0a\x6c\x69\x73\x74\x2e\x5f\x5f\x6e\x65\x5f\x5f\x20\x3d\x20\x6c\x61\x6d\x62\x64\x61\x20\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x3a\x20\x6e\x6f\x74\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x65\x71\x5f\x5f\x28\x6f\x74\x68\x65\x72\x29\x0a\x74\x75\x70\x6c\x65\x2e\x5f\x5f\x6e\x65\x5f\x5f\x20\x3d\x20\x6c\x61\x6d\x62\x64\x61\x20\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x3a\x20\x6e\x6f\x74\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x65\x71\x5f\x5f\x28\x6f\x74\x68\x65\x72\x29\x0a\x0a\x64\x65\x66\x20\x6c\x69\x73\x74\x40\x63\x6f\x75\x6e\x74\x28\x73\x65\x6c\x66\x2c\x20\x78\x29\x3a\x0a\x20\x20\x20\x20\x72\x65\x73\x20\x3d\x20\x30\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x73\x65\x6c\x66\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x69\x20\x3d\x3d\x20\x78\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x73\x20\x2b\x3d\x20\x31\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x73\x0a\x74\x75\x70\x6c\x65\x2e\x63\x6f\x75\x6e\x74\x20\x3d\x20\x6c\x69\x73\x74\x2e\x63\x6f\x75\x6e\x74\x0a\x0a\x64\x65\x66\x20\x6c\x69\x73\x74\x40\x5f\x5f\x63\x6f\x6e\x74\x61\x69\x6e\x73\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x69\x74\x65\x6d\x29\x3a\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x73\x65\x6c\x66\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x69\x20\x3d\x3d\x20\x69\x74\x65\x6d\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x54\x72\x75\x65\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x46\x61\x6c\x73\x65\x0a\x74\x75\x70\x6c\x65\x2e\x5f\x5f\x63\x6f\x6e\x74\x61\x69\x6e\x73\x5f\x5f\x20\x3d\x20\x6c\x69\x73\x74\x2e\x5f\x5f\x63\x6f\x6e\x74\x61\x69\x6e\x73\x5f\x5f\x0a\x0a\x0a\x63\x6c\x61\x73\x73\x20\x70\x72\x6f\x70\x65\x72\x74\x79\x3a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x69\x6e\x69\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x66\x67\x65\x74\x2c\x20\x66\x73\x65\x74\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x66\x67\x65\x74\x20\x3d\x20\x66\x67\x65\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x66\x73\x65\x74\x20\x3d\x20\x66\x73\x65\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x68\x61\x73\x61\x74\x74\x72\x28\x66\x67\x65\x74\x2c\x20\x27\x5f\x5f\x64\x6f\x63\x5f\x5f\x27\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x64\x6f\x63\x5f\x5f\x20\x3d\x20\x66\x67\x65\x74\x2e\x5f\x5f\x64\x6f\x63\x5f\x5f\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x67\x65\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x62\x6a\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x66\x67\x65\x74\x28\x6f\x62\x6a\x29\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x73\x65\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x62\x6a\x2c\x20\x76\x61\x6c\x75\x65\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x73\x65\x6c\x66\x2e\x66\x73\x65\x74\x20\x69\x73\x20\x4e\x6f\x6e\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x61\x69\x73\x65\x20\x41\x74\x74\x72\x69\x62\x75\x74\x65\x45\x72\x72\x6f\x72\x28\x22\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x70\x72\x6f\x70\x65\x72\x74\x79\x22\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x66\x73\x65\x74\x28\x6f\x62\x6a\x2c\x20\x76\x61\x6c\x75\x65\x29\x0a\x0a\x63\x6c\x61\x73\x73\x20\x73\x74\x61\x74\x69\x63\x6d\x65\x74\x68\x6f\x64\x3a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x69\x6e\x69\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x66\x20\x3d\x20\x66\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x67\x65\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x62\x6a\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x66\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x63\x61\x6c\x6c\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x2a\x61\x72\x67\x73\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x66\x28\x2a\x61\x72\x67\x73\x29\x0a\x20\x20\x20\x20\x0a\x64\x65\x66\x20\x74\x79\x70\x65\x40\x5f\x5f\x72\x65\x70\x72\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x22\x3c\x63\x6c\x61\x73\x73\x20\x27\x22\x20\x2b\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x6e\x61\x6d\x65\x5f\x5f\x20\x2b\x20\x22\x27\x3e\x22\x0a\x0a\x64\x65\x66\x20\x68\x65\x6c\x70\x28\x6f\x62\x6a\x29\x3a\x0a\x20\x20\x20\x20\x69\x66\x20\x68\x61\x73\x61\x74\x74\x72\x28\x6f\x62\x6a\x2c\x20\x27\x5f\x5f\x66\x75\x6e\x63\x5f\x5f\x27\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x62\x6a\x20\x3d\x20\x6f\x62\x6a\x2e\x5f\x5f\x66\x75\x6e\x63\x5f\x5f\x0a\x20\x20\x20\x20\x69\x66\x20\x68\x61\x73\x61\x74\x74\x72\x28\x6f\x62\x6a\x2c\x20\x27\x5f\x5f\x64\x6f\x63\x5f\x5f\x27\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x70\x72\x69\x6e\x74\x28\x6f\x62\x6a\x2e\x5f\x5f\x64\x6f\x63\x5f\x5f\x29\x0a\x20\x20\x20\x20\x65\x6c\x73\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x70\x72\x69\x6e\x74\x28\x22\x4e\x6f\x20\x64\x6f\x63\x73\x74\x72\x69\x6e\x67\x20\x66\x6f\x75\x6e\x64\x22\x29\x0a"}, 6727 - {"_set", "\x63\x6c\x61\x73\x73\x20\x73\x65\x74\x3a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x69\x6e\x69\x74\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3d\x4e\x6f\x6e\x65\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x20\x3d\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x20\x6f\x72\x20\x5b\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x61\x20\x3d\x20\x7b\x7d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x69\x74\x65\x6d\x20\x69\x6e\x20\x69\x74\x65\x72\x61\x62\x6c\x65\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x61\x64\x64\x28\x69\x74\x65\x6d\x29\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x61\x64\x64\x28\x73\x65\x6c\x66\x2c\x20\x65\x6c\x65\x6d\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x65\x6c\x65\x6d\x5d\x20\x3d\x20\x4e\x6f\x6e\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x64\x69\x73\x63\x61\x72\x64\x28\x73\x65\x6c\x66\x2c\x20\x65\x6c\x65\x6d\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x65\x6c\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x65\x6c\x65\x6d\x5d\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x72\x65\x6d\x6f\x76\x65\x28\x73\x65\x6c\x66\x2c\x20\x65\x6c\x65\x6d\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x64\x65\x6c\x20\x73\x65\x6c\x66\x2e\x5f\x61\x5b\x65\x6c\x65\x6d\x5d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x63\x6c\x65\x61\x72\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x5f\x61\x2e\x63\x6c\x65\x61\x72\x28\x29\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x75\x70\x64\x61\x74\x65\x28\x73\x65\x6c\x66\x2c\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x6f\x74\x68\x65\x72\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x6c\x66\x2e\x61\x64\x64\x28\x65\x6c\x65\x6d\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x6c\x65\x6e\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6c\x65\x6e\x28\x73\x65\x6c\x66\x2e\x5f\x61\x29\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x63\x6f\x70\x79\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x74\x28\x73\x65\x6c\x66\x2e\x5f\x61\x2e\x6b\x65\x79\x73\x28\x29\x29\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x61\x6e\x64\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x20\x3d\x20\x73\x65\x74\x28\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x73\x65\x6c\x66\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x6f\x74\x68\x65\x72\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x2e\x61\x64\x64\x28\x65\x6c\x65\x6d\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x74\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x6f\x72\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x20\x3d\x20\x73\x65\x6c\x66\x2e\x63\x6f\x70\x79\x28\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x6f\x74\x68\x65\x72\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x2e\x61\x64\x64\x28\x65\x6c\x65\x6d\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x74\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x73\x75\x62\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x20\x3d\x20\x73\x65\x74\x28\x29\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x73\x65\x6c\x66\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x65\x6c\x65\x6d\x20\x6e\x6f\x74\x20\x69\x6e\x20\x6f\x74\x68\x65\x72\x3a\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x2e\x61\x64\x64\x28\x65\x6c\x65\x6d\x29\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x74\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x78\x6f\x72\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x20\x3d\x20\x73\x65\x74\x28\x29\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x73\x65\x6c\x66\x3a\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x65\x6c\x65\x6d\x20\x6e\x6f\x74\x20\x69\x6e\x20\x6f\x74\x68\x65\x72\x3a\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x2e\x61\x64\x64\x28\x65\x6c\x65\x6d\x29\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x6f\x74\x68\x65\x72\x3a\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x65\x6c\x65\x6d\x20\x6e\x6f\x74\x20\x69\x6e\x20\x73\x65\x6c\x66\x3a\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x2e\x61\x64\x64\x28\x65\x6c\x65\x6d\x29\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x74\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x75\x6e\x69\x6f\x6e\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x20\x7c\x20\x6f\x74\x68\x65\x72\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x69\x6e\x74\x65\x72\x73\x65\x63\x74\x69\x6f\x6e\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x20\x26\x20\x6f\x74\x68\x65\x72\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x64\x69\x66\x66\x65\x72\x65\x6e\x63\x65\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x20\x2d\x20\x6f\x74\x68\x65\x72\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x73\x79\x6d\x6d\x65\x74\x72\x69\x63\x5f\x64\x69\x66\x66\x65\x72\x65\x6e\x63\x65\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x20\x5e\x20\x6f\x74\x68\x65\x72\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x65\x71\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x78\x6f\x72\x5f\x5f\x28\x6f\x74\x68\x65\x72\x29\x2e\x5f\x5f\x6c\x65\x6e\x5f\x5f\x28\x29\x20\x3d\x3d\x20\x30\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x6e\x65\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x78\x6f\x72\x5f\x5f\x28\x6f\x74\x68\x65\x72\x29\x2e\x5f\x5f\x6c\x65\x6e\x5f\x5f\x28\x29\x20\x21\x3d\x20\x30\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x69\x73\x64\x69\x73\x6a\x6f\x69\x6e\x74\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x61\x6e\x64\x5f\x5f\x28\x6f\x74\x68\x65\x72\x29\x2e\x5f\x5f\x6c\x65\x6e\x5f\x5f\x28\x29\x20\x3d\x3d\x20\x30\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x69\x73\x73\x75\x62\x73\x65\x74\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x5f\x73\x75\x62\x5f\x5f\x28\x6f\x74\x68\x65\x72\x29\x2e\x5f\x5f\x6c\x65\x6e\x5f\x5f\x28\x29\x20\x3d\x3d\x20\x30\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x69\x73\x73\x75\x70\x65\x72\x73\x65\x74\x28\x73\x65\x6c\x66\x2c\x20\x6f\x74\x68\x65\x72\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x6f\x74\x68\x65\x72\x2e\x5f\x5f\x73\x75\x62\x5f\x5f\x28\x73\x65\x6c\x66\x29\x2e\x5f\x5f\x6c\x65\x6e\x5f\x5f\x28\x29\x20\x3d\x3d\x20\x30\x0a\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x63\x6f\x6e\x74\x61\x69\x6e\x73\x5f\x5f\x28\x73\x65\x6c\x66\x2c\x20\x65\x6c\x65\x6d\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x65\x6c\x65\x6d\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x72\x65\x70\x72\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x6c\x65\x6e\x28\x73\x65\x6c\x66\x29\x20\x3d\x3d\x20\x30\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x27\x73\x65\x74\x28\x29\x27\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x27\x7b\x27\x2b\x20\x27\x2c\x20\x27\x2e\x6a\x6f\x69\x6e\x28\x5b\x72\x65\x70\x72\x28\x69\x29\x20\x66\x6f\x72\x20\x69\x20\x69\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x2e\x6b\x65\x79\x73\x28\x29\x5d\x29\x20\x2b\x20\x27\x7d\x27\x0a\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x64\x65\x66\x20\x5f\x5f\x69\x74\x65\x72\x5f\x5f\x28\x73\x65\x6c\x66\x29\x3a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x73\x65\x6c\x66\x2e\x5f\x61\x2e\x6b\x65\x79\x73\x28\x29"}, 6728 - 6729 - }; 6730 - } // namespace pkpy 6731 - 6732 - 6733 - 6734 - namespace pkpy{ 6735 - 6736 - class RangeIter final: public BaseIter { 6737 - i64 current; 6738 - Range r; // copy by value, so we don't need to keep ref 6739 - public: 6740 - RangeIter(VM* vm, PyObject* ref) : BaseIter(vm) { 6741 - this->r = OBJ_GET(Range, ref); 6742 - this->current = r.start; 6743 - } 6744 - 6745 - bool _has_next(){ 6746 - return r.step > 0 ? current < r.stop : current > r.stop; 6747 - } 6748 - 6749 - PyObject* next(){ 6750 - if(!_has_next()) return vm->StopIteration; 6751 - current += r.step; 6752 - return VAR(current-r.step); 6753 - } 6754 - }; 6755 - 6756 - template <typename T> 6757 - class ArrayIter final: public BaseIter { 6758 - PyObject* ref; 6759 - T* array; 6760 - int index; 6761 - public: 6762 - ArrayIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref) { 6763 - array = &OBJ_GET(T, ref); 6764 - index = 0; 6765 - } 6766 - 6767 - PyObject* next() override{ 6768 - if(index >= array->size()) return vm->StopIteration; 6769 - return array->operator[](index++); 6770 - } 6771 - 6772 - void _gc_mark() const{ 6773 - OBJ_MARK(ref); 6774 - } 6775 - }; 6776 - 6777 - class StringIter final: public BaseIter { 6778 - PyObject* ref; 6779 - int index; 6780 - public: 6781 - StringIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref), index(0) {} 6782 - 6783 - PyObject* next() override{ 6784 - // TODO: optimize this to use iterator 6785 - // operator[] is O(n) complexity 6786 - Str* str = &OBJ_GET(Str, ref); 6787 - if(index == str->u8_length()) return vm->StopIteration; 6788 - return VAR(str->u8_getitem(index++)); 6789 - } 6790 - 6791 - void _gc_mark() const{ 6792 - OBJ_MARK(ref); 6793 - } 6794 - }; 6795 - 6796 - inline PyObject* Generator::next(){ 6797 - if(state == 2) return vm->StopIteration; 6798 - // reset frame._sp_base 6799 - frame._sp_base = frame._s->_sp; 6800 - frame._locals.a = frame._s->_sp; 6801 - // restore the context 6802 - for(PyObject* obj: s_backup) frame._s->push(obj); 6803 - s_backup.clear(); 6804 - vm->callstack.push(std::move(frame)); 6805 - PyObject* ret = vm->_run_top_frame(); 6806 - if(ret == PY_OP_YIELD){ 6807 - // backup the context 6808 - frame = std::move(vm->callstack.top()); 6809 - PyObject* ret = frame._s->popx(); 6810 - for(PyObject* obj: frame.stack_view()) s_backup.push_back(obj); 6811 - vm->_pop_frame(); 6812 - state = 1; 6813 - if(ret == vm->StopIteration) state = 2; 6814 - return ret; 6815 - }else{ 6816 - state = 2; 6817 - return vm->StopIteration; 6818 - } 6819 - } 6820 - 6821 - inline void Generator::_gc_mark() const{ 6822 - frame._gc_mark(); 6823 - for(PyObject* obj: s_backup) OBJ_MARK(obj); 6824 - } 6825 - 6826 - } // namespace pkpy 6827 - 6828 - 6829 - namespace pkpy { 6830 - 6831 - // https://github.com/zhicheng/base64/blob/master/base64.c 6832 - 6833 - #define BASE64_PAD '=' 6834 - #define BASE64DE_FIRST '+' 6835 - #define BASE64DE_LAST 'z' 6836 - 6837 - /* BASE 64 encode table */ 6838 - static const char base64en[] = { 6839 - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 6840 - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 6841 - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 6842 - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 6843 - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 6844 - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 6845 - 'w', 'x', 'y', 'z', '0', '1', '2', '3', 6846 - '4', '5', '6', '7', '8', '9', '+', '/', 6847 - }; 6848 - 6849 - /* ASCII order for BASE 64 decode, 255 in unused character */ 6850 - static const unsigned char base64de[] = { 6851 - /* nul, soh, stx, etx, eot, enq, ack, bel, */ 6852 - 255, 255, 255, 255, 255, 255, 255, 255, 6853 - 6854 - /* bs, ht, nl, vt, np, cr, so, si, */ 6855 - 255, 255, 255, 255, 255, 255, 255, 255, 6856 - 6857 - /* dle, dc1, dc2, dc3, dc4, nak, syn, etb, */ 6858 - 255, 255, 255, 255, 255, 255, 255, 255, 6859 - 6860 - /* can, em, sub, esc, fs, gs, rs, us, */ 6861 - 255, 255, 255, 255, 255, 255, 255, 255, 6862 - 6863 - /* sp, '!', '"', '#', '$', '%', '&', ''', */ 6864 - 255, 255, 255, 255, 255, 255, 255, 255, 6865 - 6866 - /* '(', ')', '*', '+', ',', '-', '.', '/', */ 6867 - 255, 255, 255, 62, 255, 255, 255, 63, 6868 - 6869 - /* '0', '1', '2', '3', '4', '5', '6', '7', */ 6870 - 52, 53, 54, 55, 56, 57, 58, 59, 6871 - 6872 - /* '8', '9', ':', ';', '<', '=', '>', '?', */ 6873 - 60, 61, 255, 255, 255, 255, 255, 255, 6874 - 6875 - /* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */ 6876 - 255, 0, 1, 2, 3, 4, 5, 6, 6877 - 6878 - /* 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */ 6879 - 7, 8, 9, 10, 11, 12, 13, 14, 6880 - 6881 - /* 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */ 6882 - 15, 16, 17, 18, 19, 20, 21, 22, 6883 - 6884 - /* 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */ 6885 - 23, 24, 25, 255, 255, 255, 255, 255, 6886 - 6887 - /* '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */ 6888 - 255, 26, 27, 28, 29, 30, 31, 32, 6889 - 6890 - /* 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */ 6891 - 33, 34, 35, 36, 37, 38, 39, 40, 6892 - 6893 - /* 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */ 6894 - 41, 42, 43, 44, 45, 46, 47, 48, 6895 - 6896 - /* 'x', 'y', 'z', '{', '|', '}', '~', del, */ 6897 - 49, 50, 51, 255, 255, 255, 255, 255 6898 - }; 6899 - 6900 - unsigned int 6901 - base64_encode(const unsigned char *in, unsigned int inlen, char *out) 6902 - { 6903 - int s; 6904 - unsigned int i; 6905 - unsigned int j; 6906 - unsigned char c; 6907 - unsigned char l; 6908 - 6909 - s = 0; 6910 - l = 0; 6911 - for (i = j = 0; i < inlen; i++) { 6912 - c = in[i]; 6913 - 6914 - switch (s) { 6915 - case 0: 6916 - s = 1; 6917 - out[j++] = base64en[(c >> 2) & 0x3F]; 6918 - break; 6919 - case 1: 6920 - s = 2; 6921 - out[j++] = base64en[((l & 0x3) << 4) | ((c >> 4) & 0xF)]; 6922 - break; 6923 - case 2: 6924 - s = 0; 6925 - out[j++] = base64en[((l & 0xF) << 2) | ((c >> 6) & 0x3)]; 6926 - out[j++] = base64en[c & 0x3F]; 6927 - break; 6928 - } 6929 - l = c; 6930 - } 6931 - 6932 - switch (s) { 6933 - case 1: 6934 - out[j++] = base64en[(l & 0x3) << 4]; 6935 - out[j++] = BASE64_PAD; 6936 - out[j++] = BASE64_PAD; 6937 - break; 6938 - case 2: 6939 - out[j++] = base64en[(l & 0xF) << 2]; 6940 - out[j++] = BASE64_PAD; 6941 - break; 6942 - } 6943 - 6944 - out[j] = 0; 6945 - 6946 - return j; 6947 - } 6948 - 6949 - unsigned int 6950 - base64_decode(const char *in, unsigned int inlen, unsigned char *out) 6951 - { 6952 - unsigned int i; 6953 - unsigned int j; 6954 - unsigned char c; 6955 - 6956 - if (inlen & 0x3) { 6957 - return 0; 6958 - } 6959 - 6960 - for (i = j = 0; i < inlen; i++) { 6961 - if (in[i] == BASE64_PAD) { 6962 - break; 6963 - } 6964 - if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST) { 6965 - return 0; 6966 - } 6967 - 6968 - c = base64de[(unsigned char)in[i]]; 6969 - if (c == 255) { 6970 - return 0; 6971 - } 6972 - 6973 - switch (i & 0x3) { 6974 - case 0: 6975 - out[j] = (c << 2) & 0xFF; 6976 - break; 6977 - case 1: 6978 - out[j++] |= (c >> 4) & 0x3; 6979 - out[j] = (c & 0xF) << 4; 6980 - break; 6981 - case 2: 6982 - out[j++] |= (c >> 2) & 0xF; 6983 - out[j] = (c & 0x3) << 6; 6984 - break; 6985 - case 3: 6986 - out[j++] |= c; 6987 - break; 6988 - } 6989 - } 6990 - 6991 - return j; 6992 - } 6993 - 6994 - void add_module_base64(VM* vm){ 6995 - PyObject* mod = vm->new_module("base64"); 6996 - 6997 - // b64encode 6998 - vm->bind_static_method<1>(mod, "b64encode", [](VM* vm, ArgsView args){ 6999 - Bytes& b = CAST(Bytes&, args[0]); 7000 - std::vector<char> out(b.size() * 2); 7001 - int size = base64_encode((const unsigned char*)b.data(), b.size(), out.data()); 7002 - out.resize(size); 7003 - return VAR(Bytes(std::move(out))); 7004 - }); 7005 - 7006 - // b64decode 7007 - vm->bind_static_method<1>(mod, "b64decode", [](VM* vm, ArgsView args){ 7008 - Bytes& b = CAST(Bytes&, args[0]); 7009 - std::vector<char> out(b.size()); 7010 - int size = base64_decode(b.data(), b.size(), (unsigned char*)out.data()); 7011 - out.resize(size); 7012 - return VAR(Bytes(std::move(out))); 7013 - }); 7014 - } 7015 - 7016 - } // namespace pkpy 7017 - 7018 - 7019 - namespace pkpy { 7020 - 7021 - #define PY_CLASS(T, mod, name) \ 7022 - static Type _type(VM* vm) { \ 7023 - static const StrName __x0(#mod); \ 7024 - static const StrName __x1(#name); \ 7025 - return OBJ_GET(Type, vm->_modules[__x0]->attr(__x1)); \ 7026 - } \ 7027 - static PyObject* register_class(VM* vm, PyObject* mod) { \ 7028 - PyObject* type = vm->new_type_object(mod, #name, vm->tp_object); \ 7029 - if(OBJ_NAME(mod) != #mod) { \ 7030 - auto msg = fmt("register_class() failed: ", OBJ_NAME(mod), " != ", #mod); \ 7031 - throw std::runtime_error(msg); \ 7032 - } \ 7033 - T::_register(vm, mod, type); \ 7034 - type->attr()._try_perfect_rehash(); \ 7035 - return type; \ 7036 - } 7037 - 7038 - #define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), T(__VA_ARGS__)) 7039 - 7040 - 7041 - struct VoidP{ 7042 - PY_CLASS(VoidP, c, void_p) 7043 - 7044 - void* ptr; 7045 - VoidP(void* ptr): ptr(ptr){} 7046 - 7047 - static void _register(VM* vm, PyObject* mod, PyObject* type){ 7048 - vm->bind_static_method<1>(type, "__new__", CPP_NOT_IMPLEMENTED()); 7049 - 7050 - vm->bind_static_method<1>(type, "__repr__", [](VM* vm, ArgsView args){ 7051 - VoidP& self = CAST(VoidP&, args[0]); 7052 - std::stringstream ss; 7053 - ss << "<void* at " << self.ptr << ">"; 7054 - return VAR(ss.str()); 7055 - }); 7056 - } 7057 - }; 7058 - 7059 - inline void add_module_c(VM* vm){ 7060 - PyObject* mod = vm->new_module("c"); 7061 - VoidP::register_class(vm, mod); 7062 - } 7063 - 7064 - inline PyObject* py_var(VM* vm, void* p){ 7065 - return VAR_T(VoidP, p); 7066 - } 7067 - 7068 - inline PyObject* py_var(VM* vm, char* p){ 7069 - return VAR_T(VoidP, p); 7070 - } 7071 - /***********************************************/ 7072 - 7073 - template<typename T> 7074 - struct _pointer { 7075 - static constexpr int level = 0; 7076 - using baseT = T; 7077 - }; 7078 - 7079 - template<typename T> 7080 - struct _pointer<T*> { 7081 - static constexpr int level = _pointer<T>::level + 1; 7082 - using baseT = typename _pointer<T>::baseT; 7083 - }; 7084 - 7085 - template<typename T> 7086 - struct pointer { 7087 - static constexpr int level = _pointer<std::decay_t<T>>::level; 7088 - using baseT = typename _pointer<std::decay_t<T>>::baseT; 7089 - }; 7090 - 7091 - template<typename T> 7092 - T py_pointer_cast(VM* vm, PyObject* var){ 7093 - static_assert(std::is_pointer_v<T>); 7094 - VoidP& p = CAST(VoidP&, var); 7095 - return reinterpret_cast<T>(p.ptr); 7096 - } 7097 - } // namespace pkpy 7098 - 7099 - 7100 - #if __has_include("httplib.h") 7101 - #include "httplib.h" 7102 - 7103 - namespace pkpy { 7104 - 7105 - inline void add_module_requests(VM* vm){ 7106 - static StrName m_requests("requests"); 7107 - static StrName m_Response("Response"); 7108 - PyObject* mod = vm->new_module(m_requests); 7109 - CodeObject_ code = vm->compile(kPythonLibs["requests"], "requests.py", EXEC_MODE); 7110 - vm->_exec(code, mod); 7111 - 7112 - vm->bind_func<4>(mod, "_request", [](VM* vm, ArgsView args){ 7113 - Str method = CAST(Str&, args[0]); 7114 - Str url = CAST(Str&, args[1]); 7115 - PyObject* headers = args[2]; // a dict object 7116 - PyObject* body = args[3]; // a bytes object 7117 - 7118 - if(url.index("http://") != 0){ 7119 - vm->ValueError("url must start with http://"); 7120 - } 7121 - 7122 - for(char c: url){ 7123 - switch(c){ 7124 - case '.': 7125 - case '-': 7126 - case '_': 7127 - case '~': 7128 - case ':': 7129 - case '/': 7130 - break; 7131 - default: 7132 - if(!isalnum(c)){ 7133 - vm->ValueError(fmt("invalid character in url: '", c, "'")); 7134 - } 7135 - } 7136 - } 7137 - 7138 - int slash = url.index("/", 7); 7139 - Str path = "/"; 7140 - if(slash != -1){ 7141 - path = url.substr(slash); 7142 - url = url.substr(0, slash); 7143 - if(path.empty()) path = "/"; 7144 - } 7145 - 7146 - httplib::Client client(url.str()); 7147 - 7148 - httplib::Headers h; 7149 - if(headers != vm->None){ 7150 - List list = CAST(List&, headers); 7151 - for(auto& item : list){ 7152 - Tuple t = CAST(Tuple&, item); 7153 - Str key = CAST(Str&, t[0]); 7154 - Str value = CAST(Str&, t[1]); 7155 - h.emplace(key.str(), value.str()); 7156 - } 7157 - } 7158 - 7159 - auto _to_resp = [=](const httplib::Result& res){ 7160 - return vm->call( 7161 - vm->_modules[m_requests]->attr(m_Response), 7162 - VAR(res->status), 7163 - VAR(res->reason), 7164 - VAR(Bytes(res->body)) 7165 - ); 7166 - }; 7167 - 7168 - if(method == "GET"){ 7169 - httplib::Result res = client.Get(path.str(), h); 7170 - return _to_resp(res); 7171 - }else if(method == "POST"){ 7172 - Bytes b = CAST(Bytes&, body); 7173 - httplib::Result res = client.Post(path.str(), h, b.data(), b.size(), "application/octet-stream"); 7174 - return _to_resp(res); 7175 - }else if(method == "PUT"){ 7176 - Bytes b = CAST(Bytes&, body); 7177 - httplib::Result res = client.Put(path.str(), h, b.data(), b.size(), "application/octet-stream"); 7178 - return _to_resp(res); 7179 - }else if(method == "DELETE"){ 7180 - httplib::Result res = client.Delete(path.str(), h); 7181 - return _to_resp(res); 7182 - }else{ 7183 - vm->ValueError("invalid method"); 7184 - } 7185 - UNREACHABLE(); 7186 - }); 7187 - } 7188 - 7189 - } // namespace pkpy 7190 - 7191 - #else 7192 - 7193 - inline void add_module_requests(void* vm){ } 7194 - 7195 - #endif 7196 - 7197 - 7198 - #if PK_ENABLE_OS 7199 - 7200 - #include <filesystem> 7201 - #include <cstdio> 7202 - 7203 - namespace pkpy{ 7204 - 7205 - inline int _ = set_read_file_cwd([](const Str& name){ 7206 - std::filesystem::path path(name.sv()); 7207 - bool exists = std::filesystem::exists(path); 7208 - if(!exists) return Bytes(); 7209 - std::string cname = name.str(); 7210 - FILE* fp = fopen(cname.c_str(), "rb"); 7211 - if(!fp) return Bytes(); 7212 - fseek(fp, 0, SEEK_END); 7213 - std::vector<char> buffer(ftell(fp)); 7214 - fseek(fp, 0, SEEK_SET); 7215 - fread(buffer.data(), 1, buffer.size(), fp); 7216 - fclose(fp); 7217 - return Bytes(std::move(buffer)); 7218 - }); 7219 - 7220 - struct FileIO { 7221 - PY_CLASS(FileIO, io, FileIO) 7222 - 7223 - Str file; 7224 - Str mode; 7225 - FILE* fp; 7226 - 7227 - bool is_text() const { return mode != "rb" && mode != "wb" && mode != "ab"; } 7228 - 7229 - FileIO(VM* vm, std::string file, std::string mode): file(file), mode(mode) { 7230 - fp = fopen(file.c_str(), mode.c_str()); 7231 - if(!fp) vm->IOError(strerror(errno)); 7232 - } 7233 - 7234 - void close(){ 7235 - if(fp == nullptr) return; 7236 - fclose(fp); 7237 - fp = nullptr; 7238 - } 7239 - 7240 - static void _register(VM* vm, PyObject* mod, PyObject* type){ 7241 - vm->bind_static_method<2>(type, "__new__", [](VM* vm, ArgsView args){ 7242 - return VAR_T(FileIO, 7243 - vm, CAST(Str&, args[0]).str(), CAST(Str&, args[1]).str() 7244 - ); 7245 - }); 7246 - 7247 - vm->bind_method<0>(type, "read", [](VM* vm, ArgsView args){ 7248 - FileIO& io = CAST(FileIO&, args[0]); 7249 - fseek(io.fp, 0, SEEK_END); 7250 - std::vector<char> buffer(ftell(io.fp)); 7251 - fseek(io.fp, 0, SEEK_SET); 7252 - fread(buffer.data(), 1, buffer.size(), io.fp); 7253 - Bytes b(std::move(buffer)); 7254 - if(io.is_text()) return VAR(Str(b.str())); 7255 - return VAR(std::move(b)); 7256 - }); 7257 - 7258 - vm->bind_method<1>(type, "write", [](VM* vm, ArgsView args){ 7259 - FileIO& io = CAST(FileIO&, args[0]); 7260 - if(io.is_text()){ 7261 - Str& s = CAST(Str&, args[1]); 7262 - fwrite(s.data, 1, s.length(), io.fp); 7263 - }else{ 7264 - Bytes& buffer = CAST(Bytes&, args[1]); 7265 - fwrite(buffer.data(), 1, buffer.size(), io.fp); 7266 - } 7267 - return vm->None; 7268 - }); 7269 - 7270 - vm->bind_method<0>(type, "close", [](VM* vm, ArgsView args){ 7271 - FileIO& io = CAST(FileIO&, args[0]); 7272 - io.close(); 7273 - return vm->None; 7274 - }); 7275 - 7276 - vm->bind_method<0>(type, "__exit__", [](VM* vm, ArgsView args){ 7277 - FileIO& io = CAST(FileIO&, args[0]); 7278 - io.close(); 7279 - return vm->None; 7280 - }); 7281 - 7282 - vm->bind_method<0>(type, "__enter__", CPP_LAMBDA(vm->None)); 7283 - } 7284 - }; 7285 - 7286 - inline void add_module_io(VM* vm){ 7287 - PyObject* mod = vm->new_module("io"); 7288 - FileIO::register_class(vm, mod); 7289 - vm->bind_builtin_func<2>("open", [](VM* vm, ArgsView args){ 7290 - static StrName m_io("io"); 7291 - static StrName m_FileIO("FileIO"); 7292 - return vm->call(vm->_modules[m_io]->attr(m_FileIO), args[0], args[1]); 7293 - }); 7294 - } 7295 - 7296 - inline void add_module_os(VM* vm){ 7297 - PyObject* mod = vm->new_module("os"); 7298 - PyObject* path_obj = vm->heap.gcnew<DummyInstance>(vm->tp_object, {}); 7299 - mod->attr().set("path", path_obj); 7300 - 7301 - // Working directory is shared by all VMs!! 7302 - vm->bind_func<0>(mod, "getcwd", [](VM* vm, ArgsView args){ 7303 - return VAR(std::filesystem::current_path().string()); 7304 - }); 7305 - 7306 - vm->bind_func<1>(mod, "chdir", [](VM* vm, ArgsView args){ 7307 - std::filesystem::path path(CAST(Str&, args[0]).sv()); 7308 - std::filesystem::current_path(path); 7309 - return vm->None; 7310 - }); 7311 - 7312 - vm->bind_func<1>(mod, "listdir", [](VM* vm, ArgsView args){ 7313 - std::filesystem::path path(CAST(Str&, args[0]).sv()); 7314 - std::filesystem::directory_iterator di; 7315 - try{ 7316 - di = std::filesystem::directory_iterator(path); 7317 - }catch(std::filesystem::filesystem_error& e){ 7318 - std::string msg = e.what(); 7319 - auto pos = msg.find_last_of(":"); 7320 - if(pos != std::string::npos) msg = msg.substr(pos + 1); 7321 - vm->IOError(Str(msg).lstrip()); 7322 - } 7323 - List ret; 7324 - for(auto& p: di) ret.push_back(VAR(p.path().filename().string())); 7325 - return VAR(ret); 7326 - }); 7327 - 7328 - vm->bind_func<1>(mod, "remove", [](VM* vm, ArgsView args){ 7329 - std::filesystem::path path(CAST(Str&, args[0]).sv()); 7330 - bool ok = std::filesystem::remove(path); 7331 - if(!ok) vm->IOError("operation failed"); 7332 - return vm->None; 7333 - }); 7334 - 7335 - vm->bind_func<1>(mod, "mkdir", [](VM* vm, ArgsView args){ 7336 - std::filesystem::path path(CAST(Str&, args[0]).sv()); 7337 - bool ok = std::filesystem::create_directory(path); 7338 - if(!ok) vm->IOError("operation failed"); 7339 - return vm->None; 7340 - }); 7341 - 7342 - vm->bind_func<1>(mod, "rmdir", [](VM* vm, ArgsView args){ 7343 - std::filesystem::path path(CAST(Str&, args[0]).sv()); 7344 - bool ok = std::filesystem::remove(path); 7345 - if(!ok) vm->IOError("operation failed"); 7346 - return vm->None; 7347 - }); 7348 - 7349 - vm->bind_func<-1>(path_obj, "join", [](VM* vm, ArgsView args){ 7350 - std::filesystem::path path; 7351 - for(int i=0; i<args.size(); i++){ 7352 - path /= CAST(Str&, args[i]).sv(); 7353 - } 7354 - return VAR(path.string()); 7355 - }); 7356 - 7357 - vm->bind_func<1>(path_obj, "exists", [](VM* vm, ArgsView args){ 7358 - std::filesystem::path path(CAST(Str&, args[0]).sv()); 7359 - bool exists = std::filesystem::exists(path); 7360 - return VAR(exists); 7361 - }); 7362 - 7363 - vm->bind_func<1>(path_obj, "basename", [](VM* vm, ArgsView args){ 7364 - std::filesystem::path path(CAST(Str&, args[0]).sv()); 7365 - return VAR(path.filename().string()); 7366 - }); 7367 - } 7368 - 7369 - } // namespace pkpy 7370 - 7371 - 7372 - #else 7373 - 7374 - namespace pkpy{ 7375 - inline void add_module_io(void* vm){} 7376 - inline void add_module_os(void* vm){} 7377 - } // namespace pkpy 7378 - 7379 - #endif 7380 - 7381 - 7382 - namespace pkpy { 7383 - 7384 - inline CodeObject_ VM::compile(Str source, Str filename, CompileMode mode, bool unknown_global_scope) { 7385 - Compiler compiler(this, source, filename, mode, unknown_global_scope); 7386 - try{ 7387 - return compiler.compile(); 7388 - }catch(Exception& e){ 7389 - #if DEBUG_FULL_EXCEPTION 7390 - std::cerr << e.summary() << std::endl; 7391 - #endif 7392 - _error(e); 7393 - return nullptr; 7394 - } 7395 - } 7396 - 7397 - #define BIND_NUM_ARITH_OPT(name, op) \ 7398 - _vm->bind_method<1>("int", #name, [](VM* vm, ArgsView args){ \ 7399 - if(is_int(args[1])){ \ 7400 - return VAR(_CAST(i64, args[0]) op _CAST(i64, args[1])); \ 7401 - }else{ \ 7402 - return VAR(vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \ 7403 - } \ 7404 - }); \ 7405 - _vm->bind_method<1>("float", #name, [](VM* vm, ArgsView args){ \ 7406 - return VAR(_CAST(f64, args[0]) op vm->num_to_float(args[1])); \ 7407 - }); 7408 - 7409 - 7410 - 7411 - #define BIND_NUM_LOGICAL_OPT(name, op, is_eq) \ 7412 - _vm->bind_method<1>("int", #name, [](VM* vm, ArgsView args){ \ 7413 - if(is_int(args[1])) return VAR(_CAST(i64, args[0]) op _CAST(i64, args[1])); \ 7414 - if(is_float(args[1])) return VAR(vm->num_to_float(args[0]) op _CAST(f64, args[1])); \ 7415 - if constexpr(is_eq) return VAR(args[0] op args[1]); \ 7416 - vm->TypeError("unsupported operand type(s) for " #op ); \ 7417 - return vm->None; \ 7418 - }); \ 7419 - _vm->bind_method<1>("float", #name, [](VM* vm, ArgsView args){ \ 7420 - if(is_float(args[1])) return VAR(_CAST(f64, args[0]) op _CAST(f64, args[1])); \ 7421 - if(is_int(args[1])) return VAR(_CAST(f64, args[0]) op _CAST(i64, args[1])); \ 7422 - if constexpr(is_eq) return VAR(args[0] op args[1]); \ 7423 - vm->TypeError("unsupported operand type(s) for " #op ); \ 7424 - return vm->None; \ 7425 - }); 7426 - 7427 - 7428 - inline void init_builtins(VM* _vm) { 7429 - BIND_NUM_ARITH_OPT(__add__, +) 7430 - BIND_NUM_ARITH_OPT(__sub__, -) 7431 - BIND_NUM_ARITH_OPT(__mul__, *) 7432 - 7433 - BIND_NUM_LOGICAL_OPT(__lt__, <, false) 7434 - BIND_NUM_LOGICAL_OPT(__le__, <=, false) 7435 - BIND_NUM_LOGICAL_OPT(__gt__, >, false) 7436 - BIND_NUM_LOGICAL_OPT(__ge__, >=, false) 7437 - BIND_NUM_LOGICAL_OPT(__eq__, ==, true) 7438 - BIND_NUM_LOGICAL_OPT(__ne__, !=, true) 7439 - 7440 - #undef BIND_NUM_ARITH_OPT 7441 - #undef BIND_NUM_LOGICAL_OPT 7442 - 7443 - _vm->bind_builtin_func<2>("super", [](VM* vm, ArgsView args) { 7444 - vm->check_non_tagged_type(args[0], vm->tp_type); 7445 - Type type = OBJ_GET(Type, args[0]); 7446 - if(!vm->isinstance(args[1], type)){ 7447 - Str _0 = obj_type_name(vm, OBJ_GET(Type, vm->_t(args[1]))); 7448 - Str _1 = obj_type_name(vm, type); 7449 - vm->TypeError("super(): " + _0.escape() + " is not an instance of " + _1.escape()); 7450 - } 7451 - Type base = vm->_all_types[type].base; 7452 - return vm->heap.gcnew(vm->tp_super, Super(args[1], base)); 7453 - }); 7454 - 7455 - _vm->bind_builtin_func<2>("isinstance", [](VM* vm, ArgsView args) { 7456 - vm->check_non_tagged_type(args[1], vm->tp_type); 7457 - Type type = OBJ_GET(Type, args[1]); 7458 - return VAR(vm->isinstance(args[0], type)); 7459 - }); 7460 - 7461 - _vm->bind_builtin_func<0>("globals", [](VM* vm, ArgsView args) { 7462 - PyObject* mod = vm->top_frame()->_module; 7463 - return VAR(MappingProxy(mod)); 7464 - }); 7465 - 7466 - _vm->bind_builtin_func<1>("id", [](VM* vm, ArgsView args) { 7467 - PyObject* obj = args[0]; 7468 - if(is_tagged(obj)) return VAR((i64)0); 7469 - return VAR(BITS(obj)); 7470 - }); 7471 - 7472 - _vm->bind_builtin_func<2>("divmod", [](VM* vm, ArgsView args) { 7473 - i64 lhs = CAST(i64, args[0]); 7474 - i64 rhs = CAST(i64, args[1]); 7475 - if(rhs == 0) vm->ZeroDivisionError(); 7476 - return VAR(Tuple({VAR(lhs/rhs), VAR(lhs%rhs)})); 7477 - }); 7478 - 7479 - _vm->bind_builtin_func<1>("eval", [](VM* vm, ArgsView args) { 7480 - CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<eval>", EVAL_MODE, true); 7481 - FrameId frame = vm->top_frame(); 7482 - return vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals); 7483 - }); 7484 - 7485 - _vm->bind_builtin_func<1>("exec", [](VM* vm, ArgsView args) { 7486 - CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<exec>", EXEC_MODE, true); 7487 - FrameId frame = vm->top_frame(); 7488 - vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals); 7489 - return vm->None; 7490 - }); 7491 - 7492 - _vm->bind_builtin_func<-1>("exit", [](VM* vm, ArgsView args) { 7493 - if(args.size() == 0) std::exit(0); 7494 - else if(args.size() == 1) std::exit(CAST(int, args[0])); 7495 - else vm->TypeError("exit() takes at most 1 argument"); 7496 - return vm->None; 7497 - }); 7498 - 7499 - _vm->bind_builtin_func<1>("repr", CPP_LAMBDA(vm->asRepr(args[0]))); 7500 - _vm->bind_builtin_func<1>("len", [](VM* vm, ArgsView args){ 7501 - return vm->call_method(args[0], __len__); 7502 - }); 7503 - 7504 - _vm->bind_builtin_func<1>("hash", [](VM* vm, ArgsView args){ 7505 - i64 value = vm->hash(args[0]); 7506 - if(((value << 2) >> 2) != value) value >>= 2; 7507 - return VAR(value); 7508 - }); 7509 - 7510 - _vm->bind_builtin_func<1>("chr", [](VM* vm, ArgsView args) { 7511 - i64 i = CAST(i64, args[0]); 7512 - if (i < 0 || i > 128) vm->ValueError("chr() arg not in range(128)"); 7513 - return VAR(std::string(1, (char)i)); 7514 - }); 7515 - 7516 - _vm->bind_builtin_func<1>("ord", [](VM* vm, ArgsView args) { 7517 - const Str& s = CAST(Str&, args[0]); 7518 - if (s.length()!=1) vm->TypeError("ord() expected an ASCII character"); 7519 - return VAR((i64)(s[0])); 7520 - }); 7521 - 7522 - _vm->bind_builtin_func<2>("hasattr", [](VM* vm, ArgsView args) { 7523 - return VAR(vm->getattr(args[0], CAST(Str&, args[1]), false) != nullptr); 7524 - }); 7525 - 7526 - _vm->bind_builtin_func<3>("setattr", [](VM* vm, ArgsView args) { 7527 - vm->setattr(args[0], CAST(Str&, args[1]), args[2]); 7528 - return vm->None; 7529 - }); 7530 - 7531 - _vm->bind_builtin_func<2>("getattr", [](VM* vm, ArgsView args) { 7532 - const Str& name = CAST(Str&, args[1]); 7533 - return vm->getattr(args[0], name); 7534 - }); 7535 - 7536 - _vm->bind_builtin_func<1>("hex", [](VM* vm, ArgsView args) { 7537 - std::stringstream ss; 7538 - ss << std::hex << CAST(i64, args[0]); 7539 - return VAR("0x" + ss.str()); 7540 - }); 7541 - 7542 - _vm->bind_builtin_func<1>("iter", [](VM* vm, ArgsView args) { 7543 - return vm->asIter(args[0]); 7544 - }); 7545 - 7546 - _vm->bind_builtin_func<1>("next", [](VM* vm, ArgsView args) { 7547 - return vm->PyIterNext(args[0]); 7548 - }); 7549 - 7550 - _vm->bind_builtin_func<1>("dir", [](VM* vm, ArgsView args) { 7551 - std::set<StrName> names; 7552 - if(args[0]->is_attr_valid()){ 7553 - std::vector<StrName> keys = args[0]->attr().keys(); 7554 - names.insert(keys.begin(), keys.end()); 7555 - } 7556 - const NameDict& t_attr = vm->_t(args[0])->attr(); 7557 - std::vector<StrName> keys = t_attr.keys(); 7558 - names.insert(keys.begin(), keys.end()); 7559 - List ret; 7560 - for (StrName name : names) ret.push_back(VAR(name.sv())); 7561 - return VAR(std::move(ret)); 7562 - }); 7563 - 7564 - _vm->bind_method<0>("object", "__repr__", [](VM* vm, ArgsView args) { 7565 - PyObject* self = args[0]; 7566 - if(is_tagged(self)) self = nullptr; 7567 - std::stringstream ss; 7568 - ss << "<" << OBJ_NAME(vm->_t(self)) << " object at " << std::hex << self << ">"; 7569 - return VAR(ss.str()); 7570 - }); 7571 - 7572 - _vm->bind_method<1>("object", "__eq__", CPP_LAMBDA(VAR(args[0] == args[1]))); 7573 - _vm->bind_method<1>("object", "__ne__", CPP_LAMBDA(VAR(args[0] != args[1]))); 7574 - 7575 - _vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(vm->_t(args[0]))); 7576 - _vm->bind_static_method<-1>("range", "__new__", [](VM* vm, ArgsView args) { 7577 - Range r; 7578 - switch (args.size()) { 7579 - case 1: r.stop = CAST(i64, args[0]); break; 7580 - case 2: r.start = CAST(i64, args[0]); r.stop = CAST(i64, args[1]); break; 7581 - case 3: r.start = CAST(i64, args[0]); r.stop = CAST(i64, args[1]); r.step = CAST(i64, args[2]); break; 7582 - default: vm->TypeError("expected 1-3 arguments, but got " + std::to_string(args.size())); 7583 - } 7584 - return VAR(r); 7585 - }); 7586 - 7587 - _vm->bind_method<0>("range", "__iter__", CPP_LAMBDA( 7588 - vm->PyIter(RangeIter(vm, args[0])) 7589 - )); 7590 - 7591 - _vm->bind_method<0>("NoneType", "__repr__", CPP_LAMBDA(VAR("None"))); 7592 - _vm->bind_method<0>("NoneType", "__json__", CPP_LAMBDA(VAR("null"))); 7593 - 7594 - _vm->bind_method<1>("int", "__truediv__", [](VM* vm, ArgsView args) { 7595 - f64 rhs = vm->num_to_float(args[1]); 7596 - if (rhs == 0) vm->ZeroDivisionError(); 7597 - return VAR(_CAST(i64, args[0]) / rhs); 7598 - }); 7599 - 7600 - _vm->bind_method<1>("float", "__truediv__", [](VM* vm, ArgsView args) { 7601 - f64 rhs = vm->num_to_float(args[1]); 7602 - if (rhs == 0) vm->ZeroDivisionError(); 7603 - return VAR(_CAST(f64, args[0]) / rhs); 7604 - }); 7605 - 7606 - auto py_number_pow = [](VM* vm, ArgsView args) { 7607 - if(is_both_int(args[0], args[1])){ 7608 - i64 lhs = _CAST(i64, args[0]); 7609 - i64 rhs = _CAST(i64, args[1]); 7610 - bool flag = false; 7611 - if(rhs < 0) {flag = true; rhs = -rhs;} 7612 - i64 ret = 1; 7613 - while(rhs){ 7614 - if(rhs & 1) ret *= lhs; 7615 - lhs *= lhs; 7616 - rhs >>= 1; 7617 - } 7618 - if(flag) return VAR((f64)(1.0 / ret)); 7619 - return VAR(ret); 7620 - }else{ 7621 - return VAR((f64)std::pow(vm->num_to_float(args[0]), vm->num_to_float(args[1]))); 7622 - } 7623 - }; 7624 - 7625 - _vm->bind_method<1>("int", "__pow__", py_number_pow); 7626 - _vm->bind_method<1>("float", "__pow__", py_number_pow); 7627 - 7628 - /************ PyInt ************/ 7629 - _vm->bind_static_method<1>("int", "__new__", [](VM* vm, ArgsView args) { 7630 - if (is_type(args[0], vm->tp_float)) return VAR((i64)CAST(f64, args[0])); 7631 - if (is_type(args[0], vm->tp_int)) return args[0]; 7632 - if (is_type(args[0], vm->tp_bool)) return VAR(_CAST(bool, args[0]) ? 1 : 0); 7633 - if (is_type(args[0], vm->tp_str)) { 7634 - const Str& s = CAST(Str&, args[0]); 7635 - try{ 7636 - size_t parsed = 0; 7637 - i64 val = Number::stoi(s.str(), &parsed, 10); 7638 - if(parsed != s.length()) throw std::invalid_argument("<?>"); 7639 - return VAR(val); 7640 - }catch(std::invalid_argument&){ 7641 - vm->ValueError("invalid literal for int(): " + s.escape()); 7642 - } 7643 - } 7644 - vm->TypeError("int() argument must be a int, float, bool or str"); 7645 - return vm->None; 7646 - }); 7647 - 7648 - _vm->bind_method<1>("int", "__floordiv__", [](VM* vm, ArgsView args) { 7649 - i64 rhs = CAST(i64, args[1]); 7650 - if(rhs == 0) vm->ZeroDivisionError(); 7651 - return VAR(CAST(i64, args[0]) / rhs); 7652 - }); 7653 - 7654 - _vm->bind_method<1>("int", "__mod__", [](VM* vm, ArgsView args) { 7655 - i64 rhs = CAST(i64, args[1]); 7656 - if(rhs == 0) vm->ZeroDivisionError(); 7657 - return VAR(CAST(i64, args[0]) % rhs); 7658 - }); 7659 - 7660 - _vm->bind_method<0>("int", "__repr__", CPP_LAMBDA(VAR(std::to_string(CAST(i64, args[0]))))); 7661 - _vm->bind_method<0>("int", "__json__", CPP_LAMBDA(VAR(std::to_string(CAST(i64, args[0]))))); 7662 - 7663 - #define INT_BITWISE_OP(name,op) \ 7664 - _vm->bind_method<1>("int", #name, CPP_LAMBDA(VAR(CAST(i64, args[0]) op CAST(i64, args[1])))); 7665 - 7666 - INT_BITWISE_OP(__lshift__, <<) 7667 - INT_BITWISE_OP(__rshift__, >>) 7668 - INT_BITWISE_OP(__and__, &) 7669 - INT_BITWISE_OP(__or__, |) 7670 - INT_BITWISE_OP(__xor__, ^) 7671 - 7672 - #undef INT_BITWISE_OP 7673 - 7674 - /************ PyFloat ************/ 7675 - _vm->bind_static_method<1>("float", "__new__", [](VM* vm, ArgsView args) { 7676 - if (is_type(args[0], vm->tp_int)) return VAR((f64)CAST(i64, args[0])); 7677 - if (is_type(args[0], vm->tp_float)) return args[0]; 7678 - if (is_type(args[0], vm->tp_bool)) return VAR(_CAST(bool, args[0]) ? 1.0 : 0.0); 7679 - if (is_type(args[0], vm->tp_str)) { 7680 - const Str& s = CAST(Str&, args[0]); 7681 - if(s == "inf") return VAR(INFINITY); 7682 - if(s == "-inf") return VAR(-INFINITY); 7683 - try{ 7684 - f64 val = Number::stof(s.str()); 7685 - return VAR(val); 7686 - }catch(std::invalid_argument&){ 7687 - vm->ValueError("invalid literal for float(): '" + s + "'"); 7688 - } 7689 - } 7690 - vm->TypeError("float() argument must be a int, float, bool or str"); 7691 - return vm->None; 7692 - }); 7693 - 7694 - _vm->bind_method<0>("float", "__repr__", [](VM* vm, ArgsView args) { 7695 - f64 val = CAST(f64, args[0]); 7696 - if(std::isinf(val) || std::isnan(val)) return VAR(std::to_string(val)); 7697 - std::stringstream ss; 7698 - ss << std::setprecision(std::numeric_limits<f64>::max_digits10-1-2) << val; 7699 - std::string s = ss.str(); 7700 - if(std::all_of(s.begin()+1, s.end(), isdigit)) s += ".0"; 7701 - return VAR(s); 7702 - }); 7703 - 7704 - _vm->bind_method<0>("float", "__json__", [](VM* vm, ArgsView args) { 7705 - f64 val = CAST(f64, args[0]); 7706 - if(std::isinf(val) || std::isnan(val)) vm->ValueError("cannot jsonify 'nan' or 'inf'"); 7707 - return VAR(std::to_string(val)); 7708 - }); 7709 - 7710 - /************ PyString ************/ 7711 - _vm->bind_static_method<1>("str", "__new__", CPP_LAMBDA(vm->asStr(args[0]))); 7712 - 7713 - _vm->bind_method<1>("str", "__add__", [](VM* vm, ArgsView args) { 7714 - const Str& lhs = _CAST(Str&, args[0]); 7715 - const Str& rhs = CAST(Str&, args[1]); 7716 - return VAR(lhs + rhs); 7717 - }); 7718 - 7719 - _vm->bind_method<0>("str", "__len__", [](VM* vm, ArgsView args) { 7720 - const Str& self = _CAST(Str&, args[0]); 7721 - return VAR(self.u8_length()); 7722 - }); 7723 - 7724 - _vm->bind_method<1>("str", "__contains__", [](VM* vm, ArgsView args) { 7725 - const Str& self = _CAST(Str&, args[0]); 7726 - const Str& other = CAST(Str&, args[1]); 7727 - return VAR(self.index(other) != -1); 7728 - }); 7729 - 7730 - _vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0])); 7731 - _vm->bind_method<0>("str", "__iter__", CPP_LAMBDA(vm->PyIter(StringIter(vm, args[0])))); 7732 - 7733 - _vm->bind_method<0>("str", "__repr__", [](VM* vm, ArgsView args) { 7734 - const Str& self = _CAST(Str&, args[0]); 7735 - return VAR(self.escape()); 7736 - }); 7737 - 7738 - _vm->bind_method<0>("str", "__json__", [](VM* vm, ArgsView args) { 7739 - const Str& self = _CAST(Str&, args[0]); 7740 - return VAR(self.escape(false)); 7741 - }); 7742 - 7743 - _vm->bind_method<1>("str", "__eq__", [](VM* vm, ArgsView args) { 7744 - const Str& self = _CAST(Str&, args[0]); 7745 - if(!is_type(args[1], vm->tp_str)) return VAR(false); 7746 - return VAR(self == CAST(Str&, args[1])); 7747 - }); 7748 - 7749 - _vm->bind_method<1>("str", "__ne__", [](VM* vm, ArgsView args) { 7750 - const Str& self = _CAST(Str&, args[0]); 7751 - if(!is_type(args[1], vm->tp_str)) return VAR(true); 7752 - return VAR(self != CAST(Str&, args[1])); 7753 - }); 7754 - 7755 - _vm->bind_method<1>("str", "__getitem__", [](VM* vm, ArgsView args) { 7756 - const Str& self = _CAST(Str&, args[0]); 7757 - 7758 - if(is_type(args[1], vm->tp_slice)){ 7759 - const Slice& s = _CAST(Slice&, args[1]); 7760 - int start, stop, step; 7761 - vm->parse_int_slice(s, self.u8_length(), start, stop, step); 7762 - return VAR(self.u8_slice(start, stop, step)); 7763 - } 7764 - 7765 - int index = CAST(int, args[1]); 7766 - index = vm->normalized_index(index, self.u8_length()); 7767 - return VAR(self.u8_getitem(index)); 7768 - }); 7769 - 7770 - _vm->bind_method<1>("str", "__gt__", [](VM* vm, ArgsView args) { 7771 - const Str& self = _CAST(Str&, args[0]); 7772 - const Str& obj = CAST(Str&, args[1]); 7773 - return VAR(self > obj); 7774 - }); 7775 - 7776 - _vm->bind_method<1>("str", "__lt__", [](VM* vm, ArgsView args) { 7777 - const Str& self = _CAST(Str&, args[0]); 7778 - const Str& obj = CAST(Str&, args[1]); 7779 - return VAR(self < obj); 7780 - }); 7781 - 7782 - _vm->bind_method<-1>("str", "replace", [](VM* vm, ArgsView args) { 7783 - if(args.size() != 1+2 && args.size() != 1+3) vm->TypeError("replace() takes 2 or 3 arguments"); 7784 - const Str& self = _CAST(Str&, args[0]); 7785 - const Str& old = CAST(Str&, args[1]); 7786 - const Str& new_ = CAST(Str&, args[2]); 7787 - int count = args.size()==1+3 ? CAST(int, args[3]) : -1; 7788 - return VAR(self.replace(old, new_, count)); 7789 - }); 7790 - 7791 - _vm->bind_method<1>("str", "index", [](VM* vm, ArgsView args) { 7792 - const Str& self = _CAST(Str&, args[0]); 7793 - const Str& sub = CAST(Str&, args[1]); 7794 - int index = self.index(sub); 7795 - if(index == -1) vm->ValueError("substring not found"); 7796 - return VAR(index); 7797 - }); 7798 - 7799 - _vm->bind_method<1>("str", "startswith", [](VM* vm, ArgsView args) { 7800 - const Str& self = _CAST(Str&, args[0]); 7801 - const Str& prefix = CAST(Str&, args[1]); 7802 - return VAR(self.index(prefix) == 0); 7803 - }); 7804 - 7805 - _vm->bind_method<1>("str", "endswith", [](VM* vm, ArgsView args) { 7806 - const Str& self = _CAST(Str&, args[0]); 7807 - const Str& suffix = CAST(Str&, args[1]); 7808 - int offset = self.length() - suffix.length(); 7809 - if(offset < 0) return vm->False; 7810 - bool ok = memcmp(self.data+offset, suffix.data, suffix.length()) == 0; 7811 - return VAR(ok); 7812 - }); 7813 - 7814 - _vm->bind_method<0>("str", "encode", [](VM* vm, ArgsView args) { 7815 - const Str& self = _CAST(Str&, args[0]); 7816 - std::vector<char> buffer(self.length()); 7817 - memcpy(buffer.data(), self.data, self.length()); 7818 - return VAR(Bytes(std::move(buffer))); 7819 - }); 7820 - 7821 - _vm->bind_method<1>("str", "join", [](VM* vm, ArgsView args) { 7822 - const Str& self = _CAST(Str&, args[0]); 7823 - FastStrStream ss; 7824 - PyObject* obj = vm->asList(args[1]); 7825 - const List& list = CAST(List&, obj); 7826 - for (int i = 0; i < list.size(); ++i) { 7827 - if (i > 0) ss << self; 7828 - ss << CAST(Str&, list[i]); 7829 - } 7830 - return VAR(ss.str()); 7831 - }); 7832 - 7833 - /************ PyList ************/ 7834 - _vm->bind_method<1>("list", "append", [](VM* vm, ArgsView args) { 7835 - List& self = _CAST(List&, args[0]); 7836 - self.push_back(args[1]); 7837 - return vm->None; 7838 - }); 7839 - 7840 - _vm->bind_method<1>("list", "extend", [](VM* vm, ArgsView args) { 7841 - List& self = _CAST(List&, args[0]); 7842 - PyObject* obj = vm->asList(args[1]); 7843 - const List& list = CAST(List&, obj); 7844 - self.extend(list); 7845 - return vm->None; 7846 - }); 7847 - 7848 - _vm->bind_method<0>("list", "reverse", [](VM* vm, ArgsView args) { 7849 - List& self = _CAST(List&, args[0]); 7850 - std::reverse(self.begin(), self.end()); 7851 - return vm->None; 7852 - }); 7853 - 7854 - _vm->bind_method<1>("list", "__mul__", [](VM* vm, ArgsView args) { 7855 - const List& self = _CAST(List&, args[0]); 7856 - int n = CAST(int, args[1]); 7857 - List result; 7858 - result.reserve(self.size() * n); 7859 - for(int i = 0; i < n; i++) result.extend(self); 7860 - return VAR(std::move(result)); 7861 - }); 7862 - 7863 - _vm->bind_method<2>("list", "insert", [](VM* vm, ArgsView args) { 7864 - List& self = _CAST(List&, args[0]); 7865 - int index = CAST(int, args[1]); 7866 - if(index < 0) index += self.size(); 7867 - if(index < 0) index = 0; 7868 - if(index > self.size()) index = self.size(); 7869 - self.insert(index, args[2]); 7870 - return vm->None; 7871 - }); 7872 - 7873 - _vm->bind_method<0>("list", "clear", [](VM* vm, ArgsView args) { 7874 - _CAST(List&, args[0]).clear(); 7875 - return vm->None; 7876 - }); 7877 - 7878 - _vm->bind_method<0>("list", "copy", CPP_LAMBDA(VAR(_CAST(List, args[0])))); 7879 - 7880 - _vm->bind_method<1>("list", "__add__", [](VM* vm, ArgsView args) { 7881 - const List& self = _CAST(List&, args[0]); 7882 - const List& other = CAST(List&, args[1]); 7883 - List new_list(self); // copy construct 7884 - new_list.extend(other); 7885 - return VAR(std::move(new_list)); 7886 - }); 7887 - 7888 - _vm->bind_method<0>("list", "__len__", [](VM* vm, ArgsView args) { 7889 - const List& self = _CAST(List&, args[0]); 7890 - return VAR(self.size()); 7891 - }); 7892 - 7893 - _vm->bind_method<0>("list", "__iter__", [](VM* vm, ArgsView args) { 7894 - return vm->PyIter(ArrayIter<List>(vm, args[0])); 7895 - }); 7896 - 7897 - _vm->bind_method<1>("list", "__getitem__", [](VM* vm, ArgsView args) { 7898 - const List& self = _CAST(List&, args[0]); 7899 - 7900 - if(is_type(args[1], vm->tp_slice)){ 7901 - const Slice& s = _CAST(Slice&, args[1]); 7902 - int start, stop, step; 7903 - vm->parse_int_slice(s, self.size(), start, stop, step); 7904 - List new_list; 7905 - for(int i=start; step>0?i<stop:i>stop; i+=step) new_list.push_back(self[i]); 7906 - return VAR(std::move(new_list)); 7907 - } 7908 - 7909 - int index = CAST(int, args[1]); 7910 - index = vm->normalized_index(index, self.size()); 7911 - return self[index]; 7912 - }); 7913 - 7914 - _vm->bind_method<2>("list", "__setitem__", [](VM* vm, ArgsView args) { 7915 - List& self = _CAST(List&, args[0]); 7916 - int index = CAST(int, args[1]); 7917 - index = vm->normalized_index(index, self.size()); 7918 - self[index] = args[2]; 7919 - return vm->None; 7920 - }); 7921 - 7922 - _vm->bind_method<1>("list", "__delitem__", [](VM* vm, ArgsView args) { 7923 - List& self = _CAST(List&, args[0]); 7924 - int index = CAST(int, args[1]); 7925 - index = vm->normalized_index(index, self.size()); 7926 - self.erase(index); 7927 - return vm->None; 7928 - }); 7929 - 7930 - /************ PyTuple ************/ 7931 - _vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, ArgsView args) { 7932 - List list = CAST(List, vm->asList(args[0])); 7933 - return VAR(Tuple(std::move(list))); 7934 - }); 7935 - 7936 - _vm->bind_method<0>("tuple", "__iter__", [](VM* vm, ArgsView args) { 7937 - return vm->PyIter(ArrayIter<Tuple>(vm, args[0])); 7938 - }); 7939 - 7940 - _vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, ArgsView args) { 7941 - const Tuple& self = _CAST(Tuple&, args[0]); 7942 - 7943 - if(is_type(args[1], vm->tp_slice)){ 7944 - const Slice& s = _CAST(Slice&, args[1]); 7945 - int start, stop, step; 7946 - vm->parse_int_slice(s, self.size(), start, stop, step); 7947 - List new_list; 7948 - for(int i=start; step>0?i<stop:i>stop; i+=step) new_list.push_back(self[i]); 7949 - return VAR(Tuple(std::move(new_list))); 7950 - } 7951 - 7952 - int index = CAST(int, args[1]); 7953 - index = vm->normalized_index(index, self.size()); 7954 - return self[index]; 7955 - }); 7956 - 7957 - _vm->bind_method<0>("tuple", "__len__", [](VM* vm, ArgsView args) { 7958 - const Tuple& self = _CAST(Tuple&, args[0]); 7959 - return VAR(self.size()); 7960 - }); 7961 - 7962 - /************ bool ************/ 7963 - _vm->bind_static_method<1>("bool", "__new__", CPP_LAMBDA(VAR(vm->asBool(args[0])))); 7964 - 7965 - _vm->bind_method<0>("bool", "__repr__", [](VM* vm, ArgsView args) { 7966 - bool val = _CAST(bool, args[0]); 7967 - return VAR(val ? "True" : "False"); 7968 - }); 7969 - 7970 - _vm->bind_method<0>("bool", "__json__", [](VM* vm, ArgsView args) { 7971 - bool val = _CAST(bool, args[0]); 7972 - return VAR(val ? "true" : "false"); 7973 - }); 7974 - 7975 - _vm->bind_method<1>("bool", "__xor__", [](VM* vm, ArgsView args) { 7976 - bool self = _CAST(bool, args[0]); 7977 - bool other = CAST(bool, args[1]); 7978 - return VAR(self ^ other); 7979 - }); 7980 - 7981 - _vm->bind_method<0>("ellipsis", "__repr__", CPP_LAMBDA(VAR("Ellipsis"))); 7982 - 7983 - /************ bytes ************/ 7984 - _vm->bind_static_method<1>("bytes", "__new__", [](VM* vm, ArgsView args){ 7985 - List& list = CAST(List&, args[0]); 7986 - std::vector<char> buffer(list.size()); 7987 - for(int i=0; i<list.size(); i++){ 7988 - i64 b = CAST(i64, list[i]); 7989 - if(b<0 || b>255) vm->ValueError("byte must be in range[0, 256)"); 7990 - buffer[i] = (char)b; 7991 - } 7992 - return VAR(Bytes(std::move(buffer))); 7993 - }); 7994 - 7995 - _vm->bind_method<1>("bytes", "__getitem__", [](VM* vm, ArgsView args) { 7996 - const Bytes& self = _CAST(Bytes&, args[0]); 7997 - int index = CAST(int, args[1]); 7998 - index = vm->normalized_index(index, self.size()); 7999 - return VAR(self[index]); 8000 - }); 8001 - 8002 - _vm->bind_method<0>("bytes", "__repr__", [](VM* vm, ArgsView args) { 8003 - const Bytes& self = _CAST(Bytes&, args[0]); 8004 - std::stringstream ss; 8005 - ss << "b'"; 8006 - for(int i=0; i<self.size(); i++){ 8007 - ss << "\\x" << std::hex << std::setw(2) << std::setfill('0') << self[i]; 8008 - } 8009 - ss << "'"; 8010 - return VAR(ss.str()); 8011 - }); 8012 - 8013 - _vm->bind_method<0>("bytes", "__len__", [](VM* vm, ArgsView args) { 8014 - const Bytes& self = _CAST(Bytes&, args[0]); 8015 - return VAR(self.size()); 8016 - }); 8017 - 8018 - _vm->bind_method<0>("bytes", "decode", [](VM* vm, ArgsView args) { 8019 - const Bytes& self = _CAST(Bytes&, args[0]); 8020 - // TODO: check encoding is utf-8 8021 - return VAR(Str(self.str())); 8022 - }); 8023 - 8024 - _vm->bind_method<1>("bytes", "__eq__", [](VM* vm, ArgsView args) { 8025 - const Bytes& self = _CAST(Bytes&, args[0]); 8026 - if(!is_type(args[1], vm->tp_bytes)) return VAR(false); 8027 - const Bytes& other = CAST(Bytes&, args[1]); 8028 - return VAR(self == other); 8029 - }); 8030 - 8031 - _vm->bind_method<1>("bytes", "__ne__", [](VM* vm, ArgsView args) { 8032 - const Bytes& self = _CAST(Bytes&, args[0]); 8033 - if(!is_type(args[1], vm->tp_bytes)) return VAR(true); 8034 - const Bytes& other = CAST(Bytes&, args[1]); 8035 - return VAR(self != other); 8036 - }); 8037 - 8038 - /************ slice ************/ 8039 - _vm->bind_static_method<3>("slice", "__new__", [](VM* vm, ArgsView args) { 8040 - return VAR(Slice(args[0], args[1], args[2])); 8041 - }); 8042 - 8043 - _vm->bind_method<0>("slice", "__repr__", [](VM* vm, ArgsView args) { 8044 - const Slice& self = _CAST(Slice&, args[0]); 8045 - std::stringstream ss; 8046 - ss << "slice("; 8047 - ss << CAST(Str, vm->asRepr(self.start)) << ", "; 8048 - ss << CAST(Str, vm->asRepr(self.stop)) << ", "; 8049 - ss << CAST(Str, vm->asRepr(self.step)) << ")"; 8050 - return VAR(ss.str()); 8051 - }); 8052 - 8053 - /************ MappingProxy ************/ 8054 - _vm->bind_method<0>("mappingproxy", "keys", [](VM* vm, ArgsView args) { 8055 - MappingProxy& self = _CAST(MappingProxy&, args[0]); 8056 - List keys; 8057 - for(StrName name : self.attr().keys()) keys.push_back(VAR(name.sv())); 8058 - return VAR(std::move(keys)); 8059 - }); 8060 - 8061 - _vm->bind_method<0>("mappingproxy", "values", [](VM* vm, ArgsView args) { 8062 - MappingProxy& self = _CAST(MappingProxy&, args[0]); 8063 - List values; 8064 - for(auto& item : self.attr().items()) values.push_back(item.second); 8065 - return VAR(std::move(values)); 8066 - }); 8067 - 8068 - _vm->bind_method<0>("mappingproxy", "items", [](VM* vm, ArgsView args) { 8069 - MappingProxy& self = _CAST(MappingProxy&, args[0]); 8070 - List items; 8071 - for(auto& item : self.attr().items()){ 8072 - PyObject* t = VAR(Tuple({VAR(item.first.sv()), item.second})); 8073 - items.push_back(std::move(t)); 8074 - } 8075 - return VAR(std::move(items)); 8076 - }); 8077 - 8078 - _vm->bind_method<0>("mappingproxy", "__len__", [](VM* vm, ArgsView args) { 8079 - MappingProxy& self = _CAST(MappingProxy&, args[0]); 8080 - return VAR(self.attr().size()); 8081 - }); 8082 - 8083 - _vm->bind_method<1>("mappingproxy", "__getitem__", [](VM* vm, ArgsView args) { 8084 - MappingProxy& self = _CAST(MappingProxy&, args[0]); 8085 - StrName key = CAST(Str&, args[1]); 8086 - PyObject* ret = self.attr().try_get(key); 8087 - if(ret == nullptr) vm->AttributeError(key.sv()); 8088 - return ret; 8089 - }); 8090 - 8091 - _vm->bind_method<0>("mappingproxy", "__repr__", [](VM* vm, ArgsView args) { 8092 - MappingProxy& self = _CAST(MappingProxy&, args[0]); 8093 - std::stringstream ss; 8094 - ss << "mappingproxy({"; 8095 - bool first = true; 8096 - for(auto& item : self.attr().items()){ 8097 - if(!first) ss << ", "; 8098 - first = false; 8099 - ss << item.first.escape() << ": " << CAST(Str, vm->asRepr(item.second)); 8100 - } 8101 - ss << "})"; 8102 - return VAR(ss.str()); 8103 - }); 8104 - 8105 - _vm->bind_method<1>("mappingproxy", "__contains__", [](VM* vm, ArgsView args) { 8106 - MappingProxy& self = _CAST(MappingProxy&, args[0]); 8107 - StrName key = CAST(Str&, args[1]); 8108 - return VAR(self.attr().contains(key)); 8109 - }); 8110 - } 8111 - 8112 - #ifdef _WIN32 8113 - #define __EXPORT __declspec(dllexport) inline 8114 - #elif __APPLE__ 8115 - #define __EXPORT __attribute__((visibility("default"))) __attribute__((used)) inline 8116 - #elif __EMSCRIPTEN__ 8117 - #include <emscripten.h> 8118 - #define __EXPORT EMSCRIPTEN_KEEPALIVE inline 8119 - #else 8120 - #define __EXPORT inline 8121 - #endif 8122 - 8123 - inline void add_module_time(VM* vm){ 8124 - PyObject* mod = vm->new_module("time"); 8125 - vm->bind_func<0>(mod, "time", [](VM* vm, ArgsView args) { 8126 - auto now = std::chrono::high_resolution_clock::now(); 8127 - return VAR(std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count() / 1000000.0); 8128 - }); 8129 - } 8130 - 8131 - inline void add_module_sys(VM* vm){ 8132 - PyObject* mod = vm->new_module("sys"); 8133 - vm->setattr(mod, "version", VAR(PK_VERSION)); 8134 - 8135 - PyObject* stdout_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {}); 8136 - PyObject* stderr_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {}); 8137 - vm->setattr(mod, "stdout", stdout_); 8138 - vm->setattr(mod, "stderr", stderr_); 8139 - 8140 - vm->bind_func<1>(stdout_, "write", [](VM* vm, ArgsView args) { 8141 - vm->_stdout(vm, CAST(Str&, args[0])); 8142 - return vm->None; 8143 - }); 8144 - 8145 - vm->bind_func<1>(stderr_, "write", [](VM* vm, ArgsView args) { 8146 - vm->_stderr(vm, CAST(Str&, args[0])); 8147 - return vm->None; 8148 - }); 8149 - } 8150 - 8151 - inline void add_module_json(VM* vm){ 8152 - PyObject* mod = vm->new_module("json"); 8153 - vm->bind_func<1>(mod, "loads", [](VM* vm, ArgsView args) { 8154 - const Str& expr = CAST(Str&, args[0]); 8155 - CodeObject_ code = vm->compile(expr, "<json>", JSON_MODE); 8156 - return vm->_exec(code, vm->top_frame()->_module); 8157 - }); 8158 - 8159 - vm->bind_func<1>(mod, "dumps", CPP_LAMBDA(vm->call_method(args[0], __json__))); 8160 - } 8161 - 8162 - inline void add_module_math(VM* vm){ 8163 - PyObject* mod = vm->new_module("math"); 8164 - mod->attr().set("pi", VAR(3.1415926535897932384)); 8165 - mod->attr().set("e" , VAR(2.7182818284590452354)); 8166 - 8167 - vm->bind_func<1>(mod, "log", CPP_LAMBDA(VAR(std::log(vm->num_to_float(args[0]))))); 8168 - vm->bind_func<1>(mod, "log10", CPP_LAMBDA(VAR(std::log10(vm->num_to_float(args[0]))))); 8169 - vm->bind_func<1>(mod, "log2", CPP_LAMBDA(VAR(std::log2(vm->num_to_float(args[0]))))); 8170 - vm->bind_func<1>(mod, "sin", CPP_LAMBDA(VAR(std::sin(vm->num_to_float(args[0]))))); 8171 - vm->bind_func<1>(mod, "cos", CPP_LAMBDA(VAR(std::cos(vm->num_to_float(args[0]))))); 8172 - vm->bind_func<1>(mod, "tan", CPP_LAMBDA(VAR(std::tan(vm->num_to_float(args[0]))))); 8173 - vm->bind_func<1>(mod, "isnan", CPP_LAMBDA(VAR(std::isnan(vm->num_to_float(args[0]))))); 8174 - vm->bind_func<1>(mod, "isinf", CPP_LAMBDA(VAR(std::isinf(vm->num_to_float(args[0]))))); 8175 - vm->bind_func<1>(mod, "fabs", CPP_LAMBDA(VAR(std::fabs(vm->num_to_float(args[0]))))); 8176 - vm->bind_func<1>(mod, "floor", CPP_LAMBDA(VAR((i64)std::floor(vm->num_to_float(args[0]))))); 8177 - vm->bind_func<1>(mod, "ceil", CPP_LAMBDA(VAR((i64)std::ceil(vm->num_to_float(args[0]))))); 8178 - vm->bind_func<1>(mod, "sqrt", CPP_LAMBDA(VAR(std::sqrt(vm->num_to_float(args[0]))))); 8179 - vm->bind_func<2>(mod, "gcd", [](VM* vm, ArgsView args) { 8180 - i64 a = CAST(i64, args[0]); 8181 - i64 b = CAST(i64, args[1]); 8182 - if(a < 0) a = -a; 8183 - if(b < 0) b = -b; 8184 - while(b != 0){ 8185 - i64 t = b; 8186 - b = a % b; 8187 - a = t; 8188 - } 8189 - return VAR(a); 8190 - }); 8191 - } 8192 - 8193 - inline void add_module_dis(VM* vm){ 8194 - PyObject* mod = vm->new_module("dis"); 8195 - vm->bind_func<1>(mod, "dis", [](VM* vm, ArgsView args) { 8196 - PyObject* f = args[0]; 8197 - if(is_type(f, vm->tp_bound_method)) f = CAST(BoundMethod, args[0]).func; 8198 - CodeObject_ code = CAST(Function&, f).decl->code; 8199 - vm->_stdout(vm, vm->disassemble(code)); 8200 - return vm->None; 8201 - }); 8202 - } 8203 - 8204 - struct ReMatch { 8205 - PY_CLASS(ReMatch, re, Match) 8206 - 8207 - i64 start; 8208 - i64 end; 8209 - std::cmatch m; 8210 - ReMatch(i64 start, i64 end, std::cmatch m) : start(start), end(end), m(m) {} 8211 - 8212 - static void _register(VM* vm, PyObject* mod, PyObject* type){ 8213 - vm->bind_method<-1>(type, "__init__", CPP_NOT_IMPLEMENTED()); 8214 - vm->bind_method<0>(type, "start", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).start))); 8215 - vm->bind_method<0>(type, "end", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).end))); 8216 - 8217 - vm->bind_method<0>(type, "span", [](VM* vm, ArgsView args) { 8218 - auto& self = _CAST(ReMatch&, args[0]); 8219 - return VAR(Tuple({VAR(self.start), VAR(self.end)})); 8220 - }); 8221 - 8222 - vm->bind_method<1>(type, "group", [](VM* vm, ArgsView args) { 8223 - auto& self = _CAST(ReMatch&, args[0]); 8224 - int index = CAST(int, args[1]); 8225 - index = vm->normalized_index(index, self.m.size()); 8226 - return VAR(self.m[index].str()); 8227 - }); 8228 - } 8229 - }; 8230 - 8231 - inline PyObject* _regex_search(const Str& pattern, const Str& string, bool from_start, VM* vm){ 8232 - std::regex re(pattern.begin(), pattern.end()); 8233 - std::cmatch m; 8234 - if(std::regex_search(string.begin(), string.end(), m, re)){ 8235 - if(from_start && m.position() != 0) return vm->None; 8236 - i64 start = string._byte_index_to_unicode(m.position()); 8237 - i64 end = string._byte_index_to_unicode(m.position() + m.length()); 8238 - return VAR_T(ReMatch, start, end, m); 8239 - } 8240 - return vm->None; 8241 - }; 8242 - 8243 - inline void add_module_re(VM* vm){ 8244 - PyObject* mod = vm->new_module("re"); 8245 - ReMatch::register_class(vm, mod); 8246 - 8247 - vm->bind_func<2>(mod, "match", [](VM* vm, ArgsView args) { 8248 - const Str& pattern = CAST(Str&, args[0]); 8249 - const Str& string = CAST(Str&, args[1]); 8250 - return _regex_search(pattern, string, true, vm); 8251 - }); 8252 - 8253 - vm->bind_func<2>(mod, "search", [](VM* vm, ArgsView args) { 8254 - const Str& pattern = CAST(Str&, args[0]); 8255 - const Str& string = CAST(Str&, args[1]); 8256 - return _regex_search(pattern, string, false, vm); 8257 - }); 8258 - 8259 - vm->bind_func<3>(mod, "sub", [](VM* vm, ArgsView args) { 8260 - const Str& pattern = CAST(Str&, args[0]); 8261 - const Str& repl = CAST(Str&, args[1]); 8262 - const Str& string = CAST(Str&, args[2]); 8263 - std::regex re(pattern.begin(), pattern.end()); 8264 - return VAR(std::regex_replace(string.str(), re, repl.str())); 8265 - }); 8266 - 8267 - vm->bind_func<2>(mod, "split", [](VM* vm, ArgsView args) { 8268 - const Str& pattern = CAST(Str&, args[0]); 8269 - const Str& string = CAST(Str&, args[1]); 8270 - std::regex re(pattern.begin(), pattern.end()); 8271 - std::cregex_token_iterator it(string.begin(), string.end(), re, -1); 8272 - std::cregex_token_iterator end; 8273 - List vec; 8274 - for(; it != end; ++it){ 8275 - vec.push_back(VAR(it->str())); 8276 - } 8277 - return VAR(vec); 8278 - }); 8279 - } 8280 - 8281 - struct Random{ 8282 - PY_CLASS(Random, random, Random) 8283 - std::mt19937 gen; 8284 - 8285 - Random(){ 8286 - gen.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count()); 8287 - } 8288 - 8289 - static void _register(VM* vm, PyObject* mod, PyObject* type){ 8290 - vm->bind_static_method<0>(type, "__new__", CPP_LAMBDA(VAR_T(Random))); 8291 - 8292 - vm->bind_method<1>(type, "seed", [](VM* vm, ArgsView args) { 8293 - Random& self = _CAST(Random&, args[0]); 8294 - self.gen.seed(CAST(i64, args[1])); 8295 - return vm->None; 8296 - }); 8297 - 8298 - vm->bind_method<2>(type, "randint", [](VM* vm, ArgsView args) { 8299 - Random& self = _CAST(Random&, args[0]); 8300 - i64 a = CAST(i64, args[1]); 8301 - i64 b = CAST(i64, args[2]); 8302 - std::uniform_int_distribution<i64> dis(a, b); 8303 - return VAR(dis(self.gen)); 8304 - }); 8305 - 8306 - vm->bind_method<0>(type, "random", [](VM* vm, ArgsView args) { 8307 - Random& self = _CAST(Random&, args[0]); 8308 - std::uniform_real_distribution<f64> dis(0.0, 1.0); 8309 - return VAR(dis(self.gen)); 8310 - }); 8311 - 8312 - vm->bind_method<2>(type, "uniform", [](VM* vm, ArgsView args) { 8313 - Random& self = _CAST(Random&, args[0]); 8314 - f64 a = CAST(f64, args[1]); 8315 - f64 b = CAST(f64, args[2]); 8316 - std::uniform_real_distribution<f64> dis(a, b); 8317 - return VAR(dis(self.gen)); 8318 - }); 8319 - } 8320 - }; 8321 - 8322 - inline void add_module_random(VM* vm){ 8323 - PyObject* mod = vm->new_module("random"); 8324 - Random::register_class(vm, mod); 8325 - CodeObject_ code = vm->compile(kPythonLibs["random"], "random.py", EXEC_MODE); 8326 - vm->_exec(code, mod); 8327 - } 8328 - 8329 - inline void add_module_gc(VM* vm){ 8330 - PyObject* mod = vm->new_module("gc"); 8331 - vm->bind_func<0>(mod, "collect", CPP_LAMBDA(VAR(vm->heap.collect()))); 8332 - } 8333 - 8334 - inline void VM::post_init(){ 8335 - init_builtins(this); 8336 - #if !DEBUG_NO_BUILTIN_MODULES 8337 - add_module_sys(this); 8338 - add_module_time(this); 8339 - add_module_json(this); 8340 - add_module_math(this); 8341 - add_module_re(this); 8342 - add_module_dis(this); 8343 - add_module_c(this); 8344 - add_module_gc(this); 8345 - add_module_random(this); 8346 - add_module_base64(this); 8347 - 8348 - for(const char* name: {"this", "functools", "collections", "heapq", "bisect"}){ 8349 - _lazy_modules[name] = kPythonLibs[name]; 8350 - } 8351 - 8352 - CodeObject_ code = compile(kPythonLibs["builtins"], "<builtins>", EXEC_MODE); 8353 - this->_exec(code, this->builtins); 8354 - code = compile(kPythonLibs["_dict"], "<dict>", EXEC_MODE); 8355 - this->_exec(code, this->builtins); 8356 - code = compile(kPythonLibs["_set"], "<set>", EXEC_MODE); 8357 - this->_exec(code, this->builtins); 8358 - 8359 - // property is defined in builtins.py so we need to add it after builtins is loaded 8360 - _t(tp_object)->attr().set(__class__, property(CPP_LAMBDA(vm->_t(args[0])))); 8361 - _t(tp_type)->attr().set(__base__, property([](VM* vm, ArgsView args){ 8362 - const PyTypeInfo& info = vm->_all_types[OBJ_GET(Type, args[0])]; 8363 - return info.base.index == -1 ? vm->None : vm->_all_types[info.base].obj; 8364 - })); 8365 - _t(tp_type)->attr().set(__name__, property([](VM* vm, ArgsView args){ 8366 - const PyTypeInfo& info = vm->_all_types[OBJ_GET(Type, args[0])]; 8367 - return VAR(info.name); 8368 - })); 8369 - 8370 - _t(tp_bound_method)->attr().set("__self__", property([](VM* vm, ArgsView args){ 8371 - return CAST(BoundMethod&, args[0]).self; 8372 - })); 8373 - _t(tp_bound_method)->attr().set("__func__", property([](VM* vm, ArgsView args){ 8374 - return CAST(BoundMethod&, args[0]).func; 8375 - })); 8376 - 8377 - vm->bind_method<1>(_t(tp_bound_method), "__eq__", [](VM* vm, ArgsView args){ 8378 - if(!is_non_tagged_type(args[1], vm->tp_bound_method)) return vm->False; 8379 - bool ok = _CAST(BoundMethod&, args[0]) == _CAST(BoundMethod&, args[1]); 8380 - return VAR(ok); 8381 - }); 8382 - 8383 - vm->bind_method<1>(_t(tp_bound_method), "__ne__", [](VM* vm, ArgsView args){ 8384 - if(!is_non_tagged_type(args[1], vm->tp_bound_method)) return vm->True; 8385 - bool ok = _CAST(BoundMethod&, args[0]) != _CAST(BoundMethod&, args[1]); 8386 - return VAR(ok); 8387 - }); 8388 - 8389 - _t(tp_slice)->attr().set("start", property([](VM* vm, ArgsView args){ 8390 - return CAST(Slice&, args[0]).start; 8391 - })); 8392 - _t(tp_slice)->attr().set("stop", property([](VM* vm, ArgsView args){ 8393 - return CAST(Slice&, args[0]).stop; 8394 - })); 8395 - _t(tp_slice)->attr().set("step", property([](VM* vm, ArgsView args){ 8396 - return CAST(Slice&, args[0]).step; 8397 - })); 8398 - _t(tp_object)->attr().set("__dict__", property([](VM* vm, ArgsView args){ 8399 - if(is_tagged(args[0]) || !args[0]->is_attr_valid()){ 8400 - vm->AttributeError("__dict__"); 8401 - } 8402 - return VAR(MappingProxy(args[0])); 8403 - })); 8404 - 8405 - if(enable_os){ 8406 - add_module_io(this); 8407 - add_module_os(this); 8408 - add_module_requests(this); 8409 - } 8410 - #endif 8411 - } 8412 - 8413 - } // namespace pkpy 8414 - 8415 - /*************************GLOBAL NAMESPACE*************************/ 8416 - static std::map<void*, void(*)(void*)> _pk_deleter_map; 8417 - 8418 - extern "C" { 8419 - __EXPORT 8420 - void pkpy_delete(void* p){ 8421 - auto it = _pk_deleter_map.find(p); 8422 - if(it != _pk_deleter_map.end()){ 8423 - it->second(p); 8424 - }else{ 8425 - free(p); 8426 - } 8427 - } 8428 - 8429 - __EXPORT 8430 - void pkpy_vm_exec(pkpy::VM* vm, const char* source){ 8431 - vm->exec(source, "main.py", pkpy::EXEC_MODE); 8432 - } 8433 - 8434 - __EXPORT 8435 - char* pkpy_vm_get_global(pkpy::VM* vm, const char* name){ 8436 - pkpy::PyObject* val = vm->_main->attr().try_get(name); 8437 - if(val == nullptr) return nullptr; 8438 - try{ 8439 - pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->asRepr(val)); 8440 - return repr.c_str_dup(); 8441 - }catch(...){ 8442 - return nullptr; 8443 - } 8444 - } 8445 - 8446 - __EXPORT 8447 - char* pkpy_vm_eval(pkpy::VM* vm, const char* source){ 8448 - pkpy::PyObject* ret = vm->exec(source, "<eval>", pkpy::EVAL_MODE); 8449 - if(ret == nullptr) return nullptr; 8450 - try{ 8451 - pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->asRepr(ret)); 8452 - return repr.c_str_dup(); 8453 - }catch(...){ 8454 - return nullptr; 8455 - } 8456 - } 8457 - 8458 - __EXPORT 8459 - pkpy::REPL* pkpy_new_repl(pkpy::VM* vm){ 8460 - pkpy::REPL* p = new pkpy::REPL(vm); 8461 - _pk_deleter_map[p] = [](void* p){ delete (pkpy::REPL*)p; }; 8462 - return p; 8463 - } 8464 - 8465 - __EXPORT 8466 - bool pkpy_repl_input(pkpy::REPL* r, const char* line){ 8467 - return r->input(line); 8468 - } 8469 - 8470 - __EXPORT 8471 - void pkpy_vm_add_module(pkpy::VM* vm, const char* name, const char* source){ 8472 - vm->_lazy_modules[name] = source; 8473 - } 8474 - 8475 - __EXPORT 8476 - pkpy::VM* pkpy_new_vm(bool enable_os=true){ 8477 - pkpy::VM* p = new pkpy::VM(enable_os); 8478 - _pk_deleter_map[p] = [](void* p){ delete (pkpy::VM*)p; }; 8479 - return p; 8480 - } 8481 - } 8482 - 8483 - #endif // POCKETPY_H
-578
vendor/pocketpy/pocketpy_c.cpp
··· 1 - #include "pocketpy.h" 2 - #include "pocketpy_c.h" 3 - 4 - using namespace pkpy; 5 - 6 - #define PKPY_STACK_SIZE 32 7 - 8 - #define SAFEGUARD_OPEN try { \ 9 - 10 - #define SAFEGUARD_CLOSE \ 11 - } catch(std::exception& e) { \ 12 - std::cerr << "ERROR: a std::exception " \ 13 - << "this probably means pocketpy itself has a bug!\n" \ 14 - << e.what() << "\n"; \ 15 - exit(2); \ 16 - } catch(...) { \ 17 - std::cerr << "ERROR: a unknown exception was thrown from " << __func__ \ 18 - << "\nthis probably means pocketpy itself has a bug!\n"; \ 19 - exit(2); \ 20 - } 21 - 22 - 23 - #define ERRHANDLER_OPEN SAFEGUARD_OPEN \ 24 - try { \ 25 - if (vm->c_data->size() > 0 && vm->c_data->top() == nullptr) \ 26 - return false; \ 27 - 28 - #define ERRHANDLER_CLOSE \ 29 - } catch( Exception e ) { \ 30 - vm->c_data->push(py_var(vm, e)); \ 31 - vm->c_data->push(NULL); \ 32 - return false; \ 33 - } \ 34 - SAFEGUARD_CLOSE \ 35 - 36 - 37 - 38 - class CVM : public VM { 39 - public : 40 - 41 - ValueStackImpl<PKPY_STACK_SIZE>* c_data; 42 - CVM(bool enable_os=true) : VM(enable_os) { 43 - c_data = new ValueStackImpl<PKPY_STACK_SIZE>(); 44 - } 45 - 46 - ~CVM() { 47 - c_data->clear(); 48 - delete c_data; 49 - } 50 - }; 51 - 52 - 53 - //for now I will unpack a tuple automatically, we may not want to handle 54 - //it this way, not sure 55 - //it is more lua like, but maybe not python like 56 - static void unpack_return(CVM* vm, PyObject* ret) { 57 - if (is_type(ret, vm->tp_tuple)) { 58 - Tuple& t = py_cast<Tuple&>(vm, ret); 59 - for (int i = 0; i < t.size(); i++) 60 - vm->c_data->push(t[i]); 61 - } else if (ret == vm->None) { 62 - //do nothing here 63 - //having to pop the stack after every call that returns none is annoying 64 - //lua does not do this 65 - // 66 - //so for now we will not push none on the stack when it is the sole thing returned 67 - //if this becomes a problem we can change it 68 - // 69 - //you can still check if it returned none by comparing stack size before 70 - //and after if you have to 71 - } else 72 - vm->c_data->push(ret); 73 - 74 - } 75 - 76 - 77 - bool pkpy_clear_error(pkpy_vm* vm_handle, char** message) { 78 - CVM* vm = (CVM*) vm_handle; 79 - SAFEGUARD_OPEN 80 - 81 - if (vm->c_data->size() == 0 || vm->c_data->top() != nullptr) 82 - return false; 83 - 84 - vm->c_data->pop(); 85 - Exception& e = py_cast<Exception&>(vm, vm->c_data->top()); 86 - if (message != nullptr) 87 - *message = e.summary().c_str_dup(); 88 - else 89 - std::cerr << "ERROR: " << e.summary() << "\n"; 90 - 91 - vm->c_data->clear(); 92 - vm->callstack.clear(); 93 - vm->s_data.clear(); 94 - return true; 95 - 96 - SAFEGUARD_CLOSE 97 - } 98 - 99 - void gc_marker_ex(CVM* vm) { 100 - for(PyObject* obj: *vm->c_data) if(obj!=nullptr) OBJ_MARK(obj); 101 - } 102 - 103 - 104 - static void noop_output_handler(VM* vm, const Str& str) { 105 - (void) vm; 106 - (void) str; 107 - } 108 - 109 - pkpy_vm* pkpy_vm_create(bool use_stdio, bool enable_os) { 110 - 111 - CVM* vm = new CVM(enable_os); 112 - vm->c_data = new ValueStackImpl<PKPY_STACK_SIZE>(); 113 - vm->_gc_marker_ex = (void (*)(VM*)) gc_marker_ex; 114 - 115 - if (!use_stdio) { 116 - vm->_stdout = noop_output_handler; 117 - vm->_stderr = noop_output_handler; 118 - } 119 - 120 - return (pkpy_vm*) vm; 121 - } 122 - 123 - bool pkpy_vm_run(pkpy_vm* vm_handle, const char* source) { 124 - CVM* vm = (CVM*) vm_handle; 125 - ERRHANDLER_OPEN 126 - 127 - CodeObject_ code = vm->compile(source, "<c-bound>", EXEC_MODE); 128 - PyObject* result = vm->_exec(code, vm->_main); 129 - 130 - //unpack_return(w, result); 131 - //NOTE: it seems like vm->_exec should return whatever the last command it 132 - //ran returned but instead it seems to pretty much always return None 133 - //so I guess uncomment this line if that every changes 134 - 135 - return true; 136 - ERRHANDLER_CLOSE 137 - } 138 - 139 - void pkpy_vm_destroy(pkpy_vm* vm_handle) { 140 - CVM* vm = (CVM*) vm_handle; 141 - delete vm; 142 - } 143 - 144 - static void propagate_if_errored(CVM* vm, ValueStackImpl<PKPY_STACK_SIZE>* stored_stack) { 145 - try { 146 - if (vm->c_data->size() == 0 || vm->c_data->top() != nullptr) 147 - return; 148 - 149 - vm->c_data->pop(); 150 - Exception& e = py_cast<Exception&>(vm, vm->c_data->top()); 151 - vm->c_data->pop(); 152 - 153 - vm->c_data = stored_stack; 154 - 155 - throw e; 156 - } catch(Exception& e) { 157 - throw; 158 - } catch(...) { 159 - std::cerr << "ERROR: a non pocketpy exeception was thrown " 160 - << "this probably means pocketpy itself has a bug!\n"; 161 - exit(2); 162 - } 163 - } 164 - 165 - PyObject* c_function_wrapper(VM* vm, ArgsView args) { 166 - LuaStyleFuncC f = py_cast<NativeFunc&>(vm, args[-2])._lua_f; 167 - CVM* cvm = (CVM*) vm; 168 - 169 - //setup c stack 170 - ValueStackImpl<PKPY_STACK_SIZE> local_stack; 171 - 172 - for (int i = 0; i < args.size(); i++) 173 - local_stack.push(args[i]); 174 - 175 - ValueStackImpl<PKPY_STACK_SIZE>* stored_stack = cvm->c_data; 176 - cvm->c_data = &local_stack; 177 - 178 - int retc = f(cvm); 179 - 180 - propagate_if_errored(cvm, stored_stack); 181 - cvm->c_data = stored_stack; 182 - 183 - PyObject* ret = cvm->None; 184 - 185 - if (retc == 1) 186 - ret = local_stack.top(); 187 - else if (retc > 1) { 188 - Tuple t(retc); 189 - 190 - for (int i = 0; i < retc; i++) { 191 - int stack_index = (local_stack.size() - retc) + i; 192 - t[i] = local_stack.begin()[stack_index]; 193 - } 194 - 195 - ret = py_var(cvm, t); 196 - } 197 - 198 - return ret; 199 - } 200 - 201 - bool pkpy_push_function(pkpy_vm* vm_handle, pkpy_function f) { 202 - CVM* vm = (CVM*) vm_handle; 203 - ERRHANDLER_OPEN 204 - 205 - //TODO right now we just treat all c bound functions a varargs functions 206 - //do we want to change that? 207 - NativeFunc nf = NativeFunc(c_function_wrapper, -1, 0); 208 - nf._lua_f = (LuaStyleFuncC) f; 209 - 210 - vm->c_data->push(py_var(vm, nf)); 211 - 212 - return true; 213 - ERRHANDLER_CLOSE 214 - } 215 - 216 - bool pkpy_push_int(pkpy_vm* vm_handle, int value) { 217 - CVM* vm = (CVM*) vm_handle; 218 - ERRHANDLER_OPEN 219 - 220 - vm->c_data->push(py_var(vm, value)); 221 - 222 - return true; 223 - ERRHANDLER_CLOSE 224 - } 225 - 226 - bool pkpy_push_float(pkpy_vm* vm_handle, double value) { 227 - CVM* vm = (CVM*) vm_handle; 228 - ERRHANDLER_OPEN 229 - vm->c_data->push(py_var(vm, value)); 230 - 231 - return true; 232 - ERRHANDLER_CLOSE 233 - } 234 - 235 - bool pkpy_push_bool(pkpy_vm* vm_handle, bool value) { 236 - CVM* vm = (CVM*) vm_handle; 237 - ERRHANDLER_OPEN 238 - vm->c_data->push(py_var(vm, value)); 239 - 240 - return true; 241 - ERRHANDLER_CLOSE 242 - } 243 - 244 - bool pkpy_push_string(pkpy_vm* vm_handle, const char* value) { 245 - CVM* vm = (CVM*) vm_handle; 246 - ERRHANDLER_OPEN 247 - vm->c_data->push(py_var(vm, value)); 248 - 249 - return true; 250 - ERRHANDLER_CLOSE 251 - } 252 - 253 - bool pkpy_push_stringn(pkpy_vm* vm_handle, const char* value, int length) { 254 - CVM* vm = (CVM*) vm_handle; 255 - ERRHANDLER_OPEN 256 - 257 - Str s = Str(value, length); 258 - vm->c_data->push(py_var(vm, s)); 259 - 260 - return true; 261 - ERRHANDLER_CLOSE 262 - } 263 - 264 - bool pkpy_push_voidp(pkpy_vm* vm_handle, void* value) { 265 - CVM* vm = (CVM*) vm_handle; 266 - ERRHANDLER_OPEN 267 - vm->c_data->push(py_var(vm, value)); 268 - 269 - return true; 270 - ERRHANDLER_CLOSE 271 - } 272 - 273 - bool pkpy_push_none(pkpy_vm* vm_handle) { 274 - CVM* vm = (CVM*) vm_handle; 275 - ERRHANDLER_OPEN 276 - vm->c_data->push(vm->None); 277 - 278 - return true; 279 - ERRHANDLER_CLOSE 280 - } 281 - 282 - 283 - 284 - bool pkpy_set_global(pkpy_vm* vm_handle, const char* name) { 285 - CVM* vm = (CVM*) vm_handle; 286 - ERRHANDLER_OPEN 287 - 288 - vm->_main->attr().set(name, vm->c_data->top()); 289 - 290 - vm->c_data->pop(); 291 - 292 - return true; 293 - ERRHANDLER_CLOSE 294 - } 295 - 296 - //get global will also get bulitins 297 - bool pkpy_get_global(pkpy_vm* vm_handle, const char* name) { 298 - CVM* vm = (CVM*) vm_handle; 299 - ERRHANDLER_OPEN 300 - 301 - PyObject* o = vm->_main->attr().try_get(name); 302 - if (o == nullptr) { 303 - o = vm->builtins->attr().try_get(name); 304 - if (o == nullptr) 305 - throw Exception("NameError", "could not find requested global"); 306 - } 307 - 308 - vm->c_data->push(o); 309 - 310 - return true; 311 - ERRHANDLER_CLOSE 312 - } 313 - 314 - 315 - bool pkpy_call(pkpy_vm* vm_handle, int argc) { 316 - CVM* vm = (CVM*) vm_handle; 317 - ERRHANDLER_OPEN 318 - 319 - int callable_index = vm->c_data->size() - argc - 1; 320 - 321 - PyObject* callable = vm->c_data->begin()[callable_index]; 322 - 323 - vm->s_data.push(callable); 324 - vm->s_data.push(PY_NULL); 325 - 326 - for (int i = 0; i < argc; i++) 327 - vm->s_data.push(vm->c_data->begin()[callable_index + i + 1]); 328 - 329 - PyObject* o = vm->vectorcall(argc); 330 - 331 - vm->c_data->shrink(argc + 1); 332 - 333 - unpack_return(vm, o); 334 - 335 - return true; 336 - ERRHANDLER_CLOSE 337 - } 338 - 339 - bool pkpy_call_method(pkpy_vm* vm_handle, const char* name, int argc) { 340 - CVM* vm = (CVM*) vm_handle; 341 - ERRHANDLER_OPEN 342 - 343 - int self_index = vm->c_data->size() - argc - 1; 344 - PyObject* self = vm->c_data->begin()[self_index]; 345 - 346 - PyObject* callable = vm->get_unbound_method(self, name, &self); 347 - 348 - vm->s_data.push(callable); 349 - vm->s_data.push(self); 350 - 351 - for (int i = 0; i < argc; i++) 352 - vm->s_data.push(vm->c_data->begin()[self_index + i + 1]); 353 - 354 - PyObject* o = vm->vectorcall(argc); 355 - 356 - vm->c_data->shrink(argc + 1); 357 - 358 - unpack_return(vm, o); 359 - 360 - return true; 361 - ERRHANDLER_CLOSE 362 - } 363 - 364 - 365 - 366 - static int lua_to_cstack_index(int index, int size) { 367 - if (index < 0) 368 - index = size + index; 369 - return index; 370 - } 371 - 372 - bool pkpy_to_int(pkpy_vm* vm_handle, int index, int* ret) { 373 - CVM* vm = (CVM*) vm_handle; 374 - ERRHANDLER_OPEN 375 - 376 - index = lua_to_cstack_index(index, vm->c_data->size()); 377 - 378 - PyObject* o = vm->c_data->begin()[index]; 379 - 380 - if (!is_type(o, vm->tp_int)) 381 - throw Exception("TypeError", "pkpy_to_int on non int object"); 382 - 383 - if (ret != nullptr) 384 - *ret = py_cast<int>(vm, o); 385 - 386 - return true; 387 - ERRHANDLER_CLOSE 388 - } 389 - 390 - bool pkpy_to_float(pkpy_vm* vm_handle, int index, double* ret) { 391 - CVM* vm = (CVM*) vm_handle; 392 - ERRHANDLER_OPEN 393 - 394 - index = lua_to_cstack_index(index, vm->c_data->size()); 395 - 396 - PyObject* o = vm->c_data->begin()[index]; 397 - 398 - if (!is_type(o, vm->tp_float)) 399 - throw Exception("TypeError", "pkpy_to_float on non float object"); 400 - 401 - if (ret != nullptr) 402 - *ret = py_cast<double>(vm, o); 403 - 404 - return true; 405 - ERRHANDLER_CLOSE 406 - } 407 - 408 - bool pkpy_to_bool(pkpy_vm* vm_handle, int index, bool* ret) { 409 - CVM* vm = (CVM*) vm_handle; 410 - ERRHANDLER_OPEN 411 - 412 - index = lua_to_cstack_index(index, vm->c_data->size()); 413 - 414 - PyObject* o = vm->c_data->begin()[index]; 415 - if (!is_type(o, vm->tp_bool)) 416 - throw Exception("TypeError", "pkpy_to_bool on non bool object"); 417 - 418 - if (ret != nullptr) 419 - *ret = py_cast<bool>(vm, o); 420 - 421 - return true; 422 - ERRHANDLER_CLOSE 423 - } 424 - 425 - bool pkpy_to_voidp(pkpy_vm* vm_handle, int index, void** ret) { 426 - CVM* vm = (CVM*) vm_handle; 427 - ERRHANDLER_OPEN 428 - 429 - index = lua_to_cstack_index(index, vm->c_data->size()); 430 - 431 - PyObject* o = vm->c_data->begin()[index]; 432 - if (!is_type(o, VoidP::_type(vm))) 433 - throw Exception("TypeError", "pkpy_to_voidp on non void* object"); 434 - 435 - if (ret != nullptr) 436 - *ret = py_cast<void*>(vm, o); 437 - 438 - return true; 439 - ERRHANDLER_CLOSE 440 - } 441 - 442 - bool pkpy_to_string(pkpy_vm* vm_handle, int index, char** ret) { 443 - CVM* vm = (CVM*) vm_handle; 444 - ERRHANDLER_OPEN 445 - 446 - index = lua_to_cstack_index(index, vm->c_data->size()); 447 - 448 - PyObject* o = vm->c_data->begin()[index]; 449 - if (!is_type(o, vm->tp_str)) 450 - throw Exception("TypeError", "pkpy_to_string on non string object"); 451 - 452 - if (ret != nullptr) { 453 - Str& s = py_cast<Str&>(vm, o); 454 - *ret = s.c_str_dup(); 455 - } 456 - 457 - return true; 458 - ERRHANDLER_CLOSE 459 - } 460 - 461 - bool pkpy_to_stringn(pkpy_vm* vm_handle, int index, const char** ret, int* size) { 462 - CVM* vm = (CVM*) vm_handle; 463 - ERRHANDLER_OPEN 464 - 465 - index = lua_to_cstack_index(index, vm->c_data->size()); 466 - 467 - PyObject* o = vm->c_data->begin()[index]; 468 - if (ret != nullptr) { 469 - std::string_view sv = py_cast<Str&>(vm, o).sv(); 470 - *ret = sv.data(); 471 - *size = sv.size(); 472 - } 473 - 474 - return true; 475 - ERRHANDLER_CLOSE 476 - } 477 - 478 - 479 - bool pkpy_is_int(pkpy_vm* vm_handle, int index) { 480 - CVM* vm = (CVM*) vm_handle; 481 - index = lua_to_cstack_index(index, vm->c_data->size()); 482 - PyObject* o = vm->c_data->begin()[index]; 483 - 484 - return is_type(o, vm->tp_int); 485 - } 486 - bool pkpy_is_float(pkpy_vm* vm_handle, int index) { 487 - CVM* vm = (CVM*) vm_handle; 488 - index = lua_to_cstack_index(index, vm->c_data->size()); 489 - PyObject* o = vm->c_data->begin()[index]; 490 - 491 - return is_type(o, vm->tp_float); 492 - } 493 - bool pkpy_is_bool(pkpy_vm* vm_handle, int index) { 494 - CVM* vm = (CVM*) vm_handle; 495 - index = lua_to_cstack_index(index, vm->c_data->size()); 496 - PyObject* o = vm->c_data->begin()[index]; 497 - 498 - return is_type(o, vm->tp_bool); 499 - } 500 - bool pkpy_is_string(pkpy_vm* vm_handle, int index) { 501 - CVM* vm = (CVM*) vm_handle; 502 - index = lua_to_cstack_index(index, vm->c_data->size()); 503 - PyObject* o = vm->c_data->begin()[index]; 504 - 505 - return is_type(o, vm->tp_str); 506 - } 507 - bool pkpy_is_voidp(pkpy_vm* vm_handle, int index) { 508 - CVM* vm = (CVM*) vm_handle; 509 - index = lua_to_cstack_index(index, vm->c_data->size()); 510 - PyObject* o = vm->c_data->begin()[index]; 511 - 512 - return is_type(o, VoidP::_type(vm)); 513 - } 514 - 515 - bool pkpy_is_none(pkpy_vm* vm_handle, int index) { 516 - CVM* vm = (CVM*) vm_handle; 517 - index = lua_to_cstack_index(index, vm->c_data->size()); 518 - PyObject* o = vm->c_data->begin()[index]; 519 - 520 - return o == vm->None; 521 - } 522 - 523 - bool pkpy_check_global(pkpy_vm* vm_handle, const char* name) { 524 - CVM* vm = (CVM*) vm_handle; 525 - SAFEGUARD_OPEN 526 - PyObject* o = vm->_main->attr().try_get(name); 527 - if (o == nullptr) { 528 - o = vm->builtins->attr().try_get(name); 529 - if (o == nullptr) 530 - return false; 531 - } 532 - return true; 533 - 534 - SAFEGUARD_CLOSE 535 - } 536 - 537 - bool pkpy_check_error(pkpy_vm* vm_handle) { 538 - CVM* vm = (CVM*) vm_handle; 539 - SAFEGUARD_OPEN 540 - if (vm->c_data->size() > 0 && vm->c_data->top() == nullptr) 541 - return true; 542 - return false; 543 - SAFEGUARD_CLOSE 544 - } 545 - 546 - 547 - bool pkpy_check_stack(pkpy_vm* vm_handle, int free) { 548 - CVM* vm = (CVM*) vm_handle; 549 - return free + vm->c_data->size() <= PKPY_STACK_SIZE; 550 - } 551 - 552 - int pkpy_stack_size(pkpy_vm* vm_handle) { 553 - CVM* vm = (CVM*) vm_handle; 554 - return vm->c_data->size(); 555 - } 556 - 557 - bool pkpy_pop(pkpy_vm* vm_handle, int n) { 558 - CVM* vm = (CVM*) vm_handle; 559 - vm->c_data->shrink(n); 560 - return true; 561 - } 562 - 563 - 564 - bool pkpy_push(pkpy_vm* vm_handle, int index) { 565 - CVM* vm = (CVM*) vm_handle; 566 - index = lua_to_cstack_index(index, vm->c_data->size()); 567 - vm->c_data->push(vm->c_data->begin()[index]); 568 - return true; 569 - } 570 - 571 - 572 - bool pkpy_error(pkpy_vm* vm_handle, const char* message) { 573 - CVM* vm = (CVM*) vm_handle; 574 - ERRHANDLER_OPEN 575 - throw Exception("CBindingError", message); 576 - ERRHANDLER_CLOSE 577 - } 578 -
-115
vendor/pocketpy/pocketpy_c.h
··· 1 - #ifndef POCKETPY_C_H 2 - #define POCKETPY_C_H 3 - 4 - #ifdef __cplusplus 5 - extern "C" { 6 - #endif 7 - 8 - #include <stdbool.h> 9 - #include <stdint.h> 10 - 11 - typedef struct pkpy_vm_handle pkpy_vm; 12 - 13 - //we we take a lot of inspiration from the lua api for these bindings 14 - //the key difference being most methods return a bool, 15 - //true if it succeeded false if it did not 16 - 17 - //if a method returns false call the pkpy_clear_error method to check the error and clear it 18 - //if pkpy_clear_error returns false it means that no error was set, and it takes no action 19 - //if pkpy_clear_error returns true it means there was an error and it was cleared, 20 - //it will provide a string summary of the error in the message parameter (if it is not NULL) 21 - //if null is passed in as message, and it will just print the message to stderr 22 - bool pkpy_clear_error(pkpy_vm*, char** message); 23 - //NOTE you are responsible for freeing message 24 - 25 - //this will cause the vm to enter an error state and report the given message 26 - //when queried 27 - //note that at the moment this is more like a panic than throwing an error 28 - //the user will not be able to catch it with python code 29 - bool pkpy_error(pkpy_vm*, const char* message); 30 - 31 - 32 - pkpy_vm* pkpy_vm_create(bool use_stdio, bool enable_os); 33 - bool pkpy_vm_run(pkpy_vm*, const char* source); 34 - void pkpy_vm_destroy(pkpy_vm*); 35 - 36 - typedef int (*pkpy_function)(pkpy_vm*); 37 - 38 - bool pkpy_pop(pkpy_vm*, int n); 39 - 40 - //push the item at index onto the top of the stack (as well as leaving it where 41 - //it is on the stack) 42 - bool pkpy_push(pkpy_vm*, int index); 43 - 44 - bool pkpy_push_function(pkpy_vm*, pkpy_function); 45 - bool pkpy_push_int(pkpy_vm*, int); 46 - bool pkpy_push_float(pkpy_vm*, double); 47 - bool pkpy_push_bool(pkpy_vm*, bool); 48 - bool pkpy_push_string(pkpy_vm*, const char*); 49 - bool pkpy_push_stringn(pkpy_vm*, const char*, int length); 50 - bool pkpy_push_voidp(pkpy_vm*, void*); 51 - bool pkpy_push_none(pkpy_vm*); 52 - 53 - bool pkpy_set_global(pkpy_vm*, const char* name); 54 - bool pkpy_get_global(pkpy_vm*, const char* name); 55 - 56 - //first push callable you want to call 57 - //then push the arguments to send 58 - //argc is the number of arguments that was pushed (not counting the callable) 59 - bool pkpy_call(pkpy_vm*, int argc); 60 - 61 - //first push the object the method belongs to (self) 62 - //then push the the argments 63 - //argc is the number of arguments that was pushed (not counting the callable or self) 64 - //name is the name of the method to call on the object 65 - bool pkpy_call_method(pkpy_vm*, const char* name, int argc); 66 - 67 - 68 - //we will break with the lua api here 69 - //lua uses 1 as the index to the first pushed element for all of these functions 70 - //but we will start counting at zero to match python 71 - //we will allow negative numbers to count backwards from the top 72 - bool pkpy_to_int(pkpy_vm*, int index, int* ret); 73 - bool pkpy_to_float(pkpy_vm*, int index, double* ret); 74 - bool pkpy_to_bool(pkpy_vm*, int index, bool* ret); 75 - bool pkpy_to_voidp(pkpy_vm*, int index, void** ret); 76 - 77 - //this method provides a strong reference, you are responsible for freeing the 78 - //string when you are done with it 79 - bool pkpy_to_string(pkpy_vm*, int index, char** ret); 80 - 81 - //this method provides a weak reference, it is only valid until the 82 - //next api call 83 - //it is not null terminated 84 - bool pkpy_to_stringn(pkpy_vm*, int index, const char** ret, int* size); 85 - 86 - 87 - //these do not follow the same error semantics as above, their return values 88 - //just say whether the check succeeded or not, or else return the value asked for 89 - 90 - bool pkpy_is_int(pkpy_vm*, int index); 91 - bool pkpy_is_float(pkpy_vm*, int index); 92 - bool pkpy_is_bool(pkpy_vm*, int index); 93 - bool pkpy_is_string(pkpy_vm*, int index); 94 - bool pkpy_is_voidp(pkpy_vm*, int index); 95 - bool pkpy_is_none(pkpy_vm*, int index); 96 - 97 - 98 - //will return true if global exists 99 - bool pkpy_check_global(pkpy_vm*, const char* name); 100 - 101 - //will return true if the vm is currently in an error state 102 - bool pkpy_check_error(pkpy_vm*); 103 - 104 - //will return true if at least free empty slots remain on the stack 105 - bool pkpy_check_stack(pkpy_vm*, int free); 106 - 107 - //returns the number of elements on the stack 108 - int pkpy_stack_size(pkpy_vm*); 109 - 110 - 111 - #ifdef __cplusplus 112 - } 113 - #endif 114 - 115 - #endif