ceval.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241
  1. #include "pocketpy/common/str.h"
  2. #include "pocketpy/common/utils.h"
  3. #include "pocketpy/interpreter/frame.h"
  4. #include "pocketpy/interpreter/vm.h"
  5. #include "pocketpy/common/memorypool.h"
  6. #include "pocketpy/common/sstream.h"
  7. #include "pocketpy/objects/codeobject.h"
  8. #include "pocketpy/pocketpy.h"
  9. #include "pocketpy/objects/error.h"
  10. #include <stdbool.h>
  11. static bool stack_unpack_sequence(VM* self, uint16_t arg);
  12. static bool stack_format_object(VM* self, c11_sv spec);
  13. #define DISPATCH() \
  14. do { \
  15. frame->ip++; \
  16. goto __NEXT_STEP; \
  17. } while(0)
  18. #define DISPATCH_JUMP(__offset) \
  19. do { \
  20. frame->ip += __offset; \
  21. goto __NEXT_STEP; \
  22. } while(0)
  23. #define DISPATCH_JUMP_ABSOLUTE(__target) \
  24. do { \
  25. frame->ip = c11__at(Bytecode, &frame->co->codes, __target); \
  26. goto __NEXT_STEP; \
  27. } while(0)
  28. /* Stack manipulation macros */
  29. // https://github.com/python/cpython/blob/3.9/Python/ceval.c#L1123
  30. #define TOP() (self->stack.sp - 1)
  31. #define SECOND() (self->stack.sp - 2)
  32. #define THIRD() (self->stack.sp - 3)
  33. #define FOURTH() (self->stack.sp - 4)
  34. #define STACK_SHRINK(n) (self->stack.sp -= n)
  35. #define STACK_GROW(n) (self->stack.sp += n)
  36. #define PUSH(v) \
  37. do { \
  38. *self->stack.sp = *(v); \
  39. self->stack.sp++; \
  40. } while(0)
  41. #define POP() (--self->stack.sp)
  42. #define POPX() (*--self->stack.sp)
  43. #define SP() (self->stack.sp)
  44. // [a, b] -> [?, a, b]
  45. #define INSERT_THIRD() \
  46. do { \
  47. PUSH(TOP()); \
  48. *SECOND() = *THIRD(); \
  49. } while(0)
  50. #define vectorcall_opcall(argc, kwargc) \
  51. do { \
  52. FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \
  53. switch(res) { \
  54. case RES_RETURN: PUSH(&self->last_retval); break; \
  55. case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \
  56. case RES_ERROR: goto __ERROR; \
  57. default: c11__unreachedable(); \
  58. } \
  59. } while(0)
  60. static bool unpack_dict_to_buffer(py_Ref key, py_Ref val, void* ctx) {
  61. py_TValue** p = ctx;
  62. if(py_isstr(key)) {
  63. py_Name name = py_namev(py_tosv(key));
  64. py_newint(*p, name);
  65. py_assign(*p + 1, val);
  66. (*p) += 2;
  67. return true;
  68. }
  69. return TypeError("keywords must be strings, not '%t'", key->type);
  70. }
  71. FrameResult VM__run_top_frame(VM* self) {
  72. Frame* frame = self->top_frame;
  73. const Frame* base_frame = frame;
  74. while(true) {
  75. Bytecode byte;
  76. __NEXT_FRAME:
  77. frame->ip++;
  78. __NEXT_STEP:
  79. byte = *frame->ip;
  80. #if PK_DEBUG
  81. pk_print_stack(self, frame, byte);
  82. // assert(!py_checkexc(true));
  83. #endif
  84. switch((Opcode)byte.op) {
  85. case OP_NO_OP: DISPATCH();
  86. /*****************************************/
  87. case OP_POP_TOP: POP(); DISPATCH();
  88. case OP_DUP_TOP: PUSH(TOP()); DISPATCH();
  89. case OP_DUP_TOP_TWO:
  90. // [a, b]
  91. PUSH(SECOND()); // [a, b, a]
  92. PUSH(SECOND()); // [a, b, a, b]
  93. DISPATCH();
  94. case OP_ROT_TWO: {
  95. py_TValue tmp = *TOP();
  96. *TOP() = *SECOND();
  97. *SECOND() = tmp;
  98. DISPATCH();
  99. }
  100. case OP_ROT_THREE: {
  101. // [a, b, c] -> [c, a, b]
  102. py_TValue tmp = *TOP();
  103. *TOP() = *SECOND();
  104. *SECOND() = *THIRD();
  105. *THIRD() = tmp;
  106. DISPATCH();
  107. }
  108. case OP_PRINT_EXPR:
  109. if(TOP()->type != tp_NoneType) {
  110. bool ok = py_repr(TOP());
  111. if(!ok) goto __ERROR;
  112. self->callbacks.print(py_tostr(&self->last_retval));
  113. self->callbacks.print("\n");
  114. }
  115. POP();
  116. DISPATCH();
  117. /*****************************************/
  118. case OP_LOAD_CONST: PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg)); DISPATCH();
  119. case OP_LOAD_NONE: py_newnone(SP()++); DISPATCH();
  120. case OP_LOAD_TRUE: py_newbool(SP()++, true); DISPATCH();
  121. case OP_LOAD_FALSE: py_newbool(SP()++, false); DISPATCH();
  122. /*****************************************/
  123. case OP_LOAD_SMALL_INT: py_newint(SP()++, (int16_t)byte.arg); DISPATCH();
  124. /*****************************************/
  125. case OP_LOAD_ELLIPSIS: py_newellipsis(SP()++); DISPATCH();
  126. case OP_LOAD_FUNCTION: {
  127. FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
  128. Function* ud = py_newobject(SP(), tp_function, 0, sizeof(Function));
  129. Function__ctor(ud, decl, frame->module);
  130. if(decl->nested) {
  131. ud->closure = FastLocals__to_namedict(frame->locals, frame->co);
  132. py_Name name = py_name(decl->code.name->data);
  133. // capture itself to allow recursion
  134. NameDict__set(ud->closure, name, *SP());
  135. }
  136. SP()++;
  137. DISPATCH();
  138. }
  139. case OP_LOAD_NULL:
  140. py_newnil(SP()++);
  141. DISPATCH();
  142. /*****************************************/
  143. case OP_LOAD_FAST: {
  144. PUSH(&frame->locals[byte.arg]);
  145. if(py_isnil(TOP())) {
  146. py_Name name = c11__getitem(uint16_t, &frame->co->varnames, byte.arg);
  147. UnboundLocalError(name);
  148. goto __ERROR;
  149. }
  150. DISPATCH();
  151. }
  152. case OP_LOAD_NAME: {
  153. assert(frame->is_dynamic);
  154. py_Name name = byte.arg;
  155. py_TValue* tmp;
  156. py_newstr(SP()++, py_name2str(name));
  157. // locals
  158. if(!py_isnone(&frame->p0[1])) {
  159. if(py_getitem(&frame->p0[1], TOP())) {
  160. py_assign(TOP(), py_retval());
  161. DISPATCH();
  162. } else {
  163. if(py_matchexc(tp_KeyError)) {
  164. py_clearexc(NULL);
  165. } else {
  166. goto __ERROR;
  167. }
  168. }
  169. }
  170. // globals
  171. if(py_getitem(&frame->p0[0], TOP())) {
  172. py_assign(TOP(), py_retval());
  173. DISPATCH();
  174. } else {
  175. if(py_matchexc(tp_KeyError)) {
  176. py_clearexc(NULL);
  177. } else {
  178. goto __ERROR;
  179. }
  180. }
  181. // builtins
  182. tmp = py_getdict(&self->builtins, name);
  183. if(tmp != NULL) {
  184. py_assign(TOP(), tmp);
  185. DISPATCH();
  186. }
  187. NameError(name);
  188. goto __ERROR;
  189. }
  190. case OP_LOAD_NONLOCAL: {
  191. py_Name name = byte.arg;
  192. py_Ref tmp = Frame__f_closure_try_get(frame, name);
  193. if(tmp != NULL) {
  194. PUSH(tmp);
  195. DISPATCH();
  196. }
  197. tmp = py_getdict(frame->module, name);
  198. if(tmp != NULL) {
  199. PUSH(tmp);
  200. DISPATCH();
  201. }
  202. tmp = py_getdict(&self->builtins, name);
  203. if(tmp != NULL) {
  204. PUSH(tmp);
  205. DISPATCH();
  206. }
  207. NameError(name);
  208. goto __ERROR;
  209. }
  210. case OP_LOAD_GLOBAL: {
  211. py_Name name = byte.arg;
  212. py_Ref tmp = py_getdict(frame->module, name);
  213. if(tmp != NULL) {
  214. PUSH(tmp);
  215. DISPATCH();
  216. }
  217. tmp = py_getdict(&self->builtins, name);
  218. if(tmp != NULL) {
  219. PUSH(tmp);
  220. DISPATCH();
  221. }
  222. NameError(name);
  223. goto __ERROR;
  224. }
  225. case OP_LOAD_ATTR: {
  226. if(py_getattr(TOP(), byte.arg)) {
  227. py_assign(TOP(), py_retval());
  228. } else {
  229. goto __ERROR;
  230. }
  231. DISPATCH();
  232. }
  233. case OP_LOAD_CLASS_GLOBAL: {
  234. py_Name name = byte.arg;
  235. py_Ref tmp = py_getdict(self->__curr_class, name);
  236. if(tmp) {
  237. PUSH(tmp);
  238. DISPATCH();
  239. }
  240. // load global if attribute not found
  241. tmp = py_getdict(frame->module, name);
  242. if(tmp) {
  243. PUSH(tmp);
  244. DISPATCH();
  245. }
  246. tmp = py_getdict(&self->builtins, name);
  247. if(tmp) {
  248. PUSH(tmp);
  249. DISPATCH();
  250. }
  251. NameError(name);
  252. goto __ERROR;
  253. }
  254. case OP_LOAD_METHOD: {
  255. // [self] -> [unbound, self]
  256. bool ok = py_pushmethod(byte.arg);
  257. if(!ok) {
  258. // fallback to getattr
  259. if(py_getattr(TOP(), byte.arg)) {
  260. py_assign(TOP(), py_retval());
  261. py_newnil(SP()++);
  262. } else {
  263. goto __ERROR;
  264. }
  265. }
  266. DISPATCH();
  267. }
  268. case OP_LOAD_SUBSCR: {
  269. // [a, b] -> a[b]
  270. py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__);
  271. if(magic) {
  272. if(magic->type == tp_nativefunc) {
  273. if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR;
  274. POP();
  275. py_assign(TOP(), py_retval());
  276. } else {
  277. INSERT_THIRD(); // [?, a, b]
  278. *THIRD() = *magic; // [__getitem__, a, b]
  279. if(!py_vectorcall(1, 0)) goto __ERROR;
  280. PUSH(py_retval());
  281. }
  282. DISPATCH();
  283. }
  284. TypeError("'%t' object is not subscriptable", SECOND()->type);
  285. goto __ERROR;
  286. }
  287. case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH();
  288. case OP_STORE_NAME: {
  289. assert(frame->is_dynamic);
  290. py_Name name = byte.arg;
  291. py_newstr(SP()++, py_name2str(name));
  292. // [value, name]
  293. if(!py_isnone(&frame->p0[1])) {
  294. // locals
  295. if(py_setitem(&frame->p0[1], TOP(), SECOND())) {
  296. STACK_SHRINK(2);
  297. DISPATCH();
  298. } else {
  299. if(py_matchexc(tp_KeyError)) {
  300. py_clearexc(NULL);
  301. NameError(name);
  302. }
  303. goto __ERROR;
  304. }
  305. } else {
  306. // globals
  307. if(py_setitem(&frame->p0[0], TOP(), SECOND())) {
  308. STACK_SHRINK(2);
  309. DISPATCH();
  310. } else {
  311. if(py_matchexc(tp_KeyError)) {
  312. py_clearexc(NULL);
  313. NameError(name);
  314. }
  315. goto __ERROR;
  316. }
  317. }
  318. DISPATCH();
  319. }
  320. case OP_STORE_GLOBAL: {
  321. py_setdict(frame->module, byte.arg, TOP());
  322. POP();
  323. DISPATCH();
  324. }
  325. case OP_STORE_ATTR: {
  326. // [val, a] -> a.b = val
  327. if(!py_setattr(TOP(), byte.arg, SECOND())) goto __ERROR;
  328. STACK_SHRINK(2);
  329. DISPATCH();
  330. }
  331. case OP_STORE_SUBSCR: {
  332. // [val, a, b] -> a[b] = val
  333. py_Ref magic = py_tpfindmagic(SECOND()->type, __setitem__);
  334. if(magic) {
  335. PUSH(THIRD()); // [val, a, b, val]
  336. if(magic->type == tp_nativefunc) {
  337. if(!py_callcfunc(magic->_cfunc, 3, THIRD())) goto __ERROR;
  338. STACK_SHRINK(4);
  339. } else {
  340. *FOURTH() = *magic; // [__selitem__, a, b, val]
  341. if(!py_vectorcall(2, 0)) goto __ERROR;
  342. }
  343. DISPATCH();
  344. }
  345. TypeError("'%t' object does not support item assignment", SECOND()->type);
  346. goto __ERROR;
  347. }
  348. case OP_DELETE_FAST: {
  349. py_Ref tmp = &frame->locals[byte.arg];
  350. if(py_isnil(tmp)) {
  351. py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
  352. UnboundLocalError(name);
  353. goto __ERROR;
  354. }
  355. py_newnil(tmp);
  356. DISPATCH();
  357. }
  358. case OP_DELETE_NAME: {
  359. assert(frame->is_dynamic);
  360. py_Name name = byte.arg;
  361. py_newstr(SP()++, py_name2str(name));
  362. if(!py_isnone(&frame->p0[1])) {
  363. // locals
  364. if(py_delitem(&frame->p0[1], TOP())) {
  365. POP();
  366. DISPATCH();
  367. } else {
  368. if(py_matchexc(tp_KeyError)) {
  369. py_clearexc(NULL);
  370. NameError(name);
  371. }
  372. goto __ERROR;
  373. }
  374. } else {
  375. // globals
  376. if(py_delitem(&frame->p0[0], TOP())) {
  377. POP();
  378. DISPATCH();
  379. } else {
  380. if(py_matchexc(tp_KeyError)) {
  381. py_clearexc(NULL);
  382. NameError(name);
  383. }
  384. goto __ERROR;
  385. }
  386. }
  387. DISPATCH();
  388. }
  389. case OP_DELETE_GLOBAL: {
  390. py_Name name = byte.arg;
  391. bool ok = py_deldict(frame->module, name);
  392. if(!ok) {
  393. NameError(name);
  394. goto __ERROR;
  395. }
  396. DISPATCH();
  397. }
  398. case OP_DELETE_ATTR: {
  399. if(!py_delattr(TOP(), byte.arg)) goto __ERROR;
  400. DISPATCH();
  401. }
  402. case OP_DELETE_SUBSCR: {
  403. // [a, b] -> del a[b]
  404. py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__);
  405. if(magic) {
  406. if(magic->type == tp_nativefunc) {
  407. if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR;
  408. STACK_SHRINK(2);
  409. } else {
  410. INSERT_THIRD(); // [?, a, b]
  411. *THIRD() = *magic; // [__delitem__, a, b]
  412. if(!py_vectorcall(1, 0)) goto __ERROR;
  413. }
  414. DISPATCH();
  415. }
  416. TypeError("'%t' object does not support item deletion", SECOND()->type);
  417. goto __ERROR;
  418. }
  419. /*****************************************/
  420. case OP_BUILD_IMAG: {
  421. // [x]
  422. py_Ref f = py_getdict(&self->builtins, py_name("complex"));
  423. assert(f != NULL);
  424. py_TValue tmp = *TOP();
  425. *TOP() = *f; // [complex]
  426. py_newnil(SP()++); // [complex, NULL]
  427. py_newint(SP()++, 0); // [complex, NULL, 0]
  428. *SP()++ = tmp; // [complex, NULL, 0, x]
  429. if(!py_vectorcall(2, 0)) goto __ERROR;
  430. PUSH(py_retval());
  431. DISPATCH();
  432. }
  433. case OP_BUILD_BYTES: {
  434. int size;
  435. py_Ref string = c11__at(py_TValue, &frame->co->consts, byte.arg);
  436. const char* data = py_tostrn(string, &size);
  437. unsigned char* p = py_newbytes(SP()++, size);
  438. memcpy(p, data, size);
  439. DISPATCH();
  440. }
  441. case OP_BUILD_TUPLE: {
  442. py_TValue tmp;
  443. py_newtuple(&tmp, byte.arg);
  444. py_TValue* begin = SP() - byte.arg;
  445. for(int i = 0; i < byte.arg; i++) {
  446. py_tuple_setitem(&tmp, i, begin + i);
  447. }
  448. SP() = begin;
  449. PUSH(&tmp);
  450. DISPATCH();
  451. }
  452. case OP_BUILD_LIST: {
  453. py_TValue tmp;
  454. py_newlistn(&tmp, byte.arg);
  455. py_TValue* begin = SP() - byte.arg;
  456. for(int i = 0; i < byte.arg; i++) {
  457. py_list_setitem(&tmp, i, begin + i);
  458. }
  459. SP() = begin;
  460. PUSH(&tmp);
  461. DISPATCH();
  462. }
  463. case OP_BUILD_DICT: {
  464. py_TValue* begin = SP() - byte.arg * 2;
  465. py_Ref tmp = py_pushtmp();
  466. py_newdict(tmp);
  467. for(int i = 0; i < byte.arg * 2; i += 2) {
  468. bool ok = py_dict_setitem(tmp, begin + i, begin + i + 1);
  469. if(!ok) goto __ERROR;
  470. }
  471. SP() = begin;
  472. PUSH(tmp);
  473. DISPATCH();
  474. }
  475. case OP_BUILD_SET: {
  476. py_TValue* begin = SP() - byte.arg;
  477. py_Ref typeobject_set = py_getdict(&self->builtins, py_name("set"));
  478. assert(typeobject_set != NULL);
  479. py_push(typeobject_set);
  480. py_pushnil();
  481. if(!py_vectorcall(0, 0)) goto __ERROR;
  482. py_push(py_retval()); // empty set
  483. py_Name id_add = py_name("add");
  484. for(int i = 0; i < byte.arg; i++) {
  485. py_push(TOP());
  486. if(!py_pushmethod(id_add)) {
  487. c11__abort("OP_BUILD_SET: failed to load method 'add'");
  488. }
  489. py_push(begin + i);
  490. if(!py_vectorcall(1, 0)) goto __ERROR;
  491. }
  492. py_TValue tmp = *TOP();
  493. SP() = begin;
  494. PUSH(&tmp);
  495. DISPATCH();
  496. }
  497. case OP_BUILD_SLICE: {
  498. // [start, stop, step]
  499. py_TValue tmp;
  500. py_newslice(&tmp);
  501. py_setslot(&tmp, 0, THIRD());
  502. py_setslot(&tmp, 1, SECOND());
  503. py_setslot(&tmp, 2, TOP());
  504. STACK_SHRINK(3);
  505. PUSH(&tmp);
  506. DISPATCH();
  507. }
  508. case OP_BUILD_STRING: {
  509. py_TValue* begin = SP() - byte.arg;
  510. c11_sbuf ss;
  511. c11_sbuf__ctor(&ss);
  512. for(int i = 0; i < byte.arg; i++) {
  513. if(!py_str(begin + i)) goto __ERROR;
  514. c11_sbuf__write_sv(&ss, py_tosv(&self->last_retval));
  515. }
  516. SP() = begin;
  517. c11_sbuf__py_submit(&ss, SP()++);
  518. DISPATCH();
  519. }
  520. /*****************************/
  521. case OP_BINARY_OP: {
  522. py_Name op = byte.arg & 0xFF;
  523. py_Name rop = byte.arg >> 8;
  524. if(!pk_stack_binaryop(self, op, rop)) goto __ERROR;
  525. POP();
  526. *TOP() = self->last_retval;
  527. DISPATCH();
  528. }
  529. case OP_IS_OP: {
  530. bool res = py_isidentical(SECOND(), TOP());
  531. POP();
  532. if(byte.arg) res = !res;
  533. py_newbool(TOP(), res);
  534. DISPATCH();
  535. }
  536. case OP_CONTAINS_OP: {
  537. // [b, a] -> b __contains__ a (a in b) -> [retval]
  538. py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__);
  539. if(magic) {
  540. if(magic->type == tp_nativefunc) {
  541. if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR;
  542. STACK_SHRINK(2);
  543. } else {
  544. INSERT_THIRD(); // [?, b, a]
  545. *THIRD() = *magic; // [__contains__, a, b]
  546. if(!py_vectorcall(1, 0)) goto __ERROR;
  547. }
  548. bool res = py_tobool(py_retval());
  549. if(byte.arg) res = !res;
  550. py_newbool(SP()++, res);
  551. DISPATCH();
  552. }
  553. TypeError("'%t' type does not support '__contains__'", SECOND()->type);
  554. goto __ERROR;
  555. }
  556. /*****************************************/
  557. case OP_JUMP_FORWARD: DISPATCH_JUMP((int16_t)byte.arg);
  558. case OP_POP_JUMP_IF_FALSE: {
  559. int res = py_bool(TOP());
  560. if(res < 0) goto __ERROR;
  561. POP();
  562. if(!res) DISPATCH_JUMP((int16_t)byte.arg);
  563. DISPATCH();
  564. }
  565. case OP_POP_JUMP_IF_TRUE: {
  566. int res = py_bool(TOP());
  567. if(res < 0) goto __ERROR;
  568. POP();
  569. if(res) DISPATCH_JUMP((int16_t)byte.arg);
  570. DISPATCH();
  571. }
  572. case OP_JUMP_IF_TRUE_OR_POP: {
  573. int res = py_bool(TOP());
  574. if(res < 0) goto __ERROR;
  575. if(res) {
  576. DISPATCH_JUMP((int16_t)byte.arg);
  577. } else {
  578. POP();
  579. DISPATCH();
  580. }
  581. }
  582. case OP_JUMP_IF_FALSE_OR_POP: {
  583. int res = py_bool(TOP());
  584. if(res < 0) goto __ERROR;
  585. if(!res) {
  586. DISPATCH_JUMP((int16_t)byte.arg);
  587. } else {
  588. POP();
  589. DISPATCH();
  590. }
  591. }
  592. case OP_SHORTCUT_IF_FALSE_OR_POP: {
  593. int res = py_bool(TOP());
  594. if(res < 0) goto __ERROR;
  595. if(!res) { // [b, False]
  596. STACK_SHRINK(2); // []
  597. py_newbool(SP()++, false); // [False]
  598. DISPATCH_JUMP((int16_t)byte.arg);
  599. } else {
  600. POP(); // [b]
  601. DISPATCH();
  602. }
  603. }
  604. case OP_LOOP_CONTINUE:
  605. // just an alias of OP_JUMP_FORWARD
  606. DISPATCH_JUMP((int16_t)byte.arg);
  607. case OP_LOOP_BREAK: {
  608. int target = Frame__ip(frame) + byte.arg;
  609. Frame__prepare_jump_break(frame, &self->stack, target);
  610. DISPATCH_JUMP((int16_t)byte.arg);
  611. }
  612. case OP_JUMP_ABSOLUTE_TOP: {
  613. int target = py_toint(TOP());
  614. POP();
  615. DISPATCH_JUMP_ABSOLUTE(target);
  616. }
  617. case OP_GOTO: {
  618. int target = c11_smallmap_n2i__get(&frame->co->labels, byte.arg, -1);
  619. if(target < 0) {
  620. RuntimeError("label '%n' not found", byte.arg);
  621. goto __ERROR;
  622. }
  623. Frame__prepare_jump_break(frame, &self->stack, target);
  624. DISPATCH_JUMP_ABSOLUTE(target);
  625. }
  626. /*****************************************/
  627. case OP_CALL: {
  628. ManagedHeap__collect_if_needed(&self->heap);
  629. vectorcall_opcall(byte.arg & 0xFF, byte.arg >> 8);
  630. DISPATCH();
  631. }
  632. case OP_CALL_VARGS: {
  633. // [_0, _1, _2 | k1, v1, k2, v2]
  634. uint16_t argc = byte.arg & 0xFF;
  635. uint16_t kwargc = byte.arg >> 8;
  636. int n = 0;
  637. py_TValue* sp = SP();
  638. py_TValue* p1 = sp - kwargc * 2;
  639. py_TValue* base = p1 - argc;
  640. py_TValue* buf = self->__vectorcall_buffer;
  641. for(py_TValue* curr = base; curr != p1; curr++) {
  642. if(curr->type != tp_star_wrapper) {
  643. buf[n++] = *curr;
  644. } else {
  645. py_TValue* args = py_getslot(curr, 0);
  646. py_TValue* p;
  647. int length = pk_arrayview(args, &p);
  648. if(length != -1) {
  649. for(int j = 0; j < length; j++) {
  650. buf[n++] = p[j];
  651. }
  652. argc += length - 1;
  653. } else {
  654. TypeError("*args must be a list or tuple, got '%t'", args->type);
  655. goto __ERROR;
  656. }
  657. }
  658. }
  659. for(py_TValue* curr = p1; curr != sp; curr += 2) {
  660. if(curr[1].type != tp_star_wrapper) {
  661. buf[n++] = curr[0];
  662. buf[n++] = curr[1];
  663. } else {
  664. assert(py_toint(&curr[0]) == 0);
  665. py_TValue* kwargs = py_getslot(&curr[1], 0);
  666. if(kwargs->type == tp_dict) {
  667. py_TValue* p = buf + n;
  668. if(!py_dict_apply(kwargs, unpack_dict_to_buffer, &p)) goto __ERROR;
  669. n = p - buf;
  670. kwargc += py_dict_len(kwargs) - 1;
  671. } else {
  672. TypeError("**kwargs must be a dict, got '%t'", kwargs->type);
  673. goto __ERROR;
  674. }
  675. }
  676. }
  677. memcpy(base, buf, n * sizeof(py_TValue));
  678. SP() = base + n;
  679. vectorcall_opcall(argc, kwargc);
  680. DISPATCH();
  681. }
  682. case OP_RETURN_VALUE: {
  683. if(byte.arg == BC_NOARG) {
  684. self->last_retval = POPX();
  685. } else {
  686. py_newnone(&self->last_retval);
  687. }
  688. VM__pop_frame(self);
  689. if(frame == base_frame) { // [ frameBase<- ]
  690. return RES_RETURN;
  691. } else {
  692. frame = self->top_frame;
  693. PUSH(&self->last_retval);
  694. goto __NEXT_FRAME;
  695. }
  696. DISPATCH();
  697. }
  698. case OP_YIELD_VALUE: {
  699. py_assign(py_retval(), TOP());
  700. POP();
  701. return RES_YIELD;
  702. }
  703. /////////
  704. case OP_LIST_APPEND: {
  705. // [list, iter, value]
  706. py_list_append(THIRD(), TOP());
  707. POP();
  708. DISPATCH();
  709. }
  710. case OP_DICT_ADD: {
  711. // [dict, iter, key, value]
  712. bool ok = py_dict_setitem(FOURTH(), SECOND(), TOP());
  713. if(!ok) goto __ERROR;
  714. STACK_SHRINK(2);
  715. DISPATCH();
  716. }
  717. case OP_SET_ADD: {
  718. // [set, iter, value]
  719. py_push(THIRD()); // [| set]
  720. if(!py_pushmethod(py_name("add"))) {
  721. c11__abort("OP_SET_ADD: failed to load method 'add'");
  722. } // [|add() set]
  723. py_push(THIRD());
  724. if(!py_vectorcall(1, 0)) goto __ERROR;
  725. POP();
  726. DISPATCH();
  727. }
  728. /////////
  729. case OP_UNARY_NEGATIVE: {
  730. if(!pk_callmagic(__neg__, 1, TOP())) goto __ERROR;
  731. *TOP() = self->last_retval;
  732. DISPATCH();
  733. }
  734. case OP_UNARY_NOT: {
  735. int res = py_bool(TOP());
  736. if(res < 0) goto __ERROR;
  737. py_newbool(TOP(), !res);
  738. DISPATCH();
  739. }
  740. case OP_UNARY_STAR: {
  741. py_TValue value = POPX();
  742. int* level = py_newobject(SP()++, tp_star_wrapper, 1, sizeof(int));
  743. *level = byte.arg;
  744. py_setslot(TOP(), 0, &value);
  745. DISPATCH();
  746. }
  747. case OP_UNARY_INVERT: {
  748. if(!pk_callmagic(__invert__, 1, TOP())) goto __ERROR;
  749. *TOP() = self->last_retval;
  750. DISPATCH();
  751. }
  752. ////////////////
  753. case OP_GET_ITER: {
  754. if(!py_iter(TOP())) goto __ERROR;
  755. *TOP() = *py_retval();
  756. DISPATCH();
  757. }
  758. case OP_FOR_ITER: {
  759. int res = py_next(TOP());
  760. if(res == -1) goto __ERROR;
  761. if(res) {
  762. PUSH(py_retval());
  763. DISPATCH();
  764. } else {
  765. int target = Frame__prepare_loop_break(frame, &self->stack);
  766. DISPATCH_JUMP_ABSOLUTE(target);
  767. }
  768. }
  769. ////////
  770. case OP_IMPORT_PATH: {
  771. py_Ref path_object = c11__at(py_TValue, &frame->co->consts, byte.arg);
  772. const char* path = py_tostr(path_object);
  773. int res = py_import(path);
  774. if(res == -1) goto __ERROR;
  775. if(res == 0) {
  776. ImportError("No module named '%s'", path);
  777. goto __ERROR;
  778. }
  779. PUSH(py_retval());
  780. DISPATCH();
  781. }
  782. case OP_POP_IMPORT_STAR: {
  783. // [module]
  784. NameDict* dict = PyObject__dict(TOP()->_obj);
  785. py_Ref all = NameDict__try_get(dict, __all__);
  786. if(all) {
  787. py_TValue* p;
  788. int length = pk_arrayview(all, &p);
  789. if(length == -1) {
  790. TypeError("'__all__' must be a list or tuple, got '%t'", all->type);
  791. goto __ERROR;
  792. }
  793. for(int i = 0; i < length; i++) {
  794. py_Name name = py_namev(py_tosv(p + i));
  795. py_Ref value = NameDict__try_get(dict, name);
  796. if(value == NULL) {
  797. ImportError("cannot import name '%n'", name);
  798. goto __ERROR;
  799. } else {
  800. py_setdict(frame->module, name, value);
  801. }
  802. }
  803. } else {
  804. for(int i = 0; i < dict->length; i++) {
  805. NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
  806. if(!kv->key) continue;
  807. c11_sv name = py_name2sv(kv->key);
  808. if(name.size == 0 || name.data[0] == '_') continue;
  809. py_setdict(frame->module, kv->key, &kv->value);
  810. }
  811. }
  812. POP();
  813. DISPATCH();
  814. }
  815. ////////
  816. case OP_UNPACK_SEQUENCE: {
  817. if(!stack_unpack_sequence(self, byte.arg)) goto __ERROR;
  818. DISPATCH();
  819. }
  820. case OP_UNPACK_EX: {
  821. py_TValue* p;
  822. int length = pk_arrayview(TOP(), &p);
  823. if(length == -1) {
  824. TypeError("expected list or tuple to unpack, got %t", TOP()->type);
  825. goto __ERROR;
  826. }
  827. int exceed = length - byte.arg;
  828. if(exceed < 0) {
  829. ValueError("not enough values to unpack");
  830. goto __ERROR;
  831. }
  832. POP();
  833. for(int i = 0; i < byte.arg; i++) {
  834. PUSH(p + i);
  835. }
  836. py_newlistn(SP()++, exceed);
  837. for(int i = 0; i < exceed; i++) {
  838. py_list_setitem(TOP(), i, p + byte.arg + i);
  839. }
  840. DISPATCH();
  841. }
  842. ///////////
  843. case OP_BEGIN_CLASS: {
  844. // [base]
  845. py_Name name = byte.arg;
  846. py_Type base;
  847. if(py_isnone(TOP())) {
  848. base = tp_object;
  849. } else {
  850. if(!py_checktype(TOP(), tp_type)) goto __ERROR;
  851. base = py_totype(TOP());
  852. }
  853. POP();
  854. py_TypeInfo* base_ti = TypeList__get(&self->types, base);
  855. if(base_ti->is_sealed) {
  856. TypeError("type '%t' is not an acceptable base type", base);
  857. goto __ERROR;
  858. }
  859. py_Type type =
  860. pk_newtype(py_name2str(name), base, frame->module, NULL, true, false);
  861. PUSH(py_tpobject(type));
  862. self->__curr_class = TOP();
  863. DISPATCH();
  864. }
  865. case OP_END_CLASS: {
  866. // [cls or decorated]
  867. // TODO: if __eq__ is defined, check __ne__ and provide a default implementation
  868. py_Name name = byte.arg;
  869. // set into f_globals
  870. py_setdict(frame->module, name, TOP());
  871. if(py_istype(TOP(), tp_type)) {
  872. // call on_end_subclass
  873. py_TypeInfo* ti = TypeList__get(&self->types, py_totype(TOP()));
  874. if(ti->base != tp_object) {
  875. py_TypeInfo* base_ti = ti->base_ti;
  876. if(base_ti->on_end_subclass) base_ti->on_end_subclass(ti);
  877. }
  878. }
  879. POP();
  880. self->__curr_class = NULL;
  881. DISPATCH();
  882. }
  883. case OP_STORE_CLASS_ATTR: {
  884. py_Name name = byte.arg;
  885. if(py_istype(TOP(), tp_function)) {
  886. Function* ud = py_touserdata(TOP());
  887. ud->clazz = self->__curr_class->_obj;
  888. }
  889. py_setdict(self->__curr_class, name, TOP());
  890. POP();
  891. DISPATCH();
  892. }
  893. case OP_ADD_CLASS_ANNOTATION: {
  894. // [type_hint string]
  895. py_Type type = py_totype(self->__curr_class);
  896. py_TypeInfo* ti = TypeList__get(&self->types, type);
  897. if(py_isnil(&ti->annotations)) py_newdict(&ti->annotations);
  898. bool ok = py_dict_setitem_by_str(&ti->annotations, py_name2str(byte.arg), TOP());
  899. if(!ok) goto __ERROR;
  900. POP();
  901. DISPATCH();
  902. }
  903. ///////////
  904. case OP_WITH_ENTER: {
  905. // [expr]
  906. py_push(TOP());
  907. if(!py_pushmethod(__enter__)) {
  908. TypeError("'%t' object does not support the context manager protocol",
  909. TOP()->type);
  910. goto __ERROR;
  911. }
  912. if(!py_vectorcall(0, 0)) goto __ERROR;
  913. PUSH(py_retval());
  914. DISPATCH();
  915. }
  916. case OP_WITH_EXIT: {
  917. // [expr]
  918. py_push(TOP());
  919. if(!py_pushmethod(__exit__)) {
  920. TypeError("'%t' object does not support the context manager protocol",
  921. TOP()->type);
  922. goto __ERROR;
  923. }
  924. if(!py_vectorcall(0, 0)) goto __ERROR;
  925. DISPATCH();
  926. }
  927. ///////////
  928. case OP_TRY_ENTER: {
  929. Frame__set_unwind_target(frame, SP());
  930. DISPATCH();
  931. }
  932. case OP_EXCEPTION_MATCH: {
  933. if(!py_checktype(TOP(), tp_type)) goto __ERROR;
  934. bool ok = py_isinstance(&self->curr_exception, py_totype(TOP()));
  935. py_newbool(TOP(), ok);
  936. DISPATCH();
  937. }
  938. case OP_RAISE: {
  939. // [exception]
  940. if(py_istype(TOP(), tp_type)) {
  941. if(!py_tpcall(py_totype(TOP()), 0, NULL)) goto __ERROR;
  942. py_assign(TOP(), py_retval());
  943. }
  944. if(!py_isinstance(TOP(), tp_BaseException)) {
  945. TypeError("exceptions must derive from BaseException");
  946. goto __ERROR;
  947. }
  948. py_raise(TOP());
  949. goto __ERROR;
  950. }
  951. case OP_RAISE_ASSERT: {
  952. if(byte.arg) {
  953. if(!py_str(TOP())) goto __ERROR;
  954. POP();
  955. py_exception(tp_AssertionError, "%s", py_tostr(py_retval()));
  956. } else {
  957. py_exception(tp_AssertionError, "");
  958. }
  959. goto __ERROR;
  960. }
  961. case OP_RE_RAISE: {
  962. assert(self->curr_exception.type);
  963. goto __ERROR_RE_RAISE;
  964. }
  965. case OP_PUSH_EXCEPTION: {
  966. assert(self->curr_exception.type);
  967. PUSH(&self->curr_exception);
  968. DISPATCH();
  969. }
  970. case OP_BEGIN_EXC_HANDLING: {
  971. self->is_curr_exc_handled = true;
  972. DISPATCH();
  973. }
  974. case OP_END_EXC_HANDLING: {
  975. assert(self->curr_exception.type);
  976. py_clearexc(NULL);
  977. DISPATCH();
  978. }
  979. //////////////////
  980. case OP_FORMAT_STRING: {
  981. py_Ref spec = c11__at(py_TValue, &frame->co->consts, byte.arg);
  982. bool ok = stack_format_object(self, py_tosv(spec));
  983. if(!ok) goto __ERROR;
  984. DISPATCH();
  985. }
  986. default: c11__unreachedable();
  987. }
  988. c11__unreachedable();
  989. __ERROR:
  990. py_BaseException__stpush(&self->curr_exception,
  991. frame->co->src,
  992. Frame__lineno(frame),
  993. frame->has_function ? frame->co->name->data : NULL);
  994. __ERROR_RE_RAISE:
  995. do {
  996. } while(0);
  997. int target = Frame__prepare_jump_exception_handler(frame, &self->stack);
  998. if(target >= 0) {
  999. // 1. Exception can be handled inside the current frame
  1000. DISPATCH_JUMP_ABSOLUTE(target);
  1001. } else {
  1002. // 2. Exception need to be propagated to the upper frame
  1003. bool is_base_frame_to_be_popped = frame == base_frame;
  1004. VM__pop_frame(self);
  1005. if(self->top_frame == NULL || is_base_frame_to_be_popped) {
  1006. // propagate to the top level
  1007. return RES_ERROR;
  1008. }
  1009. frame = self->top_frame;
  1010. goto __ERROR;
  1011. }
  1012. }
  1013. return RES_RETURN;
  1014. }
  1015. bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop) {
  1016. // [a, b]
  1017. py_Ref magic = py_tpfindmagic(SECOND()->type, op);
  1018. if(magic) {
  1019. bool ok = py_call(magic, 2, SECOND());
  1020. if(!ok) return false;
  1021. if(self->last_retval.type != tp_NotImplementedType) return true;
  1022. }
  1023. // try reverse operation
  1024. if(rop) {
  1025. // [a, b] -> [b, a]
  1026. py_TValue tmp = *TOP();
  1027. *TOP() = *SECOND();
  1028. *SECOND() = tmp;
  1029. magic = py_tpfindmagic(SECOND()->type, rop);
  1030. if(magic) {
  1031. bool ok = py_call(magic, 2, SECOND());
  1032. if(!ok) return false;
  1033. if(self->last_retval.type != tp_NotImplementedType) return true;
  1034. }
  1035. }
  1036. // eq/ne op never fails
  1037. bool res = py_isidentical(SECOND(), TOP());
  1038. if(op == __eq__) {
  1039. py_newbool(py_retval(), res);
  1040. return true;
  1041. }
  1042. if(op == __ne__) {
  1043. py_newbool(py_retval(), !res);
  1044. return true;
  1045. }
  1046. return TypeError("unsupported operand type(s) for '%n'", op);
  1047. }
  1048. bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {
  1049. VM* self = pk_current_vm;
  1050. PUSH(lhs);
  1051. PUSH(rhs);
  1052. bool ok = pk_stack_binaryop(self, op, rop);
  1053. STACK_SHRINK(2);
  1054. return ok;
  1055. }
  1056. static bool stack_unpack_sequence(VM* self, uint16_t arg) {
  1057. py_TValue* p;
  1058. int length = pk_arrayview(TOP(), &p);
  1059. if(length == -1) return TypeError("expected list or tuple to unpack, got %t", TOP()->type);
  1060. if(length != arg) return ValueError("expected %d values to unpack, got %d", arg, length);
  1061. POP();
  1062. for(int i = 0; i < length; i++) {
  1063. PUSH(p + i);
  1064. }
  1065. return true;
  1066. }
  1067. static bool stack_format_object(VM* self, c11_sv spec) {
  1068. // format TOS via `spec` inplace
  1069. // spec: '!r:.2f', '.2f'
  1070. py_StackRef val = TOP();
  1071. if(spec.size == 0) return py_str(val);
  1072. if(spec.data[0] == '!') {
  1073. if(c11_sv__startswith(spec, (c11_sv){"!r", 2})) {
  1074. spec.data += 2;
  1075. spec.size -= 2;
  1076. if(!py_repr(val)) return false;
  1077. py_assign(val, py_retval());
  1078. if(spec.size == 0) return true;
  1079. } else {
  1080. return ValueError("invalid conversion specifier (only !r is supported)");
  1081. }
  1082. }
  1083. assert(spec.size > 0);
  1084. if(spec.data[0] == ':') {
  1085. spec.data++;
  1086. spec.size--;
  1087. }
  1088. char type;
  1089. switch(spec.data[spec.size - 1]) {
  1090. case 'f':
  1091. case 'd':
  1092. case 's':
  1093. type = spec.data[spec.size - 1];
  1094. spec.size--; // remove last char
  1095. break;
  1096. default: type = ' '; break;
  1097. }
  1098. char pad_c = ' ';
  1099. if(strchr("0-=*#@!~", spec.data[0])) {
  1100. pad_c = spec.data[0];
  1101. spec = c11_sv__slice(spec, 1);
  1102. }
  1103. char align;
  1104. if(spec.data[0] == '^') {
  1105. align = '^';
  1106. spec = c11_sv__slice(spec, 1);
  1107. } else if(spec.data[0] == '>') {
  1108. align = '>';
  1109. spec = c11_sv__slice(spec, 1);
  1110. } else if(spec.data[0] == '<') {
  1111. align = '<';
  1112. spec = c11_sv__slice(spec, 1);
  1113. } else {
  1114. align = (py_isint(val) || py_isfloat(val)) ? '>' : '<';
  1115. }
  1116. int dot = c11_sv__index(spec, '.');
  1117. py_i64 width, precision;
  1118. if(dot >= 0) {
  1119. if(dot == 0) {
  1120. // {.2f}
  1121. width = -1;
  1122. } else {
  1123. // {10.2f}
  1124. IntParsingResult res = c11__parse_uint(c11_sv__slice2(spec, 0, dot), &width, 10);
  1125. if(res != IntParsing_SUCCESS) return ValueError("invalid format specifer");
  1126. }
  1127. IntParsingResult res = c11__parse_uint(c11_sv__slice(spec, dot + 1), &precision, 10);
  1128. if(res != IntParsing_SUCCESS) return ValueError("invalid format specifer");
  1129. } else {
  1130. // {10s}
  1131. IntParsingResult res = c11__parse_uint(spec, &width, 10);
  1132. if(res != IntParsing_SUCCESS) return ValueError("invalid format specifer");
  1133. precision = -1;
  1134. }
  1135. if(type != 'f' && dot >= 0) {
  1136. return ValueError("precision not allowed in the format specifier");
  1137. }
  1138. c11_sbuf buf;
  1139. c11_sbuf__ctor(&buf);
  1140. if(type == 'f') {
  1141. py_f64 x;
  1142. if(!py_castfloat(val, &x)) {
  1143. c11_sbuf__dtor(&buf);
  1144. return false;
  1145. }
  1146. if(precision < 0) precision = 6;
  1147. c11_sbuf__write_f64(&buf, x, precision);
  1148. } else if(type == 'd') {
  1149. if(!py_checkint(val)) {
  1150. c11_sbuf__dtor(&buf);
  1151. return false;
  1152. }
  1153. c11_sbuf__write_i64(&buf, py_toint(val));
  1154. } else if(type == 's') {
  1155. if(!py_checkstr(val)) {
  1156. c11_sbuf__dtor(&buf);
  1157. return false;
  1158. }
  1159. c11_sbuf__write_sv(&buf, py_tosv(val));
  1160. } else {
  1161. if(!py_str(val)) {
  1162. c11_sbuf__dtor(&buf);
  1163. return false;
  1164. }
  1165. c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
  1166. }
  1167. c11_string* body = c11_sbuf__submit(&buf);
  1168. int length = c11_sv__u8_length(c11_string__sv(body));
  1169. c11_sbuf__ctor(&buf); // reinit sbuf
  1170. if(width != -1 && width > length) {
  1171. switch(align) {
  1172. case '>': {
  1173. c11_sbuf__write_pad(&buf, width - length, pad_c);
  1174. c11_sbuf__write_sv(&buf, c11_string__sv(body));
  1175. break;
  1176. }
  1177. case '<': {
  1178. c11_sbuf__write_sv(&buf, c11_string__sv(body));
  1179. c11_sbuf__write_pad(&buf, width - length, pad_c);
  1180. break;
  1181. }
  1182. case '^': {
  1183. int pad_left = (width - length) / 2;
  1184. int pad_right = (width - length) - pad_left;
  1185. c11_sbuf__write_pad(&buf, pad_left, pad_c);
  1186. c11_sbuf__write_sv(&buf, c11_string__sv(body));
  1187. c11_sbuf__write_pad(&buf, pad_right, pad_c);
  1188. break;
  1189. }
  1190. default: c11__unreachedable();
  1191. }
  1192. } else {
  1193. c11_sbuf__write_sv(&buf, c11_string__sv(body));
  1194. }
  1195. c11_string__delete(body);
  1196. // inplace update
  1197. c11_sbuf__py_submit(&buf, val);
  1198. return true;
  1199. }